custom/plugins/HatslogicSwProductsAndLayoutsScheduler/src/Subscriber/ProductScheduler.php line 101

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. /**
  3.  * (c) 2Hats Logic Solutions <info@2hatslogic.com>
  4.  */
  5. namespace Hatslogic\Sw\ProductsAndLayoutsScheduler\Subscriber;
  6. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  7. use Doctrine\DBAL\Connection;
  8. use Shopware\Core\Content\Product\Events\ProductListingCriteriaEvent;
  9. use Shopware\Core\Content\Product\ProductEvents;
  10. use Symfony\Component\DependencyInjection\ContainerInterface;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\RangeFilter;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
  14. use Shopware\Core\Content\Product\Events\ProductSearchCriteriaEvent;
  15. use Symfony\Component\HttpFoundation\RequestStack;
  16. use Shopware\Core\PlatformRequest;
  17. use Symfony\Component\HttpFoundation\RedirectResponse;
  18. use Symfony\Component\Routing\RouterInterface;
  19. use Shopware\Core\System\SystemConfig\SystemConfigService;
  20. use Symfony\Component\HttpKernel\KernelEvents;
  21. use Symfony\Component\HttpKernel\Event\RequestEvent;
  22. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  23. use Shopware\Core\Framework\Context;
  24. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  25. use Hatslogic\Sw\ProductsAndLayoutsScheduler\HatslogicSwProductsAndLayoutsScheduler;
  26. use Shopware\Core\Content\Product\Events\ProductSuggestCriteriaEvent;
  27. class ProductScheduler implements EventSubscriberInterface
  28. {
  29.    /**
  30.      * @var ContainerInterface
  31.      */
  32.     protected $container;
  33.     /**
  34.      * @var Connection
  35.      */
  36.     private $connection;
  37.     /**
  38.      * @var RequestStack
  39.      */
  40.     private $requestStack;
  41.     /**
  42.      * @var RouterInterface
  43.      */
  44.     private $router;
  45.     /**
  46.      * @var SystemConfigService
  47.      */
  48.     private $systemConfigService;
  49.     /**
  50.      * @var EntityRepositoryInterface
  51.      */
  52.     private $productRepository;
  53.     public function __construct(
  54.         ContainerInterface $container
  55.         Connection $connection,
  56.         RequestStack $requestStack,
  57.         RouterInterface $router,
  58.         SystemConfigService $systemConfigService,
  59.         EntityRepositoryInterface $productRepository
  60.     ) {
  61.         $this->container $container;
  62.         $this->connection $connection;
  63.         $this->requestStack $requestStack;
  64.         $this->router $router;
  65.         $this->systemConfigService $systemConfigService;
  66.         $this->productRepository $productRepository;
  67.     }
  68.     public static function getSubscribedEvents(): array
  69.     {
  70.         return [
  71.             ProductEvents::PRODUCT_LISTING_CRITERIA => 'productListingCriteria',
  72.             ProductEvents::PRODUCT_SEARCH_CRITERIA => 'productSearchCriteria',
  73.             ProductEvents::PRODUCT_SUGGEST_CRITERIA => 'productSuggestCriteria',
  74.             KernelEvents::REQUEST => 'onProductLoaded'
  75.         ];
  76.     }
  77.     public function getProductDetailsById($id)
  78.     {
  79.         $criteria = (new Criteria())
  80.             ->addFilter(new EqualsFilter(
  81.             'product.id'$id));
  82.         $result $this->productRepository->search($criteriaContext::createDefaultContext());
  83.         $productDetails $result->first();
  84.         return ($productDetails) ? $productDetailsnull;
  85.     }
  86.     public function onProductLoaded(RequestEvent $event)
  87.     {
  88.         $request $event->getRequest();
  89.         $attributes $request->attributes;
  90.         $route $attributes->get('_route');
  91.         if($route == 'frontend.detail.page')
  92.         {
  93.             $productId $attributes->get('productId');
  94.             $salesChannelId $attributes->get(PlatformRequest::ATTRIBUTE_SALES_CHANNEL_ID);
  95.             if($this->isProductSchedulerActive($salesChannelId))
  96.             {
  97.                 $productDetails $this->getProductDetailsById($productId);
  98.                 if(empty($productDetails)) {
  99.                     return;
  100.                 }
  101.                 $customFields $productDetails->getCustomFields();
  102.                 if(!empty($customFields))
  103.                 {
  104.                     $productDetailPageVisibilityStatus $this->getProductDetailPageVisibilityStatus($customFields);
  105.                     if(!$productDetailPageVisibilityStatus)
  106.                     {
  107.                        $response = new RedirectResponse($this->router->generate('frontend.home.page'), 301);
  108.                        $event->setResponse($response);
  109.                        return;
  110.                     }
  111.                 }
  112.             }
  113.         }
  114.         return;
  115.     }
  116.     public function getProductDetailPageVisibilityStatus($customFields)
  117.     {
  118.         $pageVisible true;
  119.         if(!empty($customFields))
  120.         {
  121.             $currentDateTimeTimeStamp strtotime(date(HatslogicSwProductsAndLayoutsScheduler::SCHEDULER_DATE_TIME_FORMAT));
  122.             $scheduledFrom = isset($customFields['product_scheduled_from']) ? $customFields['product_scheduled_from'] : '';
  123.             $scheduledTo = isset($customFields['product_scheduled_to']) ? $customFields['product_scheduled_to'] : '';
  124.             $scheduledFromTimeStamp = !empty($scheduledFrom) ? strtotime($scheduledFrom) : '';
  125.             $scheduledToTimeStamp = !empty($scheduledTo) ? strtotime($scheduledTo) : '';
  126.             if(!empty($scheduledFrom) || !empty($scheduledTo))
  127.             {
  128.                 $pageVisible false;
  129.             }
  130.             if(!empty($scheduledFrom) && !empty($scheduledTo))
  131.             {
  132.                 if(($scheduledFromTimeStamp <= $currentDateTimeTimeStamp) && ($scheduledToTimeStamp >= $currentDateTimeTimeStamp))
  133.                 {
  134.                     $pageVisible true;
  135.                 }
  136.             } else if(!empty($scheduledFrom)) {
  137.                 if($scheduledFromTimeStamp <= $currentDateTimeTimeStamp)
  138.                 {
  139.                     $pageVisible true;
  140.                 }
  141.             } else if(!empty($scheduledTo)) {
  142.                 if($scheduledToTimeStamp >= $currentDateTimeTimeStamp)
  143.                 {
  144.                     $pageVisible true;
  145.                 }
  146.             }
  147.         } 
  148.         return $pageVisible;
  149.     }
  150.     public function productSuggestCriteria(ProductSuggestCriteriaEvent $event)
  151.     {
  152.         $salesChannelContext $event->getSalesChannelContext();
  153.         $salesChannelId $salesChannelContext->getSalesChannel()->getId();
  154.         if($this->isProductSchedulerActive($salesChannelId))
  155.         {
  156.             $event->getCriteria()->addAssociation('customFields');
  157.             $productScheduledDateRangeFilter $this->getProductScheduledDateRangeFilter();
  158.             $event->getCriteria()->addFilter(
  159.                 $productScheduledDateRangeFilter
  160.             );
  161.         }
  162.         return true;
  163.     }
  164.     public function productSearchCriteria(ProductSearchCriteriaEvent $event)
  165.     {
  166.         $salesChannelContext $event->getSalesChannelContext();
  167.         $salesChannelId $salesChannelContext->getSalesChannel()->getId();
  168.         if($this->isProductSchedulerActive($salesChannelId))
  169.         {
  170.             $event->getCriteria()->addAssociation('customFields');
  171.             $productScheduledDateRangeFilter $this->getProductScheduledDateRangeFilter();
  172.             $event->getCriteria()->addFilter(
  173.                 $productScheduledDateRangeFilter
  174.             );
  175.         }
  176.         return true;
  177.     }
  178.     public function productListingCriteria(ProductListingCriteriaEvent $event)
  179.     {
  180.         $salesChannelContext $event->getSalesChannelContext();
  181.         $salesChannelId $salesChannelContext->getSalesChannel()->getId();
  182.         if($this->isProductSchedulerActive($salesChannelId))
  183.         {
  184.             $event->getCriteria()->addAssociation('customFields');
  185.             $productScheduledDateRangeFilter $this->getProductScheduledDateRangeFilter();
  186.             $event->getCriteria()->addFilter(
  187.                 $productScheduledDateRangeFilter
  188.             );
  189.         }
  190.         return true;
  191.     }
  192.     public function getProductScheduledDateRangeFilter(): MultiFilter
  193.     {
  194.         $filterNoDateRange = new MultiFilter(
  195.             MultiFilter::CONNECTION_AND,
  196.             [
  197.                 new EqualsFilter('customFields.product_scheduled_from'null),
  198.                 new EqualsFilter('customFields.product_scheduled_to'null),
  199.             ]
  200.         );
  201.         $filterStartedNoEndDate = new MultiFilter(
  202.             MultiFilter::CONNECTION_AND,
  203.             [
  204.                 new RangeFilter('customFields.product_scheduled_from', [RangeFilter::LTE => date(HatslogicSwProductsAndLayoutsScheduler::SCHEDULER_DATE_TIME_FORMAT)]),
  205.                 new EqualsFilter('customFields.product_scheduled_to'null),
  206.             ]
  207.         );
  208.         $filterActiveNoStartDate = new MultiFilter(
  209.             MultiFilter::CONNECTION_AND,
  210.             [
  211.                 new EqualsFilter('customFields.product_scheduled_from'null),
  212.                 new RangeFilter('customFields.product_scheduled_to', [RangeFilter::GTE => date(HatslogicSwProductsAndLayoutsScheduler::SCHEDULER_DATE_TIME_FORMAT)]),
  213.             ]
  214.         );
  215.         $activeDateRangeFilter = new MultiFilter(
  216.             MultiFilter::CONNECTION_AND,
  217.             [
  218.                 new RangeFilter('customFields.product_scheduled_from', [RangeFilter::LTE => date(HatslogicSwProductsAndLayoutsScheduler::SCHEDULER_DATE_TIME_FORMAT)]),
  219.                 new RangeFilter('customFields.product_scheduled_to', [RangeFilter::GTE => date(HatslogicSwProductsAndLayoutsScheduler::SCHEDULER_DATE_TIME_FORMAT)]),
  220.             ]
  221.         );
  222.         $dateFilter = new MultiFilter(
  223.             MultiFilter::CONNECTION_OR,
  224.             [
  225.                 $filterNoDateRange,
  226.                 $filterActiveNoStartDate,
  227.                 $filterStartedNoEndDate,
  228.                 $activeDateRangeFilter,
  229.             ]
  230.         );
  231.         return $dateFilter;
  232.     }
  233.     public function isProductSchedulerActive($salesChannelId)
  234.     {
  235.         $isProductSchedulerActive $this->systemConfigService->get('HatslogicSwProductsAndLayoutsScheduler.config.enableProductsScheduler'$salesChannelId);
  236.         return $isProductSchedulerActive;
  237.     }  
  238. }