custom/plugins/SwpProductOptionsSix/src/Subscriber/Page/Product/ProductSubscriber.php line 69

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 ProductSubscriber.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\Page\Product;
  15. use Shopware\Core\Content\Property\Aggregate\PropertyGroupOption\PropertyGroupOptionCollection;
  16. use Shopware\Core\Content\Property\PropertyGroupCollection;
  17. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  18. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  19. use Shopware\Core\Framework\Struct\ArrayStruct;
  20. use Shopware\Core\System\SystemConfig\SystemConfigService;
  21. use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
  22. use Swp\ProductOptionsSix\Core\Content\ProductOptions\SalesChannel\ProductOptionsLoader;
  23. use Swp\ProductOptionsSix\Core\Content\ProductOptions\SalesChannel\ProductOptionsLoaderInterface;
  24. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  25. class ProductSubscriber implements EventSubscriberInterface
  26. {
  27.     /** @var SystemConfigService */
  28.     private $systemConfigService;
  29.     /** @var ProductOptionsLoaderInterface */
  30.     private $productOptionsLoader;
  31.     /** @var EntityRepository */
  32.     private $filterRepository;
  33.     /**
  34.      * ProductSubscriber constructor.
  35.      *
  36.      * @param SystemConfigService $systemConfigService
  37.      * @param EntityRepository $filterRepository
  38.      * @param ProductOptionsLoaderInterface $productOptionsLoader
  39.      */
  40.     public function __construct(
  41.         SystemConfigService $systemConfigService,
  42.         EntityRepository $filterRepository,
  43.         ProductOptionsLoaderInterface $productOptionsLoader
  44.     ) {
  45.         $this->systemConfigService $systemConfigService;
  46.         $this->filterRepository $filterRepository;
  47.         $this->productOptionsLoader $productOptionsLoader;
  48.     }
  49.     /**
  50.      * @return array
  51.      */
  52.     public static function getSubscribedEvents(): array
  53.     {
  54.         return [
  55.             ProductPageLoadedEvent::class => 'onProductPageLoaded'
  56.         ];
  57.     }
  58.     /**
  59.      * @param ProductPageLoadedEvent $event
  60.      */
  61.     public function onProductPageLoaded(ProductPageLoadedEvent $event): void
  62.     {
  63.         if (!$this->isCannelActive($event)) {
  64.             return;
  65.         }
  66.         $product $event->getPage()->getProduct();
  67.         if($product->getChildCount() && !$product->getParentId()) {
  68.             return;
  69.         }
  70.         list ($productOptions$parentProducts) = $this->productOptionsLoader->load($product->getId(), $event->getSalesChannelContext());
  71.         $propertyIds $this->getOptionPropertys($productOptions);
  72.         $filters $this->getFilters($event$propertyIds);
  73.         // add to extensions
  74.         $product->addExtension(
  75.             ProductOptionsLoader::PRODUCT_OPTIONS_EXT_KEY,
  76.             (new ArrayStruct())->assign([
  77.                 'assignedOptions' => $productOptions,
  78.                 'parentProducts' => $parentProducts,
  79.                 'filters' => $filters
  80.             ])
  81.         );
  82.     }
  83.     /**
  84.      * @param ProductPageLoadedEvent $event
  85.      * @param array $propertyIds
  86.      * @return PropertyGroupCollection|null
  87.      */
  88.     private function getFilters(ProductPageLoadedEvent $event, array $propertyIds = []): ?PropertyGroupCollection
  89.     {
  90.         $propertyIds \array_unique($propertyIds);
  91.         if (count($propertyIds) === 0) {
  92.             return null;
  93.         }
  94.         /** @var array $propertyIds */
  95.         $criteria = new Criteria($propertyIds);
  96.         $criteria->addAssociation('group');
  97.         $criteria->setTitle('product-listing::property-filter');
  98.         /** @var PropertyGroupOptionCollection $filters */
  99.         $filters $this->filterRepository->search($criteria$event->getContext())->getEntities();
  100.         // group options by their property-group
  101.         $groupedFilters $filters->groupByPropertyGroups();
  102.         $groupedFilters->sortByPositions();
  103.         $groupedFilters->sortByConfig();
  104.         return $groupedFilters;
  105.     }
  106.     /**
  107.      * @param array $productOptions
  108.      * @param array $propertyIds
  109.      * @return array
  110.      */
  111.     private function getOptionPropertys(
  112.         array $productOptions,
  113.         array $propertyIds = []
  114.     ): array
  115.     {
  116.         foreach ($productOptions as $productOption) {
  117.             if ($productOption->getExtension(ProductOptionsLoader::PRODUCT_OPTIONS_EXT_KEY)->has('children')) {
  118.                 $propertyIds $this->getOptionPropertys(
  119.                     $productOption->getExtension(ProductOptionsLoader::PRODUCT_OPTIONS_EXT_KEY)->get('children'),
  120.                     $propertyIds
  121.                 );
  122.                 continue;
  123.             }
  124.             $options $productOption->getExtension(ProductOptionsLoader::PRODUCT_OPTIONS_EXT_KEY)->get('options');
  125.             if (!\is_array($options)) {
  126.                 continue;
  127.             }
  128.             foreach ($options as $option) {
  129.                 $addIds $option->getPropertyIds();
  130.                 if (\is_array($addIds)) {
  131.                     $propertyIds \array_merge($propertyIds$addIds);
  132.                 }
  133.             }
  134.         }
  135.         return $propertyIds;
  136.     }
  137.     /**
  138.      * @param ProductPageLoadedEvent $event
  139.      * @return array|mixed|null
  140.      */
  141.     private function isCannelActive(ProductPageLoadedEvent $event)
  142.     {
  143.         return $this->systemConfigService->get(
  144.             'SwpProductOptionsSix.config.channelActive',
  145.             $event->getSalesChannelContext()->getSalesChannel()->getId()
  146.         );
  147.     }
  148. }