diff core/lib/Drupal/Core/Template/TwigEnvironment.php @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children 129ea1e6d783
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/lib/Drupal/Core/Template/TwigEnvironment.php	Wed Nov 29 16:09:58 2017 +0000
@@ -0,0 +1,146 @@
+<?php
+
+namespace Drupal\Core\Template;
+
+use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Render\Markup;
+use Drupal\Core\State\StateInterface;
+
+/**
+ * A class that defines a Twig environment for Drupal.
+ *
+ * Instances of this class are used to store the configuration and extensions,
+ * and are used to load templates from the file system or other locations.
+ *
+ * @see core\vendor\twig\twig\lib\Twig\Environment.php
+ */
+class TwigEnvironment extends \Twig_Environment {
+
+  /**
+   * Static cache of template classes.
+   *
+   * @var array
+   */
+  protected $templateClasses;
+
+  protected $twigCachePrefix = '';
+
+  /**
+   * Constructs a TwigEnvironment object and stores cache and storage
+   * internally.
+   *
+   * @param string $root
+   *   The app root.
+   * @param \Drupal\Core\Cache\CacheBackendInterface $cache
+   *   The cache bin.
+   * @param string $twig_extension_hash
+   *   The Twig extension hash.
+   * @param \Drupal\Core\State\StateInterface $state
+   *   The state service.
+   * @param \Twig_LoaderInterface $loader
+   *   The Twig loader or loader chain.
+   * @param array $options
+   *   The options for the Twig environment.
+   */
+  public function __construct($root, CacheBackendInterface $cache, $twig_extension_hash, StateInterface $state, \Twig_LoaderInterface $loader = NULL, $options = []) {
+    // 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';
+
+    $this->templateClasses = [];
+
+    $options += [
+      // @todo Ensure garbage collection of expired files.
+      'cache' => TRUE,
+      'debug' => FALSE,
+      'auto_reload' => NULL,
+    ];
+    // Ensure autoescaping is always on.
+    $options['autoescape'] = 'html';
+
+    $policy = new TwigSandboxPolicy();
+    $sandbox = new \Twig_Extension_Sandbox($policy, TRUE);
+    $this->addExtension($sandbox);
+
+    if ($options['cache'] === TRUE) {
+      $current = $state->get('twig_extension_hash_prefix', ['twig_extension_hash' => '']);
+      if ($current['twig_extension_hash'] !== $twig_extension_hash || empty($current['twig_cache_prefix'])) {
+        $current = [
+          'twig_extension_hash' => $twig_extension_hash,
+          // Generate a new prefix which invalidates any existing cached files.
+          'twig_cache_prefix' => uniqid(),
+
+        ];
+        $state->set('twig_extension_hash_prefix', $current);
+      }
+      $this->twigCachePrefix = $current['twig_cache_prefix'];
+
+      $options['cache'] = new TwigPhpStorageCache($cache, $this->twigCachePrefix);
+    }
+
+    $this->loader = $loader;
+    parent::__construct($this->loader, $options);
+  }
+
+  /**
+   * Get the cache prefixed used by \Drupal\Core\Template\TwigPhpStorageCache
+   *
+   * @return string
+   *   The file cache prefix, or empty string if the cache is disabled.
+   */
+  public function getTwigCachePrefix() {
+    return $this->twigCachePrefix;
+  }
+
+  /**
+   * Gets the template class associated with the given string.
+   *
+   * @param string $name
+   *   The name for which to calculate the template class name.
+   * @param int $index
+   *   The index if it is an embedded template.
+   *
+   * @return string
+   *   The template class name.
+   */
+  public function getTemplateClass($name, $index = NULL) {
+    // 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
+    // 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.
+    $cache_index = $name . (NULL === $index ? '' : '_' . $index);
+    if (!isset($this->templateClasses[$cache_index])) {
+      $this->templateClasses[$cache_index] = $this->templateClassPrefix . hash('sha256', $this->loader->getCacheKey($name)) . (NULL === $index ? '' : '_' . $index);
+    }
+    return $this->templateClasses[$cache_index];
+  }
+
+  /**
+   * Renders a twig string directly.
+   *
+   * Warning: You should use the render element 'inline_template' together with
+   * the #template attribute instead of this method directly.
+   * On top of that you have to ensure that the template string is not dynamic
+   * but just an ordinary static php string, because there may be installations
+   * using read-only PHPStorage that want to generate all possible twig
+   * templates as part of a build step. So it is important that an automated
+   * script can find the templates and extract them. This is only possible if
+   * the template is a regular string.
+   *
+   * @param string $template_string
+   *   The template string to render with placeholders.
+   * @param array $context
+   *   An array of parameters to pass to the template.
+   *
+   * @return \Drupal\Component\Render\MarkupInterface|string
+   *   The rendered inline template as a Markup object.
+   *
+   * @see \Drupal\Core\Template\Loader\StringLoader::exists()
+   */
+  public function renderInline($template_string, array $context = []) {
+    // Prefix all inline templates with a special comment.
+    $template_string = '{# inline_template_start #}' . $template_string;
+    return Markup::create($this->loadTemplate($template_string, NULL)->render($context));
+  }
+
+}