Upgraded drupal core with security updates
[yaffs-website] / web / core / lib / Drupal / Core / Template / TwigEnvironment.php
1 <?php
2
3 namespace Drupal\Core\Template;
4
5 use Drupal\Core\Cache\CacheBackendInterface;
6 use Drupal\Core\Render\Markup;
7 use Drupal\Core\State\StateInterface;
8
9 /**
10  * A class that defines a Twig environment for Drupal.
11  *
12  * Instances of this class are used to store the configuration and extensions,
13  * and are used to load templates from the file system or other locations.
14  *
15  * @see core\vendor\twig\twig\lib\Twig\Environment.php
16  */
17 class TwigEnvironment extends \Twig_Environment {
18
19   /**
20    * Static cache of template classes.
21    *
22    * @var array
23    */
24   protected $templateClasses;
25
26   protected $twigCachePrefix = '';
27
28   /**
29    * Constructs a TwigEnvironment object and stores cache and storage
30    * internally.
31    *
32    * @param string $root
33    *   The app root.
34    * @param \Drupal\Core\Cache\CacheBackendInterface $cache
35    *   The cache bin.
36    * @param string $twig_extension_hash
37    *   The Twig extension hash.
38    * @param \Drupal\Core\State\StateInterface $state
39    *   The state service.
40    * @param \Twig_LoaderInterface $loader
41    *   The Twig loader or loader chain.
42    * @param array $options
43    *   The options for the Twig environment.
44    */
45   public function __construct($root, CacheBackendInterface $cache, $twig_extension_hash, StateInterface $state, \Twig_LoaderInterface $loader = NULL, $options = []) {
46     // Ensure that twig.engine is loaded, given that it is needed to render a
47     // template because functions like TwigExtension::escapeFilter() are called.
48     require_once $root . '/core/themes/engines/twig/twig.engine';
49
50     $this->templateClasses = [];
51
52     $options += [
53       // @todo Ensure garbage collection of expired files.
54       'cache' => TRUE,
55       'debug' => FALSE,
56       'auto_reload' => NULL,
57     ];
58     // Ensure autoescaping is always on.
59     $options['autoescape'] = 'html';
60
61     $policy = new TwigSandboxPolicy();
62     $sandbox = new \Twig_Extension_Sandbox($policy, TRUE);
63     $this->addExtension($sandbox);
64
65     if ($options['cache'] === TRUE) {
66       $current = $state->get('twig_extension_hash_prefix', ['twig_extension_hash' => '']);
67       if ($current['twig_extension_hash'] !== $twig_extension_hash || empty($current['twig_cache_prefix'])) {
68         $current = [
69           'twig_extension_hash' => $twig_extension_hash,
70           // Generate a new prefix which invalidates any existing cached files.
71           'twig_cache_prefix' => uniqid(),
72
73         ];
74         $state->set('twig_extension_hash_prefix', $current);
75       }
76       $this->twigCachePrefix = $current['twig_cache_prefix'];
77
78       $options['cache'] = new TwigPhpStorageCache($cache, $this->twigCachePrefix);
79     }
80
81     $this->loader = $loader;
82     parent::__construct($this->loader, $options);
83   }
84
85   /**
86    * Get the cache prefixed used by \Drupal\Core\Template\TwigPhpStorageCache
87    *
88    * @return string
89    *   The file cache prefix, or empty string if the cache is disabled.
90    */
91   public function getTwigCachePrefix() {
92     return $this->twigCachePrefix;
93   }
94
95   /**
96    * Gets the template class associated with the given string.
97    *
98    * @param string $name
99    *   The name for which to calculate the template class name.
100    * @param int $index
101    *   The index if it is an embedded template.
102    *
103    * @return string
104    *   The template class name.
105    */
106   public function getTemplateClass($name, $index = NULL) {
107     // We override this method to add caching because it gets called multiple
108     // times when the same template is used more than once. For example, a page
109     // rendering 50 nodes without any node template overrides will use the same
110     // node.html.twig for the output of each node and the same compiled class.
111     $cache_index = $name . (NULL === $index ? '' : '_' . $index);
112     if (!isset($this->templateClasses[$cache_index])) {
113       $this->templateClasses[$cache_index] = $this->templateClassPrefix . hash('sha256', $this->loader->getCacheKey($name)) . (NULL === $index ? '' : '_' . $index);
114     }
115     return $this->templateClasses[$cache_index];
116   }
117
118   /**
119    * Renders a twig string directly.
120    *
121    * Warning: You should use the render element 'inline_template' together with
122    * the #template attribute instead of this method directly.
123    * On top of that you have to ensure that the template string is not dynamic
124    * but just an ordinary static php string, because there may be installations
125    * using read-only PHPStorage that want to generate all possible twig
126    * templates as part of a build step. So it is important that an automated
127    * script can find the templates and extract them. This is only possible if
128    * the template is a regular string.
129    *
130    * @param string $template_string
131    *   The template string to render with placeholders.
132    * @param array $context
133    *   An array of parameters to pass to the template.
134    *
135    * @return \Drupal\Component\Render\MarkupInterface|string
136    *   The rendered inline template as a Markup object.
137    *
138    * @see \Drupal\Core\Template\Loader\StringLoader::exists()
139    */
140   public function renderInline($template_string, array $context = []) {
141     // Prefix all inline templates with a special comment.
142     $template_string = '{# inline_template_start #}' . $template_string;
143     return Markup::create($this->loadTemplate($template_string, NULL)->render($context));
144   }
145
146 }