[ Index ]

PHP Cross Reference of phpBB-3.2.8-deutsch

title

Body

[close]

/vendor/twig/twig/src/TokenParser/ -> ForTokenParser.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\TokenParser;
  14  
  15  use Twig\Error\SyntaxError;
  16  use Twig\Node\Expression\AssignNameExpression;
  17  use Twig\Node\Expression\ConstantExpression;
  18  use Twig\Node\Expression\GetAttrExpression;
  19  use Twig\Node\Expression\NameExpression;
  20  use Twig\Node\ForNode;
  21  use Twig\Token;
  22  use Twig\TokenStream;
  23  
  24  /**
  25   * Loops over each item of a sequence.
  26   *
  27   *   <ul>
  28   *    {% for user in users %}
  29   *      <li>{{ user.username|e }}</li>
  30   *    {% endfor %}
  31   *   </ul>
  32   *
  33   * @final
  34   */
  35  class ForTokenParser extends AbstractTokenParser
  36  {
  37      public function parse(Token $token)
  38      {
  39          $lineno = $token->getLine();
  40          $stream = $this->parser->getStream();
  41          $targets = $this->parser->getExpressionParser()->parseAssignmentExpression();
  42          $stream->expect(Token::OPERATOR_TYPE, 'in');
  43          $seq = $this->parser->getExpressionParser()->parseExpression();
  44  
  45          $ifexpr = null;
  46          if ($stream->nextIf(Token::NAME_TYPE, 'if')) {
  47              $ifexpr = $this->parser->getExpressionParser()->parseExpression();
  48          }
  49  
  50          $stream->expect(Token::BLOCK_END_TYPE);
  51          $body = $this->parser->subparse([$this, 'decideForFork']);
  52          if ('else' == $stream->next()->getValue()) {
  53              $stream->expect(Token::BLOCK_END_TYPE);
  54              $else = $this->parser->subparse([$this, 'decideForEnd'], true);
  55          } else {
  56              $else = null;
  57          }
  58          $stream->expect(Token::BLOCK_END_TYPE);
  59  
  60          if (\count($targets) > 1) {
  61              $keyTarget = $targets->getNode(0);
  62              $keyTarget = new AssignNameExpression($keyTarget->getAttribute('name'), $keyTarget->getTemplateLine());
  63              $valueTarget = $targets->getNode(1);
  64              $valueTarget = new AssignNameExpression($valueTarget->getAttribute('name'), $valueTarget->getTemplateLine());
  65          } else {
  66              $keyTarget = new AssignNameExpression('_key', $lineno);
  67              $valueTarget = $targets->getNode(0);
  68              $valueTarget = new AssignNameExpression($valueTarget->getAttribute('name'), $valueTarget->getTemplateLine());
  69          }
  70  
  71          if ($ifexpr) {
  72              $this->checkLoopUsageCondition($stream, $ifexpr);
  73              $this->checkLoopUsageBody($stream, $body);
  74          }
  75  
  76          return new ForNode($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, $lineno, $this->getTag());
  77      }
  78  
  79      public function decideForFork(Token $token)
  80      {
  81          return $token->test(['else', 'endfor']);
  82      }
  83  
  84      public function decideForEnd(Token $token)
  85      {
  86          return $token->test('endfor');
  87      }
  88  
  89      // the loop variable cannot be used in the condition
  90      protected function checkLoopUsageCondition(TokenStream $stream, \Twig_NodeInterface $node)
  91      {
  92          if ($node instanceof GetAttrExpression && $node->getNode('node') instanceof NameExpression && 'loop' == $node->getNode('node')->getAttribute('name')) {
  93              throw new SyntaxError('The "loop" variable cannot be used in a looping condition.', $node->getTemplateLine(), $stream->getSourceContext());
  94          }
  95  
  96          foreach ($node as $n) {
  97              if (!$n) {
  98                  continue;
  99              }
 100  
 101              $this->checkLoopUsageCondition($stream, $n);
 102          }
 103      }
 104  
 105      // check usage of non-defined loop-items
 106      // it does not catch all problems (for instance when a for is included into another or when the variable is used in an include)
 107      protected function checkLoopUsageBody(TokenStream $stream, \Twig_NodeInterface $node)
 108      {
 109          if ($node instanceof GetAttrExpression && $node->getNode('node') instanceof NameExpression && 'loop' == $node->getNode('node')->getAttribute('name')) {
 110              $attribute = $node->getNode('attribute');
 111              if ($attribute instanceof ConstantExpression && \in_array($attribute->getAttribute('value'), ['length', 'revindex0', 'revindex', 'last'])) {
 112                  throw new SyntaxError(sprintf('The "loop.%s" variable is not defined when looping with a condition.', $attribute->getAttribute('value')), $node->getTemplateLine(), $stream->getSourceContext());
 113              }
 114          }
 115  
 116          // should check for parent.loop.XXX usage
 117          if ($node instanceof ForNode) {
 118              return;
 119          }
 120  
 121          foreach ($node as $n) {
 122              if (!$n) {
 123                  continue;
 124              }
 125  
 126              $this->checkLoopUsageBody($stream, $n);
 127          }
 128      }
 129  
 130      public function getTag()
 131      {
 132          return 'for';
 133      }
 134  }
 135  
 136  class_alias('Twig\TokenParser\ForTokenParser', 'Twig_TokenParser_For');


Generated: Tue Apr 7 19:42:26 2020 Cross-referenced by PHPXref 0.7.1