diff --git a/src/TwigExtension.php b/src/TwigExtension.php index dc20e33..953da88 100644 --- a/src/TwigExtension.php +++ b/src/TwigExtension.php @@ -2,13 +2,17 @@ namespace Drupal\twig_tweak; +use Drupal\Core\Block\TitleBlockPluginInterface; use Drupal\Core\Config\ConfigFactoryInterface; +use Drupal\Core\Controller\TitleResolverInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Menu\MenuLinkTreeInterface; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Site\Settings; use Drupal\Core\Utility\Token; use Drupal\image\Entity\ImageStyle; +use Symfony\Cmf\Component\Routing\RouteObjectInterface; +use Symfony\Component\HttpFoundation\RequestStack; /** * Twig extension with some useful functions and filters. @@ -50,6 +54,20 @@ class TwigExtension extends \Twig_Extension { */ protected $menuTree; + /** + * The request stack. + * + * @var \Symfony\Component\HttpFoundation\RequestStack + */ + protected $requestStack; + + /** + * The title resolver. + * + * @var \Drupal\Core\Controller\TitleResolverInterface + */ + protected $titleResolver; + /** * TwigExtension constructor. * @@ -63,13 +81,19 @@ class TwigExtension extends \Twig_Extension { * The route match. * @param \Drupal\Core\Menu\MenuLinkTreeInterface $menu_tree * The menu tree service. + * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack + * The request stack. + * @param \Drupal\Core\Controller\TitleResolverInterface $title_resolver + * The title resolver. */ - public function __construct(EntityTypeManagerInterface $entity_type_manager, Token $token, ConfigFactoryInterface $config_factory, RouteMatchInterface $route_match, MenuLinkTreeInterface $menu_tree) { + public function __construct(EntityTypeManagerInterface $entity_type_manager, Token $token, ConfigFactoryInterface $config_factory, RouteMatchInterface $route_match, MenuLinkTreeInterface $menu_tree, RequestStack $request_stack, TitleResolverInterface $title_resolver) { $this->entityTypeManager = $entity_type_manager; $this->token = $token; $this->configFactory = $config_factory; $this->routeMatch = $route_match; $this->menuTree = $menu_tree; + $this->requestStack = $request_stack; + $this->titleResolver = $title_resolver; } /** @@ -79,6 +103,7 @@ class TwigExtension extends \Twig_Extension { return [ new \Twig_SimpleFunction('drupal_view', 'views_embed_view'), new \Twig_SimpleFunction('drupal_block', [$this, 'drupalBlock']), + new \Twig_SimpleFunction('drupal_region', [$this, 'drupalRegion']), new \Twig_SimpleFunction('drupal_token', [$this, 'drupalToken']), new \Twig_SimpleFunction('drupal_entity', [$this, 'drupalEntity']), new \Twig_SimpleFunction('drupal_field', [$this, 'drupalField']), @@ -113,6 +138,42 @@ class TwigExtension extends \Twig_Extension { return 'twig_tweak'; } + /** + * Builds the render array of a given region. + * + * @param string $region + * The region to build. + * @param string $theme + * (Optional) The name of the theme to load the region. If it is not + * provided default site theme will be used. + * + * @return array + * A render array to display the region content. + */ + public function drupalRegion($region, $theme = NULL) { + $blocks = $this->entityTypeManager->getStorage('block')->loadByProperties([ + 'region' => $region, + 'theme' => $theme ?: $this->configFactory->get('system.theme')->get('default'), + ]); + + $view_builder = $this->entityTypeManager->getViewBuilder('block'); + + $build = []; + /* @var $blocks \Drupal\block\BlockInterface[] */ + foreach ($blocks as $id => $block) { + $block_plugin = $block->getPlugin(); + if ($block_plugin instanceof TitleBlockPluginInterface) { + $request = $this->requestStack->getCurrentRequest(); + if ($route = $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT)) { + $block_plugin->setTitle($this->titleResolver->getTitle($request, $route)); + } + } + $build[$id] = $view_builder->view($block); + } + + return $build; + } + /** * Builds the render array for the provided block. * diff --git a/tests/src/Functional/TwigTweakTest.php b/tests/src/Functional/TwigTweakTest.php index c0acbb7..3cfe1f8 100644 --- a/tests/src/Functional/TwigTweakTest.php +++ b/tests/src/Functional/TwigTweakTest.php @@ -77,7 +77,6 @@ class TwigTweakTest extends BrowserTestBase { // Test loading entity from url. $xpath = '//div[@class = "tt-entity-from-url" and . = ""]'; $this->assertByXpath($xpath); - $this->drupalGet('/node/2'); $xpath = '//div[@class = "tt-entity-from-url"]'; $xpath .= '/article[contains(@class, "node")]'; @@ -100,6 +99,13 @@ class TwigTweakTest extends BrowserTestBase { $xpath = '//div[@class = "tt-menu-depth"]/ul[@class = "menu"]/li[not(ul)]/a[. = "Link 1"]'; $this->assertByXpath($xpath); + // Test region. + $xpath = '//div[@class = "tt-region"]'; + $xpath .= '/div[contains(@class, "block-page-title-block") and h1[@class="page-title" and . = "Beta"]]'; + $xpath .= '/following-sibling::div[@class="messages messages--warning" and contains(., "Hi!")]'; + $xpath .= '/following-sibling::div[contains(@class, "block-system-powered-by-block")]/span[. = "Powered by Drupal"]'; + $this->assertByXpath($xpath); + // Test block. $xpath = '//div[@class = "tt-block"]'; $xpath .= '/div[@id="block-powered-by-drupal"]/span[contains(., "Powered by Drupal")]'; @@ -141,4 +147,13 @@ class TwigTweakTest extends BrowserTestBase { $this->assertSession()->elementExists('xpath', $xpath); } + /** + * {@inheritdoc} + */ + protected function drupalGet($path, array $options = [], array $headers = []) { + // Title block rendered through drupal_region() is cached by some reason. + \Drupal::service('cache_tags.invalidator')->invalidateTags(['block_view']); + return parent::drupalGet($path, $options, $headers); + } + } diff --git a/tests/twig_tweak_test/config/install/block.block.classy_page_title.yml b/tests/twig_tweak_test/config/install/block.block.classy_page_title.yml new file mode 100644 index 0000000..3dd4f0c --- /dev/null +++ b/tests/twig_tweak_test/config/install/block.block.classy_page_title.yml @@ -0,0 +1,17 @@ +langcode: en +status: true +dependencies: + theme: + - classy +id: classy_page_title +theme: classy +region: sidebar_first +weight: 0 +provider: null +plugin: page_title_block +settings: + id: page_title_block + label: 'Page title' + provider: core + label_display: '0' +visibility: { } diff --git a/tests/twig_tweak_test/config/install/block.block.classy_powered_by_drupal.yml b/tests/twig_tweak_test/config/install/block.block.classy_powered_by_drupal.yml new file mode 100644 index 0000000..ad953f9 --- /dev/null +++ b/tests/twig_tweak_test/config/install/block.block.classy_powered_by_drupal.yml @@ -0,0 +1,19 @@ +langcode: en +status: true +dependencies: + module: + - system + theme: + - classy +id: classy_powered_by_drupal +theme: classy +region: sidebar_first +weight: 20 +provider: null +plugin: system_powered_by_block +settings: + id: system_powered_by_block + label: 'Powered by Drupal' + provider: system + label_display: '0' +visibility: { } diff --git a/tests/twig_tweak_test/config/install/block.block.classy_status_messages.yml b/tests/twig_tweak_test/config/install/block.block.classy_status_messages.yml new file mode 100644 index 0000000..19bd131 --- /dev/null +++ b/tests/twig_tweak_test/config/install/block.block.classy_status_messages.yml @@ -0,0 +1,19 @@ +langcode: en +status: true +dependencies: + module: + - system + theme: + - classy +id: classy_status_messages +theme: classy +region: sidebar_first +weight: 10 +provider: null +plugin: system_messages_block +settings: + id: system_messages_block + label: 'Status messages' + provider: system + label_display: '0' +visibility: { } 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 1b6cc46..b16f453 100644 --- a/tests/twig_tweak_test/templates/twig-tweak-test.html.twig +++ b/tests/twig_tweak_test/templates/twig-tweak-test.html.twig @@ -9,6 +9,7 @@
{{ drupal_menu('twig-tweak-test') }}
{{ drupal_menu('twig-tweak-test', 2) }}
{{ drupal_menu('twig-tweak-test', 1, 1) }}
+
{{ drupal_region('sidebar_first') }}
{{ drupal_block('powered_by_drupal') }}
{{ drupal_token('site:name') }}
{{ drupal_token('node:title', {'node': node}) }}
diff --git a/twig_tweak.services.yml b/twig_tweak.services.yml index 34911f6..d040ea0 100644 --- a/twig_tweak.services.yml +++ b/twig_tweak.services.yml @@ -1,6 +1,13 @@ services: twig_tweak.twig_extension: class: Drupal\twig_tweak\TwigExtension - arguments: ['@entity_type.manager', '@token', '@config.factory', '@current_route_match', '@menu.link_tree', '@menu.active_trail'] + arguments: + - '@entity_type.manager' + - '@token' + - '@config.factory' + - '@current_route_match' + - '@menu.link_tree' + - '@request_stack' + - '@title_resolver' tags: - { name: twig.extension }