AbstractNodeTest   A
last analyzed

Complexity

Total Complexity 7

Size/Duplication

Total Lines 98
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 7
eloc 35
dl 0
loc 98
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A parse() 0 25 1
A hackLineNumbers() 0 19 4
A compile() 0 7 1
A setUp() 0 10 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\Tests\Twig;
12
13
use PHPUnit\Framework\TestCase;
14
use Twig\Environment;
15
use Twig\Parser;
16
use Twig\Source;
17
use Twig\Compiler;
18
use Twig\Node\Node;
19
use Twig\Token;
20
use Twig\TokenStream;
21
use Twig\TwigFunction;
22
use Twig_Error_Syntax as SyntaxError; // Workaround for PhpStorm to recognise type hints. Namespaced name: Twig\Error\SyntaxError
23
use Yarhon\RouteGuardBundle\Twig\TokenParser\RouteTokenParser;
24
use Yarhon\RouteGuardBundle\Twig\Node\RouteNode;
25
26
abstract class AbstractNodeTest extends TestCase
27
{
28
    /**
29
     * @var Environment
30
     */
31
    protected $environment;
32
33
    private $tagName = 'route';
34
35
    private $tagVariableName = '_route';
36
37
    public function setUp()
38
    {
39
        $loader = $this->getMockBuilder(\Twig\Loader\LoaderInterface::class)->getMock();
40
41
        $this->environment = new Environment($loader, ['cache' => false, 'autoescape' => false, 'optimizations' => 0]);
42
43
        $this->environment->addTokenParser(new RouteTokenParser($this->tagName, false));
44
        $this->environment->addFunction(new TwigFunction('route_guard_route', function () {}));
45
46
        RouteNode::setVariableName($this->tagVariableName);
47
    }
48
49
    /**
50
     * @param string $source
51
     *
52
     * @return Node
53
     *
54
     * @throws SyntaxError
55
     * @throws \ReflectionException
56
     */
57
    protected function parse($source)
58
    {
59
        $replacements = [
60
            '$tagName' => $this->tagName,
61
        ];
62
        $source = strtr($source, $replacements);
63
64
        // "name" (template name) parameter as null is significant for the private $name property
65
        // of parsed Node instances to be propagated with null value (it's default value).
66
        // Then properties of this instances would be strictly equal to properties
67
        // of Node instances created in test cases.
68
        $source = new Source($source, null);
69
        $stream = $this->environment->tokenize($source);
70
71
        // Twig lexer will set line numbers starting from 1 (and only 1, if source is one-line string).
72
        // This sets line numbers of all tokens to 0 (default value in Node class constructor)
73
        // to allow skip non-required line number parameters in Nodes instances created in test cases.
74
        $this->hackLineNumbers($stream, 0);
75
76
        $parser = new Parser($this->environment);
77
78
        $node = $parser->parse($stream);
79
        $node = $node->getNode('body')->getNode(0);
80
81
        return $node;
82
    }
83
84
    /**
85
     * @param TokenStream $stream
86
     * @param $line
87
     *
88
     * @throws \ReflectionException
89
     */
90
    protected function hackLineNumbers(TokenStream $stream, $line)
91
    {
92
        $tokens = [];
93
94
        $i = 1;
95
        while (true) {
96
            try {
97
                $tokens[] = $stream->look($i);
98
                ++$i;
99
            } catch (SyntaxError $e) {
100
                break;
101
            }
102
        }
103
104
        $property = new \ReflectionProperty(Token::class, 'lineno');
105
        $property->setAccessible(true);
106
107
        foreach ($tokens as $token) {
108
            $property->setValue($token, $line);
109
        }
110
    }
111
112
    /**
113
     * @param Node $node
114
     *
115
     * @return string
116
     */
117
    protected function compile(Node $node)
118
    {
119
        $compiler = new Compiler($this->environment);
120
        $compiler->compile($node);
121
        $source = $compiler->getSource();
122
123
        return $source;
124
    }
125
}
126