diff --git a/composer.lock b/composer.lock index 48b3ba21a6..3928c319bc 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,6 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "1167766f8eca494239cc8a1baa1ea6bb", "content-hash": "0cfc95231ad5eb3f8d306e45c9cc92d9", "packages": [ { @@ -48,7 +47,7 @@ "cors", "stack" ], - "time": "2016-08-01 12:05:04" + "time": "2016-08-01T12:05:04+00:00" }, { "name": "composer/installers", @@ -143,7 +142,7 @@ "zend", "zikula" ], - "time": "2015-02-18 17:17:01" + "time": "2015-02-18T17:17:01+00:00" }, { "name": "composer/semver", @@ -204,7 +203,7 @@ "validation", "versioning" ], - "time": "2015-09-21 09:42:36" + "time": "2015-09-21T09:42:36+00:00" }, { "name": "doctrine/annotations", @@ -272,7 +271,7 @@ "docblock", "parser" ], - "time": "2015-08-31 12:32:49" + "time": "2015-08-31T12:32:49+00:00" }, { "name": "doctrine/cache", @@ -342,7 +341,7 @@ "cache", "caching" ], - "time": "2015-08-31 12:36:41" + "time": "2015-08-31T12:36:41+00:00" }, { "name": "doctrine/collections", @@ -408,7 +407,7 @@ "collections", "iterator" ], - "time": "2015-04-14 22:21:58" + "time": "2015-04-14T22:21:58+00:00" }, { "name": "doctrine/common", @@ -481,7 +480,7 @@ "persistence", "spl" ], - "time": "2015-08-31 13:00:22" + "time": "2015-08-31T13:00:22+00:00" }, { "name": "doctrine/inflector", @@ -548,7 +547,7 @@ "singularize", "string" ], - "time": "2014-12-20 21:24:13" + "time": "2014-12-20T21:24:13+00:00" }, { "name": "doctrine/lexer", @@ -602,7 +601,7 @@ "lexer", "parser" ], - "time": "2014-09-09 13:34:57" + "time": "2014-09-09T13:34:57+00:00" }, { "name": "easyrdf/easyrdf", @@ -664,7 +663,7 @@ "rdfa", "sparql" ], - "time": "2015-02-27 09:45:49" + "time": "2015-02-27T09:45:49+00:00" }, { "name": "egulias/email-validator", @@ -717,7 +716,7 @@ "validation", "validator" ], - "time": "2015-06-22 21:07:51" + "time": "2015-06-22T21:07:51+00:00" }, { "name": "guzzlehttp/guzzle", @@ -779,7 +778,7 @@ "rest", "web service" ], - "time": "2016-07-15 17:22:37" + "time": "2016-07-15T17:22:37+00:00" }, { "name": "guzzlehttp/promises", @@ -830,7 +829,7 @@ "keywords": [ "promise" ], - "time": "2016-05-18 16:56:05" + "time": "2016-05-18T16:56:05+00:00" }, { "name": "guzzlehttp/psr7", @@ -888,7 +887,7 @@ "stream", "uri" ], - "time": "2016-06-24 23:00:38" + "time": "2016-06-24T23:00:38+00:00" }, { "name": "ircmaxell/password-compat", @@ -930,7 +929,7 @@ "hashing", "password" ], - "time": "2014-11-20 16:49:30" + "time": "2014-11-20T16:49:30+00:00" }, { "name": "masterminds/html5", @@ -995,7 +994,7 @@ "serializer", "xml" ], - "time": "2016-05-10 14:11:45" + "time": "2016-05-10T14:11:45+00:00" }, { "name": "paragonie/random_compat", @@ -1043,7 +1042,7 @@ "pseudorandom", "random" ], - "time": "2016-04-03 06:00:07" + "time": "2016-04-03T06:00:07+00:00" }, { "name": "psr/http-message", @@ -1092,7 +1091,7 @@ "request", "response" ], - "time": "2015-05-04 20:22:00" + "time": "2015-05-04T20:22:00+00:00" }, { "name": "psr/log", @@ -1130,7 +1129,7 @@ "psr", "psr-3" ], - "time": "2012-12-21 11:40:51" + "time": "2012-12-21T11:40:51+00:00" }, { "name": "stack/builder", @@ -1179,7 +1178,7 @@ "keywords": [ "stack" ], - "time": "2016-06-02 06:58:42" + "time": "2016-06-02T06:58:42+00:00" }, { "name": "symfony-cmf/routing", @@ -1238,7 +1237,7 @@ "database", "routing" ], - "time": "2016-03-31 09:11:39" + "time": "2016-03-31T09:11:39+00:00" }, { "name": "symfony/class-loader", @@ -1291,7 +1290,7 @@ ], "description": "Symfony ClassLoader Component", "homepage": "https://symfony.com", - "time": "2016-11-29 08:25:54" + "time": "2016-11-29T08:25:54+00:00" }, { "name": "symfony/console", @@ -1352,7 +1351,7 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2016-12-06 11:59:35" + "time": "2016-12-06T11:59:35+00:00" }, { "name": "symfony/debug", @@ -1409,7 +1408,7 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2016-11-15 12:53:17" + "time": "2016-11-15T12:53:17+00:00" }, { "name": "symfony/dependency-injection", @@ -1472,7 +1471,7 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2016-12-08 14:41:31" + "time": "2016-12-08T14:41:31+00:00" }, { "name": "symfony/dom-crawler", @@ -1528,7 +1527,7 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", - "time": "2016-12-10 14:24:35" + "time": "2016-12-10T14:24:35+00:00" }, { "name": "symfony/event-dispatcher", @@ -1588,7 +1587,7 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2016-10-13 01:43:15" + "time": "2016-10-13T01:43:15+00:00" }, { "name": "symfony/http-foundation", @@ -1643,7 +1642,7 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2016-11-27 04:20:28" + "time": "2016-11-27T04:20:28+00:00" }, { "name": "symfony/http-kernel", @@ -1725,7 +1724,7 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2016-12-13 12:16:15" + "time": "2016-12-13T12:16:15+00:00" }, { "name": "symfony/polyfill-apcu", @@ -1778,7 +1777,7 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/polyfill-iconv", @@ -1837,7 +1836,7 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -1896,7 +1895,7 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/polyfill-php54", @@ -1954,7 +1953,7 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/polyfill-php55", @@ -2010,7 +2009,7 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/process", @@ -2059,7 +2058,7 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2016-11-24 00:43:03" + "time": "2016-11-24T00:43:03+00:00" }, { "name": "symfony/psr-http-message-bridge", @@ -2113,7 +2112,7 @@ "http-message", "psr-7" ], - "time": "2015-05-29 17:57:12" + "time": "2015-05-29T17:57:12+00:00" }, { "name": "symfony/routing", @@ -2188,7 +2187,7 @@ "uri", "url" ], - "time": "2016-11-25 12:26:42" + "time": "2016-11-25T12:26:42+00:00" }, { "name": "symfony/serializer", @@ -2252,7 +2251,7 @@ ], "description": "Symfony Serializer Component", "homepage": "https://symfony.com", - "time": "2016-11-03 07:52:58" + "time": "2016-11-03T07:52:58+00:00" }, { "name": "symfony/translation", @@ -2316,7 +2315,7 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2016-11-18 21:10:01" + "time": "2016-11-18T21:10:01+00:00" }, { "name": "symfony/validator", @@ -2389,7 +2388,7 @@ ], "description": "Symfony Validator Component", "homepage": "https://symfony.com", - "time": "2016-12-08 15:59:39" + "time": "2016-12-08T15:59:39+00:00" }, { "name": "symfony/yaml", @@ -2438,33 +2437,34 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2016-11-14 16:15:57" + "time": "2016-11-14T16:15:57+00:00" }, { "name": "twig/twig", - "version": "v1.25.0", + "version": "v2.0.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "f16a634ab08d87e520da5671ec52153d627f10f6" + "reference": "2a86dde1288d7270169083d0e078dc7ebe0f48b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/f16a634ab08d87e520da5671ec52153d627f10f6", - "reference": "f16a634ab08d87e520da5671ec52153d627f10f6", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/2a86dde1288d7270169083d0e078dc7ebe0f48b6", + "reference": "2a86dde1288d7270169083d0e078dc7ebe0f48b6", "shasum": "" }, "require": { - "php": ">=5.2.7" + "php": "^7.0", + "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { "symfony/debug": "~2.7", - "symfony/phpunit-bridge": "~2.7" + "symfony/phpunit-bridge": "~3.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.25-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -2499,7 +2499,7 @@ "keywords": [ "templating" ], - "time": "2016-09-21 23:05:12" + "time": "2017-01-05T17:12:02+00:00" }, { "name": "wikimedia/composer-merge-plugin", @@ -2548,7 +2548,7 @@ } ], "description": "Composer plugin to merge multiple composer.json files", - "time": "2016-03-08 17:11:37" + "time": "2016-03-08T17:11:37+00:00" }, { "name": "zendframework/zend-diactoros", @@ -2598,7 +2598,7 @@ "psr", "psr-7" ], - "time": "2015-08-10 20:04:20" + "time": "2015-08-10T20:04:20+00:00" }, { "name": "zendframework/zend-escaper", @@ -2642,7 +2642,7 @@ "escaper", "zf2" ], - "time": "2015-06-03 14:05:37" + "time": "2015-06-03T14:05:37+00:00" }, { "name": "zendframework/zend-feed", @@ -2701,7 +2701,7 @@ "feed", "zf2" ], - "time": "2015-08-04 21:39:18" + "time": "2015-08-04T21:39:18+00:00" }, { "name": "zendframework/zend-hydrator", @@ -2757,7 +2757,7 @@ "hydrator", "zf2" ], - "time": "2015-09-17 14:06:43" + "time": "2015-09-17T14:06:43+00:00" }, { "name": "zendframework/zend-stdlib", @@ -2815,7 +2815,7 @@ "stdlib", "zf2" ], - "time": "2015-09-25 04:06:33" + "time": "2015-09-25T04:06:33+00:00" } ], "packages-dev": [ @@ -2875,7 +2875,7 @@ "testing", "web" ], - "time": "2016-10-17 08:31:38" + "time": "2016-10-17T08:31:38+00:00" }, { "name": "behat/mink-browserkit-driver", @@ -2931,7 +2931,7 @@ "browser", "testing" ], - "time": "2016-03-05 08:59:47" + "time": "2016-03-05T08:59:47+00:00" }, { "name": "behat/mink-goutte-driver", @@ -2986,7 +2986,7 @@ "headless", "testing" ], - "time": "2016-03-05 09:04:22" + "time": "2016-03-05T09:04:22+00:00" }, { "name": "doctrine/instantiator", @@ -3040,7 +3040,7 @@ "constructor", "instantiate" ], - "time": "2015-06-14 21:17:01" + "time": "2015-06-14T21:17:01+00:00" }, { "name": "fabpot/goutte", @@ -3089,7 +3089,7 @@ "keywords": [ "scraper" ], - "time": "2015-11-05 12:58:44" + "time": "2015-11-05T12:58:44+00:00" }, { "name": "jcalderonzumba/gastonjs", @@ -3146,7 +3146,7 @@ "headless", "phantomjs" ], - "time": "2016-01-18 09:21:03" + "time": "2016-01-18T09:21:03+00:00" }, { "name": "jcalderonzumba/mink-phantomjs-driver", @@ -3207,7 +3207,7 @@ "phantomjs", "testing" ], - "time": "2015-12-04 13:55:02" + "time": "2015-12-04T13:55:02+00:00" }, { "name": "mikey179/vfsStream", @@ -3253,7 +3253,7 @@ ], "description": "Virtual file system to mock the real file system in unit tests.", "homepage": "http://vfs.bovigo.org/", - "time": "2015-10-06 16:59:57" + "time": "2015-10-06T16:59:57+00:00" }, { "name": "phpdocumentor/reflection-docblock", @@ -3302,7 +3302,7 @@ "email": "mike.vanriel@naenius.com" } ], - "time": "2015-02-03 12:10:50" + "time": "2015-02-03T12:10:50+00:00" }, { "name": "phpspec/prophecy", @@ -3362,7 +3362,7 @@ "spy", "stub" ], - "time": "2015-08-13 10:07:40" + "time": "2015-08-13T10:07:40+00:00" }, { "name": "phpunit/php-code-coverage", @@ -3424,7 +3424,7 @@ "testing", "xunit" ], - "time": "2015-10-06 15:47:00" + "time": "2015-10-06T15:47:00+00:00" }, { "name": "phpunit/php-file-iterator", @@ -3471,7 +3471,7 @@ "filesystem", "iterator" ], - "time": "2015-06-21 13:08:43" + "time": "2015-06-21T13:08:43+00:00" }, { "name": "phpunit/php-text-template", @@ -3512,7 +3512,7 @@ "keywords": [ "template" ], - "time": "2015-06-21 13:50:34" + "time": "2015-06-21T13:50:34+00:00" }, { "name": "phpunit/php-timer", @@ -3553,7 +3553,7 @@ "keywords": [ "timer" ], - "time": "2015-06-21 08:01:12" + "time": "2015-06-21T08:01:12+00:00" }, { "name": "phpunit/php-token-stream", @@ -3602,7 +3602,7 @@ "keywords": [ "tokenizer" ], - "time": "2015-09-15 10:49:45" + "time": "2015-09-15T10:49:45+00:00" }, { "name": "phpunit/phpunit", @@ -3674,7 +3674,7 @@ "testing", "xunit" ], - "time": "2016-07-21 06:48:14" + "time": "2016-07-21T06:48:14+00:00" }, { "name": "phpunit/phpunit-mock-objects", @@ -3730,7 +3730,7 @@ "mock", "xunit" ], - "time": "2015-10-02 06:51:40" + "time": "2015-10-02T06:51:40+00:00" }, { "name": "sebastian/comparator", @@ -3794,7 +3794,7 @@ "compare", "equality" ], - "time": "2015-07-26 15:48:44" + "time": "2015-07-26T15:48:44+00:00" }, { "name": "sebastian/diff", @@ -3846,7 +3846,7 @@ "keywords": [ "diff" ], - "time": "2015-02-22 15:13:53" + "time": "2015-02-22T15:13:53+00:00" }, { "name": "sebastian/environment", @@ -3896,7 +3896,7 @@ "environment", "hhvm" ], - "time": "2015-08-03 06:14:51" + "time": "2015-08-03T06:14:51+00:00" }, { "name": "sebastian/exporter", @@ -3962,7 +3962,7 @@ "export", "exporter" ], - "time": "2015-06-21 07:55:53" + "time": "2015-06-21T07:55:53+00:00" }, { "name": "sebastian/global-state", @@ -4013,7 +4013,7 @@ "keywords": [ "global state" ], - "time": "2014-10-06 09:23:50" + "time": "2014-10-06T09:23:50+00:00" }, { "name": "sebastian/recursion-context", @@ -4066,7 +4066,7 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2015-06-21 08:04:50" + "time": "2015-06-21T08:04:50+00:00" }, { "name": "sebastian/version", @@ -4101,7 +4101,7 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-06-21 13:59:46" + "time": "2015-06-21T13:59:46+00:00" }, { "name": "symfony/browser-kit", @@ -4158,7 +4158,7 @@ ], "description": "Symfony BrowserKit Component", "homepage": "https://symfony.com", - "time": "2016-10-13 13:35:11" + "time": "2016-10-13T13:35:11+00:00" }, { "name": "symfony/css-selector", @@ -4211,7 +4211,7 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "time": "2016-11-03 07:52:58" + "time": "2016-11-03T07:52:58+00:00" } ], "aliases": [], diff --git a/core/composer.json b/core/composer.json index 71f07d029f..78e94c7b01 100644 --- a/core/composer.json +++ b/core/composer.json @@ -19,7 +19,7 @@ "symfony/process": "~2.8", "symfony/polyfill-iconv": "~1.0", "symfony/yaml": "~2.8", - "twig/twig": "^1.23.1", + "twig/twig": "^1.23.1|^2", "doctrine/common": "2.5.*", "doctrine/annotations": "1.2.*", "guzzlehttp/guzzle": "^6.2.1", diff --git a/core/lib/Drupal/Core/Template/Loader/StringLoader.php b/core/lib/Drupal/Core/Template/Loader/StringLoader.php index 6325b9e98a..400bab578b 100644 --- a/core/lib/Drupal/Core/Template/Loader/StringLoader.php +++ b/core/lib/Drupal/Core/Template/Loader/StringLoader.php @@ -20,7 +20,7 @@ * @see \Drupal\Core\Render\Element\InlineTemplate * @see twig_render_template() */ -class StringLoader implements \Twig_LoaderInterface, \Twig_ExistsLoaderInterface { +class StringLoader implements \Twig_LoaderInterface, \Twig_ExistsLoaderInterface, \Twig_SourceContextLoaderInterface { /** * {@inheritdoc} @@ -44,6 +44,14 @@ public function getSource($name) { /** * {@inheritdoc} */ + public function getSourceContext($name) { + $name = (string) $name; + return new \Twig_Source($name, $name); + } + + /** + * {@inheritdoc} + */ public function getCacheKey($name) { return $name; } diff --git a/core/lib/Drupal/Core/Template/TwigEnvironment.php b/core/lib/Drupal/Core/Template/TwigEnvironment.php index f5ee459767..dc44520f2d 100644 --- a/core/lib/Drupal/Core/Template/TwigEnvironment.php +++ b/core/lib/Drupal/Core/Template/TwigEnvironment.php @@ -24,6 +24,8 @@ class TwigEnvironment extends \Twig_Environment { protected $templateClasses; protected $twigCachePrefix = ''; + + protected $templateClassPrefix = '__TwigTemplate_'; /** * Constructs a TwigEnvironment object and stores cache and storage @@ -42,11 +44,7 @@ class TwigEnvironment extends \Twig_Environment { * @param array $options * The options for the Twig environment. */ - public function __construct($root, CacheBackendInterface $cache, $twig_extension_hash, StateInterface $state, \Twig_LoaderInterface $loader = NULL, $options = array()) { - // Ensure that twig.engine is loaded, given that it is needed to render a - // template because functions like TwigExtension::escapeFilter() are called. - require_once $root . '/core/themes/engines/twig/twig.engine'; - + public function __construct($root, CacheBackendInterface $cache, $twig_extension_hash, StateInterface $state, \Twig_LoaderInterface $loader = NULL, array $options = array()) { $this->templateClasses = array(); $options += array( @@ -57,11 +55,6 @@ public function __construct($root, CacheBackendInterface $cache, $twig_extension ); // Ensure autoescaping is always on. $options['autoescape'] = 'html'; - - $policy = new TwigSandboxPolicy(); - $sandbox = new \Twig_Extension_Sandbox($policy, TRUE); - $this->addExtension($sandbox); - if ($options['cache'] === TRUE) { $current = $state->get('twig_extension_hash_prefix', ['twig_extension_hash' => '']); if ($current['twig_extension_hash'] !== $twig_extension_hash || empty($current['twig_cache_prefix'])) { @@ -78,8 +71,11 @@ public function __construct($root, CacheBackendInterface $cache, $twig_extension $options['cache'] = new TwigPhpStorageCache($cache, $this->twigCachePrefix); } - $this->loader = $loader; - parent::__construct($this->loader, $options); + $this->setLoader($loader); + parent::__construct($this->getLoader(), $options); + $policy = new TwigSandboxPolicy(); + $sandbox = new \Twig_Extension_Sandbox($policy, TRUE); + $this->addExtension($sandbox); } /** @@ -110,7 +106,7 @@ public function getTemplateClass($name, $index = NULL) { // node.html.twig for the output of each node and the same compiled class. $cache_index = $name . (NULL === $index ? '' : '_' . $index); if (!isset($this->templateClasses[$cache_index])) { - $this->templateClasses[$cache_index] = $this->templateClassPrefix . hash('sha256', $this->loader->getCacheKey($name)) . (NULL === $index ? '' : '_' . $index); + $this->templateClasses[$cache_index] = $this->templateClassPrefix . hash('sha256', $this->getLoader()->getCacheKey($name)) . (NULL === $index ? '' : '_' . $index); } return $this->templateClasses[$cache_index]; } diff --git a/core/lib/Drupal/Core/Template/TwigExtension.php b/core/lib/Drupal/Core/Template/TwigExtension.php index 7d67ff991c..b3edd81867 100644 --- a/core/lib/Drupal/Core/Template/TwigExtension.php +++ b/core/lib/Drupal/Core/Template/TwigExtension.php @@ -177,7 +177,7 @@ public function getFilters() { new \Twig_SimpleFilter('safe_join', [$this, 'safeJoin'], ['needs_environment' => TRUE, 'is_safe' => ['html']]), // Array filters. - new \Twig_SimpleFilter('without', 'twig_without'), + new \Twig_SimpleFilter('without', [$this, 'withoutFilter']), // CSS class and ID filters. new \Twig_SimpleFilter('clean_class', '\Drupal\Component\Utility\Html::getClass'), @@ -629,4 +629,37 @@ public function createAttribute(array $attributes = []) { return new Attribute($attributes); } + /** + * Removes child elements from a copy of the original array. + * + * Creates a copy of the renderable array and removes child elements by key + * specified through filter's arguments. The copy can be printed without these + * elements. The original renderable array is still available and can be used + * to print child elements in their entirety in the twig template. + * + * @param array|object $element + * The parent renderable array to exclude the child items. + * @param string[] $args, ... + * The string keys of $element to prevent printing. + * + * @return array + * The filtered renderable array. + */ + public function withoutFilter($element) { + if ($element instanceof \ArrayAccess) { + $filtered_element = clone $element; + } + else { + $filtered_element = $element; + } + $args = func_get_args(); + unset($args[0]); + foreach ($args as $arg) { + if (isset($filtered_element[$arg])) { + unset($filtered_element[$arg]); + } + } + return $filtered_element; + } + } diff --git a/core/lib/Drupal/Core/Template/TwigNodeTrans.php b/core/lib/Drupal/Core/Template/TwigNodeTrans.php index 21006fd1ed..1caf3b4e4b 100644 --- a/core/lib/Drupal/Core/Template/TwigNodeTrans.php +++ b/core/lib/Drupal/Core/Template/TwigNodeTrans.php @@ -17,7 +17,7 @@ class TwigNodeTrans extends \Twig_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(\Twig_Node $body, \Twig_Node $plural, \Twig_Node $count, \Twig_Node $options, $lineno, $tag = NULL) { parent::__construct(array( 'count' => $count, 'body' => $body, @@ -103,7 +103,7 @@ protected function compileString(\Twig_Node $body) { $text = ''; foreach ($body as $node) { - if (get_class($node) === 'Twig_Node' && $node->getNode(0) instanceof \Twig_Node_SetTemp) { + if (get_class($node) === 'Twig_Node') { $node = $node->getNode(1); } @@ -157,7 +157,7 @@ protected function compileString(\Twig_Node $body) { if (!is_null($args)) { $argName = $args->getAttribute('name'); } - $expr = new \Twig_Node_Expression_Name($argName, $n->getLine()); + $expr = new \Twig_Node_Expression_Name($argName, $n->getTemplateLine()); } $placeholder = sprintf('%s%s', $argPrefix, $argName); $text .= $placeholder; @@ -176,7 +176,7 @@ protected function compileString(\Twig_Node $body) { $text = $body->getAttribute('data'); } - return array(new \Twig_Node(array(new \Twig_Node_Expression_Constant(trim($text), $body->getLine()))), $tokens); + return array(new \Twig_Node(array(new \Twig_Node_Expression_Constant(trim($text), $body->getTemplateLine()))), $tokens); } } diff --git a/core/lib/Drupal/Core/Template/TwigNodeVisitor.php b/core/lib/Drupal/Core/Template/TwigNodeVisitor.php index 6222d69e3a..17cbb428cb 100644 --- a/core/lib/Drupal/Core/Template/TwigNodeVisitor.php +++ b/core/lib/Drupal/Core/Template/TwigNodeVisitor.php @@ -33,7 +33,7 @@ protected function doLeaveNode(\Twig_Node $node, \Twig_Environment $env) { return $node; } $class = get_class($node); - $line = $node->getLine(); + $line = $node->getTemplateLine(); return new $class( new \Twig_Node_Expression_Function('render_var', new \Twig_Node(array($node->getNode('expr'))), $line), $line diff --git a/core/lib/Drupal/Core/Template/TwigTransTokenParser.php b/core/lib/Drupal/Core/Template/TwigTransTokenParser.php index fb16017537..579f2d4331 100644 --- a/core/lib/Drupal/Core/Template/TwigTransTokenParser.php +++ b/core/lib/Drupal/Core/Template/TwigTransTokenParser.php @@ -21,10 +21,10 @@ class TwigTransTokenParser extends \Twig_TokenParser { public function parse(\Twig_Token $token) { $lineno = $token->getLine(); $stream = $this->parser->getStream(); - $body = NULL; - $options = NULL; - $count = NULL; - $plural = NULL; + $body = []; + $options = []; + $count = []; + $plural = []; if (!$stream->test(\Twig_Token::BLOCK_END_TYPE) && $stream->test(\Twig_Token::STRING_TYPE)) { $body = $this->parser->getExpressionParser()->parseExpression(); @@ -47,6 +47,18 @@ public function parse(\Twig_Token $token) { $this->checkTransString($body, $lineno); + if ($body === []) { + $body = new \Twig_Node($body); + } + if ($plural === []) { + $plural = new \Twig_Node($plural); + } + if ($count === []) { + $count = new \Twig_Node($count); + } + if ($options === []) { + $options = new \Twig_Node($options); + } $node = new TwigNodeTrans($body, $plural, $count, $options, $lineno, $this->getTag()); return $node; 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 78d1020288..3baa6e2b9c 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,11 +2,10 @@ namespace Drupal\twig_extension_test\TwigExtension; - /** * A test Twig extension that adds a custom function and a custom filter. */ -class TestExtension extends \Twig_Extension { +class TestExtension extends \TwigExtension { /** * Generates a list of all Twig functions that this extension defines. @@ -21,9 +20,9 @@ class TestExtension extends \Twig_Extension { * The value is a standard PHP callback that defines what the function does. */ public function getFunctions() { - return array( - 'testfunc' => new \Twig_Function_Function(array('Drupal\twig_extension_test\TwigExtension\TestExtension', 'testFunction')), - ); + return [ + new \Twig_SimpleFunction('testfunc', [$this, 'testFunction']), + ]; } /** @@ -39,9 +38,9 @@ public function getFunctions() { * The value is a standard PHP callback that defines what the filter does. */ public function getFilters() { - return array( - 'testfilter' => new \Twig_Filter_Function(array('Drupal\twig_extension_test\TwigExtension\TestExtension', 'testFilter')), - ); + return [ + new \Twig_SimpleFilter('testfilter', [$this, 'testFilter']), + ]; } /** diff --git a/core/modules/system/tests/modules/twig_extension_test/twig_extension_test.services.yml b/core/modules/system/tests/modules/twig_extension_test/twig_extension_test.services.yml index 491d1e8c5b..8784c0f341 100644 --- a/core/modules/system/tests/modules/twig_extension_test/twig_extension_test.services.yml +++ b/core/modules/system/tests/modules/twig_extension_test/twig_extension_test.services.yml @@ -1,6 +1,5 @@ services: twig_extension_test.twig.test_extension: - arguments: ['@renderer'] class: Drupal\twig_extension_test\TwigExtension\TestExtension tags: - { name: twig.extension } diff --git a/core/tests/Drupal/KernelTests/Core/Theme/TwigEnvironmentTest.php b/core/tests/Drupal/KernelTests/Core/Theme/TwigEnvironmentTest.php index c3e7af6a3c..3804e1072c 100644 --- a/core/tests/Drupal/KernelTests/Core/Theme/TwigEnvironmentTest.php +++ b/core/tests/Drupal/KernelTests/Core/Theme/TwigEnvironmentTest.php @@ -115,13 +115,18 @@ public function testCacheFilename() { // Note: Later we refetch the twig service in order to bypass its internal // static cache. $environment = \Drupal::service('twig'); + $template_path = 'core/modules/system/templates/container.html.twig'; - $original_filename = $environment->getCacheFilename('core/modules/system/templates/container.html.twig'); + $cache = $environment->getCache(); + $class = $environment->getTemplateClass($template_path); + $original_filename = $cache->generateKey($template_path, $class); \Drupal::getContainer()->set('twig', NULL); \Drupal::service('module_installer')->install(['twig_extension_test']); $environment = \Drupal::service('twig'); - $new_extension_filename = $environment->getCacheFilename('core/modules/system/templates/container.html.twig'); + $cache = $environment->getCache(); + $class = $environment->getTemplateClass($template_path); + $new_extension_filename = $cache->generateKey($template_path, $class); \Drupal::getContainer()->set('twig', NULL); $this->assertNotEqual($new_extension_filename, $original_filename); diff --git a/core/tests/Drupal/Tests/Core/Template/AttributeTest.php b/core/tests/Drupal/Tests/Core/Template/AttributeTest.php index 09ec9894dc..3ffd46da3b 100644 --- a/core/tests/Drupal/Tests/Core/Template/AttributeTest.php +++ b/core/tests/Drupal/Tests/Core/Template/AttributeTest.php @@ -263,7 +263,7 @@ public function testChainAddRemoveClasses() { * @covers ::addClass */ public function testTwigAddRemoveClasses($template, $expected, $seed_attributes = array()) { - $loader = new \Twig_Loader_String(); + $loader = new \Twig_Loader_Array($template); $twig = new \Twig_Environment($loader); $data = array('attributes' => new Attribute($seed_attributes)); $result = $twig->render($template, $data); diff --git a/core/tests/Drupal/Tests/Core/Template/TwigExtensionTest.php b/core/tests/Drupal/Tests/Core/Template/TwigExtensionTest.php index 396b2f9765..eb8cfb34b6 100644 --- a/core/tests/Drupal/Tests/Core/Template/TwigExtensionTest.php +++ b/core/tests/Drupal/Tests/Core/Template/TwigExtensionTest.php @@ -10,6 +10,19 @@ use Drupal\Core\Template\TwigExtension; use Drupal\Tests\UnitTestCase; +if (!function_exists(__NAMESPACE__ . 't')) { + + function t($string, array $args = []) { + return strtr($string, $args); + } + +} +if (!function_exists(__NAMESPACE__ . 'file_create_url')) { + + function file_create_url() {} + +} + /** * Tests the twig extension. * @@ -74,7 +87,9 @@ public function setUp() { * @dataProvider providerTestEscaping */ public function testEscaping($template, $expected) { - $twig = new \Twig_Environment(NULL, array( + $renderer = $this->getMock('\Drupal\Core\Render\RendererInterface'); + $loader = new \Twig_Loader_Filesystem(); + $twig = new \Twig_Environment($loader, array( 'debug' => TRUE, 'cache' => FALSE, 'autoescape' => 'html', @@ -134,7 +149,7 @@ public function testActiveTheme() { ->method('getActiveTheme') ->willReturn($active_theme); - $loader = new \Twig_Loader_String(); + $loader = new \Twig_Loader_Array([]); $twig = new \Twig_Environment($loader); $twig->addExtension($this->systemUnderTest); $result = $twig->render('{{ active_theme() }}'); @@ -171,7 +186,7 @@ public function testActiveThemePath() { ->method('getActiveTheme') ->willReturn($active_theme); - $loader = new \Twig_Loader_String(); + $loader = new \Twig_Loader_Array([]); $twig = new \Twig_Environment($loader); $twig->addExtension($this->systemUnderTest); $result = $twig->render('{{ active_theme_path() }}'); @@ -184,7 +199,9 @@ public function testActiveThemePath() { * @covers ::escapeFilter */ public function testSafeStringEscaping() { - $twig = new \Twig_Environment(NULL, array( + $renderer = $this->getMock('\Drupal\Core\Render\RendererInterface'); + $loader = new \Twig_Loader_Filesystem(); + $twig = new \Twig_Environment($loader, array( 'debug' => TRUE, 'cache' => FALSE, 'autoescape' => 'html', @@ -268,7 +285,8 @@ public function providerTestRenderVar() { * @covers ::bubbleArgMetadata */ public function testEscapeWithGeneratedLink() { - $twig = new \Twig_Environment(NULL, [ + $loader = new \Twig_Loader_Filesystem(); + $twig = new \Twig_Environment($loader, [ 'debug' => TRUE, 'cache' => FALSE, 'autoescape' => 'html', @@ -326,7 +344,7 @@ public function testRenderVarWithGeneratedLink() { * @covers ::createAttribute */ public function testCreateAttribute() { - $loader = new StringLoader(); + $loader = new \Twig_Loader_Array([]); $twig = new \Twig_Environment($loader); $twig->addExtension($this->systemUnderTest);