vendor/shopware/core/Checkout/Order/Listener/OrderStateChangeEventListener.php line 94

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Checkout\Order\Listener;
  3. use Shopware\Core\Checkout\Cart\Exception\OrderDeliveryNotFoundException;
  4. use Shopware\Core\Checkout\Cart\Exception\OrderNotFoundException;
  5. use Shopware\Core\Checkout\Cart\Exception\OrderTransactionNotFoundException;
  6. use Shopware\Core\Checkout\Cart\Order\OrderConverter;
  7. use Shopware\Core\Checkout\Order\Aggregate\OrderDelivery\OrderDeliveryEntity;
  8. use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionEntity;
  9. use Shopware\Core\Checkout\Order\Event\OrderStateChangeCriteriaEvent;
  10. use Shopware\Core\Checkout\Order\Event\OrderStateMachineStateChangeEvent;
  11. use Shopware\Core\Checkout\Order\OrderEntity;
  12. use Shopware\Core\Checkout\Payment\PaymentMethodEntity;
  13. use Shopware\Core\Framework\Context;
  14. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  15. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  16. use Shopware\Core\Framework\Event\BusinessEventCollector;
  17. use Shopware\Core\Framework\Event\BusinessEventCollectorEvent;
  18. use Shopware\Core\System\StateMachine\Aggregation\StateMachineState\StateMachineStateEntity;
  19. use Shopware\Core\System\StateMachine\Event\StateMachineStateChangeEvent;
  20. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  21. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  22. class OrderStateChangeEventListener implements EventSubscriberInterface
  23. {
  24.     /**
  25.      * @var EntityRepositoryInterface
  26.      */
  27.     private $stateRepository;
  28.     /**
  29.      * @var EntityRepositoryInterface
  30.      */
  31.     private $orderRepository;
  32.     /**
  33.      * @var EntityRepositoryInterface
  34.      */
  35.     private $transactionRepository;
  36.     /**
  37.      * @var EntityRepositoryInterface
  38.      */
  39.     private $deliveryRepository;
  40.     /**
  41.      * @var EventDispatcherInterface
  42.      */
  43.     private $eventDispatcher;
  44.     /**
  45.      * @var OrderConverter
  46.      */
  47.     private $orderConverter;
  48.     /**
  49.      * @var BusinessEventCollector
  50.      */
  51.     private $businessEventCollector;
  52.     public function __construct(
  53.         EntityRepositoryInterface $orderRepository,
  54.         EntityRepositoryInterface $transactionRepository,
  55.         EntityRepositoryInterface $deliveryRepository,
  56.         EventDispatcherInterface $eventDispatcher,
  57.         OrderConverter $orderConverter,
  58.         BusinessEventCollector $businessEventCollector,
  59.         EntityRepositoryInterface $stateRepository
  60.     ) {
  61.         $this->orderRepository $orderRepository;
  62.         $this->transactionRepository $transactionRepository;
  63.         $this->deliveryRepository $deliveryRepository;
  64.         $this->eventDispatcher $eventDispatcher;
  65.         $this->orderConverter $orderConverter;
  66.         $this->stateRepository $stateRepository;
  67.         $this->businessEventCollector $businessEventCollector;
  68.     }
  69.     public static function getSubscribedEvents()
  70.     {
  71.         return [
  72.             'state_machine.order.state_changed' => 'onOrderStateChange',
  73.             'state_machine.order_delivery.state_changed' => 'onOrderDeliveryStateChange',
  74.             'state_machine.order_transaction.state_changed' => 'onOrderTransactionStateChange',
  75.             BusinessEventCollectorEvent::NAME => 'onAddStateEvents',
  76.         ];
  77.     }
  78.     /**
  79.      * @throws OrderDeliveryNotFoundException
  80.      * @throws OrderNotFoundException
  81.      */
  82.     public function onOrderDeliveryStateChange(StateMachineStateChangeEvent $event): void
  83.     {
  84.         $orderDeliveryId $event->getTransition()->getEntityId();
  85.         $context $event->getContext();
  86.         /** @var OrderDeliveryEntity|null $orderDelivery */
  87.         $orderDelivery $this->deliveryRepository
  88.             ->search(new Criteria([$orderDeliveryId]), $context)
  89.             ->first();
  90.         if ($orderDelivery === null) {
  91.             throw new OrderDeliveryNotFoundException($orderDeliveryId);
  92.         }
  93.         $order $this->getOrder($orderDelivery->getOrderId(), $event->getContext());
  94.         $context $this->getContext($order$event->getContext());
  95.         $this->dispatchEvent($event->getStateEventName(), $order$context);
  96.     }
  97.     /**
  98.      * @throws OrderNotFoundException
  99.      * @throws OrderTransactionNotFoundException
  100.      */
  101.     public function onOrderTransactionStateChange(StateMachineStateChangeEvent $event): void
  102.     {
  103.         $orderTransactionId $event->getTransition()->getEntityId();
  104.         $criteria = new Criteria([$orderTransactionId]);
  105.         $criteria->addAssociation('paymentMethod');
  106.         $orderTransaction $this->transactionRepository
  107.             ->search($criteria$event->getContext())
  108.             ->first();
  109.         if (!$orderTransaction instanceof OrderTransactionEntity) {
  110.             throw new OrderTransactionNotFoundException($orderTransactionId);
  111.         }
  112.         if (!$orderTransaction->getPaymentMethod() instanceof PaymentMethodEntity) {
  113.             throw new OrderTransactionNotFoundException($orderTransactionId);
  114.         }
  115.         $order $this->getOrder($orderTransaction->getOrderId(), $event->getContext());
  116.         $context $this->getContext($order$event->getContext());
  117.         $this->dispatchEvent($event->getStateEventName(), $order$context);
  118.     }
  119.     /**
  120.      * @throws OrderNotFoundException
  121.      */
  122.     public function onOrderStateChange(StateMachineStateChangeEvent $event): void
  123.     {
  124.         $orderId $event->getTransition()->getEntityId();
  125.         $order $this->getOrder($orderId$event->getContext());
  126.         $context $this->getContext($order$event->getContext());
  127.         $this->dispatchEvent($event->getStateEventName(), $order$context);
  128.     }
  129.     public function onAddStateEvents(BusinessEventCollectorEvent $event): void
  130.     {
  131.         $context $event->getContext();
  132.         $collection $event->getCollection();
  133.         $criteria = new Criteria();
  134.         $criteria->addAssociation('stateMachine');
  135.         $states $this->stateRepository->search($criteria$context);
  136.         $sides = [
  137.             StateMachineStateChangeEvent::STATE_MACHINE_TRANSITION_SIDE_ENTER,
  138.             StateMachineStateChangeEvent::STATE_MACHINE_TRANSITION_SIDE_LEAVE,
  139.         ];
  140.         /** @var StateMachineStateEntity $state */
  141.         foreach ($states as $state) {
  142.             foreach ($sides as $side) {
  143.                 $machine $state->getStateMachine();
  144.                 if (!$machine) {
  145.                     continue;
  146.                 }
  147.                 $name implode('.', [
  148.                     $side,
  149.                     $machine->getTechnicalName(),
  150.                     $state->getTechnicalName(),
  151.                 ]);
  152.                 $definition $this->businessEventCollector->define(OrderStateMachineStateChangeEvent::class, $name);
  153.                 if (!$definition) {
  154.                     continue;
  155.                 }
  156.                 $collection->set($name$definition);
  157.             }
  158.         }
  159.     }
  160.     /**
  161.      * @throws OrderNotFoundException
  162.      */
  163.     private function dispatchEvent(string $stateEventNameOrderEntity $orderContext $context): void
  164.     {
  165.         $this->eventDispatcher->dispatch(
  166.             new OrderStateMachineStateChangeEvent($stateEventName$order$order->getSalesChannelId(), $context),
  167.             $stateEventName
  168.         );
  169.     }
  170.     private function getContext(OrderEntity $orderContext $context): Context
  171.     {
  172.         $context = clone $context;
  173.         $salesChannelContext $this->orderConverter->assembleSalesChannelContext($order$context);
  174.         if ($order->getRuleIds() !== null) {
  175.             $salesChannelContext->setRuleIds($order->getRuleIds());
  176.         }
  177.         return $salesChannelContext->getContext();
  178.     }
  179.     /**
  180.      * @throws OrderNotFoundException
  181.      */
  182.     private function getOrder(string $orderIdContext $context): OrderEntity
  183.     {
  184.         $orderCriteria $this->getOrderCriteria($orderId);
  185.         $order $this->orderRepository
  186.             ->search($orderCriteria$context)
  187.             ->first();
  188.         if (!$order instanceof OrderEntity) {
  189.             throw new OrderNotFoundException($orderId);
  190.         }
  191.         return $order;
  192.     }
  193.     private function getOrderCriteria(string $orderId): Criteria
  194.     {
  195.         $criteria = new Criteria([$orderId]);
  196.         $criteria->addAssociation('orderCustomer.salutation');
  197.         $criteria->addAssociation('orderCustomer.customer');
  198.         $criteria->addAssociation('stateMachineState');
  199.         $criteria->addAssociation('deliveries.shippingMethod');
  200.         $criteria->addAssociation('deliveries.shippingOrderAddress.country');
  201.         $criteria->addAssociation('salesChannel');
  202.         $criteria->addAssociation('transactions.paymentMethod');
  203.         $criteria->addAssociation('lineItems');
  204.         $criteria->addAssociation('currency');
  205.         $criteria->addAssociation('addresses.country');
  206.         $event = new OrderStateChangeCriteriaEvent($orderId$criteria);
  207.         $this->eventDispatcher->dispatch($event);
  208.         return $criteria;
  209.     }
  210. }