message = $message; $this->id = $id; $this->root = $root; } public static function root(): self { return new self( null, null, true ); } public static function empty(?string $id = null): self { return new self( null, $id, ); } public static function with(Message $message): self { return new self( $message ); } public function fill(Message $message): void { $this->message = $message; } public function hasMessage(): bool { return $this->message !== null; } public function getMessage(): ?Message { return $this->message; } public function getId(): ?string { return $this->id; } public function isRoot(): bool { return $this->root; } public function hasParent(): bool { return $this->parent !== null; } public function getParent(): Container { if ($this->isRoot() || $this->parent === null) { throw new RuntimeException('Container root has no parent'); } return $this->parent; } public function setParent(?Container $parent): void { $this->unlink(); $this->parent = $parent; if ($parent !== null) { $parent->children[spl_object_id($this)] = $this; } } public function hasAncestor(Container $container): bool { if ($this->parent === $container) { return true; } if ($this->parent !== null) { return $this->parent->hasAncestor($container); } return false; } public function unlink(): void { if ($this->parent !== null) { $this->parent->removeChild($this); } $this->parent = null; } private function removeChild(Container $child): void { $objId = spl_object_id($child); if (array_key_exists($objId, $this->children)) { unset($this->children[$objId]); } } public function hasChildren(): bool { return $this->children !== []; } /** * @return Container[] */ public function getChildren(): array { return $this->children; } #[\Override] #[ReturnTypeWillChange] public function jsonSerialize() { return [ 'message' => $this->message, 'id' => $this->id, 'root' => $this->root, 'children' => $this->children, ]; } }