3 namespace Drupal\Core\Template;
5 use Drupal\Component\Utility\Crypt;
6 use Drupal\Core\Cache\CacheBackendInterface;
7 use Drupal\Core\PhpStorage\PhpStorageFactory;
10 * Provides an alternate cache storage for Twig using PhpStorage.
12 * This class is designed to work on setups with multiple webheads using a local
13 * filesystem for the twig cache. When generating the cache key, a hash value
14 * depending on the enabled extensions is included. This prevents stale
15 * templates from being reused when twig extensions are enabled or disabled.
17 * @see \Drupal\Core\DependencyInjection\Compiler\TwigExtensionPass
19 class TwigPhpStorageCache implements \Twig_CacheInterface {
22 * The maximum length for each part of the cache key suffix.
24 const SUFFIX_SUBSTRING_LENGTH = 25;
27 * The cache object used for auto-refresh via mtime.
29 * @var \Drupal\Core\Cache\CacheBackendInterface
34 * The PhpStorage object used for storing the templates.
36 * @var \Drupal\Component\PhpStorage\PhpStorageInterface
41 * The template cache filename prefix.
45 protected $templateCacheFilenamePrefix;
48 * Store cache backend and other information internally.
50 * @param \Drupal\Core\Cache\CacheBackendInterface $cache
52 * @param string $twig_cache_prefix
53 * A Twig cache file prefix that changes when Twig extensions change.
55 public function __construct(CacheBackendInterface $cache, $twig_cache_prefix) {
56 $this->cache = $cache;
57 $this->templateCacheFilenamePrefix = $twig_cache_prefix;
61 * Gets the PHP code storage object to use for the compiled Twig files.
63 * @return \Drupal\Component\PhpStorage\PhpStorageInterface
65 protected function storage() {
66 if (!isset($this->storage)) {
67 $this->storage = PhpStorageFactory::get('twig');
69 return $this->storage;
75 public function generateKey($name, $className) {
76 if (strpos($name, '{# inline_template_start #}') === 0) {
77 // $name is an inline template, and can have characters that are not valid
78 // for a filename. $suffix is unique for each inline template so we just
79 // use the generic name 'inline-template' here.
80 $name = 'inline-template';
83 $name = basename($name);
86 // Windows (and some encrypted Linux systems) only support 255 characters in
87 // a path. On Windows a requirements error is displayed and installation is
88 // blocked if Drupal's public files path is longer than 120 characters.
89 // Thus, to always be less than 255, file paths may not be more than 135
90 // characters long. Using the default PHP file storage class, the Twig cache
91 // file path will be 124 characters long at most, which provides a margin of
93 $suffix = substr($name, 0, self::SUFFIX_SUBSTRING_LENGTH) . '_';
94 $suffix .= substr(Crypt::hashBase64($className), 0, self::SUFFIX_SUBSTRING_LENGTH);
96 // The cache prefix is what gets invalidated.
97 return $this->templateCacheFilenamePrefix . '_' . $suffix;
103 public function load($key) {
104 $this->storage()->load($key);
110 public function write($key, $content) {
111 $this->storage()->save($key, $content);
112 // Save the last mtime.
113 $cid = 'twig:' . $key;
114 $this->cache->set($cid, REQUEST_TIME);
120 public function getTimestamp($key) {
121 $cid = 'twig:' . $key;
122 if ($cache = $this->cache->get($cid)) {