diff --git a/core/lib/Drupal/Core/Template/TwigCacheChain.php b/core/lib/Drupal/Core/Template/TwigCacheChain.php new file mode 100644 index 0000000..3696e09 --- /dev/null +++ b/core/lib/Drupal/Core/Template/TwigCacheChain.php @@ -0,0 +1,104 @@ +caches = $caches; + } + + /** + * {@inheritdoc} + */ + public function generateKey($name, $className) { + foreach ($this->caches as $cache) { + if ($cache instanceof \Twig_CacheInterface) { + $key = $cache->generateKey($name, $className); + return $key; + } + } + } + + /** + * {@inheritdoc} + */ + public function has($key) { + foreach ($this->caches as $cache) { + if ($cache instanceof \Twig_CacheInterface) { + if ($has = $cache->has($key)) { + return $has; + } + } + } + } + + /** + * {@inheritdoc} + */ + public function load($key) { + foreach ($this->caches as $cache) { + if ($cache instanceof \Twig_CacheInterface) { + try { + if ($cache->has($key)) { + $cache->load($key); + } + return; + } + catch (\RuntimeException $e) { + } + } + } + } + + /** + * {@inheritdoc} + */ + public function write($key, $content) { + foreach ($this->caches as $cache) { + if ($cache instanceof \Twig_CacheInterface) { + try { + $cache->write($key, $content); + return; + } + catch (\RuntimeException $e) { + } + } + } + } + + /** + * {@inheritdoc} + */ + public function getTimestamp($key) { + foreach ($this->caches as $cache) { + if ($cache instanceof \Twig_CacheInterface) { + if ($timestamp = $cache->getTimestamp($key)) { + return $timestamp; + } + } + } + } + +} diff --git a/core/lib/Drupal/Core/Template/TwigEnvironment.php b/core/lib/Drupal/Core/Template/TwigEnvironment.php index 3988d20..405284d 100644 --- a/core/lib/Drupal/Core/Template/TwigEnvironment.php +++ b/core/lib/Drupal/Core/Template/TwigEnvironment.php @@ -22,13 +22,6 @@ class TwigEnvironment extends \Twig_Environment { /** - * The template cache filename prefix. - * - * @var string - */ - protected $templateCacheFilenamePrefix; - - /** * Static cache of template classes. * * @var array @@ -51,8 +44,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->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'; @@ -68,9 +59,11 @@ public function __construct($root, CacheBackendInterface $cache, $twig_extension // Ensure autoescaping is always on. $options['autoescape'] = 'html'; + $php_storage_cache = new TwigPhpStorageCache($cache, $twig_extension_hash); + $null_cache = new \Twig_Cache_Null(); + if ($options['cache'] === TRUE) { - // @todo Try to use $this->setCache()? - $options['cache'] = new TwigPhpStorageCache($cache, $twig_extension_hash); + $options['cache'] = new TwigCacheChain([$php_storage_cache, $null_cache]); } $this->loader = $loader; diff --git a/core/lib/Drupal/Core/Template/TwigPhpStorageCache.php b/core/lib/Drupal/Core/Template/TwigPhpStorageCache.php index 22d33b0..ce98a26 100644 --- a/core/lib/Drupal/Core/Template/TwigPhpStorageCache.php +++ b/core/lib/Drupal/Core/Template/TwigPhpStorageCache.php @@ -20,7 +20,7 @@ class TwigPhpStorageCache implements \Twig_CacheInterface { * * @var \Drupal\Core\Cache\CacheBackendInterface */ - protected $cache_object = NULL; + protected $cache = NULL; /** * The PhpStorage object used for storing the templates. @@ -45,7 +45,7 @@ class TwigPhpStorageCache implements \Twig_CacheInterface { * The Twig extension hash. */ public function __construct(CacheBackendInterface $cache, $twig_extension_hash) { - $this->cache_object = $cache; + $this->cache = $cache; $this->templateCacheFilenamePrefix = $twig_extension_hash; } @@ -87,13 +87,8 @@ public function has($key) { * {@inheritdoc} */ public function load($key) { - if ($this->has($key)) { - $this->storage()->load($key); - } - else { - // @todo Add race condition handling stuff around here? - // Compile and eval? How do we get to the Twig env from here? - // Maybe we can just fall back to the null cache somehow or incorporate this into write(). + if (!$this->storage()->load($key)) { + throw new \RuntimeException(sprintf('Failed to load Twig cache file "%s".', $key)); } } @@ -101,10 +96,12 @@ public function load($key) { * {@inheritdoc} */ public function write($key, $content) { - $this->storage()->save($key, $content); + if (!$this->storage()->save($key, $content)) { + throw new \RuntimeException(sprintf('Failed to write Twig cache file "%s".', $key)); + } // Save the last modification time. $cid = 'twig:' . $key; - $this->cache_object->set($cid, REQUEST_TIME); + $this->cache->set($cid, REQUEST_TIME); } /** @@ -112,9 +109,12 @@ public function write($key, $content) { */ public function getTimestamp($key) { $cid = 'twig:' . $key; - if ($cache = $this->cache_object->get($cid)) { + if ($cache = $this->cache->get($cid)) { return $cache->data; } + else { + return REQUEST_TIME; + } } }