function BlockComponentRenderArray::onBuildRender

Same name in other branches
  1. 8.9.x core/modules/layout_builder/src/EventSubscriber/BlockComponentRenderArray.php \Drupal\layout_builder\EventSubscriber\BlockComponentRenderArray::onBuildRender()
  2. 10 core/modules/layout_builder/src/EventSubscriber/BlockComponentRenderArray.php \Drupal\layout_builder\EventSubscriber\BlockComponentRenderArray::onBuildRender()
  3. 11.x core/modules/layout_builder/src/EventSubscriber/BlockComponentRenderArray.php \Drupal\layout_builder\EventSubscriber\BlockComponentRenderArray::onBuildRender()

Builds render arrays for block plugins and sets it on the event.

Parameters

\Drupal\layout_builder\Event\SectionComponentBuildRenderArrayEvent $event: The section component render event.

File

core/modules/layout_builder/src/EventSubscriber/BlockComponentRenderArray.php, line 61

Class

BlockComponentRenderArray
Builds render arrays and handles access for all block components.

Namespace

Drupal\layout_builder\EventSubscriber

Code

public function onBuildRender(SectionComponentBuildRenderArrayEvent $event) {
    $block = $event->getPlugin();
    if (!$block instanceof BlockPluginInterface) {
        return;
    }
    // Set block access dependency even if we are not checking access on
    // this level. The block itself may render another
    // RefinableDependentAccessInterface object and need to pass on this value.
    if ($block instanceof RefinableDependentAccessInterface) {
        $contexts = $event->getContexts();
        if (isset($contexts['layout_builder.entity'])) {
            if ($entity = $contexts['layout_builder.entity']->getContextValue()) {
                if ($event->inPreview()) {
                    // If previewing in Layout Builder allow access.
                    $block->setAccessDependency(new LayoutPreviewAccessAllowed());
                }
                else {
                    $block->setAccessDependency($entity);
                }
            }
        }
    }
    // Only check access if the component is not being previewed.
    if ($event->inPreview()) {
        $access = AccessResult::allowed()->setCacheMaxAge(0);
    }
    else {
        $access = $block->access($this->currentUser, TRUE);
    }
    $event->addCacheableDependency($access);
    if ($access->isAllowed()) {
        $event->addCacheableDependency($block);
        // @todo Revisit after https://www.drupal.org/node/3027653, as this will
        //   provide a better way to remove contextual links from Views blocks.
        //   Currently, doing this requires setting
        //   \Drupal\views\ViewExecutable::$showAdminLinks() to false before the
        //   Views block is built.
        if ($block instanceof ViewsBlock && $event->inPreview()) {
            $block->getViewExecutable()
                ->setShowAdminLinks(FALSE);
        }
        $content = $block->build();
        // We don't output the block render data if there are no render elements
        // found, but we want to capture the cache metadata from the block
        // regardless.
        $event->addCacheableDependency(CacheableMetadata::createFromRenderArray($content));
        $is_content_empty = Element::isEmpty($content);
        $is_placeholder_ready = $event->inPreview() && $block instanceof PreviewFallbackInterface;
        // If the content is empty and no placeholder is available, return.
        if ($is_content_empty && !$is_placeholder_ready) {
            return;
        }
        $build = [
            // @todo Move this to BlockBase in https://www.drupal.org/node/2931040.
'#theme' => 'block',
            '#configuration' => $block->getConfiguration(),
            '#plugin_id' => $block->getPluginId(),
            '#base_plugin_id' => $block->getBaseId(),
            '#derivative_plugin_id' => $block->getDerivativeId(),
            '#in_preview' => $event->inPreview(),
            '#weight' => $event->getComponent()
                ->getWeight(),
        ];
        // Place the $content returned by the block plugin into a 'content' child
        // element, as a way to allow the plugin to have complete control of its
        // properties and rendering (for instance, its own #theme) without
        // conflicting with the properties used above, or alternate ones used by
        // alternate block rendering approaches in contributed modules. However,
        // the use of a child element is an implementation detail of this
        // particular block rendering approach. Semantically, the content returned
        // by the block plugin, and in particular, attributes and contextual links
        // are information that belong to the entire block. Therefore, we must
        // move these properties from $content and merge them into the top-level
        // element.
        if (isset($content['#attributes'])) {
            $build['#attributes'] = $content['#attributes'];
            unset($content['#attributes']);
        }
        // Hide contextual links for inline blocks until the UX issues surrounding
        // editing them directly are resolved.
        // @see https://www.drupal.org/project/drupal/issues/3075308
        if (!$block instanceof InlineBlock && !empty($content['#contextual_links'])) {
            $build['#contextual_links'] = $content['#contextual_links'];
        }
        $build['content'] = $content;
        if ($event->inPreview()) {
            if ($block instanceof PreviewFallbackInterface) {
                $preview_fallback_string = $block->getPreviewFallbackString();
            }
            else {
                $preview_fallback_string = $this->t('"@block" block', [
                    '@block' => $block->label(),
                ]);
            }
            // @todo Use new label methods so
            //   data-layout-content-preview-placeholder-label doesn't have to use
            //   preview fallback in https://www.drupal.org/node/2025649.
            $build['#attributes']['data-layout-content-preview-placeholder-label'] = $preview_fallback_string;
            if ($is_content_empty && $is_placeholder_ready) {
                $build['content']['#markup'] = $this->t('Placeholder for the @preview_fallback', [
                    '@preview_fallback' => $block->getPreviewFallbackString(),
                ]);
            }
        }
        $event->setBuild($build);
    }
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.