PluginProbe
WebTotem Security / 3.0.1
WebTotem Security v3.0.1
3.0.1 3.0.0 trunk 1.0 1.1 1.2 1.3 1.3.1 1.3.2 1.3.3 2.0 2.1 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.1 2.2.2 2.2.3 2.2.4 All 109 releases
wt-security / vendor / twig / twig / src / Node / ModuleNode.php

ModuleNode.php in WebTotem Security 3.0.1, at vendor/twig/twig/src/Node/ModuleNode.php

465 lines 14.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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
13 namespace Twig\Node;
14
15 use Twig\Compiler;
16 use Twig\Node\Expression\AbstractExpression;
17 use Twig\Node\Expression\ConstantExpression;
18 use Twig\Source;
19
20 /**
21 * Represents a module node.
22 *
23 * Consider this class as being final. If you need to customize the behavior of
24 * the generated class, consider adding nodes to the following nodes: display_start,
25 * display_end, constructor_start, constructor_end, and class_end.
26 *
27 * @author Fabien Potencier <fabien@symfony.com>
28 */
29 final class ModuleNode extends Node
30 {
31 public function __construct(Node $body, ?AbstractExpression $parent, Node $blocks, Node $macros, Node $traits, $embeddedTemplates, Source $source)
32 {
33 $nodes = [
34 'body' => $body,
35 'blocks' => $blocks,
36 'macros' => $macros,
37 'traits' => $traits,
38 'display_start' => new Node(),
39 'display_end' => new Node(),
40 'constructor_start' => new Node(),
41 'constructor_end' => new Node(),
42 'class_end' => new Node(),
43 ];
44 if (null !== $parent) {
45 $nodes['parent'] = $parent;
46 }
47
48 // embedded templates are set as attributes so that they are only visited once by the visitors
49 parent::__construct($nodes, [
50 'index' => null,
51 'embedded_templates' => $embeddedTemplates,
52 ], 1);
53
54 // populate the template name of all node children
55 $this->setSourceContext($source);
56 }
57
58 public function setIndex($index)
59 {
60 $this->setAttribute('index', $index);
61 }
62
63 public function compile(Compiler $compiler): void
64 {
65 $this->compileTemplate($compiler);
66
67 foreach ($this->getAttribute('embedded_templates') as $template) {
68 $compiler->subcompile($template);
69 }
70 }
71
72 protected function compileTemplate(Compiler $compiler)
73 {
74 if (!$this->getAttribute('index')) {
75 $compiler->write('<?php');
76 }
77
78 $this->compileClassHeader($compiler);
79
80 $this->compileConstructor($compiler);
81
82 $this->compileGetParent($compiler);
83
84 $this->compileDisplay($compiler);
85
86 $compiler->subcompile($this->getNode('blocks'));
87
88 $this->compileMacros($compiler);
89
90 $this->compileGetTemplateName($compiler);
91
92 $this->compileIsTraitable($compiler);
93
94 $this->compileDebugInfo($compiler);
95
96 $this->compileGetSourceContext($compiler);
97
98 $this->compileClassFooter($compiler);
99 }
100
101 protected function compileGetParent(Compiler $compiler)
102 {
103 if (!$this->hasNode('parent')) {
104 return;
105 }
106 $parent = $this->getNode('parent');
107
108 $compiler
109 ->write("protected function doGetParent(array \$context)\n", "{\n")
110 ->indent()
111 ->addDebugInfo($parent)
112 ->write('return ')
113 ;
114
115 if ($parent instanceof ConstantExpression) {
116 $compiler->subcompile($parent);
117 } else {
118 $compiler
119 ->raw('$this->loadTemplate(')
120 ->subcompile($parent)
121 ->raw(', ')
122 ->repr($this->getSourceContext()->getName())
123 ->raw(', ')
124 ->repr($parent->getTemplateLine())
125 ->raw(')')
126 ;
127 }
128
129 $compiler
130 ->raw(";\n")
131 ->outdent()
132 ->write("}\n\n")
133 ;
134 }
135
136 protected function compileClassHeader(Compiler $compiler)
137 {
138 $compiler
139 ->write("\n\n")
140 ;
141 if (!$this->getAttribute('index')) {
142 $compiler
143 ->write("use Twig\Environment;\n")
144 ->write("use Twig\Error\LoaderError;\n")
145 ->write("use Twig\Error\RuntimeError;\n")
146 ->write("use Twig\Extension\SandboxExtension;\n")
147 ->write("use Twig\Markup;\n")
148 ->write("use Twig\Sandbox\SecurityError;\n")
149 ->write("use Twig\Sandbox\SecurityNotAllowedTagError;\n")
150 ->write("use Twig\Sandbox\SecurityNotAllowedFilterError;\n")
151 ->write("use Twig\Sandbox\SecurityNotAllowedFunctionError;\n")
152 ->write("use Twig\Source;\n")
153 ->write("use Twig\Template;\n\n")
154 ;
155 }
156 $compiler
157 // if the template name contains */, add a blank to avoid a PHP parse error
158 ->write('/* '.str_replace('*/', '* /', $this->getSourceContext()->getName())." */\n")
159 ->write('class '.$compiler->getEnvironment()->getTemplateClass($this->getSourceContext()->getName(), $this->getAttribute('index')))
160 ->raw(" extends Template\n")
161 ->write("{\n")
162 ->indent()
163 ->write("private \$source;\n")
164 ->write("private \$macros = [];\n\n")
165 ;
166 }
167
168 protected function compileConstructor(Compiler $compiler)
169 {
170 $compiler
171 ->write("public function __construct(Environment \$env)\n", "{\n")
172 ->indent()
173 ->subcompile($this->getNode('constructor_start'))
174 ->write("parent::__construct(\$env);\n\n")
175 ->write("\$this->source = \$this->getSourceContext();\n\n")
176 ;
177
178 // parent
179 if (!$this->hasNode('parent')) {
180 $compiler->write("\$this->parent = false;\n\n");
181 }
182
183 $countTraits = \count($this->getNode('traits'));
184 if ($countTraits) {
185 // traits
186 foreach ($this->getNode('traits') as $i => $trait) {
187 $node = $trait->getNode('template');
188
189 $compiler
190 ->addDebugInfo($node)
191 ->write(sprintf('$_trait_%s = $this->loadTemplate(', $i))
192 ->subcompile($node)
193 ->raw(', ')
194 ->repr($node->getTemplateName())
195 ->raw(', ')
196 ->repr($node->getTemplateLine())
197 ->raw(");\n")
198 ->write(sprintf("if (!\$_trait_%s->isTraitable()) {\n", $i))
199 ->indent()
200 ->write("throw new RuntimeError('Template \"'.")
201 ->subcompile($trait->getNode('template'))
202 ->raw(".'\" cannot be used as a trait.', ")
203 ->repr($node->getTemplateLine())
204 ->raw(", \$this->source);\n")
205 ->outdent()
206 ->write("}\n")
207 ->write(sprintf("\$_trait_%s_blocks = \$_trait_%s->getBlocks();\n\n", $i, $i))
208 ;
209
210 foreach ($trait->getNode('targets') as $key => $value) {
211 $compiler
212 ->write(sprintf('if (!isset($_trait_%s_blocks[', $i))
213 ->string($key)
214 ->raw("])) {\n")
215 ->indent()
216 ->write("throw new RuntimeError('Block ")
217 ->string($key)
218 ->raw(' is not defined in trait ')
219 ->subcompile($trait->getNode('template'))
220 ->raw(".', ")
221 ->repr($node->getTemplateLine())
222 ->raw(", \$this->source);\n")
223 ->outdent()
224 ->write("}\n\n")
225
226 ->write(sprintf('$_trait_%s_blocks[', $i))
227 ->subcompile($value)
228 ->raw(sprintf('] = $_trait_%s_blocks[', $i))
229 ->string($key)
230 ->raw(sprintf(']; unset($_trait_%s_blocks[', $i))
231 ->string($key)
232 ->raw("]);\n\n")
233 ;
234 }
235 }
236
237 if ($countTraits > 1) {
238 $compiler
239 ->write("\$this->traits = array_merge(\n")
240 ->indent()
241 ;
242
243 for ($i = 0; $i < $countTraits; ++$i) {
244 $compiler
245 ->write(sprintf('$_trait_%s_blocks'.($i == $countTraits - 1 ? '' : ',')."\n", $i))
246 ;
247 }
248
249 $compiler
250 ->outdent()
251 ->write(");\n\n")
252 ;
253 } else {
254 $compiler
255 ->write("\$this->traits = \$_trait_0_blocks;\n\n")
256 ;
257 }
258
259 $compiler
260 ->write("\$this->blocks = array_merge(\n")
261 ->indent()
262 ->write("\$this->traits,\n")
263 ->write("[\n")
264 ;
265 } else {
266 $compiler
267 ->write("\$this->blocks = [\n")
268 ;
269 }
270
271 // blocks
272 $compiler
273 ->indent()
274 ;
275
276 foreach ($this->getNode('blocks') as $name => $node) {
277 $compiler
278 ->write(sprintf("'%s' => [\$this, 'block_%s'],\n", $name, $name))
279 ;
280 }
281
282 if ($countTraits) {
283 $compiler
284 ->outdent()
285 ->write("]\n")
286 ->outdent()
287 ->write(");\n")
288 ;
289 } else {
290 $compiler
291 ->outdent()
292 ->write("];\n")
293 ;
294 }
295
296 $compiler
297 ->subcompile($this->getNode('constructor_end'))
298 ->outdent()
299 ->write("}\n\n")
300 ;
301 }
302
303 protected function compileDisplay(Compiler $compiler)
304 {
305 $compiler
306 ->write("protected function doDisplay(array \$context, array \$blocks = [])\n", "{\n")
307 ->indent()
308 ->write("\$macros = \$this->macros;\n")
309 ->subcompile($this->getNode('display_start'))
310 ->subcompile($this->getNode('body'))
311 ;
312
313 if ($this->hasNode('parent')) {
314 $parent = $this->getNode('parent');
315
316 $compiler->addDebugInfo($parent);
317 if ($parent instanceof ConstantExpression) {
318 $compiler
319 ->write('$this->parent = $this->loadTemplate(')
320 ->subcompile($parent)
321 ->raw(', ')
322 ->repr($this->getSourceContext()->getName())
323 ->raw(', ')
324 ->repr($parent->getTemplateLine())
325 ->raw(");\n")
326 ;
327 $compiler->write('$this->parent');
328 } else {
329 $compiler->write('$this->getParent($context)');
330 }
331 $compiler->raw("->display(\$context, array_merge(\$this->blocks, \$blocks));\n");
332 }
333
334 $compiler
335 ->subcompile($this->getNode('display_end'))
336 ->outdent()
337 ->write("}\n\n")
338 ;
339 }
340
341 protected function compileClassFooter(Compiler $compiler)
342 {
343 $compiler
344 ->subcompile($this->getNode('class_end'))
345 ->outdent()
346 ->write("}\n")
347 ;
348 }
349
350 protected function compileMacros(Compiler $compiler)
351 {
352 $compiler->subcompile($this->getNode('macros'));
353 }
354
355 protected function compileGetTemplateName(Compiler $compiler)
356 {
357 $compiler
358 ->write("public function getTemplateName()\n", "{\n")
359 ->indent()
360 ->write('return ')
361 ->repr($this->getSourceContext()->getName())
362 ->raw(";\n")
363 ->outdent()
364 ->write("}\n\n")
365 ;
366 }
367
368 protected function compileIsTraitable(Compiler $compiler)
369 {
370 // A template can be used as a trait if:
371 // * it has no parent
372 // * it has no macros
373 // * it has no body
374 //
375 // Put another way, a template can be used as a trait if it
376 // only contains blocks and use statements.
377 $traitable = !$this->hasNode('parent') && 0 === \count($this->getNode('macros'));
378 if ($traitable) {
379 if ($this->getNode('body') instanceof BodyNode) {
380 $nodes = $this->getNode('body')->getNode(0);
381 } else {
382 $nodes = $this->getNode('body');
383 }
384
385 if (!\count($nodes)) {
386 $nodes = new Node([$nodes]);
387 }
388
389 foreach ($nodes as $node) {
390 if (!\count($node)) {
391 continue;
392 }
393
394 if ($node instanceof TextNode && ctype_space($node->getAttribute('data'))) {
395 continue;
396 }
397
398 if ($node instanceof BlockReferenceNode) {
399 continue;
400 }
401
402 $traitable = false;
403 break;
404 }
405 }
406
407 if ($traitable) {
408 return;
409 }
410
411 $compiler
412 ->write("public function isTraitable()\n", "{\n")
413 ->indent()
414 ->write(sprintf("return %s;\n", $traitable ? 'true' : 'false'))
415 ->outdent()
416 ->write("}\n\n")
417 ;
418 }
419
420 protected function compileDebugInfo(Compiler $compiler)
421 {
422 $compiler
423 ->write("public function getDebugInfo()\n", "{\n")
424 ->indent()
425 ->write(sprintf("return %s;\n", str_replace("\n", '', var_export(array_reverse($compiler->getDebugInfo(), true), true))))
426 ->outdent()
427 ->write("}\n\n")
428 ;
429 }
430
431 protected function compileGetSourceContext(Compiler $compiler)
432 {
433 $compiler
434 ->write("public function getSourceContext()\n", "{\n")
435 ->indent()
436 ->write('return new Source(')
437 ->string($compiler->getEnvironment()->isDebug() ? $this->getSourceContext()->getCode() : '')
438 ->raw(', ')
439 ->string($this->getSourceContext()->getName())
440 ->raw(', ')
441 ->string($this->getSourceContext()->getPath())
442 ->raw(");\n")
443 ->outdent()
444 ->write("}\n")
445 ;
446 }
447
448 protected function compileLoadTemplate(Compiler $compiler, $node, $var)
449 {
450 if ($node instanceof ConstantExpression) {
451 $compiler
452 ->write(sprintf('%s = $this->loadTemplate(', $var))
453 ->subcompile($node)
454 ->raw(', ')
455 ->repr($node->getTemplateName())
456 ->raw(', ')
457 ->repr($node->getTemplateLine())
458 ->raw(");\n")
459 ;
460 } else {
461 throw new \LogicException('Trait templates can only be constant nodes.');
462 }
463 }
464 }
465