diff --git a/core/core.services.yml b/core/core.services.yml index cb935793a6b0..5e6e2d9a80a9 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -1553,13 +1553,9 @@ services: - { name: service_collector, tag: 'twig.extension', call: addExtension } twig.extension: class: Drupal\Core\Template\TwigExtension - arguments: ['@renderer'] + arguments: ['@renderer', '@url_generator', '@theme.manager', '@date.formatter'] tags: - { name: twig.extension, priority: 100 } - calls: - - [setUrlGenerator, ['@url_generator']] - - [setThemeManager, ['@theme.manager']] - - [setDateFormatter, ['@date.formatter']] # @todo Figure out what to do about debugging functions. # @see https://www.drupal.org/node/1804998 twig.extension.debug: diff --git a/core/lib/Drupal/Core/Template/TwigExtension.php b/core/lib/Drupal/Core/Template/TwigExtension.php index 3fcbe2c86f37..7d67ff991c4c 100644 --- a/core/lib/Drupal/Core/Template/TwigExtension.php +++ b/core/lib/Drupal/Core/Template/TwigExtension.php @@ -58,9 +58,18 @@ class TwigExtension extends \Twig_Extension { * * @param \Drupal\Core\Render\RendererInterface $renderer * The renderer. + * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator + * The URL generator. + * @param \Drupal\Core\Theme\ThemeManagerInterface $theme_manager + * The theme manager. + * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter + * The date formatter. */ - public function __construct(RendererInterface $renderer) { + public function __construct(RendererInterface $renderer, UrlGeneratorInterface $url_generator, ThemeManagerInterface $theme_manager, DateFormatterInterface $date_formatter) { $this->renderer = $renderer; + $this->urlGenerator = $url_generator; + $this->themeManager = $theme_manager; + $this->dateFormatter = $date_formatter; } /** @@ -72,7 +81,6 @@ class TwigExtension extends \Twig_Extension { * @return $this * * @deprecated in Drupal 8.0.x-dev, will be removed before Drupal 9.0.0. - * Use \Drupal\Core\Template\TwigExtension::setUrlGenerator(). */ public function setGenerators(UrlGeneratorInterface $url_generator) { return $this->setUrlGenerator($url_generator); @@ -85,6 +93,8 @@ class TwigExtension extends \Twig_Extension { * The URL generator. * * @return $this + * + * @deprecated in Drupal 8.3.x-dev, will be removed before Drupal 9.0.0. */ public function setUrlGenerator(UrlGeneratorInterface $url_generator) { $this->urlGenerator = $url_generator; @@ -98,6 +108,8 @@ class TwigExtension extends \Twig_Extension { * The theme manager. * * @return $this + * + * @deprecated in Drupal 8.3.x-dev, will be removed before Drupal 9.0.0. */ public function setThemeManager(ThemeManagerInterface $theme_manager) { $this->themeManager = $theme_manager; @@ -111,6 +123,8 @@ class TwigExtension extends \Twig_Extension { * The date formatter. * * @return $this + * + * @deprecated in Drupal 8.3.x-dev, will be removed before Drupal 9.0.0. */ public function setDateFormatter(DateFormatterInterface $date_formatter) { $this->dateFormatter = $date_formatter; diff --git a/core/modules/system/tests/modules/twig_extension_test/src/TwigExtension/TestExtension.php b/core/modules/system/tests/modules/twig_extension_test/src/TwigExtension/TestExtension.php index 4afa3a78cbdd..78d10202882f 100644 --- a/core/modules/system/tests/modules/twig_extension_test/src/TwigExtension/TestExtension.php +++ b/core/modules/system/tests/modules/twig_extension_test/src/TwigExtension/TestExtension.php @@ -2,12 +2,11 @@ namespace Drupal\twig_extension_test\TwigExtension; -use Drupal\Core\Template\TwigExtension; /** * A test Twig extension that adds a custom function and a custom filter. */ -class TestExtension extends TwigExtension { +class TestExtension extends \Twig_Extension { /** * Generates a list of all Twig functions that this extension defines. diff --git a/core/tests/Drupal/Tests/Core/Template/TwigExtensionTest.php b/core/tests/Drupal/Tests/Core/Template/TwigExtensionTest.php index 38373aa06739..396b2f9765ff 100644 --- a/core/tests/Drupal/Tests/Core/Template/TwigExtensionTest.php +++ b/core/tests/Drupal/Tests/Core/Template/TwigExtensionTest.php @@ -1,16 +1,9 @@ renderer = $this->getMock('\Drupal\Core\Render\RendererInterface'); + $this->urlGenerator = $this->getMock('\Drupal\Core\Routing\UrlGeneratorInterface'); + $this->themeManager = $this->getMock('\Drupal\Core\Theme\ThemeManagerInterface'); + $this->dateFormatter = $this->getMock('\Drupal\Core\Datetime\DateFormatterInterface'); + + $this->systemUnderTest = new TwigExtension($this->renderer, $this->urlGenerator, $this->themeManager, $this->dateFormatter); + } + /** * Tests the escaping * * @dataProvider providerTestEscaping */ public function testEscaping($template, $expected) { - $renderer = $this->getMock('\Drupal\Core\Render\RendererInterface'); $twig = new \Twig_Environment(NULL, array( 'debug' => TRUE, 'cache' => FALSE, 'autoescape' => 'html', - 'optimizations' => 0 + 'optimizations' => 0, )); - $twig->addExtension((new TwigExtension($renderer))->setUrlGenerator($this->getMock('Drupal\Core\Routing\UrlGeneratorInterface'))); + $twig->addExtension($this->systemUnderTest); $nodes = $twig->parse($twig->tokenize($template)); $this->assertSame($expected, $nodes->getNode('body') - ->getNode(0) - ->getNode('expr') instanceof \Twig_Node_Expression_Filter); + ->getNode(0) + ->getNode('expr') instanceof \Twig_Node_Expression_Filter); } /** @@ -83,25 +124,19 @@ class TwigExtensionTest extends UnitTestCase { * Tests the active_theme function. */ public function testActiveTheme() { - $renderer = $this->getMock('\Drupal\Core\Render\RendererInterface'); - $extension = new TwigExtension($renderer); - $theme_manager = $this->getMock('\Drupal\Core\Theme\ThemeManagerInterface'); $active_theme = $this->getMockBuilder('\Drupal\Core\Theme\ActiveTheme') ->disableOriginalConstructor() ->getMock(); - $active_theme - ->expects($this->once()) + $active_theme->expects($this->once()) ->method('getName') ->willReturn('test_theme'); - $theme_manager - ->expects($this->once()) + $this->themeManager->expects($this->once()) ->method('getActiveTheme') ->willReturn($active_theme); - $extension->setThemeManager($theme_manager); $loader = new \Twig_Loader_String(); $twig = new \Twig_Environment($loader); - $twig->addExtension($extension); + $twig->addExtension($this->systemUnderTest); $result = $twig->render('{{ active_theme() }}'); $this->assertEquals('test_theme', $result); } @@ -110,30 +145,21 @@ class TwigExtensionTest extends UnitTestCase { * Tests the format_date filter. */ public function testFormatDate() { - $date_formatter = $this->getMockBuilder('\Drupal\Core\Datetime\DateFormatter') - ->disableOriginalConstructor() - ->getMock(); - $date_formatter->expects($this->exactly(2)) + $this->dateFormatter->expects($this->exactly(2)) ->method('format') ->willReturn('1978-11-19'); - $renderer = $this->getMock('\Drupal\Core\Render\RendererInterface'); - $extension = new TwigExtension($renderer); - $extension->setDateFormatter($date_formatter); $loader = new StringLoader(); $twig = new \Twig_Environment($loader); - $twig->addExtension($extension); + $twig->addExtension($this->systemUnderTest); $result = $twig->render('{{ time|format_date("html_date") }}'); - $this->assertEquals($date_formatter->format('html_date'), $result); + $this->assertEquals($this->dateFormatter->format('html_date'), $result); } /** * Tests the active_theme_path function. */ public function testActiveThemePath() { - $renderer = $this->getMock('\Drupal\Core\Render\RendererInterface'); - $extension = new TwigExtension($renderer); - $theme_manager = $this->getMock('\Drupal\Core\Theme\ThemeManagerInterface'); $active_theme = $this->getMockBuilder('\Drupal\Core\Theme\ActiveTheme') ->disableOriginalConstructor() ->getMock(); @@ -141,15 +167,13 @@ class TwigExtensionTest extends UnitTestCase { ->expects($this->once()) ->method('getPath') ->willReturn('foo/bar'); - $theme_manager - ->expects($this->once()) + $this->themeManager->expects($this->once()) ->method('getActiveTheme') ->willReturn($active_theme); - $extension->setThemeManager($theme_manager); $loader = new \Twig_Loader_String(); $twig = new \Twig_Environment($loader); - $twig->addExtension($extension); + $twig->addExtension($this->systemUnderTest); $result = $twig->render('{{ active_theme_path() }}'); $this->assertEquals('foo/bar', $result); } @@ -160,34 +184,32 @@ class TwigExtensionTest extends UnitTestCase { * @covers ::escapeFilter */ public function testSafeStringEscaping() { - $renderer = $this->getMock('\Drupal\Core\Render\RendererInterface'); $twig = new \Twig_Environment(NULL, array( 'debug' => TRUE, 'cache' => FALSE, 'autoescape' => 'html', - 'optimizations' => 0 + 'optimizations' => 0, )); - $twig_extension = new TwigExtension($renderer); // By default, TwigExtension will attempt to cast objects to strings. // Ensure objects that implement MarkupInterface are unchanged. $safe_string = $this->getMock('\Drupal\Component\Render\MarkupInterface'); - $this->assertSame($safe_string, $twig_extension->escapeFilter($twig, $safe_string, 'html', 'UTF-8', TRUE)); + $this->assertSame($safe_string, $this->systemUnderTest->escapeFilter($twig, $safe_string, 'html', 'UTF-8', TRUE)); // Ensure objects that do not implement MarkupInterface are escaped. $string_object = new TwigExtensionTestString(""); - $this->assertSame('<script>alert('here');</script>', $twig_extension->escapeFilter($twig, $string_object, 'html', 'UTF-8', TRUE)); + $this->assertSame('<script>alert('here');</script>', $this->systemUnderTest->escapeFilter($twig, $string_object, 'html', 'UTF-8', TRUE)); } /** * @covers ::safeJoin */ public function testSafeJoin() { - $renderer = $this->prophesize(RendererInterface::class); - $renderer->render(['#markup' => 'will be rendered', '#printed' => FALSE])->willReturn('will be rendered'); - $renderer = $renderer->reveal(); + $this->renderer->expects($this->any()) + ->method('render') + ->with(['#markup' => 'will be rendered', '#printed' => FALSE]) + ->willReturn('will be rendered'); - $twig_extension = new TwigExtension($renderer); $twig_environment = $this->prophesize(TwigEnvironment::class)->reveal(); // Simulate t(). @@ -198,9 +220,9 @@ class TwigExtensionTest extends UnitTestCase { $items = [ 'will be escaped', $markup, - ['#markup' => 'will be rendered'] + ['#markup' => 'will be rendered'], ]; - $result = $twig_extension->safeJoin($twig_environment, $items, '
'); + $result = $this->systemUnderTest->safeJoin($twig_environment, $items, '
'); $this->assertEquals('<em>will be escaped</em>
will be markup
will be rendered', $result); // Ensure safe_join Twig filter supports Traversable variables. @@ -209,12 +231,12 @@ class TwigExtensionTest extends UnitTestCase { $markup, ['#markup' => 'will be rendered'], ]); - $result = $twig_extension->safeJoin($twig_environment, $items, ', '); + $result = $this->systemUnderTest->safeJoin($twig_environment, $items, ', '); $this->assertEquals('<em>will be escaped</em>, will be markup, will be rendered', $result); // Ensure safe_join Twig filter supports empty variables. $items = NULL; - $result = $twig_extension->safeJoin($twig_environment, $items, '
'); + $result = $this->systemUnderTest->safeJoin($twig_environment, $items, '
'); $this->assertEmpty($result); } @@ -222,13 +244,12 @@ class TwigExtensionTest extends UnitTestCase { * @dataProvider providerTestRenderVar */ public function testRenderVar($result, $input) { - $renderer = $this->prophesize(RendererInterface::class); - $renderer->render($result += ['#printed' => FALSE])->willReturn('Rendered output'); + $this->renderer->expects($this->any()) + ->method('render') + ->with($result += ['#printed' => FALSE]) + ->willReturn('Rendered output'); - $renderer = $renderer->reveal(); - $twig_extension = new TwigExtension($renderer); - - $this->assertEquals('Rendered output', $twig_extension->renderVar($input)); + $this->assertEquals('Rendered output', $this->systemUnderTest->renderVar($input)); } public function providerTestRenderVar() { @@ -247,7 +268,6 @@ class TwigExtensionTest extends UnitTestCase { * @covers ::bubbleArgMetadata */ public function testEscapeWithGeneratedLink() { - $renderer = $this->prophesize(RendererInterface::class); $twig = new \Twig_Environment(NULL, [ 'debug' => TRUE, 'cache' => FALSE, @@ -256,22 +276,23 @@ class TwigExtensionTest extends UnitTestCase { ] ); - $twig_extension = new TwigExtension($renderer->reveal()); - $twig->addExtension($twig_extension->setUrlGenerator($this->prophesize(UrlGeneratorInterface::class)->reveal())); + $twig->addExtension($this->systemUnderTest); $link = new GeneratedLink(); $link->setGeneratedLink(''); $link->addCacheTags(['foo']); $link->addAttachments(['library' => ['system/base']]); - $result = $twig_extension->escapeFilter($twig, $link, 'html', NULL, TRUE); - $renderer->render([ - "#cache" => [ - "contexts" => [], - "tags" => ["foo"], - "max-age" => -1 - ], - "#attached" => ['library' => ['system/base']], - ])->shouldHaveBeenCalled(); + $this->renderer->expects($this->atLeastOnce()) + ->method('render') + ->with([ + "#cache" => [ + "contexts" => [], + "tags" => ["foo"], + "max-age" => -1, + ], + "#attached" => ['library' => ['system/base']], + ]); + $result = $this->systemUnderTest->escapeFilter($twig, $link, 'html', NULL, TRUE); $this->assertEquals('', $result); } @@ -280,22 +301,22 @@ class TwigExtensionTest extends UnitTestCase { * @covers ::bubbleArgMetadata */ public function testRenderVarWithGeneratedLink() { - $renderer = $this->prophesize(RendererInterface::class); - $twig_extension = new TwigExtension($renderer->reveal()); $link = new GeneratedLink(); $link->setGeneratedLink(''); $link->addCacheTags(['foo']); $link->addAttachments(['library' => ['system/base']]); - $result = $twig_extension->renderVar($link); - $renderer->render([ - "#cache" => [ - "contexts" => [], - "tags" => ["foo"], - "max-age" => -1 - ], - "#attached" => ['library' => ['system/base']], - ])->shouldHaveBeenCalled(); + $this->renderer->expects($this->atLeastOnce()) + ->method('render') + ->with([ + "#cache" => [ + "contexts" => [], + "tags" => ["foo"], + "max-age" => -1, + ], + "#attached" => ['library' => ['system/base']], + ]); + $result = $this->systemUnderTest->renderVar($link); $this->assertEquals('', $result); } @@ -305,11 +326,9 @@ class TwigExtensionTest extends UnitTestCase { * @covers ::createAttribute */ public function testCreateAttribute() { - $renderer = $this->prophesize(RendererInterface::class); - $extension = new TwigExtension($renderer->reveal()); $loader = new StringLoader(); $twig = new \Twig_Environment($loader); - $twig->addExtension($extension); + $twig->addExtension($this->systemUnderTest); $iterations = [ ['class' => ['kittens'], 'data-toggle' => 'modal', 'data-lang' => 'es'],