How to prepend a collection to another collection, so we ensure the first is placed at the beggining of the second ?
Thanks
How to prepend a collection to another collection, so we ensure the first is placed at the beggining of the second ?
Thanks
Considering the page collections, I think prepend()
or merge()
methods will do the trick. Especially merge()
.
Thanks,
prepend got me an exception, I assumed because the description refers to ‘an element’ and not a collection as in merge.
Using merge did not seem to respect the order, as in one collection before the other.
The code I am using this with is a old’ish, a bit convoluted and I am resisting the urge to rewrite it, but let me reproduce it here anyway, it is a page method:
'sortedProgrammesPanel' => function () {
// Sorts LISTED 'programme' pages by 'publicationDate' of their last child,
// or by their own publicationDate if they don't have children.
$sortedProgrammesPanel = new Pages();
$theChildren = new Pages();
foreach(site()->children()->filterBy('intendedtemplate', 'programme')->listed() as $p) {
if ($p->hasChildren()) {
$theChildren->append($p->children()->last()); // appends the last children
} else { // if no children, append the parent itself
$theChildren->append($p);
}
}
// Sort
$theChildren = $theChildren->sortBy('publicationDate', 'desc');
// Now loop $theChildren to sort programme pages
foreach($theChildren as $c) {
if ($c->intendedTemplate() == 'programme') { // If it is a programme without children
$sortedProgrammesPanel->append($c); // Append the programme itself
} else {
$sortedProgrammesPanel->append($c->parent()); // If it is an update append the parent programme
}
}
// Prepend draft programmes to the collection and return it
$sortedProgrammesPanel->merge(site()->children()->filterBy('intendedtemplate', 'programme')->drafts());
return $sortedProgrammesPanel->indexOf($this);
}
This page method is used in query language as such:
sections:
programmes:
type: pages
headline: Programmes
status: all
sortable: false
sortBy: sortedProgrammesPanel
templates:
- programme
image: false
width: 1/2
In this pages section in the panel I get the drafts mixed between the listed programme pages, and not at the beggining or end of the list, which is what I am attempting to achieve
Thank you
If I got the problem right.
I think you don’t need to sort the collection in section (sortBy: sortedProgrammesPanel
), you have already listed on PHP side.
Try to use the merge method on drafts.
$drafts = site()->children()->filterBy('intendedtemplate', 'programme')->drafts();
$programmes = $drafts->merge($sortedProgrammesPanel);
Let’s clean this up first. All these lines can be replaced with:
$sortedChildren = site()->children()->listed()->filterBy('intendedTemplate', 'programme')->sortBy( function( $item ) {
if ( $item->hasChildren () ) {
return $item->children()->last()->publicationDate()->toDate();
}
return $item->publicationDate()->toDate();
}, 'desc');
Thank you both,
@ahmetbora As far as I understood you, this is not a collection but a page method that I pass to sortBy: on site blueprint to sort the programmes in a particular order.
@texnixe Danke.
The following works well.
<?php
Kirby::plugin('plagasul/page-methods', [
'pageMethods' => [
'sortedProgrammesPanel' => function () {
$drafts = site()->drafts()->filterBy('intendedtemplate', 'programme');
$sortedProgrammesPanel = site()->children()->listed()->filterBy('intendedTemplate', 'programme')->sortBy( function( $item ) {
if ( $item->hasChildren () ) {
return $item->children()->last()->publicationDate()->toDate();
}
return $item->publicationDate()->toDate();
}
, 'desc');
return $drafts->merge($sortedProgrammesPanel)->indexOf($this);
}
]
]);
Merging listed programmes into the drafts, as suggested by @ahmetbora effectively prepends listed programmes to drafts so we get: Drafts, Listed programmes. Merging drafts into listed programmes, prepends drafts, so we get: Listed programmes, Drafts.
So that is the way to control prepending or appending a collection into another.
Cheers!