1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace MyWheels\TwigSpreadsheetBundle\Twig\NodeVisitor; |
4
|
|
|
|
5
|
|
|
use MyWheels\TwigSpreadsheetBundle\Twig\Node\BaseNode; |
6
|
|
|
use MyWheels\TwigSpreadsheetBundle\Twig\Node\DocumentNode; |
7
|
|
|
|
8
|
|
|
/** |
9
|
|
|
* Class SyntaxCheckNodeVisitor. |
10
|
|
|
*/ |
11
|
|
|
class SyntaxCheckNodeVisitor extends \Twig_BaseNodeVisitor |
|
|
|
|
12
|
|
|
{ |
13
|
|
|
/** |
14
|
|
|
* @var array |
15
|
|
|
*/ |
16
|
|
|
protected $path = []; |
17
|
|
|
|
18
|
|
|
/** |
19
|
|
|
* {@inheritdoc} |
20
|
|
|
*/ |
21
|
51 |
|
public function getPriority() |
22
|
|
|
{ |
23
|
51 |
|
return 0; |
24
|
|
|
} |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* {@inheritdoc} |
28
|
|
|
* |
29
|
|
|
* @throws \Twig_Error_Syntax |
30
|
|
|
*/ |
31
|
51 |
|
protected function doEnterNode(\Twig_Node $node, \Twig_Environment $env) |
32
|
|
|
{ |
33
|
|
|
try { |
34
|
51 |
|
if ($node instanceof BaseNode) { |
35
|
42 |
|
$this->checkAllowedParents($node); |
36
|
|
|
} else { |
37
|
51 |
|
$this->checkAllowedChildren($node); |
38
|
|
|
} |
39
|
16 |
|
} catch (\Twig_Error_Syntax $e) { |
40
|
|
|
// reset path since throwing an error prevents doLeaveNode to be called |
41
|
16 |
|
$this->path = []; |
42
|
16 |
|
throw $e; |
43
|
|
|
} |
44
|
|
|
|
45
|
51 |
|
$this->path[] = $node !== null ? \get_class($node) : null; |
46
|
|
|
|
47
|
51 |
|
return $node; |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* {@inheritdoc} |
52
|
|
|
*/ |
53
|
43 |
|
protected function doLeaveNode(\Twig_Node $node, \ Twig_Environment $env) |
54
|
|
|
{ |
55
|
43 |
|
array_pop($this->path); |
56
|
|
|
|
57
|
43 |
|
return $node; |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* @param \Twig_Node $node |
62
|
|
|
* |
63
|
|
|
* @throws \Twig_Error_Syntax |
64
|
|
|
*/ |
65
|
51 |
|
private function checkAllowedChildren(\Twig_Node $node) |
66
|
|
|
{ |
67
|
51 |
|
$hasDocumentNode = false; |
68
|
51 |
|
$hasTextNode = false; |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* @var \Twig_Node $currentNode |
72
|
|
|
*/ |
73
|
51 |
|
foreach ($node->getIterator() as $currentNode) { |
74
|
51 |
|
if ($currentNode instanceof \Twig_Node_Text) { |
75
|
45 |
|
if ($hasDocumentNode) { |
76
|
4 |
|
throw new \Twig_Error_Syntax(sprintf('Node "%s" is not allowed after Node "%s".', \Twig_Node_Text::class, DocumentNode::class)); |
|
|
|
|
77
|
|
|
} |
78
|
41 |
|
$hasTextNode = true; |
79
|
51 |
|
} elseif ($currentNode instanceof DocumentNode) { |
80
|
43 |
|
if ($hasTextNode) { |
81
|
4 |
|
throw new \Twig_Error_Syntax(sprintf('Node "%s" is not allowed before Node "%s".', \Twig_Node_Text::class, DocumentNode::class)); |
|
|
|
|
82
|
|
|
} |
83
|
51 |
|
$hasDocumentNode = true; |
84
|
|
|
} |
85
|
|
|
} |
86
|
51 |
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* @param BaseNode $node |
90
|
|
|
* |
91
|
|
|
* @throws \Twig_Error_Syntax |
92
|
|
|
*/ |
93
|
42 |
|
private function checkAllowedParents(BaseNode $node) |
94
|
|
|
{ |
95
|
42 |
|
$parentName = null; |
96
|
|
|
|
97
|
|
|
// find first parent from this bundle |
98
|
42 |
|
foreach (array_reverse($this->path) as $className) { |
99
|
42 |
|
if (strpos($className, 'MyWheels\\TwigSpreadsheetBundle\\Twig\\Node\\') === 0) { |
100
|
39 |
|
$parentName = $className; |
101
|
42 |
|
break; |
102
|
|
|
} |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
// allow no parents (e.g. macros, includes) |
106
|
42 |
|
if ($parentName === null) { |
107
|
42 |
|
return; |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
// check if parent is allowed |
111
|
39 |
|
foreach ($node->getAllowedParents() as $className) { |
112
|
35 |
|
if ($className === $parentName) { |
113
|
35 |
|
return; |
114
|
|
|
} |
115
|
|
|
} |
116
|
|
|
|
117
|
8 |
|
throw new \Twig_Error_Syntax(sprintf('Node "%s" is not allowed inside of Node "%s".', \get_class($node), $parentName)); |
|
|
|
|
118
|
|
|
} |
119
|
|
|
} |
120
|
|
|
|
This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.