You are here

public function BlockPreviewRenderer::buildBlockPreview in Panopoly 8.2

Builds a render array representing a preview of the block.

Parameters

string $block_id: The block plugin id.

\Drupal\Core\Plugin\Context\ContextInterface[] $contexts: The available contexts.

Return value

array A render array of the block preview.

Throws

\Drupal\Component\Plugin\Exception\PluginException

File

modules/panopoly/panopoly_magic/src/BlockPreviewRenderer.php, line 59

Class

BlockPreviewRenderer
A service for rendering block previews.

Namespace

Drupal\panopoly_magic

Code

public function buildBlockPreview($block_id, array $contexts = []) {
  $block_definition = $this->blockManager
    ->getDefinition($block_id);

  /** @var \Drupal\Core\Block\BlockPluginInterface $block_plugin */
  $block_plugin = $this->blockManager
    ->createInstance($block_id);

  // Map contexts automatically in preparation for rendering.
  if ($block_plugin instanceof ContextAwarePluginInterface) {
    $mapping = $block_plugin
      ->getContextMapping();
    foreach ($block_plugin
      ->getContextDefinitions() as $context_slot => $definition) {

      // If it's already mapped, skip.
      if (isset($mapping[$context_slot])) {
        continue;
      }

      // If the context is required, assign the first valid context.
      if ($definition
        ->isRequired()) {
        $valid_contexts = $this->contextHandler
          ->getMatchingContexts($contexts, $definition);
        if (count($valid_contexts) > 0) {
          $valid_context_ids = array_keys($valid_contexts);
          $mapping[$context_slot] = $valid_context_ids[0];
        }
      }
    }
    try {
      $this->contextHandler
        ->applyContextMapping($block_plugin, $contexts, $mapping);
    } catch (ContextException $e) {
      return [
        '#markup' => $this
          ->t("Missing required context"),
      ];
    }
  }
  if (!empty($block_definition['preview_settings']) && is_array($block_definition['preview_settings'])) {
    if ($block_plugin
      ->getBaseId() === 'inline_block') {
      $block_definition['preview_settings']['type'] = $block_plugin
        ->getDerivativeId();
      $block_entity = BlockContent::create($block_definition['preview_settings']);
      $block_plugin
        ->setConfiguration([
        'block_serialized' => serialize($block_entity),
      ]);
    }
    else {
      $block_plugin
        ->setConfiguration(array_merge($block_plugin
        ->getConfiguration(), $block_definition['preview_settings']));
    }
  }
  try {

    // First, favor callbacks added to the definition, because this is how a
    // third-party module would add a custom preview to a block, possibly
    // overriding its original preview.
    if (!empty($block_definition['preview_callback']) && is_callable($block_definition['preview_callback'])) {
      return call_user_func($block_definition['preview_callback'], $block_plugin);
    }

    // Second, favor images, because these are also intended for use by
    // third-party modules (the block itself would use BlockPreviewInterface
    // and return the image render array itself).
    if (!empty($block_definition['preview_image'])) {
      $preview_image = [
        '#theme' => 'image',
        '#uri' => $block_definition['preview_image'],
      ];
      if (!empty($block_definition['preview_alt'])) {
        $preview_image['#alt'] = $block_definition['preview_alt'];
      }
      return $preview_image;
    }

    // Then, allow the block plugin to preview its own preview.
    if ($block_plugin instanceof BlockPreviewInterface) {
      return $block_plugin
        ->buildPreview();
    }

    // Finally, we'll render the block the normal way as the last resort.
    return $block_plugin
      ->build();
  } catch (ContextException $e) {
    return [
      '#markup' => $this
        ->t("Missing required context"),
    ];
  }
}