blob: c0fe6df0d10af102c72f1e9d05d7277fd346d2aa [file] [log] [blame]
Matthias Andreas Benkard12a57352021-12-28 18:02:04 +01001<?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
13namespace Twig\TokenParser;
14
15use Twig\Error\SyntaxError;
16use Twig\Node\IfNode;
17use Twig\Node\Node;
18use Twig\Token;
19
20/**
21 * Tests a condition.
22 *
23 * {% if users %}
24 * <ul>
25 * {% for user in users %}
26 * <li>{{ user.username|e }}</li>
27 * {% endfor %}
28 * </ul>
29 * {% endif %}
30 *
31 * @internal
32 */
33final class IfTokenParser extends AbstractTokenParser
34{
35 public function parse(Token $token): Node
36 {
37 $lineno = $token->getLine();
38 $expr = $this->parser->getExpressionParser()->parseExpression();
39 $stream = $this->parser->getStream();
40 $stream->expect(/* Token::BLOCK_END_TYPE */ 3);
41 $body = $this->parser->subparse([$this, 'decideIfFork']);
42 $tests = [$expr, $body];
43 $else = null;
44
45 $end = false;
46 while (!$end) {
47 switch ($stream->next()->getValue()) {
48 case 'else':
49 $stream->expect(/* Token::BLOCK_END_TYPE */ 3);
50 $else = $this->parser->subparse([$this, 'decideIfEnd']);
51 break;
52
53 case 'elseif':
54 $expr = $this->parser->getExpressionParser()->parseExpression();
55 $stream->expect(/* Token::BLOCK_END_TYPE */ 3);
56 $body = $this->parser->subparse([$this, 'decideIfFork']);
57 $tests[] = $expr;
58 $tests[] = $body;
59 break;
60
61 case 'endif':
62 $end = true;
63 break;
64
65 default:
66 throw new SyntaxError(sprintf('Unexpected end of template. Twig was looking for the following tags "else", "elseif", or "endif" to close the "if" block started at line %d).', $lineno), $stream->getCurrent()->getLine(), $stream->getSourceContext());
67 }
68 }
69
70 $stream->expect(/* Token::BLOCK_END_TYPE */ 3);
71
72 return new IfNode(new Node($tests), $else, $lineno, $this->getTag());
73 }
74
75 public function decideIfFork(Token $token): bool
76 {
77 return $token->test(['elseif', 'else', 'endif']);
78 }
79
80 public function decideIfEnd(Token $token): bool
81 {
82 return $token->test(['endif']);
83 }
84
85 public function getTag(): string
86 {
87 return 'if';
88 }
89}