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

Parser.php

Zuletzt modifiziert: 09.10.2024, 12:57 - Dateigröße: 11.73 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 parser implementation.
 015   *
 016   * @author Fabien Potencier <fabien@symfony.com>
 017   */
 018  class Twig_Parser implements Twig_ParserInterface
 019  {
 020      protected $stack = array();
 021      protected $stream;
 022      protected $parent;
 023      protected $handlers;
 024      protected $visitors;
 025      protected $expressionParser;
 026      protected $blocks;
 027      protected $blockStack;
 028      protected $macros;
 029      protected $env;
 030      protected $reservedMacroNames;
 031      protected $importedSymbols;
 032      protected $traits;
 033      protected $embeddedTemplates = array();
 034   
 035      /**
 036       * Constructor.
 037       *
 038       * @param Twig_Environment $env A Twig_Environment instance
 039       */
 040      public function __construct(Twig_Environment $env)
 041      {
 042          $this->env = $env;
 043      }
 044   
 045      public function getEnvironment()
 046      {
 047          return $this->env;
 048      }
 049   
 050      public function getVarName()
 051      {
 052          return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false));
 053      }
 054   
 055      public function getFilename()
 056      {
 057          return $this->stream->getFilename();
 058      }
 059   
 060      /**
 061       * {@inheritdoc}
 062       */
 063      public function parse(Twig_TokenStream $stream, $test = null, $dropNeedle = false)
 064      {
 065          // push all variables into the stack to keep the current state of the parser
 066          // using get_object_vars() instead of foreach would lead to https://bugs.php.net/71336
 067          $vars = array();
 068          foreach ($this as $k => $v) {
 069              $vars[$k] = $v;
 070          }
 071   
 072          unset($vars['stack'], $vars['env'], $vars['handlers'], $vars['visitors'], $vars['expressionParser'], $vars['reservedMacroNames']);
 073          $this->stack[] = $vars;
 074   
 075          // tag handlers
 076          if (null === $this->handlers) {
 077              $this->handlers = $this->env->getTokenParsers();
 078              $this->handlers->setParser($this);
 079          }
 080   
 081          // node visitors
 082          if (null === $this->visitors) {
 083              $this->visitors = $this->env->getNodeVisitors();
 084          }
 085   
 086          if (null === $this->expressionParser) {
 087              $this->expressionParser = new Twig_ExpressionParser($this, $this->env->getUnaryOperators(), $this->env->getBinaryOperators());
 088          }
 089   
 090          $this->stream = $stream;
 091          $this->parent = null;
 092          $this->blocks = array();
 093          $this->macros = array();
 094          $this->traits = array();
 095          $this->blockStack = array();
 096          $this->importedSymbols = array(array());
 097          $this->embeddedTemplates = array();
 098   
 099          try {
 100              $body = $this->subparse($test, $dropNeedle);
 101   
 102              if (null !== $this->parent && null === $body = $this->filterBodyNodes($body)) {
 103                  $body = new Twig_Node();
 104              }
 105          } catch (Twig_Error_Syntax $e) {
 106              if (!$e->getTemplateFile()) {
 107                  $e->setTemplateFile($this->getFilename());
 108              }
 109   
 110              if (!$e->getTemplateLine()) {
 111                  $e->setTemplateLine($this->stream->getCurrent()->getLine());
 112              }
 113   
 114              throw $e;
 115          }
 116   
 117          $node = new Twig_Node_Module(new Twig_Node_Body(array($body)), $this->parent, new Twig_Node($this->blocks), new Twig_Node($this->macros), new Twig_Node($this->traits), $this->embeddedTemplates, $this->getFilename());
 118   
 119          $traverser = new Twig_NodeTraverser($this->env, $this->visitors);
 120   
 121          $node = $traverser->traverse($node);
 122   
 123          // restore previous stack so previous parse() call can resume working
 124          foreach (array_pop($this->stack) as $key => $val) {
 125              $this->$key = $val;
 126          }
 127   
 128          return $node;
 129      }
 130   
 131      public function subparse($test, $dropNeedle = false)
 132      {
 133          $lineno = $this->getCurrentToken()->getLine();
 134          $rv = array();
 135          while (!$this->stream->isEOF()) {
 136              switch ($this->getCurrentToken()->getType()) {
 137                  case Twig_Token::TEXT_TYPE:
 138                      $token = $this->stream->next();
 139                      $rv[] = new Twig_Node_Text($token->getValue(), $token->getLine());
 140                      break;
 141   
 142                  case Twig_Token::VAR_START_TYPE:
 143                      $token = $this->stream->next();
 144                      $expr = $this->expressionParser->parseExpression();
 145                      $this->stream->expect(Twig_Token::VAR_END_TYPE);
 146                      $rv[] = new Twig_Node_Print($expr, $token->getLine());
 147                      break;
 148   
 149                  case Twig_Token::BLOCK_START_TYPE:
 150                      $this->stream->next();
 151                      $token = $this->getCurrentToken();
 152   
 153                      if ($token->getType() !== Twig_Token::NAME_TYPE) {
 154                          throw new Twig_Error_Syntax('A block must start with a tag name.', $token->getLine(), $this->getFilename());
 155                      }
 156   
 157                      if (null !== $test && call_user_func($test, $token)) {
 158                          if ($dropNeedle) {
 159                              $this->stream->next();
 160                          }
 161   
 162                          if (1 === count($rv)) {
 163                              return $rv[0];
 164                          }
 165   
 166                          return new Twig_Node($rv, array(), $lineno);
 167                      }
 168   
 169                      $subparser = $this->handlers->getTokenParser($token->getValue());
 170                      if (null === $subparser) {
 171                          if (null !== $test) {
 172                              $e = new Twig_Error_Syntax(sprintf('Unexpected "%s" tag', $token->getValue()), $token->getLine(), $this->getFilename());
 173   
 174                              if (is_array($test) && isset($test[0]) && $test[0] instanceof Twig_TokenParserInterface) {
 175                                  $e->appendMessage(sprintf(' (expecting closing tag for the "%s" tag defined near line %s).', $test[0]->getTag(), $lineno));
 176                              }
 177                          } else {
 178                              $e = new Twig_Error_Syntax(sprintf('Unknown "%s" tag.', $token->getValue()), $token->getLine(), $this->getFilename());
 179                              $e->addSuggestions($token->getValue(), array_keys($this->env->getTags()));
 180                          }
 181   
 182                          throw $e;
 183                      }
 184   
 185                      $this->stream->next();
 186   
 187                      $node = $subparser->parse($token);
 188                      if (null !== $node) {
 189                          $rv[] = $node;
 190                      }
 191                      break;
 192   
 193                  default:
 194                      throw new Twig_Error_Syntax('Lexer or parser ended up in unsupported state.', 0, $this->getFilename());
 195              }
 196          }
 197   
 198          if (1 === count($rv)) {
 199              return $rv[0];
 200          }
 201   
 202          return new Twig_Node($rv, array(), $lineno);
 203      }
 204   
 205      public function addHandler($name, $class)
 206      {
 207          $this->handlers[$name] = $class;
 208      }
 209   
 210      public function addNodeVisitor(Twig_NodeVisitorInterface $visitor)
 211      {
 212          $this->visitors[] = $visitor;
 213      }
 214   
 215      public function getBlockStack()
 216      {
 217          return $this->blockStack;
 218      }
 219   
 220      public function peekBlockStack()
 221      {
 222          return $this->blockStack[count($this->blockStack) - 1];
 223      }
 224   
 225      public function popBlockStack()
 226      {
 227          array_pop($this->blockStack);
 228      }
 229   
 230      public function pushBlockStack($name)
 231      {
 232          $this->blockStack[] = $name;
 233      }
 234   
 235      public function hasBlock($name)
 236      {
 237          return isset($this->blocks[$name]);
 238      }
 239   
 240      public function getBlock($name)
 241      {
 242          return $this->blocks[$name];
 243      }
 244   
 245      public function setBlock($name, Twig_Node_Block $value)
 246      {
 247          $this->blocks[$name] = new Twig_Node_Body(array($value), array(), $value->getLine());
 248      }
 249   
 250      public function hasMacro($name)
 251      {
 252          return isset($this->macros[$name]);
 253      }
 254   
 255      public function setMacro($name, Twig_Node_Macro $node)
 256      {
 257          if ($this->isReservedMacroName($name)) {
 258              throw new Twig_Error_Syntax(sprintf('"%s" cannot be used as a macro name as it is a reserved keyword.', $name), $node->getLine(), $this->getFilename());
 259          }
 260   
 261          $this->macros[$name] = $node;
 262      }
 263   
 264      public function isReservedMacroName($name)
 265      {
 266          if (null === $this->reservedMacroNames) {
 267              $this->reservedMacroNames = array();
 268              $r = new ReflectionClass($this->env->getBaseTemplateClass());
 269              foreach ($r->getMethods() as $method) {
 270                  $methodName = strtolower($method->getName());
 271   
 272                  if ('get' === substr($methodName, 0, 3) && isset($methodName[3])) {
 273                      $this->reservedMacroNames[] = substr($methodName, 3);
 274                  }
 275              }
 276          }
 277   
 278          return in_array(strtolower($name), $this->reservedMacroNames);
 279      }
 280   
 281      public function addTrait($trait)
 282      {
 283          $this->traits[] = $trait;
 284      }
 285   
 286      public function hasTraits()
 287      {
 288          return count($this->traits) > 0;
 289      }
 290   
 291      public function embedTemplate(Twig_Node_Module $template)
 292      {
 293          $template->setIndex(mt_rand());
 294   
 295          $this->embeddedTemplates[] = $template;
 296      }
 297   
 298      public function addImportedSymbol($type, $alias, $name = null, Twig_Node_Expression $node = null)
 299      {
 300          $this->importedSymbols[0][$type][$alias] = array('name' => $name, 'node' => $node);
 301      }
 302   
 303      public function getImportedSymbol($type, $alias)
 304      {
 305          foreach ($this->importedSymbols as $functions) {
 306              if (isset($functions[$type][$alias])) {
 307                  return $functions[$type][$alias];
 308              }
 309          }
 310      }
 311   
 312      public function isMainScope()
 313      {
 314          return 1 === count($this->importedSymbols);
 315      }
 316   
 317      public function pushLocalScope()
 318      {
 319          array_unshift($this->importedSymbols, array());
 320      }
 321   
 322      public function popLocalScope()
 323      {
 324          array_shift($this->importedSymbols);
 325      }
 326   
 327      /**
 328       * Gets the expression parser.
 329       *
 330       * @return Twig_ExpressionParser The expression parser
 331       */
 332      public function getExpressionParser()
 333      {
 334          return $this->expressionParser;
 335      }
 336   
 337      public function getParent()
 338      {
 339          return $this->parent;
 340      }
 341   
 342      public function setParent($parent)
 343      {
 344          $this->parent = $parent;
 345      }
 346   
 347      /**
 348       * Gets the token stream.
 349       *
 350       * @return Twig_TokenStream The token stream
 351       */
 352      public function getStream()
 353      {
 354          return $this->stream;
 355      }
 356   
 357      /**
 358       * Gets the current token.
 359       *
 360       * @return Twig_Token The current token
 361       */
 362      public function getCurrentToken()
 363      {
 364          return $this->stream->getCurrent();
 365      }
 366   
 367      protected function filterBodyNodes(Twig_NodeInterface $node)
 368      {
 369          // check that the body does not contain non-empty output nodes
 370          if (
 371              ($node instanceof Twig_Node_Text && !ctype_space($node->getAttribute('data')))
 372              ||
 373              (!$node instanceof Twig_Node_Text && !$node instanceof Twig_Node_BlockReference && $node instanceof Twig_NodeOutputInterface)
 374          ) {
 375              if (false !== strpos((string) $node, chr(0xEF).chr(0xBB).chr(0xBF))) {
 376                  throw new Twig_Error_Syntax('A template that extends another one cannot have a body but a byte order mark (BOM) has been detected; it must be removed.', $node->getLine(), $this->getFilename());
 377              }
 378   
 379              throw new Twig_Error_Syntax('A template that extends another one cannot have a body.', $node->getLine(), $this->getFilename());
 380          }
 381   
 382          // bypass "set" nodes as they "capture" the output
 383          if ($node instanceof Twig_Node_Set) {
 384              return $node;
 385          }
 386   
 387          if ($node instanceof Twig_NodeOutputInterface) {
 388              return;
 389          }
 390   
 391          foreach ($node as $k => $n) {
 392              if (null !== $n && null === $this->filterBodyNodes($n)) {
 393                  $node->removeNode($k);
 394              }
 395          }
 396   
 397          return $node;
 398      }
 399  }
 400