From 837b829a53efd5f18aff9fc7e6dfc73513aa70c6 Mon Sep 17 00:00:00 2001 From: catch <catch@35733.no-reply.drupal.org> Date: Wed, 5 Jan 2022 11:17:42 +0000 Subject: [PATCH] =?UTF-8?q?Issue=20#3094493=20by=20longwave,=20G=C3=A1bor?= =?UTF-8?q?=20Hojtsy,=20alexpott,=20naveen433,=20Chi,=20catch,=20andypost,?= =?UTF-8?q?=20Krzysztof=20Doma=C5=84ski,=20shaal,=20xjm,=20fgm,=20Luke.Leb?= =?UTF-8?q?er,=20daffie,=20Berdir,=20Fabianx,=20effulgentsia:=20Upgrade=20?= =?UTF-8?q?to=20Twig=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.lock | 24 ++++------ .../Metapackage/CoreRecommended/composer.json | 2 +- core/composer.json | 2 +- .../Core/Template/Loader/FilesystemLoader.php | 2 +- .../Core/Template/Loader/StringLoader.php | 6 +-- .../Template/Loader/ThemeRegistryLoader.php | 10 ++-- .../Drupal/Core/Template/TwigEnvironment.php | 4 +- .../Core/Template/TwigPhpStorageCache.php | 8 ++-- .../Core/Template/TwigSandboxPolicy.php | 12 ++--- .../help_topics/src/HelpTopicTwigLoader.php | 2 +- .../tests/src/Unit/HelpTopicTwigTest.php | 46 ++++--------------- .../src/Loader/TestLoader.php | 8 ++-- .../src/Functional/Theme/TwigLoaderTest.php | 4 +- .../Core/Theme/FrontMatterTest.php | 3 +- .../Core/Theme/TwigEnvironmentTest.php | 2 +- .../Core/Theme/TwigWhiteListTest.php | 2 +- core/themes/engines/twig/twig.engine | 2 +- 17 files changed, 53 insertions(+), 86 deletions(-) diff --git a/composer.lock b/composer.lock index 5b6777f9a78d..ca0806a233f2 100644 --- a/composer.lock +++ b/composer.lock @@ -452,7 +452,7 @@ "dist": { "type": "path", "url": "core", - "reference": "25a2835ba98c19a6fa4d60089d813a81de36e5e5" + "reference": "7963aa1162a3808d6d854bbba38a125121839b66" }, "require": { "asm89/stack-cors": "^1.1", @@ -494,7 +494,7 @@ "symfony/translation": "^4.4", "symfony/validator": "^4.4", "symfony/yaml": "^4.4.19", - "twig/twig": "^2.12.0", + "twig/twig": "^3.0", "typo3/phar-stream-wrapper": "^3.1.3" }, "conflict": { @@ -651,8 +651,7 @@ "autoload": { "psr-4": { "Drupal\\Core\\": "lib/Drupal/Core", - "Drupal\\Component\\": "lib/Drupal/Component", - "Drupal\\Driver\\": "../drivers/lib/Drupal/Driver" + "Drupal\\Component\\": "lib/Drupal/Component" }, "classmap": [ "lib/Drupal.php", @@ -4284,16 +4283,16 @@ }, { "name": "twig/twig", - "version": "v2.14.7", + "version": "v3.3.7", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "8e202327ee1ed863629de9b18a5ec70ac614d88f" + "reference": "8f168c6ffa3ce76d1786b3cd52275424a3fc675b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/8e202327ee1ed863629de9b18a5ec70ac614d88f", - "reference": "8e202327ee1ed863629de9b18a5ec70ac614d88f", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/8f168c6ffa3ce76d1786b3cd52275424a3fc675b", + "reference": "8f168c6ffa3ce76d1786b3cd52275424a3fc675b", "shasum": "" }, "require": { @@ -4308,13 +4307,10 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.14-dev" + "dev-master": "3.3-dev" } }, "autoload": { - "psr-0": { - "Twig_": "lib/" - }, "psr-4": { "Twig\\": "src/" } @@ -4347,7 +4343,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v2.14.7" + "source": "https://github.com/twigphp/Twig/tree/v3.3.7" }, "funding": [ { @@ -4359,7 +4355,7 @@ "type": "tidelift" } ], - "time": "2021-09-17T08:39:54+00:00" + "time": "2022-01-03T21:15:37+00:00" }, { "name": "typo3/phar-stream-wrapper", diff --git a/composer/Metapackage/CoreRecommended/composer.json b/composer/Metapackage/CoreRecommended/composer.json index 264055c04d96..96e100bfb060 100644 --- a/composer/Metapackage/CoreRecommended/composer.json +++ b/composer/Metapackage/CoreRecommended/composer.json @@ -59,7 +59,7 @@ "symfony/validator": "v4.4.35", "symfony/var-dumper": "v5.4.0", "symfony/yaml": "v4.4.34", - "twig/twig": "v2.14.7", + "twig/twig": "v3.3.7", "typo3/phar-stream-wrapper": "v3.1.7" } } diff --git a/core/composer.json b/core/composer.json index 64078e9d8aa6..4c320a030ce9 100644 --- a/core/composer.json +++ b/core/composer.json @@ -33,7 +33,7 @@ "symfony/polyfill-php80": "^1.16", "symfony/yaml": "^4.4.19", "typo3/phar-stream-wrapper": "^3.1.3", - "twig/twig": "^2.12.0", + "twig/twig": "^3.0", "doctrine/annotations": "^1.12", "guzzlehttp/guzzle": "^7.3.0", "laminas/laminas-feed": "^2.12", diff --git a/core/lib/Drupal/Core/Template/Loader/FilesystemLoader.php b/core/lib/Drupal/Core/Template/Loader/FilesystemLoader.php index 1864b3e128c4..6f4ddc11a753 100644 --- a/core/lib/Drupal/Core/Template/Loader/FilesystemLoader.php +++ b/core/lib/Drupal/Core/Template/Loader/FilesystemLoader.php @@ -50,7 +50,7 @@ public function __construct($paths, ModuleHandlerInterface $module_handler, Them * @param string $namespace * (optional) A path name. */ - public function addPath($path, $namespace = self::MAIN_NAMESPACE) { + public function addPath(string $path, string $namespace = self::MAIN_NAMESPACE): void { // Invalidate the cache. $this->cache = []; $this->paths[$namespace][] = rtrim($path, '/\\'); diff --git a/core/lib/Drupal/Core/Template/Loader/StringLoader.php b/core/lib/Drupal/Core/Template/Loader/StringLoader.php index 888569e54696..5049c6a48637 100644 --- a/core/lib/Drupal/Core/Template/Loader/StringLoader.php +++ b/core/lib/Drupal/Core/Template/Loader/StringLoader.php @@ -40,21 +40,21 @@ public function exists($name) { /** * {@inheritdoc} */ - public function getCacheKey($name) { + public function getCacheKey(string $name): string { return $name; } /** * {@inheritdoc} */ - public function isFresh($name, $time) { + public function isFresh(string $name, int $time): bool { return TRUE; } /** * {@inheritdoc} */ - public function getSourceContext($name) { + public function getSourceContext(string $name): Source { $name = (string) $name; return new Source($name, $name); } diff --git a/core/lib/Drupal/Core/Template/Loader/ThemeRegistryLoader.php b/core/lib/Drupal/Core/Template/Loader/ThemeRegistryLoader.php index 1271ef1627ec..5ac41be79b4f 100644 --- a/core/lib/Drupal/Core/Template/Loader/ThemeRegistryLoader.php +++ b/core/lib/Drupal/Core/Template/Loader/ThemeRegistryLoader.php @@ -38,13 +38,13 @@ public function __construct(Registry $theme_registry) { * @param bool $throw * Whether to throw an exception when an error occurs. * - * @return string|false - * The path to the template, or false if the template is not found. + * @return string|null + * The path to the template, or NULL if the template is not found. * * @throws \Twig\Error\LoaderError * Thrown if a template matching $name cannot be found. */ - protected function findTemplate($name, $throw = TRUE) { + protected function findTemplate(string $name, bool $throw = TRUE) { // Allow for loading based on the Drupal theme registry. $hook = str_replace('.html.twig', '', strtr($name, '-', '_')); $theme_registry = $this->themeRegistry->getRuntime(); @@ -66,13 +66,13 @@ protected function findTemplate($name, $throw = TRUE) { throw new LoaderError(sprintf('Unable to find template "%s" in the Drupal theme registry.', $name)); } - return FALSE; + return NULL; } /** * {@inheritdoc} */ - public function getCacheKey($name) { + public function getCacheKey(string $name): string { // The parent implementation does unnecessary work that triggers // deprecations in PHP 8.1. return $this->findTemplate($name) ?: ''; diff --git a/core/lib/Drupal/Core/Template/TwigEnvironment.php b/core/lib/Drupal/Core/Template/TwigEnvironment.php index d6db9fbbe6b2..258d9c022223 100644 --- a/core/lib/Drupal/Core/Template/TwigEnvironment.php +++ b/core/lib/Drupal/Core/Template/TwigEnvironment.php @@ -105,7 +105,7 @@ public function __construct($root, CacheBackendInterface $cache, $twig_extension /** * {@inheritdoc} */ - public function compileSource(Source $source) { + public function compileSource(Source $source): string { // Note: always use \Drupal\Core\Serialization\Yaml here instead of the // "serializer.yaml" service. This allows the core serializer to utilize // core related functionality which isn't available as the standalone @@ -195,7 +195,7 @@ public function getTemplateMetadata(string $name): array { * @return string * The template class name. */ - public function getTemplateClass($name, $index = NULL) { + public function getTemplateClass(string $name, int $index = NULL): string { // We override this method to add caching because it gets called multiple // times when the same template is used more than once. For example, a page // rendering 50 nodes without any node template overrides will use the same diff --git a/core/lib/Drupal/Core/Template/TwigPhpStorageCache.php b/core/lib/Drupal/Core/Template/TwigPhpStorageCache.php index fcffa1cd1358..7c2f44f6b752 100644 --- a/core/lib/Drupal/Core/Template/TwigPhpStorageCache.php +++ b/core/lib/Drupal/Core/Template/TwigPhpStorageCache.php @@ -73,7 +73,7 @@ protected function storage() { /** * {@inheritdoc} */ - public function generateKey($name, $className) { + public function generateKey(string $name, string $className): string { if (strpos($name, '{# inline_template_start #}') === 0) { // $name is an inline template, and can have characters that are not valid // for a filename. $suffix is unique for each inline template so we just @@ -101,14 +101,14 @@ public function generateKey($name, $className) { /** * {@inheritdoc} */ - public function load($key) { + public function load(string $key): void { $this->storage()->load($key); } /** * {@inheritdoc} */ - public function write($key, $content) { + public function write(string $key, string $content): void { $this->storage()->save($key, $content); // Save the last mtime. $cid = 'twig:' . $key; @@ -118,7 +118,7 @@ public function write($key, $content) { /** * {@inheritdoc} */ - public function getTimestamp($key) { + public function getTimestamp(string $key): int { $cid = 'twig:' . $key; if ($cache = $this->cache->get($cid)) { return $cache->data; diff --git a/core/lib/Drupal/Core/Template/TwigSandboxPolicy.php b/core/lib/Drupal/Core/Template/TwigSandboxPolicy.php index bdfc98cd6366..ff92b25c37bc 100644 --- a/core/lib/Drupal/Core/Template/TwigSandboxPolicy.php +++ b/core/lib/Drupal/Core/Template/TwigSandboxPolicy.php @@ -75,33 +75,33 @@ public function __construct() { /** * {@inheritdoc} */ - public function checkSecurity($tags, $filters, $functions) {} + public function checkSecurity($tags, $filters, $functions): void {} /** * {@inheritdoc} */ - public function checkPropertyAllowed($obj, $property) {} + public function checkPropertyAllowed($obj, $property): void {} /** * {@inheritdoc} */ - public function checkMethodAllowed($obj, $method) { + public function checkMethodAllowed($obj, $method): void { foreach ($this->allowed_classes as $class => $key) { if ($obj instanceof $class) { - return TRUE; + return; } } // Return quickly for an exact match of the method name. if (isset($this->allowed_methods[$method])) { - return TRUE; + return; } // If the method name starts with an allowed prefix, allow it. Note: // strpos() is between 3x and 7x faster than preg_match() in this case. foreach ($this->allowed_prefixes as $prefix) { if (strpos($method, $prefix) === 0) { - return TRUE; + return; } } diff --git a/core/modules/help_topics/src/HelpTopicTwigLoader.php b/core/modules/help_topics/src/HelpTopicTwigLoader.php index cdfeaf616f42..ccf334019627 100644 --- a/core/modules/help_topics/src/HelpTopicTwigLoader.php +++ b/core/modules/help_topics/src/HelpTopicTwigLoader.php @@ -69,7 +69,7 @@ protected function addExtension($path) { /** * {@inheritdoc} */ - public function getSourceContext($name) { + public function getSourceContext(string $name): Source { $path = $this->findTemplate($name); $contents = file_get_contents($path); diff --git a/core/modules/help_topics/tests/src/Unit/HelpTopicTwigTest.php b/core/modules/help_topics/tests/src/Unit/HelpTopicTwigTest.php index 13e360ccf322..8748bc709e8a 100644 --- a/core/modules/help_topics/tests/src/Unit/HelpTopicTwigTest.php +++ b/core/modules/help_topics/tests/src/Unit/HelpTopicTwigTest.php @@ -5,6 +5,8 @@ use Drupal\Core\Cache\Cache; use Drupal\help_topics\HelpTopicTwig; use Drupal\Tests\UnitTestCase; +use Twig\Template; +use Twig\TemplateWrapper; /** * Unit test for the HelpTopicTwig class. @@ -94,48 +96,16 @@ protected function getTwigMock() { ->disableOriginalConstructor() ->getMock(); + $template = $this->getMockForAbstractClass(Template::class, [$twig], '', TRUE, TRUE, TRUE, ['render']); + $template + ->method('render') + ->willReturn(self::PLUGIN_INFORMATION['body']); + $twig ->method('load') - ->willReturn(new FakeTemplateWrapper(self::PLUGIN_INFORMATION['body'])); + ->willReturn(new TemplateWrapper($twig, $template)); return $twig; } } - -/** - * Defines a fake template class to mock \Twig\TemplateWrapper. - * - * We cannot use getMockBuilder() for this, because the Twig TemplateWrapper - * class is declared "final" and cannot be mocked. - */ -class FakeTemplateWrapper { - - /** - * Body text to return from the render() method. - * - * @var string - */ - protected $body; - - /** - * Constructor. - * - * @param string $body - * Body text to return from the render() method. - */ - public function __construct($body) { - $this->body = $body; - } - - /** - * Mocks the \Twig\TemplateWrapper render() method. - * - * @param array $context - * (optional) Render context. - */ - public function render(array $context = []) { - return $this->body; - } - -} diff --git a/core/modules/system/tests/modules/twig_loader_test/src/Loader/TestLoader.php b/core/modules/system/tests/modules/twig_loader_test/src/Loader/TestLoader.php index f7731d848340..b0ae55de52bb 100644 --- a/core/modules/system/tests/modules/twig_loader_test/src/Loader/TestLoader.php +++ b/core/modules/system/tests/modules/twig_loader_test/src/Loader/TestLoader.php @@ -13,7 +13,7 @@ class TestLoader implements LoaderInterface { /** * {@inheritdoc} */ - public function getSourceContext($name) { + public function getSourceContext(string $name): Source { $name = (string) $name; $value = $name === 'kittens' ? 'kittens' : 'cats'; return new Source($value, $name); @@ -22,21 +22,21 @@ public function getSourceContext($name) { /** * {@inheritdoc} */ - public function exists($name) { + public function exists(string $name) { return TRUE; } /** * {@inheritdoc} */ - public function getCacheKey($name) { + public function getCacheKey(string $name): string { return $name; } /** * {@inheritdoc} */ - public function isFresh($name, $time) { + public function isFresh(string $name, int $time): bool { return TRUE; } diff --git a/core/modules/system/tests/src/Functional/Theme/TwigLoaderTest.php b/core/modules/system/tests/src/Functional/Theme/TwigLoaderTest.php index b98fda092607..37b7558a1740 100644 --- a/core/modules/system/tests/src/Functional/Theme/TwigLoaderTest.php +++ b/core/modules/system/tests/src/Functional/Theme/TwigLoaderTest.php @@ -29,10 +29,10 @@ class TwigLoaderTest extends BrowserTestBase { public function testTwigLoaderAddition() { $environment = \Drupal::service('twig'); - $template = $environment->loadTemplate('kittens'); + $template = $environment->load('kittens'); $this->assertEquals('kittens', $template->render([]), 'Passing "kittens" to the custom Twig loader returns "kittens".'); - $template = $environment->loadTemplate('meow'); + $template = $environment->load('meow'); $this->assertEquals('cats', $template->render([]), 'Passing something other than "kittens" to the custom Twig loader returns "cats".'); } diff --git a/core/tests/Drupal/KernelTests/Core/Theme/FrontMatterTest.php b/core/tests/Drupal/KernelTests/Core/Theme/FrontMatterTest.php index 93d55e7b9823..d33fff88fea7 100644 --- a/core/tests/Drupal/KernelTests/Core/Theme/FrontMatterTest.php +++ b/core/tests/Drupal/KernelTests/Core/Theme/FrontMatterTest.php @@ -8,6 +8,7 @@ use Symfony\Component\DependencyInjection\Definition; use Twig\Error\Error; use Twig\Error\SyntaxError; +use Twig\Loader\FilesystemLoader; /** * Tests Twig front matter support. @@ -44,7 +45,7 @@ protected function setUp(): void { public function register(ContainerBuilder $container) { parent::register($container); - $definition = new Definition('Twig_Loader_Filesystem', [[sys_get_temp_dir()]]); + $definition = new Definition(FilesystemLoader::class, [[sys_get_temp_dir()]]); $definition->setPublic(TRUE); $container->setDefinition('twig_loader__file_system', $definition) ->addTag('twig.loader'); diff --git a/core/tests/Drupal/KernelTests/Core/Theme/TwigEnvironmentTest.php b/core/tests/Drupal/KernelTests/Core/Theme/TwigEnvironmentTest.php index 783a0ec9bc26..270b4b24a58c 100644 --- a/core/tests/Drupal/KernelTests/Core/Theme/TwigEnvironmentTest.php +++ b/core/tests/Drupal/KernelTests/Core/Theme/TwigEnvironmentTest.php @@ -105,7 +105,7 @@ public function testTemplateNotFoundException() { $environment = \Drupal::service('twig'); try { - $environment->loadTemplate('this-template-does-not-exist.html.twig')->render([]); + $environment->load('this-template-does-not-exist.html.twig')->render([]); $this->fail('Did not throw an exception as expected.'); } catch (LoaderError $e) { diff --git a/core/tests/Drupal/KernelTests/Core/Theme/TwigWhiteListTest.php b/core/tests/Drupal/KernelTests/Core/Theme/TwigWhiteListTest.php index 11983e4868c9..a1044efb60a2 100644 --- a/core/tests/Drupal/KernelTests/Core/Theme/TwigWhiteListTest.php +++ b/core/tests/Drupal/KernelTests/Core/Theme/TwigWhiteListTest.php @@ -131,7 +131,7 @@ public function testWhiteListChaining() { 'field_term' => $this->term->id(), ]); $node->save(); - $template = $environment->loadTemplate($this->getThemePath('test_theme') . '/templates/node.html.twig'); + $template = $environment->load($this->getThemePath('test_theme') . '/templates/node.html.twig'); $markup = $template->render(['node' => $node]); $this->setRawContent($markup); $this->assertText('Sometimes people are just jerks'); diff --git a/core/themes/engines/twig/twig.engine b/core/themes/engines/twig/twig.engine index bcc984a02e24..665407c79a24 100644 --- a/core/themes/engines/twig/twig.engine +++ b/core/themes/engines/twig/twig.engine @@ -52,7 +52,7 @@ function twig_render_template($template_file, array $variables) { 'debug_suffix' => '', ]; try { - $output['rendered_markup'] = $twig_service->loadTemplate($template_file)->render($variables); + $output['rendered_markup'] = $twig_service->load($template_file)->render($variables); } catch (RuntimeError $e) { // In case there is a previous exception, re-throw the previous exception, -- GitLab