blob: af477e6535691b06c47e5b3687a501414309159c [file] [log] [blame]
Matthias Andreas Benkard12a57352021-12-28 18:02:04 +01001<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) Fabien Potencier
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Twig\NodeVisitor;
13
14use Twig\Environment;
15use Twig\Node\Expression\AssignNameExpression;
16use Twig\Node\Expression\ConstantExpression;
17use Twig\Node\Expression\GetAttrExpression;
18use Twig\Node\Expression\MethodCallExpression;
19use Twig\Node\Expression\NameExpression;
20use Twig\Node\ImportNode;
21use Twig\Node\ModuleNode;
22use Twig\Node\Node;
23
24/**
25 * @author Fabien Potencier <fabien@symfony.com>
26 *
27 * @internal
28 */
29final class MacroAutoImportNodeVisitor implements NodeVisitorInterface
30{
31 private $inAModule = false;
32 private $hasMacroCalls = false;
33
34 public function enterNode(Node $node, Environment $env): Node
35 {
36 if ($node instanceof ModuleNode) {
37 $this->inAModule = true;
38 $this->hasMacroCalls = false;
39 }
40
41 return $node;
42 }
43
44 public function leaveNode(Node $node, Environment $env): Node
45 {
46 if ($node instanceof ModuleNode) {
47 $this->inAModule = false;
48 if ($this->hasMacroCalls) {
49 $node->getNode('constructor_end')->setNode('_auto_macro_import', new ImportNode(new NameExpression('_self', 0), new AssignNameExpression('_self', 0), 0, 'import', true));
50 }
51 } elseif ($this->inAModule) {
52 if (
53 $node instanceof GetAttrExpression &&
54 $node->getNode('node') instanceof NameExpression &&
55 '_self' === $node->getNode('node')->getAttribute('name') &&
56 $node->getNode('attribute') instanceof ConstantExpression
57 ) {
58 $this->hasMacroCalls = true;
59
60 $name = $node->getNode('attribute')->getAttribute('value');
61 $node = new MethodCallExpression($node->getNode('node'), 'macro_'.$name, $node->getNode('arguments'), $node->getTemplateLine());
62 $node->setAttribute('safe', true);
63 }
64 }
65
66 return $node;
67 }
68
69 public function getPriority(): int
70 {
71 // we must be ran before auto-escaping
72 return -10;
73 }
74}