custom/plugins/MaxiaListingVariants6/src/Subscriber/Storefront.php line 77

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Maxia\MaxiaListingVariants6\Subscriber;
  3. use Maxia\MaxiaListingVariants6\Service\ConfigService;
  4. use Maxia\MaxiaListingVariants6\Service\ListingVariantsLoader;
  5. use Monolog\Logger;
  6. use Shopware\Core\Content\Product\Events\ProductListingCollectFilterEvent;
  7. use Shopware\Core\Content\Product\Events\ProductListingResultEvent;
  8. use Shopware\Core\Content\Product\Events\ProductSearchResultEvent;
  9. use Shopware\Core\Framework\Struct\ArrayEntity;
  10. use Shopware\Storefront\Event\StorefrontRenderEvent;
  11. use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
  12. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  13. use TypeError;
  14. /**
  15.  * @package Maxia\MaxiaListingVariants6\Subscriber
  16.  */
  17. class Storefront implements EventSubscriberInterface
  18. {
  19.     public static function getSubscribedEvents(): array
  20.     {
  21.         $events = [
  22.             StorefrontRenderEvent::class => 'onStorefrontRender',
  23.             ProductSearchResultEvent::class => ['onSearchResult', -10],
  24.             ProductPageLoadedEvent::class => ['onProductPageLoaded', -10],
  25.             ProductListingResultEvent::class => ['onProductListingResult', -10],
  26.             ProductListingCollectFilterEvent::class => 'onCollectFilters'
  27.         ];
  28.         if (class_exists('\Acris\Search\Core\Content\Product\Events\ProductManufacturerResultEvent')) {
  29.             /** @phpstan-ignore-next-line */
  30.             $events[\Acris\Search\Core\Content\Product\Events\ProductManufacturerResultEvent::class]
  31.                 = 'onAcrisProductManufacturerResultEvent';
  32.         }
  33.         if (class_exists('\Acris\SuggestedProducts\Storefront\Page\RecentlyViewed\RecentlyViewedPageLoadedEvent')) {
  34.             /** @phpstan-ignore-next-line */
  35.             $events[\Acris\SuggestedProducts\Storefront\Page\RecentlyViewed\RecentlyViewedPageLoadedEvent::class]
  36.                 = 'onAcrisRecentlyViewedPageLoadedEvent';
  37.         }
  38.         return $events;
  39.     }
  40.     /**
  41.      * @var ListingVariantsLoader
  42.      */
  43.     private $listingVariantsLoader;
  44.     /**
  45.      * @var ConfigService
  46.      */
  47.     private $configService;
  48.     /**
  49.      * @var Logger
  50.      */
  51.     private $logger;
  52.     public function __construct(
  53.         ListingVariantsLoader $variantListingService,
  54.         Logger $logger,
  55.         ConfigService $configService
  56.     ) {
  57.         $this->listingVariantsLoader $variantListingService;
  58.         $this->configService $configService;
  59.         $this->logger $logger;
  60.     }
  61.     public function onCollectFilters(ProductListingCollectFilterEvent $event)
  62.     {
  63.         ListingVariantsLoader::setFilters($event->getFilters());
  64.     }
  65.     public function onStorefrontRender(StorefrontRenderEvent $event)
  66.     {
  67.         // add plugin config to context
  68.         $context $event->getSalesChannelContext();
  69.         $config $this->configService->getBaseConfig($context);
  70.         $context->addExtension('maxiaListingVariants'$config);
  71.         if (!$config->isPluginEnabled()) {
  72.             return;
  73.         }
  74.         $request $event->getRequest();
  75.         // CbaxModulManufacturers: Load variants on storefront render (plugin has no result event)
  76.         if ($request->attributes->get('_route') === 'frontend.cbax.manufacturer.detail') {
  77.             try {
  78.                 /** @var \Shopware\Core\Framework\DataAbstractionLayer\Search\EntitySearchResult $products */
  79.                 $products $event->getParameters()['cbaxModulManufacturers']['products'];
  80.                 if ($products && $products->getEntities() && $products->getTotal()) {
  81.                     $this->listingVariantsLoader->load($products->getEntities()->getElements(), $event->getSalesChannelContext());
  82.                 }
  83.             } catch (\Exception $e) {
  84.                 $this->logger->error('Exception occurred when loading variants in cbax manufacturer listing: '.
  85.                     $e->getMessage().",\nStack trace: ".$e->getTraceAsString());
  86.             }
  87.         }
  88.     }
  89.     /**
  90.      * Loads variants in search results listing.
  91.      *
  92.      * @param ProductSearchResultEvent $event
  93.      */
  94.     public function onSearchResult(ProductSearchResultEvent $event)
  95.     {
  96.         $products $event->getResult()->getEntities();
  97.         $config $this->configService->getBaseConfig($event->getSalesChannelContext());
  98.         if ($config->isPluginEnabled() && $config->isShowInSearchListing()) {
  99.             $disablePreselection $config->isDisablePreselectionInSearch();
  100.             if ($event->getSalesChannelContext()->hasExtension('acris_exact_search')
  101.                 && $event->getResult()->getTotal() === 1)
  102.             {
  103.                 $disablePreselection true;
  104.             }
  105.             if ($disablePreselection) {
  106.                 $event->getRequest()->attributes->set('maxia-handle-variant-preselection'false);
  107.             }
  108.             try {
  109.                 $this->listingVariantsLoader->load($products->getElements(), $event->getSalesChannelContext());
  110.             } catch (\Exception $e) {
  111.                 $this->logger->error('Exception occurred when loading variants in search result: '.
  112.                     $e->getMessage().",\nStack trace: ".$e->getTraceAsString());
  113.             }
  114.         }
  115.     }
  116.     /**
  117.      * Loads variants via ProductListingResultEvent
  118.      *
  119.      * @param ProductListingResultEvent $event
  120.      */
  121.     public function onProductListingResult(ProductListingResultEvent $event)
  122.     {
  123.         $products $event->getResult()->getEntities();
  124.         $config $this->configService->getBaseConfig($event->getSalesChannelContext());
  125.         /** @var ArrayEntity $extension */
  126.         $extension $event->getResult()->getExtension('maxiaListingVariants');
  127.         if ($config->isPluginEnabled() && $extension && $extension->get('loadVariants')) {
  128.             try {
  129.                 $this->listingVariantsLoader->load($products->getElements(), $event->getSalesChannelContext());
  130.             } catch (\Exception $e) {
  131.                 $this->logger->error('Exception occurred when loading variants in product listing result: '.
  132.                     $e->getMessage().",\nStack trace: ".$e->getTraceAsString());
  133.             }
  134.         }
  135.     }
  136.     /**
  137.      * Load variants in cross selling when no cms layout is assigned.
  138.      * Otherwise, variants will be loaded from CrossSellingCmsElementResolver
  139.      *
  140.      * @param ProductPageLoadedEvent $event
  141.      */
  142.     public function onProductPageLoaded(ProductPageLoadedEvent $event)
  143.     {
  144.         $config $this->configService->getBaseConfig($event->getSalesChannelContext());
  145.         if (!$config->isPluginEnabled() || !$config->isShowInCrossSelling()) {
  146.             return;
  147.         }
  148.         // get cross selling products
  149.         $page $event->getPage();
  150.         $crossSellings = [];
  151.         try {
  152.             if ($event->getPage()->getCrossSellings()) {
  153.                 foreach ($event->getPage()->getCrossSellings()->getElements() as $element) {
  154.                     $crossSellings[] = $element->getProducts()->getElements();
  155.                 }
  156.             }
  157.         } catch (TypeError $e) {}
  158.         // get AcrisSuggestedProductsCS products
  159.         $extensionKeys = [
  160.             'acris_customers_also_bought',
  161.             'acris_customers_also_viewed',
  162.             'acris_recently_viewed_allowed',
  163.             'acris_recently_viewed_products',
  164.             'acrisSuggestedProducts'
  165.         ];
  166.         foreach ($extensionKeys as $key) {
  167.             if ($page->getProduct()->hasExtension($key)) {
  168.                 $extension $page->getProduct()->getExtension($key);
  169.                 if (!$extension) {
  170.                     continue;
  171.                 }
  172.                 if ($extension instanceof ArrayEntity && isset($extension['products'])) {
  173.                     $products $extension['products'];
  174.                 } else {
  175.                     $products $extension->getProducts();
  176.                 }
  177.                 if (is_array($products)) {
  178.                     $crossSellings[] = $products;
  179.                 } else {
  180.                     $crossSellings[] = $products->getElements();
  181.                 }
  182.             }
  183.         }
  184.         // load variants for all cross sellings
  185.         if ($crossSellings) {
  186.             foreach ($crossSellings as $products) {
  187.                 try {
  188.                     $this->listingVariantsLoader->load($products$event->getSalesChannelContext());
  189.                 } catch (\Exception $e) {
  190.                     $this->logger->error('Exception occurred when loading variants in cross selling: '.
  191.                         $e->getMessage().",\nStack trace: ".$e->getTraceAsString());
  192.                 }
  193.             }
  194.         }
  195.     }
  196.     /**
  197.      * AcrisSearchCS manufacturer product listing
  198.      *
  199.      * @param \Acris\Search\Core\Content\Product\Events\ProductManufacturerResultEvent $event
  200.      */
  201.     /** @phpstan-ignore-next-line */
  202.     public function onAcrisProductManufacturerResultEvent(\Acris\Search\Core\Content\Product\Events\ProductManufacturerResultEvent $event)
  203.     {
  204.         $products $event->getResult()->getEntities();
  205.         $config $this->configService->getBaseConfig($event->getSalesChannelContext());
  206.         if ($config->isPluginEnabled()) {
  207.             try {
  208.                 $this->listingVariantsLoader->load($products->getElements(), $event->getSalesChannelContext());
  209.             } catch (\Exception $e) {
  210.                 $this->logger->error('Exception occurred when loading variants on ProductManufacturerResultEvent: '.
  211.                     $e->getMessage().",\nStack trace: ".$e->getTraceAsString());
  212.             }
  213.         }
  214.     }
  215.     /**
  216.      * AcrisSuggestedProductsCS recently viewed products
  217.     /** @phpstan-ignore-next-line */
  218.     public function onAcrisRecentlyViewedPageLoadedEvent(\Acris\SuggestedProducts\Storefront\Page\RecentlyViewed\RecentlyViewedPageLoadedEvent $event)
  219.     {
  220.         $config $this->configService->getBaseConfig($event->getSalesChannelContext());
  221.         if ($config->isPluginEnabled() && $config->isShowInCrossSelling()) {
  222.             try {
  223.                 $this->listingVariantsLoader->load($event->getPage()->getProducts(), $event->getSalesChannelContext());
  224.             } catch (\Exception $e) {
  225.                 $this->logger->error('Exception occurred when loading variants on ProductManufacturerResultEvent: '.
  226.                     $e->getMessage().",\nStack trace: ".$e->getTraceAsString());
  227.             }
  228.         }
  229.     }
  230. }