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