For more information about this repository, visit the project page at https://www.drupal.org/project/twig_tweak
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
181 lines
5.8 KiB
181 lines
5.8 KiB
<?php |
|
|
|
namespace Drupal\twig_tweak\View; |
|
|
|
use Drupal\Core\Block\BlockPluginInterface; |
|
use Drupal\Core\Block\TitleBlockPluginInterface; |
|
use Drupal\Core\Cache\CacheableDependencyInterface; |
|
use Drupal\Core\Cache\CacheableMetadata; |
|
use Drupal\Core\Controller\TitleResolverInterface; |
|
use Drupal\Core\Plugin\ContextAwarePluginInterface; |
|
use Drupal\Core\Plugin\Context\ContextHandlerInterface; |
|
use Drupal\Core\Plugin\Context\ContextRepositoryInterface; |
|
use Drupal\Core\Render\Element; |
|
use Drupal\Core\Routing\RouteMatchInterface; |
|
use Drupal\Core\Session\AccountInterface; |
|
use Symfony\Component\HttpFoundation\RequestStack; |
|
|
|
/** |
|
* Block view builder. |
|
*/ |
|
class BlockViewBuilder { |
|
|
|
/** |
|
* The plugin.manager.block service. |
|
* |
|
* @var \Drupal\Core\Cache\CacheableDependencyInterface |
|
*/ |
|
protected $pluginManagerBlock; |
|
|
|
/** |
|
* The context repository service. |
|
* |
|
* @var \Drupal\Core\Plugin\Context\ContextRepositoryInterface |
|
*/ |
|
protected $contextRepository; |
|
|
|
/** |
|
* The plugin context handler. |
|
* |
|
* @var \Drupal\Core\Plugin\Context\ContextHandlerInterface |
|
*/ |
|
protected $contextHandler; |
|
|
|
/** |
|
* The current user. |
|
* |
|
* @var \Drupal\Core\Session\AccountInterface |
|
*/ |
|
protected $account; |
|
|
|
/** |
|
* The request stack. |
|
* |
|
* @var \Symfony\Component\HttpFoundation\RequestStack |
|
*/ |
|
protected $requestStack; |
|
|
|
/** |
|
* The current route match. |
|
* |
|
* @var \Drupal\Core\Routing\RouteMatchInterface |
|
*/ |
|
protected $routeMatch; |
|
|
|
/** |
|
* The title resolver. |
|
* |
|
* @var \Drupal\Core\Controller\TitleResolverInterface |
|
*/ |
|
protected $titleResolver; |
|
|
|
/** |
|
* Constructs a BlockViewBuilder object. |
|
*/ |
|
public function __construct( |
|
CacheableDependencyInterface $plugin_manager_block, |
|
ContextRepositoryInterface $context_repository, |
|
ContextHandlerInterface $context_handler, |
|
AccountInterface $account, |
|
RequestStack $request_stack, |
|
RouteMatchInterface $route_match, |
|
TitleResolverInterface $title_resolver |
|
) { |
|
$this->pluginManagerBlock = $plugin_manager_block; |
|
$this->contextRepository = $context_repository; |
|
$this->contextHandler = $context_handler; |
|
$this->account = $account; |
|
$this->requestStack = $request_stack; |
|
$this->routeMatch = $route_match; |
|
$this->titleResolver = $title_resolver; |
|
} |
|
|
|
/** |
|
* Builds the render array for a block. |
|
* |
|
* @param string $id |
|
* The string of block plugin to render. |
|
* @param array $configuration |
|
* (optional) Pass on any configuration to the plugin block. |
|
* @param bool $wrapper |
|
* (optional) Whether or not use block template for rendering. |
|
* |
|
* @return array |
|
* A renderable array representing the content of the block. |
|
*/ |
|
public function build(string $id, array $configuration = [], bool $wrapper = TRUE): array { |
|
|
|
$configuration += ['label_display' => BlockPluginInterface::BLOCK_LABEL_VISIBLE]; |
|
|
|
/** @var \Drupal\Core\Block\BlockPluginInterface $block_plugin */ |
|
$block_plugin = $this->pluginManagerBlock->createInstance($id, $configuration); |
|
|
|
// Inject runtime contexts. |
|
if ($block_plugin instanceof ContextAwarePluginInterface) { |
|
$contexts = $this->contextRepository->getRuntimeContexts($block_plugin->getContextMapping()); |
|
$this->contextHandler->applyContextMapping($block_plugin, $contexts); |
|
} |
|
|
|
$build = []; |
|
$access = $block_plugin->access($this->account, TRUE); |
|
if ($access->isAllowed()) { |
|
// Title block needs a special treatment. |
|
if ($block_plugin instanceof TitleBlockPluginInterface) { |
|
$request = $this->requestStack->getCurrentRequest(); |
|
$title = $this->titleResolver->getTitle($request, $this->routeMatch->getRouteObject()); |
|
$block_plugin->setTitle($title); |
|
} |
|
|
|
// 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. |
|
$build['content'] = $block_plugin->build(); |
|
|
|
if ($block_plugin instanceof TitleBlockPluginInterface) { |
|
$build['content']['#cache']['contexts'][] = 'url'; |
|
} |
|
// Some blocks returns NULL instead of array when empty. |
|
// @see https://www.drupal.org/project/drupal/issues/3212354 |
|
if ($wrapper && is_array($build['content']) && !Element::isEmpty($build['content'])) { |
|
$build += [ |
|
'#theme' => 'block', |
|
'#id' => $configuration['id'] ?? NULL, |
|
'#attributes' => [], |
|
'#contextual_links' => [], |
|
'#configuration' => $block_plugin->getConfiguration(), |
|
'#plugin_id' => $block_plugin->getPluginId(), |
|
'#base_plugin_id' => $block_plugin->getBaseId(), |
|
'#derivative_plugin_id' => $block_plugin->getDerivativeId(), |
|
]; |
|
// Semantically, the content returned by the plugin is the block, and in |
|
// particular, #attributes and #contextual_links is information about |
|
// the *entire* block. Therefore, we must move these properties into the |
|
// top-level element. |
|
foreach (['#attributes', '#contextual_links'] as $property) { |
|
if (isset($build['content'][$property])) { |
|
$build[$property] = $build['content'][$property]; |
|
unset($build['content'][$property]); |
|
} |
|
} |
|
} |
|
} |
|
|
|
CacheableMetadata::createFromRenderArray($build) |
|
->merge(CacheableMetadata::createFromObject($access)) |
|
->merge(CacheableMetadata::createFromObject($block_plugin)) |
|
->applyTo($build); |
|
|
|
if (!isset($build['#cache']['keys'])) { |
|
$build['#cache']['keys'] = [ |
|
'twig_tweak_block', |
|
$id, |
|
'[configuration]=' . hash('sha256', serialize($configuration)), |
|
'[wrapper]=' . (int) $wrapper, |
|
]; |
|
} |
|
|
|
return $build; |
|
} |
|
|
|
}
|
|
|