<?php
declare(strict_types=1);
namespace Wbfk\Offer\Subscriber;
use Shopware\Core\Checkout\Cart\Event\CartChangedEvent;
use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
use Shopware\Storefront\Page\Checkout\Cart\CheckoutCartPageLoadedEvent;
use Shopware\Storefront\Page\Checkout\Offcanvas\OffcanvasCartPageLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Wbfk\Offer\Core\Checkout\Cart\Custom\CartMode;
use Wbfk\Offer\Storefront\Controller\CartModeChangeRoute;
class CartModeToggle implements EventSubscriberInterface
{
public function __construct(
private readonly RequestStack $requestStack,
private readonly CartModeChangeRoute $cartModeChangeRoute
) {
}
public static function getSubscribedEvents(): array
{
return [
CartChangedEvent::class => 'setCartModeToRedirectParameters',
OffcanvasCartPageLoadedEvent::class => 'toggleCartModeOnOffcanvasCart',
CheckoutCartPageLoadedEvent::class => 'toggleCartModeBasedOnRequestSource',
];
}
/**
* From the product detail page, when a user adds a product to cart, the cart should be in cart mode,
* but if the user adds a product to offer, the cart should be in offer mode.
* Switch to modes based on the request parameter cartMode
*
* @param OffcanvasCartPageLoadedEvent $event
* @return void
*/
public function toggleCartModeOnOffcanvasCart(OffcanvasCartPageLoadedEvent $event): void
{
$requestedCartMode = $this->requestStack->getCurrentRequest()?->get('cartMode', null);
if (!$requestedCartMode) {
return;
}
$cart = $event->getPage()->getCart();
/** @var ?CartMode $cartMode */
$cartMode = $cart->getExtension('cartMode');
$currentCartMode = $cartMode?->getSelectedCartMode();
if ($currentCartMode === $requestedCartMode) {
return;
}
$requestDataBag = new RequestDataBag(['cartMode' => $requestedCartMode]);
$cartResponse = $this->cartModeChangeRoute->change($requestDataBag, $event->getPage()->getCart(), $event->getSalesChannelContext());
$event->getPage()->setCart($cartResponse->getCart());
}
/**
* When a user visits checkout/cart, checkout/confirm cart should be in cart mode
* and visiting checkout/offer cart should be in offer mode
* This method will switch the cart mode based on the request source
*
* @param CheckoutCartPageLoadedEvent $event
* @return void
*/
public function toggleCartModeBasedOnRequestSource(CheckoutCartPageLoadedEvent $event): void
{
$currentRoute = $event->getRequest()->attributes->get('_route');
if (!in_array($currentRoute, ['frontend.checkout.cart.page', 'frontend.checkout.confirm.page', 'frontend.wbfk-offer.checkout.offer.page'])) {
return;
}
$expectedCartMode = $currentRoute === 'frontend.wbfk-offer.checkout.offer.page' ? 'offer' : 'cart';
/** @var ?CartMode $cartMode */
$cartMode = $event->getPage()->getCart()->getExtension('cartMode');
if ($cartMode?->getSelectedCartMode() === $expectedCartMode) {
return;
}
$requestDataBag = new RequestDataBag(['cartMode' => $expectedCartMode]);
$cartResponse = $this->cartModeChangeRoute->change($requestDataBag, $event->getPage()->getCart(), $event->getSalesChannelContext());
$event->getPage()->setCart($cartResponse->getCart());
}
/**
* From PDP add to cart/ add to offer button is handled by js plugin.
* During adding to cart/ add to offer, offcanvas redirect is set by the plugin, and we will have to extend the plugin to set the cart mode.
* To avoid extending the plugin, we pass cartMode as part of add to cart form data.
* Then force the cart mode to be part of redirect parameters.
* Check: custom/plugins/WbfkThemeMMedientechnik/src/Resources/views/storefront/component/buy-widget/buy-widget-form.html.twig
*
* @param CartChangedEvent $event
* @return void
*/
public function setCartModeToRedirectParameters(CartChangedEvent $event): void
{
$currentRequest = $this->requestStack->getCurrentRequest();
if (!$currentRequest || !$currentRequest->get('cartMode')) {
return;
}
$params = $currentRequest->get('redirectParameters');
if (is_string($params)) {
$params = json_decode($params, true);
}
if (empty($params)) {
$params = [];
}
$requestedCartMode = $currentRequest->get('cartMode');
$cart = $event->getCart();
/** @var ?CartMode $cartMode */
$cartMode = $cart->getExtension('cartMode');
if ($cartMode?->getSelectedCartMode() === $requestedCartMode) {
return;
}
$params['cartMode'] = $requestedCartMode;
$currentRequest->attributes->set('redirectParameters', json_encode($params));
}
}