Jump to content

Programmatic manual sorting of page reference pages


Martin Muzatko
 Share

Recommended Posts

Hello!

I want to set the manual page sort of a page reference field with a pageArray.

I found this existing thread which does not answer the question unfortunately.

https://processwire.com/talk/topic/18510-sort-page-reference-field/?tab=comments#comment-162124

It looks like there are different concepts of sort. One that works with properties (sort=created) and one with a page as argument and index as second.

However, I found this in wire\modules\Inputfield\InputfieldPage\InputfieldPage.module, that may explain how sorting is done when doing manual drag and drop. How can I reproduce that for my own sorting?

        // if pages were added, re-sort them in case they were dragged to a different order
        // an example of this would be when used with the InputfieldPageAutocomplete
        if(count($this->pagesAdded) && is_array($value)) {
            $sortedValue = $this->wire('pages')->newPageArray();
            foreach($newValue as $page) {
                if($page->id < 1) $page = $this->pagesAdded->shift();
                if($page->id && !$sortedValue->has($page)) $sortedValue->add($page);
            }
            $newValue = $sortedValue;
            $this->setAttribute('value', $newValue);
        }
Link to comment
Share on other sites

Not totally sure what you are asking, but you can do a sort of some pages (either as part of a selector, or using the sort() method of WireArray) or you can set the sort value of some page(s) (either by setting $page->sort to some integer value, or by using the $pages->sort() method). The sort value of pages under a given parent determines their order in the page tree if no automatic sort of children is defined on the parent template/page.

And if you do "sort=sort" or $some_pagearray->sort("sort") you are sorting by the sort value. Makes sense??

If you are saying you want to go through some pages and put them in a manual order that is different than their manual order in the page tree then one approach is to set a custom property of each page to an integer and then sort by that custom property.

foreach($some_pagearray as $p) {
    // Some code to work out $sort_int for $p so that it will go where you want
    // ...
    $p->custom_sort = $sort_int;
}
$some_pagearray->sort('custom_sort');

 

 

Link to comment
Share on other sites

If you are searching for programatically save your own programatical defined sort order, you may find useful code snippets here:

 

Interesting for you are the function(calls) of databaseUpdateSortInPages

Also reading the few discussion posts may be of interest.

  • Like 1
Link to comment
Share on other sites

I need to programmatically SET the order/sorting of the pages, not when getting the pages from the page selector field.

The problem is, that setting the manual sort value of the page won't help, as they are neglected by the page reference field.

To tell the full story: I'm building a CMS in a CMS.

image.thumb.png.3e54e7688fdd109cd231e57ff6abe073.png

 

image.thumb.png.b4442fc7842b098e65f218c0231ef942.png

 

pageModules are set via Rest API:

function setPageModules($page, $data, $contentPage = false) {
    $page->of(false);
    $pages = $page->pageModules;
    if (!$contentPage) {
        $contentPage = wire('pages')->get('template=page-contents');
    }
    
    foreach ($data as $key => $moduleData) {
        if(isset($moduleData->id)) {
            $module = wire('pages')->get($moduleData->id);
            $module->of(false);
            setFieldValues($moduleData, $module);
            $module->save();
        } else {
            $module = new Page();
            $module->parent = $contentPage;
            $module->of(false);
            $module->template = $moduleData->template;
            $module->title = $page->title.'_'.$moduleData->template;
            $module->save();
            $module->of(false);
            setFieldValues($moduleData, $module);
            $module->save();
            $moduleData->id = $module->id;
            $page->pageModules->add($module);
        }
    }
    $page->save();
    $page->of(false);
    
    foreach($data as $key => $moduleData) {
        // TODO: SORTING!
        // $module = wire('pages')->get($moduleData->id);
        // $module->sort = $key + 1;
        // $module->save();
    }
    $page->pageModules->save();
    foreach ($page->pageModules as $module) {
        $index = array_filter($data, function($item) use ($module) {
            return $item->id == $module->id;
        });
        if (!count($index)) {
            $module->delete(true);
        }
    }
    $page->save();
}

the $contentPage holds all content modules ever created. So it gets quite messy:

 

image.thumb.png.1cb4d56a1aad812ef5ea336ec6ff798a.png

 

So now I need to set the sorting, defined by the user input ( I get an array ob content module objects via my rest API)

But there is no way to set the manual sorting of a page reference field.

I will look through your thread horst. Thanks!

Link to comment
Share on other sites

8 hours ago, Martin Muzatko said:

But there is no way to set the manual sorting of a page reference field.

What is causing you to draw this conclusion?

The value of a (multiple) Page Reference field is a PageArray. The sort order of pages in the field will be the sort order of the pages in the PageArray at the time the field (or the whole page containing the field) is saved. So setting the sort order of the field consists of putting the pages in the PageArray into the order you want and then saving the field (or the whole page containing the field).

So if I have a Page Reference field "colours" which is currently empty on page $p and I add some pages to the field then the order is the order in which I add them (to the PageArray)...

$p->of(false);
$yellow = $pages->get('name=yellow');
$p->colours->add($yellow);
$red = $pages->get('name=red');
$p->colours->add($red);
$blue = $pages->get('name=blue');
$p->colours->add($blue);
$p->save('colours'); // Alternatively you could save the whole page
// Sort order of $p->colours is yellow, red, blue

Suppose I now want to change this sort order to some other custom order. Let's say I want to sort them by the length of the page name.

$p->of(false);
foreach($p->colours as $colour) {
    $colour->custom_sort = strlen($colour->name);
}
$p->colours->sort('custom_sort');
$p->save('colours'); // Alternatively you could save the whole page
// Sort order of $p->colours is red, blue, yellow

 

  • Like 2
Link to comment
Share on other sites

Is "custom_sort" a builtin of processwire? I wouldn't want to implement an extra field for that.

Also: Since contentmodules can also be re-used on other pages, I don't know if setting the sorting on the page itself would help.

Link to comment
Share on other sites

1 hour ago, Martin Muzatko said:

Is "custom_sort" a builtin of processwire? I wouldn't want to implement an extra field for that.

It is neither built-in nor is it a field - it is just a custom property that you are setting to a page object while it is in memory. You can name the property anything you like - it doesn't need to be named "custom_sort".

1 hour ago, Martin Muzatko said:

Also: Since contentmodules can also be re-used on other pages, I don't know if setting the sorting on the page itself would help.

The "custom_sort" is not saved to the database for any page - it only exists while the page is in memory, and it's purpose is simply to provide some property to use the sort() method on. Then once the PageArray is sorted on that property and saved to the Page Reference field the sort is retained as part of the Page Reference field value.

If you just give it a go it will probably start to make more sense. 

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...