<?php
namespace NewsletterSendinblue\Subscriber;
use Monolog\Logger;
use NewsletterSendinblue\Service\Cart\CartEventProducer;
use NewsletterSendinblue\Service\ConfigService;
use NewsletterSendinblue\Service\OrderSyncService;
use NewsletterSendinblue\Traits\HelperTrait;
use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionDefinition;
use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionEntity;
use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStates;
use Shopware\Core\Checkout\Order\OrderDefinition;
use Shopware\Core\Checkout\Order\OrderEntity;
use Shopware\Core\Checkout\Order\OrderStates;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\System\StateMachine\Aggregation\StateMachineState\StateMachineStateEntity;
use Shopware\Core\System\StateMachine\Event\StateMachineTransitionEvent;
use Shopware\Core\Checkout\Order\Aggregate\OrderCustomer\OrderCustomerEntity;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class CartOrderSubscriber implements EventSubscriberInterface
{
use HelperTrait;
const ORDER_OPEN = 'open';
/**
* @var ConfigService
*/
private $configService;
/**
* @var CartEventProducer
*/
private $cartEventProducer;
/**
* @var EntityRepositoryInterface
*/
private $systemConfigRepository;
/**
* @var EntityRepositoryInterface
*/
private $orderTransactionRepository;
/**
* @var OrderSyncService
*/
private $orderSyncService;
/**
* @var Logger
*/
private $logger;
/**
* @var EntityRepositoryInterface
*/
private $brevoAbandonedCartRepository;
/**
* @param ConfigService $configService
* @param CartEventProducer $cartEventProducer
* @param EntityRepositoryInterface $systemConfigRepository
* @param EntityRepositoryInterface $orderTransactionRepository
* @param OrderSyncService $orderSyncService
* @param Logger $logger
*/
public function __construct(
ConfigService $configService,
CartEventProducer $cartEventProducer,
EntityRepositoryInterface $systemConfigRepository,
EntityRepositoryInterface $orderTransactionRepository,
OrderSyncService $orderSyncService,
Logger $logger,
EntityRepositoryInterface $brevoAbandonedCartRepository
)
{
$this->configService = $configService;
$this->cartEventProducer = $cartEventProducer;
$this->systemConfigRepository = $systemConfigRepository;
$this->orderTransactionRepository = $orderTransactionRepository;
$this->orderSyncService = $orderSyncService;
$this->logger = $logger;
$this->brevoAbandonedCartRepository = $brevoAbandonedCartRepository;
}
/**
* @return string[]
*/
public static function getSubscribedEvents(): array
{
return [
CheckoutOrderPlacedEvent::class => 'onOrderPlaced',
StateMachineTransitionEvent::class => 'onStateChanged',
];
}
/**
* @param StateMachineTransitionEvent $event
* @return void
*/
public function onStateChanged(StateMachineTransitionEvent $event): void
{
$connectionId = $this->getAutoSyncConnectionId(
ConfigService::CONFIG_IS_ORDERS_AUTO_SYNC_ENABLED,
$event->getContext()
);
if (empty($connectionId)) {
return;
}
$entity = $event->getEntityName();
$toState = $event->getToPlace()->getTechnicalName();
if (
($entity === OrderTransactionDefinition::ENTITY_NAME
&& in_array($toState, OrderSyncService::PAYMENT_SYNC_STATUSES))
) {
$orderId = $this->getOrderId($event);
if (!$orderId) {
return;
}
$order = $this->orderSyncService->getOrder($orderId, $event->getContext());
if (!$order instanceof OrderEntity) {
return;
}
if ($toState === OrderTransactionStates::STATE_CHARGEBACK) {
$toState = OrderTransactionStates::STATE_OPEN;
}
$this->orderSyncService->sync($order, $connectionId, $toState, $event->getContext());
}
}
/**
* @param CheckoutOrderPlacedEvent $event
* @return void
*/
public function onOrderPlaced(CheckoutOrderPlacedEvent $event): void
{
$this->configService->setSalesChannelId($event->getSalesChannelId());
if ($this->configService->isAutoSyncEnabled()) {
$this->cartEventProducer->createTransactionalOrder(
$event->getOrder(), $event->getContext(), $event->getSalesChannelId()
);
}
// ORDER AUTO SYNC
$connectionId = $this->getAutoSyncConnectionId(
ConfigService::CONFIG_IS_ORDERS_AUTO_SYNC_ENABLED,
$event->getContext()
);
if (!empty($connectionId)) {
$order = $event->getOrder();
$toState = self::ORDER_OPEN;
if ($order->getTransactions()->first() instanceof OrderTransactionEntity
&& $order->getTransactions()->first()->getStateMachineState() instanceof StateMachineStateEntity
) {
$toState = $order->getTransactions()->first()->getStateMachineState()->getTechnicalName();
}
$this->orderSyncService->sync($order, $connectionId, $toState, $event->getContext());
}
if ($this->configService->isAbandonedCartTrackingEnabled()) {
if ($event->getOrder()->getOrderCustomer() instanceof OrderCustomerEntity) {
try {
$this->brevoAbandonedCartRepository->delete([
['id' => md5($event->getOrder()->getOrderCustomer()->getEmail())]
], $event->getContext());
} catch (\Throwable $e) {
}
}
}
}
/**
* @param StateMachineTransitionEvent $event
* @return string|null
*/
private function getOrderId(StateMachineTransitionEvent $event): ?string
{
$orderId = null;
switch ($event->getEntityName()) {
case OrderDefinition::ENTITY_NAME:
$orderId = $event->getEntityId();
break;
case OrderTransactionDefinition::ENTITY_NAME:
$transactions = $this->orderTransactionRepository->search(new Criteria([$event->getEntityId()]), $event->getContext());
if (count($transactions) > 0) {
$orderId = $transactions->first()->getOrderId();
}
break;
}
return $orderId;
}
}