Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

Template.php

Zuletzt modifiziert: 09.10.2024, 12:57 - Dateigröße: 20.13 KiB


001  <?php
002   
003  /*
004   * This file is part of Twig.
005   *
006   * (c) 2009 Fabien Potencier
007   * (c) 2009 Armin Ronacher
008   *
009   * For the full copyright and license information, please view the LICENSE
010   * file that was distributed with this source code.
011   */
012   
013  /**
014   * Default base class for compiled templates.
015   *
016   * @author Fabien Potencier <fabien@symfony.com>
017   */
018  abstract class Twig_Template implements Twig_TemplateInterface
019  {
020      protected static $cache = array();
021   
022      protected $parent;
023      protected $parents = array();
024      protected $env;
025      protected $blocks = array();
026      protected $traits = array();
027   
028      /**
029       * Constructor.
030       *
031       * @param Twig_Environment $env A Twig_Environment instance
032       */
033      public function __construct(Twig_Environment $env)
034      {
035          $this->env = $env;
036      }
037   
038      /**
039       * Returns the template name.
040       *
041       * @return string The template name
042       */
043      abstract public function getTemplateName();
044   
045      /**
046       * @deprecated since 1.20 (to be removed in 2.0)
047       */
048      public function getEnvironment()
049      {
050          @trigger_error('The '.__METHOD__.' method is deprecated since version 1.20 and will be removed in 2.0.', E_USER_DEPRECATED);
051   
052          return $this->env;
053      }
054   
055      /**
056       * Returns the parent template.
057       *
058       * This method is for internal use only and should never be called
059       * directly.
060       *
061       * @param array $context
062       *
063       * @return Twig_TemplateInterface|false The parent template or false if there is no parent
064       *
065       * @internal
066       */
067      public function getParent(array $context)
068      {
069          if (null !== $this->parent) {
070              return $this->parent;
071          }
072   
073          try {
074              $parent = $this->doGetParent($context);
075   
076              if (false === $parent) {
077                  return false;
078              }
079   
080              if ($parent instanceof self) {
081                  return $this->parents[$parent->getTemplateName()] = $parent;
082              }
083   
084              if (!isset($this->parents[$parent])) {
085                  $this->parents[$parent] = $this->loadTemplate($parent);
086              }
087          } catch (Twig_Error_Loader $e) {
088              $e->setTemplateFile(null);
089              $e->guess();
090   
091              throw $e;
092          }
093   
094          return $this->parents[$parent];
095      }
096   
097      protected function doGetParent(array $context)
098      {
099          return false;
100      }
101   
102      public function isTraitable()
103      {
104          return true;
105      }
106   
107      /**
108       * Displays a parent block.
109       *
110       * This method is for internal use only and should never be called
111       * directly.
112       *
113       * @param string $name    The block name to display from the parent
114       * @param array  $context The context
115       * @param array  $blocks  The current set of blocks
116       *
117       * @internal
118       */
119      public function displayParentBlock($name, array $context, array $blocks = array())
120      {
121          $name = (string) $name;
122   
123          if (isset($this->traits[$name])) {
124              $this->traits[$name][0]->displayBlock($name, $context, $blocks, false);
125          } elseif (false !== $parent = $this->getParent($context)) {
126              $parent->displayBlock($name, $context, $blocks, false);
127          } else {
128              throw new Twig_Error_Runtime(sprintf('The template has no parent and no traits defining the "%s" block', $name), -1, $this->getTemplateName());
129          }
130      }
131   
132      /**
133       * Displays a block.
134       *
135       * This method is for internal use only and should never be called
136       * directly.
137       *
138       * @param string $name      The block name to display
139       * @param array  $context   The context
140       * @param array  $blocks    The current set of blocks
141       * @param bool   $useBlocks Whether to use the current set of blocks
142       *
143       * @internal
144       */
145      public function displayBlock($name, array $context, array $blocks = array(), $useBlocks = true)
146      {
147          $name = (string) $name;
148   
149          if ($useBlocks && isset($blocks[$name])) {
150              $template = $blocks[$name][0];
151              $block = $blocks[$name][1];
152          } elseif (isset($this->blocks[$name])) {
153              $template = $this->blocks[$name][0];
154              $block = $this->blocks[$name][1];
155          } else {
156              $template = null;
157              $block = null;
158          }
159   
160          if (null !== $template) {
161              // avoid RCEs when sandbox is enabled
162              if (!$template instanceof self) {
163                  throw new LogicException('A block must be a method on a Twig_Template instance.');
164              }
165   
166              try {
167                  $template->$block($context, $blocks);
168              } catch (Twig_Error $e) {
169                  if (!$e->getTemplateFile()) {
170                      $e->setTemplateFile($template->getTemplateName());
171                  }
172   
173                  // this is mostly useful for Twig_Error_Loader exceptions
174                  // see Twig_Error_Loader
175                  if (false === $e->getTemplateLine()) {
176                      $e->setTemplateLine(-1);
177                      $e->guess();
178                  }
179   
180                  throw $e;
181              } catch (Exception $e) {
182                  throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $template->getTemplateName(), $e);
183              }
184          } elseif (false !== $parent = $this->getParent($context)) {
185              $parent->displayBlock($name, $context, array_merge($this->blocks, $blocks), false);
186          }
187      }
188   
189      /**
190       * Renders a parent block.
191       *
192       * This method is for internal use only and should never be called
193       * directly.
194       *
195       * @param string $name    The block name to render from the parent
196       * @param array  $context The context
197       * @param array  $blocks  The current set of blocks
198       *
199       * @return string The rendered block
200       *
201       * @internal
202       */
203      public function renderParentBlock($name, array $context, array $blocks = array())
204      {
205          ob_start();
206          $this->displayParentBlock($name, $context, $blocks);
207   
208          return ob_get_clean();
209      }
210   
211      /**
212       * Renders a block.
213       *
214       * This method is for internal use only and should never be called
215       * directly.
216       *
217       * @param string $name      The block name to render
218       * @param array  $context   The context
219       * @param array  $blocks    The current set of blocks
220       * @param bool   $useBlocks Whether to use the current set of blocks
221       *
222       * @return string The rendered block
223       *
224       * @internal
225       */
226      public function renderBlock($name, array $context, array $blocks = array(), $useBlocks = true)
227      {
228          ob_start();
229          $this->displayBlock($name, $context, $blocks, $useBlocks);
230   
231          return ob_get_clean();
232      }
233   
234      /**
235       * Returns whether a block exists or not.
236       *
237       * This method is for internal use only and should never be called
238       * directly.
239       *
240       * This method does only return blocks defined in the current template
241       * or defined in "used" traits.
242       *
243       * It does not return blocks from parent templates as the parent
244       * template name can be dynamic, which is only known based on the
245       * current context.
246       *
247       * @param string $name The block name
248       *
249       * @return bool true if the block exists, false otherwise
250       *
251       * @internal
252       */
253      public function hasBlock($name)
254      {
255          return isset($this->blocks[(string) $name]);
256      }
257   
258      /**
259       * Returns all block names.
260       *
261       * This method is for internal use only and should never be called
262       * directly.
263       *
264       * @return array An array of block names
265       *
266       * @see hasBlock
267       *
268       * @internal
269       */
270      public function getBlockNames()
271      {
272          return array_keys($this->blocks);
273      }
274   
275      protected function loadTemplate($template, $templateName = null, $line = null, $index = null)
276      {
277          try {
278              if (is_array($template)) {
279                  return $this->env->resolveTemplate($template);
280              }
281   
282              if ($template instanceof self) {
283                  return $template;
284              }
285   
286              return $this->env->loadTemplate($template, $index);
287          } catch (Twig_Error $e) {
288              if (!$e->getTemplateFile()) {
289                  $e->setTemplateFile($templateName ? $templateName : $this->getTemplateName());
290              }
291   
292              if ($e->getTemplateLine()) {
293                  throw $e;
294              }
295   
296              if (!$line) {
297                  $e->guess();
298              } else {
299                  $e->setTemplateLine($line);
300              }
301   
302              throw $e;
303          }
304      }
305   
306      /**
307       * Returns all blocks.
308       *
309       * This method is for internal use only and should never be called
310       * directly.
311       *
312       * @return array An array of blocks
313       *
314       * @see hasBlock
315       *
316       * @internal
317       */
318      public function getBlocks()
319      {
320          return $this->blocks;
321      }
322   
323      /**
324       * Returns the template source code.
325       *
326       * @return string|null The template source code or null if it is not available
327       */
328      public function getSource()
329      {
330          $reflector = new ReflectionClass($this);
331          $file = $reflector->getFileName();
332   
333          if (!file_exists($file)) {
334              return;
335          }
336   
337          $source = file($file, FILE_IGNORE_NEW_LINES);
338          array_splice($source, 0, $reflector->getEndLine());
339   
340          $i = 0;
341          while (isset($source[$i]) && '/* */' === substr_replace($source[$i], '', 3, -2)) {
342              $source[$i] = str_replace('*//* ', '*/', substr($source[$i], 3, -2));
343              ++$i;
344          }
345          array_splice($source, $i);
346   
347          return implode("\n", $source);
348      }
349   
350      /**
351       * {@inheritdoc}
352       */
353      public function display(array $context, array $blocks = array())
354      {
355          $this->displayWithErrorHandling($this->env->mergeGlobals($context), array_merge($this->blocks, $blocks));
356      }
357   
358      /**
359       * {@inheritdoc}
360       */
361      public function render(array $context)
362      {
363          $level = ob_get_level();
364          ob_start();
365          try {
366              $this->display($context);
367          } catch (Exception $e) {
368              while (ob_get_level() > $level) {
369                  ob_end_clean();
370              }
371   
372              throw $e;
373          } catch (Throwable $e) {
374              while (ob_get_level() > $level) {
375                  ob_end_clean();
376              }
377   
378              throw $e;
379          }
380   
381          return ob_get_clean();
382      }
383   
384      protected function displayWithErrorHandling(array $context, array $blocks = array())
385      {
386          try {
387              $this->doDisplay($context, $blocks);
388          } catch (Twig_Error $e) {
389              if (!$e->getTemplateFile()) {
390                  $e->setTemplateFile($this->getTemplateName());
391              }
392   
393              // this is mostly useful for Twig_Error_Loader exceptions
394              // see Twig_Error_Loader
395              if (false === $e->getTemplateLine()) {
396                  $e->setTemplateLine(-1);
397                  $e->guess();
398              }
399   
400              throw $e;
401          } catch (Exception $e) {
402              throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $this->getTemplateName(), $e);
403          }
404      }
405   
406      /**
407       * Auto-generated method to display the template with the given context.
408       *
409       * @param array $context An array of parameters to pass to the template
410       * @param array $blocks  An array of blocks to pass to the template
411       */
412      abstract protected function doDisplay(array $context, array $blocks = array());
413   
414      /**
415       * Returns a variable from the context.
416       *
417       * This method is for internal use only and should never be called
418       * directly.
419       *
420       * This method should not be overridden in a sub-class as this is an
421       * implementation detail that has been introduced to optimize variable
422       * access for versions of PHP before 5.4. This is not a way to override
423       * the way to get a variable value.
424       *
425       * @param array  $context           The context
426       * @param string $item              The variable to return from the context
427       * @param bool   $ignoreStrictCheck Whether to ignore the strict variable check or not
428       *
429       * @return mixed The content of the context variable
430       *
431       * @throws Twig_Error_Runtime if the variable does not exist and Twig is running in strict mode
432       *
433       * @internal
434       */
435      final protected function getContext($context, $item, $ignoreStrictCheck = false)
436      {
437          if (!array_key_exists($item, $context)) {
438              if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
439                  return;
440              }
441   
442              throw new Twig_Error_Runtime(sprintf('Variable "%s" does not exist', $item), -1, $this->getTemplateName());
443          }
444   
445          return $context[$item];
446      }
447   
448      /**
449       * Returns the attribute value for a given array/object.
450       *
451       * @param mixed  $object            The object or array from where to get the item
452       * @param mixed  $item              The item to get from the array or object
453       * @param array  $arguments         An array of arguments to pass if the item is an object method
454       * @param string $type              The type of attribute (@see Twig_Template constants)
455       * @param bool   $isDefinedTest     Whether this is only a defined check
456       * @param bool   $ignoreStrictCheck Whether to ignore the strict attribute check or not
457       *
458       * @return mixed The attribute value, or a Boolean when $isDefinedTest is true, or null when the attribute is not set and $ignoreStrictCheck is true
459       *
460       * @throws Twig_Error_Runtime if the attribute does not exist and Twig is running in strict mode and $isDefinedTest is false
461       */
462      protected function getAttribute($object, $item, array $arguments = array(), $type = self::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false)
463      {
464          // array
465          if (self::METHOD_CALL !== $type) {
466              $arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item;
467   
468              if ((is_array($object) && array_key_exists($arrayItem, $object))
469                  || ($object instanceof ArrayAccess && isset($object[$arrayItem]))
470              ) {
471                  if ($isDefinedTest) {
472                      return true;
473                  }
474   
475                  return $object[$arrayItem];
476              }
477   
478              if (self::ARRAY_CALL === $type || !is_object($object)) {
479                  if ($isDefinedTest) {
480                      return false;
481                  }
482   
483                  if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
484                      return;
485                  }
486   
487                  if ($object instanceof ArrayAccess) {
488                      $message = sprintf('Key "%s" in object with ArrayAccess of class "%s" does not exist', $arrayItem, get_class($object));
489                  } elseif (is_object($object)) {
490                      $message = sprintf('Impossible to access a key "%s" on an object of class "%s" that does not implement ArrayAccess interface', $item, get_class($object));
491                  } elseif (is_array($object)) {
492                      if (empty($object)) {
493                          $message = sprintf('Key "%s" does not exist as the array is empty', $arrayItem);
494                      } else {
495                          $message = sprintf('Key "%s" for array with keys "%s" does not exist', $arrayItem, implode(', ', array_keys($object)));
496                      }
497                  } elseif (self::ARRAY_CALL === $type) {
498                      if (null === $object) {
499                          $message = sprintf('Impossible to access a key ("%s") on a null variable', $item);
500                      } else {
501                          $message = sprintf('Impossible to access a key ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
502                      }
503                  } elseif (null === $object) {
504                      $message = sprintf('Impossible to access an attribute ("%s") on a null variable', $item);
505                  } else {
506                      $message = sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
507                  }
508   
509                  throw new Twig_Error_Runtime($message, -1, $this->getTemplateName());
510              }
511          }
512   
513          if (!is_object($object)) {
514              if ($isDefinedTest) {
515                  return false;
516              }
517   
518              if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
519                  return;
520              }
521   
522              if (null === $object) {
523                  $message = sprintf('Impossible to invoke a method ("%s") on a null variable', $item);
524              } else {
525                  $message = sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
526              }
527   
528              throw new Twig_Error_Runtime($message, -1, $this->getTemplateName());
529          }
530   
531          // object property
532          if (self::METHOD_CALL !== $type && !$object instanceof self) { // Twig_Template does not have public properties, and we don't want to allow access to internal ones
533              if (isset($object->$item) || array_key_exists((string) $item, $object)) {
534                  if ($isDefinedTest) {
535                      return true;
536                  }
537   
538                  if ($this->env->hasExtension('sandbox')) {
539                      $this->env->getExtension('sandbox')->checkPropertyAllowed($object, $item);
540                  }
541   
542                  return $object->$item;
543              }
544          }
545   
546          $class = get_class($object);
547   
548          // object method
549          if (!isset(self::$cache[$class]['methods'])) {
550              // get_class_methods returns all methods accessible in the scope, but we only want public ones to be accessible in templates
551              if ($object instanceof self) {
552                  $ref = new ReflectionClass($class);
553                  $methods = array();
554   
555                  foreach ($ref->getMethods(ReflectionMethod::IS_PUBLIC) as $refMethod) {
556                      $methodName = strtolower($refMethod->name);
557   
558                      // Accessing the environment from templates is forbidden to prevent untrusted changes to the environment
559                      if ('getenvironment' !== $methodName) {
560                          $methods[$methodName] = true;
561                      }
562                  }
563   
564                  self::$cache[$class]['methods'] = $methods;
565              } else {
566                  self::$cache[$class]['methods'] = array_change_key_case(array_flip(get_class_methods($object)));
567              }
568          }
569   
570          $call = false;
571          $lcItem = strtolower($item);
572          if (isset(self::$cache[$class]['methods'][$lcItem])) {
573              $method = (string) $item;
574          } elseif (isset(self::$cache[$class]['methods']['get'.$lcItem])) {
575              $method = 'get'.$item;
576          } elseif (isset(self::$cache[$class]['methods']['is'.$lcItem])) {
577              $method = 'is'.$item;
578          } elseif (isset(self::$cache[$class]['methods']['__call'])) {
579              $method = (string) $item;
580              $call = true;
581          } else {
582              if ($isDefinedTest) {
583                  return false;
584              }
585   
586              if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
587                  return;
588              }
589   
590              throw new Twig_Error_Runtime(sprintf('Neither the property "%1$s" nor one of the methods "%1$s()", "get%1$s()"/"is%1$s()" or "__call()" exist and have public access in class "%2$s"', $item, get_class($object)), -1, $this->getTemplateName());
591          }
592   
593          if ($isDefinedTest) {
594              return true;
595          }
596   
597          if ($this->env->hasExtension('sandbox')) {
598              $this->env->getExtension('sandbox')->checkMethodAllowed($object, $method);
599          }
600   
601          // Some objects throw exceptions when they have __call, and the method we try
602          // to call is not supported. If ignoreStrictCheck is true, we should return null.
603          try {
604              $ret = call_user_func_array(array($object, $method), $arguments);
605          } catch (BadMethodCallException $e) {
606              if ($call && ($ignoreStrictCheck || !$this->env->isStrictVariables())) {
607                  return;
608              }
609              throw $e;
610          }
611   
612          // useful when calling a template method from a template
613          // this is not supported but unfortunately heavily used in the Symfony profiler
614          if ($object instanceof Twig_TemplateInterface) {
615              return $ret === '' ? '' : new Twig_Markup($ret, $this->env->getCharset());
616          }
617   
618          return $ret;
619      }
620  }
621