id = $id; $this->title = $title; } /** * @return string */ public function getId(): string { return $this->id; } /** * Get the namespace of this node * * @return string */ public function getNs(): string { return getNS($this->id); } /** * @return string|null */ public function getTitle(): ?string { return $this->title; } /** * @param string|null $title */ public function setTitle(?string $title): void { $this->title = $title; } /** * Get all nodes on the same level * @return AbstractNode[] */ public function getSiblings(): array { return $this->getParent()->getChildren(); } /** * Get all sub nodes, may return an empty array * * @return AbstractNode[] */ public function getChildren(): array { return $this->children; } /** * Does this node have children? * * @return bool */ public function hasChildren(): bool { return $this->children !== []; } /** * Get all sub nodes and their sub nodes and so on * * @return AbstractNode[] */ public function getDescendants(): array { $descendants = []; foreach ($this->children as $child) { $descendants[] = $child; $descendants = array_merge($descendants, $child->getDescendants()); } return $descendants; } /** * Get all parent nodes in reverse order * * This list is cached, so it will only be calculated once. * * @return AbstractNode[] */ public function getParents(): array { if (!$this->parents) { $parent = $this->parent; while ($parent) { $this->parents[] = $parent; $parent = $parent->getParent(); } } return $this->parents; } /** * Set the direct parent node */ public function setParent(AbstractNode $parent): void { $this->parent = $parent; } /** * Get the direct parent node * * @return AbstractNode|null */ public function getParent(): ?AbstractNode { return $this->parent; } /** * @param AbstractNode $child * @return void */ public function addChild(AbstractNode $child): void { $child->setParent($this); $this->children[] = $child; } /** * Allows to attach an arbitrary property to the page * * @param string $name * @param mixed $value * @return void */ public function setProperty(string $name, $value): void { $this->properties[$name] = $value; } /** * Get the named property, default is returned when the property is not set * * @param string $name * @param mixed $default * @return mixed */ public function getProperty(string $name, $default = null) { return $this->properties[$name] ?? $default; } /** * Sort the children of this node and all its descendants * * The given comparator function will be called with two nodes as arguments and needs to * return an integer less than, equal to, or greater than zero if the first argument is considered * to be respectively less than, equal to, or greater than the second. * * @param callable $comparator * @return void */ public function sort(callable $comparator): void { usort($this->children, $comparator); foreach ($this->children as $child) { $child->sort($comparator); } } /** * Get the string representation of the node * * Uses plus char to show the depth of the node in the tree * * @return string */ public function __toString(): string { return str_pad('', count($this->getParents()), '+') . $this->id; } }