Hello @texnixe, and thank you for the answer.
Sorry for not being clear. This project is quite heavy, so I tried to simplify it, I’ll be more precise now on.
Long story short, the website have articles (here named as contributions) separated in three templates, and they all have authors (not users), represented either by a page within the site, or by a virtual one builded upon a tag field. I’m referencing the authors of an article by a method within the article’s page model, returning a collection of pages. This method is named auteurices()
.
The articles are also organised within parents pages, named as antennes and programmes. Antennes are at the roots of the content, and programmes are children of antennes. Articles can be either children of an antenne or of a programme.
However, for an article, antennes and programmes can either be its parents, or some other pages linked to it by a pages field. Both are also referenced by two methods within the article’s page model, returning two collections of pages. These methods are named antennes()
and programmes()
.
Here, I’m on the author page model, and I would like to build two distinct collections of pages representing all the antennes and all the programmes of this author’s articles.
To do this, I first get all the author’s articles. This is made by filtering all the website articles (which are builded inside a kirby->collection()
), by looking for the author’s page id inside the results of their auteurices()
method.
Then I get the antennes and programmes of these articles by recovering the results of the antennes()
and programmes()
methods. And my troubles are at this point (more on that at the end).
Author page model :
On this model, i’m building the author’s article pages collection, and I’m trying to get the antennes and programmes of these articles inside another two collections.
class AuteuricePage extends Page {
public function contributions() {
return kirby()->collection('contributions')
->filterBy( 'auteurices','*=', $this->id() );
}
// This below I find quite quirky
public function antennes() {
$elms = $this->contributions()->pluck('antennes', null, true);
$a = [];
foreach ($elms as $value) {
$a[] = $value->pluck('id');
}
$a = call_user_func_array('array_merge', $a);
return pages($a);
}
public function programmes() {
// same logic as antennes().
}
}
Here is the detail of the collection :
//kirby/site/collections/contributions.php
return function ($site) {
return $site->page('antennes')
->index()
->listed()
->filterBy('template', 'in', templates)
// templates is a const array
->sortBy('date', 'desc');
};
Article Page Model
On that page model, I build the article’s authors page collection, as well as the article’s antennes and programmes pages collections.
For the authors, basically, I build a page collection both with the authors page referenced by a multiselect field and with virual pages made upon a tag field. As the articles can have both, only one, or none, the collection is safely merged or returned at the end.
For antennes and programmes, as they are ancestors of the article, I’m just picking the right one and merge()
the linked ones if they exists.
class ArticlePage extends Page {
public function auteurices() {
// auteurice is a multiselect field querying author pages.
$auteurice = $this->auteurice()->split();
$auteurice = pages($auteurice);
// auteuriceFantomes is a tag field.
$auteuricesFantomes = $this->auteuriceFantomes();
// Theses functions are detailed below
$auteuricesFantomes = makePages($auteuricesFantomes);
return mergeIfExist($auteurice, $auteuricesFantomes);
}
public function antennes() {
$antenne = null;
// If the parent is a programme, then the antenne will be the programme parent.
if($page->parent()->template() == 'programme') {
$antenne = $page->parent()->parent();
}
// Else, the antenne is the parent.
elseif($page->parent()->template() == 'antenne') {
$antenne = $page->parent();
}
// Here i'm recovering the antennes linked to the page by a pages field.
$antennesAdd = $page->antenneAdd()->toPages();
// Function are detailed below.
$antennes = mergeIfExist($antennesAdd, $antenne);
return $antennes;
}
public function programmes() {
// Same kind of logic than for antennes…
}
}
The function makePages()
is used to build of collection of virtual pages with a tag field.
function makePages($field) {
if($field->exist() && $field->isNotEmpty()) {
$arr = [];
foreach($field->split(',') as $key => $value) {
$parent = site()->page('auteurices');
$arr[] = new Page([
'slug' => 'ghosts/' . Str::slug($value),
'content' => [
'title' => $value,
],
'parent' => $parent,
]);
}
$pages = new Pages($arr);
return $pages;
}
}
The function mergeIfExist()
safely return the end collection.
function mergeIfExist($obj1, $obj2) {
if($obj1 && $obj2) return $obj1->merge($obj2);
elseif($obj1 && ! $obj2) return $obj1;
elseif(! $obj1 && $obj2 ) return $obj2;
}
What the troubles are
So, inside the authors page model, I would like for the antennes / programmes pages collection to be builded that way :
pages($this->contributions()->pluck('antennes', ',', true));
Which seems to be a proper and nicer way to do it.
However, when I’m applying pluck()
to the collection, it returns a multidimensional array that i cannot use inside the pages()
helpers. And when I’m trying to split()
it, the restul array is a bit weird. Eg :
Array
(
[0] => page/antenne1
page/antenne4
[1] => page/antenne2
page/antenne6
…
)
My suspicions are upon the merge()
of the antennes and programmes linked by a pages field, inside the article model. But I’m not sure how and why.
Here it is. I hope I’m clearer this time. And thank you again for your time. I know I’m only asking for code improvements here, as my code basically works, but I do really think there is some logic I’m missing, or something I do not understand, and would like to learn it ![:slight_smile: :slight_smile:](https://emoji.discourse-cdn.com/apple/slight_smile.png?v=9)