relativeBookItem = $relativeBookItem; $this->flatTree = $this->treeToFlatOrderedCollection($bookTree); $this->currentIndex = $this->getCurrentIndex(); } /** * Get the next logical entity within the book hierarchy. */ public function getNext(): ?Entity { return $this->flatTree->get($this->currentIndex + 1); } /** * Get the next logical entity within the book hierarchy. */ public function getPrevious(): ?Entity { return $this->flatTree->get($this->currentIndex - 1); } /** * Get the index of the current relative item. */ protected function getCurrentIndex(): ?int { $index = $this->flatTree->search(function (Entity $entity) { return get_class($entity) === get_class($this->relativeBookItem) && $entity->id === $this->relativeBookItem->id; }); return $index === false ? null : $index; } /** * Convert a book tree collection to a flattened version * where all items follow the expected order of user flow. */ protected function treeToFlatOrderedCollection(Collection $bookTree): Collection { $flatOrdered = collect(); /** @var Entity $item */ foreach ($bookTree->all() as $item) { $flatOrdered->push($item); $childPages = $item->getAttribute('visible_pages') ?? []; $flatOrdered = $flatOrdered->concat($childPages); } return $flatOrdered; } }