<?php declare(strict_types=1);
/**
* (c) 2Hats Logic Solutions <info@2hatslogic.com>
*/
namespace Hatslogic\Sw\ProductsAndLayoutsScheduler\Subscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Doctrine\DBAL\Connection;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Symfony\Component\HttpFoundation\RequestStack;
use Shopware\Core\PlatformRequest;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\RouterInterface;
use Shopware\Storefront\Event\StorefrontRenderEvent;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Storefront\Page\Navigation\NavigationPageLoadedEvent;
use Shopware\Core\Content\Cms\DataResolver\ResolverContext\EntityResolverContext;
use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\EntityDefinition;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Core\Content\Category\CategoryEntity;
use Shopware\Core\Content\Cms\SalesChannel\SalesChannelCmsPageLoaderInterface;
use Hatslogic\Sw\ProductsAndLayoutsScheduler\HatslogicSwProductsAndLayoutsScheduler;
use Symfony\Component\HttpFoundation\Session\Session;
class CmsPageScheduler implements EventSubscriberInterface
{
/**
* @var ContainerInterface
*/
protected $container;
/**
* @var Connection
*/
private $connection;
/**
* @var RequestStack
*/
private $requestStack;
/**
* @var RouterInterface
*/
private $router;
/**
* @var SystemConfigService
*/
private $systemConfigService;
/**
* @var EntityRepositoryInterface
*/
private $cmsPageRepository;
/**
* @var EntityDefinition
*/
private $categoryDefinition;
/**
* @var SalesChannelRepositoryInterface
*/
private $categoryRepository;
/**
* @var SalesChannelCmsPageLoaderInterface
*/
private $cmsPageLoader;
/**
* @var Session
*/
private $session;
public function __construct(
ContainerInterface $container,
Connection $connection,
RequestStack $requestStack,
RouterInterface $router,
SystemConfigService $systemConfigService,
EntityDefinition $categoryDefinition,
SalesChannelRepositoryInterface $categoryRepository,
SalesChannelCmsPageLoaderInterface $cmsPageLoader,
EntityRepositoryInterface $cmsPageRepository,
Session $session
) {
$this->container = $container;
$this->connection = $connection;
$this->requestStack = $requestStack;
$this->router = $router;
$this->systemConfigService = $systemConfigService;
$this->cmsPageRepository = $cmsPageRepository;
$this->categoryDefinition = $categoryDefinition;
$this->categoryRepository = $categoryRepository;
$this->cmsPageLoader = $cmsPageLoader;
$this->session = $session;
}
public static function getSubscribedEvents(): array
{
return [
StorefrontRenderEvent::class => 'onStorefrontRender',
KernelEvents::REQUEST => 'onCmsPageLoaded',
NavigationPageLoadedEvent::class => 'onNavigationPageLoaded'
];
}
private function loadCategory(string $categoryId, SalesChannelContext $context): CategoryEntity
{
$criteria = new Criteria([$categoryId]);
$criteria->addAssociation('media');
$category = $this->categoryRepository->search($criteria, $context)->get($categoryId);
return $category;
}
public function onNavigationPageLoaded(NavigationPageLoadedEvent $event)
{
$master = $this->requestStack->getMasterRequest();
$salesChannelId = $master->attributes->get(PlatformRequest::ATTRIBUTE_SALES_CHANNEL_ID);
$route = $master->attributes->get('_route');
if(($route == 'frontend.navigation.page' || $route == 'frontend.home.page') && $this->isLayoutSchedulerActive($salesChannelId))
{
$cmsPageDetails = $event->getPage()->getCmsPage();
$customFields = $cmsPageDetails->getCustomFields();
if(!empty($customFields))
{
$cmsPageVisibilityStatus = $this->getCmsPageVisibilityStatus($customFields);
if(!$cmsPageVisibilityStatus) {
$salesChannelContext = $event->getSalesChannelContext();
$request = $event->getRequest();
$defaultCategoryCmsPage = $this->getDefaultCategoryCmsPage();
$pageId = $defaultCategoryCmsPage->getId();
$navigationId = $request->get('navigationId', $salesChannelContext->getSalesChannel()->getNavigationCategoryId());
$category = $this->loadCategory($navigationId, $salesChannelContext);
if ($pageId && !empty($category)) {
$resolverContext = new EntityResolverContext($salesChannelContext, $request, $this->categoryDefinition, $category);
$pages = $this->cmsPageLoader->load($request, new Criteria([$pageId]), $salesChannelContext, $category->getTranslation('slotConfig'), $resolverContext);
$event->getPage()->setCmsPage($pages->get($pageId));
}
}
}
}
return;
}
private function getDefaultCategoryCmsPage()
{
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('type', 'product_list'));
$criteria->addFilter(new EqualsFilter('locked', 1));
$result = $this->cmsPageRepository->search($criteria, Context::createDefaultContext());
$cmsPageDetails = $result->first();
return ($cmsPageDetails) ? $cmsPageDetails: null;
}
public function getCmsPageById($id)
{
$criteria = (new Criteria())
->addFilter(new EqualsFilter(
'cms_page.id', $id));
$result = $this->cmsPageRepository->search($criteria, Context::createDefaultContext());
$cmsPageDetails = $result->first();
return ($cmsPageDetails) ? $cmsPageDetails: null;
}
public function onCmsPageLoaded(RequestEvent $event)
{
$request = $event->getRequest();
$attributes = $request->attributes;
$route = $attributes->get('_route');
if($route == 'frontend.cms.page')
{
$cmsPageId = $attributes->get('id');
$salesChannelId = $attributes->get(PlatformRequest::ATTRIBUTE_SALES_CHANNEL_ID);
$xmlHttpRequest = $attributes->get('XmlHttpRequest');
if($xmlHttpRequest !=1 && $this->isLayoutSchedulerActive($salesChannelId))
{
$cmsPageDetails = $this->getCmsPageById($cmsPageId);
if(empty($cmsPageDetails)) {
return;
}
$customFields = $cmsPageDetails->getCustomFields();
if(!empty($customFields))
{
$cmsPageVisibilityStatus = $this->getCmsPageVisibilityStatus($customFields);
if(!$cmsPageVisibilityStatus)
{
$response = new RedirectResponse($this->router->generate('frontend.home.page'), 301);
$event->setResponse($response);
return;
}
}
}
}
return;
}
public function getCmsPageVisibilityStatus($customFields)
{
$pageVisible = true;
if(!empty($customFields))
{
$currentDateTimeTimeStamp = strtotime(date(HatslogicSwProductsAndLayoutsScheduler::SCHEDULER_DATE_TIME_FORMAT));
$publishedFrom = isset($customFields['layouts_scheduler_published_from']) ? $customFields['layouts_scheduler_published_from'] : '';
$publishedTo = isset($customFields['layouts_scheduler_published_to']) ? $customFields['layouts_scheduler_published_to'] : '';
$publishedFromTimeStamp = !empty($publishedFrom) ? strtotime($publishedFrom) : '';
$publishedToTimeStamp = !empty($publishedTo) ? strtotime($publishedTo) : '';
if(!empty($publishedFrom) || !empty($publishedTo)) {
$pageVisible = false;
}
if(!empty($publishedFrom) && !empty($publishedTo))
{
if(($publishedFromTimeStamp <= $currentDateTimeTimeStamp) && ($publishedToTimeStamp >= $currentDateTimeTimeStamp))
{
$pageVisible = true;
}
} else if(!empty($publishedFrom)) {
if($publishedFromTimeStamp <= $currentDateTimeTimeStamp)
{
$pageVisible = true;
}
} else if(!empty($publishedTo)) {
if($publishedToTimeStamp >= $currentDateTimeTimeStamp)
{
$pageVisible = true;
}
}
}
return $pageVisible;
}
public function onStorefrontRender(StorefrontRenderEvent $event)
{
$route = $event->getRequest()->get('_route');
$xmlHttpRequest = $event->getRequest()->get('XmlHttpRequest');
$cmsPageVisibilityStatus = true;
$salesChannelId = $event->getRequest()->get(PlatformRequest::ATTRIBUTE_SALES_CHANNEL_ID);
if($route == 'frontend.cms.page' && $xmlHttpRequest == 1 && $this->isLayoutSchedulerActive($salesChannelId))
{
$parameters = $event->getParameters();
$customFields = $parameters['cmsPage']->get('customFields');
if(!empty($customFields))
{
$cmsPageVisibilityStatus = $this->getCmsPageVisibilityStatus($customFields);
}
}
$event->setParameter('cmsPageVisibilityStatus', $cmsPageVisibilityStatus);
}
public function isLayoutSchedulerActive($salesChannelId)
{
$islayoutSchedulerActive = $this->systemConfigService->get('HatslogicSwProductsAndLayoutsScheduler.config.enableLayoutsScheduler', $salesChannelId);
return $islayoutSchedulerActive;
}
}