custom/plugins/Goesting/src/Subscriber/StorefrontRenderSubscriber.php line 147

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Websignaal\Goesting\Subscriber;
  3. use Shopware\Storefront\Event\StorefrontRenderEvent;
  4. use Shopware\Core\Framework\Context;
  5. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  6. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  7. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\RangeFilter;
  9. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  11. use Shopware\Core\Content\Product\Events\ProductListingCriteriaEvent;
  12. use Shopware\Core\Content\Product\Events\ProductSearchCriteriaEvent;
  13. use Shopware\Core\Content\Product\SalesChannel\CrossSelling\CrossSellingElementCollection;
  14. class StorefrontRenderSubscriber implements EventSubscriberInterface
  15. {
  16.        /**
  17.      * @var EntityRepositoryInterface
  18.      */
  19.     private $categoryRepository;
  20.     /**
  21.      * @var EntityRepositoryInterface
  22.      */
  23.     private $productRepository;
  24.     /**
  25.      * @var EntityRepositoryInterface
  26.      */
  27.     private $propertyGroupOptionRepository;
  28.     public function __construct(
  29.         EntityRepositoryInterface $categoryRepository,
  30.         EntityRepositoryInterface $productRepository,
  31.         EntityRepositoryInterface $propertyGroupOptionRepository
  32.     )
  33.     {
  34.         $this->categoryRepository $categoryRepository;
  35.         $this->productRepository $productRepository;
  36.         $this->propertyGroupOptionRepository $propertyGroupOptionRepository;
  37.     }
  38.     public static function getSubscribedEvents(): array
  39.     {
  40.         return[
  41.             StorefrontRenderEvent::class => 'onStorefrontRender',
  42.             ProductListingCriteriaEvent::class => 'addAssociationsToProductListing',
  43.             ProductSearchCriteriaEvent::class => 'addAssociationsToProductSearch' 
  44.         ];
  45.     }
  46.      public function onStorefrontRender(StorefrontRenderEvent $event)
  47.      {
  48.         
  49.         $route $event->getRequest()->get('_route');
  50.         //only execute the code if the route is the detail page 
  51.         if($route == 'frontend.detail.page'){
  52.             
  53.             $page $event->getParameters()['page'];
  54.             $crossSellings$page->getCrossSellings();
  55.             $this->getCrossSellingsWithAssociations($crossSellings,$event->getContext());
  56.             //check if page is set and of the right entityType
  57.             if($page && is_a($page'Shopware\Storefront\Page\Product\ProductPage'))
  58.             {
  59.                 //get product from page
  60.                 $product$page->getProduct();
  61.                 if($product)
  62.                 {
  63.                     $categoryCollection$this->getCategoryCollectionByIds($product->getCategoryIds(), $event->getContext());
  64.                     $propertyGroupCollection $this->getPropertGroupOption($product->getId(), $event->getContext());
  65.                     if ($categoryCollection) {
  66.                         //add categoryCollection to product entity on detail page
  67.                         $page->getProduct()->setCategories($categoryCollection);
  68.                         //add propertyGroupCollection to product entity on detail page
  69.                         $page->getProduct()->setProperties($propertyGroupCollection);
  70.                         $page->setProduct($product);
  71.                         //set newly updated page to event
  72.                         $event->setParameter('page'$page);
  73.                         
  74.                     }
  75.                 }
  76.             }
  77.         }
  78.     } 
  79.     public function getCrossSellingsWithAssociations($crossSellings,$context)
  80.     {
  81.        $crossSellingWithAssociations = new CrossSellingElementCollection();
  82.        $crossSellProductsIds= [];
  83.        
  84.        //get CrossSellings ProductCollections
  85.        foreach($crossSellings as $crossSelling)
  86.        {
  87.            $crossSellProducts$crossSelling->getProducts();
  88.            //check each products in crossSell if they are found in allowed products (matching to the current model).
  89.            foreach($crossSellProducts as $crossSellProduct)
  90.            {
  91.             $crossSellProductsIds[] = $crossSellProduct->getId();
  92.            }
  93.             $crossSellProducts $this->getCrossSellingProductCollection($crossSellProductsIds$context);
  94.             $crossSelling->setProducts($crossSellProducts);
  95.            // add the crossSelling to the allowed CrossSellings
  96.            $crossSellingWithAssociations->add($crossSelling);
  97.        }
  98.        
  99.        return $crossSellingWithAssociations;
  100.     }
  101.     private function getCrossSellingProductCollection($productIds,$context)
  102.     {
  103.         $criteria = new Criteria();
  104.         $criteria->addFilter(new EqualsAnyFilter('id'$productIds));
  105.         $criteria->addAssociation('categories');
  106.         $criteria->addAssociation('properties');
  107.         $criteria->addAssociation('properties.group');
  108.         $criteria->addAssociation('properties.media');
  109.         $criteria->addAssociation('cover');
  110.         $productCollection $this->productRepository->search($criteria$context)->getEntities();
  111.         return $productCollection;
  112.     }
  113.     public function addAssociationsToProductListing(ProductListingCriteriaEvent $event)
  114.     {
  115.         $criteria $event->getCriteria();
  116.         $criteria->addAssociation('categories');
  117.         $criteria->addAssociation('properties');
  118.         $criteria->addAssociation('properties.group');
  119.         $criteria->addAssociation('properties.media');
  120.     }
  121.     public function addAssociationsToProductSearch(ProductSearchCriteriaEvent $event)
  122.     {
  123.         $criteria $event->getCriteria();
  124.         $criteria->addAssociation('categories');
  125.         $criteria->addAssociation('properties');
  126.         $criteria->addAssociation('properties.group');
  127.         $criteria->addAssociation('properties.media');
  128.     }
  129.     
  130.     private function getCategoryCollectionByIds($categoryIds$context)
  131.     {
  132.         $criteria = new Criteria();
  133.         $criteria->addFilter(new EqualsAnyFilter('id'$categoryIds));
  134.         //removes the Products category
  135.         $criteria->addFilter(
  136.             new RangeFilter('level', [
  137.                 RangeFilter::GT => 2
  138.             ])
  139.         );
  140.         $criteria->addAssociation('seoUrls');
  141.         $criteria->addAssociation('media');
  142.         $categoryCollection $this->categoryRepository->search($criteria,  $context)->getEntities();
  143.         return $categoryCollection;
  144.     }
  145.     private function getPropertGroupOption($productId,$context)
  146.     {
  147.         $criteria = new Criteria();
  148.         $criteria->addAssociation('productProperties');
  149.         $criteria->addAssociation('group');
  150.         $criteria->addFilter(new EqualsFilter('productProperties.id'$productId));
  151.         $criteria->addAssociation('media');
  152.         $propertyGroupOptionCollection $this->propertyGroupOptionRepository->search($criteria$context)->getEntities();
  153.         return $propertyGroupOptionCollection;
  154.     }
  155. }