vendor/shopware/core/Content/Flow/Dispatching/FlowDispatcher.php line 128

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Content\Flow\Dispatching;
  3. use Psr\EventDispatcher\StoppableEventInterface;
  4. use Psr\Log\LoggerInterface;
  5. use Shopware\Core\Content\Flow\Dispatching\Struct\Flow;
  6. use Shopware\Core\Content\Flow\Exception\ExecuteSequenceException;
  7. use Shopware\Core\Framework\Context;
  8. use Shopware\Core\Framework\Event\BusinessEvent;
  9. use Shopware\Core\Framework\Event\FlowEvent;
  10. use Shopware\Core\Framework\Event\FlowEventAware;
  11. use Shopware\Core\Framework\Event\FlowLogEvent;
  12. use Shopware\Core\Framework\Feature;
  13. use Shopware\Core\Framework\Log\Package;
  14. use Symfony\Component\DependencyInjection\ContainerInterface;
  15. use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
  16. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  17. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  18. /**
  19. * @internal not intended for decoration or replacement
  20. */
  21. #[Package('business-ops')]
  22. class FlowDispatcher implements EventDispatcherInterface
  23. {
  24. private EventDispatcherInterface $dispatcher;
  25. private ContainerInterface $container;
  26. private LoggerInterface $logger;
  27. private FlowFactory $flowFactory;
  28. public function __construct(EventDispatcherInterface $dispatcher, LoggerInterface $logger, FlowFactory $flowFactory)
  29. {
  30. $this->dispatcher = $dispatcher;
  31. $this->logger = $logger;
  32. $this->flowFactory = $flowFactory;
  33. }
  34. public function setContainer(ContainerInterface $container): void
  35. {
  36. $this->container = $container;
  37. }
  38. /**
  39. * @template TEvent of object
  40. *
  41. * @param TEvent $event
  42. *
  43. * @return TEvent
  44. */
  45. public function dispatch($event, ?string $eventName = null): object
  46. {
  47. $event = $this->dispatcher->dispatch($event, $eventName);
  48. if (!$event instanceof FlowEventAware) {
  49. return $event;
  50. }
  51. if (Feature::isActive('v6.5.0.0')) {
  52. $flowLogEvent = new FlowLogEvent(FlowLogEvent::NAME, $event);
  53. $this->dispatcher->dispatch($flowLogEvent, $flowLogEvent->getName());
  54. }
  55. if (Feature::isActive('FEATURE_NEXT_17858')) {
  56. if ($event instanceof FlowEvent) {
  57. return $event;
  58. }
  59. } else {
  60. if ($event instanceof BusinessEvent || $event instanceof FlowEvent) {
  61. return $event;
  62. }
  63. }
  64. if ($event instanceof StoppableEventInterface && $event->isPropagationStopped()) {
  65. return $event;
  66. }
  67. if ($event->getContext()->hasState(Context::SKIP_TRIGGER_FLOW)) {
  68. return $event;
  69. }
  70. $storableFlow = $this->flowFactory->create($event);
  71. /** @deprecated tag:v6.5.0 Will be removed */
  72. if (!Feature::isActive('v6.5.0.0')) {
  73. $storableFlow->setOriginalEvent($event);
  74. }
  75. $this->callFlowExecutor($storableFlow);
  76. return $event;
  77. }
  78. /**
  79. * @param string $eventName
  80. * @param callable $listener
  81. * @param int $priority
  82. */
  83. public function addListener($eventName, $listener, $priority = 0): void
  84. {
  85. $this->dispatcher->addListener($eventName, $listener, $priority);
  86. }
  87. public function addSubscriber(EventSubscriberInterface $subscriber): void
  88. {
  89. $this->dispatcher->addSubscriber($subscriber);
  90. }
  91. /**
  92. * @param string $eventName
  93. * @param callable $listener
  94. */
  95. public function removeListener($eventName, $listener): void
  96. {
  97. $this->dispatcher->removeListener($eventName, $listener);
  98. }
  99. public function removeSubscriber(EventSubscriberInterface $subscriber): void
  100. {
  101. $this->dispatcher->removeSubscriber($subscriber);
  102. }
  103. public function getListeners(?string $eventName = null): array
  104. {
  105. return $this->dispatcher->getListeners($eventName);
  106. }
  107. /**
  108. * @param string $eventName
  109. * @param callable $listener
  110. */
  111. public function getListenerPriority($eventName, $listener): ?int
  112. {
  113. return $this->dispatcher->getListenerPriority($eventName, $listener);
  114. }
  115. public function hasListeners(?string $eventName = null): bool
  116. {
  117. return $this->dispatcher->hasListeners($eventName);
  118. }
  119. private function callFlowExecutor(StorableFlow $event): void
  120. {
  121. $flows = $this->getFlows($event->getName());
  122. if (empty($flows)) {
  123. return;
  124. }
  125. /** @var FlowExecutor|null $flowExecutor */
  126. $flowExecutor = $this->container->get(FlowExecutor::class);
  127. if ($flowExecutor === null) {
  128. throw new ServiceNotFoundException(FlowExecutor::class);
  129. }
  130. foreach ($flows as $flow) {
  131. try {
  132. /** @var Flow $payload */
  133. $payload = $flow['payload'];
  134. $flowExecutor->execute($payload, $event);
  135. } catch (ExecuteSequenceException $e) {
  136. $this->logger->error(
  137. "Could not execute flow with error message:\n"
  138. . 'Flow name: ' . $flow['name'] . "\n"
  139. . 'Flow id: ' . $flow['id'] . "\n"
  140. . 'Sequence id: ' . $e->getSequenceId() . "\n"
  141. . $e->getMessage() . "\n"
  142. . 'Error Code: ' . $e->getCode() . "\n"
  143. );
  144. } catch (\Throwable $e) {
  145. $this->logger->error(
  146. "Could not execute flow with error message:\n"
  147. . 'Flow name: ' . $flow['name'] . "\n"
  148. . 'Flow id: ' . $flow['id'] . "\n"
  149. . $e->getMessage() . "\n"
  150. . 'Error Code: ' . $e->getCode() . "\n"
  151. );
  152. }
  153. }
  154. }
  155. /**
  156. * @return array<string, mixed>
  157. */
  158. private function getFlows(string $eventName): array
  159. {
  160. /** @var AbstractFlowLoader|null $flowLoader */
  161. $flowLoader = $this->container->get(FlowLoader::class);
  162. if ($flowLoader === null) {
  163. throw new ServiceNotFoundException(FlowExecutor::class);
  164. }
  165. $flows = $flowLoader->load();
  166. $result = [];
  167. if (\array_key_exists($eventName, $flows)) {
  168. $result = $flows[$eventName];
  169. }
  170. return $result;
  171. }
  172. }