<?php declare(strict_types=1);
namespace MoorlMagazine\Core\Content\MagazineArticle\SalesChannel\Detail;
use MoorlMagazine\Core\Content\MagazineArticle\MagazineArticleDefinition;
use MoorlMagazine\Core\Content\MagazineArticle\SalesChannel\MagazineArticleAvailableFilter;
use MoorlMagazine\Core\Content\MagazineArticle\SalesChannel\SalesChannelMagazineArticleDefinition;
use MoorlMagazine\Core\Content\MagazineArticle\SalesChannel\SalesChannelMagazineArticleEntity;
use Shopware\Core\Content\Cms\DataResolver\ResolverContext\EntityResolverContext;
use Shopware\Core\Content\Cms\Exception\PageNotFoundException;
use Shopware\Core\Content\Cms\SalesChannel\SalesChannelCmsPageLoaderInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\RangeFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
use Shopware\Core\Framework\Plugin\Exception\DecorationPatternException;
use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
/**
* @Route(defaults={"_routeScope"={"store-api"}})
*/
class MagazineArticleDetailRoute extends AbstractMagazineArticleDetailRoute
{
private SalesChannelRepositoryInterface $magazineArticleRepository;
private SalesChannelCmsPageLoaderInterface $cmsPageLoader;
private MagazineArticleDefinition $magazineArticleDefinition;
public function __construct(
SalesChannelRepositoryInterface $magazineArticleRepository,
SalesChannelCmsPageLoaderInterface $cmsPageLoader,
SalesChannelMagazineArticleDefinition $magazineArticleDefinition
) {
$this->magazineArticleRepository = $magazineArticleRepository;
$this->cmsPageLoader = $cmsPageLoader;
$this->magazineArticleDefinition = $magazineArticleDefinition;
}
public function getDecorated(): AbstractMagazineArticleDetailRoute
{
throw new DecorationPatternException(self::class);
}
/**
* @throws PageNotFoundException
*/
public function reload(
Request $request,
SalesChannelContext $context,
SalesChannelMagazineArticleEntity $magazineArticle
): MagazineArticleDetailRouteResponse
{
$pageId = $magazineArticle->getCmsPageId();
if (!$pageId) {
return new MagazineArticleDetailRouteResponse($magazineArticle);
}
$slotConfig = $magazineArticle->getTranslation('slotConfig');
$resolverContext = new EntityResolverContext($context, $request, $this->magazineArticleDefinition, $magazineArticle);
$pages = $this->cmsPageLoader->load(
$request,
$this->createCriteria($pageId, $request),
$context,
$slotConfig,
$resolverContext
);
if (!$pages->has($pageId)) {
throw new PageNotFoundException($pageId);
}
$magazineArticle->setCmsPage($pages->get($pageId));
return new MagazineArticleDetailRouteResponse($magazineArticle);
}
/**
* @throws PageNotFoundException
*/
public function load(
string $magazineArticleId,
Request $request,
SalesChannelContext $context,
Criteria $criteria
): MagazineArticleDetailRouteResponse
{
$this->addFilters($context, $criteria);
$criteria->setIds([$magazineArticleId]);
/** @var SalesChannelMagazineArticleEntity $magazineArticle */
$magazineArticle = $this->magazineArticleRepository
->search($criteria, $context)
->first();
if (!$magazineArticle) {
throw new PageNotFoundException($magazineArticleId);
}
$this->enrichNextArticle($context, $criteria, $magazineArticle);
$this->enrichPreviousArticle($context, $criteria, $magazineArticle);
/* If a CMS page for content is defined */
$contentPageId = $magazineArticle->getContentCmsPageId();
if ($contentPageId) {
$pages = $this->cmsPageLoader->load(
$request,
$this->createCriteria($contentPageId, $request),
$context
);
if (!$pages->has($contentPageId)) {
throw new PageNotFoundException($contentPageId);
}
$magazineArticle->addExtension('contentCmsPage', $pages->get($contentPageId));
/* Do not process the page, first the new content need to be processed */
return new MagazineArticleDetailRouteResponse($magazineArticle);
}
$pageId = $magazineArticle->getCmsPageId();
if (!$pageId) {
return new MagazineArticleDetailRouteResponse($magazineArticle);
}
$slotConfig = $magazineArticle->getTranslation('slotConfig');
$resolverContext = new EntityResolverContext($context, $request, $this->magazineArticleDefinition, $magazineArticle);
$pages = $this->cmsPageLoader->load(
$request,
$this->createCriteria($pageId, $request),
$context,
$slotConfig,
$resolverContext
);
if (!$pages->has($pageId)) {
throw new PageNotFoundException($pageId);
}
$magazineArticle->setCmsPage($pages->get($pageId));
return new MagazineArticleDetailRouteResponse($magazineArticle);
}
private function addFilters(SalesChannelContext $context, Criteria $criteria): void
{
$criteria->addFilter(
new MagazineArticleAvailableFilter($context)
);
$criteria->addAssociation('swCategories');
$criteria->addAssociation('comments');
$commentsCriteria = $criteria->getAssociation('comments');
$commentsCriteria->addSorting(new FieldSorting('createdAt', FieldSorting::ASCENDING));
$commentsCriteria->addFilter(new EqualsFilter('active', true));
}
private function createCriteria(string $pageId, Request $request): Criteria
{
$criteria = new Criteria([$pageId]);
$criteria->setTitle('magazine_article_detail::cms-page');
$slots = $request->get('slots');
if (\is_string($slots)) {
$slots = explode('|', $slots);
}
if (!empty($slots) && \is_array($slots)) {
$criteria
->getAssociation('sections.blocks')
->addFilter(new EqualsAnyFilter('slots.id', $slots));
}
return $criteria;
}
public function enrichNextArticle(SalesChannelContext $context, Criteria $criteria, SalesChannelMagazineArticleEntity $magazineArticle): void
{
$criteria->setIds([]);
$criteria->resetSorting();
$criteria->resetFilters();
$criteria->addSorting(new FieldSorting('autoIncrement', FieldSorting::DESCENDING));
$criteria->addFilter(new RangeFilter('autoIncrement', ['lt' => $magazineArticle->getAutoIncrement()]));
$criteria->setLimit(1);
$magazineArticle->setNextMagazineArticle(
$this->magazineArticleRepository->search($criteria, $context)->first()
);
}
public function enrichPreviousArticle(SalesChannelContext $context, Criteria $criteria, SalesChannelMagazineArticleEntity $magazineArticle): void
{
$criteria->setIds([]);
$criteria->resetSorting();
$criteria->resetFilters();
$criteria->addSorting(new FieldSorting('autoIncrement', FieldSorting::ASCENDING));
$criteria->addFilter(new RangeFilter('autoIncrement', ['gt' => $magazineArticle->getAutoIncrement()]));
$criteria->setLimit(1);
$magazineArticle->setPreviousMagazineArticle(
$this->magazineArticleRepository->search($criteria, $context)->first()
);
}
}