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 +122 -42 10.1.4 → 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,65 +60,75 @@
54 60 $pagination = new PaginationHelper();
55 61 $settings['elementsPerPage'] = $pagination->getListLimit();
56 62 }
57 63
64 + $elements = acym_loadObjectList($query, '', $settings['offset'], $settings['elementsPerPage']);
65 + array_map([$this, 'fixTypes'], $elements);
66 +
58 67 return [
59 - 'elements' => acym_loadObjectList($query, '', $settings['offset'], $settings['elementsPerPage']),
68 + 'elements' => $elements,
60 69 'total' => acym_loadObject($queryCount),
61 70 ];
62 71 }
63 72
64 - public function save($automation)
73 + public function save(object $element): ?int
65 74 {
66 - foreach ($automation as $oneAttribute => $value) {
75 + foreach ($element as $oneAttribute => $value) {
67 76 if (empty($value)) {
68 77 continue;
69 78 }
70 79
71 - if (is_array($value)) {
72 - $value = json_encode($value);
73 - }
74 -
75 - $automation->$oneAttribute = strip_tags($value);
80 + $element->$oneAttribute = is_array($value) ? json_encode($value) : acym_stripTags($value);
76 81 }
77 82
78 - return parent::save($automation);
83 + return parent::save($element);
79 84 }
80 85
81 - public function delete($elements)
86 + public function delete(array $elements): int
82 87 {
83 88 if (empty($elements)) return 0;
84 89
85 - if (!is_array($elements)) $elements = [$elements];
86 90 acym_arrayToInteger($elements);
87 91
88 92 $steps = acym_loadResultArray('SELECT id FROM #__acym_step WHERE automation_id IN ('.implode(',', $elements).')');
89 93 $stepClass = new StepClass();
90 - $stepsDeleted = $stepClass->delete($steps);
94 + $stepClass->delete($steps);
91 95
92 96 return parent::delete($elements);
93 97 }
94 98
95 - 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
96 104 {
97 - if (!acym_level(ACYM_ENTERPRISE) || empty($trigger)) {
105 + if (!acym_level(ACYM_ENTERPRISE) || empty($triggers)) {
98 106 return;
99 107 }
100 108
109 + if (!is_array($triggers)) {
110 + $triggers = [$triggers];
111 + }
112 +
101 113 $stepClass = new StepClass();
102 114 $actionClass = new ActionClass();
103 115 $conditionClass = new ConditionClass();
104 - $steps = $stepClass->getActiveStepByTrigger($trigger);
105 116
117 + $steps = $stepClass->getActiveStepByTrigger($triggers);
118 +
106 119 $data['time'] = time();
107 120 foreach ($steps as $step) {
108 121 $newData = $data;
109 122 $execute = false;
110 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
111 126 if (!empty($step->next_execution) && $step->next_execution <= $newData['time']) {
112 127 $execute = true;
113 128 }
114 129
130 + // Call the triggers to set the next execution time
115 131 acym_trigger('onAcymExecuteTrigger', [&$step, &$execute, &$newData]);
116 132
117 133 $newData['automation'] = $this->getOneById($step->automation_id);
118 134
@@ -120,9 +136,11 @@
120 136 $step->last_execution = $newData['time'];
121 137 $conditions = $conditionClass->getConditionsByStepId($step->id);
122 138 if (!empty($conditions)) {
123 139 foreach ($conditions as $condition) {
124 - if (!$this->_verifyCondition($condition->conditions, $newData)) continue;
140 + if (!$this->verifyCondition($condition->conditions, $newData)) {
141 + continue;
142 + }
125 143
126 144 $actions = $actionClass->getActionsByStepId($step->id);
127 145 if (empty($actions)) continue;
128 146
@@ -136,13 +154,14 @@
136 154 $stepClass->save($step);
137 155 }
138 156 }
139 157
140 - public function execute($action, $data = [])
158 + public function execute(object $action, array $data = []): bool
141 159 {
142 160 $usersTriggeringAction = empty($data['userIds']) ? [] : $data['userIds'];
143 161 $userTriggeringAction = empty($data['userId']) ? 0 : $data['userId'];
144 - $action->actions = json_decode($action->actions, true);
162 +
163 + $action->actions = json_decode($action->actions ?? '[]', true);
145 164 if (empty($action->actions)) return false;
146 165
147 166 $isMassAction = false;
148 167 static $massAction = 0;
@@ -150,9 +169,9 @@
150 169 $action->id = $massAction--;
151 170 $isMassAction = true;
152 171 }
153 172
154 - $action->filters = json_decode($action->filters, true);
173 + $action->filters = json_decode($action->filters ?? '[]', true);
155 174 if (empty($action->filters)) return false;
156 175
157 176
158 177 $initialWhere = ['1 = 1'];
@@ -169,9 +188,9 @@
169 188 $initialWhere = ['user.id IN ('.implode(', ', $usersTriggeringAction).')'];
170 189 }
171 190 }
172 191
173 - $typeFilter = $action->filters['type_filter'];
192 + $typeFilter = $action->filters['type_filter'] ?? null;
174 193
175 194 unset($action->filters['type_filter']);
176 195 if (empty($action->filters)) {
177 196 $query->where = $initialWhere;
@@ -176,8 +195,9 @@
176 195 if (empty($action->filters)) {
177 196 $query->where = $initialWhere;
178 197 }
179 198
199 + //We do the or first
180 200 foreach ($action->filters as $or => $orValue) {
181 201 if (empty($orValue)) {
182 202 continue;
183 203 }
@@ -182,10 +202,12 @@
182 202 continue;
183 203 }
184 204 $num = 0;
185 205 $query->where = $initialWhere;
206 + //Next the and
186 207 foreach ($orValue as $and => $andValue) {
187 208 $num++;
209 + //Finally we have all names filter
188 210 foreach ($andValue as $filterName => $filterOptions) {
189 211 acym_trigger('onAcymProcessFilter_'.$filterName, [&$query, &$filterOptions, &$num]);
190 212 }
191 213 }
@@ -207,9 +229,11 @@
207 229 }
208 230 }
209 231
210 232 if (!$isMassAction) {
211 - $action->filters['type_filter'] = $typeFilter;
233 + if ($typeFilter !== null) {
234 + $action->filters['type_filter'] = $typeFilter;
235 + }
212 236 $action->filters = json_encode($action->filters);
213 237 $action->actions = json_encode($action->actions);
214 238 $actionClass = new ActionClass();
215 239 $actionClass->save($action);
@@ -219,15 +243,17 @@
219 243
220 244 return $this->didAnAction;
221 245 }
222 246
223 - private function _verifyCondition($conditions, $data = [])
247 + private function verifyCondition(array $conditions, array $data = []): bool
224 248 {
225 - if (empty($conditions)) return true;
249 + if (empty($conditions)) {
250 + return true;
251 + }
252 +
226 253 $userTriggeringAction = empty($data['userId']) ? 0 : $data['userId'];
227 254 $usersTriggeringAction = empty($data['userIds']) ? [] : $data['userIds'];
228 255
229 - $conditions = json_decode($conditions, true);
230 256 $query = new AutomationHelper();
231 257 $initialWhere = ['1 = 1'];
232 258 if (!empty($conditions['type_condition']) && $conditions['type_condition'] == 'user') {
233 259 if (empty($usersTriggeringAction)) {
@@ -245,13 +271,16 @@
245 271
246 272 foreach ($conditions as $or => $orValue) {
247 273 if (empty($orValue)) continue;
248 274
275 + // we increment id condition not validate
249 276 $conditionNotValid = 0;
250 277 $num = 0;
278 + //Next the and
251 279 foreach ($orValue as $and => $andValue) {
252 280 $num++;
253 281 $query->where = $initialWhere;
282 + //Finally we have all names condition
254 283 foreach ($andValue as $filterName => $filterOptions) {
255 284 acym_trigger('onAcymProcessCondition_'.$filterName, [&$query, &$filterOptions, &$num, &$conditionNotValid]);
256 285 }
257 286 }
@@ -261,10 +290,71 @@
261 290
262 291 return false;
263 292 }
264 293
265 - public function getAutomationsAdmin($ids = [])
294 + public function triggerManual(array $automationIds): array
266 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 + {
267 357 acym_arrayToInteger($ids);
268 358
269 359 $query = 'SELECT * FROM #__acym_automation WHERE `admin` = 1';
270 360 if (!empty($ids)) {
@@ -270,20 +360,10 @@
270 360 if (!empty($ids)) {
271 361 $query .= ' AND `id` IN ('.implode(', ', $ids).')';
272 362 }
273 363
274 - return acym_loadObjectList($query, 'name');
275 - }
364 + $automations = acym_loadObjectList($query, 'name');
365 + array_map([$this, 'fixTypes'], $automations);
276 366
277 - public function getActionsByAutomationId($id)
278 - {
279 - return acym_loadObjectList(
280 - 'SELECT action.*
281 - FROM `#__acym_action` AS `action`
282 - JOIN `#__acym_condition` AS `condition`
283 - ON `action`.`condition_id` = `condition`.`id`
284 - JOIN `#__acym_step` AS `step`
285 - ON `condition`.`step_id` = `step`.`id`
286 - WHERE `step`.`automation_id` = '.intval($id)
287 - );
367 + return $automations;
288 368 }
289 369 }