visitors = array(); } /** * Adds a visitor. * * @param PHPParser_NodeVisitorInterface $visitor Visitor to add */ public function addVisitor(PHPParser_NodeVisitorInterface $visitor) { $this->visitors[] = $visitor; } /** * Traverses a node or an array using the registered visitors. * * @param PHPParser_NodeAbstract|array $node Node or array */ public function traverse(&$node) { foreach ($this->visitors as $visitor) { $visitor->beforeTraverse($node); } $this->_traverse($node); foreach ($this->visitors as $visitor) { $visitor->afterTraverse($node); } } protected function _traverse(&$node) { if (!is_array($node) && !$node instanceof Traversable) { return; } $doNodes = array(); foreach ($node as $subNodeKey => &$subNode) { if ($subNode instanceof PHPParser_NodeAbstract) { foreach ($this->visitors as $visitor) { $visitor->enterNode($subNode); } } $this->_traverse($subNode); if ($subNode instanceof PHPParser_NodeAbstract) { foreach ($this->visitors as $visitor) { $return = $visitor->leaveNode($subNode); if (false === $return) { $doNodes[] = array($subNodeKey, array()); break; } elseif (is_array($return)) { $doNodes[] = array($subNodeKey, $return); break; } } } } if (!empty($doNodes)) { if (is_array($node)) { while (list($key, $replace) = array_pop($doNodes)) { array_splice($node, $key, 1, $replace); } } else { while (list($key, $replace) = array_pop($doNodes)) { if (!empty($replace)) { throw new Exception('Nodes can only be merged if the parent is an array'); } unset($node[$key]); } } } } }