core/core.services.yml | 2 +- .../Core/Display/Annotation/DisplayVariant.php | 2 +- .../EventSubscriber/MainContentViewSubscriber.php | 9 ++---- .../Drupal/Core/Render/BareHtmlPageRenderer.php | 4 ++- .../Core/Render/BareHtmlPageRendererInterface.php | 14 +++++--- .../Core/Render/MainContent/DialogRenderer.php | 2 +- .../Core/Render/MainContent/HtmlRenderer.php | 37 +++++++++++++++------- .../MainContent/MainContentRenderersPass.php | 2 +- .../Render}/PageDisplayVariantSelectionEvent.php | 30 +++++++++++++++--- .../Plugin/DisplayVariant/SimplePageVariant.php | 4 +-- .../Drupal/Core/Render/RenderEvents.php} | 13 ++++---- core/modules/block/block.services.yml | 1 - .../BlockPageDisplayVariantSubscriber.php | 28 +++------------- .../system/src/Tests/Common/PageRenderTest.php | 8 +++-- core/modules/system/theme.api.php | 4 +-- 15 files changed, 92 insertions(+), 68 deletions(-) diff --git a/core/core.services.yml b/core/core.services.yml index 52050cd..57f3cc3 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -659,7 +659,7 @@ services: - { name: event_subscriber } main_content_renderer.html: class: Drupal\Core\Render\MainContent\HtmlRenderer - arguments: ['@title_resolver', '@plugin.manager.display_variant', '@event_dispatcher'] + arguments: ['@title_resolver', '@plugin.manager.display_variant', '@event_dispatcher', '@module_handler'] tags: - { name: render.main_content_renderer, format: html } main_content_renderer.ajax: diff --git a/core/lib/Drupal/Core/Display/Annotation/DisplayVariant.php b/core/lib/Drupal/Core/Display/Annotation/DisplayVariant.php index df1b52a..53d58e3 100644 --- a/core/lib/Drupal/Core/Display/Annotation/DisplayVariant.php +++ b/core/lib/Drupal/Core/Display/Annotation/DisplayVariant.php @@ -26,7 +26,7 @@ * Plugin namespace: Plugin\DisplayVariant * * For working examples, see - * - \Drupal\system\Plugin\DisplayVariant\SimplePageVariant + * - \Drupal\Core\Render\Plugin\DisplayVariant\SimplePageVariant * - \Drupal\block\Plugin\DisplayVariant\BlockPageVariant * - \Drupal\block\Plugin\DisplayVariant\DemoBlockPageVariant * diff --git a/core/lib/Drupal/Core/EventSubscriber/MainContentViewSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/MainContentViewSubscriber.php index 0c386bf..75c3028 100644 --- a/core/lib/Drupal/Core/EventSubscriber/MainContentViewSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/MainContentViewSubscriber.php @@ -57,7 +57,7 @@ class MainContentViewSubscriber implements EventSubscriberInterface { * @param \Drupal\Core\Routing\RouteMatchInterface $route_match * The current route match. * @param array $main_content_renderers - * The available main content renderer services, keyed per format. + * The available main content renderer service IDs, keyed by format. */ public function __construct(ClassResolverInterface $class_resolver, RouteMatchInterface $route_match, array $main_content_renderers) { $this->classResolver = $class_resolver; @@ -95,13 +95,10 @@ public function onViewRenderArray(GetResponseForControllerResultEvent $event) { } /** - * Registers the methods in this class that should be listeners. - * - * @return array - * An array of event listener definitions. + * {@inheritdoc} */ static function getSubscribedEvents() { - $events[KernelEvents::VIEW][] = array('onViewRenderArray', 30); + $events[KernelEvents::VIEW][] = ['onViewRenderArray']; return $events; } diff --git a/core/lib/Drupal/Core/Render/BareHtmlPageRenderer.php b/core/lib/Drupal/Core/Render/BareHtmlPageRenderer.php index cd5adaa..a8904e6 100644 --- a/core/lib/Drupal/Core/Render/BareHtmlPageRenderer.php +++ b/core/lib/Drupal/Core/Render/BareHtmlPageRenderer.php @@ -70,7 +70,9 @@ protected function renderBarePage(array $content, $title, array $page_additions, ]; // We must first render the contents of the html.html.twig template, see - // \Drupal\Core\Render\MainContent\HtmlRenderer::renderPage() for details. + // \Drupal\Core\Render\MainContent\HtmlRenderer::renderResponse() for more + // information about this; the exact same pattern is used there and + // explained in detail there. drupal_render_root($html['page']); return drupal_render($html); } diff --git a/core/lib/Drupal/Core/Render/BareHtmlPageRendererInterface.php b/core/lib/Drupal/Core/Render/BareHtmlPageRendererInterface.php index 4bba7c8..7450199 100644 --- a/core/lib/Drupal/Core/Render/BareHtmlPageRendererInterface.php +++ b/core/lib/Drupal/Core/Render/BareHtmlPageRendererInterface.php @@ -25,16 +25,22 @@ * - exception handlers * * i.e. use this when rendering HTML pages in limited environments. Otherwise, - * use a @code _content @endcode route, thiswill cause a main content controller - * (\Drupal\Core\ControllerMainContentControllerInterface) to be used, and in - * case of a HTML request that will be + * use a @code _content @endcode route, this will cause a main content renderer + * (\Drupal\Core\Render\MainContent\MainContentRendererInterface) to be used, + * and in case of a HTML request that will be * \Drupal\Core\Render\MainContent\HtmlRenderer. * + * In fact, this is not only *typically* used in a limited environment, it even + * *must* be used in a limited environment: when using the bare HTML page + * renderer, use as little state/additional services as possible, because the + * same safeguards aren't present (precisely because this is intended to be used + * in a limited environment). + * * Currently, there are two types of bare pages available: * 1. install (hook_preprocess_install_page(), install-page.html.twig) * 2. maintenance (hook_preprocess_maintenance_page(), maintenance-page.html.twig) * - * @see \Drupal\Core\Controller\HtmlController + * @see \Drupal\Core\Render\MainContent\HtmlRenderer */ interface BareHtmlPageRendererInterface { diff --git a/core/lib/Drupal/Core/Render/MainContent/DialogRenderer.php b/core/lib/Drupal/Core/Render/MainContent/DialogRenderer.php index 24462cb..adb550a 100644 --- a/core/lib/Drupal/Core/Render/MainContent/DialogRenderer.php +++ b/core/lib/Drupal/Core/Render/MainContent/DialogRenderer.php @@ -21,7 +21,7 @@ class DialogRenderer { /** * The title resolver. * - * @var \Drupal\Core\Controller\TitleResolver + * @var \Drupal\Core\Controller\TitleResolverInterface */ protected $titleResolver; diff --git a/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php b/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php index 47e33bb..3783c5d 100644 --- a/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php +++ b/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php @@ -12,9 +12,10 @@ use Drupal\Core\Cache\Cache; use Drupal\Core\Controller\TitleResolverInterface; use Drupal\Core\Display\PageVariantInterface; +use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Render\PageDisplayVariantSelectionEvent; +use Drupal\Core\Render\RenderEvents; use Drupal\Core\Routing\RouteMatchInterface; -use Drupal\system\Event\PageDisplayVariantSelectionEvent; -use Drupal\system\Event\SystemEvents; use Symfony\Component\DependencyInjection\ContainerAwareTrait; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Request; @@ -47,6 +48,13 @@ class HtmlRenderer { protected $eventDispatcher; /** + * The module handler. + * + * @var \Drupal\Core\Extension\ModuleHandlerInterface + */ + protected $moduleHandler; + + /** * Constructs a new HtmlRenderer. * * @param \Drupal\Core\Controller\TitleResolverInterface $title_resolver @@ -55,11 +63,14 @@ class HtmlRenderer { * The display variant manager. * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher * The event dispatcher. + * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler + * The module handler. */ - public function __construct(TitleResolverInterface $title_resolver, PluginManagerInterface $display_variant_manager, EventDispatcherInterface $event_dispatcher) { + public function __construct(TitleResolverInterface $title_resolver, PluginManagerInterface $display_variant_manager, EventDispatcherInterface $event_dispatcher, ModuleHandlerInterface $module_handler) { $this->titleResolver = $title_resolver; $this->displayVariantManager = $display_variant_manager; $this->eventDispatcher = $event_dispatcher; + $this->moduleHandler = $module_handler; } /** @@ -91,8 +102,8 @@ protected function prepare(array $main_content, Request $request, RouteMatchInte else { // Select the page display variant to be used to render this main content, // default to the built-in "simple page". - $event = new PageDisplayVariantSelectionEvent('simple_page'); - $this->eventDispatcher->dispatch(SystemEvents::SELECT_PAGE_DISPLAY_VARIANT, $event); + $event = new PageDisplayVariantSelectionEvent('simple_page', $route_match); + $this->eventDispatcher->dispatch(RenderEvents::SELECT_PAGE_DISPLAY_VARIANT, $event); $variant_id = $event->getPluginId(); // We must render the main content now already, because it might provide a @@ -219,13 +230,15 @@ public function renderResponse(array $main_content, Request $request, RouteMatch * * @throws \LogicException * + * @internal + * * @see hook_page_attachments() * @see hook_page_attachments_alter() */ - public static function invokePageAttachmentHooks(array &$page) { + public function invokePageAttachmentHooks(array &$page) { // Modules can add attachments. $attachments = []; - foreach (\Drupal::moduleHandler()->getImplementations('page_attachments') as $module) { + foreach ($this->moduleHandler->getImplementations('page_attachments') as $module) { $function = $module . '_page_attachments'; $function($attachments); } @@ -234,7 +247,7 @@ public static function invokePageAttachmentHooks(array &$page) { } // Modules and themes can alter page attachments. - \Drupal::moduleHandler()->alter('page_attachments', $attachments); + $this->moduleHandler->alter('page_attachments', $attachments); \Drupal::theme()->alter('page_attachments', $attachments); if (array_diff(array_keys($attachments), ['#attached', '#post_render_cache']) !== []) { throw new \LogicException('Only #attached and #post_render_cache may be set in hook_page_attachments_alter().'); @@ -257,19 +270,21 @@ public static function invokePageAttachmentHooks(array &$page) { * * @throws \LogicException * + * @internal + * * @see hook_page_top() * @see hook_page_bottom() * @see html.html.twig */ - public static function buildPageTopAndBottom(array &$html) { + public function buildPageTopAndBottom(array &$html) { // Modules can add render arrays to the top and bottom of the page. $page_top = []; $page_bottom = []; - foreach (\Drupal::moduleHandler()->getImplementations('page_top') as $module) { + foreach ($this->moduleHandler->getImplementations('page_top') as $module) { $function = $module . '_page_top'; $function($page_top); } - foreach (\Drupal::moduleHandler()->getImplementations('page_bottom') as $module) { + foreach ($this->moduleHandler->getImplementations('page_bottom') as $module) { $function = $module . '_page_bottom'; $function($page_bottom); } diff --git a/core/lib/Drupal/Core/Render/MainContent/MainContentRenderersPass.php b/core/lib/Drupal/Core/Render/MainContent/MainContentRenderersPass.php index dbb72be..08b4665 100644 --- a/core/lib/Drupal/Core/Render/MainContent/MainContentRenderersPass.php +++ b/core/lib/Drupal/Core/Render/MainContent/MainContentRenderersPass.php @@ -18,7 +18,7 @@ class MainContentRenderersPass implements CompilerPassInterface { /** * {@inheritdoc} * - * Collects the available main content renderer services into the + * Collects the available main content renderer service IDs into the * main_content_renderers parameter, keyed by format. */ public function process(ContainerBuilder $container) { diff --git a/core/modules/system/src/Event/PageDisplayVariantSelectionEvent.php b/core/lib/Drupal/Core/Render/PageDisplayVariantSelectionEvent.php similarity index 52% rename from core/modules/system/src/Event/PageDisplayVariantSelectionEvent.php rename to core/lib/Drupal/Core/Render/PageDisplayVariantSelectionEvent.php index 9177a18..17771bd 100644 --- a/core/modules/system/src/Event/PageDisplayVariantSelectionEvent.php +++ b/core/lib/Drupal/Core/Render/PageDisplayVariantSelectionEvent.php @@ -2,17 +2,19 @@ /** * @file - * Contains \Drupal\system\Event\PageDisplayVariantSelectionEvent. + * Contains \Drupal\Core\Render\PageDisplayVariantSelectionEvent. */ -namespace Drupal\system\Event; +namespace Drupal\Core\Render; +use Drupal\Core\Routing\RouteMatchInterface; use Symfony\Component\EventDispatcher\Event; /** * Event fired when rendering main content, to select a page display variant. * - * @see \Drupal\system\Event\SystemEvents::SELECT_PAGE_DISPLAY_VARIANT + * @see \Drupal\Core\Render\RenderEvents::SELECT_PAGE_DISPLAY_VARIANT + * @see \Drupal\Core\Render\MainContent\HtmlRenderer */ class PageDisplayVariantSelectionEvent extends Event { @@ -24,13 +26,23 @@ class PageDisplayVariantSelectionEvent extends Event { protected $pluginId; /** + * The current route match. + * + * @var \Drupal\Core\Routing\RouteMatchInterface + */ + protected $routeMatch; + + /** * Constructs the page display variant plugin selection event. * * @param string * The ID of the page display variant plugin to use by default. + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * The current route match, for context. */ - public function __construct($plugin_id) { + public function __construct($plugin_id, RouteMatchInterface $route_match) { $this->pluginId = $plugin_id; + $this->routeMatch = $route_match; } /** @@ -52,4 +64,14 @@ public function getPluginId() { return $this->pluginId; } + /** + * Gets the current route match. + * + * @return \Drupal\Core\Routing\RouteMatchInterface + * The current route match, for context. + */ + public function getRouteMatch() { + return $this->routeMatch; + } + } diff --git a/core/modules/system/src/Plugin/DisplayVariant/SimplePageVariant.php b/core/lib/Drupal/Core/Render/Plugin/DisplayVariant/SimplePageVariant.php similarity index 85% rename from core/modules/system/src/Plugin/DisplayVariant/SimplePageVariant.php rename to core/lib/Drupal/Core/Render/Plugin/DisplayVariant/SimplePageVariant.php index afe298a..7772875 100644 --- a/core/modules/system/src/Plugin/DisplayVariant/SimplePageVariant.php +++ b/core/lib/Drupal/Core/Render/Plugin/DisplayVariant/SimplePageVariant.php @@ -2,10 +2,10 @@ /** * @file - * Contains \Drupal\system\Plugin\DisplayVariant\SimplePageVariant. + * Contains \Drupal\Core\Render\Plugin\DisplayVariant\SimplePageVariant. */ -namespace Drupal\system\Plugin\DisplayVariant; +namespace Drupal\Core\Render\Plugin\DisplayVariant; use Drupal\Core\Display\PageVariantInterface; use Drupal\Core\Display\VariantBase; diff --git a/core/modules/system/src/Event/SystemEvents.php b/core/lib/Drupal/Core/Render/RenderEvents.php similarity index 26% rename from core/modules/system/src/Event/SystemEvents.php rename to core/lib/Drupal/Core/Render/RenderEvents.php index a99eb59..8b0fa55 100644 --- a/core/modules/system/src/Event/SystemEvents.php +++ b/core/lib/Drupal/Core/Render/RenderEvents.php @@ -2,22 +2,21 @@ /** * @file - * Contains \Drupal\system\Event\SystemEvents. + * Contains \Drupal\Core\Render\RenderEvents. */ -namespace Drupal\system\Event; +namespace Drupal\Core\Render; /** - * Defines events for the base system. + * Defines events for the render system. */ -final class SystemEvents { +final class RenderEvents { /** * Name of the event when selecting a page display variant to use. * - * @see \Drupal\Core\Block\BlockBase::getConditionContexts() - * @see \Drupal\system\Event\PageDisplayVariantSelectionEvent + * @see \Drupal\Core\Render\PageDisplayVariantSelectionEvent */ - const SELECT_PAGE_DISPLAY_VARIANT= 'system.page_display_variant.select'; + const SELECT_PAGE_DISPLAY_VARIANT = 'render.page_display_variant.select'; } diff --git a/core/modules/block/block.services.yml b/core/modules/block/block.services.yml index 9c7be32..601ff51 100644 --- a/core/modules/block/block.services.yml +++ b/core/modules/block/block.services.yml @@ -5,7 +5,6 @@ services: - { name: theme_negotiator, priority: 1000 } block.page_display_variant_subscriber: class: Drupal\block\EventSubscriber\BlockPageDisplayVariantSubscriber - arguments: ['@current_route_match'] tags: - { name: event_subscriber } block.current_user_context: diff --git a/core/modules/block/src/EventSubscriber/BlockPageDisplayVariantSubscriber.php b/core/modules/block/src/EventSubscriber/BlockPageDisplayVariantSubscriber.php index b6127fb..1a13d26 100644 --- a/core/modules/block/src/EventSubscriber/BlockPageDisplayVariantSubscriber.php +++ b/core/modules/block/src/EventSubscriber/BlockPageDisplayVariantSubscriber.php @@ -7,10 +7,9 @@ namespace Drupal\block\EventSubscriber; -use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; -use Drupal\system\Event\PageDisplayVariantSelectionEvent; -use Drupal\system\Event\SystemEvents; +use Drupal\Core\Render\PageDisplayVariantSelectionEvent; +use Drupal\Core\Render\RenderEvents; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** @@ -22,30 +21,13 @@ class BlockPageDisplayVariantSubscriber implements EventSubscriberInterface { /** - * The current route match. - * - * @var \Drupal\Core\Routing\RouteMatchInterface - */ - protected $routeMatch; - - /** - * Constructs a BlockPageDisplayVariantSubscriber object. - * - * @param \Drupal\Core\Routing\RouteMatchInterface $route_match - * The current route match. - */ - public function __construct(RouteMatchInterface $route_match) { - $this->routeMatch = $route_match; - } - - /** * Selects the block page display variant. * - * @param \Drupal\system\Event\PageDisplayVariantSelectionEvent $event + * @param \Drupal\Core\Render\PageDisplayVariantSelectionEvent $event * The event to process. */ public function onSelectPageDisplayVariant(PageDisplayVariantSelectionEvent $event) { - if ($this->routeMatch->getRouteName() != 'block.admin_demo') { + if ($event->getRouteMatch()->getRouteName() != 'block.admin_demo') { $event->setPluginId('block_page'); } else { @@ -57,7 +39,7 @@ public function onSelectPageDisplayVariant(PageDisplayVariantSelectionEvent $eve * {@inheritdoc} */ static function getSubscribedEvents() { - $events[SystemEvents::SELECT_PAGE_DISPLAY_VARIANT][] = array('onSelectPageDisplayVariant'); + $events[RenderEvents::SELECT_PAGE_DISPLAY_VARIANT][] = array('onSelectPageDisplayVariant'); return $events; } diff --git a/core/modules/system/src/Tests/Common/PageRenderTest.php b/core/modules/system/src/Tests/Common/PageRenderTest.php index ad8a087..e660448 100644 --- a/core/modules/system/src/Tests/Common/PageRenderTest.php +++ b/core/modules/system/src/Tests/Common/PageRenderTest.php @@ -60,16 +60,18 @@ function testHookPageAttachmentsAlter() { * The page render hook to assert expected exceptions for. */ function assertPageRenderHookExceptions($module, $hook) { + $html_renderer = \Drupal::getContainer()->get('main_content_renderer.html'); + // Assert a valid hook implementation doesn't trigger an exception. $page = []; - HtmlRenderer::invokePageAttachmentHooks($page); + $html_renderer->invokePageAttachmentHooks($page); // Assert an invalid hook implementation doesn't trigger an exception. \Drupal::state()->set($module . '.' . $hook . '.descendant_attached', TRUE); $assertion = $hook . '() implementation that sets #attached on a descendant triggers an exception'; $page = []; try { - HtmlRenderer::invokePageAttachmentHooks($page); + $html_renderer->invokePageAttachmentHooks($page); $this->error($assertion); } catch (\LogicException $e) { @@ -83,7 +85,7 @@ function assertPageRenderHookExceptions($module, $hook) { $assertion = $hook . '() implementation that sets a child render array triggers an exception'; $page = []; try { - HtmlRenderer::invokePageAttachmentHooks($page); + $html_renderer->invokePageAttachmentHooks($page); $this->error($assertion); } catch (\LogicException $e) { diff --git a/core/modules/system/theme.api.php b/core/modules/system/theme.api.php index 37b769e..b7fe983 100644 --- a/core/modules/system/theme.api.php +++ b/core/modules/system/theme.api.php @@ -352,9 +352,9 @@ * 1. \Drupal\Core\Render\MainContent\HtmlRenderer::prepare() takes the main * content render array; if it already is #type 'page', then most of the work * it must do is already done. In the other case, we need to build that #type - * 'page' render array still. The SystemEvents::SELECT_PAGE_DISPLAY_VARIANT + * 'page' render array still. The RenderEvents::SELECT_PAGE_DISPLAY_VARIANT * event is dispatched, to select a page display variant. By default, - * \Drupal\system\Plugin\DisplayVariant\SimplePageVariant is used, which + * \Drupal\Core\Render\Plugin\DisplayVariant\SimplePageVariant is used, which * doesn't apply any decorations. But, when Block module is enabled, * \Drupal\block\Plugin\DisplayVariant\BlockPageVariant is used, which allows * the site builder to place blocks in any of the page regions, and hence