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

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