Chris@0: blockRepository = $block_repository; Chris@0: $this->blockViewBuilder = $block_view_builder; Chris@0: $this->blockListCacheTags = $block_list_cache_tags; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { Chris@0: return new static( Chris@0: $configuration, Chris@0: $plugin_id, Chris@0: $plugin_definition, Chris@0: $container->get('block.repository'), Chris@0: $container->get('entity.manager')->getViewBuilder('block'), Chris@0: $container->get('entity.manager')->getDefinition('block')->getListCacheTags() Chris@0: ); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function setMainContent(array $main_content) { Chris@0: $this->mainContent = $main_content; Chris@0: return $this; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function setTitle($title) { Chris@0: $this->title = $title; Chris@0: return $this; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function build() { Chris@0: // Track whether blocks showing the main content and messages are displayed. Chris@0: $main_content_block_displayed = FALSE; Chris@0: $messages_block_displayed = FALSE; Chris@0: Chris@0: $build = [ Chris@0: '#cache' => [ Chris@0: 'tags' => $this->blockListCacheTags, Chris@0: ], Chris@0: ]; Chris@0: // Load all region content assigned via blocks. Chris@0: $cacheable_metadata_list = []; Chris@0: foreach ($this->blockRepository->getVisibleBlocksPerRegion($cacheable_metadata_list) as $region => $blocks) { Chris@0: /** @var $blocks \Drupal\block\BlockInterface[] */ Chris@0: foreach ($blocks as $key => $block) { Chris@0: $block_plugin = $block->getPlugin(); Chris@0: if ($block_plugin instanceof MainContentBlockPluginInterface) { Chris@0: $block_plugin->setMainContent($this->mainContent); Chris@0: $main_content_block_displayed = TRUE; Chris@0: } Chris@0: elseif ($block_plugin instanceof TitleBlockPluginInterface) { Chris@0: $block_plugin->setTitle($this->title); Chris@0: } Chris@0: elseif ($block_plugin instanceof MessagesBlockPluginInterface) { Chris@0: $messages_block_displayed = TRUE; Chris@0: } Chris@0: $build[$region][$key] = $this->blockViewBuilder->view($block); Chris@0: Chris@0: // The main content block cannot be cached: it is a placeholder for the Chris@0: // render array returned by the controller. It should be rendered as-is, Chris@0: // with other placed blocks "decorating" it. Analogous reasoning for the Chris@0: // title block. Chris@0: if ($block_plugin instanceof MainContentBlockPluginInterface || $block_plugin instanceof TitleBlockPluginInterface) { Chris@0: unset($build[$region][$key]['#cache']['keys']); Chris@0: } Chris@0: } Chris@0: if (!empty($build[$region])) { Chris@0: // \Drupal\block\BlockRepositoryInterface::getVisibleBlocksPerRegion() Chris@0: // returns the blocks in sorted order. Chris@0: $build[$region]['#sorted'] = TRUE; Chris@0: } Chris@0: } Chris@0: Chris@0: // If no block that shows the main content is displayed, still show the main Chris@0: // content. Otherwise the end user will see all displayed blocks, but not Chris@0: // the main content they came for. Chris@0: if (!$main_content_block_displayed) { Chris@0: $build['content']['system_main'] = $this->mainContent; Chris@0: } Chris@0: Chris@0: // If no block displays status messages, still render them. Chris@0: if (!$messages_block_displayed) { Chris@0: $build['content']['messages'] = [ Chris@0: '#weight' => -1000, Chris@0: '#type' => 'status_messages', Chris@0: ]; Chris@0: } Chris@0: Chris@0: // If any render arrays are manually placed, render arrays and blocks must Chris@0: // be sorted. Chris@0: if (!$main_content_block_displayed || !$messages_block_displayed) { Chris@0: unset($build['content']['#sorted']); Chris@0: } Chris@0: Chris@0: // The access results' cacheability is currently added to the top level of the Chris@0: // render array. This is done to prevent issues with empty regions being Chris@0: // displayed. Chris@0: // This would need to be changed to allow caching of block regions, as each Chris@0: // region must then have the relevant cacheable metadata. Chris@0: $merged_cacheable_metadata = CacheableMetadata::createFromRenderArray($build); Chris@0: foreach ($cacheable_metadata_list as $cacheable_metadata) { Chris@0: $merged_cacheable_metadata = $merged_cacheable_metadata->merge($cacheable_metadata); Chris@0: } Chris@0: $merged_cacheable_metadata->applyTo($build); Chris@0: Chris@0: return $build; Chris@0: } Chris@0: Chris@0: }