diff --git a/mailpoet/lib/Automation/Engine/Control/ActionScheduler.php b/mailpoet/lib/Automation/Engine/Control/ActionScheduler.php index 923029e9a7..455eb84d2a 100644 --- a/mailpoet/lib/Automation/Engine/Control/ActionScheduler.php +++ b/mailpoet/lib/Automation/Engine/Control/ActionScheduler.php @@ -12,4 +12,8 @@ class ActionScheduler { public function schedule(int $timestamp, string $hook, array $args = []): int { return as_schedule_single_action($timestamp, $hook, $args, self::GROUP_ID); } + + public function hasScheduledAction(string $hook, array $args = []): bool { + return as_has_scheduled_action($hook, $args, self::GROUP_ID); + } } diff --git a/mailpoet/lib/Automation/Engine/Control/StepRunner.php b/mailpoet/lib/Automation/Engine/Control/StepRunner.php index 8b0d1c949a..de11a33ec9 100644 --- a/mailpoet/lib/Automation/Engine/Control/StepRunner.php +++ b/mailpoet/lib/Automation/Engine/Control/StepRunner.php @@ -82,6 +82,12 @@ class StepRunner { throw Exceptions::workflowNotFound($workflowRun->getWorkflowId()); } + // complete workflow run + if (!$stepId) { + $this->workflowRunStorage->updateStatus($workflowRunId, WorkflowRun::STATUS_COMPLETE); + return; + } + $step = $workflow->getStep($stepId); if (!$step) { throw Exceptions::workflowStepNotFound($stepId); @@ -94,19 +100,21 @@ class StepRunner { throw new InvalidStateException(); } - // enqueue next step / complete workflow - $nextStepId = $step->getNextStepId(); - if ($nextStepId) { - $this->actionScheduler->enqueue(Hooks::WORKFLOW_STEP, [ - [ - 'workflow_run_id' => $workflowRunId, - 'step_id' => $nextStepId, - ], - ]); - } else { - $this->workflowRunStorage->updateStatus($workflowRunId, WorkflowRun::STATUS_COMPLETE); + $nextStepArgs = [ + [ + 'workflow_run_id' => $workflowRunId, + 'step_id' => $step->getNextStepId(), + ], + ]; + + // next step scheduled by action + if ($this->actionScheduler->hasScheduledAction(Hooks::WORKFLOW_STEP, $nextStepArgs)) { + return; } + // enqueue next step + $this->actionScheduler->enqueue(Hooks::WORKFLOW_STEP, $nextStepArgs); + // TODO: allow long-running steps (that are not done here yet) } } diff --git a/mailpoet/lib/Automation/Engine/Engine.php b/mailpoet/lib/Automation/Engine/Engine.php index d201517e70..e333ce09ba 100644 --- a/mailpoet/lib/Automation/Engine/Engine.php +++ b/mailpoet/lib/Automation/Engine/Engine.php @@ -6,11 +6,15 @@ use MailPoet\Automation\Engine\API\API; use MailPoet\Automation\Engine\Control\StepRunner; use MailPoet\Automation\Engine\Control\TriggerHandler; use MailPoet\Automation\Engine\Storage\WorkflowStorage; +use MailPoet\Automation\Integrations\Core\CoreIntegration; class Engine { /** @var API */ private $api; + /** @var CoreIntegration */ + private $coreIntegration; + /** @var Registry */ private $registry; @@ -28,6 +32,7 @@ class Engine { public function __construct( API $api, + CoreIntegration $coreIntegration, Registry $registry, StepRunner $stepRunner, TriggerHandler $triggerHandler, @@ -35,6 +40,7 @@ class Engine { WorkflowStorage $workflowStorage ) { $this->api = $api; + $this->coreIntegration = $coreIntegration; $this->registry = $registry; $this->stepRunner = $stepRunner; $this->triggerHandler = $triggerHandler; @@ -50,6 +56,7 @@ class Engine { $this->stepRunner->initialize(); $this->triggerHandler->initialize(); + $this->coreIntegration->register($this->registry); $this->wordPress->doAction(Hooks::INITIALIZE, [$this->registry]); $this->registerActiveTriggerHooks(); } diff --git a/mailpoet/lib/Automation/Integrations/Core/Actions/WaitAction.php b/mailpoet/lib/Automation/Integrations/Core/Actions/WaitAction.php new file mode 100644 index 0000000000..136eb72467 --- /dev/null +++ b/mailpoet/lib/Automation/Integrations/Core/Actions/WaitAction.php @@ -0,0 +1,40 @@ +actionScheduler = $actionScheduler; + } + + public function getKey(): string { + return 'core:wait'; + } + + public function getName(): string { + return __('Wait', 'mailpoet'); + } + + public function run(Workflow $workflow, WorkflowRun $workflowRun, Step $step): void { + $this->actionScheduler->schedule(time() + $step->getArgs()['seconds'], Hooks::WORKFLOW_STEP, [ + [ + 'workflow_run_id' => $workflowRun->getId(), + 'step_id' => $step->getNextStepId(), + ], + ]); + + // TODO: call a step complete ($id) hook instead? + } +} diff --git a/mailpoet/lib/Automation/Integrations/Core/CoreIntegration.php b/mailpoet/lib/Automation/Integrations/Core/CoreIntegration.php new file mode 100644 index 0000000000..f70e15ba19 --- /dev/null +++ b/mailpoet/lib/Automation/Integrations/Core/CoreIntegration.php @@ -0,0 +1,22 @@ +waitAction = $waitAction; + } + + public function register(Registry $registry): void { + $registry->addAction($this->waitAction); + } +} diff --git a/mailpoet/lib/DI/ContainerConfigurator.php b/mailpoet/lib/DI/ContainerConfigurator.php index d5cbf01321..384211ad55 100644 --- a/mailpoet/lib/DI/ContainerConfigurator.php +++ b/mailpoet/lib/DI/ContainerConfigurator.php @@ -118,6 +118,9 @@ class ContainerConfigurator implements IContainerConfigurator { $container->autowire(\MailPoet\Automation\Engine\Storage\WorkflowRunStorage::class)->setPublic(true); $container->autowire(\MailPoet\Automation\Engine\Storage\WorkflowStorage::class)->setPublic(true); $container->autowire(\MailPoet\Automation\Engine\WordPress::class)->setPublic(true); + // Automation - core integration + $container->autowire(\MailPoet\Automation\Integrations\Core\Actions\WaitAction::class)->setPublic(true); + $container->autowire(\MailPoet\Automation\Integrations\Core\CoreIntegration::class)->setPublic(true); // Automation - MailPoet integration $container->autowire(\MailPoet\Automation\Integrations\MailPoet\MailPoetIntegration::class)->setPublic(true); $container->autowire(\MailPoet\Automation\Integrations\MailPoet\Subjects\SegmentSubject::class)->setPublic(true);