A stocking full of $pages updates 23 December 2016

ProcessWire 3.0.46

Christmas stockings are where you find the small gifts, while the big stuff goes wrapped up under the tree. Yet, looking back, it often seems like some of the most useful stuff ends up in those stockings… Swiss army knifes, digital tire gauges, flash drives, and so on. This week, the big stuff is between you and Santa, but what we do have are lots of useful stocking stuffers for you to enjoy in ProcessWire 3.0.46!

New $pages API finding method

$page->findIDs($selector)This method works just like $pages->find() except that it simply returns an array of matching page IDs. If there are situations where that's all you need, this method is a whole lot faster than $pages->find(). Read more

New $pages API manipulation methods

The following new $pages API methods are useful for manually sorted pages.

$pages->sort($page, $n)This method sets and saves the sort value of $page to integer $n (0 based), and then also adjusts the sort values of all sibling pages as needed to ensure consistent order.

$pages->sort($page, true)This is an alternate use of the sort() method that makes it re-build the sort values for all children of $page. In doing this, it removes any gaps or collisions in the sort values.

One nice thing about the sort() method is that it doesn't actually load any pages to do its job. It handles it all at the database level, so it can do it's job quickly regardless of scale.

I'm not sure how often this might be needed by others, but we needed it for certain instances in the core, and there was also a request for something like it, so we made it part of the advanced $pages API group.

$pages->insertAfter($page, $afterPage)This method inserts $page after the given $afterPage and commits it to the database. Internally it uses the above $pages->sort() method, so the sort values of siblings are adjusted as needed to achieve the correct placement in a manner that's efficient.

The $afterPage argument can either have the same parent as $page or a different parent. If the parent is different then the given $page goes through a $pages->save() as well (along with all related hooks) to update the parent.

$pages->insertBefore($page, $beforePage)This works exactly like the insertAfter() method except that it inserts $page before the given $beforePage instead.

These new insert before/after methods work consistently with those you may already be familiar with in WireArray types or InputfieldWrapper types.

Support for negative “limit” and “start” values in selectors

If you've used limit=n in a selector before, you know that it is how we typically do pagination. For instance, if we wanted to get the first 10 children of $page (or the current pagination), we would do something like $page->children("limit=10"), or something similar with a $pages->find() call.

Now you can also specify negative numbers for that limit. For instance, if you specified limit=-10, it will pull the last 10 items rather than the first 10.

// get the last 10 children
$lastChildren = $page->children("limit=-10");
// get the last child
$lastChild = $page->child("limit=-1");
// last 3 items
$pages->find("template=basic-page, limit=-3");

While less commonly used, there's also the "start" property in selectors that typically goes along as an optional extra with the "limit", and specifies which index the results should start from (zero-based). This too can now accept negative values as well. For instance, if you wanted the 2nd to the last child:

$child = $page->child("start=-2");

Or maybe the 2nd to the last pagination of 10 pages:

$items = $page->children("start=-20, limit=10");

I'm using the Page children() and child() methods in most of the examples above, but should note that this capability exists anywhere that you would use a page matching selector in ProcessWire, whether from a $pages API call, a $page traversal call, or any kind of WireArray or PageArray find/filter call. Meaning they are supported by both database and in-memory selector operations.

New “index=n” available in selectors

This new selector property lets you specify the zero-based index of the item you want to retrieve. Think of it like an nth-child() CSS selector, or a jQuery eq() method. It's similar to using a start=n, limit=1 selector, and like them, also accepts negative values to reference the end rather than the beginning. Essentially, it provides a shorter or more clear syntax for instances where you want to pluck an item at a specific index. Here's a few examples:

// get the 10th match
$pages->find("index=9, foo=bar");
// get the 10th last match
$pages->find("index=-10, bar=baz");
// get the 2nd child
$page->child("index=1");

The index property also accepts the keywords "first" and "last", which refer to "0" or "-1", but might provide more readable syntax for some cases:

Like the start and limit updates, the index property can be used in all database and in-memory selectors.

ProDrafts updates

We're nearing the 1-year anniversary of ProDrafts in a couple of months, and have a lot of nice upgrades on the way to celebrate. Here's a summary of what's in store for our January update:

When a user doesn't have permission to publish a draft, they now have the option to "submit it for approval". This places it in a pending review queue for users that have permission to publish it. Editors can also make updates to their draft or withdraw it from the approval queue.

When editing a draft that's been submitted for approval, users with publish permission to the page can now click "Approve" or "Reject". If they click Approve, the page is published. If they Reject, the page is removed from the pending queue and sent back to the editor for further changes.

Notification emails accompany the workflow so that publishers know when drafts are pending and editors know when their drafts are approved or rejected. Publishers and editors can subscribe to email notifications by checking a box in their user profile.

The drafts list screen (ProcessProDrafts) now uses tabs to isolate drafts awaiting approval from the main list of drafts.

Lastly, I wanted to mention that I'm also currently working on repeater support for drafts as well. This part isn't as far along as the workflow processes mentioned above, but since many have asked for it I wanted to let you know it's in our current high priority list of ProDrafts updates and actively being worked on right now and into the holidays.

Other tweaks in 3.0.46

We've made some adjustments to the dropdown submit buttons (like seen in the page editor) so that they should be a little more friendly when using a mouse. When you click to open the dropdown, it no longer disappears immediately if you hover away from it. Now it will stay open for a second or two, to prevent unintentional menu closure.

A debug mode memory leak that occurred even when debug mode was off has been fixed in the $pages->findMany() method. This would not have been an issue except at very large scale, but now not even a small memory leak is possible here. We've also optimized the performance for some usages of $pages->findMany() as well. Thanks to @apeisa and Avoine for helping us to identify these.

Tomorrow, I'll be starting off my Christmas eve with a coffee and the ProcessWire Weekly, and hope to see you there.

Latest Forum Posts

Latest Blog Post

ProcessWire 3.0.76, a new front-end account module and much moreThis week we’ve got a new core version, a new version of the Uikit 3 admin theme, a new version of ProCache with SCSS and LESS support, plus a brand new module that provides user login, new user registration and a user profile editor, all for the front-end of your site. / Blog / RSSSeptember 22 6:02 pm