Hi.
I’m looking to set up a calendar that can order content from different page templates.
I have several blueprints (shows
and rendezvous
), which have date informations and are stored in multiple directories. In shows
, the dates are stored in a structure (several dates are possible). In rendezvous
, only one date is possible.
I’d like to mix these two types of contents together and to sort them by date, so that I have:
- 26/04/2020
- 19:00 – [rendezvous 1]
- 20:30 – [show 1]
- 22:00 – [rendezvous 2]
- 28/04/2020
- 14:30 – [show 2]
- 20:30 – [show 1]
- 05/05/2020
Notes:
- I may have performance issues (relying on $site->index() filtered by templates array), because there will be a lot of events
- All events should be future events (not difficult, but I failed to solve via custom pages models)
- I must duplicate shows display on multiple days, according to each date.
I can’t figure out where to start…
If anyone here can help me, thank you in advance.
What numbers are we talking here? A custom cache for the events might be useful if there are two many. Avoid $site->index()
if possible.
Yes, you can merge structure items with pages by creating a single collection from array items.
How exactly are these stored? Could you post the blueprint?
Hi Sonja.
Thank you for your answer.
Regarding the potential performance issues, I’ll try to deal with a custom cache.
Shows belong to a “season”, they’re stored in /content/seasons/2019-2020/
. Rendezvous are in /content/rendezvous/
. To group shows by day, I used the solution you provided here: Create a collection of pages from a structure field - #10 by texnixe.
# controllers/calendar.php
return function ($site, $page, $kirby) {
// get future shows
$shows = page("seasons/2019-2020")->children()->listed()->filter(function ($child) {
# what should I use to grab only future shows ?
});
// get all dates
foreach($shows as $show) {
$dates = $show->dates()->toStructure()->pluck('date');
sort($dates);
foreach($dates as $date) {
$mydates[] = strtotime($date);
}
}
// deduplicate + sort
$mydates = array_unique($mydates, SORT_NUMERIC);
sort($mydates);
return [
'shows' => $shows,
'dates' => $mydates
];
};
function getShowsPerDate($shows, $day) {
$showsPerDay = $shows->filter(function($child) use($day) {
$dates = $child->dates()->toStructure()->pluck('date');
foreach($dates as $date) {
$strDates[] = strtotime($date);
}
// check if the current day is in dates
if(in_array($day, $strDates)) {
return $child;
}
});
return $showsPerDay;
}
Then, in the template:
<?php foreach($dates as $date) :
$dayShows = getShowsPerDate($shows, $date); ?>
<?php foreach($dayShows as $show) :?>
(…)
This logic works for shows (even if I thought I’d better have the final data prepared in the controller without calling getShowsPerDate in the loop), but I don’t know where neither how to plug the rendezvous…
Sure. Nothing fancy here (I simplified):
# show.yml
fields:
dates:
label: Dates
type: structure
fields:
place:
type: text
date:
type: date
label: Date
time: true
# rendezvous.yml
fields:
place:
type: text
date:
type: date
label: Date
time: true
Thanks a lot for your help. I hope I’ve been clear enough.