loadNavigation(); return $this->previousPost; } /** * Get the news post immediately after the current post. * * @return Post|null */ public function getNextPost(): ?Post { $this->loadNavigation(); return $this->nextPost; } /** * Get the active storefront ID. * * @return int */ public function getCurrentStoreId(): int { return (int) $this->store->getStore()->getId(); } /** * Resolve both navigation directions once per request. * * @return void */ private function loadNavigation(): void { if ($this->navigationLoaded) { return; } $this->navigationLoaded = true; $currentPost = $this->getPost(); $currentPostId = (int) $currentPost->getId(); $publishDate = (string) $currentPost->getData('publish_date'); if ($currentPostId <= 0 || $publishDate === '') { return; } $this->previousPost = $this->findPost([ 'publish_date' => ['eq' => $publishDate], 'post_id' => ['lt' => $currentPostId], ], 'DESC'); if ($this->previousPost === null) { $this->previousPost = $this->findPost([ 'publish_date' => ['lt' => $publishDate], ], 'DESC'); } $this->nextPost = $this->findPost([ 'publish_date' => ['eq' => $publishDate], 'post_id' => ['gt' => $currentPostId], ], 'ASC'); if ($this->nextPost === null) { $this->nextPost = $this->findPost([ 'publish_date' => ['gt' => $publishDate], ], 'ASC'); } } /** * Get the closest published post matching the supplied filters. * * @param array $filters * @param string $direction * @return Post|null */ private function findPost(array $filters, string $direction): ?Post { $collection = $this->helperData->getPostList($this->getCurrentStoreId()); foreach ($filters as $field => $condition) { $collection->addFieldToFilter($field, $condition); } $collection->setOrder('publish_date', $direction) ->setOrder('post_id', $direction) ->setPageSize(1) ->setCurPage(1); $post = $collection->getFirstItem(); return $post instanceof Post && $post->getId() ? $post : null; } }