PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / 11.1.0
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress v11.1.0
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
← All changes | back/Classes/AutomationClass.php +124 -45 10.0.1 → 11.1.0 View file →
@@ -8,11 +8,12 @@
8 8
9 9 class AutomationClass extends AcymClass
10 10 {
11 11 const ACTIONS_TO_SKIP = ['acy_send_email'];
12 - var $didAnAction = false;
13 - var $report = [];
14 12
13 + public bool $didAnAction = false;
14 + public array $report = [];
15 +
15 16 public function __construct()
16 17 {
17 18 parent::__construct();
18 19
@@ -17,8 +18,13 @@
17 18 parent::__construct();
18 19
19 20 $this->table = 'automation';
20 21 $this->pkey = 'id';
22 + $this->intColumns = [
23 + 'id',
24 + 'active',
25 + 'admin',
26 + ];
21 27 }
22 28
23 29 public function getMatchingElements(array $settings = []): array
24 30 {
@@ -36,15 +42,15 @@
36 42 }
37 43
38 44 if (!empty($settings['status'])) {
39 45 $query .= empty($filters) ? ' WHERE ' : ' AND ';
40 - $query .= 'active = '.($settings['status'] == 'active' ? '1' : '0');
46 + $query .= 'active = '.($settings['status'] === 'active' ? '1' : '0');
41 47 }
42 48
43 49 if (!empty($settings['ordering']) && !empty($settings['ordering_sort_order'])) {
44 50 $query .= ' ORDER BY '.acym_secureDBColumn($settings['ordering']).' '.acym_secureDBColumn(strtoupper($settings['ordering_sort_order']));
45 51 } else {
46 - $query .= ' ORDER BY id asc';
52 + $query .= ' ORDER BY ordering asc';
47 53 }
48 54
49 55 if (empty($settings['offset']) || $settings['offset'] < 0) {
50 56 $settings['offset'] = 0;
@@ -54,66 +60,75 @@
54 60 $pagination = new PaginationHelper();
55 61 $settings['elementsPerPage'] = $pagination->getListLimit();
56 62 }
57 63
58 - $results['elements'] = acym_loadObjectList($query, '', $settings['offset'], $settings['elementsPerPage']);
64 + $elements = acym_loadObjectList($query, '', $settings['offset'], $settings['elementsPerPage']);
65 + array_map([$this, 'fixTypes'], $elements);
59 66
60 - $results['total'] = acym_loadObject($queryCount);
61 -
62 - return $results;
67 + return [
68 + 'elements' => $elements,
69 + 'total' => acym_loadObject($queryCount),
70 + ];
63 71 }
64 72
65 - public function save($automation)
73 + public function save(object $element): ?int
66 74 {
67 - foreach ($automation as $oneAttribute => $value) {
75 + foreach ($element as $oneAttribute => $value) {
68 76 if (empty($value)) {
69 77 continue;
70 78 }
71 79
72 - if (is_array($value)) {
73 - $value = json_encode($value);
74 - }
75 -
76 - $automation->$oneAttribute = strip_tags($value);
80 + $element->$oneAttribute = is_array($value) ? json_encode($value) : acym_stripTags($value);
77 81 }
78 82
79 - return parent::save($automation);
83 + return parent::save($element);
80 84 }
81 85
82 - public function delete($elements)
86 + public function delete(array $elements): int
83 87 {
84 88 if (empty($elements)) return 0;
85 89
86 - if (!is_array($elements)) $elements = [$elements];
87 90 acym_arrayToInteger($elements);
88 91
89 92 $steps = acym_loadResultArray('SELECT id FROM #__acym_step WHERE automation_id IN ('.implode(',', $elements).')');
90 93 $stepClass = new StepClass();
91 - $stepsDeleted = $stepClass->delete($steps);
94 + $stepClass->delete($steps);
92 95
93 96 return parent::delete($elements);
94 97 }
95 98
96 - public function trigger($trigger, $data = [])
99 + /**
100 + * @param mixed $trigger The identifier of the trigger
101 + * @param array $data An array with data for user-type triggers (user id, order, event...)
102 + */
103 + public function trigger($triggers, array $data = []): void
97 104 {
98 - if (!acym_level(ACYM_ENTERPRISE) || empty($trigger)) {
105 + if (!acym_level(ACYM_ENTERPRISE) || empty($triggers)) {
99 106 return;
100 107 }
101 108
109 + if (!is_array($triggers)) {
110 + $triggers = [$triggers];
111 + }
112 +
102 113 $stepClass = new StepClass();
103 114 $actionClass = new ActionClass();
104 115 $conditionClass = new ConditionClass();
105 - $steps = $stepClass->getActiveStepByTrigger($trigger);
106 116
117 + $steps = $stepClass->getActiveStepByTrigger($triggers);
118 +
107 119 $data['time'] = time();
108 120 foreach ($steps as $step) {
109 121 $newData = $data;
110 122 $execute = false;
111 123
124 + // If we reached the next execution time we execute
125 + // next_execution is only set if one of the time triggers like "asap" or "day" is selected in the automation
112 126 if (!empty($step->next_execution) && $step->next_execution <= $newData['time']) {
113 127 $execute = true;
114 128 }
115 129
130 + // Call the triggers to set the next execution time
116 131 acym_trigger('onAcymExecuteTrigger', [&$step, &$execute, &$newData]);
117 132
118 133 $newData['automation'] = $this->getOneById($step->automation_id);
119 134
@@ -121,9 +136,11 @@
121 136 $step->last_execution = $newData['time'];
122 137 $conditions = $conditionClass->getConditionsByStepId($step->id);
123 138 if (!empty($conditions)) {
124 139 foreach ($conditions as $condition) {
125 - if (!$this->_verifyCondition($condition->conditions, $newData)) continue;
140 + if (!$this->verifyCondition($condition->conditions, $newData)) {
141 + continue;
142 + }
126 143
127 144 $actions = $actionClass->getActionsByStepId($step->id);
128 145 if (empty($actions)) continue;
129 146
@@ -137,13 +154,14 @@
137 154 $stepClass->save($step);
138 155 }
139 156 }
140 157
141 - public function execute($action, $data = [])
158 + public function execute(object $action, array $data = []): bool
142 159 {
143 160 $usersTriggeringAction = empty($data['userIds']) ? [] : $data['userIds'];
144 161 $userTriggeringAction = empty($data['userId']) ? 0 : $data['userId'];
145 - $action->actions = json_decode($action->actions, true);
162 +
163 + $action->actions = json_decode($action->actions ?? '[]', true);
146 164 if (empty($action->actions)) return false;
147 165
148 166 $isMassAction = false;
149 167 static $massAction = 0;
@@ -151,9 +169,9 @@
151 169 $action->id = $massAction--;
152 170 $isMassAction = true;
153 171 }
154 172
155 - $action->filters = json_decode($action->filters, true);
173 + $action->filters = json_decode($action->filters ?? '[]', true);
156 174 if (empty($action->filters)) return false;
157 175
158 176
159 177 $initialWhere = ['1 = 1'];
@@ -170,9 +188,9 @@
170 188 $initialWhere = ['user.id IN ('.implode(', ', $usersTriggeringAction).')'];
171 189 }
172 190 }
173 191
174 - $typeFilter = $action->filters['type_filter'];
192 + $typeFilter = $action->filters['type_filter'] ?? null;
175 193
176 194 unset($action->filters['type_filter']);
177 195 if (empty($action->filters)) {
178 196 $query->where = $initialWhere;
@@ -177,8 +195,9 @@
177 195 if (empty($action->filters)) {
178 196 $query->where = $initialWhere;
179 197 }
180 198
199 + //We do the or first
181 200 foreach ($action->filters as $or => $orValue) {
182 201 if (empty($orValue)) {
183 202 continue;
184 203 }
@@ -183,10 +202,12 @@
183 202 continue;
184 203 }
185 204 $num = 0;
186 205 $query->where = $initialWhere;
206 + //Next the and
187 207 foreach ($orValue as $and => $andValue) {
188 208 $num++;
209 + //Finally we have all names filter
189 210 foreach ($andValue as $filterName => $filterOptions) {
190 211 acym_trigger('onAcymProcessFilter_'.$filterName, [&$query, &$filterOptions, &$num]);
191 212 }
192 213 }
@@ -208,9 +229,11 @@
208 229 }
209 230 }
210 231
211 232 if (!$isMassAction) {
212 - $action->filters['type_filter'] = $typeFilter;
233 + if ($typeFilter !== null) {
234 + $action->filters['type_filter'] = $typeFilter;
235 + }
213 236 $action->filters = json_encode($action->filters);
214 237 $action->actions = json_encode($action->actions);
215 238 $actionClass = new ActionClass();
216 239 $actionClass->save($action);
@@ -220,15 +243,17 @@
220 243
221 244 return $this->didAnAction;
222 245 }
223 246
224 - private function _verifyCondition($conditions, $data = [])
247 + private function verifyCondition(array $conditions, array $data = []): bool
225 248 {
226 - if (empty($conditions)) return true;
249 + if (empty($conditions)) {
250 + return true;
251 + }
252 +
227 253 $userTriggeringAction = empty($data['userId']) ? 0 : $data['userId'];
228 254 $usersTriggeringAction = empty($data['userIds']) ? [] : $data['userIds'];
229 255
230 - $conditions = json_decode($conditions, true);
231 256 $query = new AutomationHelper();
232 257 $initialWhere = ['1 = 1'];
233 258 if (!empty($conditions['type_condition']) && $conditions['type_condition'] == 'user') {
234 259 if (empty($usersTriggeringAction)) {
@@ -246,13 +271,16 @@
246 271
247 272 foreach ($conditions as $or => $orValue) {
248 273 if (empty($orValue)) continue;
249 274
275 + // we increment id condition not validate
250 276 $conditionNotValid = 0;
251 277 $num = 0;
278 + //Next the and
252 279 foreach ($orValue as $and => $andValue) {
253 280 $num++;
254 281 $query->where = $initialWhere;
282 + //Finally we have all names condition
255 283 foreach ($andValue as $filterName => $filterOptions) {
256 284 acym_trigger('onAcymProcessCondition_'.$filterName, [&$query, &$filterOptions, &$num, &$conditionNotValid]);
257 285 }
258 286 }
@@ -262,10 +290,71 @@
262 290
263 291 return false;
264 292 }
265 293
266 - public function getAutomationsAdmin($ids = [])
294 + public function triggerManual(array $automationIds): array
267 295 {
296 + if (!acym_level(ACYM_ENTERPRISE) || empty($automationIds)) {
297 + return [];
298 + }
299 +
300 + acym_arrayToInteger($automationIds);
301 +
302 + $actionClass = new ActionClass();
303 + $conditionClass = new ConditionClass();
304 + $stepClass = new StepClass();
305 +
306 + $executedCount = 0;
307 + $skippedCount = 0;
308 +
309 + foreach ($automationIds as $automationId) {
310 + $steps = $stepClass->getStepsByAutomationId($automationId);
311 + if (empty($steps)) {
312 + continue;
313 + }
314 +
315 + $step = $steps[0];
316 + if (!empty($step->triggers)) {
317 + $step->triggers = json_decode($step->triggers, true);
318 + }
319 +
320 + if (!empty($step->triggers['type_trigger']) && $step->triggers['type_trigger'] !== 'classic') {
321 + $skippedCount++;
322 + continue;
323 + }
324 +
325 + $data = ['time' => time()];
326 + $data['automation'] = $this->getOneById($step->automation_id);
327 +
328 + $conditions = $conditionClass->getConditionsByStepId($step->id);
329 + if (!empty($conditions)) {
330 + foreach ($conditions as $condition) {
331 + if (!$this->verifyCondition($condition->conditions, $data)) {
332 + continue;
333 + }
334 +
335 + $actions = $actionClass->getActionsByStepId($step->id);
336 + if (empty($actions)) {
337 + continue;
338 + }
339 +
340 + foreach ($actions as $action) {
341 + $this->execute($action, $data);
342 + }
343 + }
344 + }
345 +
346 + $executedCount++;
347 + }
348 +
349 + return [
350 + 'executed' => $executedCount,
351 + 'skipped' => $skippedCount,
352 + ];
353 + }
354 +
355 + public function getAutomationsAdmin(array $ids = []): array
356 + {
268 357 acym_arrayToInteger($ids);
269 358
270 359 $query = 'SELECT * FROM #__acym_automation WHERE `admin` = 1';
271 360 if (!empty($ids)) {
@@ -271,20 +360,10 @@
271 360 if (!empty($ids)) {
272 361 $query .= ' AND `id` IN ('.implode(', ', $ids).')';
273 362 }
274 363
275 - return acym_loadObjectList($query, 'name');
276 - }
364 + $automations = acym_loadObjectList($query, 'name');
365 + array_map([$this, 'fixTypes'], $automations);
277 366
278 - public function getActionsByAutomationId($id)
279 - {
280 - return acym_loadObjectList(
281 - 'SELECT action.*
282 - FROM `#__acym_action` AS `action`
283 - JOIN `#__acym_condition` AS `condition`
284 - ON `action`.`condition_id` = `condition`.`id`
285 - JOIN `#__acym_step` AS `step`
286 - ON `condition`.`step_id` = `step`.`id`
287 - WHERE `step`.`automation_id` = '.intval($id)
288 - );
367 + return $automations;
289 368 }
290 369 }