diff --git a/composer.lock b/composer.lock index 9b2b43dfe3..59e4b29c99 100644 --- a/composer.lock +++ b/composer.lock @@ -653,7 +653,7 @@ "dist": { "type": "path", "url": "core", - "reference": "9faae700fd9adfe0a1c5ffd73dcc334b3be5ce5a" + "reference": "ae05b62ba90c6bb364ba715d7005d99e188b8b85" }, "require": { "asm89/stack-cors": "^1.1", @@ -695,7 +695,7 @@ "symfony/translation": "^4.4", "symfony/validator": "^4.4", "symfony/yaml": "^4.4", - "twig/twig": "^1.38.2", + "twig/twig": "^2.12.0", "typo3/phar-stream-wrapper": "^3.1.3", "zendframework/zend-diactoros": "^1.8", "zendframework/zend-feed": "^2.12" @@ -3472,21 +3472,22 @@ }, { "name": "twig/twig", - "version": "v1.42.3", + "version": "v2.12.1", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "201baee843e0ffe8b0b956f336dd42b2a92fae4e" + "reference": "ddd4134af9bfc6dba4eff7c8447444ecc45b9ee5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/201baee843e0ffe8b0b956f336dd42b2a92fae4e", - "reference": "201baee843e0ffe8b0b956f336dd42b2a92fae4e", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/ddd4134af9bfc6dba4eff7c8447444ecc45b9ee5", + "reference": "ddd4134af9bfc6dba4eff7c8447444ecc45b9ee5", "shasum": "" }, "require": { - "php": ">=5.5.0", - "symfony/polyfill-ctype": "^1.8" + "php": "^7.0", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-mbstring": "^1.3" }, "require-dev": { "psr/container": "^1.0", @@ -3496,7 +3497,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.42-dev" + "dev-master": "2.12-dev" } }, "autoload": { @@ -3534,7 +3535,7 @@ "keywords": [ "templating" ], - "time": "2019-08-24T12:51:03+00:00" + "time": "2019-10-17T07:34:53+00:00" }, { "name": "typo3/phar-stream-wrapper", diff --git a/composer/Metapackage/CoreRecommended/composer.json b/composer/Metapackage/CoreRecommended/composer.json index c42c8708a8..fabe0c14b6 100644 --- a/composer/Metapackage/CoreRecommended/composer.json +++ b/composer/Metapackage/CoreRecommended/composer.json @@ -59,7 +59,7 @@ "symfony/translation-contracts": "v1.1.7", "symfony/validator": "4.4.x-dev", "symfony/yaml": "4.4.x-dev", - "twig/twig": "v1.42.3", + "twig/twig": "v2.12.1", "typo3/phar-stream-wrapper": "v3.1.3", "zendframework/zend-diactoros": "1.8.7", "zendframework/zend-escaper": "2.6.1", diff --git a/core/composer.json b/core/composer.json index 392bbe073a..2573c591d2 100644 --- a/core/composer.json +++ b/core/composer.json @@ -32,7 +32,7 @@ "symfony/polyfill-iconv": "^1.0", "symfony/yaml": "^4.4", "typo3/phar-stream-wrapper": "^3.1.3", - "twig/twig": "^1.38.2", + "twig/twig": "^2.12.0", "doctrine/common": "^2.7", "doctrine/annotations": "^1.4", "guzzlehttp/guzzle": "^6.3", diff --git a/core/core.services.yml b/core/core.services.yml index 9d6ad2711a..5cdcc3efe5 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -1643,11 +1643,11 @@ services: # @todo Figure out what to do about debugging functions. # @see https://www.drupal.org/node/1804998 twig.extension.debug: - class: Twig_Extension_Debug + class: Twig\Extension\DebugExtension tags: - { name: twig.extension } twig.loader: - class: Twig_Loader_Chain + class: Twig\Loader\ChainLoader public: false tags: - { name: service_collector, tag: twig.loader, call: addLoader, required: TRUE } diff --git a/core/lib/Drupal/Core/Render/Markup.php b/core/lib/Drupal/Core/Render/Markup.php index 0947f8fc67..8278389df9 100644 --- a/core/lib/Drupal/Core/Render/Markup.php +++ b/core/lib/Drupal/Core/Render/Markup.php @@ -17,7 +17,7 @@ * rendering. * * @see \Drupal\Core\Template\TwigExtension::escapeFilter - * @see \Twig_Markup + * @see \Twig\Markup */ final class Markup implements MarkupInterface, \Countable { use MarkupTrait; diff --git a/core/lib/Drupal/Core/Template/Loader/FilesystemLoader.php b/core/lib/Drupal/Core/Template/Loader/FilesystemLoader.php index b84e790b62..4edb6e2d8d 100644 --- a/core/lib/Drupal/Core/Template/Loader/FilesystemLoader.php +++ b/core/lib/Drupal/Core/Template/Loader/FilesystemLoader.php @@ -4,6 +4,7 @@ use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Extension\ThemeHandlerInterface; +use Twig\Loader\FilesystemLoader as TwigFilesystemLoader; /** * Loads templates from the filesystem. @@ -12,7 +13,7 @@ * filesystem loader so that templates can be referenced by namespace, like * @block/block.html.twig or @mytheme/page.html.twig. */ -class FilesystemLoader extends \Twig_Loader_Filesystem { +class FilesystemLoader extends TwigFilesystemLoader { /** * Constructs a new FilesystemLoader object. diff --git a/core/lib/Drupal/Core/Template/Loader/StringLoader.php b/core/lib/Drupal/Core/Template/Loader/StringLoader.php index 909a09a8f8..3991a72680 100644 --- a/core/lib/Drupal/Core/Template/Loader/StringLoader.php +++ b/core/lib/Drupal/Core/Template/Loader/StringLoader.php @@ -2,7 +2,7 @@ namespace Drupal\Core\Template\Loader; -use Twig\Loader\ExistsLoaderInterface; +use Twig\Loader\LoaderInterface; use Twig\Loader\SourceContextLoaderInterface; use Twig\Source; @@ -18,13 +18,13 @@ * This class override ensures that the string loader behaves as expected in * the loader chain. If Twig's string loader is used as is, any string (even a * reference to a file-based Twig template) is treated as a valid template and - * is rendered instead of a \Twig_Error_Loader exception being thrown. + * is rendered instead of a \Twig\Error\LoaderError exception being thrown. * * @see \Drupal\Core\Template\TwigEnvironment::renderInline() * @see \Drupal\Core\Render\Element\InlineTemplate * @see twig_render_template() */ -class StringLoader implements \Twig_LoaderInterface, ExistsLoaderInterface, SourceContextLoaderInterface { +class StringLoader implements LoaderInterface, SourceContextLoaderInterface { /** * {@inheritdoc} diff --git a/core/lib/Drupal/Core/Template/Loader/ThemeRegistryLoader.php b/core/lib/Drupal/Core/Template/Loader/ThemeRegistryLoader.php index 862092b606..b59b83d8ff 100644 --- a/core/lib/Drupal/Core/Template/Loader/ThemeRegistryLoader.php +++ b/core/lib/Drupal/Core/Template/Loader/ThemeRegistryLoader.php @@ -3,13 +3,15 @@ namespace Drupal\Core\Template\Loader; use Drupal\Core\Theme\Registry; +use Twig\Error\LoaderError; +use Twig\Loader\FilesystemLoader; /** * Loads templates based on information from the Drupal theme registry. * * Allows for template inheritance based on the currently active template. */ -class ThemeRegistryLoader extends \Twig_Loader_Filesystem { +class ThemeRegistryLoader extends FilesystemLoader { /** * The theme registry used to determine which template to use. @@ -39,7 +41,7 @@ public function __construct(Registry $theme_registry) { * @return string|false * The path to the template, or false if the template is not found. * - * @throws \Twig_Error_Loader + * @throws \Twig\Error\LoaderError * Thrown if a template matching $name cannot be found. */ protected function findTemplate($name, $throw = TRUE) { @@ -61,7 +63,7 @@ protected function findTemplate($name, $throw = TRUE) { } if ($throw) { - throw new \Twig_Error_Loader(sprintf('Unable to find template "%s" in the Drupal theme registry.', $name)); + throw new LoaderError(sprintf('Unable to find template "%s" in the Drupal theme registry.', $name)); } return FALSE; diff --git a/core/lib/Drupal/Core/Template/TwigEnvironment.php b/core/lib/Drupal/Core/Template/TwigEnvironment.php index 426234459b..b59f8a73f7 100644 --- a/core/lib/Drupal/Core/Template/TwigEnvironment.php +++ b/core/lib/Drupal/Core/Template/TwigEnvironment.php @@ -6,16 +6,17 @@ use Drupal\Core\PhpStorage\PhpStorageFactory; use Drupal\Core\Render\Markup; use Drupal\Core\State\StateInterface; +use Twig\Environment; +use Twig\Extension\SandboxExtension; +use Twig\Loader\LoaderInterface; /** * A class that defines a Twig environment for Drupal. * * Instances of this class are used to store the configuration and extensions, * and are used to load templates from the file system or other locations. - * - * @see core\vendor\twig\twig\lib\Twig\Environment.php */ -class TwigEnvironment extends \Twig_Environment { +class TwigEnvironment extends Environment { /** * Key name of the Twig cache prefix metadata key-value pair in State. @@ -55,12 +56,12 @@ class TwigEnvironment extends \Twig_Environment { * The Twig extension hash. * @param \Drupal\Core\State\StateInterface $state * The state service. - * @param \Twig_LoaderInterface $loader + * @param \Twig\Loader\LoaderInterface $loader * The Twig loader or loader chain. * @param array $options * The options for the Twig environment. */ - public function __construct($root, CacheBackendInterface $cache, $twig_extension_hash, StateInterface $state, \Twig_LoaderInterface $loader = NULL, array $options = []) { + public function __construct($root, CacheBackendInterface $cache, $twig_extension_hash, StateInterface $state, LoaderInterface $loader = NULL, array $options = []) { $this->state = $state; // Ensure that twig.engine is loaded, given that it is needed to render a @@ -97,7 +98,7 @@ public function __construct($root, CacheBackendInterface $cache, $twig_extension $this->setLoader($loader); parent::__construct($this->getLoader(), $options); $policy = new TwigSandboxPolicy(); - $sandbox = new \Twig_Extension_Sandbox($policy, TRUE); + $sandbox = new SandboxExtension($policy, TRUE); $this->addExtension($sandbox); } diff --git a/core/lib/Drupal/Core/Template/TwigExtension.php b/core/lib/Drupal/Core/Template/TwigExtension.php index db6e080b5f..2188cffa44 100644 --- a/core/lib/Drupal/Core/Template/TwigExtension.php +++ b/core/lib/Drupal/Core/Template/TwigExtension.php @@ -14,6 +14,14 @@ use Drupal\Core\Routing\UrlGeneratorInterface; use Drupal\Core\Theme\ThemeManagerInterface; use Drupal\Core\Url; +use Twig\Environment; +use Twig\Extension\AbstractExtension; +use Twig\Markup as TwigMarkup; +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Node; +use Twig\TwigFilter; +use Twig\TwigFunction; /** * A class providing Drupal Twig extensions. @@ -23,7 +31,7 @@ * * @see \Drupal\Core\CoreServiceProvider */ -class TwigExtension extends \Twig_Extension { +class TwigExtension extends AbstractExtension { /** * The URL generator. @@ -137,19 +145,19 @@ public function setDateFormatter(DateFormatterInterface $date_formatter) { public function getFunctions() { return [ // This function will receive a renderable array, if an array is detected. - new \Twig_SimpleFunction('render_var', [$this, 'renderVar']), + new TwigFunction('render_var', [$this, 'renderVar']), // The url and path function are defined in close parallel to those found // in \Symfony\Bridge\Twig\Extension\RoutingExtension - new \Twig_SimpleFunction('url', [$this, 'getUrl'], ['is_safe_callback' => [$this, 'isUrlGenerationSafe']]), - new \Twig_SimpleFunction('path', [$this, 'getPath'], ['is_safe_callback' => [$this, 'isUrlGenerationSafe']]), - new \Twig_SimpleFunction('link', [$this, 'getLink']), - new \Twig_SimpleFunction('file_url', function ($uri) { + new TwigFunction('url', [$this, 'getUrl'], ['is_safe_callback' => [$this, 'isUrlGenerationSafe']]), + new TwigFunction('path', [$this, 'getPath'], ['is_safe_callback' => [$this, 'isUrlGenerationSafe']]), + new TwigFunction('link', [$this, 'getLink']), + new TwigFunction('file_url', function ($uri) { return file_url_transform_relative(file_create_url($uri)); }), - new \Twig_SimpleFunction('attach_library', [$this, 'attachLibrary']), - new \Twig_SimpleFunction('active_theme_path', [$this, 'getActiveThemePath']), - new \Twig_SimpleFunction('active_theme', [$this, 'getActiveTheme']), - new \Twig_SimpleFunction('create_attribute', [$this, 'createAttribute']), + new TwigFunction('attach_library', [$this, 'attachLibrary']), + new TwigFunction('active_theme_path', [$this, 'getActiveThemePath']), + new TwigFunction('active_theme', [$this, 'getActiveTheme']), + new TwigFunction('create_attribute', [$this, 'createAttribute']), ]; } @@ -159,32 +167,32 @@ public function getFunctions() { public function getFilters() { return [ // Translation filters. - new \Twig_SimpleFilter('t', 't', ['is_safe' => ['html']]), - new \Twig_SimpleFilter('trans', 't', ['is_safe' => ['html']]), + new TwigFilter('t', 't', ['is_safe' => ['html']]), + new TwigFilter('trans', 't', ['is_safe' => ['html']]), // The "raw" filter is not detectable when parsing "trans" tags. To detect // which prefix must be used for translation (@, !, %), we must clone the // "raw" filter and give it identifiable names. These filters should only // be used in "trans" tags. // @see TwigNodeTrans::compileString() - new \Twig_SimpleFilter('placeholder', [$this, 'escapePlaceholder'], ['is_safe' => ['html'], 'needs_environment' => TRUE]), + new TwigFilter('placeholder', [$this, 'escapePlaceholder'], ['is_safe' => ['html'], 'needs_environment' => TRUE]), // Replace twig's escape filter with our own. - new \Twig_SimpleFilter('drupal_escape', [$this, 'escapeFilter'], ['needs_environment' => TRUE, 'is_safe_callback' => 'twig_escape_filter_is_safe']), + new TwigFilter('drupal_escape', [$this, 'escapeFilter'], ['needs_environment' => TRUE, 'is_safe_callback' => 'twig_escape_filter_is_safe']), // Implements safe joining. // @todo Make that the default for |join? Upstream issue: // https://github.com/fabpot/Twig/issues/1420 - new \Twig_SimpleFilter('safe_join', [$this, 'safeJoin'], ['needs_environment' => TRUE, 'is_safe' => ['html']]), + new TwigFilter('safe_join', [$this, 'safeJoin'], ['needs_environment' => TRUE, 'is_safe' => ['html']]), // Array filters. - new \Twig_SimpleFilter('without', [$this, 'withoutFilter']), + new TwigFilter('without', [$this, 'withoutFilter']), // CSS class and ID filters. - new \Twig_SimpleFilter('clean_class', '\Drupal\Component\Utility\Html::getClass'), - new \Twig_SimpleFilter('clean_id', '\Drupal\Component\Utility\Html::getId'), + new TwigFilter('clean_class', '\Drupal\Component\Utility\Html::getClass'), + new TwigFilter('clean_id', '\Drupal\Component\Utility\Html::getId'), // This filter will render a renderable array to use the string results. - new \Twig_SimpleFilter('render', [$this, 'renderVar']), - new \Twig_SimpleFilter('format_date', [$this->dateFormatter, 'format']), + new TwigFilter('render', [$this, 'renderVar']), + new TwigFilter('format_date', [$this->dateFormatter, 'format']), ]; } @@ -299,7 +307,7 @@ public function getLink($text, $url, $attributes = []) { } // The text has been processed by twig already, convert it to a safe object // for the render system. - if ($text instanceof \Twig_Markup) { + if ($text instanceof TwigMarkup) { $text = Markup::create($text); } $build = [ @@ -351,18 +359,18 @@ public function getActiveThemePath() { * If param1 and param2 reference placeholders in the route, it would not * need to be escaped, but we don't know that in advance. * - * @param \Twig_Node $args_node + * @param \Twig\Node\Node $args_node * The arguments of the path/url functions. * * @return array * An array with the contexts the URL is safe */ - public function isUrlGenerationSafe(\Twig_Node $args_node) { + public function isUrlGenerationSafe(Node $args_node) { // Support named arguments. $parameter_node = $args_node->hasNode('parameters') ? $args_node->getNode('parameters') : ($args_node->hasNode(1) ? $args_node->getNode(1) : NULL); - if (!isset($parameter_node) || $parameter_node instanceof \Twig_Node_Expression_Array && count($parameter_node) <= 2 && - (!$parameter_node->hasNode(1) || $parameter_node->getNode(1) instanceof \Twig_Node_Expression_Constant)) { + if (!isset($parameter_node) || $parameter_node instanceof ArrayExpression && count($parameter_node) <= 2 && + (!$parameter_node->hasNode(1) || $parameter_node->getNode(1) instanceof ConstantExpression)) { return ['html']; } @@ -392,15 +400,15 @@ public function attachLibrary($library) { /** * Provides a placeholder wrapper around ::escapeFilter. * - * @param \Twig_Environment $env - * A Twig_Environment instance. + * @param \Twig\Environment $env + * A Twig Environment instance. * @param mixed $string * The value to be escaped. * * @return string|null * The escaped, rendered output, or NULL if there is no valid output. */ - public function escapePlaceholder(\Twig_Environment $env, $string) { + public function escapePlaceholder(Environment $env, $string) { $return = $this->escapeFilter($env, $string); return $return ? '' . $return . '' : NULL; @@ -414,8 +422,8 @@ public function escapePlaceholder(\Twig_Environment $env, $string) { * Note: This function should be kept in sync with * theme_render_and_autoescape(). * - * @param \Twig_Environment $env - * A Twig_Environment instance. + * @param \Twig\Environment $env + * A Twig Environment instance. * @param mixed $arg * The value to be escaped. * @param string $strategy @@ -436,7 +444,7 @@ public function escapePlaceholder(\Twig_Environment $env, $string) { * @todo Refactor this to keep it in sync with theme_render_and_autoescape() * in https://www.drupal.org/node/2575065 */ - public function escapeFilter(\Twig_Environment $env, $arg, $strategy = 'html', $charset = NULL, $autoescape = FALSE) { + public function escapeFilter(Environment $env, $arg, $strategy = 'html', $charset = NULL, $autoescape = FALSE) { // Check for a numeric zero int or float. if ($arg === 0 || $arg === 0.0) { return 0; @@ -449,8 +457,8 @@ public function escapeFilter(\Twig_Environment $env, $arg, $strategy = 'html', $ $this->bubbleArgMetadata($arg); - // Keep Twig_Markup objects intact to support autoescaping. - if ($autoescape && ($arg instanceof \Twig_Markup || $arg instanceof MarkupInterface)) { + // Keep \Twig\Markup objects intact to support autoescaping. + if ($autoescape && ($arg instanceof TwigMarkup || $arg instanceof MarkupInterface)) { return $arg; } @@ -538,7 +546,7 @@ protected function bubbleArgMetadata($arg) { * If an object is passed which does not implement __toString(), * RenderableInterface or toString() then an exception is thrown; * Other objects are casted to string. However in the case that the - * object is an instance of a Twig_Markup object it is returned directly + * object is an instance of a \Twig\Markup object it is returned directly * to support auto escaping. * * If an array is passed it is rendered via render() and scalar values are @@ -552,7 +560,7 @@ protected function bubbleArgMetadata($arg) { * RenderableInterface or toString(). * * @return mixed - * The rendered output or an Twig_Markup object. + * The rendered output or an \Twig\Markup object. * * @see render * @see TwigNodeVisitor @@ -604,8 +612,8 @@ public function renderVar($arg) { /** * Joins several strings together safely. * - * @param \Twig_Environment $env - * A Twig_Environment instance. + * @param \Twig\Environment $env + * A Twig Environment instance. * @param mixed[]|\Traversable|null $value * The pieces to join. * @param string $glue @@ -616,7 +624,7 @@ public function renderVar($arg) { * @return string * The strings joined together. */ - public function safeJoin(\Twig_Environment $env, $value, $glue = '') { + public function safeJoin(Environment $env, $value, $glue = '') { if ($value instanceof \Traversable) { $value = iterator_to_array($value, FALSE); } diff --git a/core/lib/Drupal/Core/Template/TwigNodeTrans.php b/core/lib/Drupal/Core/Template/TwigNodeTrans.php index b6d6d077d4..e581fa9c2b 100644 --- a/core/lib/Drupal/Core/Template/TwigNodeTrans.php +++ b/core/lib/Drupal/Core/Template/TwigNodeTrans.php @@ -2,7 +2,18 @@ namespace Drupal\Core\Template; +use Twig\Compiler; +use Twig\Error\SyntaxError; use Twig\Node\CheckToStringNode; +use Twig\Node\Expression\AbstractExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\FilterExpression; +use Twig\Node\Expression\FunctionExpression; +use Twig\Node\Expression\GetAttrExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Node\Expression\TempNameExpression; +use Twig\Node\Node; +use Twig\Node\PrintNode; /** * A class that defines the Twig 'trans' tag for Drupal. @@ -14,12 +25,12 @@ * @see https://twig-extensions.readthedocs.io/en/latest/i18n.html * @see https://github.com/fabpot/Twig-extensions */ -class TwigNodeTrans extends \Twig_Node { +class TwigNodeTrans extends Node { /** * {@inheritdoc} */ - public function __construct(\Twig_Node $body, \Twig_Node $plural = NULL, \Twig_Node_Expression $count = NULL, \Twig_Node_Expression $options = NULL, $lineno, $tag = NULL) { + public function __construct(Node $body, Node $plural = NULL, AbstractExpression $count = NULL, AbstractExpression $options = NULL, $lineno, $tag = NULL) { $nodes['body'] = $body; if ($count !== NULL) { $nodes['count'] = $count; @@ -36,7 +47,7 @@ public function __construct(\Twig_Node $body, \Twig_Node $plural = NULL, \Twig_N /** * {@inheritdoc} */ - public function compile(\Twig_Compiler $compiler) { + public function compile(Compiler $compiler) { $compiler->addDebugInfo($this); list($singular, $tokens) = $this->compileString($this->getNode('body')); @@ -88,7 +99,7 @@ public function compile(\Twig_Compiler $compiler) { /** * Extracts the text and tokens for the "trans" tag. * - * @param \Twig_Node $body + * @param \Twig\Node\Node $body * The node to compile. * * @return array @@ -96,10 +107,11 @@ public function compile(\Twig_Compiler $compiler) { * - string $text * The extracted text. * - array $tokens - * The extracted tokens as new \Twig_Node_Expression_Name instances. + * The extracted tokens as new \Twig\Node\Expression\TempNameExpression + * instances. */ - protected function compileString(\Twig_Node $body) { - if ($body instanceof \Twig_Node_Expression_Name || $body instanceof \Twig_Node_Expression_Constant || $body instanceof \Twig_Node_Expression_TempName) { + protected function compileString(Node $body) { + if ($body instanceof NameExpression || $body instanceof ConstantExpression || $body instanceof TempNameExpression) { return [$body, []]; } @@ -108,13 +120,9 @@ protected function compileString(\Twig_Node $body) { $text = ''; foreach ($body as $node) { - if (get_class($node) === 'Twig_Node' && $node->getNode(0) instanceof \Twig_Node_SetTemp) { - $node = $node->getNode(1); - } - - if ($node instanceof \Twig_Node_Print) { + if ($node instanceof PrintNode) { $n = $node->getNode('expr'); - while ($n instanceof \Twig_Node_Expression_Filter) { + while ($n instanceof FilterExpression) { $n = $n->getNode('node'); } @@ -124,7 +132,7 @@ protected function compileString(\Twig_Node $body) { $args = $n; // Support TwigExtension->renderVar() function in chain. - if ($args instanceof \Twig_Node_Expression_Function) { + if ($args instanceof FunctionExpression) { $args = $n->getNode('arguments')->getNode(0); } @@ -134,7 +142,7 @@ protected function compileString(\Twig_Node $body) { // safe for templates. // @see TwigExtension::getFilters() $argPrefix = '@'; - while ($args instanceof \Twig_Node_Expression_Filter) { + while ($args instanceof FilterExpression) { switch ($args->getNode('filter')->getAttribute('value')) { case 'placeholder': $argPrefix = '%'; @@ -145,7 +153,7 @@ protected function compileString(\Twig_Node $body) { if ($args instanceof CheckToStringNode) { $args = $args->getNode('expr'); } - if ($args instanceof \Twig_Node_Expression_GetAttr) { + if ($args instanceof GetAttrExpression) { $argName = []; // Reuse the incoming expression. $expr = $args; @@ -153,7 +161,7 @@ protected function compileString(\Twig_Node $body) { $argName[] = $args->getNode('attribute')->getAttribute('value'); while ($args->hasNode('node')) { $args = $args->getNode('node'); - if ($args instanceof \Twig_Node_Expression_Name) { + if ($args instanceof NameExpression) { $argName[] = $args->getAttribute('name'); } else { @@ -168,7 +176,7 @@ protected function compileString(\Twig_Node $body) { if (!is_null($args)) { $argName = $args->getAttribute('name'); } - $expr = new \Twig_Node_Expression_Name($argName, $n->getTemplateLine()); + $expr = new NameExpression($argName, $n->getTemplateLine()); } $placeholder = sprintf('%s%s', $argPrefix, $argName); $text .= $placeholder; @@ -181,14 +189,14 @@ protected function compileString(\Twig_Node $body) { } } elseif (!$body->hasAttribute('data')) { - throw new \Twig_Error_Syntax('{% trans %} tag cannot be empty'); + throw new SyntaxError('{% trans %} tag cannot be empty'); } else { $text = $body->getAttribute('data'); } return [ - new \Twig_Node([new \Twig_Node_Expression_Constant(trim($text), $body->getTemplateLine())]), + new Node([new ConstantExpression(trim($text), $body->getTemplateLine())]), $tokens, ]; } diff --git a/core/lib/Drupal/Core/Template/TwigNodeVisitor.php b/core/lib/Drupal/Core/Template/TwigNodeVisitor.php index 5286242281..0429b6a31d 100644 --- a/core/lib/Drupal/Core/Template/TwigNodeVisitor.php +++ b/core/lib/Drupal/Core/Template/TwigNodeVisitor.php @@ -2,8 +2,15 @@ namespace Drupal\Core\Template; +use Twig\Environment; +use Twig\Node\Expression\FilterExpression; +use Twig\Node\Expression\FunctionExpression; +use Twig\Node\Node; +use Twig\Node\PrintNode; +use Twig\NodeVisitor\AbstractNodeVisitor; + /** - * Provides a Twig_NodeVisitor to change the generated parse-tree. + * Provides a TwigNodeVisitor to change the generated parse-tree. * * This is used to ensure that everything printed is wrapped via the * TwigExtension->renderVar() function in order to just write {{ content }} @@ -11,22 +18,22 @@ * * @see twig_render */ -class TwigNodeVisitor extends \Twig_BaseNodeVisitor { +class TwigNodeVisitor extends AbstractNodeVisitor { /** * {@inheritdoc} */ - protected function doEnterNode(\Twig_Node $node, \Twig_Environment $env) { + protected function doEnterNode(Node $node, Environment $env) { return $node; } /** * {@inheritdoc} */ - protected function doLeaveNode(\Twig_Node $node, \Twig_Environment $env) { + protected function doLeaveNode(Node $node, Environment $env) { // We use this to inject a call to render_var -> TwigExtension->renderVar() // before anything is printed. - if ($node instanceof \Twig_Node_Print) { + if ($node instanceof PrintNode) { if (!empty($this->skipRenderVarFunction)) { // No need to add the callback, we have escape active already. unset($this->skipRenderVarFunction); @@ -35,12 +42,12 @@ protected function doLeaveNode(\Twig_Node $node, \Twig_Environment $env) { $class = get_class($node); $line = $node->getTemplateLine(); return new $class( - new \Twig_Node_Expression_Function('render_var', new \Twig_Node([$node->getNode('expr')]), $line), + new FunctionExpression('render_var', new Node([$node->getNode('expr')]), $line), $line ); } // Change the 'escape' filter to our own 'drupal_escape' filter. - elseif ($node instanceof \Twig_Node_Expression_Filter) { + elseif ($node instanceof FilterExpression) { $name = $node->getNode('filter')->getAttribute('value'); if ('escape' == $name || 'e' == $name) { // Use our own escape filter that is MarkupInterface aware. diff --git a/core/lib/Drupal/Core/Template/TwigPhpStorageCache.php b/core/lib/Drupal/Core/Template/TwigPhpStorageCache.php index 995ce97803..fcffa1cd13 100644 --- a/core/lib/Drupal/Core/Template/TwigPhpStorageCache.php +++ b/core/lib/Drupal/Core/Template/TwigPhpStorageCache.php @@ -5,6 +5,7 @@ use Drupal\Component\Utility\Crypt; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\PhpStorage\PhpStorageFactory; +use Twig\Cache\CacheInterface; /** * Provides an alternate cache storage for Twig using PhpStorage. @@ -16,7 +17,7 @@ * * @see \Drupal\Core\DependencyInjection\Compiler\TwigExtensionPass */ -class TwigPhpStorageCache implements \Twig_CacheInterface { +class TwigPhpStorageCache implements CacheInterface { /** * The maximum length for each part of the cache key suffix. diff --git a/core/lib/Drupal/Core/Template/TwigSandboxPolicy.php b/core/lib/Drupal/Core/Template/TwigSandboxPolicy.php index 4adc9d60d3..ab8dc33feb 100644 --- a/core/lib/Drupal/Core/Template/TwigSandboxPolicy.php +++ b/core/lib/Drupal/Core/Template/TwigSandboxPolicy.php @@ -3,6 +3,8 @@ namespace Drupal\Core\Template; use Drupal\Core\Site\Settings; +use Twig\Sandbox\SecurityError; +use Twig\Sandbox\SecurityPolicyInterface; /** * Default sandbox policy for Twig templates. @@ -13,7 +15,7 @@ * objects can do by whitelisting certain classes, method names, and method * names with an allowed prefix. All object properties may be accessed. */ -class TwigSandboxPolicy implements \Twig_Sandbox_SecurityPolicyInterface { +class TwigSandboxPolicy implements SecurityPolicyInterface { /** * An array of whitelisted methods in the form of methodName => TRUE. @@ -102,7 +104,7 @@ public function checkMethodAllowed($obj, $method) { } } - throw new \Twig_Sandbox_SecurityError(sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, get_class($obj))); + throw new SecurityError(sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, get_class($obj))); } } diff --git a/core/lib/Drupal/Core/Template/TwigTransTokenParser.php b/core/lib/Drupal/Core/Template/TwigTransTokenParser.php index 07580e90d7..93e4fdcfe3 100644 --- a/core/lib/Drupal/Core/Template/TwigTransTokenParser.php +++ b/core/lib/Drupal/Core/Template/TwigTransTokenParser.php @@ -2,6 +2,16 @@ namespace Drupal\Core\Template; +use Twig\Error\SyntaxError; +use Twig\Node\Expression\FilterExpression; +use Twig\Node\Expression\GetAttrExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Node\Node; +use Twig\Node\PrintNode; +use Twig\Node\TextNode; +use Twig\Token; +use Twig\TokenParser\AbstractTokenParser; + /** * A class that defines the Twig 'trans' token parser for Drupal. * @@ -9,16 +19,15 @@ * code into an Abstract Syntax Tree (AST). The AST will later be compiled * into PHP code usable for runtime execution of the template. * - * @see \Twig_TokenParser * @see https://twig-extensions.readthedocs.io/en/latest/i18n.html * @see https://github.com/fabpot/Twig-extensions */ -class TwigTransTokenParser extends \Twig_TokenParser { +class TwigTransTokenParser extends AbstractTokenParser { /** * {@inheritdoc} */ - public function parse(\Twig_Token $token) { + public function parse(Token $token) { $lineno = $token->getLine(); $stream = $this->parser->getStream(); $body = NULL; @@ -26,24 +35,24 @@ public function parse(\Twig_Token $token) { $count = NULL; $plural = NULL; - if (!$stream->test(\Twig_Token::BLOCK_END_TYPE) && $stream->test(\Twig_Token::STRING_TYPE)) { + if (!$stream->test(Token::BLOCK_END_TYPE) && $stream->test(Token::STRING_TYPE)) { $body = $this->parser->getExpressionParser()->parseExpression(); } - if (!$stream->test(\Twig_Token::BLOCK_END_TYPE) && $stream->test(\Twig_Token::NAME_TYPE, 'with')) { + if (!$stream->test(Token::BLOCK_END_TYPE) && $stream->test(Token::NAME_TYPE, 'with')) { $stream->next(); $options = $this->parser->getExpressionParser()->parseExpression(); } if (!$body) { - $stream->expect(\Twig_Token::BLOCK_END_TYPE); + $stream->expect(Token::BLOCK_END_TYPE); $body = $this->parser->subparse([$this, 'decideForFork']); if ('plural' === $stream->next()->getValue()) { $count = $this->parser->getExpressionParser()->parseExpression(); - $stream->expect(\Twig_Token::BLOCK_END_TYPE); + $stream->expect(Token::BLOCK_END_TYPE); $plural = $this->parser->subparse([$this, 'decideForEnd'], TRUE); } } - $stream->expect(\Twig_Token::BLOCK_END_TYPE); + $stream->expect(Token::BLOCK_END_TYPE); $this->checkTransString($body, $lineno); @@ -76,27 +85,27 @@ public function getTag() { /** * Ensure that any nodes that are parsed are only of allowed types. * - * @param \Twig_Node $body + * @param \Twig\Node\Node $body * The expression to check. * @param int $lineno * The source line. * - * @throws \Twig_Error_Syntax + * @throws \Twig\Error\SyntaxError */ - protected function checkTransString(\Twig_Node $body, $lineno) { + protected function checkTransString(Node $body, $lineno) { foreach ($body as $node) { if ( - $node instanceof \Twig_Node_Text + $node instanceof TextNode || - ($node instanceof \Twig_Node_Print && $node->getNode('expr') instanceof \Twig_Node_Expression_Name) + ($node instanceof PrintNode && $node->getNode('expr') instanceof NameExpression) || - ($node instanceof \Twig_Node_Print && $node->getNode('expr') instanceof \Twig_Node_Expression_GetAttr) + ($node instanceof PrintNode && $node->getNode('expr') instanceof GetAttrExpression) || - ($node instanceof \Twig_Node_Print && $node->getNode('expr') instanceof \Twig_Node_Expression_Filter) + ($node instanceof PrintNode && $node->getNode('expr') instanceof FilterExpression) ) { continue; } - throw new \Twig_Error_Syntax(sprintf('The text to be translated with "trans" can only contain references to simple variables'), $lineno); + throw new SyntaxError(sprintf('The text to be translated with "trans" can only contain references to simple variables'), $lineno); } } diff --git a/core/modules/block_content/templates/block-content-add-list.html.twig b/core/modules/block_content/templates/block-content-add-list.html.twig index 08104617c6..f04d5e58ba 100644 --- a/core/modules/block_content/templates/block-content-add-list.html.twig +++ b/core/modules/block_content/templates/block-content-add-list.html.twig @@ -14,11 +14,11 @@ * @ingroup themeable */ #} -{% spaceless %} +{% apply spaceless %}
{% for type in types %}
{{ type.link }}
{{ type.description }}
{% endfor %}
-{% endspaceless %} +{% endapply %} diff --git a/core/modules/book/templates/book-export-html.html.twig b/core/modules/book/templates/book-export-html.html.twig index 5fb2e971a5..025762ca12 100644 --- a/core/modules/book/templates/book-export-html.html.twig +++ b/core/modules/book/templates/book-export-html.html.twig @@ -36,12 +36,12 @@ to be exported as printer-friendly HTML. #} - {% for i in 1..depth-1 if depth > 1 %} + {% if depth > 1 %}{% for i in 1..depth-1 %}
- {% endfor %} + {% endfor %}{% endif %} {{ contents }} - {% for i in 1..depth-1 if depth > 1 %} + {% if depth > 1 %}{% for i in 1..depth-1 %}
- {% endfor %} + {% endfor %}{% endif %} diff --git a/core/modules/ckeditor/templates/ckeditor-settings-toolbar.html.twig b/core/modules/ckeditor/templates/ckeditor-settings-toolbar.html.twig index bc8e836493..3636bf06c5 100644 --- a/core/modules/ckeditor/templates/ckeditor-settings-toolbar.html.twig +++ b/core/modules/ckeditor/templates/ckeditor-settings-toolbar.html.twig @@ -13,7 +13,7 @@ * @ingroup themeable */ #} -{% spaceless %} +{% apply spaceless %}
{{ 'Toolbar configuration'|t }}
@@ -72,4 +72,4 @@
-{% endspaceless %} +{% endapply %} diff --git a/core/modules/forum/templates/forum-list.html.twig b/core/modules/forum/templates/forum-list.html.twig index c2e55675c7..6bf4220b82 100644 --- a/core/modules/forum/templates/forum-list.html.twig +++ b/core/modules/forum/templates/forum-list.html.twig @@ -50,7 +50,7 @@ depth this forum resides at. This will allow us to use CSS left-margin for indenting. #} - {% for i in 1..forum.depth if forum.depth > 0 %}
{% endfor %} + {% if forum.depth > 0 %}{% for i in 1..forum.depth %}
{% endfor %}{% endif %}
{{ forum.icon_title }}
@@ -58,7 +58,7 @@ {% if forum.description.value %}
{{ forum.description.value }}
{% endif %} - {% for i in 1..forum.depth if forum.depth > 0 %}
{% endfor %} + {% if forum.depth > 0 %}{% for i in 1..forum.depth %}
{% endfor %}{% endif %} {% if forum.is_container == false %} diff --git a/core/modules/help_topics/src/HelpTopicTwigLoader.php b/core/modules/help_topics/src/HelpTopicTwigLoader.php index b785736f19..27260983d0 100644 --- a/core/modules/help_topics/src/HelpTopicTwigLoader.php +++ b/core/modules/help_topics/src/HelpTopicTwigLoader.php @@ -7,6 +7,7 @@ use Drupal\Core\Extension\ThemeHandlerInterface; use Drupal\Core\Serialization\Yaml; use Twig\Error\LoaderError; +use Twig\Loader\FilesystemLoader; use Twig\Source; /** @@ -24,7 +25,7 @@ * experimental modules and development releases of contributed modules. * See https://www.drupal.org/core/experimental for more information. */ -class HelpTopicTwigLoader extends \Twig_Loader_Filesystem { +class HelpTopicTwigLoader extends FilesystemLoader { /** * {@inheritdoc} diff --git a/core/modules/help_topics/tests/src/Unit/HelpTopicTwigTest.php b/core/modules/help_topics/tests/src/Unit/HelpTopicTwigTest.php index 201b73b70f..1682e0cbe0 100644 --- a/core/modules/help_topics/tests/src/Unit/HelpTopicTwigTest.php +++ b/core/modules/help_topics/tests/src/Unit/HelpTopicTwigTest.php @@ -104,7 +104,7 @@ protected function getTwigMock() { } /** - * Defines a fake template class to mock \Twig_TemplateWrapper. + * 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. @@ -129,7 +129,7 @@ public function __construct($body) { } /** - * Mocks the \Twig_TemplateWrapper render() method. + * Mocks the \Twig\TemplateWrapper render() method. * * @param array $context * (optional) Render context. diff --git a/core/modules/link/templates/link-formatter-link-separate.html.twig b/core/modules/link/templates/link-formatter-link-separate.html.twig index 469cd9aef8..932aae8ba9 100644 --- a/core/modules/link/templates/link-formatter-link-separate.html.twig +++ b/core/modules/link/templates/link-formatter-link-separate.html.twig @@ -14,7 +14,7 @@ * @ingroup themeable */ #} -{% spaceless %} +{% apply spaceless %} {{ title }} {{ link }} -{% endspaceless %} +{% endapply %} diff --git a/core/modules/system/templates/dropbutton-wrapper.html.twig b/core/modules/system/templates/dropbutton-wrapper.html.twig index 5f1aadf97f..62d2ef200d 100644 --- a/core/modules/system/templates/dropbutton-wrapper.html.twig +++ b/core/modules/system/templates/dropbutton-wrapper.html.twig @@ -12,11 +12,11 @@ */ #} {% if children %} - {% spaceless %} + {% apply spaceless %}
{{ children }}
- {% endspaceless %} + {% endapply %} {% endif %} diff --git a/core/modules/system/templates/indentation.html.twig b/core/modules/system/templates/indentation.html.twig index c7067fbe08..3cb4fa4f3c 100644 --- a/core/modules/system/templates/indentation.html.twig +++ b/core/modules/system/templates/indentation.html.twig @@ -11,4 +11,4 @@ * @ingroup themeable */ #} -{% for i in 1..size if size > 0 %}
 
{% endfor %} +{% if size > 0 %}{% for i in 1..size %}
 
{% endfor %}{% endif %} diff --git a/core/modules/system/templates/select.html.twig b/core/modules/system/templates/select.html.twig index 0b5c3d22c5..a86ed97f98 100644 --- a/core/modules/system/templates/select.html.twig +++ b/core/modules/system/templates/select.html.twig @@ -12,7 +12,7 @@ * @ingroup themeable */ #} -{% spaceless %} +{% apply spaceless %} {% for option in options %} {% if option.type == 'optgroup' %} @@ -26,4 +26,4 @@ {% endif %} {% endfor %} -{% endspaceless %} +{% endapply %} 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 2f51e721a6..753c90f2f4 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,13 +2,14 @@ namespace Drupal\twig_extension_test\TwigExtension; +use Twig\Extension\AbstractExtension; use Twig\TwigFilter; use Twig\TwigFunction; /** * A test Twig extension that adds a custom function and a custom filter. */ -class TestExtension extends \Twig_Extension { +class TestExtension extends AbstractExtension { /** * Generates a list of all Twig functions that this extension defines. 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 e9a05b0ad2..250950539f 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 @@ -2,12 +2,15 @@ namespace Drupal\twig_loader_test\Loader; +use Twig\Loader\ExistsLoaderInterface; +use Twig\Loader\LoaderInterface; +use Twig\Loader\SourceContextLoaderInterface; use Twig\Source; /** * A test Twig loader. */ -class TestLoader implements \Twig_LoaderInterface, \Twig_ExistsLoaderInterface, \Twig_SourceContextLoaderInterface { +class TestLoader implements LoaderInterface, ExistsLoaderInterface, SourceContextLoaderInterface { /** * {@inheritdoc} diff --git a/core/modules/system/tests/src/Functional/Theme/TwigTransTest.php b/core/modules/system/tests/src/Functional/Theme/TwigTransTest.php index c664c5dd73..75596f7ade 100644 --- a/core/modules/system/tests/src/Functional/Theme/TwigTransTest.php +++ b/core/modules/system/tests/src/Functional/Theme/TwigTransTest.php @@ -4,6 +4,7 @@ use Drupal\Core\Language\LanguageInterface; use Drupal\Tests\BrowserTestBase; +use Twig\Error\SyntaxError; /** * Tests Twig "trans" tags. @@ -107,7 +108,7 @@ public function testEmptyTwigTransTags() { $this->fail('{% trans %}{% endtrans %} did not throw an exception.'); } - catch (\Twig_Error_Syntax $e) { + catch (SyntaxError $e) { $this->assertTrue(strstr($e->getMessage(), '{% trans %} tag cannot be empty'), '{% trans %}{% endtrans %} threw the expected exception.'); } catch (\Exception $e) { diff --git a/core/modules/toolbar/templates/toolbar.html.twig b/core/modules/toolbar/templates/toolbar.html.twig index cb82774b86..64e29eabfa 100644 --- a/core/modules/toolbar/templates/toolbar.html.twig +++ b/core/modules/toolbar/templates/toolbar.html.twig @@ -29,7 +29,7 @@ {% set tray = trays[key] %} {{ tab.link }} - {% spaceless %} + {% apply spaceless %} {% if tray.label %} - {% endspaceless %} + {% endapply %} {% endfor %} diff --git a/core/modules/views/src/Plugin/views/field/FieldPluginBase.php b/core/modules/views/src/Plugin/views/field/FieldPluginBase.php index 8030f8860a..14539d7565 100644 --- a/core/modules/views/src/Plugin/views/field/FieldPluginBase.php +++ b/core/modules/views/src/Plugin/views/field/FieldPluginBase.php @@ -13,6 +13,7 @@ use Drupal\views\Render\ViewsRenderPipelineMarkup; use Drupal\views\ResultRow; use Drupal\views\ViewExecutable; +use Twig\Environment; /** * @defgroup views_field_handlers Views field handler plugins @@ -726,7 +727,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) { '#default_value' => $this->options['alter']['text'], // The tag list will be escaped. '#description' => $this->t('The text to display for this field. You may enter data from this view as per the "Replacement patterns" below. You may include Twig or the following allowed HTML tags: @tags', [ - '@twig_docs' => 'https://twig.symfony.com/doc/' . \Twig_Environment::MAJOR_VERSION . '.x', + '@twig_docs' => 'https://twig.symfony.com/doc/' . Environment::MAJOR_VERSION . '.x', '@tags' => '<' . implode('> <', Xss::getAdminTagList()) . '>', ]), '#states' => [ diff --git a/core/tests/Drupal/KernelTests/Core/Theme/TwigEnvironmentTest.php b/core/tests/Drupal/KernelTests/Core/Theme/TwigEnvironmentTest.php index bbc1253a3f..65f80c4054 100644 --- a/core/tests/Drupal/KernelTests/Core/Theme/TwigEnvironmentTest.php +++ b/core/tests/Drupal/KernelTests/Core/Theme/TwigEnvironmentTest.php @@ -9,6 +9,8 @@ use Drupal\Core\Template\TwigPhpStorageCache; use Drupal\KernelTests\KernelTestBase; use Symfony\Component\DependencyInjection\Definition; +use Twig\Environment; +use Twig\Error\LoaderError; /** * Tests the twig environment. @@ -106,7 +108,7 @@ public function testTemplateNotFoundException() { $environment->loadTemplate('this-template-does-not-exist.html.twig')->render([]); $this->fail('Did not throw an exception as expected.'); } - catch (\Twig_Error_Loader $e) { + catch (LoaderError $e) { $this->assertTrue(strpos($e->getMessage(), 'Template "this-template-does-not-exist.html.twig" is not defined') === 0); } } @@ -184,7 +186,7 @@ public function testCacheFilename() { public function register(ContainerBuilder $container) { parent::register($container); - $container->setDefinition('twig_loader__file_system', new Definition('Twig_Loader_Filesystem', [[sys_get_temp_dir()]])) + $container->setDefinition('twig_loader__file_system', new Definition('Twig\Loader\FilesystemLoader', [[sys_get_temp_dir()]])) ->addTag('twig.loader'); } @@ -216,7 +218,7 @@ public function testTemplateInvalidation() { // Manually change $templateClassPrefix to force a different template // classname, as the other class is still loaded. This wouldn't be a problem // on a real site where you reload the page. - $reflection = new \ReflectionClass(\Twig_Environment::class); + $reflection = new \ReflectionClass(Environment::class); $property_reflection = $reflection->getProperty('templateClassPrefix'); $property_reflection->setAccessible(TRUE); $property_reflection->setValue($environment, 'otherPrefix'); diff --git a/core/tests/Drupal/Tests/Core/Template/AttributeTest.php b/core/tests/Drupal/Tests/Core/Template/AttributeTest.php index 911b6e150d..5dd35aeb55 100644 --- a/core/tests/Drupal/Tests/Core/Template/AttributeTest.php +++ b/core/tests/Drupal/Tests/Core/Template/AttributeTest.php @@ -10,6 +10,7 @@ use Drupal\Core\Template\Loader\StringLoader; use Drupal\Tests\UnitTestCase; use Drupal\Component\Render\MarkupInterface; +use Twig\Environment; /** * @coversDefaultClass \Drupal\Core\Template\Attribute @@ -265,7 +266,7 @@ public function testChainAddRemoveClasses() { */ public function testTwigAddRemoveClasses($template, $expected, $seed_attributes = []) { $loader = new StringLoader(); - $twig = new \Twig_Environment($loader); + $twig = new Environment($loader); $data = ['attributes' => new Attribute($seed_attributes)]; $result = $twig->createTemplate($template)->render($data); $this->assertEquals($expected, $result); diff --git a/core/tests/Drupal/Tests/Core/Template/TwigExtensionTest.php b/core/tests/Drupal/Tests/Core/Template/TwigExtensionTest.php index 87d5397b31..a463601cf4 100644 --- a/core/tests/Drupal/Tests/Core/Template/TwigExtensionTest.php +++ b/core/tests/Drupal/Tests/Core/Template/TwigExtensionTest.php @@ -10,6 +10,11 @@ use Drupal\Core\Template\TwigExtension; use Drupal\Core\Url; use Drupal\Tests\UnitTestCase; +use Twig\Environment; +use Twig\Loader\ArrayLoader; +use Twig\Loader\FilesystemLoader; +use Twig\Node\Expression\FilterExpression; +use Twig\Source; /** * Tests the twig extension. @@ -75,8 +80,8 @@ public function setUp() { * @dataProvider providerTestEscaping */ public function testEscaping($template, $expected) { - $loader = new \Twig_Loader_Filesystem(); - $twig = new \Twig_Environment($loader, [ + $loader = new FilesystemLoader(); + $twig = new Environment($loader, [ 'debug' => TRUE, 'cache' => FALSE, 'autoescape' => 'html', @@ -85,11 +90,11 @@ public function testEscaping($template, $expected) { $twig->addExtension($this->systemUnderTest); $name = '__string_template_test__'; - $nodes = $twig->parse($twig->tokenize(new \Twig_Source($template, $name))); + $nodes = $twig->parse($twig->tokenize(new Source($template, $name))); $this->assertSame($expected, $nodes->getNode('body') ->getNode(0) - ->getNode('expr') instanceof \Twig_Node_Expression_Filter); + ->getNode('expr') instanceof FilterExpression); } /** @@ -138,7 +143,7 @@ public function testActiveTheme() { ->willReturn($active_theme); $loader = new StringLoader(); - $twig = new \Twig_Environment($loader); + $twig = new Environment($loader); $twig->addExtension($this->systemUnderTest); $result = $twig->render('{{ active_theme() }}'); $this->assertEquals('test_theme', $result); @@ -155,7 +160,7 @@ public function testFormatDate() { })); $loader = new StringLoader(); - $twig = new \Twig_Environment($loader); + $twig = new Environment($loader); $twig->addExtension($this->systemUnderTest); $timestamp = strtotime('1978-11-19'); $result = $twig->render('{{ time|format_date("html_date") }}', ['time' => $timestamp]); @@ -178,7 +183,7 @@ public function testActiveThemePath() { ->willReturn($active_theme); $loader = new StringLoader(); - $twig = new \Twig_Environment($loader); + $twig = new Environment($loader); $twig->addExtension($this->systemUnderTest); $result = $twig->render('{{ active_theme_path() }}'); $this->assertEquals('foo/bar', $result); @@ -190,8 +195,8 @@ public function testActiveThemePath() { * @covers ::escapeFilter */ public function testSafeStringEscaping() { - $loader = new \Twig_Loader_Filesystem(); - $twig = new \Twig_Environment($loader, [ + $loader = new FilesystemLoader(); + $twig = new Environment($loader, [ 'debug' => TRUE, 'cache' => FALSE, 'autoescape' => 'html', @@ -275,8 +280,8 @@ public function providerTestRenderVar() { * @covers ::bubbleArgMetadata */ public function testEscapeWithGeneratedLink() { - $loader = new \Twig_Loader_Filesystem(); - $twig = new \Twig_Environment($loader, [ + $loader = new FilesystemLoader(); + $twig = new Environment($loader, [ 'debug' => TRUE, 'cache' => FALSE, 'autoescape' => 'html', @@ -335,8 +340,8 @@ public function testRenderVarWithGeneratedLink() { */ public function testCreateAttribute() { $name = '__string_template_test_1__'; - $loader = new \Twig_Loader_Array([$name => "{% for iteration in iterations %}{% endfor %}"]); - $twig = new \Twig_Environment($loader); + $loader = new ArrayLoader([$name => "{% for iteration in iterations %}{% endfor %}"]); + $twig = new Environment($loader); $twig->addExtension($this->systemUnderTest); $iterations = [ @@ -350,7 +355,7 @@ public function testCreateAttribute() { // Test default creation of empty attribute object and using its method. $name = '__string_template_test_2__'; - $loader = new \Twig_Loader_Array([$name => ""]); + $loader = new ArrayLoader([$name => ""]); $twig->setLoader($loader); $result = $twig->render($name); $expected = '
'; diff --git a/core/tests/Drupal/Tests/Core/Template/TwigSandboxTest.php b/core/tests/Drupal/Tests/Core/Template/TwigSandboxTest.php index 019acbe1dc..e1bbd3d330 100644 --- a/core/tests/Drupal/Tests/Core/Template/TwigSandboxTest.php +++ b/core/tests/Drupal/Tests/Core/Template/TwigSandboxTest.php @@ -11,6 +11,9 @@ use Drupal\Core\Template\TwigSandboxPolicy; use Drupal\Core\Template\Loader\StringLoader; use Drupal\Tests\UnitTestCase; +use Twig\Environment; +use Twig\Extension\SandboxExtension; +use Twig\Sandbox\SecurityError; /** * Tests the twig sandbox policy. @@ -24,7 +27,7 @@ class TwigSandboxTest extends UnitTestCase { /** * The Twig environment loaded with the sandbox extension. * - * @var \Twig_Environment + * @var \Twig\Environment */ protected $twig; @@ -35,9 +38,9 @@ protected function setUp() { parent::setUp(); $loader = new StringLoader(); - $this->twig = new \Twig_Environment($loader); + $this->twig = new Environment($loader); $policy = new TwigSandboxPolicy(); - $sandbox = new \Twig_Extension_Sandbox($policy, TRUE); + $sandbox = new SandboxExtension($policy, TRUE); $this->twig->addExtension($sandbox); } @@ -48,7 +51,7 @@ protected function setUp() { */ public function testEntityDangerousMethods($template) { $entity = $this->createMock('Drupal\Core\Entity\EntityInterface'); - $this->expectException(\Twig_Sandbox_SecurityError::class); + $this->expectException(SecurityError::class); $this->twig->render($template, ['entity' => $entity]); } diff --git a/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php b/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php index 46493f2979..9bdbc4932b 100644 --- a/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php +++ b/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php @@ -193,6 +193,9 @@ public static function getSkippedDeprecations() { 'The "core/matchmedia" asset library is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. See https://www.drupal.org/node/3086653', 'The "core/matchmedia.addListener" asset library is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. See https://www.drupal.org/node/3086653', 'The "core/classList" asset library is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use the the native browser implementation instead. See https://www.drupal.org/node/3089511', + // The following deprecation is listed for Twig2 compatibility when unit + // testing using \Symfony\Component\ErrorHandler\DebugClassLoader. + 'The "Twig\Environment::getTemplateClass()" method is considered internal. It may change without further notice. You should not extend it from "Drupal\Core\Template\TwigEnvironment".', ]; } diff --git a/core/themes/claro/templates/admin/indentation.html.twig b/core/themes/claro/templates/admin/indentation.html.twig index 7618abab8a..9b22d3b51d 100644 --- a/core/themes/claro/templates/admin/indentation.html.twig +++ b/core/themes/claro/templates/admin/indentation.html.twig @@ -9,7 +9,7 @@ * - size: Optional. The number of indentations to create. */ #} -{% for i in 1..size if size > 0 %}
+{% if size > 0 %}{% for i in 1..size %}
-
{% endfor %} +
{% endfor %}{% endif %} diff --git a/core/themes/claro/templates/form/input.html.twig b/core/themes/claro/templates/form/input.html.twig index f8a6cab610..12697039f4 100644 --- a/core/themes/claro/templates/form/input.html.twig +++ b/core/themes/claro/templates/form/input.html.twig @@ -11,7 +11,7 @@ * @see claro_preprocess_input() */ #} -{% spaceless %} +{% apply spaceless %} {% if autocomplete_message %}
@@ -21,4 +21,4 @@ {% else %} {{ children }} {% endif %} -{% endspaceless %} +{% endapply %} diff --git a/core/themes/claro/templates/pager.html.twig b/core/themes/claro/templates/pager.html.twig index e59cdb3600..e91a3ff031 100644 --- a/core/themes/claro/templates/pager.html.twig +++ b/core/themes/claro/templates/pager.html.twig @@ -40,7 +40,7 @@
    {# Print first item if we are not on the first page. #} {% if items.first %} - {% spaceless %} + {% apply spaceless %}
  • {{ 'First page'|t }} @@ -49,12 +49,12 @@
  • - {% endspaceless %} + {% endapply %} {% endif %} {# Print previous item if we are not on the first page. #} {% if items.previous %} - {% spaceless %} + {% apply spaceless %}
  • - {% endspaceless %} + {% endapply %} {% endif %} {# Add an ellipsis if there are further previous pages. #} @@ -73,7 +73,7 @@ {# Now generate the actual pager piece. #} {% for key, item in items.pages %} - {% spaceless %} + {% apply spaceless %}
  • {% if current == key %} {% set title = 'Current page'|t %} @@ -87,7 +87,7 @@ {{ key }}
  • - {% endspaceless %} + {% endapply %} {% endfor %} {# Add an ellipsis if there are further next pages. #} @@ -97,7 +97,7 @@ {# Print next item if we are not on the last page. #} {% if items.next %} - {% spaceless %} + {% apply spaceless %}
  • - {% endspaceless %} + {% endapply %} {% endif %} {# Print last item if we are not on the last page. #} {% if items.last %} - {% spaceless %} + {% apply spaceless %}
  • {{ 'Last page'|t }} @@ -120,7 +120,7 @@
  • - {% endspaceless %} + {% endapply %} {% endif %}
diff --git a/core/themes/claro/templates/views/views-mini-pager.html.twig b/core/themes/claro/templates/views/views-mini-pager.html.twig index 7f429be4c5..c84eb710c9 100644 --- a/core/themes/claro/templates/views/views-mini-pager.html.twig +++ b/core/themes/claro/templates/views/views-mini-pager.html.twig @@ -22,13 +22,13 @@ {{ 'Pagination'|t }} {% if items.previous %} - {% spaceless %} + {% apply spaceless %}
  • {{ 'Previous page'|t }}
  • - {% endspaceless %} + {% endapply %} {% endif %} {% if items.current %} @@ -41,13 +41,13 @@ {% endif %} {% if items.next %} - {% spaceless %} + {% apply spaceless %}
  • {{ 'Next page'|t }}
  • - {% endspaceless %} + {% endapply %} {% endif %} diff --git a/core/themes/classy/templates/dataset/forum-list.html.twig b/core/themes/classy/templates/dataset/forum-list.html.twig index ce610bb49b..d8523f1598 100644 --- a/core/themes/classy/templates/dataset/forum-list.html.twig +++ b/core/themes/classy/templates/dataset/forum-list.html.twig @@ -52,7 +52,7 @@ depth this forum resides at. This will allow us to use CSS left-margin for indenting. #} - {% for i in 1..forum.depth if forum.depth > 0 %}
    {% endfor %} + {% if forum.depth > 0 %}{% for i in 1..forum.depth %}
    {% endfor %}{% endif %}
    {{ forum.icon_title }}
    @@ -60,7 +60,7 @@ {% if forum.description.value %}
    {{ forum.description.value }}
    {% endif %} - {% for i in 1..forum.depth if forum.depth > 0 %}
    {% endfor %} + {% if forum.depth > 0 %}{% for i in 1..forum.depth %}
    {% endfor %}{% endif %} {% if forum.is_container == false %} diff --git a/core/themes/classy/templates/field/link-formatter-link-separate.html.twig b/core/themes/classy/templates/field/link-formatter-link-separate.html.twig index cb94264c66..52c8d29a77 100644 --- a/core/themes/classy/templates/field/link-formatter-link-separate.html.twig +++ b/core/themes/classy/templates/field/link-formatter-link-separate.html.twig @@ -12,11 +12,11 @@ * @see template_preprocess_link_formatter_link_separate() */ #} -{% spaceless %} +{% apply spaceless %} -{% endspaceless %} +{% endapply %} diff --git a/core/themes/classy/templates/form/dropbutton-wrapper.html.twig b/core/themes/classy/templates/form/dropbutton-wrapper.html.twig index ca68716db2..a2bdc21d67 100644 --- a/core/themes/classy/templates/form/dropbutton-wrapper.html.twig +++ b/core/themes/classy/templates/form/dropbutton-wrapper.html.twig @@ -10,11 +10,11 @@ */ #} {% if children %} - {% spaceless %} + {% apply spaceless %}
    {{ children }}
    - {% endspaceless %} + {% endapply %} {% endif %} diff --git a/core/themes/classy/templates/form/select.html.twig b/core/themes/classy/templates/form/select.html.twig index 8af42616f7..9c8a97c058 100644 --- a/core/themes/classy/templates/form/select.html.twig +++ b/core/themes/classy/templates/form/select.html.twig @@ -10,7 +10,7 @@ * @see template_preprocess_select() */ #} -{% spaceless %} +{% apply spaceless %} {% for option in options %} {% if option.type == 'optgroup' %} @@ -24,4 +24,4 @@ {% endif %} {% endfor %} -{% endspaceless %} +{% endapply %} diff --git a/core/themes/classy/templates/layout/book-export-html.html.twig b/core/themes/classy/templates/layout/book-export-html.html.twig index ea33648d38..b7525f7efa 100644 --- a/core/themes/classy/templates/layout/book-export-html.html.twig +++ b/core/themes/classy/templates/layout/book-export-html.html.twig @@ -34,12 +34,12 @@ to be exported as printer-friendly HTML. #} - {% for i in 1..depth-1 if depth > 1 %} + {% if depth > 1 %}{% for i in 1..depth-1 %}
    - {% endfor %} + {% endfor %}{% endif %} {{ contents }} - {% for i in 1..depth-1 if depth > 1 %} + {% if depth > 1 %}{% for i in 1..depth-1 %}
    - {% endfor %} + {% endfor %}{% endif %} diff --git a/core/themes/classy/templates/navigation/toolbar.html.twig b/core/themes/classy/templates/navigation/toolbar.html.twig index 20f12d48b2..5ef3ffad3a 100644 --- a/core/themes/classy/templates/navigation/toolbar.html.twig +++ b/core/themes/classy/templates/navigation/toolbar.html.twig @@ -27,7 +27,7 @@ {% set tray = trays[key] %} {{ tab.link }} - {% spaceless %} + {% apply spaceless %} {% if tray.label %}
    - {% endspaceless %} + {% endapply %} {% endfor %} diff --git a/core/themes/engines/twig/twig.engine b/core/themes/engines/twig/twig.engine index a3d2a5e26d..589b5263b4 100644 --- a/core/themes/engines/twig/twig.engine +++ b/core/themes/engines/twig/twig.engine @@ -8,6 +8,7 @@ use Drupal\Component\Utility\Html; use Drupal\Core\Render\Markup; use Drupal\Core\Extension\Extension; +use Twig\Error\RuntimeError; /** * Implements hook_theme(). @@ -52,7 +53,7 @@ function twig_init(Extension $theme) { * The output generated by the template, plus any debug information. */ function twig_render_template($template_file, array $variables) { - /** @var \Twig_Environment $twig_service */ + /** @var \Twig\Environment $twig_service */ $twig_service = \Drupal::service('twig'); $output = [ 'debug_prefix' => '', @@ -63,10 +64,10 @@ function twig_render_template($template_file, array $variables) { try { $output['rendered_markup'] = $twig_service->loadTemplate($template_file)->render($variables); } - catch (\Twig_Error_Runtime $e) { + catch (RuntimeError $e) { // In case there is a previous exception, re-throw the previous exception, // so that the original exception is shown, rather than - // \Twig_Template::displayWithErrorHandling()'s exception. + // \Twig\Template::displayWithErrorHandling()'s exception. $previous_exception = $e->getPrevious(); if ($previous_exception) { throw $previous_exception; diff --git a/core/themes/stable/templates/admin/block-content-add-list.html.twig b/core/themes/stable/templates/admin/block-content-add-list.html.twig index ae99d1f834..23717f2fac 100644 --- a/core/themes/stable/templates/admin/block-content-add-list.html.twig +++ b/core/themes/stable/templates/admin/block-content-add-list.html.twig @@ -12,11 +12,11 @@ * @see template_preprocess_block_content_add_list() */ #} -{% spaceless %} +{% apply spaceless %}
    {% for type in types %}
    {{ type.link }}
    {{ type.description }}
    {% endfor %}
    -{% endspaceless %} +{% endapply %} diff --git a/core/themes/stable/templates/admin/ckeditor-settings-toolbar.html.twig b/core/themes/stable/templates/admin/ckeditor-settings-toolbar.html.twig index 392c494301..c5e87e0fb9 100644 --- a/core/themes/stable/templates/admin/ckeditor-settings-toolbar.html.twig +++ b/core/themes/stable/templates/admin/ckeditor-settings-toolbar.html.twig @@ -11,7 +11,7 @@ * @see template_preprocess_ckeditor_settings_toolbar() */ #} -{% spaceless %} +{% apply spaceless %}
    {{ 'Toolbar configuration'|t }}
    @@ -70,4 +70,4 @@
    -{% endspaceless %} +{% endapply %} diff --git a/core/themes/stable/templates/admin/indentation.html.twig b/core/themes/stable/templates/admin/indentation.html.twig index c8244b5112..591933de07 100644 --- a/core/themes/stable/templates/admin/indentation.html.twig +++ b/core/themes/stable/templates/admin/indentation.html.twig @@ -9,4 +9,4 @@ * - size: Optional. The number of indentations to create. */ #} -{% for i in 1..size if size > 0 %}
     
    {% endfor %} +{% if size > 0 %}{% for i in 1..size %}
     
    {% endfor %}{% endif %} diff --git a/core/themes/stable/templates/dataset/forum-list.html.twig b/core/themes/stable/templates/dataset/forum-list.html.twig index 3de920ae1d..892c59156a 100644 --- a/core/themes/stable/templates/dataset/forum-list.html.twig +++ b/core/themes/stable/templates/dataset/forum-list.html.twig @@ -48,7 +48,7 @@ depth this forum resides at. This will allow us to use CSS left-margin for indenting. #} - {% for i in 1..forum.depth if forum.depth > 0 %}
    {% endfor %} + {% if forum.depth > 0 %}{% for i in 1..forum.depth %}
    {% endfor %}{% endif %}
    {{ forum.icon_title }}
    @@ -56,7 +56,7 @@ {% if forum.description.value %}
    {{ forum.description.value }}
    {% endif %} - {% for i in 1..forum.depth if forum.depth > 0 %}
    {% endfor %} + {% if forum.depth > 0 %}{% for i in 1..forum.depth %}
    {% endfor %}{% endif %} {% if forum.is_container == false %} diff --git a/core/themes/stable/templates/field/link-formatter-link-separate.html.twig b/core/themes/stable/templates/field/link-formatter-link-separate.html.twig index 0aa1b4a11c..b75457b412 100644 --- a/core/themes/stable/templates/field/link-formatter-link-separate.html.twig +++ b/core/themes/stable/templates/field/link-formatter-link-separate.html.twig @@ -12,7 +12,7 @@ * @see template_preprocess_link_formatter_link_separate() */ #} -{% spaceless %} +{% apply spaceless %} {{ title }} {{ link }} -{% endspaceless %} +{% endapply %} diff --git a/core/themes/stable/templates/form/dropbutton-wrapper.html.twig b/core/themes/stable/templates/form/dropbutton-wrapper.html.twig index ca68716db2..a2bdc21d67 100644 --- a/core/themes/stable/templates/form/dropbutton-wrapper.html.twig +++ b/core/themes/stable/templates/form/dropbutton-wrapper.html.twig @@ -10,11 +10,11 @@ */ #} {% if children %} - {% spaceless %} + {% apply spaceless %}
    {{ children }}
    - {% endspaceless %} + {% endapply %} {% endif %} diff --git a/core/themes/stable/templates/form/select.html.twig b/core/themes/stable/templates/form/select.html.twig index 3150bdcb36..28c355b3cd 100644 --- a/core/themes/stable/templates/form/select.html.twig +++ b/core/themes/stable/templates/form/select.html.twig @@ -10,7 +10,7 @@ * @see template_preprocess_select() */ #} -{% spaceless %} +{% apply spaceless %} {% for option in options %} {% if option.type == 'optgroup' %} @@ -24,4 +24,4 @@ {% endif %} {% endfor %} -{% endspaceless %} +{% endapply %} diff --git a/core/themes/stable/templates/layout/book-export-html.html.twig b/core/themes/stable/templates/layout/book-export-html.html.twig index 17ac1bc248..86bb37ed22 100644 --- a/core/themes/stable/templates/layout/book-export-html.html.twig +++ b/core/themes/stable/templates/layout/book-export-html.html.twig @@ -34,12 +34,12 @@ to be exported as printer-friendly HTML. #} - {% for i in 1..depth-1 if depth > 1 %} + {% if depth > 1 %}{% for i in 1..depth-1 %}
    - {% endfor %} + {% endfor %}{% endif %} {{ contents }} - {% for i in 1..depth-1 if depth > 1 %} + {% if depth > 1 %}{% for i in 1..depth-1 %}
    - {% endfor %} + {% endfor %}{% endif %} diff --git a/core/themes/stable/templates/navigation/toolbar.html.twig b/core/themes/stable/templates/navigation/toolbar.html.twig index 497bc781e5..efbe00c2db 100644 --- a/core/themes/stable/templates/navigation/toolbar.html.twig +++ b/core/themes/stable/templates/navigation/toolbar.html.twig @@ -27,7 +27,7 @@ {% set tray = trays[key] %} {{ tab.link }} - {% spaceless %} + {% apply spaceless %} {% if tray.label %} - {% endspaceless %} + {% endapply %} {% endfor %}