[ Index ]

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


Generated: Sun Jun 23 12:25:44 2024 Cross-referenced by PHPXref 0.7.1