custom/plugins/EwGrecoBundle/src/Subscriber/LineItemSubscriber.php line 51

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Ew\GrecoBundle\Subscriber;
  3. use Shopware\Core\Checkout\Cart\Cart;
  4. use Shopware\Core\Checkout\Cart\Event\AfterLineItemAddedEvent;
  5. use Shopware\Core\Checkout\Cart\Event\BeforeLineItemAddedEvent;
  6. use Shopware\Core\Checkout\Cart\LineItem\LineItem;
  7. use Shopware\Core\Checkout\Cart\LineItemFactoryRegistry;
  8. use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
  9. use Shopware\Core\Framework\Context;
  10. use Shopware\Core\Framework\DataAbstractionLayer\EntityCollection;
  11. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  13. use Shopware\Core\Framework\Struct\ArrayStruct;
  14. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  15. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  16. use Symfony\Component\HttpFoundation\RequestStack;
  17. class LineItemSubscriber implements EventSubscriberInterface
  18. {
  19.     private CartService $cartService;
  20.     private LineItemFactoryRegistry $factory;
  21.     private EntityRepository $productRepository;
  22.     public function __construct(
  23.         CartService $cartService,
  24.         LineItemFactoryRegistry $factory,
  25.         EntityRepository $productRepository
  26.     ) {
  27.         $this->cartService $cartService;
  28.         $this->factory $factory;
  29.         $this->productRepository $productRepository;
  30.     }
  31.     /**
  32.      * @inheritDoc
  33.      */
  34.     public static function getSubscribedEvents(): array
  35.     {
  36.         return [
  37.             BeforeLineItemAddedEvent::class => 'onLineItemAdded'
  38.         ];
  39.     }
  40.     /**
  41.      * @param BeforeLineItemAddedEvent $event
  42.      * @return void
  43.      */
  44.     public function onLineItemAdded(BeforeLineItemAddedEvent $event)
  45.     {
  46.         $updatedOnce $event->getContext()->getExtension('updatedOnce');
  47.         if (!$updatedOnce) {
  48.             $cart $event->getCart();
  49.             // Get product ids from cart
  50.             $productIds $cart->getLineItems()
  51.                 ->filterType(LineItem::PRODUCT_LINE_ITEM_TYPE)
  52.                 ->map(fn(LineItem $lineItem) => $lineItem->getReferencedId());
  53.             // Fetch products in cart
  54.             $products $this->getProducts($productIds$event->getContext());
  55.             // Retrieve all bundle products from cart and remove the ones that are already added
  56.             foreach ($event->getCart()->getLineItems() as $lineItem) {
  57.                 if ($products->has($lineItem->getReferencedId())) {
  58.                     $product $products->get($lineItem->getReferencedId());
  59.                     if (isset($product->getCustomFields()['greco_bundle_article']) && $product->getCustomFields()['greco_bundle_article']) {
  60.                         if ($cart->getLineItems()->has($lineItem->getReferencedId())) {
  61.                             if (isset($lineItem->getPayload()['added'])) {
  62.                                 $this->removeProductFromCart($event->getCart(), $lineItem->getReferencedId(), $event->getSalesChannelContext());
  63.                             }
  64.                         }
  65.                     }
  66.                 }
  67.             }
  68.             $pseudoArticles = [];
  69.             // Clean cart for removed bundle products
  70.             foreach ($cart->getLineItems() as $lineItem) {
  71.                 if ($products->has($lineItem->getReferencedId())) {
  72.                     $product $products->get($lineItem->getReferencedId());
  73.                     if (isset($product->getCustomFields()['greco_pseudo_article']) && $product->getCustomFields()['greco_pseudo_article']) {
  74.                         $this->removeProductFromCart($cart$lineItem->getId(), $event->getSalesChannelContext());
  75.                         if (isset($product->getCustomFields()['greco_pseudo_articles']) && $product->getCustomFields()['greco_pseudo_articles']) {
  76.                             foreach ($product->getCustomFields()['greco_pseudo_articles'] as $productId) {
  77.                                 $pseudoArticles[] = $productId;
  78.                             }
  79.                         }
  80.                     }
  81.                 }
  82.             }
  83.             // Add missing bundle items to cart
  84.             if (!empty($pseudoArticles)) {
  85.                 foreach ($pseudoArticles as $productId) {
  86.                     if (!in_array($productId$productIds)) {
  87.                         // Add bundle item to cart
  88.                         $this->addProductToCart($cart$productId1$event->getSalesChannelContext());
  89.                     }
  90.                 }
  91.             }
  92.             $event->getContext()->setExtensions(['updatedOnce' => new ArrayStruct(['isUpdated' => true])]);
  93.         }
  94.     }
  95.     /**
  96.      * Add product to cart
  97.      *
  98.      * @param Cart $cart
  99.      * @param string $productId
  100.      * @param int $quantity
  101.      * @param SalesChannelContext $context
  102.      */
  103.     private function addProductToCart(Cart $cartstring $productIdint $quantitySalesChannelContext $context): void
  104.     {
  105.         $lineItem $this->factory->create([
  106.             'type' => LineItem::PRODUCT_LINE_ITEM_TYPE,
  107.             'referencedId' => $productId,
  108.             'quantity' => $quantity,
  109.         ], $context);
  110.         $lineItem->setPayloadValue('added'true);
  111.         $this->cartService->add($cart$lineItem$context);
  112.     }
  113.     /**
  114.      * Remove product from cart
  115.      *
  116.      * @param Cart $cart
  117.      * @param string $itemId
  118.      * @param SalesChannelContext $context
  119.      */
  120.     private function removeProductFromCart(Cart $cartstring $itemIdSalesChannelContext $context): void
  121.     {
  122.         $this->cartService->remove($cart$itemId$context);
  123.     }
  124.     /**
  125.      * Get product
  126.      *
  127.      * @param array $productIds
  128.      * @param Context $context
  129.      * @return EntityCollection
  130.      */
  131.     private function getProducts(array $productIdsContext $context): EntityCollection
  132.     {
  133.         $criteria = (new Criteria($productIds));
  134.         return $this->productRepository->search($criteria$context)->getEntities();
  135.     }
  136. }