diff --git a/core/lib/Drupal/Core/Template/TwigEnvironment.php b/core/lib/Drupal/Core/Template/TwigEnvironment.php index 00e8716..97341ac 100644 --- a/core/lib/Drupal/Core/Template/TwigEnvironment.php +++ b/core/lib/Drupal/Core/Template/TwigEnvironment.php @@ -31,13 +31,6 @@ class TwigEnvironment extends \Twig_Environment { protected $templateClasses; /** - * The string loader implementation used for inline template rendering. - * - * @var \Twig_Loader_String - */ - protected $stringLoader; - - /** * Constructs a TwigEnvironment object and stores cache and storage * internally. */ @@ -66,7 +59,6 @@ public function __construct(\Twig_LoaderInterface $loader = NULL, ModuleHandlerI } $this->templateClasses = array(); - $this->stringLoader = new \Twig_Loader_String(); $options += array( // @todo Ensure garbage collection of expired files. @@ -77,7 +69,8 @@ public function __construct(\Twig_LoaderInterface $loader = NULL, ModuleHandlerI // Ensure autoescaping is always on. $options['autoescape'] = TRUE; - parent::__construct($loader, $options); + $this->loader = new \Twig_Loader_Chain([$loader, new \Twig_Loader_String()]); + parent::__construct($this->loader, $options); } /** @@ -92,12 +85,9 @@ protected function isFresh($cache_filename, $name) { /** * Compile the source and write the compiled template to disk. - * - * @param bool $inline - * TRUE, if the $cache_filename is a rendered template. */ - public function updateCompiledTemplate($cache_filename, $name, $inline = FALSE) { - $source = $this->getLoader($inline)->getSource($name); + public function updateCompiledTemplate($cache_filename, $name) { + $source = $this->loader->getSource($name); $compiled_source = $this->compileSource($source, $name); $this->storage()->save($cache_filename, $compiled_source); // Save the last modification time @@ -106,22 +96,6 @@ public function updateCompiledTemplate($cache_filename, $name, $inline = FALSE) } /** - * Gets the Loader instance. - * - * @param bool $inline - * TRUE, if the string loader is requested. - * - * @return \Twig_LoaderInterface - * A Twig_LoaderInterface instance - */ - public function getLoader($inline = FALSE) { - if (!isset($this->loader)) { - throw new \LogicException('You must set a loader first.'); - } - return $inline ? $this->stringLoader : $this->loader; - } - - /** * Implements Twig_Environment::loadTemplate(). * * We need to overwrite this function to integrate with drupal_php_storage(). @@ -133,8 +107,6 @@ public function getLoader($inline = FALSE) { * The template name or the string which should be rendered as template. * @param int $index * The index if it is an embedded template. - * @param bool $inline - * TRUE, if the $name is a rendered template. * * @return \Twig_TemplateInterface * A template instance representing the given template name. @@ -144,8 +116,8 @@ public function getLoader($inline = FALSE) { * @throws \Twig_Error_Syntax * When an error occurred during compilation. */ - public function loadTemplate($name, $index = NULL, $inline = FALSE) { - $cls = $this->getTemplateClass($name, $index, $inline); + public function loadTemplate($name, $index = NULL) { + $cls = $this->getTemplateClass($name, $index); if (isset($this->loadedTemplates[$cls])) { return $this->loadedTemplates[$cls]; @@ -155,7 +127,7 @@ public function loadTemplate($name, $index = NULL, $inline = FALSE) { $cache_filename = $this->getCacheFilename($name); if ($cache_filename === FALSE) { - $compiled_source = $this->compileSource($this->getLoader($inline)->getSource($name), $name); + $compiled_source = $this->compileSource($this->loader->getSource($name), $name); eval('?' . '>' . $compiled_source); } else { @@ -163,11 +135,11 @@ public function loadTemplate($name, $index = NULL, $inline = FALSE) { // If autoreload is on, check that the template has not been // modified since the last compilation. if ($this->isAutoReload() && !$this->isFresh($cache_filename, $name)) { - $this->updateCompiledTemplate($cache_filename, $name, $inline); + $this->updateCompiledTemplate($cache_filename, $name); } if (!$this->storage()->load($cache_filename)) { - $this->updateCompiledTemplate($cache_filename, $name, $inline); + $this->updateCompiledTemplate($cache_filename, $name); $this->storage()->load($cache_filename); } } @@ -199,20 +171,18 @@ protected function storage() { * The name for which to calculate the template class name. * @param int $index * The index if it is an embedded template. - * @param bool $inline - * TRUE, if the $name is a rendered template. * * @return string * The template class name. */ - public function getTemplateClass($name, $index = NULL, $inline = FALSE) { + public function getTemplateClass($name, $index = NULL) { // We override this method to add caching because it gets called multiple // times when the same template is used more than once. For example, a page // rendering 50 nodes without any node template overrides will use the same // 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->getLoader($inline)->getCacheKey($name)) . (NULL === $index ? '' : '_' . $index); + $this->templateClasses[$cache_index] = $this->templateClassPrefix . hash('sha256', $this->loader->getCacheKey($name)) . (NULL === $index ? '' : '_' . $index); } return $this->templateClasses[$cache_index]; } @@ -238,7 +208,7 @@ public function getTemplateClass($name, $index = NULL, $inline = FALSE) { * The rendered inline template. */ public function renderInline($template_string, array $context = array()) { - return $this->loadTemplate($template_string, NULL, TRUE)->render($context); + return $this->loadTemplate($template_string, NULL)->render($context); } } diff --git a/core/modules/system/src/Tests/Theme/TwigEnvironmentTest.php b/core/modules/system/src/Tests/Theme/TwigEnvironmentTest.php index cc43696..6ecabec 100644 --- a/core/modules/system/src/Tests/Theme/TwigEnvironmentTest.php +++ b/core/modules/system/src/Tests/Theme/TwigEnvironmentTest.php @@ -8,6 +8,7 @@ namespace Drupal\system\Tests\Theme; use Drupal\Component\Utility\String; +use Drupal\Core\Site\Settings; use Drupal\simpletest\KernelTestBase; /** @@ -42,6 +43,26 @@ public function testInlineTemplate() { '#context' => array('unsafe_content' => $unsafe_string), ); $this->assertEqual(drupal_render($element), 'test-with-context ' . String::checkPlain($unsafe_string)); + + // Enable twig_auto_reload and twig_debug. + $settings = Settings::getAll(); + $settings['twig_debug'] = TRUE; + $settings['twig_auto_reload'] = TRUE; + + new Settings($settings); + $this->container = $this->kernel->rebuildContainer(); + \Drupal::setContainer($this->container); + + $element = array(); + $element['test'] = array( + '#type' => 'inline_template', + '#template' => 'test-with-context {{ lama }}', + '#context' => array('lama' => 'muuh'), + ); + $element_copy = $element; + // Render it twice so that twig caching is triggered. + $this->assertEqual(drupal_render($element), 'test-with-context muuh'); + $this->assertEqual(drupal_render($element_copy), 'test-with-context muuh'); } } diff --git a/core/modules/system/src/Tests/Theme/TwigSettingsTest.php b/core/modules/system/src/Tests/Theme/TwigSettingsTest.php index e570432..c7fec1d 100644 --- a/core/modules/system/src/Tests/Theme/TwigSettingsTest.php +++ b/core/modules/system/src/Tests/Theme/TwigSettingsTest.php @@ -118,4 +118,20 @@ function testTwigCacheOverride() { $this->assertFalse($new_cache_filename, 'Twig environment does not return cache filename after caching is disabled.'); } + /** + * Tests twig inline templates with auto_reload. + */ + public function testTwigInlineWithAutoReload() { + $parameters = $this->container->getParameter('twig.config'); + $parameters['auto_reload'] = TRUE; + $parameters['debug'] = TRUE; + $this->setContainerParameter('twig.config', $parameters); + $this->rebuildContainer(); + + $this->drupalGet('theme-test/inline-template-test'); + $this->assertResponse(200); + $this->drupalGet('theme-test/inline-template-test'); + $this->assertResponse(200); + } + } diff --git a/core/modules/system/tests/modules/theme_test/src/ThemeTestController.php b/core/modules/system/tests/modules/theme_test/src/ThemeTestController.php index bf0e436..4e0c0a8 100644 --- a/core/modules/system/tests/modules/theme_test/src/ThemeTestController.php +++ b/core/modules/system/tests/modules/theme_test/src/ThemeTestController.php @@ -60,6 +60,22 @@ public function testTemplate() { } /** + * Tests the inline template functionality. + * + * @return array + * A render array containing an inline template. + */ + public function testInlineTemplate() { + $element = array(); + $element['test'] = array( + '#type' => 'inline_template', + '#template' => 'test-with-context {{ lama }}', + '#context' => array('lama' => 'muuh'), + ); + return $element; + } + + /** * Calls a theme hook suggestion. * * @return string diff --git a/core/modules/system/tests/modules/theme_test/theme_test.routing.yml b/core/modules/system/tests/modules/theme_test/theme_test.routing.yml index f46f05b..d7d306e 100644 --- a/core/modules/system/tests/modules/theme_test/theme_test.routing.yml +++ b/core/modules/system/tests/modules/theme_test/theme_test.routing.yml @@ -21,6 +21,13 @@ theme_test.template_test: requirements: _access: 'TRUE' +theme_test.inline_template_test: + path: '/theme-test/inline-template-test' + defaults: + _content: '\Drupal\theme_test\ThemeTestController::testInlineTemplate' + requirements: + _access: 'TRUE' + theme_test.suggestion: path: '/theme-test/suggestion' options: