vendor/shopware/core/Content/Flow/Dispatching/Action/SetOrderStateAction.php line 87

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Content\Flow\Dispatching\Action;
  3. use Doctrine\DBAL\Connection;
  4. use Psr\Log\LoggerInterface;
  5. use Shopware\Core\Checkout\Order\SalesChannel\OrderService;
  6. use Shopware\Core\Content\Flow\Dispatching\DelayableAction;
  7. use Shopware\Core\Content\Flow\Dispatching\StorableFlow;
  8. use Shopware\Core\Defaults;
  9. use Shopware\Core\Framework\Context;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Dbal\EntityDefinitionQueryHelper;
  11. use Shopware\Core\Framework\Event\FlowEvent;
  12. use Shopware\Core\Framework\Event\OrderAware;
  13. use Shopware\Core\Framework\Feature;
  14. use Shopware\Core\Framework\ShopwareHttpException;
  15. use Shopware\Core\Framework\Uuid\Uuid;
  16. use Shopware\Core\System\StateMachine\Exception\IllegalTransitionException;
  17. use Shopware\Core\System\StateMachine\Exception\StateMachineNotFoundException;
  18. use Symfony\Component\HttpFoundation\ParameterBag;
  19. /**
  20.  * @deprecated tag:v6.5.0 - reason:remove-subscriber - FlowActions won't be executed over the event system anymore,
  21.  * therefore the actions won't implement the EventSubscriberInterface anymore.
  22.  */
  23. class SetOrderStateAction extends FlowAction implements DelayableAction
  24. {
  25.     public const FORCE_TRANSITION 'force_transition';
  26.     private const ORDER 'order';
  27.     private const ORDER_DELIVERY 'order_delivery';
  28.     private const ORDER_TRANSACTION 'order_transaction';
  29.     private Connection $connection;
  30.     private LoggerInterface $logger;
  31.     private OrderService $orderService;
  32.     /**
  33.      * @internal
  34.      */
  35.     public function __construct(
  36.         Connection $connection,
  37.         LoggerInterface $logger,
  38.         OrderService $orderService
  39.     ) {
  40.         $this->connection $connection;
  41.         $this->logger $logger;
  42.         $this->orderService $orderService;
  43.     }
  44.     public static function getName(): string
  45.     {
  46.         return 'action.set.order.state';
  47.     }
  48.     /**
  49.      * @deprecated tag:v6.5.0 - reason:remove-subscriber - Will be removed
  50.      *
  51.      * @return array<string, string|array{0: string, 1: int}|list<array{0: string, 1?: int}>>
  52.      */
  53.     public static function getSubscribedEvents()
  54.     {
  55.         if (Feature::isActive('v6.5.0.0')) {
  56.             return [];
  57.         }
  58.         return [
  59.             self::getName() => 'handle',
  60.         ];
  61.     }
  62.     /**
  63.      * @return array<int, string>
  64.      */
  65.     public function requirements(): array
  66.     {
  67.         return [OrderAware::class];
  68.     }
  69.     /**
  70.      * @deprecated tag:v6.5.0 Will be removed, implement handleFlow instead
  71.      */
  72.     public function handle(FlowEvent $event): void
  73.     {
  74.         Feature::triggerDeprecationOrThrow(
  75.             'v6.5.0.0',
  76.             Feature::deprecatedMethodMessage(__CLASS____METHOD__'v6.5.0.0')
  77.         );
  78.         $baseEvent $event->getEvent();
  79.         if (!$baseEvent instanceof OrderAware) {
  80.             return;
  81.         }
  82.         $this->update($baseEvent->getContext(), $event->getConfig(), $baseEvent->getOrderId());
  83.     }
  84.     public function handleFlow(StorableFlow $flow): void
  85.     {
  86.         if (!$flow->hasStore(OrderAware::ORDER_ID)) {
  87.             return;
  88.         }
  89.         $this->update($flow->getContext(), $flow->getConfig(), $flow->getStore(OrderAware::ORDER_ID));
  90.     }
  91.     /**
  92.      * @param array<string, mixed> $config
  93.      */
  94.     private function update(Context $context, array $configstring $orderId): void
  95.     {
  96.         if (empty($config)) {
  97.             return;
  98.         }
  99.         if ($config[self::FORCE_TRANSITION] ?? false) {
  100.             $context->addState(self::FORCE_TRANSITION);
  101.         }
  102.         $this->connection->beginTransaction();
  103.         try {
  104.             $transitions array_filter([
  105.                 self::ORDER => $config[self::ORDER] ?? null,
  106.                 self::ORDER_DELIVERY => $config[self::ORDER_DELIVERY] ?? null,
  107.                 self::ORDER_TRANSACTION => $config[self::ORDER_TRANSACTION] ?? null,
  108.             ]);
  109.             foreach ($transitions as $machine => $toPlace) {
  110.                 $this->transitState((string) $machine$orderId, (string) $toPlace$context);
  111.             }
  112.             $this->connection->commit();
  113.         } catch (ShopwareHttpException $e) {
  114.             $this->connection->rollBack();
  115.             $this->logger->error($e->getMessage());
  116.         } finally {
  117.             $context->removeState(self::FORCE_TRANSITION);
  118.         }
  119.     }
  120.     /**
  121.      * @throws IllegalTransitionException
  122.      * @throws StateMachineNotFoundException
  123.      */
  124.     private function transitState(string $machinestring $orderIdstring $toPlaceContext $context): void
  125.     {
  126.         if (!$toPlace) {
  127.             return;
  128.         }
  129.         $data = new ParameterBag();
  130.         $machineId $machine === self::ORDER $orderId $this->getMachineId($machine$orderId);
  131.         if (!$machineId) {
  132.             throw new StateMachineNotFoundException($machine);
  133.         }
  134.         $actionName $this->getAvailableActionName($machine$machineId$toPlace);
  135.         if (!$actionName) {
  136.             $actionName $toPlace;
  137.         }
  138.         switch ($machine) {
  139.             case self::ORDER:
  140.                 $this->orderService->orderStateTransition($orderId$actionName$data$context);
  141.                 return;
  142.             case self::ORDER_DELIVERY:
  143.                 $this->orderService->orderDeliveryStateTransition($machineId$actionName$data$context);
  144.                 return;
  145.             case self::ORDER_TRANSACTION:
  146.                 $this->orderService->orderTransactionStateTransition($machineId$actionName$data$context);
  147.                 return;
  148.             default:
  149.                 throw new StateMachineNotFoundException($machine);
  150.         }
  151.     }
  152.     private function getMachineId(string $machinestring $orderId): ?string
  153.     {
  154.         return $this->connection->fetchOne(
  155.             'SELECT LOWER(HEX(id)) FROM ' $machine ' WHERE order_id = :id AND version_id = :version ORDER BY created_at DESC',
  156.             [
  157.                 'id' => Uuid::fromHexToBytes($orderId),
  158.                 'version' => Uuid::fromHexToBytes(Defaults::LIVE_VERSION),
  159.             ]
  160.         ) ?: null;
  161.     }
  162.     private function getAvailableActionName(string $machinestring $machineIdstring $toPlace): ?string
  163.     {
  164.         $actionName $this->connection->fetchOne(
  165.             'SELECT action_name FROM state_machine_transition WHERE from_state_id = :fromStateId AND to_state_id = :toPlaceId',
  166.             [
  167.                 'fromStateId' => $this->getFromPlaceId($machine$machineId),
  168.                 'toPlaceId' => $this->getToPlaceId($toPlace$machine),
  169.             ]
  170.         );
  171.         return $actionName ?: null;
  172.     }
  173.     private function getToPlaceId(string $toPlacestring $machine): ?string
  174.     {
  175.         $id $this->connection->fetchOne(
  176.             'SELECT id FROM state_machine_state WHERE technical_name = :toPlace AND state_machine_id = :stateMachineId',
  177.             [
  178.                 'toPlace' => $toPlace,
  179.                 'stateMachineId' => $this->getStateMachineId($machine),
  180.             ]
  181.         );
  182.         return $id ?: null;
  183.     }
  184.     private function getFromPlaceId(string $machinestring $machineId): ?string
  185.     {
  186.         $escaped EntityDefinitionQueryHelper::escape($machine);
  187.         $id $this->connection->fetchOne(
  188.             'SELECT state_id FROM ' $escaped 'WHERE id = :id',
  189.             [
  190.                 'id' => Uuid::fromHexToBytes($machineId),
  191.             ]
  192.         );
  193.         return $id ?: null;
  194.     }
  195.     private function getStateMachineId(string $machine): ?string
  196.     {
  197.         $id $this->connection->fetchOne(
  198.             'SELECT id FROM state_machine WHERE technical_name = :technicalName',
  199.             [
  200.                 'technicalName' => $machine '.state',
  201.             ]
  202.         );
  203.         return $id ?: null;
  204.     }
  205. }