<?php declare(strict_types=1);
namespace Zeobv\CartRecovery\Core\Subscriber;
use Shopware\Core\System\SalesChannel\Context\AbstractSalesChannelContextFactory;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
use Shopware\Core\Checkout\Cart\Order\OrderConverter;
use Shopware\Core\Checkout\Cart\CartPersisterInterface;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Core\Checkout\Order\Aggregate\OrderDelivery\OrderDeliveryCollection;
use Shopware\Core\System\SalesChannel\Context\SalesChannelContextService;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Checkout\Order\OrderEntity;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
use Shopware\Core\Checkout\Order\Aggregate\OrderDeliveryPosition\OrderDeliveryPositionCollection;
/**
* Class CartConvertedSubscriber
*
* @package Zeobv\CartRecovery\Core\Subscriber
*/
class CartConvertedSubscriber implements EventSubscriberInterface
{
/**
* @var OrderConverter
*/
protected $orderConverter;
/**
* @var CartPersisterInterface
*/
protected $cartPersister;
/**
* @var AbstractSalesChannelContextFactory
*/
protected $salesChannelContextFactory;
/**
* @var EntityRepositoryInterface
*/
protected $orderDeliveryRepository;
/**
* @var EntityRepositoryInterface
*/
protected $orderDeliveryPositionsRepository;
public function __construct(
OrderConverter $orderConverter,
CartPersisterInterface $cartPersister,
AbstractSalesChannelContextFactory $salesChannelContextFactory,
EntityRepositoryInterface $orderDeliveryRepository,
EntityRepositoryInterface $orderDeliveryPositionsRepository
)
{
$this->orderConverter = $orderConverter;
$this->cartPersister = $cartPersister;
$this->salesChannelContextFactory = $salesChannelContextFactory;
$this->orderDeliveryRepository = $orderDeliveryRepository;
$this->orderDeliveryPositionsRepository = $orderDeliveryPositionsRepository;
}
/**
* @return array|string[]
*/
public static function getSubscribedEvents()
{
return [
CheckoutOrderPlacedEvent::class => 'onCheckoutOrderPlaced'
];
}
public function onCheckoutOrderPlaced(CheckoutOrderPlacedEvent $event)
{
$order = $event->getOrder();
if ($order->getDeliveries()->count() < 1) {
$deliveries = $this->getOrderDeliveries($order, $event->getContext());
} else {
$deliveries = $this->setDeliveryPositionsForOrderDeliveries($order->getDeliveries(), $event->getContext());
}
$order->setDeliveries($deliveries);
$cart = $this->orderConverter->convertToCart($order, $event->getContext());
$salesChannelContext = $this->salesChannelContextFactory->create(Uuid::randomHex(), $event->getSalesChannelId(), [
SalesChannelContextService::CUSTOMER_ID => $order->getOrderCustomer()->getCustomerId()
]);
$cart->setToken($order->getId());
$cart->setName('cart_waiting_for_recovery');
$this->cartPersister->save($cart, $salesChannelContext);
}
/**
* @param OrderEntity $order
* @param Context $context
*
* @return OrderDeliveryCollection
*/
private function getOrderDeliveries(OrderEntity $order, Context $context): OrderDeliveryCollection
{
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('orderId', $order->getId()));
$criteria->addAssociations([
'positions.orderLineItem',
'shippingOrderAddress.country',
'shippingMethod',
'state',
]);
/** @var OrderDeliveryCollection $deliveries */
$deliveries = $this->orderDeliveryRepository->search($criteria, $context)->getEntities();
return $deliveries;
}
private function setDeliveryPositionsForOrderDeliveries(OrderDeliveryCollection $deliveries, Context $context)
{
if ($deliveries->count() < 1) {
return $deliveries;
}
$criteria = new Criteria();
$criteria->addFilter(new EqualsAnyFilter('orderDeliveryId', $deliveries->getIds()));
$criteria->addAssociations(['orderLineItem']);
$positions = $this->orderDeliveryPositionsRepository->search($criteria, $context)->getEntities();
foreach ($deliveries as $delivery) {
/** @var OrderDeliveryPositionCollection $positionsForDelivery */
$positionsForDelivery = $positions->filterByProperty('orderDeliveryId', $delivery->getId());
$delivery->setPositions($positionsForDelivery);
}
return $deliveries;
}
}