diff --git a/core/lib/Drupal/Core/Template/TwigCache.php b/core/lib/Drupal/Core/Template/TwigCache.php new file mode 100644 index 0000000..77eb0fb --- /dev/null +++ b/core/lib/Drupal/Core/Template/TwigCache.php @@ -0,0 +1,95 @@ +cache = $cache; + $this->templateCacheFilenamePrefix = $template_cache_filename_prefix; + } + + /** + * {@inheritdoc} + */ + public function generateKey($name, $className) { + // We override the cache filename in order to avoid issues with not using + // shared filesystems. The Twig templates for example rely on available Twig + // extensions, so we use the twig extension hash which varies by extensions + // and their mtime. + // @see \Drupal\Core\DependencyInjection\Compiler\TwigExtensionPass + + // The first part is what is invalidated. + $key = $this->templateCacheFilenamePrefix . '_' . basename($name) . '_' . $className; + return $key; + } + + /** + * Gets the PHP code storage object to use for the compiled Twig files. + * + * @return \Drupal\Component\PhpStorage\PhpStorageInterface + */ + protected function storage() { + if (!isset($this->storage)) { + $this->storage = PhpStorageFactory::get('twig'); + } + return $this->storage; + } + + /** + * {@inheritdoc} + */ + public function has($key) { + } + + /** + * {@inheritdoc} + */ + public function write($key, $content) { + $this->storage()->save($key, $content); + // Save the last modification time + $cid = 'twig:' . $key; + $this->cache->set($cid, REQUEST_TIME); + } + + /** + * {@inheritdoc} + */ + public function load($key) { + $this->storage()->load($key); + } + + /** + * {@inheritdoc} + */ + public function getTimestamp($key) { + $cid = 'twig:' . $key; + $obj = $this->cache->get($cid); + $mtime = isset($obj->data) ? $obj->data : FALSE; + + return $mtime === FALSE || REQUEST_TIME; + } + +} diff --git a/core/lib/Drupal/Core/Template/TwigEnvironment.php b/core/lib/Drupal/Core/Template/TwigEnvironment.php index cb4df85..294dc29 100644 --- a/core/lib/Drupal/Core/Template/TwigEnvironment.php +++ b/core/lib/Drupal/Core/Template/TwigEnvironment.php @@ -23,13 +23,6 @@ class TwigEnvironment extends \Twig_Environment { /** - * The cache object used for auto-refresh via mtime. - * - * @var \Drupal\Core\Cache\CacheBackendInterface - */ - protected $cache_object = NULL; - - /** * The PhpStorage object used for storing the templates. * * @var \Drupal\Core\PhpStorage\PhpStorageFactory @@ -37,13 +30,6 @@ class TwigEnvironment extends \Twig_Environment { protected $storage = NULL; /** - * The template cache filename prefix. - * - * @var string - */ - protected $templateCacheFilenamePrefix; - - /** * Static cache of template classes. * * @var array @@ -66,9 +52,6 @@ class TwigEnvironment extends \Twig_Environment { * The options for the Twig environment. */ public function __construct($root, CacheBackendInterface $cache, $twig_extension_hash, \Twig_LoaderInterface $loader = NULL, $options = array()) { - $this->cache_object = $cache; - $this->templateCacheFilenamePrefix = $twig_extension_hash; - // 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'; @@ -84,118 +67,12 @@ public function __construct($root, CacheBackendInterface $cache, $twig_extension // Ensure autoescaping is always on. $options['autoescape'] = 'html'; - $this->loader = $loader; - parent::__construct($this->loader, $options); - } - - /** - * Checks if the compiled template needs an update. - */ - protected function isFresh($cache_filename, $name) { - $cid = 'twig:' . $cache_filename; - $obj = $this->cache_object->get($cid); - $mtime = isset($obj->data) ? $obj->data : FALSE; - return $mtime === FALSE || $this->isTemplateFresh($name, $mtime); - } - - /** - * Compile the source and write the compiled template to disk. - */ - 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 - $cid = 'twig:' . $cache_filename; - $this->cache_object->set($cid, REQUEST_TIME); - } - - /** - * {@inheritdoc} - */ - public function getCacheFilename($name) { - // We override the cache filename in order to avoid issues with not using - // shared filesystems. The Twig templates for example rely on available Twig - // extensions, so we use the twig extension hash which varies by extensions - // and their mtime. - // @see \Drupal\Core\DependencyInjection\Compiler\TwigExtensionPass - - if (!$this->cache) { - return FALSE; - } - - $class = substr($this->getTemplateClass($name), strlen($this->templateClassPrefix)); - - // The first part is what is invalidated. - return $this->templateCacheFilenamePrefix . '_' . basename($name) . '_' . $class; - } - - /** - * Implements Twig_Environment::loadTemplate(). - * - * We need to overwrite this function to integrate with drupal_php_storage(). - * - * This is a straight copy from loadTemplate() changed to use - * drupal_php_storage(). - * - * @param string $name - * The template name or the string which should be rendered as template. - * @param int $index - * The index if it is an embedded template. - * - * @return \Twig_TemplateInterface - * A template instance representing the given template name. - * - * @throws \Twig_Error_Loader - * When the template cannot be found. - * @throws \Twig_Error_Syntax - * When an error occurred during compilation. - */ - public function loadTemplate($name, $index = NULL) { - $cls = $this->getTemplateClass($name, $index); - - if (isset($this->loadedTemplates[$cls])) { - return $this->loadedTemplates[$cls]; + if ($options['cache'] === TRUE) { + $options['cache'] = new TwigCache($cache, $twig_extension_hash); } - if (!class_exists($cls, FALSE)) { - $cache_filename = $this->getCacheFilename($name); - - if ($cache_filename !== 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); - } - - if (!$this->storage()->load($cache_filename)) { - $this->updateCompiledTemplate($cache_filename, $name); - $this->storage()->load($cache_filename); - } - } - if (!class_exists($cls, FALSE)) { - $compiled_source = $this->compileSource($this->loader->getSource($name), $name); - eval('?' . '>' . $compiled_source); - } - } - - if (!$this->runtimeInitialized) { - $this->initRuntime(); - } - - return $this->loadedTemplates[$cls] = new $cls($this); - } - - /** - * Gets the PHP code storage object to use for the compiled Twig files. - * - * @return \Drupal\Component\PhpStorage\PhpStorageInterface - */ - protected function storage() { - if (!isset($this->storage)) { - $this->storage = PhpStorageFactory::get('twig'); - } - return $this->storage; + $this->loader = $loader; + parent::__construct($this->loader, $options); } /**