custom/plugins/EconsorAtBitConfiguratorConnector/src/Subscriber/AtBitCartMergeFix.php line 42

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Econsor\Shopware\AtBitConfiguratorConnector\Subscriber;
  3. use Econsor\Shopware\AtBitConfiguratorConnector\AtBitSessionKeys;
  4. use Econsor\Shopware\AtBitConfiguratorConnector\Services\AtBitPriceCalculator;
  5. use Shopware\Core\Checkout\Cart\LineItem\LineItem;
  6. use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
  7. use Shopware\Core\Framework\Struct\ArrayStruct;
  8. use Shopware\Core\System\SalesChannel\Event\SalesChannelContextRestoredEvent;
  9. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  10. use Symfony\Component\HttpFoundation\Session\Session;
  11. /**
  12.  * Shopware's login cart-merge (SalesChannelContextRestorer::mergeCart) treats every
  13.  * stackable line item as mergeable regardless of whether it already exists in the
  14.  * customer's persisted cart, so if a configurator line item id is present in both the
  15.  * guest cart (re-injected from session on every calculation) and the customer's saved
  16.  * cart, its quantity gets summed again on login. This corrects the quantity back to
  17.  * what our own session bookkeeping considers canonical, right after the merge lands.
  18.  */
  19. class AtBitCartMergeFix implements EventSubscriberInterface
  20. {
  21.     private $session;
  22.     private $cartService;
  23.     private $priceCalculator;
  24.     public function __construct(Session $sessionCartService $cartServiceAtBitPriceCalculator $priceCalculator)
  25.     {
  26.         $this->session         $session;
  27.         $this->cartService     $cartService;
  28.         $this->priceCalculator $priceCalculator;
  29.     }
  30.     public static function getSubscribedEvents(): array
  31.     {
  32.         return [
  33.             SalesChannelContextRestoredEvent::class => 'onContextRestored',
  34.         ];
  35.     }
  36.     public function onContextRestored(SalesChannelContextRestoredEvent $event): void
  37.     {
  38.         if (!$this->session->has(AtBitSessionKeys::CONFIGURATOR_PRODUCTS)) {
  39.             return;
  40.         }
  41.         $context $event->getRestoredSalesChannelContext();
  42.         $products $this->session->get(AtBitSessionKeys::CONFIGURATOR_PRODUCTS);
  43.         $cart $this->cartService->getCart($context->getToken(), $context);
  44.         $fixed false;
  45.         /** @var LineItem $sessionProduct */
  46.         foreach ($products as $id => $sessionProduct) {
  47.             $cartItem $cart->get($id);
  48.             if (!$cartItem) {
  49.                 continue;
  50.             }
  51.             $expectedQuantity $sessionProduct->getQuantity();
  52.             if ($cartItem->getQuantity() === $expectedQuantity) {
  53.                 continue;
  54.             }
  55.             /** @var ArrayStruct|null $extension */
  56.             $extension $cartItem->getExtension('atbitConfiguration');
  57.             if (!$extension instanceof ArrayStruct) {
  58.                 continue;
  59.             }
  60.             $cartItem->setQuantity($expectedQuantity);
  61.             $cartItem->setPrice($this->priceCalculator->calculate(
  62.                 (float) $extension->get('GesamtpreisOhneMwSt'),
  63.                 (float) $extension->get('MwSt'),
  64.                 $expectedQuantity
  65.             ));
  66.             $fixed true;
  67.         }
  68.         if ($fixed) {
  69.             $this->cartService->recalculate($cart$context);
  70.         }
  71.     }
  72. }