PluginProbe ʕ •ᴥ•ʔ
MailPoet – Newsletters, Email Marketing, and Automation / 5.34.2
MailPoet – Newsletters, Email Marketing, and Automation v5.34.2
5.34.2 5.34.1 5.34.0 5.33.1 5.33.0 5.32.0 5.31.0 5.30.0 5.29.0 5.28.1 5.28.0 5.27.0 5.26.0 5.26.1 5.25.0 5.24.0 4.43.0 4.43.1 4.44.0 4.44.1 4.45.0 4.46.0 4.47.0 4.48.0 4.48.1 4.48.2 4.49.0 4.49.1 4.5.0 4.5.1 4.5.2 4.50.0 4.50.1 4.51.0 4.51.1 4.51.2 4.52.0 4.53.0 4.54.0 4.55.0 4.56.0 4.57.0 4.58.0 4.58.1 4.58.2 4.6.0 4.6.1 4.6.2 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 5.0.0 5.0.1 5.0.2 5.1.0 5.1.1 5.10.0 5.10.1 5.11.0 5.12.0 5.12.1 5.12.10 5.12.11 5.12.12 5.12.13 5.12.2 5.12.3 5.12.4 5.12.5 5.12.6 5.12.7 5.12.8 5.12.9 5.13.0 5.13.1 5.13.2 5.14.0 5.14.1 5.14.2 5.14.3 5.15.0 5.15.1 5.16.0 5.16.1 5.16.2 5.16.3 5.16.4 5.17.0 5.17.1 5.17.2 5.17.3 5.17.4 5.17.5 5.17.6 5.18.0 5.19.0 5.2.0 5.2.1 5.2.2 5.2.3 5.20.0 5.21.0 5.21.1 5.21.2 5.21.3 5.22.0 5.22.1 5.22.2 5.22.3 5.22.4 5.23.0 5.23.1 5.23.2 5.3.0 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6 5.3.7 5.4.0 5.4.1 5.4.2 5.5.0 5.5.1 5.5.2 5.6.0 5.6.1 5.6.2 5.6.3 5.6.4 5.7.0 5.7.1 5.8.0 5.8.1 5.9.0 3.0.0-beta.15 3.7.1 3.0.0-beta.16 3.7.2 3.0.0-beta.17 3.7.3 3.0.0-beta.18 3.7.4 3.0.0-beta.19 3.7.5 3.0.0-beta.2 3.7.6 3.0.0-beta.20 3.7.8 3.0.0-beta.21 3.70.0 3.0.0-beta.22 3.71.0 3.0.0-beta.23 3.71.1 3.0.0-beta.23.1 3.71.2 3.0.0-beta.23.2 3.71.3 3.0.0-beta.24 3.72.0 3.0.0-beta.25 3.73.0 3.0.0-beta.26 3.73.1 3.0.0-beta.27 3.73.2 3.0.0-beta.28 3.74.0 3.0.0-beta.29 3.74.1 3.0.0-beta.3 3.74.2 3.0.0-beta.30 3.74.3 3.0.0-beta.31 3.75.0 3.0.0-beta.32 3.75.1 3.0.0-beta.33 3.76.0 3.0.0-beta.33.1 3.77.0 3.0.0-beta.34.0.0 3.77.1 3.0.0-beta.36.0.0 3.78.0 3.0.0-beta.36.0.1 3.79.0 3.0.0-beta.36.2.0 3.8 3.0.0-beta.36.3.0 3.8.1 3.0.0-beta.36.3.1 3.8.2 3.0.0-beta.37.0.0 3.8.3 3.0.0-beta.4 3.8.4 3.0.0-beta.5 3.8.5 3.0.0-beta.6 3.8.6 3.0.0-beta.7 3.80.0 3.0.0-beta.7.1 3.81.0 3.0.0-beta.8 3.82.0 3.0.0-beta.9 3.83.0 3.0.0-rc.1.0.0 3.84.0 3.0.0-rc.1.0.1 3.84.1 3.0.0-rc.1.0.2 3.85.0 3.0.0-rc.1.0.3 3.85.1 3.0.0-rc.1.0.4 3.86.0 3.0.0-rc.2.0.0 3.87.0 3.0.0-rc.2.0.1 3.87.1 3.0.0-rc.2.0.2 3.87.2 3.0.0-rc.2.0.3 3.88.0 3.0.1 3.88.1 3.0.2 3.88.2 3.0.3 3.89.0 3.0.4 3.89.1 3.0.5 3.89.2 3.0.6 3.89.3 3.0.7 3.89.4 3.0.8 3.9.0 3.0.9 3.9.1 3.1.0 3.90.0 3.10 3.90.1 3.10.1 3.90.2 3.100.0 3.91.0 3.100.1 3.91.1 3.100.2 3.92.0 3.101.0 3.92.1 3.101.1 3.93.0 3.102.0 3.93.1 3.102.1 3.94.0 3.103.0 3.95.0 3.103.1 3.95.1 3.11.0 3.96.0 3.11.1 3.96.1 3.11.2 3.97.0 3.11.3 3.98.0 3.11.4 3.98.1 3.11.5 3.99.0 3.12.0 3.99.1 3.12.1 4.0.0 3.13.0 4.0.1 3.14.0 4.1.0 3.14.1 4.1.1 3.15.0 4.10.0 3.16.0 4.11.0 3.16.1 4.11.1 3.16.2 4.12.0 3.16.3 4.12.1 3.17.0 4.12.2 3.17.1 4.13.0 3.17.2 4.14.0 3.18.0 4.15.0 3.18.1 4.16.0 3.18.2 4.17.0 3.19.0 4.17.1 3.19.1 4.18.0 3.19.2 4.18.1 3.19.3 4.19.0 3.2.0 4.2.0 3.2.1 4.20.0 3.2.2 4.20.1 3.2.3 4.20.2 3.2.4 4.21.0 3.2.5 4.22.0 3.20.0 4.22.1 3.21.0 4.22.2 3.21.1 4.23.0 3.22.0 4.24.0 3.23.0 4.25.0 3.23.1 4.26.0 3.23.2 4.26.1 3.24.0 4.27.0 3.25.0 4.28.0 3.25.1 4.29.0 3.26.0 4.3.0 3.26.1 4.3.1 3.27.0 4.30.0 3.28.0 4.31.0 3.29.0 4.31.1 3.3.0 4.32.0 3.3.1 4.33.0 3.3.2 4.34.0 3.3.3 4.35.0 3.3.4 4.35.1 3.3.5 4.36.0 3.3.6 4.37.0 3.30.0 4.38.0 3.31.0 4.39.0 3.31.1 4.4.0 3.32.0 4.40.0 3.32.1 4.41.0 3.32.2 4.41.1 3.33.0 4.41.2 3.34.0 4.41.3 3.34.1 4.42.0 3.34.2 4.42.1 3.34.3 3.34.4 3.35.0 3.35.1 3.35.3 3.35.4 3.36.0 3.37.0 3.37.1 3.37.2 3.37.3 3.38.0 3.38.1 3.39.0 3.39.1 3.39.2 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.40.0 3.40.1 3.41.0 3.41.1 3.41.2 3.42.0 3.42.1 3.42.2 3.42.3 3.43.0 3.43.1 3.44.0 3.45.0 3.45.1 3.46.0 3.46.1 3.46.10 3.46.11 3.46.12 3.46.13 3.46.14 3.46.2 3.46.3 3.46.4 3.46.5 3.46.6 3.46.7 3.46.8 3.46.9 3.47.0 3.47.1 3.47.10 3.47.11 3.47.2 3.47.3 3.47.5 3.47.6 3.47.7 3.47.9 3.48.0 3.48.1 3.49.0 3.49.1 3.5.0 3.5.1 3.50.0 3.51.0 3.51.1 3.51.2 3.52.0 3.53.0 3.54.0 3.54.1 3.54.2 3.54.3 3.55.0 3.55.1 3.56.0 3.56.1 3.56.2 3.57.0 3.57.1 3.58.0 3.59.0 3.59.1 3.59.2 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.60.0 3.60.1 3.60.10 3.60.11 3.60.12 3.60.2 3.60.3 3.60.4 3.60.6 3.60.7 3.60.8 3.60.9 3.61.0 3.62.0 3.62.1 3.63.0 3.64.0 3.64.1 3.64.2 3.64.3 3.65.0 trunk 3.65.1 3.0.0 3.66.0 3.0.0-beta.1 3.67.0 3.0.0-beta.10 3.67.1 3.0.0-beta.11 3.68.0 3.0.0-beta.12 3.69.0 3.0.0-beta.13 3.69.1 3.0.0-beta.14 3.7.0
mailpoet / lib / Automation / Integrations / MailPoet / Analytics / Endpoints / UpdateRunStatusEndpoint.php
mailpoet / lib / Automation / Integrations / MailPoet / Analytics / Endpoints Last commit date
AutomationFlowEndpoint.php 1 month ago OverviewEndpoint.php 1 year ago UpdateRunStatusEndpoint.php 2 months ago index.php 3 years ago
UpdateRunStatusEndpoint.php
179 lines
1 <?php declare(strict_types = 1);
2
3 namespace MailPoet\Automation\Integrations\MailPoet\Analytics\Endpoints;
4
5 if (!defined('ABSPATH')) exit;
6
7
8 use ActionScheduler_Store;
9 use MailPoet\API\REST\Request;
10 use MailPoet\API\REST\Response;
11 use MailPoet\Automation\Engine\API\Endpoint;
12 use MailPoet\Automation\Engine\Control\ActionScheduler as ASWrapper;
13 use MailPoet\Automation\Engine\Data\AutomationRun;
14 use MailPoet\Automation\Engine\Exceptions;
15 use MailPoet\Automation\Engine\Exceptions\UnexpectedValueException;
16 use MailPoet\Automation\Engine\Hooks;
17 use MailPoet\Automation\Engine\Storage\AutomationRunStorage;
18 use MailPoet\Validator\Builder;
19
20 class UpdateRunStatusEndpoint extends Endpoint {
21
22 /** @var AutomationRunStorage */
23 private $automationRunStorage;
24
25 /** @var ASWrapper */
26 private $actionScheduler;
27
28 public function __construct(
29 AutomationRunStorage $automationRunStorage,
30 ASWrapper $actionScheduler
31 ) {
32 $this->automationRunStorage = $automationRunStorage;
33 $this->actionScheduler = $actionScheduler;
34 }
35
36 public function handle(Request $request): Response {
37 /** @var int $runId */
38 $runId = $request->getParam('id');
39 $runId = intval($runId);
40
41 /** @var string|null $status */
42 $status = $request->getParam('status');
43
44 $run = $this->automationRunStorage->getAutomationRun($runId);
45 if (!$run) {
46 throw Exceptions::automationRunNotFound($runId);
47 }
48
49 $currentStatus = $run->getStatus();
50 $targetStatus = $status;
51
52 // Validate allowed status values
53 $allowedStatuses = [
54 AutomationRun::STATUS_RUNNING,
55 AutomationRun::STATUS_CANCELLED,
56 ];
57 if (!in_array($targetStatus, $allowedStatuses, true)) {
58 throw UnexpectedValueException::create()
59 ->withMessage(__('Invalid status value.', 'mailpoet'))
60 ->withErrors(['status' => __('Status must be "running" or "cancelled".', 'mailpoet')]);
61 }
62
63 // Validate status transitions
64 if ($currentStatus === $targetStatus) {
65 // Same status, no change needed
66 return new Response([
67 'id' => $run->getId(),
68 'status' => $run->getStatus(),
69 'updated_at' => $run->getUpdatedAt()->format(\DateTimeImmutable::W3C),
70 ]);
71 }
72
73 // Allow transitions: running → cancelled, cancelled → running
74 $allowedTransitions = [
75 AutomationRun::STATUS_RUNNING => [AutomationRun::STATUS_CANCELLED],
76 AutomationRun::STATUS_CANCELLED => [AutomationRun::STATUS_RUNNING],
77 ];
78
79 if (
80 !isset($allowedTransitions[$currentStatus]) ||
81 !in_array($targetStatus, $allowedTransitions[$currentStatus], true)
82 ) {
83 throw UnexpectedValueException::create()
84 ->withMessage(
85 sprintf(
86 // translators: This is an error message for an invalid status transition for an automation run. %1$s is the current status, %2$s is the target status.
87 __('Cannot transition run from "%1$s" to "%2$s".', 'mailpoet'),
88 $currentStatus,
89 $targetStatus
90 )
91 )
92 ->withErrors(['status' => __('Invalid status transition.', 'mailpoet')]);
93 }
94
95 // Update run status
96 $this->automationRunStorage->updateStatus($runId, $targetStatus);
97
98 // Schedule/unschedule actions based on status change
99 if ($targetStatus === AutomationRun::STATUS_CANCELLED) {
100 $this->unschedulePendingForRun($runId);
101 } elseif ($targetStatus === AutomationRun::STATUS_RUNNING) {
102 // If nothing pending for this run, enqueue next step based on stored next_step_id
103 if (!$this->hasPendingForRun($runId)) {
104 $nextStepId = $this->automationRunStorage->getNextStepId($runId);
105 if ($nextStepId) {
106 $this->enqueueStep($runId, (string)$nextStepId, 1);
107 }
108 }
109 }
110
111 // Get updated run
112 $updatedRun = $this->automationRunStorage->getAutomationRun($runId);
113 if (!$updatedRun) {
114 throw Exceptions::automationRunNotFound($runId);
115 }
116
117 // Return updated run data
118 return new Response([
119 'id' => $updatedRun->getId(),
120 'status' => $updatedRun->getStatus(),
121 'updated_at' => $updatedRun->getUpdatedAt()->format(\DateTimeImmutable::W3C),
122 ]);
123 }
124
125 public static function getRequestSchema(): array {
126 return [
127 'id' => Builder::integer()->required(),
128 'status' => Builder::string()->required(),
129 ];
130 }
131
132 private function unschedulePendingForRun(int $runId): void {
133 $actions = $this->actionScheduler->getScheduledActions([
134 'hook' => Hooks::AUTOMATION_STEP,
135 'status' => ActionScheduler_Store::STATUS_PENDING,
136 ]);
137 foreach ($actions as $action) {
138 $args = $action->get_args();
139 if ($this->argsMatchRun($args, $runId)) {
140 $this->actionScheduler->unscheduleAction(Hooks::AUTOMATION_STEP, $args);
141 }
142 }
143 }
144
145 private function hasPendingForRun(int $runId): bool {
146 $actions = $this->actionScheduler->getScheduledActions([
147 'hook' => Hooks::AUTOMATION_STEP,
148 'status' => ActionScheduler_Store::STATUS_PENDING,
149 ]);
150 foreach ($actions as $action) {
151 $args = $action->get_args();
152 if ($this->argsMatchRun($args, $runId)) {
153 return true;
154 }
155 }
156 return false;
157 }
158
159 /**
160 * @param mixed $args
161 */
162 private function argsMatchRun($args, int $runId): bool {
163 return is_array($args)
164 && isset($args[0])
165 && is_array($args[0])
166 && isset($args[0]['automation_run_id'])
167 && is_numeric($args[0]['automation_run_id'])
168 && (int)$args[0]['automation_run_id'] === $runId;
169 }
170
171 private function enqueueStep(int $runId, string $stepId, int $runNumber = 1): int {
172 return $this->actionScheduler->enqueue(Hooks::AUTOMATION_STEP, [[
173 'automation_run_id' => $runId,
174 'step_id' => $stepId,
175 'run_number' => $runNumber,
176 ]]);
177 }
178 }
179