<?php declare(strict_types = 1);
namespace Zeobv\AbandonedCart\Subscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Shopware\Core\Checkout\Cart\Cart;
use Shopware\Core\Checkout\Cart\Event\LineItemAddedEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
use Shopware\Storefront\Page\Checkout\Finish\CheckoutFinishPageLoadedEvent;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Storefront\Page\Checkout\Register\CheckoutRegisterPageLoadedEvent;
use Zeobv\AbandonedCart\Service\AbandonedCartService;
use Zeobv\AbandonedCart\Service\CartService;
class PageSubscriber implements EventSubscriberInterface
{
/**
* @var EntityRepositoryInterface
*/
protected $abandonedCartRepository;
/**
* @var AbandonedCartService
*/
protected $abandonedCartService;
/**
* @var EntityRepositoryInterface
*/
protected $salesChannelDomainRepository;
/**
* @var Request|null
*/
protected $currentRequest;
/**
* @var CartService
*/
protected $cartService;
/**
* PageSubscriber constructor.
*
* @param RequestStack $requestStack
* @param EntityRepositoryInterface $abandonedCartRepository
* @param EntityRepositoryInterface $salesChannelDomainRepository
* @param AbandonedCartService $abandonedCartService
* @param CartService $cartService
*/
public function __construct(
RequestStack $requestStack,
EntityRepositoryInterface $abandonedCartRepository,
EntityRepositoryInterface $salesChannelDomainRepository,
AbandonedCartService $abandonedCartService,
CartService $cartService
)
{
$this->currentRequest = $requestStack->getCurrentRequest();
$this->abandonedCartRepository = $abandonedCartRepository;
$this->abandonedCartService = $abandonedCartService;
$this->cartService = $cartService;
$this->salesChannelDomainRepository = $salesChannelDomainRepository;
}
/**
* @return array
*/
public static function getSubscribedEvents(): array
{
return [
LineItemAddedEvent::class => 'onLineItemAdded',
CheckoutRegisterPageLoadedEvent::class => 'onCheckoutRegisterPageLoaded',
CheckoutConfirmPageLoadedEvent::class => 'onCheckoutConfirmPageLoaded',
CheckoutFinishPageLoadedEvent::class => 'onCheckoutFinishPageLoaded',
];
}
/**
* @param LineItemAddedEvent $event
*/
public function onLineItemAdded(LineItemAddedEvent $event)
{
$cart = $event->getCart();
$salesChannelContext = $event->getContext();
if ($this->currentRequest->attributes->get('sw-domain-id')) {
$this->upsertAbandonedCart($cart, $salesChannelContext);
}
}
/**
* @param CheckoutConfirmPageLoadedEvent $event
*/
public function onCheckoutConfirmPageLoaded(CheckoutConfirmPageLoadedEvent $event)
{
$cart = $event->getPage()->getCart();
$this->abandonedCartService->saveCart($cart, $event->getSalesChannelContext());
$this->upsertAbandonedCart($cart, $event->getSalesChannelContext());
}
/**
* @param CheckoutRegisterPageLoadedEvent $event
*/
public function onCheckoutRegisterPageLoaded(CheckoutRegisterPageLoadedEvent $event)
{
$cart = $event->getPage()->getCart();
$this->abandonedCartService->saveCart($cart, $event->getSalesChannelContext());
$this->upsertAbandonedCart($cart, $event->getSalesChannelContext());
}
public function onCheckoutFinishPageLoaded(CheckoutFinishPageLoadedEvent $event)
{
$cartToken = $event->getSalesChannelContext()->getToken();
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('cartToken', $cartToken));
$abandonedCart = $this->abandonedCartRepository->search($criteria, $event->getContext())->first();
if (is_null($abandonedCart)) {
return;
}
$this->abandonedCartService->resolveAbandonedCart($abandonedCart, $event->getContext());
}
protected function upsertAbandonedCart(Cart $cart, SalesChannelContext $context)
{
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('cartToken', $cart->getToken()));
$cartResult = $this->abandonedCartRepository->search($criteria, $context->getContext());
$data = [
'id' => $cartResult->first() ? $cartResult->first()->getId() : Uuid::randomHex(),
'cartToken' => $cart->getToken(),
'lineItems' => $cart->getLineItems()->getElements(),
'currencyId' => $context->getCurrency()->getId(),
'paymentMethodId' => $context->getPaymentMethod()->getId(),
'shippingMethodId' => $context->getShippingMethod()->getId(),
'countryId' => $context->getShippingLocation()->getCountry()->getId(),
'salesChannelId' => $context->getSalesChannel()->getId(),
'salesChannelDomainId' => $this->currentRequest->attributes->get('sw-domain-id')
];
if ( $customer = $context->getCustomer() ) {
$data['customerId'] = $customer->getId();
$data['email'] = $customer->getEmail();
$this->abandonedCartRepository->upsert([$data], $context->getContext());
}
}
}