1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the puli/twig-puli-extension package. |
5
|
|
|
* |
6
|
|
|
* (c) Bernhard Schussek <[email protected]> |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace Puli\TwigExtension\NodeVisitor; |
13
|
|
|
|
14
|
|
|
use Puli\Repository\Api\ResourceRepository; |
15
|
|
|
use Puli\TwigExtension\PuliExtension; |
16
|
|
|
use Puli\UrlGenerator\Api\UrlGenerator; |
17
|
|
|
use RuntimeException; |
18
|
|
|
use Twig_Node; |
19
|
|
|
use Twig_Node_Expression_Constant; |
20
|
|
|
use Twig_Node_Expression_Function; |
21
|
|
|
use Twig_Node_Import; |
22
|
|
|
use Twig_Node_Include; |
23
|
|
|
use Twig_Node_Module; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* @since 1.0 |
27
|
|
|
* |
28
|
|
|
* @author Bernhard Schussek <[email protected]> |
29
|
|
|
*/ |
30
|
|
|
class TemplatePathResolver extends AbstractPathResolver |
31
|
|
|
{ |
32
|
|
|
/** |
33
|
|
|
* @var UrlGenerator |
34
|
|
|
*/ |
35
|
|
|
private $urlGenerator; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* @var bool |
39
|
|
|
*/ |
40
|
|
|
private $checkPaths; |
41
|
|
|
|
42
|
23 |
|
public function __construct(ResourceRepository $repo, UrlGenerator $urlGenerator = null, $checkPaths = false) |
43
|
|
|
{ |
44
|
23 |
|
parent::__construct($repo); |
45
|
|
|
|
46
|
23 |
|
$this->urlGenerator = $urlGenerator; |
47
|
23 |
|
$this->checkPaths = $checkPaths; |
48
|
23 |
|
} |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* Returns the priority for this visitor. |
52
|
|
|
* |
53
|
|
|
* Priority should be between -10 and 10 (0 is the default). |
54
|
|
|
* |
55
|
|
|
* @return int The priority level |
56
|
|
|
*/ |
57
|
23 |
|
public function getPriority() |
58
|
|
|
{ |
59
|
23 |
|
return PuliExtension::RESOLVE_PATHS; |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* {@inheritdoc} |
64
|
|
|
*/ |
65
|
19 |
|
protected function processNode(Twig_Node $node) |
66
|
|
|
{ |
67
|
19 |
|
if ($node instanceof Twig_Node_Module) { |
68
|
19 |
|
return $this->processModuleNode($node); |
69
|
|
|
} |
70
|
|
|
|
71
|
19 |
|
if ($node instanceof Twig_Node_Include) { |
72
|
6 |
|
return $this->processIncludeNode($node); |
73
|
|
|
} |
74
|
|
|
|
75
|
19 |
|
if ($node instanceof Twig_Node_Import) { |
76
|
2 |
|
return $this->processImportNode($node); |
77
|
|
|
} |
78
|
|
|
|
79
|
19 |
|
if ($node instanceof Twig_Node_Expression_Function && 'resource_url' === $node->getAttribute('name')) { |
80
|
3 |
|
return $this->processResourceUrlFunction($node); |
81
|
|
|
} |
82
|
|
|
|
83
|
19 |
|
return null; |
84
|
|
|
} |
85
|
|
|
|
86
|
19 |
|
private function processModuleNode(Twig_Node_Module $node) |
87
|
|
|
{ |
88
|
|
|
// Resolve relative parent template paths to absolute paths |
89
|
19 |
|
$parentNode = $node->getNode('parent'); |
90
|
19 |
|
$traitsNode = $node->getNode('traits'); |
91
|
|
|
|
92
|
|
|
// If the template extends another template, resolve the path |
93
|
19 |
|
if ($parentNode instanceof Twig_Node_Expression_Constant) { |
94
|
5 |
|
$this->processConstantNode($parentNode, $this->checkPaths); |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
// Resolve paths of embedded templates |
98
|
19 |
|
foreach ($node->getAttribute('embedded_templates') as $embeddedNode) { |
99
|
2 |
|
$this->processEmbeddedTemplateNode($embeddedNode); |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
// Resolve paths of used templates |
103
|
19 |
|
foreach ($traitsNode as $traitNode) { |
104
|
2 |
|
$this->processTraitNode($traitNode); |
105
|
|
|
} |
106
|
|
|
|
107
|
19 |
|
return null; |
108
|
|
|
} |
109
|
|
|
|
110
|
2 |
|
private function processEmbeddedTemplateNode(Twig_Node_Module $embeddedNode) |
111
|
|
|
{ |
112
|
2 |
|
$embedParent = $embeddedNode->getNode('parent'); |
113
|
|
|
|
114
|
|
|
// If the template extends another template, resolve the path |
115
|
2 |
|
if ($embedParent instanceof Twig_Node_Expression_Constant) { |
116
|
2 |
|
$this->processConstantNode($embedParent, $this->checkPaths); |
117
|
|
|
} |
118
|
2 |
|
} |
119
|
|
|
|
120
|
2 |
|
private function processTraitNode(Twig_Node $traitNode) |
121
|
|
|
{ |
122
|
2 |
|
$usedTemplate = $traitNode->getNode('template'); |
123
|
|
|
|
124
|
|
|
// If the template extends another template, resolve the path |
125
|
2 |
|
if ($usedTemplate instanceof Twig_Node_Expression_Constant) { |
126
|
2 |
|
$this->processConstantNode($usedTemplate, $this->checkPaths); |
127
|
|
|
} |
128
|
2 |
|
} |
129
|
|
|
|
130
|
6 |
View Code Duplication |
private function processIncludeNode(Twig_Node_Include $node) |
|
|
|
|
131
|
|
|
{ |
132
|
6 |
|
$exprNode = $node->getNode('expr'); |
133
|
|
|
|
134
|
6 |
|
if ($exprNode instanceof Twig_Node_Expression_Constant) { |
135
|
6 |
|
$this->processConstantNode($exprNode, $this->checkPaths); |
136
|
|
|
} |
137
|
|
|
|
138
|
6 |
|
return null; |
139
|
|
|
} |
140
|
|
|
|
141
|
2 |
View Code Duplication |
private function processImportNode(Twig_Node_Import $node) |
|
|
|
|
142
|
|
|
{ |
143
|
2 |
|
$exprNode = $node->getNode('expr'); |
144
|
|
|
|
145
|
2 |
|
if ($exprNode instanceof Twig_Node_Expression_Constant) { |
146
|
2 |
|
$this->processConstantNode($exprNode, $this->checkPaths); |
147
|
|
|
} |
148
|
|
|
|
149
|
2 |
|
return null; |
150
|
|
|
} |
151
|
|
|
|
152
|
3 |
|
protected function processResourceUrlFunction(Twig_Node $node) |
153
|
|
|
{ |
154
|
3 |
|
if (!$this->urlGenerator) { |
155
|
|
|
throw new RuntimeException( |
156
|
|
|
'The resource_url() function is only available if '. |
157
|
|
|
'puli/url-generator is installed.' |
158
|
|
|
); |
159
|
|
|
} |
160
|
|
|
|
161
|
3 |
|
$argsNode = $node->getNode('arguments'); |
162
|
|
|
|
163
|
3 |
|
if (!$argsNode->hasNode(0)) { |
164
|
|
|
return null; |
165
|
|
|
} |
166
|
|
|
|
167
|
3 |
|
$exprNode = $argsNode->getNode(0); |
168
|
|
|
|
169
|
3 |
|
if (!$exprNode instanceof Twig_Node_Expression_Constant) { |
170
|
|
|
return null; |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
// The paths passed to the resource_url() function must always be Puli |
174
|
|
|
// paths, so disable path checking |
175
|
3 |
|
$this->processConstantNode($exprNode, false); |
176
|
|
|
|
177
|
|
|
// Optimize away function call |
178
|
3 |
|
$exprNode->setAttribute('value', $this->urlGenerator->generateUrl($exprNode->getAttribute('value'))); |
179
|
|
|
|
180
|
3 |
|
return $exprNode; |
181
|
|
|
} |
182
|
|
|
|
183
|
16 |
|
private function processConstantNode(Twig_Node_Expression_Constant $node, $checkPath) |
184
|
|
|
{ |
185
|
16 |
|
$node->setAttribute('value', $this->resolvePath($node->getAttribute('value'), $checkPath)); |
186
|
16 |
|
} |
187
|
|
|
} |
188
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.