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 */
31final class IfTokenParser extends AbstractTokenParser
32{
33    public function parse(Token $token)
34    {
35        $lineno = $token->getLine();
36        $expr = $this->parser->getExpressionParser()->parseExpression();
37        $stream = $this->parser->getStream();
38        $stream->expect(/* Token::BLOCK_END_TYPE */ 3);
39        $body = $this->parser->subparse([$this, 'decideIfFork']);
40        $tests = [$expr, $body];
41        $else = null;
42
43        $end = false;
44        while (!$end) {
45            switch ($stream->next()->getValue()) {
46                case 'else':
47                    $stream->expect(/* Token::BLOCK_END_TYPE */ 3);
48                    $else = $this->parser->subparse([$this, 'decideIfEnd']);
49                    break;
50
51                case 'elseif':
52                    $expr = $this->parser->getExpressionParser()->parseExpression();
53                    $stream->expect(/* Token::BLOCK_END_TYPE */ 3);
54                    $body = $this->parser->subparse([$this, 'decideIfFork']);
55                    $tests[] = $expr;
56                    $tests[] = $body;
57                    break;
58
59                case 'endif':
60                    $end = true;
61                    break;
62
63                default:
64                    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());
65            }
66        }
67
68        $stream->expect(/* Token::BLOCK_END_TYPE */ 3);
69
70        return new IfNode(new Node($tests), $else, $lineno, $this->getTag());
71    }
72
73    public function decideIfFork(Token $token)
74    {
75        return $token->test(['elseif', 'else', 'endif']);
76    }
77
78    public function decideIfEnd(Token $token)
79    {
80        return $token->test(['endif']);
81    }
82
83    public function getTag()
84    {
85        return 'if';
86    }
87}
88
89class_alias('Twig\TokenParser\IfTokenParser', 'Twig_TokenParser_If');
90