custom/plugins/s360-product-recommendations/src/Subscriber/ProductDetailSubscriber.php line 42

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace S360ProductRecommendations\Subscriber;
  3. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  4. use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
  5. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  6. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  7. use Shopware\Core\Content\Cms\SalesChannel\Struct\ProductSliderStruct;
  8. use Shopware\Core\Content\ProductStream\Service\ProductStreamBuilderInterface;
  9. use Shopware\Core\Content\Product\SalesChannel\Listing\ProductListingLoader;
  10. class ProductDetailSubscriber implements EventSubscriberInterface
  11. {
  12.     private EntityRepositoryInterface $categoryRepository;
  13.     private ProductStreamBuilderInterface $productStreamBuilder;
  14.     private ProductListingLoader $listingLoader;
  15.     public function __construct(
  16.         EntityRepositoryInterface $categoryRepository,
  17.         ProductStreamBuilderInterface $productStreamBuilder,
  18.         ProductListingLoader $listingLoader
  19.     ){
  20.         $this->categoryRepository $categoryRepository;
  21.         $this->productStreamBuilder $productStreamBuilder;
  22.         $this->listingLoader $listingLoader;
  23.     }
  24.     public static function getSubscribedEvents(): array
  25.     {
  26.         // Return the events to listen to as array like this:  <event to listen to> => <method to execute>
  27.         return [
  28.             ProductPageLoadedEvent::class => 'onProductPageLoaded'
  29.         ];
  30.     }
  31.     // load either based on dynamic product group id or based on parent category
  32.     public function onProductPageLoaded(ProductPageLoadedEvent $event)
  33.     {
  34.         $productSliderStruct = new ProductSliderStruct();
  35.         $productPage $event->getPage();
  36.         $context $event->getContext();
  37.         $limit 10;
  38.         $activeCategory $productPage->getHeader()->getNavigation()->getActive();
  39.         $translated $activeCategory->getTranslated();
  40.         $productStreamId $translated["customFields"]["s360_product_recommendations_dynamic_product_group"] ?? false;
  41.         $currentProductId $productPage->getProduct()->getId();
  42.         try {
  43.             if($productStreamId){
  44.                 $filters $this->productStreamBuilder->buildFilters($productStreamId$context);
  45.                 $criteria = new Criteria();
  46.                 $criteria->addFilter(...$filters)->setLimit($limit);
  47.                 $searchResult $this->listingLoader->load($criteria$event->getSalesChannelContext());
  48.                 $products $searchResult->getEntities();
  49.                 if($products->has($currentProductId)){
  50.                     $products->remove($currentProductId);
  51.                 }
  52.                 $productSliderStruct->setProducts($products);
  53.             } else {
  54.                 // no dynamic product group assigned: try getting 10 products from parent category
  55.                 $parentCategoryId $activeCategory->getParentId();
  56.                 $productCollection $this->getProductCollectionFromCat($parentCategoryId$limit$context);
  57.                 // if no products assigned to category, get from current category
  58.                 if($productCollection->count() === 0){
  59.                     $productCollection $this->getProductCollectionFromCat($activeCategory->getId(), $limit$context);
  60.                 }
  61.                 if($productCollection->count() > 0){
  62.                     // remove current product id in case it happens to be included
  63.                     $productIds $productCollection->getIds();
  64.                     unset($productIds[$currentProductId]);
  65.                     if(count($productIds) > 0){
  66.                         $searchResult $this->listingLoader->load(new Criteria($productIds), $event->getSalesChannelContext());
  67.                         $products $searchResult->getEntities();
  68.                         $productSliderStruct->setProducts($products);
  69.                     }
  70.                 } 
  71.             }
  72.             // if no products found, struct will be empty
  73.             $productPage->addExtension("s360ProductRecommendations"$productSliderStruct);
  74.         } catch (\Exception $e){
  75.             // if exception, empty struct will be added
  76.             $productPage->addExtension("s360ProductRecommendations"$productSliderStruct);
  77.         }
  78.         
  79.     }
  80.     private function getProductCollectionFromCat($categoryId$limit$context){
  81.         $criteria = new Criteria([$categoryId]);
  82.         $criteria->addAssociation('products');
  83.         $criteria->getAssociation('products')->setLimit($limit);
  84.         $categorySearchResult $this->categoryRepository->search($criteria$context)->first();
  85.         // products that are assigned directly
  86.         return $categorySearchResult->getProducts();
  87.     }
  88. }