custom/plugins/SwpProductOptionsSix/src/Subscriber/Listing/ListingSubscriber.php line 150

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. /**
  3.  * Shopware
  4.  * Copyright © 2021
  5.  *
  6.  * @category   Shopware
  7.  * @package    SwpProductOptionsSix
  8.  * @subpackage ListingSubscriber.php
  9.  *
  10.  * @copyright  2021 Iguana-Labs GmbH
  11.  * @author     Module Factory <info at module-factory.com>
  12.  * @license    https://www.module-factory.com/eula
  13.  */
  14. namespace Swp\ProductOptionsSix\Subscriber\Listing;
  15. use Shopware\Core\Content\Cms\Aggregate\CmsSlot\CmsSlotEntity;
  16. use Shopware\Core\Content\Cms\CmsPageCollection;
  17. use Shopware\Core\Content\Cms\CmsPageEntity;
  18. use Shopware\Core\Content\Cms\Events\CmsPageLoadedEvent;
  19. use Shopware\Core\Content\Cms\SalesChannel\Struct\ProductBoxStruct;
  20. use Shopware\Core\Content\Product\Events\ProductListingResultEvent;
  21. use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
  22. use Shopware\Core\Framework\Context;
  23. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  24. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  25. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  26. use Shopware\Core\Framework\Struct\ArrayStruct;
  27. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  28. use Shopware\Core\System\SystemConfig\SystemConfigService;
  29. use Shopware\Storefront\Page\Search\SearchPageLoadedEvent;
  30. use Swp\ProductOptionsSix\Core\Content\ProductOptions\SalesChannel\Filter\ProductOptionsFilter;
  31. use Swp\ProductOptionsSix\Core\Content\ProductOptions\SalesChannel\ProductOptionsLoader;
  32. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  33. class ListingSubscriber implements EventSubscriberInterface
  34. {
  35.     /** @var SystemConfigService */
  36.     private $systemConfigService;
  37.     /** @var EntityRepository */
  38.     private $productRepository;
  39.     /** @var EntityRepository */
  40.     private $productOptionRepository;
  41.     /** @var ProductOptionsFilter */
  42.     private $productOptionsFilter;
  43.     /**
  44.      * ListingSubscriber constructor.
  45.      *
  46.      * @param SystemConfigService $systemConfigService
  47.      * @param EntityRepository $productRepository
  48.      * @param EntityRepository $productOptionRepository
  49.      * @param ProductOptionsFilter $productOptionsFilter
  50.      */
  51.     public function __construct(
  52.         SystemConfigService $systemConfigService,
  53.         EntityRepository $productRepository,
  54.         EntityRepository $productOptionRepository,
  55.         ProductOptionsFilter $productOptionsFilter
  56.     ) {
  57.         $this->systemConfigService $systemConfigService;
  58.         $this->productRepository $productRepository;
  59.         $this->productOptionRepository $productOptionRepository;
  60.         $this->productOptionsFilter $productOptionsFilter;
  61.     }
  62.     /**
  63.      * @return array
  64.      */
  65.     public static function getSubscribedEvents(): array
  66.     {
  67.         return [
  68.             CmsPageLoadedEvent::class => 'onCmsPageLoaded',
  69.             SearchPageLoadedEvent::class => 'onSearchPageLoaded',
  70.             ProductListingResultEvent::class => 'onProductListingResult'
  71.         ];
  72.     }
  73.     /**
  74.      * @param CmsPageLoadedEvent $event
  75.      */
  76.     public function onCmsPageLoaded(CmsPageLoadedEvent $event) :void
  77.     {
  78.         if (!$this->isCannelActive($event->getSalesChannelContext())) {
  79.             return;
  80.         }
  81.         /** @var CmsPageCollection $cms */
  82.         $cms $event->getResult();
  83.         /** @var CmsPageEntity $cmsEntity */
  84.         foreach ($cms->getIterator() as $cmsEntity) {
  85.             //Product
  86.             $productBoxes $cmsEntity->getElementsOfType('product-box');
  87.             /** @var CmsSlotEntity $productBox */
  88.             foreach ($productBoxes as $productBox) {
  89.                 /** @var ProductBoxStruct $box */
  90.                 $box=$productBox->getData();
  91.                 /** @var SalesChannelProductEntity $product */
  92.                 $product $box->getProduct();
  93.                 $this->addExtensionToProduct($product$event->getContext());
  94.             }
  95.             //Slider
  96.             $productBoxes $cmsEntity->getElementsOfType('product-slider');
  97.             /** @var CmsSlotEntity $productBox */
  98.             foreach ($productBoxes as $productBox) {
  99.                 $sliderProducts $productBox->getData()->getProducts();
  100.                 if ($sliderProducts === null) {
  101.                     continue;
  102.                 }
  103.                 foreach ($sliderProducts->getElements() as $product) {
  104.                     $this->addExtensionToProduct($product$event->getContext());
  105.                 }
  106.             }
  107.             //CrossSelling
  108.             $productBoxes $cmsEntity->getElementsOfType('cross-selling');
  109.             /** @var CmsSlotEntity $productBox */
  110.             foreach ($productBoxes as $productBox) {
  111.                 $crossSellings $productBox->getData()->getCrossSellings();
  112.                 if ($crossSellings === null) {
  113.                     continue;
  114.                 }
  115.                 foreach ($crossSellings->getElements() as $crossSelling) {
  116.                     $products $crossSelling->getProducts()->getElements();
  117.                     foreach ($products as $product) {
  118.                         $this->addExtensionToProduct($product$event->getContext());
  119.                     }
  120.                 }
  121.             }
  122.         }
  123.     }
  124.     /**
  125.      * @param SearchPageLoadedEvent $event
  126.      */
  127.     public function onSearchPageLoaded(SearchPageLoadedEvent $event): void
  128.     {
  129.         if (!$this->isCannelActive($event->getSalesChannelContext())) {
  130.             return;
  131.         }
  132.         $elements $event->getPage()->getListing()->getElements();
  133.         /** @var SalesChannelProductEntity $product */
  134.         foreach($elements as $product) {
  135.             $this->addExtensionToProduct($product$event->getContext());
  136.         }
  137.     }
  138.     /**
  139.      * @param ProductListingResultEvent $event
  140.      */
  141.     public function onProductListingResult(ProductListingResultEvent $event): void
  142.     {
  143.         if (!$this->isCannelActive($event->getSalesChannelContext())) {
  144.             return;
  145.         }
  146.         $elements $event->getResult()->getElements();
  147.         /** @var SalesChannelProductEntity $product */
  148.         foreach($elements as $product) {
  149.             $this->addExtensionToProduct($product$event->getContext());
  150.         }
  151.     }
  152.     /**
  153.      * @param SalesChannelProductEntity $product
  154.      * @param Context $context
  155.      * @return void
  156.      */
  157.     private function addExtensionToProduct(
  158.         SalesChannelProductEntity $product,
  159.         Context $context
  160.     ):void {
  161.         $hasOptions $this->productHasOptions($product$context);
  162.         // add to extensions
  163.         $product->addExtension(
  164.             ProductOptionsLoader::PRODUCT_OPTIONS_EXT_KEY,
  165.             (new ArrayStruct())->assign(['hasProductOptions' => $hasOptions])
  166.         );
  167.     }
  168.     /**
  169.      * @param SalesChannelProductEntity $product
  170.      * @param Context $context
  171.      * @return bool
  172.      */
  173.     private function productHasOptions(SalesChannelProductEntity $productContext $context): bool
  174.     {
  175.         $criteria = new Criteria();
  176.         $criteria->addAssociations([
  177.             'group.productoptionsgroup',
  178.             'option.productoptionsoption'
  179.         ]);
  180.         $productId $this->productOptionsFilter->getProductid($product->getId(), $context);
  181.         $criteria->addFilter(
  182.             new EqualsFilter('productId'$productId)
  183.         );
  184.         $criteria->addFilter(
  185.             $this->productOptionsFilter->getFilter()
  186.         );
  187.         $total $this->productOptionRepository->searchIds(
  188.             $criteria$context
  189.         )->getTotal();
  190.         return $total 0;
  191.     }
  192.     /**
  193.      * @param SalesChannelContext $context
  194.      * @return array|mixed|null
  195.      */
  196.     private function isCannelActive(SalesChannelContext $context)
  197.     {
  198.         return $this->systemConfigService->get(
  199.             'SwpProductOptionsSix.config.channelActive',
  200.             $context->getSalesChannel()->getId()
  201.         );
  202.     }
  203. }