enter = $enter; $this->leave = $leave; $this->stop = false; return $this->traverseNode($node); } private function traverseNode(Node $node): Node { $children = true; if ($this->enter) { $res = ($this->enter)($node); if ($res instanceof Node) { $node = $res; } elseif ($res === self::DontTraverseChildren) { $children = false; } elseif ($res === self::StopTraversal) { $this->stop = true; $children = false; } } if ($children) { foreach ($node as &$subnode) { $subnode = $this->traverseNode($subnode); if ($this->stop) { break; } } } if (!$this->stop && $this->leave) { $res = ($this->leave)($node); if ($res instanceof Node) { $node = $res; } elseif ($res === self::StopTraversal) { $this->stop = true; } } return $node; } }