When to add virtual pages?


#1

Hello,

at the moment I’m trying to extend the events plugin (https://github.com/kalebheitzman/grav-plugin-events) so that it allows to read and display events from an iCalendar file. To achieve this I’d like to create a dynamic page for each event without having real folders or real files on the disk.

I tried to utilize the already existing onPagesInitialized hook, but that doesn’t seem to work. Is this hook called too late in the Grav lifecycle to add pages? Must or should I use onPluginsInitialized instead?

Best regards,
Michael


#2

@myscha I’m not familiar with the ‘Events’-plugin, but can give you some suggestions…

The following presumes that the events collected by the plugin are stored somewhere in the site. Eg. ‘/user/data/events.yaml’.

If 2 pages in your ‘/user/pages’ folder is surmountable, you could try the following:

  • Page ‘event-list.md’ could read the data-file in Twig and generate a page which lists all events. The links for the events should contain a parameter with the ‘id’ of an event, like ‘https://mydomain/event-details/id:22’ .
  • Page ‘event-details.md’ takes the parameter and used the ‘id’ to fetch all details of the event.

If you don’t want any page in your ‘/user/pages’ folder, you could move the two files into ‘plugins/myplugin/pages’ folder and catch the ‘onPageNotFound’ event and return the pages in your plugin:

public function onPageNotFound(Event $event): void
{
    $path = $this->grav['uri']->path();

    if ($path === '/path/to/event-list') {
        $page = new Page();
        $page->init(new \SplFileInfo(__DIR__ . '/pages/event-list.md'));

        $event->page = $page;
        $event->stopPropagation();
    } elseif ($path === '/path/to/event-details') {
        $page = new Page();
        $page->init(new \SplFileInfo(__DIR__ . '/pages/even-details.md'));

        $event->page = $page;
        $event->stopPropagation();
   }

   // Default 404.md will be shown
}

Hope this gives you some ideas to work with…


#3

@pamtbaau
Thanks for your tips.

My idea was having an iCalendar file, e.g. from Thunderbird/Lightning, and provide the events therein either as a list or as a calendar. The mentioned plugin already offers the capability to do this, it only doesn’t read iCal files. So there’s no yaml file that could be read and I don’t know whether Twig offers the possibility and/or efficiency to parse other file formats.

The easiest solution would be parsing the iCalendar files(s) and writing an according file/folder for each event. My problem with this was that I considered only those event hooks that are fired on every page access. And, of course, it makes no sense to parse and re-write the events on every page load.

But, thanks to your post, I thought about using other event hooks. In the meantime I’m considering onAdminSave or onAdminAfterSave which I could use to parse the iCal file and create a file/folder for each event. This would lead to a one time run of the parsing routine which would be ok for me.

But now I’ll have to test if these hooks are fired when the plugin setting are saved, otherwise this won’t work either.