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

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