Commit 08b92945 authored by catch's avatar catch

Issue #2317557 by dawehner, Cottser, joelpittet, jhodgdon: Fixed renderInline...

Issue #2317557 by dawehner, Cottser, joelpittet, jhodgdon: Fixed renderInline not compatible with twig_auto_reload.
parent 57fc2615
...@@ -30,13 +30,6 @@ class TwigEnvironment extends \Twig_Environment { ...@@ -30,13 +30,6 @@ class TwigEnvironment extends \Twig_Environment {
*/ */
protected $templateClasses; 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 * Constructs a TwigEnvironment object and stores cache and storage
* internally. * internally.
...@@ -66,7 +59,6 @@ public function __construct(\Twig_LoaderInterface $loader = NULL, ModuleHandlerI ...@@ -66,7 +59,6 @@ public function __construct(\Twig_LoaderInterface $loader = NULL, ModuleHandlerI
} }
$this->templateClasses = array(); $this->templateClasses = array();
$this->stringLoader = new \Twig_Loader_String();
$options += array( $options += array(
// @todo Ensure garbage collection of expired files. // @todo Ensure garbage collection of expired files.
...@@ -77,7 +69,8 @@ public function __construct(\Twig_LoaderInterface $loader = NULL, ModuleHandlerI ...@@ -77,7 +69,8 @@ public function __construct(\Twig_LoaderInterface $loader = NULL, ModuleHandlerI
// Ensure autoescaping is always on. // Ensure autoescaping is always on.
$options['autoescape'] = TRUE; $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) { ...@@ -92,12 +85,9 @@ protected function isFresh($cache_filename, $name) {
/** /**
* Compile the source and write the compiled template to disk. * 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) { public function updateCompiledTemplate($cache_filename, $name) {
$source = $this->getLoader($inline)->getSource($name); $source = $this->loader->getSource($name);
$compiled_source = $this->compileSource($source, $name); $compiled_source = $this->compileSource($source, $name);
$this->storage()->save($cache_filename, $compiled_source); $this->storage()->save($cache_filename, $compiled_source);
// Save the last modification time // Save the last modification time
...@@ -105,22 +95,6 @@ public function updateCompiledTemplate($cache_filename, $name, $inline = FALSE) ...@@ -105,22 +95,6 @@ public function updateCompiledTemplate($cache_filename, $name, $inline = FALSE)
$this->cache_object->set($cid, REQUEST_TIME); $this->cache_object->set($cid, REQUEST_TIME);
} }
/**
* 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(). * Implements Twig_Environment::loadTemplate().
* *
...@@ -133,8 +107,6 @@ public function getLoader($inline = FALSE) { ...@@ -133,8 +107,6 @@ public function getLoader($inline = FALSE) {
* The template name or the string which should be rendered as template. * The template name or the string which should be rendered as template.
* @param int $index * @param int $index
* The index if it is an embedded template. * The index if it is an embedded template.
* @param bool $inline
* TRUE, if the $name is a rendered template.
* *
* @return \Twig_TemplateInterface * @return \Twig_TemplateInterface
* A template instance representing the given template name. * A template instance representing the given template name.
...@@ -144,8 +116,8 @@ public function getLoader($inline = FALSE) { ...@@ -144,8 +116,8 @@ public function getLoader($inline = FALSE) {
* @throws \Twig_Error_Syntax * @throws \Twig_Error_Syntax
* When an error occurred during compilation. * When an error occurred during compilation.
*/ */
public function loadTemplate($name, $index = NULL, $inline = FALSE) { public function loadTemplate($name, $index = NULL) {
$cls = $this->getTemplateClass($name, $index, $inline); $cls = $this->getTemplateClass($name, $index);
if (isset($this->loadedTemplates[$cls])) { if (isset($this->loadedTemplates[$cls])) {
return $this->loadedTemplates[$cls]; return $this->loadedTemplates[$cls];
...@@ -155,7 +127,7 @@ public function loadTemplate($name, $index = NULL, $inline = FALSE) { ...@@ -155,7 +127,7 @@ public function loadTemplate($name, $index = NULL, $inline = FALSE) {
$cache_filename = $this->getCacheFilename($name); $cache_filename = $this->getCacheFilename($name);
if ($cache_filename === FALSE) { 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); eval('?' . '>' . $compiled_source);
} }
else { else {
...@@ -163,11 +135,11 @@ public function loadTemplate($name, $index = NULL, $inline = FALSE) { ...@@ -163,11 +135,11 @@ public function loadTemplate($name, $index = NULL, $inline = FALSE) {
// If autoreload is on, check that the template has not been // If autoreload is on, check that the template has not been
// modified since the last compilation. // modified since the last compilation.
if ($this->isAutoReload() && !$this->isFresh($cache_filename, $name)) { 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)) { if (!$this->storage()->load($cache_filename)) {
$this->updateCompiledTemplate($cache_filename, $name, $inline); $this->updateCompiledTemplate($cache_filename, $name);
$this->storage()->load($cache_filename); $this->storage()->load($cache_filename);
} }
} }
...@@ -199,20 +171,18 @@ protected function storage() { ...@@ -199,20 +171,18 @@ protected function storage() {
* The name for which to calculate the template class name. * The name for which to calculate the template class name.
* @param int $index * @param int $index
* The index if it is an embedded template. * The index if it is an embedded template.
* @param bool $inline
* TRUE, if the $name is a rendered template.
* *
* @return string * @return string
* The template class name. * 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 // 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 // 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 // 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. // node.html.twig for the output of each node and the same compiled class.
$cache_index = $name . (NULL === $index ? '' : '_' . $index); $cache_index = $name . (NULL === $index ? '' : '_' . $index);
if (!isset($this->templateClasses[$cache_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]; return $this->templateClasses[$cache_index];
} }
...@@ -238,7 +208,7 @@ public function getTemplateClass($name, $index = NULL, $inline = FALSE) { ...@@ -238,7 +208,7 @@ public function getTemplateClass($name, $index = NULL, $inline = FALSE) {
* The rendered inline template. * The rendered inline template.
*/ */
public function renderInline($template_string, array $context = array()) { 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);
} }
} }
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
namespace Drupal\system\Tests\Theme; namespace Drupal\system\Tests\Theme;
use Drupal\Component\Utility\String; use Drupal\Component\Utility\String;
use Drupal\Core\Site\Settings;
use Drupal\simpletest\KernelTestBase; use Drupal\simpletest\KernelTestBase;
/** /**
...@@ -42,6 +43,26 @@ public function testInlineTemplate() { ...@@ -42,6 +43,26 @@ public function testInlineTemplate() {
'#context' => array('unsafe_content' => $unsafe_string), '#context' => array('unsafe_content' => $unsafe_string),
); );
$this->assertEqual(drupal_render($element), 'test-with-context ' . String::checkPlain($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');
} }
} }
......
...@@ -118,4 +118,20 @@ function testTwigCacheOverride() { ...@@ -118,4 +118,20 @@ function testTwigCacheOverride() {
$this->assertFalse($new_cache_filename, 'Twig environment does not return cache filename after caching is disabled.'); $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);
}
} }
...@@ -59,6 +59,22 @@ public function testTemplate() { ...@@ -59,6 +59,22 @@ public function testTemplate() {
return _theme('theme_test_template_test'); return _theme('theme_test_template_test');
} }
/**
* 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. * Calls a theme hook suggestion.
* *
......
...@@ -21,6 +21,13 @@ theme_test.template_test: ...@@ -21,6 +21,13 @@ theme_test.template_test:
requirements: requirements:
_access: 'TRUE' _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: theme_test.suggestion:
path: '/theme-test/suggestion' path: '/theme-test/suggestion'
options: options:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment