vendor/shopware/storefront/Checkout/Cart/SalesChannel/StorefrontCartFacade.php line 98
<?php declare(strict_types=1);
namespace Shopware\Storefront\Checkout\Cart\SalesChannel;
use Shopware\Core\Checkout\Cart\AbstractCartPersister;
use Shopware\Core\Checkout\Cart\Cart;
use Shopware\Core\Checkout\Cart\CartCalculator;
use Shopware\Core\Checkout\Cart\Error\ErrorCollection;
use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
use Shopware\Core\Checkout\Payment\Cart\Error\PaymentMethodBlockedError;
use Shopware\Core\Checkout\Shipping\Cart\Error\ShippingMethodBlockedError;
use Shopware\Core\Framework\Log\Package;
use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
use Shopware\Core\System\SalesChannel\Context\SalesChannelContextService;
use Shopware\Core\System\SalesChannel\SalesChannel\AbstractContextSwitchRoute;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Storefront\Checkout\Cart\Error\PaymentMethodChangedError;
use Shopware\Storefront\Checkout\Cart\Error\ShippingMethodChangedError;
use Shopware\Storefront\Checkout\Payment\BlockedPaymentMethodSwitcher;
use Shopware\Storefront\Checkout\Shipping\BlockedShippingMethodSwitcher;
#[Package('checkout')]
class StorefrontCartFacade
{
/**
* @internal
*/
public function __construct(
private readonly CartService $cartService,
private readonly BlockedShippingMethodSwitcher $blockedShippingMethodSwitcher,
private readonly BlockedPaymentMethodSwitcher $blockedPaymentMethodSwitcher,
private readonly AbstractContextSwitchRoute $contextSwitchRoute,
private readonly CartCalculator $calculator,
private readonly AbstractCartPersister $cartPersister
) {
}
public function get(
string $token,
SalesChannelContext $originalContext,
bool $caching = true,
bool $taxed = false
): Cart {
$originalCart = $this->cartService->getCart($token, $originalContext, $caching, $taxed);
$cartErrors = $originalCart->getErrors();
if (!$this->cartContainsBlockedMethods($cartErrors)) {
return $originalCart;
}
// Switch shipping method if blocked
$contextShippingMethod = $this->blockedShippingMethodSwitcher->switch($cartErrors, $originalContext);
// Switch payment method if blocked
$contextPaymentMethod = $this->blockedPaymentMethodSwitcher->switch($cartErrors, $originalContext);
if ($contextShippingMethod->getId() === $originalContext->getShippingMethod()->getId()
&& $contextPaymentMethod->getId() === $originalContext->getPaymentMethod()->getId()
) {
return $originalCart;
}
$updatedContext = clone $originalContext;
$updatedContext->assign([
'shippingMethod' => $contextShippingMethod,
'paymentMethod' => $contextPaymentMethod,
]);
$newCart = $this->calculator->calculate($originalCart, $updatedContext);
// Recalculated cart successfully unblocked
if (!$this->cartContainsBlockedMethods($newCart->getErrors())) {
$this->cartPersister->save($newCart, $updatedContext);
$this->updateSalesChannelContext($updatedContext);
return $newCart;
}
// Recalculated cart contains one or more blocked shipping/payment method, rollback changes
$this->removeSwitchNotices($cartErrors);
return $originalCart;
}
private function cartContainsBlockedMethods(ErrorCollection $errors): bool
{
foreach ($errors as $error) {
if ($error instanceof ShippingMethodBlockedError || $error instanceof PaymentMethodBlockedError) {
return true;
}
}
return false;
}
private function updateSalesChannelContext(SalesChannelContext $salesChannelContext): void
{
$this->contextSwitchRoute->switchContext(
new RequestDataBag([
SalesChannelContextService::SHIPPING_METHOD_ID => $salesChannelContext->getShippingMethod()->getId(),
SalesChannelContextService::PAYMENT_METHOD_ID => $salesChannelContext->getPaymentMethod()->getId(),
]),
$salesChannelContext
);
}
/**
* Remove all PaymentMethodChangedErrors and ShippingMethodChangedErrors from cart
*/
private function removeSwitchNotices(ErrorCollection $cartErrors): void
{
foreach ($cartErrors as $error) {
if (!$error instanceof ShippingMethodChangedError && !$error instanceof PaymentMethodChangedError) {
continue;
}
if ($error instanceof ShippingMethodChangedError) {
$cartErrors->add(new ShippingMethodBlockedError($error->getOldShippingMethodName()));
}
if ($error instanceof PaymentMethodChangedError) {
$cartErrors->add(new PaymentMethodBlockedError($error->getOldPaymentMethodName()));
}
$cartErrors->remove($error->getId());
}
}
}