[ Index ]

PHP Cross Reference of phpBB-3.3.14-deutsch

title

Body

[close]

/vendor/twig/twig/src/ -> Template.php (source)

   1  <?php
   2  
   3  /*
   4   * This file is part of Twig.
   5   *
   6   * (c) Fabien Potencier
   7   * (c) Armin Ronacher
   8   *
   9   * For the full copyright and license information, please view the LICENSE
  10   * file that was distributed with this source code.
  11   */
  12  
  13  namespace Twig;
  14  
  15  use Twig\Error\Error;
  16  use Twig\Error\LoaderError;
  17  use Twig\Error\RuntimeError;
  18  
  19  /**
  20   * Default base class for compiled templates.
  21   *
  22   * This class is an implementation detail of how template compilation currently
  23   * works, which might change. It should never be used directly. Use $twig->load()
  24   * instead, which returns an instance of \Twig\TemplateWrapper.
  25   *
  26   * @author Fabien Potencier <fabien@symfony.com>
  27   *
  28   * @internal
  29   */
  30  abstract class Template
  31  {
  32      public const ANY_CALL = 'any';
  33      public const ARRAY_CALL = 'array';
  34      public const METHOD_CALL = 'method';
  35  
  36      protected $parent;
  37      protected $parents = [];
  38      protected $env;
  39      protected $blocks = [];
  40      protected $traits = [];
  41      protected $extensions = [];
  42      protected $sandbox;
  43  
  44      public function __construct(Environment $env)
  45      {
  46          $this->env = $env;
  47          $this->extensions = $env->getExtensions();
  48      }
  49  
  50      /**
  51       * @internal this method will be removed in 3.0 and is only used internally to provide an upgrade path from 1.x to 2.0
  52       */
  53      public function __toString()
  54      {
  55          return $this->getTemplateName();
  56      }
  57  
  58      /**
  59       * Returns the template name.
  60       *
  61       * @return string The template name
  62       */
  63      abstract public function getTemplateName();
  64  
  65      /**
  66       * Returns debug information about the template.
  67       *
  68       * @return array Debug information
  69       */
  70      abstract public function getDebugInfo();
  71  
  72      /**
  73       * Returns information about the original template source code.
  74       *
  75       * @return Source
  76       */
  77      public function getSourceContext()
  78      {
  79          return new Source('', $this->getTemplateName());
  80      }
  81  
  82      /**
  83       * Returns the parent template.
  84       *
  85       * This method is for internal use only and should never be called
  86       * directly.
  87       *
  88       * @return Template|TemplateWrapper|false The parent template or false if there is no parent
  89       */
  90      public function getParent(array $context)
  91      {
  92          if (null !== $this->parent) {
  93              return $this->parent;
  94          }
  95  
  96          try {
  97              $parent = $this->doGetParent($context);
  98  
  99              if (false === $parent) {
 100                  return false;
 101              }
 102  
 103              if ($parent instanceof self || $parent instanceof TemplateWrapper) {
 104                  return $this->parents[$parent->getSourceContext()->getName()] = $parent;
 105              }
 106  
 107              if (!isset($this->parents[$parent])) {
 108                  $this->parents[$parent] = $this->loadTemplate($parent);
 109              }
 110          } catch (LoaderError $e) {
 111              $e->setSourceContext(null);
 112              $e->guess();
 113  
 114              throw $e;
 115          }
 116  
 117          return $this->parents[$parent];
 118      }
 119  
 120      protected function doGetParent(array $context)
 121      {
 122          return false;
 123      }
 124  
 125      public function isTraitable()
 126      {
 127          return true;
 128      }
 129  
 130      /**
 131       * Displays a parent block.
 132       *
 133       * This method is for internal use only and should never be called
 134       * directly.
 135       *
 136       * @param string $name    The block name to display from the parent
 137       * @param array  $context The context
 138       * @param array  $blocks  The current set of blocks
 139       */
 140      public function displayParentBlock($name, array $context, array $blocks = [])
 141      {
 142          if (isset($this->traits[$name])) {
 143              $this->traits[$name][0]->displayBlock($name, $context, $blocks, false);
 144          } elseif (false !== $parent = $this->getParent($context)) {
 145              $parent->displayBlock($name, $context, $blocks, false);
 146          } else {
 147              throw new RuntimeError(sprintf('The template has no parent and no traits defining the "%s" block.', $name), -1, $this->getSourceContext());
 148          }
 149      }
 150  
 151      /**
 152       * Displays a block.
 153       *
 154       * This method is for internal use only and should never be called
 155       * directly.
 156       *
 157       * @param string $name      The block name to display
 158       * @param array  $context   The context
 159       * @param array  $blocks    The current set of blocks
 160       * @param bool   $useBlocks Whether to use the current set of blocks
 161       */
 162      public function displayBlock($name, array $context, array $blocks = [], $useBlocks = true, self $templateContext = null)
 163      {
 164          if ($useBlocks && isset($blocks[$name])) {
 165              $template = $blocks[$name][0];
 166              $block = $blocks[$name][1];
 167          } elseif (isset($this->blocks[$name])) {
 168              $template = $this->blocks[$name][0];
 169              $block = $this->blocks[$name][1];
 170          } else {
 171              $template = null;
 172              $block = null;
 173          }
 174  
 175          // avoid RCEs when sandbox is enabled
 176          if (null !== $template && !$template instanceof self) {
 177              throw new \LogicException('A block must be a method on a \Twig\Template instance.');
 178          }
 179  
 180          if (null !== $template) {
 181              try {
 182                  $template->$block($context, $blocks);
 183              } catch (Error $e) {
 184                  if (!$e->getSourceContext()) {
 185                      $e->setSourceContext($template->getSourceContext());
 186                  }
 187  
 188                  // this is mostly useful for \Twig\Error\LoaderError exceptions
 189                  // see \Twig\Error\LoaderError
 190                  if (-1 === $e->getTemplateLine()) {
 191                      $e->guess();
 192                  }
 193  
 194                  throw $e;
 195              } catch (\Exception $e) {
 196                  $e = new RuntimeError(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $template->getSourceContext(), $e);
 197                  $e->guess();
 198  
 199                  throw $e;
 200              }
 201          } elseif (false !== $parent = $this->getParent($context)) {
 202              $parent->displayBlock($name, $context, array_merge($this->blocks, $blocks), false, $templateContext ?? $this);
 203          } elseif (isset($blocks[$name])) {
 204              throw new RuntimeError(sprintf('Block "%s" should not call parent() in "%s" as the block does not exist in the parent template "%s".', $name, $blocks[$name][0]->getTemplateName(), $this->getTemplateName()), -1, $blocks[$name][0]->getSourceContext());
 205          } else {
 206              throw new RuntimeError(sprintf('Block "%s" on template "%s" does not exist.', $name, $this->getTemplateName()), -1, ($templateContext ?? $this)->getSourceContext());
 207          }
 208      }
 209  
 210      /**
 211       * Renders a parent block.
 212       *
 213       * This method is for internal use only and should never be called
 214       * directly.
 215       *
 216       * @param string $name    The block name to render from the parent
 217       * @param array  $context The context
 218       * @param array  $blocks  The current set of blocks
 219       *
 220       * @return string The rendered block
 221       */
 222      public function renderParentBlock($name, array $context, array $blocks = [])
 223      {
 224          if ($this->env->isDebug()) {
 225              ob_start();
 226          } else {
 227              ob_start(function () { return ''; });
 228          }
 229          $this->displayParentBlock($name, $context, $blocks);
 230  
 231          return ob_get_clean();
 232      }
 233  
 234      /**
 235       * Renders a block.
 236       *
 237       * This method is for internal use only and should never be called
 238       * directly.
 239       *
 240       * @param string $name      The block name to render
 241       * @param array  $context   The context
 242       * @param array  $blocks    The current set of blocks
 243       * @param bool   $useBlocks Whether to use the current set of blocks
 244       *
 245       * @return string The rendered block
 246       */
 247      public function renderBlock($name, array $context, array $blocks = [], $useBlocks = true)
 248      {
 249          if ($this->env->isDebug()) {
 250              ob_start();
 251          } else {
 252              ob_start(function () { return ''; });
 253          }
 254          $this->displayBlock($name, $context, $blocks, $useBlocks);
 255  
 256          return ob_get_clean();
 257      }
 258  
 259      /**
 260       * Returns whether a block exists or not in the current context of the template.
 261       *
 262       * This method checks blocks defined in the current template
 263       * or defined in "used" traits or defined in parent templates.
 264       *
 265       * @param string $name    The block name
 266       * @param array  $context The context
 267       * @param array  $blocks  The current set of blocks
 268       *
 269       * @return bool true if the block exists, false otherwise
 270       */
 271      public function hasBlock($name, array $context, array $blocks = [])
 272      {
 273          if (isset($blocks[$name])) {
 274              return $blocks[$name][0] instanceof self;
 275          }
 276  
 277          if (isset($this->blocks[$name])) {
 278              return true;
 279          }
 280  
 281          if (false !== $parent = $this->getParent($context)) {
 282              return $parent->hasBlock($name, $context);
 283          }
 284  
 285          return false;
 286      }
 287  
 288      /**
 289       * Returns all block names in the current context of the template.
 290       *
 291       * This method checks blocks defined in the current template
 292       * or defined in "used" traits or defined in parent templates.
 293       *
 294       * @param array $context The context
 295       * @param array $blocks  The current set of blocks
 296       *
 297       * @return array An array of block names
 298       */
 299      public function getBlockNames(array $context, array $blocks = [])
 300      {
 301          $names = array_merge(array_keys($blocks), array_keys($this->blocks));
 302  
 303          if (false !== $parent = $this->getParent($context)) {
 304              $names = array_merge($names, $parent->getBlockNames($context));
 305          }
 306  
 307          return array_unique($names);
 308      }
 309  
 310      /**
 311       * @return Template|TemplateWrapper
 312       */
 313      protected function loadTemplate($template, $templateName = null, $line = null, $index = null)
 314      {
 315          try {
 316              if (\is_array($template)) {
 317                  return $this->env->resolveTemplate($template);
 318              }
 319  
 320              if ($template instanceof self || $template instanceof TemplateWrapper) {
 321                  return $template;
 322              }
 323  
 324              if ($template === $this->getTemplateName()) {
 325                  $class = static::class;
 326                  if (false !== $pos = strrpos($class, '___', -1)) {
 327                      $class = substr($class, 0, $pos);
 328                  }
 329  
 330                  return $this->env->loadClass($class, $template, $index);
 331              }
 332  
 333              return $this->env->loadTemplate($template, $index);
 334          } catch (Error $e) {
 335              if (!$e->getSourceContext()) {
 336                  $e->setSourceContext($templateName ? new Source('', $templateName) : $this->getSourceContext());
 337              }
 338  
 339              if ($e->getTemplateLine() > 0) {
 340                  throw $e;
 341              }
 342  
 343              if (!$line) {
 344                  $e->guess();
 345              } else {
 346                  $e->setTemplateLine($line);
 347              }
 348  
 349              throw $e;
 350          }
 351      }
 352  
 353      /**
 354       * @internal
 355       *
 356       * @return Template
 357       */
 358      public function unwrap()
 359      {
 360          return $this;
 361      }
 362  
 363      /**
 364       * Returns all blocks.
 365       *
 366       * This method is for internal use only and should never be called
 367       * directly.
 368       *
 369       * @return array An array of blocks
 370       */
 371      public function getBlocks()
 372      {
 373          return $this->blocks;
 374      }
 375  
 376      public function display(array $context, array $blocks = [])
 377      {
 378          $this->displayWithErrorHandling($this->env->mergeGlobals($context), array_merge($this->blocks, $blocks));
 379      }
 380  
 381      public function render(array $context)
 382      {
 383          $level = ob_get_level();
 384          if ($this->env->isDebug()) {
 385              ob_start();
 386          } else {
 387              ob_start(function () { return ''; });
 388          }
 389          try {
 390              $this->display($context);
 391          } catch (\Throwable $e) {
 392              while (ob_get_level() > $level) {
 393                  ob_end_clean();
 394              }
 395  
 396              throw $e;
 397          }
 398  
 399          return ob_get_clean();
 400      }
 401  
 402      protected function displayWithErrorHandling(array $context, array $blocks = [])
 403      {
 404          try {
 405              $this->doDisplay($context, $blocks);
 406          } catch (Error $e) {
 407              if (!$e->getSourceContext()) {
 408                  $e->setSourceContext($this->getSourceContext());
 409              }
 410  
 411              // this is mostly useful for \Twig\Error\LoaderError exceptions
 412              // see \Twig\Error\LoaderError
 413              if (-1 === $e->getTemplateLine()) {
 414                  $e->guess();
 415              }
 416  
 417              throw $e;
 418          } catch (\Exception $e) {
 419              $e = new RuntimeError(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $this->getSourceContext(), $e);
 420              $e->guess();
 421  
 422              throw $e;
 423          }
 424      }
 425  
 426      /**
 427       * Auto-generated method to display the template with the given context.
 428       *
 429       * @param array $context An array of parameters to pass to the template
 430       * @param array $blocks  An array of blocks to pass to the template
 431       */
 432      abstract protected function doDisplay(array $context, array $blocks = []);
 433  }
 434  
 435  class_alias('Twig\Template', 'Twig_Template');


Generated: Mon Nov 25 19:05:08 2024 Cross-referenced by PHPXref 0.7.1