custom/plugins/NetiNextExportOnEvent/src/Services/Flow/AbstractFlowAction.php line 57

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace NetInventors\NetiNextExportOnEvent\Services\Flow;
  4. use NetInventors\NetiNextExportOnEvent\Exception\ExceptionCollection;
  5. use NetInventors\NetiNextExportOnEvent\Services\Event\ExportOnEventAware;
  6. use NetInventors\NetiNextExportOnEvent\Services\Builder\AdditionalDataBuilder;
  7. use NetInventors\NetiNextExportOnEvent\Struct\EventDataBag;
  8. use NetInventors\NetiNextExportOnEvent\Utility\IterateUtility;
  9. use Psr\Log\LoggerInterface;
  10. use Shopware\Core\Content\Flow\Dispatching\Action\FlowAction;
  11. use Shopware\Core\Framework\Event\FlowEvent;
  12. use Shopware\Core\Framework\Event\FlowEventAware;
  13. use Shopware\Core\Framework\Event\SalesChannelAware;
  14. use Shopware\Core\Framework\Struct\Collection;
  15. use Throwable;
  16. abstract class AbstractFlowAction extends FlowAction
  17. {
  18.     protected LoggerInterface       $logger;
  19.     protected AdditionalDataBuilder $additionalDataBuilder;
  20.     public function getLogger(): LoggerInterface
  21.     {
  22.         return $this->logger;
  23.     }
  24.     public function setLogger(LoggerInterface $logger): void
  25.     {
  26.         $this->logger $logger;
  27.     }
  28.     public function setAdditionalDataBuilder(
  29.         AdditionalDataBuilder $additionalDataBuilder
  30.     ): void {
  31.         $this->additionalDataBuilder $additionalDataBuilder;
  32.     }
  33.     public static function getSubscribedEvents(): array
  34.     {
  35.         return [
  36.             static::getName() => 'handle',
  37.         ];
  38.     }
  39.     /**
  40.      * @psalm-suppress MixedReturnTypeCoercion
  41.      */
  42.     public function requirements(): array
  43.     {
  44.         return [ ExportOnEventAware::class ];
  45.     }
  46.     public function handle(
  47.         FlowEvent $event
  48.     ): void {
  49.         $config     $event->getConfig();
  50.         $sequenceId $event->getFlowState()->getSequenceId();
  51.         if (
  52.             !$this->validateConfigData(
  53.                 $config,
  54.                 [
  55.                     'sequenceId' => $sequenceId,
  56.                 ]
  57.             )
  58.         ) {
  59.             return;
  60.         }
  61.         $exceptionCollection = new ExceptionCollection();
  62.         /**
  63.          * @var EventDataBag $eventData
  64.          */
  65.         foreach ($this->createEventData($event) as $eventData) {
  66.             try {
  67.                 $this->executeEvent(
  68.                     $eventData,
  69.                     $event,
  70.                     $config,
  71.                     $sequenceId
  72.                 );
  73.             } catch (Throwable $exception) {
  74.                 $exceptionCollection->add($exception);
  75.             }
  76.         }
  77.         if (=== $exceptionCollection->count()) {
  78.             return;
  79.         }
  80.         throw $exceptionCollection;
  81.     }
  82.     /**
  83.      * @return array<string, mixed>
  84.      */
  85.     protected function getAvailableData(FlowEventAware $event): array
  86.     {
  87.         $data = [];
  88.         foreach (\array_keys($event::getAvailableData()->toArray()) as $key) {
  89.             $getter 'get' \ucfirst((string) $key);
  90.             if (!\method_exists($event$getter)) {
  91.                 continue;
  92.             }
  93.             /**
  94.              * @psalm-suppress MixedAssignment
  95.              */
  96.             $data[$key] = $event->$getter();
  97.         }
  98.         /**
  99.          * @var array<string, mixed> $data
  100.          */
  101.         return $data;
  102.     }
  103.     abstract protected function executeEvent(
  104.         EventDataBag $eventData,
  105.         FlowEvent    $event,
  106.         array        $config,
  107.         string       $sequenceId
  108.     ): void;
  109.     protected function createEventData(
  110.         FlowEvent $event
  111.     ): iterable {
  112.         $config        $event->getConfig();
  113.         $sequenceId    $event->getFlowState()->getSequenceId();
  114.         $stateEvent    $event->getEvent();
  115.         $availableData $this->additionalDataBuilder->buildAdditionalData(
  116.             $stateEvent->getName(),
  117.             $this->getAvailableData($stateEvent),
  118.             $stateEvent->getContext()
  119.         );
  120.         /**
  121.          * @var string|null $iterationPath
  122.          */
  123.         $iterationPath $config['iterationPath'] ?? null;
  124.         if (null !== $iterationPath) {
  125.             /**
  126.              * @var array $data
  127.              */
  128.             foreach ($this->getIterateableData($availableData$iterationPath) as $data) {
  129.                 yield $this->buildEventDataBag(
  130.                     $data,
  131.                     $config,
  132.                     $stateEvent,
  133.                     $sequenceId,
  134.                     $event
  135.                 );
  136.             }
  137.             return;
  138.         }
  139.         yield $this->buildEventDataBag(
  140.             $availableData,
  141.             $config,
  142.             $stateEvent,
  143.             $sequenceId,
  144.             $event
  145.         );
  146.     }
  147.     protected function validateConfigData(array $config, array $logContext = []): bool
  148.     {
  149.         if (!\array_key_exists('exportProfileId'$config)) {
  150.             $this->logger->error(
  151.                 "exportProfileId does not exist in config data:\n"
  152.                 \json_encode($configJSON_THROW_ON_ERROR) . "\n",
  153.                 $logContext
  154.             );
  155.             return false;
  156.         }
  157.         if (!\array_key_exists('filename'$config)) {
  158.             $this->logger->error(
  159.                 "filename does not exist in config data:\n"
  160.                 \json_encode($configJSON_THROW_ON_ERROR) . "\n",
  161.                 $logContext
  162.             );
  163.             return false;
  164.         }
  165.         return true;
  166.     }
  167.     /**
  168.      * @return array[]|iterable
  169.      */
  170.     protected function getIterateableData(
  171.         array  $data,
  172.         string $iterationPath
  173.     ): iterable {
  174.         $iterationKeys  \explode('.'$iterationPath);
  175.         $valueToIterate IterateUtility::getNestedValue($data$iterationKeys);
  176.         if (!\is_iterable($valueToIterate)) {
  177.             return;
  178.         }
  179.         if (!$valueToIterate instanceof Collection) {
  180.             return;
  181.         }
  182.         $classname \get_class($valueToIterate);
  183.         $i         0;
  184.         /**
  185.          * @var mixed $item
  186.          */
  187.         foreach ($valueToIterate->getElements() as $item) {
  188.             $data['iterationIndex'] = ++$i;
  189.             IterateUtility::setNestedValue(
  190.                 $data,
  191.                 $iterationKeys,
  192.                 new $classname([ $item ])
  193.             );
  194.             yield $data;
  195.         }
  196.     }
  197.     protected function buildEventDataBag(
  198.         array          $availableData,
  199.         array          $config,
  200.         FlowEventAware $stateEvent,
  201.         string         $sequenceId,
  202.         FlowEvent      $event
  203.     ): EventDataBag {
  204.         $eventData = new EventDataBag($availableData);
  205.         $eventData->assign($config);
  206.         $salesChannelId null;
  207.         if ($stateEvent instanceof SalesChannelAware) {
  208.             $salesChannelId $stateEvent->getSalesChannelId();
  209.         }
  210.         $eventData->assign(
  211.             [
  212.                 'sequenceId'     => $sequenceId,
  213.                 'context'        => $event->getContext(),
  214.                 'salesChannelId' => $salesChannelId,
  215.             ]
  216.         );
  217.         return $eventData;
  218.     }
  219. }