vendor/shopware/storefront/Checkout/Cart/SalesChannel/StorefrontCartFacade.php line 54

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Storefront\Checkout\Cart\SalesChannel;
  3. use Shopware\Core\Checkout\Cart\Cart;
  4. use Shopware\Core\Checkout\Cart\CartCalculator;
  5. use Shopware\Core\Checkout\Cart\CartPersisterInterface;
  6. use Shopware\Core\Checkout\Cart\Error\ErrorCollection;
  7. use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
  8. use Shopware\Core\Checkout\Payment\Cart\Error\PaymentMethodBlockedError;
  9. use Shopware\Core\Checkout\Shipping\Cart\Error\ShippingMethodBlockedError;
  10. use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
  11. use Shopware\Core\System\SalesChannel\Context\SalesChannelContextService;
  12. use Shopware\Core\System\SalesChannel\SalesChannel\AbstractContextSwitchRoute;
  13. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  14. use Shopware\Storefront\Checkout\Cart\Error\PaymentMethodChangedError;
  15. use Shopware\Storefront\Checkout\Cart\Error\ShippingMethodChangedError;
  16. use Shopware\Storefront\Checkout\Payment\BlockedPaymentMethodSwitcher;
  17. use Shopware\Storefront\Checkout\Shipping\BlockedShippingMethodSwitcher;
  18. class StorefrontCartFacade
  19. {
  20.     private CartService $cartService;
  21.     private BlockedShippingMethodSwitcher $blockedShippingMethodSwitcher;
  22.     private BlockedPaymentMethodSwitcher $blockedPaymentMethodSwitcher;
  23.     private AbstractContextSwitchRoute $contextSwitchRoute;
  24.     private CartCalculator $calculator;
  25.     private CartPersisterInterface $cartPersister;
  26.     /**
  27.      * @internal
  28.      */
  29.     public function __construct(
  30.         CartService $cartService,
  31.         BlockedShippingMethodSwitcher $blockedShippingMethodSwitcher,
  32.         BlockedPaymentMethodSwitcher $blockedPaymentMethodSwitcher,
  33.         AbstractContextSwitchRoute $contextSwitchRoute,
  34.         CartCalculator $calculator,
  35.         CartPersisterInterface $cartPersister
  36.     ) {
  37.         $this->cartService $cartService;
  38.         $this->blockedShippingMethodSwitcher $blockedShippingMethodSwitcher;
  39.         $this->blockedPaymentMethodSwitcher $blockedPaymentMethodSwitcher;
  40.         $this->contextSwitchRoute $contextSwitchRoute;
  41.         $this->calculator $calculator;
  42.         $this->cartPersister $cartPersister;
  43.     }
  44.     public function get(
  45.         string $token,
  46.         SalesChannelContext $originalContext
  47.     ): Cart {
  48.         $originalCart $this->cartService->getCart($token$originalContext);
  49.         $cartErrors $originalCart->getErrors();
  50.         if (!$this->cartContainsBlockedMethods($cartErrors)) {
  51.             return $originalCart;
  52.         }
  53.         // Switch shipping method if blocked
  54.         $contextShippingMethod $this->blockedShippingMethodSwitcher->switch($cartErrors$originalContext);
  55.         // Switch payment method if blocked
  56.         $contextPaymentMethod $this->blockedPaymentMethodSwitcher->switch($cartErrors$originalContext);
  57.         if ($contextShippingMethod->getId() === $originalContext->getShippingMethod()->getId()
  58.             && $contextPaymentMethod->getId() === $originalContext->getPaymentMethod()->getId()
  59.         ) {
  60.             return $originalCart;
  61.         }
  62.         $updatedContext = clone $originalContext;
  63.         $updatedContext->assign([
  64.             'shippingMethod' => $contextShippingMethod,
  65.             'paymentMethod' => $contextPaymentMethod,
  66.         ]);
  67.         $newCart $this->calculator->calculate($originalCart$updatedContext);
  68.         // Recalculated cart successfully unblocked
  69.         if (!$this->cartContainsBlockedMethods($newCart->getErrors())) {
  70.             $this->cartPersister->save($newCart$updatedContext);
  71.             $this->updateSalesChannelContext($updatedContext);
  72.             return $newCart;
  73.         }
  74.         // Recalculated cart contains one or more blocked shipping/payment method, rollback changes
  75.         $this->removeSwitchNotices($cartErrors);
  76.         return $originalCart;
  77.     }
  78.     private function cartContainsBlockedMethods(ErrorCollection $errors): bool
  79.     {
  80.         foreach ($errors as $error) {
  81.             if ($error instanceof ShippingMethodBlockedError || $error instanceof PaymentMethodBlockedError) {
  82.                 return true;
  83.             }
  84.         }
  85.         return false;
  86.     }
  87.     private function updateSalesChannelContext(SalesChannelContext $salesChannelContext): void
  88.     {
  89.         $this->contextSwitchRoute->switchContext(
  90.             new RequestDataBag([
  91.                 SalesChannelContextService::SHIPPING_METHOD_ID => $salesChannelContext->getShippingMethod()->getId(),
  92.                 SalesChannelContextService::PAYMENT_METHOD_ID => $salesChannelContext->getPaymentMethod()->getId(),
  93.             ]),
  94.             $salesChannelContext
  95.         );
  96.     }
  97.     /**
  98.      * Remove all PaymentMethodChangedErrors and ShippingMethodChangedErrors from cart
  99.      */
  100.     private function removeSwitchNotices(ErrorCollection $cartErrors): void
  101.     {
  102.         foreach ($cartErrors as $error) {
  103.             if (!$error instanceof ShippingMethodChangedError && !$error instanceof PaymentMethodChangedError) {
  104.                 continue;
  105.             }
  106.             $cartErrors->remove($error->getId());
  107.         }
  108.     }
  109. }