PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / 10.2.2
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress v10.2.2
11.1.1 11.1.0 11.0.5 11.0.4 11.0.3 11.0.2 11.0.1 11.0.0 10.11.1 10.11.0 10.10.2 10.10.1 10.10.0 10.9.1 trunk 10.0.0 10.0.1 10.1.0 10.1.1 10.1.2 10.1.3 10.1.4 10.2.0 10.2.1 10.2.2 All 62 releases
acymailing / back / Classes / ScenarioClass.php

ScenarioClass.php in AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress 10.2.2, at back/Classes/ScenarioClass.php

289 lines 9.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace AcyMailing\Classes;
4
5 use AcyMailing\Helpers\PaginationHelper;
6 use AcyMailing\Core\AcymClass;
7
8 class ScenarioClass extends AcymClass
9 {
10 private ScenarioStepClass $scenarioStepClass;
11 private ScenarioHistoryLineClass $scenarioHistoryLineClass;
12 const TYPE_DELAY = 'delay';
13 const TYPE_CONDITION = 'condition';
14 const TYPE_ACTION = 'action';
15
16 private $stepIdsToKeep = [];
17
18 public function __construct()
19 {
20 parent::__construct();
21
22 $this->table = 'scenario';
23 $this->pkey = 'id';
24 $this->scenarioStepClass = new ScenarioStepClass();
25 $this->scenarioHistoryLineClass = new ScenarioHistoryLineClass();
26 }
27
28 public function getMatchingElements(array $settings = []): array
29 {
30 $query = 'SELECT DISTINCT scenario.* FROM #__acym_scenario AS `scenario`';
31 $queryCount = 'SELECT COUNT(DISTINCT scenario.id) AS total FROM #__acym_scenario AS scenario';
32 $queryStatus = 'SELECT COUNT(DISTINCT scenario.id) AS `all`, SUM(`scenario`.`active`) AS active, SUM(IF(`scenario`.`active` = 0, 1, 0)) AS inactive FROM #__acym_scenario AS `scenario`';
33 $filters = [];
34
35 if (!empty($settings['search'])) {
36 $searchValue = acym_escapeDB('%'.$settings['search'].'%');
37 $filters[] = 'scenario.name LIKE '.$searchValue.' OR scenario.id = '.intval($settings['search']);
38 }
39
40 if (!empty($filters)) {
41 $queryStatus .= ' WHERE ('.implode(') AND (', $filters).')';
42 }
43
44 if (!empty($settings['status'])) {
45 switch ($settings['status']) {
46 case 'active':
47 $filters[] = 'scenario.active = 1';
48 break;
49 case 'inactive':
50 $filters[] = 'scenario.active = 0';
51 }
52 }
53
54 if (!empty($filters)) {
55 $query .= ' WHERE ('.implode(') AND (', $filters).')';
56 $queryCount .= ' WHERE ('.implode(') AND (', $filters).')';
57 }
58
59 if (!empty($settings['ordering']) && !empty($settings['ordering_sort_order'])) {
60 $query .= ' ORDER BY scenario.'.acym_secureDBColumn($settings['ordering']).' '.acym_secureDBColumn(strtoupper($settings['ordering_sort_order']));
61 }
62
63 if (empty($settings['offset']) || $settings['offset'] < 0) {
64 $settings['offset'] = 0;
65 }
66
67 if (empty($settings['elementsPerPage']) || $settings['elementsPerPage'] < 1) {
68 $pagination = new PaginationHelper();
69 $settings['elementsPerPage'] = $pagination->getListLimit();
70 }
71
72 return [
73 'elements' => acym_loadObjectList($query, 'id', $settings['offset'], $settings['elementsPerPage']),
74 'total' => acym_loadObject($queryCount),
75 'totalOverall' => acym_loadResult('SELECT COUNT(id) FROM #__acym_scenario'),
76 'scenariosNumberStatus' => acym_loadObjectList($queryStatus)[0],
77 ];
78 }
79
80 public function save($element): int
81 {
82 $flow = '';
83 if (!empty($element->flow)) {
84 $flow = json_decode($element->flow, true);
85
86 if (empty($flow[0]['params'])) {
87 return 0;
88 }
89
90 $element->trigger = $flow[0]['params']['trigger'];
91
92 if (!empty($element->id)) {
93 $scenario = $this->getOneById($element->id);
94 if (!empty($scenario->trigger_params['next_execution'])) {
95 $flow[0]['params']['next_execution'] = $scenario->trigger_params['next_execution'];
96 }
97 }
98
99 $element->trigger_params = json_encode($flow[0]['params']);
100 } elseif (!empty($element->trigger_params) && is_array($element->trigger_params)) {
101 $element->trigger_params = json_encode($element->trigger_params);
102 }
103
104 unset($element->flow);
105
106 $element->id = parent::save($element);
107
108 if (!empty($flow)) {
109 $this->saveFlow($flow, $element->id);
110 }
111
112 return $element->id;
113 }
114
115 public function getOneById($id)
116 {
117 $scenario = parent::getOneById($id);
118
119 if (empty($scenario->trigger_params)) {
120 return $scenario;
121 }
122
123 $scenario->trigger_params = json_decode($scenario->trigger_params, true);
124
125 return $scenario;
126 }
127
128 private function saveFlow($flow, $scenarioId)
129 {
130 if (!empty($flow[0]['children'][0])) {
131 $this->saveStep($flow[0]['children'][0], $scenarioId);
132 }
133 $this->cleanSteps($scenarioId);
134 }
135
136 private function saveStep($currentStep, $scenarioId, $previousStepId = null, $conditionValid = null)
137 {
138 if (isset($currentStep['conditionEnd'])) {
139 if ($currentStep['conditionEnd'] && !empty($currentStep['children'])) {
140 $isConditionValid = empty($currentStep['conditionValid']) ? 0 : 1;
141 $this->saveStep($currentStep['children'][0], $scenarioId, $previousStepId, $isConditionValid);
142 }
143
144 return;
145 }
146
147 switch ($currentStep['params']['type']) {
148 case self::TYPE_DELAY:
149 $type = self::TYPE_DELAY;
150 break;
151 case self::TYPE_CONDITION:
152 $type = self::TYPE_CONDITION;
153 break;
154 case self::TYPE_ACTION:
155 $type = self::TYPE_ACTION;
156 break;
157 default:
158 acym_enqueueMessage(acym_translation('ACYM_INVALID_STEP_TYPE'), 'error');
159
160 return;
161 }
162
163 $step = new \stdClass();
164 $step->id = $currentStep['slug'];
165 $step->previous_id = $previousStepId;
166 $step->type = $type;
167 $step->params = $currentStep['params'];
168 $step->scenario_id = $scenarioId;
169 $step->condition_valid = $conditionValid;
170
171 $this->scenarioStepClass->save($step);
172
173 $this->stepIdsToKeep[] = $step->id;
174
175 if (!empty($currentStep['children'])) {
176 foreach ($currentStep['children'] as $child) {
177 $this->saveStep($child, $scenarioId, $currentStep['slug']);
178 }
179 }
180 }
181
182 private function cleanSteps(int $scenarioId): void
183 {
184 $stepIdsToDelete = $this->scenarioStepClass->getAllStepsToDelete($scenarioId, $this->stepIdsToKeep);
185
186 if (empty($stepIdsToDelete)) {
187 return;
188 }
189
190 $scenarioQueueClass = new ScenarioQueueClass();
191 $scenarioQueueClass->deleteByStepIds($stepIdsToDelete);
192 $this->scenarioStepClass->delete($stepIdsToDelete);
193 }
194
195 private function formatScenario($scenario)
196 {
197 if (empty($scenario)) {
198 return null;
199 }
200
201 $scenario->trigger_params = json_decode($scenario->trigger_params, true);
202
203 return $scenario;
204 }
205
206 public function getAllActiveByTriggers(array $triggerTypes): array
207 {
208 if (empty($triggerTypes)) {
209 return [];
210 }
211
212 $triggerTypes = array_map('acym_escapeDB', $triggerTypes);
213 $query = 'SELECT * FROM #__acym_scenario WHERE active = 1 AND `trigger` IN ('.implode(', ', $triggerTypes).')';
214
215 return array_map([$this, 'formatScenario'], acym_loadObjectList($query));
216 }
217
218 public function delete($elements)
219 {
220 if (empty($elements)) {
221 return 0;
222 }
223
224 if (!is_array($elements)) {
225 $elements = [$elements];
226 }
227
228 $escapedElements = [];
229 foreach ($elements as $key => $val) {
230 $escapedElements[$key] = acym_escapeDB($val);
231 }
232
233 $scenarioHistoryLineQuery = 'DELETE FROM #__acym_scenario_history_line WHERE scenario_process_id IN (SELECT id FROM #__acym_scenario_process WHERE scenario_id IN ('.implode(
234 ',',
235 $escapedElements
236 ).'))';
237 $scenarioQueueQuery = 'DELETE FROM #__acym_scenario_queue WHERE scenario_process_id IN (SELECT id FROM #__acym_scenario_process WHERE scenario_id IN ('.implode(
238 ',',
239 $escapedElements
240 ).'))';
241 $scenarioProcessQuery = 'DELETE FROM #__acym_scenario_process WHERE scenario_id IN ('.implode(',', $escapedElements).')';
242 $scenarioStepQuery = 'DELETE FROM #__acym_scenario_step WHERE scenario_id IN ('.implode(',', $escapedElements).')';
243 acym_query($scenarioHistoryLineQuery);
244 acym_query($scenarioQueueQuery);
245 acym_query($scenarioProcessQuery);
246 acym_query($scenarioStepQuery);
247
248 return parent::delete($elements);
249 }
250
251 public function duplicate(int $scenarioId)
252 {
253 $scenarioStepClass = new ScenarioStepClass();
254
255 $scenario = $this->getOneById($scenarioId);
256
257 if (empty($scenario)) {
258 return;
259 }
260
261 unset($scenario->id);
262 $scenario->name = $scenario->name.' - '.acym_translation('ACYM_COPY');
263
264 $scenario->id = $this->save($scenario);
265
266 $scenarioSteps = $scenarioStepClass->getAllByScenarioId($scenarioId);
267
268 if (empty($scenarioSteps)) {
269 return;
270 }
271
272 $allStepIds = $scenarioStepClass->getAllStepIds();
273
274 $stepCorrespondence = [];
275
276 foreach ($scenarioSteps as $scenarioStep) {
277 $stepCorrespondence[$scenarioStep->id] = $scenarioStepClass->generateNewStepId($allStepIds);
278 $allStepIds[] = $stepCorrespondence[$scenarioStep->id];
279 }
280
281 foreach ($scenarioSteps as $scenarioStep) {
282 $scenarioStep->id = $stepCorrespondence[$scenarioStep->id];
283 $scenarioStep->previous_id = $stepCorrespondence[$scenarioStep->previous_id] ?? null;
284 $scenarioStep->scenario_id = $scenario->id;
285 $scenarioStepClass->save($scenarioStep);
286 }
287 }
288 }
289