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

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