custom/plugins/ThemeOkeOnline/src/Storefront/Page/Checkout/CheckoutCartPageLoadedEventSubscriber.php line 40

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace ThemeOkeOnline\Storefront\Page\Checkout;
  3. use Symfony\Component\HttpFoundation\Request;
  4. use Shopware\Core\Content\Product\ProductCollection;
  5. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  6. use Shopware\Core\Checkout\Cart\LineItem\LineItemCollection;
  7. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  9. use Shopware\Storefront\Page\Checkout\Cart\CheckoutCartPageLoadedEvent;
  10. use Shopware\Core\Content\Product\SalesChannel\CrossSelling\AbstractProductCrossSellingRoute;
  11. use Shopware\Core\Content\Product\SalesChannel\CrossSelling\ProductCrossSellingRouteResponse;
  12. use Shopware\Core\System\SystemConfig\SystemConfigService;
  13. class CheckoutCartPageLoadedEventSubscriber implements EventSubscriberInterface
  14. {
  15.     private SalesChannelContext $context;
  16.     /** @var ProductCrossSellingRoute $crossSellLoaderRoute */
  17.     private $crossSellLoaderRoute;
  18.     public function __construct(
  19.         AbstractProductCrossSellingRoute $crossSellLoaderRoute,
  20.         SystemConfigService $systemConfigService
  21.     )
  22.     {
  23.         $this->crossSellLoaderRoute $crossSellLoaderRoute;
  24.         $this->systemConfigService $systemConfigService;
  25.     }
  26.     public static function getSubscribedEvents(): array
  27.     {
  28.         return [
  29.             CheckoutCartPageLoadedEvent::class => ['addCrossSellProductsToCartPage']
  30.         ];
  31.     }
  32.     public function addCrossSellProductsToCartPage(CheckoutCartPageLoadedEvent $event)
  33.     {
  34.         $this->setSalesChannelContext($event->getSalesChannelContext());
  35.         $page $event->getPage();
  36.         $cart $page->getCart();
  37.         
  38.         // collect all productIds of products in cart
  39.         $productIds $this->getProductIdsFromLineItems($cart->getLineItems());
  40.         $productCollection = new ProductCollection();
  41.         $maxNumProductsInCart $this->systemConfigService->get("ThemeOkeonline.config.maxNumProductsInCart") ?? 6;
  42.         foreach($productIds as $productId)
  43.         {
  44.             if($productCollection->count() > $maxNumProductsInCart)
  45.                 break;
  46.             // load all CrossSelling products, trough the loader, to handle normal crossselling products, but also the productstream variant
  47.             $crossSellResponse $this->crossSellLoaderRoute->load($productId, new Request(), $this->getSalesChannelContext(), new Criteria());
  48.             
  49.             // merge all CrossSelling prodicts in one ProductCollection
  50.             $productCollection $this->mergeCrossSellingProductsCollectionFromObject($crossSellResponse$productCollection);
  51.         }
  52.         // add Extension to the page
  53.         if($productCollection->count() > 0)
  54.         {
  55.             $page->addExtension(
  56.                 'crossSellProducts',
  57.                 $productCollection
  58.             );
  59.         }
  60.         
  61.     }
  62.     private function getProductIdsFromLineItems(LineItemCollection $lineItems): array
  63.     {
  64.         // get both normal products, and cp-products
  65.         return array_merge(
  66.             $this->getProductIdsFromProducts($lineItems),
  67.             $this->getProductIdsFromCustomizedProducts($lineItems)
  68.         );
  69.     }
  70.     private function getProductIdsFromCustomizedProducts(LineItemCollection $lineItems): array
  71.     {
  72.         $ids = array();
  73.         // loop trough the Cp's and get the ReferenceIds from there underlaying products
  74.         $lineItems->filterType('customized-products')->map(function($lineItem) use (&$ids) {
  75.             $ids array_merge($idsarray_values($lineItem->getChildren()->filterType('product')->getReferenceIds()));
  76.         });
  77.         return $ids;
  78.     }
  79.     private function getProductIdsFromProducts(LineItemCollection $lineItems): array
  80.     {
  81.         return $lineItems->filterType('product')->getReferenceIds();   
  82.     }
  83.     private function mergeCrossSellingProductsCollectionFromObject(ProductCrossSellingRouteResponse $crossSellResponseProductCollection $productCollection): ProductCollection
  84.     {
  85.         if($array $crossSellResponse->getResult())
  86.         {
  87.             foreach($array as $crossSellingElement)
  88.             {
  89.                 $productCollection->merge($crossSellingElement->getProducts());
  90.             }
  91.         }
  92.         return $productCollection;
  93.     }
  94.     private function setSalesChannelContext(SalesChannelContext $context): void
  95.     {
  96.         $this->context $context;
  97.     }
  98.     private function getSalesChannelContext(): SalesChannelContext
  99.     {
  100.         return $this->context;
  101.     }
  102. }