PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / 11.1.1
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress v11.1.1
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/ScenarioClass.php +0 -325 11.0.2 → 11.1.1 View file →
@@ -1,325 +1,0 @@
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 - const TYPE_DELAY = 'delay';
11 - const TYPE_CONDITION = 'condition';
12 - const TYPE_ACTION = 'action';
13 -
14 - private ScenarioStepClass $scenarioStepClass;
15 -
16 - // This is a list of all the step ids we have to save when saving a scenario, this way we can delete all the steps that are not in this list
17 - private array $stepIdsToKeep = [];
18 -
19 - public function __construct()
20 - {
21 - parent::__construct();
22 -
23 - $this->table = 'scenario';
24 - $this->pkey = 'id';
25 - $this->scenarioStepClass = new ScenarioStepClass();
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 - // We don't filter by status on the status query this way we can select other statuses
55 - if (!empty($filters)) {
56 - $query .= ' WHERE ('.implode(') AND (', $filters).')';
57 - $queryCount .= ' WHERE ('.implode(') AND (', $filters).')';
58 - }
59 -
60 - if (!empty($settings['ordering']) && !empty($settings['ordering_sort_order'])) {
61 - $query .= ' ORDER BY scenario.'.acym_secureDBColumn($settings['ordering']).' '.acym_secureDBColumn(strtoupper($settings['ordering_sort_order']));
62 - }
63 -
64 - if (empty($settings['offset']) || $settings['offset'] < 0) {
65 - $settings['offset'] = 0;
66 - }
67 -
68 - if (empty($settings['elementsPerPage']) || $settings['elementsPerPage'] < 1) {
69 - $pagination = new PaginationHelper();
70 - $settings['elementsPerPage'] = $pagination->getListLimit();
71 - }
72 -
73 - return [
74 - 'elements' => acym_loadObjectList($query, 'id', $settings['offset'], $settings['elementsPerPage']),
75 - 'total' => acym_loadObject($queryCount),
76 - 'totalOverall' => acym_loadResult('SELECT COUNT(id) FROM #__acym_scenario'),
77 - 'scenariosNumberStatus' => acym_loadObjectList($queryStatus)[0],
78 - ];
79 - }
80 -
81 - public function save(object $element): ?int
82 - {
83 - $flow = [];
84 - if (!empty($element->flow)) {
85 - $flow = json_decode($element->flow, true);
86 -
87 - // The first step should the trigger
88 - if (empty($flow[0]['params'])) {
89 - return 0;
90 - }
91 -
92 - $element->trigger = $flow[0]['params']['trigger'];
93 -
94 - if (!empty($element->id)) {
95 - $scenario = $this->getOneById($element->id);
96 - if (!empty($scenario->trigger_params['next_execution'])) {
97 - $flow[0]['params']['next_execution'] = $scenario->trigger_params['next_execution'];
98 - }
99 - }
100 -
101 - $element->trigger_params = json_encode($flow[0]['params']);
102 - } elseif (!empty($element->trigger_params) && is_array($element->trigger_params)) {
103 - $element->trigger_params = json_encode($element->trigger_params);
104 - }
105 -
106 - unset($element->flow);
107 -
108 - $element->id = parent::save($element);
109 -
110 - if (!empty($flow) && !empty($element->id)) {
111 - $this->saveFlow($flow, $element->id);
112 - }
113 -
114 - return $element->id;
115 - }
116 -
117 - public function getOneById(int $id): ?object
118 - {
119 - $scenario = parent::getOneById($id);
120 -
121 - if (empty($scenario->trigger_params)) {
122 - return $scenario;
123 - }
124 -
125 - $scenario->trigger_params = json_decode($scenario->trigger_params, true);
126 -
127 - return $scenario;
128 - }
129 -
130 - private function saveFlow(array $flow, int $scenarioId): void
131 - {
132 - if (!empty($flow[0]['children'][0])) {
133 - // We save all the step
134 - $this->saveStep($flow[0]['children'][0], $scenarioId);
135 - }
136 - $this->cleanSteps($scenarioId);
137 - }
138 -
139 - private function saveStep(array $currentStep, int $scenarioId, ?string $previousStepId = null, ?int $conditionValid = null): void
140 - {
141 - // If this is a direct child of a condition we pass it, it's a hidden object for the javascript
142 - if (isset($currentStep['conditionEnd'])) {
143 - if ($currentStep['conditionEnd'] && !empty($currentStep['children'])) {
144 - $isConditionValid = empty($currentStep['conditionValid']) ? 0 : 1;
145 - $this->saveStep($currentStep['children'][0], $scenarioId, $previousStepId, $isConditionValid);
146 - }
147 -
148 - return;
149 - }
150 -
151 - switch ($currentStep['params']['type']) {
152 - case self::TYPE_DELAY:
153 - $type = self::TYPE_DELAY;
154 - break;
155 - case self::TYPE_CONDITION:
156 - $type = self::TYPE_CONDITION;
157 - break;
158 - case self::TYPE_ACTION:
159 - $type = self::TYPE_ACTION;
160 - break;
161 - default:
162 - acym_enqueueMessage(acym_translation('ACYM_INVALID_STEP_TYPE'), 'error');
163 -
164 - return;
165 - }
166 -
167 - $step = new \stdClass();
168 - $step->id = $currentStep['slug'];
169 - $step->previous_id = $previousStepId;
170 - $step->type = $type;
171 - $step->params = $currentStep['params'];
172 - $step->scenario_id = $scenarioId;
173 - $step->condition_valid = $conditionValid;
174 -
175 - $this->scenarioStepClass->save($step);
176 -
177 - $this->stepIdsToKeep[] = $step->id;
178 -
179 - if (!empty($currentStep['children'])) {
180 - foreach ($currentStep['children'] as $child) {
181 - $this->saveStep($child, $scenarioId, $currentStep['slug']);
182 - }
183 - }
184 - }
185 -
186 - private function cleanSteps(int $scenarioId): void
187 - {
188 - $stepIdsToDelete = $this->scenarioStepClass->getAllStepsToDelete($scenarioId, $this->stepIdsToKeep);
189 -
190 - if (empty($stepIdsToDelete)) {
191 - return;
192 - }
193 -
194 - $scenarioQueueClass = new ScenarioQueueClass();
195 - $scenarioQueueClass->deleteByStepIds($stepIdsToDelete);
196 - $this->scenarioStepClass->delete($stepIdsToDelete);
197 - }
198 -
199 - private function formatScenario(object $scenario): ?object
200 - {
201 - if (empty($scenario)) {
202 - return null;
203 - }
204 -
205 - $scenario->trigger_params = json_decode($scenario->trigger_params, true);
206 -
207 - return $scenario;
208 - }
209 -
210 - public function getAllActiveByTriggers(array $triggerTypes): array
211 - {
212 - if (empty($triggerTypes)) {
213 - return [];
214 - }
215 -
216 - $triggerTypes = array_map('acym_escapeDB', $triggerTypes);
217 - $query = 'SELECT * FROM #__acym_scenario WHERE active = 1 AND `trigger` IN ('.implode(', ', $triggerTypes).') ORDER BY `ordering` ASC';
218 -
219 - return array_map([$this, 'formatScenario'], acym_loadObjectList($query));
220 - }
221 -
222 - public function delete(array $elements): int
223 - {
224 - if (empty($elements)) {
225 - return 0;
226 - }
227 -
228 - $escapedElements = array_map('acym_escapeDB', $elements);
229 -
230 - $scenarioHistoryLineQuery = 'DELETE FROM #__acym_scenario_history_line WHERE scenario_process_id IN (SELECT id FROM #__acym_scenario_process WHERE scenario_id IN ('.implode(
231 - ',',
232 - $escapedElements
233 - ).'))';
234 - $scenarioQueueQuery = 'DELETE FROM #__acym_scenario_queue WHERE scenario_process_id IN (SELECT id FROM #__acym_scenario_process WHERE scenario_id IN ('.implode(
235 - ',',
236 - $escapedElements
237 - ).'))';
238 - $scenarioProcessQuery = 'DELETE FROM #__acym_scenario_process WHERE scenario_id IN ('.implode(',', $escapedElements).')';
239 - $scenarioStepQuery = 'DELETE FROM #__acym_scenario_step WHERE scenario_id IN ('.implode(',', $escapedElements).')';
240 - acym_query($scenarioHistoryLineQuery);
241 - acym_query($scenarioQueueQuery);
242 - acym_query($scenarioProcessQuery);
243 - acym_query($scenarioStepQuery);
244 -
245 - return parent::delete($elements);
246 - }
247 -
248 - public function duplicate(int $scenarioId): void
249 - {
250 - $scenarioStepClass = new ScenarioStepClass();
251 -
252 - $scenario = $this->getOneById($scenarioId);
253 -
254 - if (empty($scenario)) {
255 - return;
256 - }
257 -
258 - unset($scenario->id);
259 - $scenario->name = $scenario->name.' - '.acym_translation('ACYM_COPY');
260 -
261 - $scenario->id = $this->save($scenario);
262 -
263 - $scenarioSteps = $scenarioStepClass->getAllByScenarioId($scenarioId);
264 -
265 - if (empty($scenarioSteps)) {
266 - return;
267 - }
268 -
269 - $allStepIds = $scenarioStepClass->getAllStepIds();
270 -
271 - $stepCorrespondence = [];
272 -
273 - foreach ($scenarioSteps as $scenarioStep) {
274 - $stepCorrespondence[$scenarioStep->id] = $scenarioStepClass->generateNewStepId($allStepIds);
275 - $allStepIds[] = $stepCorrespondence[$scenarioStep->id];
276 - }
277 -
278 - foreach ($scenarioSteps as $scenarioStep) {
279 - $scenarioStep->id = $stepCorrespondence[$scenarioStep->id];
280 - $scenarioStep->previous_id = $stepCorrespondence[$scenarioStep->previous_id] ?? null;
281 - $scenarioStep->scenario_id = $scenario->id;
282 - $scenarioStepClass->save($scenarioStep);
283 - }
284 - }
285 -
286 - public function markUserUnsubscribeFromScenario(int $userId, int $scenarioId): void
287 - {
288 - $query = 'UPDATE #__acym_scenario_process SET unsubscribed = 1 WHERE scenario_id = '.intval($scenarioId).' AND user_id = '.intval($userId);
289 -
290 -
291 - acym_query($query);
292 - }
293 -
294 - public function getScenarioIdByMailId(int $mailId): ?int
295 - {
296 - $query = 'SELECT scenario_id
297 - FROM #__acym_scenario_step
298 - WHERE type = '.acym_escapeDB(self::TYPE_ACTION).'
299 - AND params LIKE '.acym_escapeDB('%[mail_id]":"'.$mailId.'"%').'
300 - LIMIT 1';
301 -
302 - return acym_loadResult($query);
303 - }
304 -
305 - public function checkUserMarkedUnsubscribed(int $userId, int $scenarioProcessId): bool
306 - {
307 - $queryScenId = 'SELECT scenario_id
308 - FROM #__acym_scenario_process
309 - WHERE id = '.intval($scenarioProcessId).'
310 - AND user_id = '.intval($userId).'
311 - LIMIT 1';
312 -
313 - $scenarioId = acym_loadResult($queryScenId);
314 -
315 - $queryUnsubscribed = 'SELECT unsubscribed
316 - FROM #__acym_scenario_process
317 - WHERE scenario_id = '.intval($scenarioId).'
318 - AND user_id = '.intval($userId).'
319 - LIMIT 1';
320 -
321 - $result = acym_loadResult($queryUnsubscribed);
322 -
323 - return !empty($result);
324 - }
325 -}