getgrav / grav

Modern, Crazy Fast, Ridiculously Easy and Amazingly Powerful Flat-File CMS powered by PHP, Markdown, Twig, and Symfony
https://getgrav.org
MIT License
14.59k stars 1.41k forks source link

How to add page virtually using plugin #3617

Open stefanrybacki opened 2 years ago

stefanrybacki commented 2 years ago

I cannot seem to be able to add a virtually via plugin that behaves the same as a md file.

Here is my plugin attempt:

<?php
namespace Grav\Plugin;

use Grav\Common\Plugin;
use RocketTheme\Toolbox\Event\Event;
use Grav\Common\Page\Page;
use Grav\Common\Grav;

class Test24Plugin extends Plugin
{

    public static function getSubscribedEvents()
    {
        return [
            'onPluginsInitialized' => ['onPluginsInitialized', 0]
        ];
    }

    public function onPluginsInitialized()
    {
        if ($this->isAdmin()) {
          return;
        }
        $this->enable([
            'onPagesInitialized' => ['onPagesInitialized', 0],
        ]);
      }

    public function onPagesInitialized()
    {
        $pages=$this->grav['pages'];
        $page = new Page();
        $page->header([
          "taxonomy"=>[
            "tag"=>['test']
          ]
        ]);

        $page->routable(true);
        $page->published(true);
        $page->visible(true);
        $page->date(date("Y-m-d H:i:s"));
        $page->title("abc2222");
        $page->content("test");

        $page->template("default");
        $page->id("test_12345");
        $page->parent($pages->root());
        $page->path("/test/12345");
        $pages->addPage($page, "/test/12345");
    }

}

What works is that I can access the page via /test/12345, however the page does not appear in any page collection defined in other pages, e.g. '@taxonomy.tag': test Do you have any pointers what else I need to do? I am on Grav v1.7.35 - PHP 8.0.22

Thanks in advance

stefanrybacki commented 2 years ago

so nobody has an idea about this?

rhukster commented 2 years ago

I have recently added a page virtually, but it only needed to be a 'page' object because I added it to a collection:

            $page = new Page();
            $page->title($data['title']);
            $page->content($data['raw_content']);
            $page->path($path);

            $header = [
                'routes' => [
                    'default' => $url,
                ],
                'process' => [
                    'markdown' => false,
                ]
            ];

            $page->header($header);

            $pages->addPage($page);
            $collection->addPage($page);

There are many examples of adding pages virtually, like in "login" plugin, which you can examine to see how it's done, but again, these are for specific applications. In Login for example, they are added based on a local plugin-provided default page, that Grav can route to if no page is provided (login page for example). They are dynamic and have to be initialized when needed. They are not automatically around and full pages for any other plugin to interact with as if they were physical files.

It's just not going to be a performant way to handle pages. Physical pages will always be much faster.

stefanrybacki commented 2 years ago

@rhukster Thanks for answering my question, however I have to admit I am not satisfied, as I believe if I add a page, whether by md file or virtually by plugin, it should IMHO be available in page collections defined in pages, or when using Page.collection methods.

So I did some debugging and it seems the problem is, that even though I add the a page virtually to the pages object, I add it to A pages object. But since the Page.collection method does Grav::instance()['pages'] it gets another pages object, which does not contain my virtually added page.

This sounds like a bug to be honest, or is there a way I can hook into creation of that pages object as well?

Just to be clear I understand, that the pages object itself is load from cache, which makes it fast, but there stands nothing in the way for my plugin to load virtual pages from cache as well before adding them to the pages object.

Thanks in advance.

rhukster commented 2 years ago

That's why in my example I also add the page to the collection object so it could be used in the collection. I agree though, this might well be a bug, just had any easy workaround.

rhukster commented 2 years ago

@mahagr can you think of any reason why a page added this way would not be available in the page's instance?

mahagr commented 2 years ago

Added pages need to be added on every page load and they may not be in taxonomies etc, depending on the order the plugins are fired. Also adding the page doesn't really do everything that the build pages logic does; you just hack the page into existence.

This is one of the reasons why I wanted to retire the old pages logic, but it was really hard to make the new Flex Pages logic compatible with the old code.

stefanrybacki commented 2 years ago

@mahagr so when using flex pages it would be possible?