125 lines
3.0 KiB
PHP
125 lines
3.0 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace Esun\Homepage\Block;
|
|
|
|
use Mageplaza\Blog\Block\Post\View;
|
|
use Mageplaza\Blog\Model\Post;
|
|
|
|
/**
|
|
* Provides chronological navigation for the current news post.
|
|
*/
|
|
class NewsPostNavigation extends View
|
|
{
|
|
/** @var bool */
|
|
private bool $navigationLoaded = false;
|
|
|
|
/** @var Post|null */
|
|
private ?Post $previousPost = null;
|
|
|
|
/** @var Post|null */
|
|
private ?Post $nextPost = null;
|
|
|
|
/**
|
|
* Get the news post immediately before the current post.
|
|
*
|
|
* @return Post|null
|
|
*/
|
|
public function getPreviousPost(): ?Post
|
|
{
|
|
$this->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;
|
|
}
|
|
}
|