vendor/shopware/core/Content/Flow/Dispatching/FlowExecutor.php line 143

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Content\Flow\Dispatching;
  3. use Shopware\Core\Checkout\Cart\AbstractRuleLoader;
  4. use Shopware\Core\Checkout\Order\OrderEntity;
  5. use Shopware\Core\Content\Flow\Dispatching\Action\FlowAction;
  6. use Shopware\Core\Content\Flow\Dispatching\Struct\ActionSequence;
  7. use Shopware\Core\Content\Flow\Dispatching\Struct\Flow;
  8. use Shopware\Core\Content\Flow\Dispatching\Struct\IfSequence;
  9. use Shopware\Core\Content\Flow\Dispatching\Struct\Sequence;
  10. use Shopware\Core\Content\Flow\Exception\ExecuteSequenceException;
  11. use Shopware\Core\Content\Flow\Rule\FlowRuleScopeBuilder;
  12. use Shopware\Core\Framework\App\Event\AppFlowActionEvent;
  13. use Shopware\Core\Framework\App\FlowAction\AppFlowActionProvider;
  14. use Shopware\Core\Framework\Event\FlowEvent;
  15. use Shopware\Core\Framework\Event\OrderAware;
  16. use Shopware\Core\Framework\Feature;
  17. use Shopware\Core\Framework\Log\Package;
  18. use Shopware\Core\Framework\Rule\Rule;
  19. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  20. /**
  21.  * @internal not intended for decoration or replacement
  22.  */
  23. #[Package('business-ops')]
  24. class FlowExecutor
  25. {
  26.     private EventDispatcherInterface $dispatcher;
  27.     private AppFlowActionProvider $appFlowActionProvider;
  28.     private AbstractRuleLoader $ruleLoader;
  29.     private FlowRuleScopeBuilder $scopeBuilder;
  30.     /**
  31.      * @var array<string, mixed>
  32.      */
  33.     private array $actions;
  34.     /**
  35.      * @param FlowAction[] $actions
  36.      */
  37.     public function __construct(
  38.         EventDispatcherInterface $dispatcher,
  39.         AppFlowActionProvider $appFlowActionProvider,
  40.         AbstractRuleLoader $ruleLoader,
  41.         FlowRuleScopeBuilder $scopeBuilder,
  42.         $actions
  43.     ) {
  44.         $this->dispatcher $dispatcher;
  45.         $this->appFlowActionProvider $appFlowActionProvider;
  46.         $this->ruleLoader $ruleLoader;
  47.         $this->scopeBuilder $scopeBuilder;
  48.         $this->actions $actions instanceof \Traversable iterator_to_array($actions) : $actions;
  49.     }
  50.     public function execute(Flow $flowStorableFlow $event): void
  51.     {
  52.         if (!Feature::isActive('v6.5.0.0')) {
  53.             $state = new FlowState($event->getOriginalEvent());
  54.         } else {
  55.             $state = new FlowState();
  56.         }
  57.         $event->setFlowState($state);
  58.         $state->flowId $flow->getId();
  59.         foreach ($flow->getSequences() as $sequence) {
  60.             $state->sequenceId $sequence->sequenceId;
  61.             $state->delayed false;
  62.             try {
  63.                 $this->executeSequence($sequence$event);
  64.             } catch (\Exception $e) {
  65.                 throw new ExecuteSequenceException($sequence->flowId$sequence->sequenceId$e->getMessage(), $e->getCode(), $e);
  66.             }
  67.             if ($state->stop) {
  68.                 return;
  69.             }
  70.         }
  71.     }
  72.     public function executeSequence(?Sequence $sequenceStorableFlow $event): void
  73.     {
  74.         if ($sequence === null) {
  75.             return;
  76.         }
  77.         $event->getFlowState()->currentSequence $sequence;
  78.         if ($sequence instanceof IfSequence) {
  79.             $this->executeIf($sequence$event);
  80.             return;
  81.         }
  82.         if ($sequence instanceof ActionSequence) {
  83.             $this->executeAction($sequence$event);
  84.         }
  85.     }
  86.     public function executeAction(ActionSequence $sequenceStorableFlow $event): void
  87.     {
  88.         $actionName $sequence->action;
  89.         if (!$actionName) {
  90.             return;
  91.         }
  92.         if ($event->getFlowState()->stop) {
  93.             return;
  94.         }
  95.         $event->setConfig($sequence->config);
  96.         $this->callHandle($sequence$event);
  97.         if ($event->getFlowState()->delayed) {
  98.             return;
  99.         }
  100.         $event->getFlowState()->currentSequence $sequence;
  101.         /** @var ActionSequence $nextAction */
  102.         $nextAction $sequence->nextAction;
  103.         if ($nextAction !== null) {
  104.             $this->executeAction($nextAction$event);
  105.         }
  106.     }
  107.     public function executeIf(IfSequence $sequenceStorableFlow $event): void
  108.     {
  109.         if ($this->sequenceRuleMatches($event$sequence->ruleId)) {
  110.             $this->executeSequence($sequence->trueCase$event);
  111.             return;
  112.         }
  113.         $this->executeSequence($sequence->falseCase$event);
  114.     }
  115.     private function callHandle(ActionSequence $sequenceStorableFlow $event): void
  116.     {
  117.         if ($sequence->appFlowActionId) {
  118.             $this->callApp($sequence$event);
  119.             return;
  120.         }
  121.         if (Feature::isActive('v6.5.0.0')) {
  122.             $action $this->actions[$sequence->action] ?? null;
  123.             if ($action) {
  124.                 $action->handleFlow($event);
  125.             }
  126.             return;
  127.         }
  128.         $globalEvent = new FlowEvent($sequence->action$event->getFlowState(), $sequence->config);
  129.         $event->setFlowEvent($globalEvent);
  130.         $this->dispatcher->dispatch($globalEvent$sequence->action);
  131.     }
  132.     private function callApp(ActionSequence $sequenceStorableFlow $event): void
  133.     {
  134.         if (!$sequence->appFlowActionId) {
  135.             return;
  136.         }
  137.         $eventData $this->appFlowActionProvider->getWebhookPayloadAndHeaders($event$sequence->appFlowActionId);
  138.         $globalEvent = new AppFlowActionEvent(
  139.             $sequence->action,
  140.             $eventData['headers'],
  141.             $eventData['payload'],
  142.         );
  143.         $this->dispatcher->dispatch($globalEvent$sequence->action);
  144.     }
  145.     private function sequenceRuleMatches(StorableFlow $eventstring $ruleId): bool
  146.     {
  147.         if (!Feature::isActive('v6.5.0.0')) {
  148.             $originalEvent $event->getOriginalEvent();
  149.             if (!$originalEvent instanceof OrderAware || !method_exists($originalEvent'getOrder')) {
  150.                 return \in_array($ruleId$event->getContext()->getRuleIds(), true);
  151.             }
  152.             $order $originalEvent->getOrder();
  153.         } else {
  154.             if (!$event->hasData(OrderAware::ORDER)) {
  155.                 return \in_array($ruleId$event->getContext()->getRuleIds(), true);
  156.             }
  157.             $order $event->getData(OrderAware::ORDER);
  158.         }
  159.         if (!$order instanceof OrderEntity) {
  160.             return \in_array($ruleId$event->getContext()->getRuleIds(), true);
  161.         }
  162.         $rule $this->ruleLoader->load($event->getContext())->filterForFlow()->get($ruleId);
  163.         if (!$rule || !$rule->getPayload() instanceof Rule) {
  164.             return \in_array($ruleId$event->getContext()->getRuleIds(), true);
  165.         }
  166.         return $rule->getPayload()->match($this->scopeBuilder->build($order$event->getContext()));
  167.     }
  168. }