diff --git a/src/TwigExtension.php b/src/TwigExtension.php index 7f11d68..c4484bd 100644 --- a/src/TwigExtension.php +++ b/src/TwigExtension.php @@ -59,6 +59,7 @@ class TwigExtension extends \Twig_Extension { new \Twig_SimpleFunction('drupal_messages', [$this, 'drupalMessages']), new \Twig_SimpleFunction('drupal_breadcrumb', [$this, 'drupalBreadcrumb']), new \Twig_SimpleFunction('drupal_breakpoint', [$this, 'drupalBreakpoint'], $all_options), + new \Twig_SimpleFunction('contextual_links', [$this, 'contextualLInks']), ]; } @@ -709,6 +710,41 @@ class TwigExtension extends \Twig_Extension { ->toRenderable(); } + /** + * Builds contextual links. + * + * Examples: + * @code + * # Basic usage. + *
+ * {{ contextual_links('entity.view.edit_form:view=frontpage&display_id=feed_1') }} + * {{ drupal_view('frontpage') }} + *
+ * + * # Multiple links. + *
+ * {{ contextual_links('node:node=123|block_content:block_content=123') }} + * {{ content }} + *
+ * @endcode + * + * @param string $id + * A serialized representation of a #contextual_links property value array. + * + * @return array + * A renderable array representing contextual links. + * + * @see https://www.drupal.org/node/2133283 + */ + public function contextualLinks($id) { + $build['#cache']['contexts'] = ['user.permissions']; + if (\Drupal::currentUser()->hasPermission('access contextual links')) { + $build['#type'] = 'contextual_links_placeholder'; + $build['#id'] = $id; + } + return $build; + } + /** * Emits a breakpoint to the debug client. * @@ -798,7 +834,6 @@ class TwigExtension extends \Twig_Extension { return file_url_transform_relative($image_style->buildUrl($path)); } else { - // @todo Throw an exception in 3.x. trigger_error(sprintf('Could not load image style %s.', $style)); } } diff --git a/tests/src/Functional/TwigTweakTest.php b/tests/src/Functional/TwigTweakTest.php index 3ea7115..86d879e 100644 --- a/tests/src/Functional/TwigTweakTest.php +++ b/tests/src/Functional/TwigTweakTest.php @@ -34,6 +34,7 @@ class TwigTweakTest extends BrowserTestBase { 'image', 'responsive_image', 'language', + 'contextual', ]; /** @@ -285,6 +286,15 @@ class TwigTweakTest extends BrowserTestBase { $xpath = '//div[@class = "tt-token-replace" and text() = "Site name: Drupal"]'; $this->assertByXpath($xpath); + // Test contextual links. + $xpath = '//div[@class="tt-contextual-links" and not(div[@data-contextual-id])]'; + $this->assertByXpath($xpath); + + $this->grantPermissions(Role::load(Role::ANONYMOUS_ID), ['access contextual links']); + $this->drupalGet($this->getUrl()); + $xpath = '//div[@class="tt-contextual-links" and div[@data-contextual-id]]'; + $this->assertByXpath($xpath); + // Test preg replacement. $xpath = '//div[@class = "tt-preg-replace" and text() = "FOO-bar"]'; $this->assertByXpath($xpath); 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 128a768..847ced8 100644 --- a/tests/twig_tweak_test/templates/twig-tweak-test.html.twig +++ b/tests/twig_tweak_test/templates/twig-tweak-test.html.twig @@ -52,6 +52,7 @@
{{ drupal_messages() }}
{{ drupal_breadcrumb() }}
+
{{ 'Site name: [site:name]' | token_replace }}
{{ 'FOO' | preg_replace('/(foo)/i', '$1-bar') }}
{{ 'public://images/ocean.jpg' | image_style('thumbnail') }}