From f8f1a94c224ff090b7c499fcd60386557c608687 Mon Sep 17 00:00:00 2001 From: Chi Date: Wed, 28 Mar 2018 14:32:55 +0500 Subject: [PATCH] Issue #2952972 by scotthooker, Chi: Rendering blocks in the same way panels does --- src/TwigExtension.php | 63 +++++++++++++++++-- tests/src/Functional/TwigTweakTest.php | 10 ++- .../templates/twig-tweak-test.html.twig | 3 +- 3 files changed, 68 insertions(+), 8 deletions(-) diff --git a/src/TwigExtension.php b/src/TwigExtension.php index caf86fa..39ab78d 100644 --- a/src/TwigExtension.php +++ b/src/TwigExtension.php @@ -3,11 +3,15 @@ namespace Drupal\twig_tweak; use Drupal\Component\Uuid\Uuid; +use Drupal\Core\Block\BlockPluginInterface; use Drupal\Core\Block\TitleBlockPluginInterface; +use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Field\FieldItemInterface; use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Link; +use Drupal\Core\Plugin\ContextAwarePluginInterface; +use Drupal\Core\Render\Element; use Drupal\Core\Site\Settings; use Drupal\Core\Url; use Drupal\image\Entity\ImageStyle; @@ -74,23 +78,70 @@ class TwigExtension extends \Twig_Extension { } /** - * Builds the render array for the provided block plugin. + * Builds the render array for a block. * * @param mixed $id - * The ID of block plugin to render. + * 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 null|array - * A render array for the block or NULL if the block does not exist. + * A render array for the block or NULL if the block cannot be rendered. */ - public function drupalBlock($id, array $configuration = []) { + public function drupalBlock($id, array $configuration = [], $wrapper = TRUE) { + + $configuration += ['label_display' => BlockPluginInterface::BLOCK_LABEL_VISIBLE]; + /** @var \Drupal\Core\Block\BlockPluginInterface $block_plugin */ $block_plugin = \Drupal::service('plugin.manager.block') ->createInstance($id, $configuration); - if ($block_plugin->access(\Drupal::currentUser())) { - return $block_plugin->build(); + + // Inject runtime contexts. + if ($block_plugin instanceof ContextAwarePluginInterface) { + $contexts = \Drupal::service('context.repository')->getRuntimeContexts($block_plugin->getContextMapping()); + \Drupal::service('context.handler')->applyContextMapping($block_plugin, $contexts); } + + if (!$block_plugin->access(\Drupal::currentUser())) { + return; + } + + $content = $block_plugin->build(); + + if ($content && !Element::isEmpty($content)) { + if ($wrapper) { + $build = [ + '#theme' => 'block', + '#attributes' => [], + '#contextual_links' => [], + '#configuration' => $block_plugin->getConfiguration(), + '#plugin_id' => $block_plugin->getPluginId(), + '#base_plugin_id' => $block_plugin->getBaseId(), + '#derivative_plugin_id' => $block_plugin->getDerivativeId(), + 'content' => $content, + ]; + } + else { + $build = $content; + } + } + else { + // Preserve cache metadata of empty blocks. + $build = [ + '#markup' => '', + '#cache' => $content['#cache'], + ]; + } + + if (!empty($content)) { + CacheableMetadata::createFromRenderArray($build) + ->merge(CacheableMetadata::createFromRenderArray($content)) + ->applyTo($build); + } + + return $build; } /** diff --git a/tests/src/Functional/TwigTweakTest.php b/tests/src/Functional/TwigTweakTest.php index 22b977c..0af16cf 100644 --- a/tests/src/Functional/TwigTweakTest.php +++ b/tests/src/Functional/TwigTweakTest.php @@ -88,11 +88,19 @@ class TwigTweakTest extends BrowserTestBase { $xpath = '//div[@class = "tt-view-result" and text() = 3]'; $this->assertByXpath($xpath); - // Test block plugin. + // Test block. $xpath = '//div[@class = "tt-block"]'; $xpath .= '/img[contains(@src, "/core/themes/classy/logo.svg") and @alt="Home"]'; $this->assertByXpath($xpath); + // Test block with wrapper. + $xpath = '//div[@class = "tt-block-with-wrapper"]'; + $xpath .= '/div[@class = "block block-system block-system-branding-block"]'; + $xpath .= '/h2[text() = "Branding"]'; + $xpath .= '/following-sibling::a[img[contains(@src, "/core/themes/classy/logo.svg") and @alt="Home"]]'; + $xpath .= '/following-sibling::div[@class = "site-name"]/a'; + $this->assertByXpath($xpath); + // Test region. $xpath = '//div[@class = "tt-region"]/div[@class = "region region-sidebar-first"]'; $xpath .= '/div[contains(@class, "block-page-title-block") and h1[@class="page-title" and text() = "Log in"]]'; diff --git a/tests/twig_tweak_test/templates/twig-tweak-test.html.twig b/tests/twig_tweak_test/templates/twig-tweak-test.html.twig index 9269cf3..34779da 100644 --- a/tests/twig_tweak_test/templates/twig-tweak-test.html.twig +++ b/tests/twig_tweak_test/templates/twig-tweak-test.html.twig @@ -21,7 +21,8 @@
{{ drupal_view('twig_tweak_test', 'page_1') }}
{{ drupal_view('twig_tweak_test', 'page_1', 1) }}
{{ drupal_view_result('twig_tweak_test', 'page_1')|length }}
-
{{ drupal_block('system_branding_block', {use_site_name: false}) }}
+
{{ drupal_block('system_branding_block', {use_site_name: false}, false) }}
+
{{ drupal_block('system_branding_block', {label: 'Branding'}) }}
{{ drupal_region('sidebar_first') }}
{{ drupal_entity('node', 1) }}
{{ drupal_entity('node', 1, 'teaser') }}