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

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