Leaderboard
Popular Content
Showing content with the highest reputation on 10/11/2012 in all areas
-
Just a quick heads up. This is the last day for nominations (they close at 3pm MT) and voting begins tomorrow morning at 8 AM MT, so check back to see if you've been short listed. From what I can see so far in the nominations, ProcessWire has been well represented so far, so keep getting those nominations in.3 points
-
Hello I am like processwire, nice family here welcome. Project I am working for my restaurant need online order system where customer select items for pickup. Don't need to payment, customer can pay at register in where Maryla can handle this . Customer select many of my food items, enter name/email and submit/checkout. Email go to Jeffry (Maryla's son my cook) and also to customer. Jeffry prepare order and 30 minutes customer may pick up hot and fresh food. Processwire good for setting this up it seems, but how best to start? Is there tutorial similar? Thank you, Roderogo Sosa2 points
-
There's another detail that makes all the difference. The fact that in contao, the buttons are aligned to the right, far away from the pages name, makes it much more difficult to identify what line of buttons refer to wish page. is how I feel like by looking at that image2 points
-
I found a way to check within a repeater template files if the repeater item is the first or the last if ( empty($page->prev-id) ) // first item if ( empty($page->next-id) ) // last item This gives the information that is needed, its a little work around but it works fine2 points
-
This is absolutely possible and is done by certain restaurants. You will need to prepare your own order form but the API is like the tortilla, makes it easier to wrap everything up if you get my meaning.2 points
-
Hey guys, Working on a new idea I've wanted to do for a long time. It's fairly simple and small but maybe you guys will be able to use it in your PW projects at some point. I'm still working on it but here's what it's all about: http://phpformbaby.skakunmedia.com It's called PHPFormBaby and I'm still not sure if it's going to be just one class or a library. But I'm going to get it out soon and get your opinions on it. Cheers!1 point
-
@AnotherAndrew, thanks for your reply. There's an discussion here, maybe you're interested.1 point
-
Martijn Geerts: I knew I might stir up the bees nest. I'm not dissing on Ryan's work at all and saying that it is not appreciated. Perhaps we should have a donation option for those that would like to support PW. I would love to support Ryan's work and expenses, even supporting the hosting for this site and the forums. I think that would be a better gesture of support than by buying code.1 point
-
As a clarification to my original post: I've no doubt that this system is very powerful and lets you do a lot from that one single view. I also have no problem with a dashboard style UI, since it does have it's merits (though quite often dashboards are added just because they look cool.. and no, that's not a very good reason.) What I don't (and won't) understand is this particular choice of UI style. In that example above I see a huge pile of icons, all visible at once. Not only does it look stuffed, some of those icons really fail to convey what action they're tied to.. and I'm also pretty sure that someone as clumsy as me would way too often click wrong one without realizing that and cause unnecessary problems. There's a reason why many UI designers like to hide action buttons by default. PW has taken a completely different approach, yet it still manages to solve similar problems: * only the most common (and only nondestructive, unless you've installed a module that adds destructive ones among them) actions are available via tree, * actions are hidden by default and only visible after a page name has been clicked, thus reducing the clutter of tree view, * text is used instead of icons (the actions of which you'd have to either guess or remember.) It's simple and powerful and has a very small chance of confusing users. Of course once you've used a system for long enough you'll know exactly what all those tricky little buttons do -- but with the approach PW has taken none of these problems even exist in the first place. My point is that a powerful system can still have well designed UI. Or is that too much to ask? Regarding the point @adamkiss made about root != pages approach, I guess that makes sense in some (limited) situations. Still, PW has proven that even many of those situations can still be handled very well with it's "everything lives within one tree structure" solution. So forgive me for being somewhat skeptical here. If there's a need to create another tree, I'd rather see it as a completely separate entity, not artificially stuffed within one huge pile of everything. But hey, that's just my opinion -- everyone has one (or more) of those1 point
-
This is another way to accomplish it, perhaps more efficiently: $n = 0; $total = count($page->thingy); foreach($page->thingy as $data) { $n++; $data->isFirst = ($n === 1); $data->isLast = ($n === $total); echo $data->render(); } Your repeater_thingy.php template should now be able to compare against $page->isFirst and $page->isLast1 point
-
Welcome to the forums Roderigo. You may want to check out Form Builder, which might accomplish a lot of what you are looking for here, and pretty easily. Though you can also do it without, but it would involve more traditional HTML form building. Either way ,I think you'll be happy with ProcessWire as a foundation for your needs.1 point
-
I think I understand what's going on, though haven't stepped through the live code yet. But it looks to me like there's potentially an issue in PW's Fieldgroups::save function where it doesn't like to be called multiple times. It queues fields for removal and doesn't do the actual remove until you call Fieldgroup::save. That's what it should do. But as far as I can tell, Fieldgroups::save doesn't clear out the removal queue after it completes the save, meaning it may try to remove something that's already been removed if you are making multiple calls to it. Assuming I'm right about that, it's an easy fix to the core (and already made it locally), but for compatibility with current versions, try making this change: after your $t->fieldgroup->save(); in uninstallField add this line: $t->fieldgroup->removedFields->remove("name=$name"); does that fix it?1 point
-
Permissions aren't a static thing, so I'm reluctant to start adding more static columns of permissions to templates. Permissions are ultimately just pages and any number of unknown permissions can exist. I can't drop permission-to-role assignment because that's the basis of our RBAC, or any RBAC. It would be throwing out the baby with the bathwater. Connecting permissions to the templates (or pages) is just a way of saying where the user can apply a group of permissions that they have. This is an expected part of an RBAC, connecting a group of permissions with another entity for further qualification (whether a page, template or something else). That doesn't mean it's always easy to understand, and RBACs are never straightforward to understand at first glance, but they are powerful. We've attempted to make it more straightforward by separating out a few specific permissions in the template (page-view, page-edit, page-create, page-add) rather than just giving them 1 checkbox that applies all the page-* permissions present in the user's roles (as in most RBACs). But it's a balance of figuring out how far to go with it. If you start taking it to the extreme, then the purpose and power of the RBAC gets lost. Having page-view, page-edit, page-create, page-add in the template access is actually unnecessary for us, but it does reduce the quantity of permissions and roles necessary to achieve a particular access control scenario (which I think is a good thing). However, it's ultimately a tradeoff because it's limiting the power of the RBAC just by having it work that way (like Diogo found). But I think it's a balanced tradeoff because it ultimately reduces complexity, especially for those not familiar with RBACs. Currently, all the page-* permissions except for page-view are activated by page-edit as a kind of a parent permission. So if the user has page-edit, then any other page-* permissions they have get activated along with it. We've separated out page-create and page-add for finer control over those aspects. And we could continue separating out more like you suggested (the ones that are currently parented by page-edit). But I don't want to push further in that direction because I think it's fighting the RBAC and reaching further towards something that can't scale beyond a predefined set of permissions. Adding more columns of permissions in the template only solves it for one person's needs. Eventually WillyC will come along and want to assign page-yoda permission to a template independently of any other permissions. I'd rather go in the opposite direction and reduce what permissions can be assigned at the template (by default), but make it definable. Imagine going to Modules > Process > ProcessTemplate > [edit module settings] and selecting from an asmSelect which permissions should be assignable at the template level -- a nice power user option? That way we aren't presenting a giant table of checkboxes for the vast majority that do not need this, but we are giving the power-user option to those that do. After all, this is the first time I've ever heard of someone wanting to give access to sort children of a page without being able to actually edit the page. So it seems like an unnecessary level of complexity for most to have to consider these rare cases every time they setup template permissions. But if we give the superuser control over what permissions deserve this "assignable at template" status, then I think that lets us veer towards simpler and more powerful at the same time.1 point
-
Given that we don't know what the user's fields or types will be ahead of time, there isn't really any way to document it with the Page class (that I know of). The function that handles this particular situation (setting a value to a $page->pageref) is FieldtypePage::sanitizeValue(). It is currently documented (with phpdoc) to indicate what it's for and all the values that it accepts and returns. But doesn't say anything like "usually you'd set a PageArray" because I don't think anyone is going to be looking here unless they already know the routes that setting a value to a Page takes. Ultimately, the best way to document this sort of stuff may be outside of the code itself and in online documentation specific to each Fieldtype. I think the cheatsheet is a great resource for this stuff. Though I don't think there's anything specific to the situation we're talking about just because it's one of those things specific to a FieldtypePage. So I think FieldtypePage probably needs it's own manual. That's what we're doing now. But I'm not sure how to communicate to someone that when they set (or get) a value to a Page, a lot of decisions go on behind the scenes. In our particular case of setting a $page->pageref, the path would be this (pseudocode): $page->set('field_name', $somePage); { // if 'field_name' is a custom field confirmed by the page's fieldgroup, use setFieldValue() $this->setFieldValue('field_name', $somePage); { // get the Field object $field = $this->fields->get('field_name'); // let the Fieldtype sanitize the value before setting it to the $page, i.e. convert Page|int|string|array to PageArray $value = $field->type->sanitizeValue($this, $field, $somePage); } } That last line is where the magic happens. The sanitizeValue will accept $somePage in various types, but always returns a PageArray back to the page. If it gets something it doesn't like, then it's either going to throw an Exception or refuse it (depending on what the Fieldtype author thinks is appropriate). Something similar happens when you get() a value from a Page, tough even more behind the scenes: $page->get('field_name'); { // if field_name is a custom field confirmed by the page's fieldgroup, use getFieldValue() $this->getFieldValue('field_name'); { $field = $this->fields->get('field_name'); $value = parent::get('field_name'); // check if it's already loaded if(is_null($value)) { // value isn't yet loaded, so load it $value = $field->type->loadPageField($this, $field); if(is_null($value)) { // if no value then set a default (like blank PageArray) $value = $field->type->getDefaultValue($this, $field); } else { // convert value to runtime type, like array of ints => PageArray of Pages $value = $field->type->wakeupValue($this, $field, $value); } } // if output formatting is on, let the fieldtype modify it for presentation (if it wants to) if($this->outputFormatting) $value = $field->type->formatValue($this, $field, $value); } } I'm not exactly sure how to document this beyond the pseudocode above, or if it even matters. I'd rather people think of it as just setting or getting values and everything works. But it seems like a separate page of documentation for each Fieldtype might help to answer some of the questions.1 point
-
1 point
-
Makes sense, must agree on everything you're saying. ProcessWire really is great with export/import like you've intended. It's kind of a side effect that some a bit unusual things work. My habit of reading the source code doesn't always (usually even) lead to right conclusions and it would probably be better not to say everything aloud. Maybe I should just start using Soma's cheatsheet more instead of that. I was just surprised to see that assign really works that way there as I never would've tried that out myself. Couldn't agree more on this now that I understand it wasn't for convenience but for something totally different. Still, it would be great if there was a way to check which features aren't supposed to be used via API but are reserved for internal use. Then it would be 'at your own risk' to use something like that. Or is it actually so that the cheatsheet tries to cover more or less everything that is safe and recommended to use? As I said before, I haven't used that enough, clearly. I'm trying to follow recommendations myself whenever possible, but it isn't always clear where to find the recommendation (other than asking here, but somehow I'm not so used to doing that every time, yet). Documenting internal methods and usages in the comments has been also discussed before and that's a good way to achieve what I'm after here. It doesn't make things clear to someone who just happens to try some syntax that's not meant to be used - but what does, apart from disabling things somehow (no, I'm not suggesting that at all). This is enough for now, I think. ProcessWire works great and is great, and will be surprising me every now and then for a very long time. And I'm very happy with the way things are even if I may whine a little sometimes.1 point
-
First time I looked I only saw the left side of that thing and thought that "well, this isn't so bad." Now I wish I didn't see the rest of it. @MarcC: that (root != home) is a strange thing, really. Never understood it myself. I guess there must be something that we're just missing though -- I've had more than one client specifically request that kind of structure before..1 point
-
This is a site I released a couple of years ago, but since their previous hosting provider couldn't upgrade her plan to mysql 5 (!) I somehow managed to get all kinds of weird textpattern messages when editing the different photoalbums. I moved her to another hosting company. Kudos to Textpattern for working on a server which was never updated since the early releases by Dean of TextPattern. Just for the photoalbums I converted the site to ProcessWire in two nights. Props for TextPattern for not infering with my code so the transformation process couldn't be done any quicker. Props for Ryan for making the other end possible. Lisettemartens.nl Game on. Got a couple of sites to convert too. Now it's time to buy that form thing.1 point
-
Mike, maybe for next year's CMS awards we can get it setup on Form Builder, which keeps out spam with honeypots, Akismet and a Turing test. The advantage of honeypots and Akismet are that the user never knows there are spam prevention measure in place (unless they submit spam), as it all happens beyond their view. The turing test option is within their view (if you decide to use it), but it's up to the administrator to decide how simple or difficult to make the test. Recaptcha would qualify as an extremely difficult Turing test. I don't blame you for using recaptcha. If that was the only choice I would choose it in a heartbeat over an unprotected form. Having built a whole lot of forms over the years, spam would fall near the top of my list of considerations on any form, so I respect use of recaptcha even if it's become a lot more difficult to solve lately.1 point
-
Great solution, thanks for posting this Pete. I figure I should follow-up and post the route that I use too, though this one depends on the server running unix. It creates rotating backups off your non-web-accessible home directory with a cron job, and then a cron job on your machine (or another server) copies the backups over every day. 1. Login to your unix-based web account (SSH or FTPS/SFTP) and create a directory off your non-web-accessible home directory where the backups will be stored. I call mine /db-backups/: mkdir /home/your-account/db-backups 2. Create a file in your home directory called .my.cnf (starting with a period). This holds your DB connection information. Place the following into that file, replacing "mysql_username" with your database username, and "mysql_password" with your database password: /home/your-account/.my.cnf [client] user=mysql_username pass=mysql_password If working on a shared server or some environment where other accounts can get into your files, make sure that .my.cnf file isn't readable by anyone else. i.e. type "chmod og-rwx .my.cnf" to remove (o)ther and (g)roup read/write/execute access to it. 3. Create another file in your non-web-accessible home directory called db-backup and paste the following in there. Update the first two lines in the script to point to the directory you created in step 1 (DB_BACKUP) and the name of the database you want to backup (DB_NAME). /home/your-account/db-backup #!/bin/bash # modify the following to suit your environment DB_BACKUP="/home/your-account/db-backups" DB_NAME="your-db-name" # title and version echo "" echo $DB_NAME echo "----------------------" echo "* Rotating backups..." rm $DB_BACKUP/$DB_NAME.5.sql mv $DB_BACKUP/$DB_NAME.4.sql $DB_BACKUP/$DB_NAME.5.sql mv $DB_BACKUP/$DB_NAME.3.sql $DB_BACKUP/$DB_NAME.4.sql mv $DB_BACKUP/$DB_NAME.2.sql $DB_BACKUP/$DB_NAME.3.sql mv $DB_BACKUP/$DB_NAME.1.sql $DB_BACKUP/$DB_NAME.2.sql echo "* Creating new backup..." mysqldump $DB_NAME > $DB_BACKUP/$DB_NAME.1.sql echo "----------------------" echo "Done" Note: I found this code somewhere else online a couple years ago and don't remember where to properly credit it. 4. Save the above and make it executable: chmod u+x db-backup If you are connected via SSH, test it out to make sure it's working by typing: ./db-backup It should create the first backup in your ./db-backups/ directory. 5. Setup a daily cron job to execute that file: /home/your-account/db-backup … most web hosting accounts have some ability to setup cron jobs in the control panel. 6. Now your server is keeping rotating backups in your account. Next I'd recommend going further and copying them to another machine, automatically every day. How you do this depends on whether you are going to use SFTP/FTPS or SSH (with rsync). Its preferable not to use regular FTP since it's not secure. In my case, I've setup a cron job on my OS X desktop to copy over the files to my computer every day. It executes a file that looks like this: #!/bin/bash /usr/bin/rsync --archive --rsh=/usr/bin/ssh --verbose user@domain.com:db-backups/* /Users/ryan/Backups/db/ That copies those rotating backups to a /Users/ryan/Backups/db/ directory on my computer. In order for the above to work, you'd have to already be using SSH with your account and have your SSH keys assigned so that you can connect without typing your login/password. If anyone is running a similar setup, I'll be glad to tell you how to do that. But I know there are other ways to automate this task and the approach you use here kind of depends on the platform and whether you have SSH access on the server. This setup is pretty bulletproof, but I'd like to have some module in PW in the future that will let it do all of this for you – Automatic backups from one server to another.1 point