RouteExpressionParser::setParser()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
ccs 2
cts 2
cp 1
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
/*
4
 *
5
 * (c) Yaroslav Honcharuk <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Yarhon\RouteGuardBundle\Twig\TokenParser;
12
13
use Twig\Token;
14
use Twig\Parser;
15
use Twig\TokenStream;
16
use Twig\Node\Node;
17
use Twig_Error_Syntax as SyntaxError; // Workaround for PhpStorm to recognise type hints. Namespaced name: Twig\Error\SyntaxError
18
use Yarhon\RouteGuardBundle\Twig\Node\RouteExpression;
19
20
/**
21
 * @author Yaroslav Honcharuk <[email protected]>
22
 */
23
class RouteExpressionParser
24
{
25
    /**
26
     * @var Parser;
27
     */
28
    private $parser;
29
30
    /**
31
     * @param Parser $parser
32
     */
33 39
    public function setParser(Parser $parser)
34
    {
35 39
        $this->parser = $parser;
36 39
    }
37
38
    /**
39
     * @param Token $token
40
     *
41
     * @return RouteExpression
42
     *
43
     * @throws SyntaxError
44
     */
45 34
    public function parse(Token $token)
46
    {
47 34
        $routeContextArguments = $this->parseRouteContextArguments();
48 34
        $expression = new RouteExpression($routeContextArguments, $token->getLine());
49
50 33
        if ($generateAs = $this->parseGenerateAs()) {
51 23
            $expression->setGenerateAs(...$generateAs);
0 ignored issues
show
Bug introduced by
$generateAs is expanded, but the parameter $referenceType of Yarhon\RouteGuardBundle\...ession::setGenerateAs() does not expect variable arguments. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

51
            $expression->setGenerateAs(/** @scrutinizer ignore-type */ ...$generateAs);
Loading history...
52
        }
53
54 31
        return $expression;
55
    }
56
57 34
    private function parseRouteContextArguments()
58
    {
59 34
        $stream = $this->parser->getStream();
60 34
        $line = $stream->getCurrent()->getLine();
61
62 34
        $arguments = [];
63 34
        while (!$stream->test(Token::BLOCK_END_TYPE) && !$stream->test('as')) {
64 33
            if (count($arguments)) {
65 20
                $stream->expect(Token::PUNCTUATION_TYPE, ',', 'Arguments must be separated by a comma');
66
            }
67
68 33
            $arguments[] = $this->parser->getExpressionParser()->parseExpression();
69
        }
70
71 34
        return new Node($arguments, [], $line);
72
    }
73
74 33
    private function parseGenerateAs()
75
    {
76 33
        $stream = $this->parser->getStream();
77
78 33
        $generateAs = [];
79
80 33
        if ($stream->nextIf('as')) {
81
            // $functionName = $stream->expect(Token::NAME_TYPE, ['url', 'path'])->getValue();
82
            // Workaround for bug in Twig_TokenStream::expect() method. See self::streamExpect().
83 25
            $message = '"name" expected with value "url" or "path"';
84 25
            $referenceType = $this->streamExpect($stream, Token::NAME_TYPE, ['url', 'path'], $message)->getValue();
85 23
            $generateAs[] = $referenceType;
86
87 23
            if ($stream->test(['absolute', 'relative'])) {
88 2
                $relative = 'absolute' !== $stream->getCurrent()->getValue();
89 2
                $generateAs[] = $relative;
90 2
                $stream->next();
91
            }
92
        }
93
94 31
        return $generateAs;
95
    }
96
97
    /**
98
     * Workaround for bug inside \Twig_TokenStream::expect.
99
     * In case of invalid template syntax, when exception is thrown, if type and/or value argument is an array,
100
     * an "Array to string conversion" error happens:
101
     * - for type because of:  Twig_Token::typeToEnglish($type)
102
     * - for value because of: sprintf(' with value "%s"', $value).
103
     *
104
     * @param TokenStream       $stream
105
     * @param array|int         $type
106
     * @param array|string|null $values
107
     * @param string|null       $message
108
     *
109
     * @return Token
110
     *
111
     * @throws SyntaxError
112
     */
113 25
    private function streamExpect(TokenStream $stream, $type, $values = null, $message = null)
114
    {
115 25
        $token = $stream->getCurrent();
116 25
        if (!$token->test($type, $values)) {
117 2
            if ($message) {
118 2
                $message = ' ('.$message.')';
119
            }
120
121 2
            throw new SyntaxError(sprintf('Unexpected token "%s" of value "%s"%s.',
122 2
                Token::typeToEnglish($token->getType()), $token->getValue(), $message),
123 2
                $token->getLine(),
124 2
                $stream->getSourceContext()
125
            );
126
        }
127 23
        $stream->next();
128
129 23
        return $token;
130
    }
131
}
132