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
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 * @final
32 */
33class IfTokenParser extends AbstractTokenParser
34{
35    public function parse(Token $token)
36    {
37        $lineno = $token->getLine();
38        $expr = $this->parser->getExpressionParser()->parseExpression();
39        $stream = $this->parser->getStream();
40        $stream->expect(Token::BLOCK_END_TYPE);
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);
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);
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);
71
72        return new IfNode(new Node($tests), $else, $lineno, $this->getTag());
73    }
74
75    public function decideIfFork(Token $token)
76    {
77        return $token->test(['elseif', 'else', 'endif']);
78    }
79
80    public function decideIfEnd(Token $token)
81    {
82        return $token->test(['endif']);
83    }
84
85    public function getTag()
86    {
87        return 'if';
88    }
89}
90
91class_alias('Twig\TokenParser\IfTokenParser', 'Twig_TokenParser_If');
92