From 9beefb3162913e6447b1447bc654695dfd35b1bd Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 9 Oct 2019 15:24:26 +0300 Subject: [PATCH] Allow Flex Pages to be initialized separately in site and admin, remove Flex Objects plugin dependency --- CHANGELOG.md | 2 +- system/blueprints/flex/pages.yaml | 123 ++++++++++++++++++ system/src/Grav/Common/Page/Pages.php | 95 +++++++++++--- .../Common/Processors/PluginsProcessor.php | 2 + .../Common/Service/PagesServiceProvider.php | 28 ++-- 5 files changed, 214 insertions(+), 36 deletions(-) create mode 100644 system/blueprints/flex/pages.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index afb0ef302..ee4fb8ff3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## mm/dd/2019 1. [](#new) - * Added Flex Pages classes + * Added Flex Pages to Grav core and removed Flex Objects plugin dependency 1. [](#bugfix) * Fixed `Page::untranslatedLanguages()` not being symmetrical to `Page::translatedLanguages()` * Fixed `Flex Pages` not calling `onPageProcessed` event when cached diff --git a/system/blueprints/flex/pages.yaml b/system/blueprints/flex/pages.yaml new file mode 100644 index 000000000..3084281e9 --- /dev/null +++ b/system/blueprints/flex/pages.yaml @@ -0,0 +1,123 @@ +title: Flex Pages +description: Manage your Grav Pages in Flex. +type: flex-objects + +extends@: + type: default + context: blueprints://pages + +config: + admin: + menu: + list: + route: '/pages' + title: PLUGIN_ADMIN.PAGES + icon: fa-file-text + authorize: ['admin.pages', 'admin.super'] + priority: 5 + + template: grav-pages + + list: + fields: + published: + width: 8 + alias: header.published + visible: + width: 8 + field: + label: Visible + type: toggle + menu: + link: edit + alias: header.menu + full_route: + field: + label: Route + type: text + link: edit + sort: + field: key + name: + width: 8 + field: + label: Type + type: text + translations: + width: 8 + field: + label: Translations + type: text +# updated_date: +# alias: header.update_date + + options: + per_page: 20 + order: + by: key + dir: asc + + # TODO: not used yet + buttons: + back: + icon: reply + title: PLUGIN_ADMIN.BACK + add: + icon: plus + label: PLUGIN_ADMIN.ADD + + edit: + # TODO: not used yet + buttons: + back: + icon: reply + title: PLUGIN_ADMIN.BACK + preview: + icon: eye + title: PLUGIN_ADMIN.PREVIEW + add: + icon: plus + label: PLUGIN_ADMIN.ADD + copy: + icon: copy + label: PLUGIN_ADMIN.COPY + move: + icon: arrows + label: PLUGIN_ADMIN.MOVE + delete: + icon: close + label: PLUGIN_ADMIN.DELETE + save: + icon: check + label: PLUGIN_ADMIN.SAVE + + site: + filter: + - withPublished + + data: + object: 'Grav\Common\Page\Flex\PageObject' + collection: 'Grav\Common\Page\Flex\PageCollection' + index: 'Grav\Common\Page\Flex\PageIndex' + storage: + class: 'Grav\Common\Page\Flex\PageStorage' + options: + formatter: + class: 'Grav\Framework\File\Formatter\MarkdownFormatter' + folder: 'page://' + ordering: + key: ASC + search: + options: + contains: 1 + fields: + - key + - menu + - title + - name + +form: + fields: + lang: + type: hidden + value: '' diff --git a/system/src/Grav/Common/Page/Pages.php b/system/src/Grav/Common/Page/Pages.php index c7d22249b..cb358c4cf 100644 --- a/system/src/Grav/Common/Page/Pages.php +++ b/system/src/Grav/Common/Page/Pages.php @@ -27,6 +27,7 @@ use Grav\Framework\Flex\FlexDirectory; use Grav\Framework\Flex\Interfaces\FlexObjectInterface; use Grav\Plugin\Admin; use RocketTheme\Toolbox\Event\Event; +use RocketTheme\Toolbox\Event\EventDispatcher; use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator; use Whoops\Exception\ErrorException; use Collator; @@ -36,8 +37,8 @@ class Pages /** @var Grav */ protected $grav; - /** @var Flex */ - protected $flex; + /** @var FlexDirectory */ + private $directory; /** @var array|PageInterface[] */ protected $instances; @@ -92,11 +93,16 @@ class Pages /** * Constructor * - * @param Grav $c + * @param Grav $grav */ - public function __construct(Grav $c) + public function __construct(Grav $grav) { - $this->grav = $c; + $this->grav = $grav; + + $type = $grav['config']->get('system.pages.type'); + if ($type === 'flex') { + $this->initFlexPages(); + } } /** @@ -253,9 +259,6 @@ class Pages $this->ignore_files = $config->get('system.pages.ignore_files'); $this->ignore_folders = $config->get('system.pages.ignore_folders'); $this->ignore_hidden = $config->get('system.pages.ignore_hidden'); - if ($config->get('system.pages.type') === 'flex') { - $this->flex = $this->grav['flex_objects'] ?? null; - } $this->instances = []; $this->children = []; @@ -291,14 +294,14 @@ class Pages */ public function instances() { - if (!$this->flex) { + if (!$this->directory) { return $this->instances; } $list = []; foreach ($this->instances as $path => $instance) { if (!$instance instanceof PageInterface) { - $instance = $this->flex->getObject($instance); + $instance = $this->directory->getObject($instance, 'flex_key'); } $list[$path] = $instance; } @@ -701,7 +704,7 @@ class Pages { $instance = $this->instances[(string)$path] ?? null; if (\is_string($instance)) { - $instance = $this->flex ? $this->flex->getObject($instance) : null; + $instance = $this->directory ? $this->directory->getObject($instance, 'flex_key') : null; if (method_exists($instance, 'initialize') && $this->grav['config']->get('system.pages.events.page')) { $instance->initialize(); } @@ -1169,7 +1172,7 @@ class Pages { $accessLevels = []; foreach ($this->all() as $page) { - if (isset($page->header()->access)) { + if (isset($page, $page->header()->access)) { if (\is_array($page->header()->access)) { foreach ($page->header()->access as $index => $accessLevel) { if (\is_array($accessLevel)) { @@ -1201,8 +1204,6 @@ class Pages return self::getParents($rawRoutes); } - - /** * Gets the home route * @@ -1255,6 +1256,60 @@ class Pages return self::getHomeRoute(); } + protected function initFlexPages(): void + { + /** @var Debugger $debugger */ + $debugger = $this->grav['debugger']; + $debugger->addMessage('Pages: Flex Directory'); + + /** @var Config $config */ + $config = $this->grav['config']; + + $options = [ + 'enabled' => true, + ] + ($config->get('plugins.flex-objects.object') ?: []); + + $directory = new FlexDirectory('pages', 'blueprints://flex/pages.yaml', $options); + + /** @var EventDispatcher $dispatcher */ + $dispatcher = $this->grav['events']; + $dispatcher->addListener( + 'onFlexInit', + static function (Event $event) use ($directory) + { + /** @var Flex $flex */ + $flex = $event['flex']; + $flex->addDirectory($directory); + } + ); + + // Stop /admin/pages from working, display error instead. + $dispatcher->addListener( + 'onAdminPage', + static function (Event $event) use ($directory) { + $grav = Grav::instance(); + [,$location,] = $grav['admin']->getRouteDetails(); + if ($location !== 'pages') { + return; + } + + $event->stopPropagation(); + + /** @var PageInterface $page */ + $page = $event['page']; + $page->init(new \SplFileInfo('plugin://admin/pages/admin/error.md')); + $page->routable(true); + $page->content('## Please install **Flex Objects** plugin. It is required to edit **Flex Pages**.'); + + $header = $page->header(); + $menu = $directory->getConfig('admin.menu.list'); + $header->access = $menu['authorize'] ?? ['admin.pages', 'admin.super']; + }, + 100000); + + $this->directory = $directory; + } + /** * Builds pages. * @@ -1273,21 +1328,21 @@ class Pages $debugger = $this->grav['debugger']; $debugger->startTimer('build-pages', 'Init frontend routes'); - $directory = $this->flex ? $this->flex->getDirectory('grav-pages') : null; - - if ($directory) { - $this->buildFlexPages($directory); + if ($this->directory) { + $this->buildFlexPages(); } else { $this->buildRegularPages(); } $debugger->stopTimer('build-pages'); } - protected function buildFlexPages(FlexDirectory $directory) + protected function buildFlexPages() { /** @var Config $config */ $config = $this->grav['config']; + $directory = $this->directory; + // TODO: right now we are just emulating normal pages, it is inefficient and bad... but works! $collection = $directory->getIndex(); $cache = $directory->getCache('index'); @@ -1874,7 +1929,7 @@ class Pages protected function getVersion() { - return $this->flex ? 'flex' : 'page'; + return $this->directory ? 'flex' : 'page'; } /** diff --git a/system/src/Grav/Common/Processors/PluginsProcessor.php b/system/src/Grav/Common/Processors/PluginsProcessor.php index 52ee4ea1c..b6c0c39f1 100644 --- a/system/src/Grav/Common/Processors/PluginsProcessor.php +++ b/system/src/Grav/Common/Processors/PluginsProcessor.php @@ -23,6 +23,8 @@ class PluginsProcessor extends ProcessorBase $this->startTimer(); // TODO: remove in 2.0. $this->container['accounts']; + // TODO: remove in 2.0. + $this->container['pages']; $this->container['plugins']->init(); $this->container->fireEvent('onPluginsInitialized'); $this->stopTimer(); diff --git a/system/src/Grav/Common/Service/PagesServiceProvider.php b/system/src/Grav/Common/Service/PagesServiceProvider.php index 0a37e831d..d41c97617 100644 --- a/system/src/Grav/Common/Service/PagesServiceProvider.php +++ b/system/src/Grav/Common/Service/PagesServiceProvider.php @@ -22,21 +22,19 @@ class PagesServiceProvider implements ServiceProviderInterface { public function register(Container $container) { - $container['pages'] = function ($c) { - return new Pages($c); + $container['pages'] = function (Grav $grav) { + return new Pages($grav); }; - $container['page'] = function ($c) { - /** @var Grav $c */ - + $container['page'] = static function (Grav $grav) { /** @var Pages $pages */ - $pages = $c['pages']; + $pages = $grav['pages']; /** @var Config $config */ - $config = $c['config']; + $config = $grav['config']; /** @var Uri $uri */ - $uri = $c['uri']; + $uri = $grav['uri']; $path = $uri->path() ?: '/'; // Don't trim to support trailing slash default routes $page = $pages->dispatch($path); @@ -45,13 +43,13 @@ class PagesServiceProvider implements ServiceProviderInterface if ($page) { // some debugger override logic if ($page->debugger() === false) { - $c['debugger']->enabled(false); + $grav['debugger']->enabled(false); } if ($config->get('system.force_ssl')) { if (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] !== 'on') { $url = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; - $c->redirect($url); + $grav->redirect($url); } } @@ -72,15 +70,15 @@ class PagesServiceProvider implements ServiceProviderInterface } /** @var Language $language */ - $language = $c['language']; + $language = $grav['language']; // Language-specific redirection scenarios if ($language->enabled() && ($language->isLanguageInUrl() xor $language->isIncludeDefaultLanguage())) { - $c->redirect($url); + $grav->redirect($url); } // Default route test and redirect if ($config->get('system.pages.redirect_default_route') && $page->route() !== $path) { - $c->redirect($url); + $grav->redirect($url); } } @@ -88,10 +86,10 @@ class PagesServiceProvider implements ServiceProviderInterface if (!$page || !$page->routable()) { // Try fallback URL stuff... - $page = $c->fallbackUrl($path); + $page = $grav->fallbackUrl($path); if (!$page) { - $path = $c['locator']->findResource('system://pages/notfound.md'); + $path = $grav['locator']->findResource('system://pages/notfound.md'); $page = new Page(); $page->init(new \SplFileInfo($path)); $page->routable(false);