<?php
declare(strict_types=1);
namespace Sisi\Blog6\Storefront\Controller;
use Shopware\Core\Content\Cms\Aggregate\CmsBlock\CmsBlockEntity;
use Shopware\Core\Content\Cms\Aggregate\CmsSection\CmsSectionEntity;
use Shopware\Core\Content\Cms\CmsPageEntity;
use Shopware\Core\Content\Cms\DataResolver\CmsSlotsDataResolver;
use Shopware\Core\Content\Cms\DataResolver\ResolverContext\ResolverContext;
use Shopware\Core\Content\Cms\Exception\PageNotFoundException;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\Routing\Annotation\RouteScope;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Storefront\Controller\StorefrontController;
use Shopware\Storefront\Page\GenericPageLoader;
use Sisi\Blog6\Core\Content\Post\PostEntity;
use Sisi\Blog6\Storefront\Page\Blog\Products\ProductsLoader;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Shopware\Storefront\Page\Page;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\RangeFilter;
/**
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* @RouteScope(scopes={"storefront"})
*/
class BlogController extends StorefrontController
{
/**
* @var GenericPageLoader
*/
private $genericPageLoader;
/**
* @var ProductsLoader
*/
private $productsLoader;
/**
* @var CmsSlotsDataResolver
*/
private $slotDataResolver;
/**
* BlogController constructor.
* @param GenericPageLoader $genericPageLoader
*/
public function __construct(GenericPageLoader $genericPageLoader, ProductsLoader $productsLoader, CmsSlotsDataResolver $slotDataResolver)
{
$this->genericPageLoader = $genericPageLoader;
$this->productsLoader = $productsLoader;
$this->slotDataResolver = $slotDataResolver;
}
/**
* @Route("/blog/{postId}", name="frontend.blog.detail", methods={"GET"})
* @param mixed $postId
* @throws PageNotFoundException
*/
public function index(Request $request, SalesChannelContext $context, Context $criteriaContext, $postId): Response
{
$page = $this->genericPageLoader->load($request, $context);
/** @var EntityRepositoryInterface $blogRepository */
$blogRepository = $this->container->get('sisi_blog6_post.repository');
$criteria = new Criteria();
$criteria->addFilter(
new EqualsFilter('id', $postId)
);
$criteria->addFilter(new EqualsFilter('enabled', true));
// Today date
$today = new \DateTime();
$today = $today->setTimezone(new \DateTimeZone('UTC'));
$todayStart = $today->format('Y-m-d H:i:s');
$criteria->addFilter(
new MultiFilter(
MultiFilter::CONNECTION_OR,
[
new RangeFilter('publishAt', ['lte' => $todayStart]),
new EqualsFilter('publishAt', null),
]
)
);
$criteria->addAssociation('user');
$criteria->addAssociation('categories');
$criteria->addAssociation('categoriesRo');
$criteria->addAssociation('cover');
$criteria->addAssociation('media');
$criteria->addAssociation('products');
$criteria->addAssociation('shoppingExperience');
$criteria->addAssociation('shoppingExperience.sections');
$criteria->addAssociation('shoppingExperience.sections.blocks.slots');
$considerInheritanceState = $criteriaContext->considerInheritance();
$criteriaContext->setConsiderInheritance(false);
$results = $blogRepository->search($criteria, $criteriaContext)->getEntities();
/** @var PostEntity|null $post */
$post = $results->first();
if (!$post) {
throw new PageNotFoundException($postId);
}
$cmsPageResult = null;
if ($post->getShoppingExperienceId()) {
$cmsPageResult = $post->getShoppingExperience();
$resolverContext = new ResolverContext($context, $request);
$this->loadSlotData($cmsPageResult, $resolverContext);
$cmsPageResult->getSections()->sort(function (CmsSectionEntity $a, CmsSectionEntity $b) {
return $a->getPosition() <=> $b->getPosition();
});
foreach ($cmsPageResult->getSections() as $section) {
$section->getBlocks()->sort(function (CmsBlockEntity $a, CmsBlockEntity $b) {
return $a->getPosition() <=> $b->getPosition();
});
}
}
$criteriaContext->setConsiderInheritance($considerInheritanceState);
// Load products
$crossSellings = $this->productsLoader->load($post->getProducts(), $context);
// Set metadata
$this->loadMetaData($page, $post);
// Sort image collection
$post->getMedia()->sort(function ($one, $two) {
return $one->getPosition() - $two->getPosition();
});
return $this->renderStorefront('@Storefront/storefront/page/blog/detail.html.twig', [
'page' => $page,
'post' => $post,
'crossSellings' => $crossSellings,
"blogCms" => $cmsPageResult
]);
}
private function loadMetaData(Page $page, PostEntity $post): void
{
$metaInformation = $page->getMetaInformation();
if (!$metaInformation) {
return;
}
$metaDescription = $post->getTranslation('shortDescription')
?? $post->getTranslation('description');
$metaInformation->setMetaDescription((string) $metaDescription);
$metaInformation->setMetaKeywords((string) $post->getTranslation('keywords'));
}
private function loadSlotData(CmsPageEntity $page, ResolverContext $resolverContext): void
{
$slots = $this->slotDataResolver->resolve($page->getSections()->getBlocks()->getSlots(), $resolverContext);
$page->getSections()->getBlocks()->setSlots($slots);
}
}