Commit dd79f791 authored by alexpott's avatar alexpott
Browse files

Issue #2571633 by lauriii, tuutti, joelpittet: Remove TwigExtension setter...

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