1<?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;
13
14use Twig\NodeVisitor\NodeVisitorInterface;
15
16/**
17 * A node traverser.
18 *
19 * It visits all nodes and their children and calls the given visitor for each.
20 *
21 * @final
22 *
23 * @author Fabien Potencier <fabien@symfony.com>
24 */
25class NodeTraverser
26{
27    protected $env;
28    protected $visitors = [];
29
30    /**
31     * @param NodeVisitorInterface[] $visitors
32     */
33    public function __construct(Environment $env, array $visitors = [])
34    {
35        $this->env = $env;
36        foreach ($visitors as $visitor) {
37            $this->addVisitor($visitor);
38        }
39    }
40
41    public function addVisitor(NodeVisitorInterface $visitor)
42    {
43        $this->visitors[$visitor->getPriority()][] = $visitor;
44    }
45
46    /**
47     * Traverses a node and calls the registered visitors.
48     *
49     * @return \Twig_NodeInterface
50     */
51    public function traverse(\Twig_NodeInterface $node)
52    {
53        ksort($this->visitors);
54        foreach ($this->visitors as $visitors) {
55            foreach ($visitors as $visitor) {
56                $node = $this->traverseForVisitor($visitor, $node);
57            }
58        }
59
60        return $node;
61    }
62
63    protected function traverseForVisitor(NodeVisitorInterface $visitor, \Twig_NodeInterface $node = null)
64    {
65        if (null === $node) {
66            return;
67        }
68
69        $node = $visitor->enterNode($node, $this->env);
70
71        foreach ($node as $k => $n) {
72            if (false !== $m = $this->traverseForVisitor($visitor, $n)) {
73                if ($m !== $n) {
74                    $node->setNode($k, $m);
75                }
76            } else {
77                $node->removeNode($k);
78            }
79        }
80
81        return $visitor->leaveNode($node, $this->env);
82    }
83}
84
85class_alias('Twig\NodeTraverser', 'Twig_NodeTraverser');
86