You are here

public function BlockPageVariant::build in Zircon Profile 8

Same name and namespace in other branches
  1. 8.0 core/modules/block/src/Plugin/DisplayVariant/BlockPageVariant.php \Drupal\block\Plugin\DisplayVariant\BlockPageVariant::build()

Builds and returns the renderable array for the display variant.

The variant can contain cacheability metadata for the configuration that was passed in setConfiguration(). In the build() method, this should be added to the render array that is returned.

Return value

array A render array for the display variant.

Overrides VariantInterface::build

File

core/modules/block/src/Plugin/DisplayVariant/BlockPageVariant.php, line 130
Contains \Drupal\block\Plugin\DisplayVariant\BlockPageVariant.

Class

BlockPageVariant
Provides a page display variant that decorates the main content with blocks.

Namespace

Drupal\block\Plugin\DisplayVariant

Code

public function build() {

  // Track whether blocks showing the main content and messages are displayed.
  $main_content_block_displayed = FALSE;
  $messages_block_displayed = FALSE;
  $build = [
    '#cache' => [
      'tags' => $this->blockListCacheTags,
    ],
  ];

  // Load all region content assigned via blocks.
  $cacheable_metadata_list = [];
  foreach ($this->blockRepository
    ->getVisibleBlocksPerRegion($cacheable_metadata_list) as $region => $blocks) {

    /** @var $blocks \Drupal\block\BlockInterface[] */
    foreach ($blocks as $key => $block) {
      $block_plugin = $block
        ->getPlugin();
      if ($block_plugin instanceof MainContentBlockPluginInterface) {
        $block_plugin
          ->setMainContent($this->mainContent);
        $main_content_block_displayed = TRUE;
      }
      elseif ($block_plugin instanceof TitleBlockPluginInterface) {
        $block_plugin
          ->setTitle($this->title);
      }
      elseif ($block_plugin instanceof MessagesBlockPluginInterface) {
        $messages_block_displayed = TRUE;
      }
      $build[$region][$key] = $this->blockViewBuilder
        ->view($block);

      // The main content block cannot be cached: it is a placeholder for the
      // render array returned by the controller. It should be rendered as-is,
      // with other placed blocks "decorating" it. Analogous reasoning for the
      // title block.
      if ($block_plugin instanceof MainContentBlockPluginInterface || $block_plugin instanceof TitleBlockPluginInterface) {
        unset($build[$region][$key]['#cache']['keys']);
      }
    }
    if (!empty($build[$region])) {

      // \Drupal\block\BlockRepositoryInterface::getVisibleBlocksPerRegion()
      // returns the blocks in sorted order.
      $build[$region]['#sorted'] = TRUE;
    }
  }

  // If no block that shows the main content is displayed, still show the main
  // content. Otherwise the end user will see all displayed blocks, but not
  // the main content they came for.
  if (!$main_content_block_displayed) {
    $build['content']['system_main'] = $this->mainContent;
  }

  // If no block displays status messages, still render them.
  if (!$messages_block_displayed) {
    $build['content']['messages'] = [
      '#weight' => -1000,
      '#type' => 'status_messages',
    ];
  }

  // If any render arrays are manually placed, render arrays and blocks must
  // be sorted.
  if (!$main_content_block_displayed || !$messages_block_displayed) {
    unset($build['content']['#sorted']);
  }

  // The access results' cacheability is currently added to the top level of the
  // render array. This is done to prevent issues with empty regions being
  // displayed.
  // This would need to be changed to allow caching of block regions, as each
  // region must then have the relevant cacheable metadata.
  $merged_cacheable_metadata = CacheableMetadata::createFromRenderArray($build);
  foreach ($cacheable_metadata_list as $cacheable_metadata) {
    $merged_cacheable_metadata = $merged_cacheable_metadata
      ->merge($cacheable_metadata);
  }
  $merged_cacheable_metadata
    ->applyTo($build);
  return $build;
}