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/Core/AcymController.php +470 -0 10.1.0 → 11.1.0 View file →
@@ -1,0 +1,470 @@
1 +<?php
2 +
3 +namespace AcyMailing\Core;
4 +
5 +abstract class AcymController extends AcymObject
6 +{
7 + private $currentClass = null;
8 + private string $sessionName;
9 +
10 + protected array $breadcrumb = [];
11 + protected array $loadScripts = [];
12 + protected array $publicFrontTasks = [];
13 + protected array $allowedTasks = [];
14 + protected array $menuAlias = [];
15 + protected string $taskCalled = '';
16 + protected string $menuClass = '';
17 +
18 + public string $defaulttask = 'listing';
19 + public string $name = '';
20 +
21 + public function __construct()
22 + {
23 + parent::__construct();
24 +
25 + $classname = get_class($this);
26 + $classname = substr($classname, strrpos($classname, '\\') + 1);
27 + $this->name = strtolower(
28 + substr(
29 + $classname,
30 + 0,
31 + strpos($classname, 'Controller')
32 + )
33 + );
34 +
35 + $currentClassName = 'AcyMailing\\Classes\\'.rtrim(ucfirst(str_replace(['Front', 'front'], '', $this->name)), 's').'Class';
36 + if (class_exists($currentClassName)) {
37 + $this->currentClass = new $currentClassName();
38 + }
39 + $this->sessionName = 'acym_filters_'.$this->name;
40 + $this->taskCalled = acym_getVar('string', 'task', '');
41 +
42 + $this->breadcrumb['AcyMailing'] = acym_completeLink('dashboard');
43 + }
44 +
45 + private function initSession(): void
46 + {
47 + $controllerSession = acym_getVar('array', $this->sessionName, [], 'SESSION');
48 + if (empty($controllerSession)) {
49 + acym_setSession($this->sessionName, []);
50 + }
51 + }
52 +
53 + /**
54 + * @param mixed $default
55 + *
56 + * @return mixed
57 + */
58 + public function getVarFiltersListing(string $type, string $varName, $default, bool $overrideIfNull = false)
59 + {
60 + if ($this->taskCalled === 'clearFilters') {
61 + return $default;
62 + }
63 +
64 + $this->initSession();
65 +
66 + $isVarInRequest = !is_null(acym_getVar('raw', $varName, null, '', ACYM_ALLOWRAW));
67 + $returnValue = $isVarInRequest ? acym_getVar($type, $varName) : null;
68 +
69 + if (is_null($returnValue) && $overrideIfNull) {
70 + $returnValue = $default;
71 + }
72 +
73 + if (!is_null($returnValue)) {
74 + $controllerSession = acym_getVar('array', $this->sessionName, [], 'SESSION');
75 + $controllerSession[$varName] = $returnValue;
76 + acym_setSession($this->sessionName, $controllerSession);
77 +
78 + return $returnValue;
79 + }
80 +
81 + $filters = acym_getVar('array', $this->sessionName, [], 'SESSION');
82 + if (!empty($filters[$varName])) {
83 + return $filters[$varName];
84 + }
85 +
86 + return $default;
87 + }
88 +
89 + public function setVarFiltersListing(string $varName, int $value): void
90 + {
91 + acym_setVar($varName, $value);
92 + $this->initSession();
93 + $controllerSession = acym_getVar('array', $this->sessionName, [], 'SESSION');
94 + $controllerSession[$varName] = $value;
95 + acym_setSession($this->sessionName, $controllerSession);
96 + }
97 +
98 + /**
99 + * Called using data-task
100 + */
101 + public function clearFilters(): void
102 + {
103 + acym_setSession($this->sessionName, []);
104 +
105 + $taskToCall = acym_getVar('string', 'cleartask', $this->defaulttask);
106 + if (in_array($taskToCall, ['campaigns_auto', 'welcome', 'unsubscribe', $this->defaulttask])) {
107 + $this->call($taskToCall);
108 + }
109 + }
110 +
111 + public function call(string $task, bool $isFront = false): void
112 + {
113 + if (
114 + !in_array($task, $this->publicFrontTasks, true)
115 + && !acym_isAllowed($this->name, $task)
116 + ) {
117 + acym_enqueueMessage(acym_translation('ACYM_ACCESS_DENIED'), 'warning');
118 + acym_redirect($isFront ? ACYM_LIVE : acym_completeLink('dashboard'));
119 +
120 + return;
121 + }
122 +
123 + // If task doesn't exist, redirect to default task + add message
124 + if (!is_callable([$this, $task])) {
125 + acym_enqueueMessage(acym_translation('ACYM_NON_EXISTING_PAGE'), 'warning');
126 + $task = $this->defaulttask;
127 + acym_setVar('task', $task);
128 + }
129 +
130 + // Call the task
131 + $this->$task();
132 + }
133 +
134 + public function loadScripts(string $task): void
135 + {
136 + if (empty($this->loadScripts)) return;
137 +
138 + $scripts = [];
139 + if (!empty($this->loadScripts['all'])) {
140 + $scripts = $this->loadScripts['all'];
141 + }
142 +
143 + if (!empty($task) && !empty($this->loadScripts[$task])) {
144 + $scripts = array_merge($scripts, $this->loadScripts[$task]);
145 + }
146 +
147 + if (empty($scripts)) return;
148 +
149 + if (in_array('editor-wysid', $scripts)) {
150 + acym_addStyle(false, ACYM_CSS.'editorWYSID.min.css?v='.filemtime(ACYM_MEDIA.'css'.DS.'editorWYSID.min.css'));
151 + acym_addScript(false, ACYM_JS.'editor_wysid_utils.min.js?v='.filemtime(ACYM_MEDIA.'js'.DS.'editor_wysid_utils.min.js'));
152 +
153 + acym_addScript(
154 + true,
155 + 'const ACYM_UNSPLASH_KEY = "'.addslashes($this->config->get('unsplash_key', '')).'";
156 + const ACYM_GIPHY_KEY = "'.addslashes($this->config->get('giphy_key', '')).'";
157 + const ACYM_SAVE_THUMBNAIL = '.(acym_isAdmin() ? (int)$this->config->get('save_thumbnail', 0) : 0).';'
158 + );
159 +
160 + // Automatically add editor dependencies
161 + $scripts = array_merge($scripts, ['colorpicker', 'datepicker', 'thumbnail', 'foundation-email', 'parse-css', 'vue-prism-editor', 'masonry']);
162 +
163 + if (empty($scripts['vue-applications'])) {
164 + $scripts['vue-applications'] = ['code_editor'];
165 + } else {
166 + $scripts['vue-applications'][] = 'code_editor';
167 + }
168 + }
169 +
170 + if (in_array('sankey', $scripts)) {
171 + acym_addScript(false, ACYM_JS.'libraries/sankey.min.js?v='.filemtime(ACYM_MEDIA.'js'.DS.'libraries'.DS.'sankey.min.js'));
172 + }
173 +
174 + if (in_array('colorpicker', $scripts)) {
175 + acym_addScript(false, ACYM_JS.'libraries/spectrum.min.js?v='.filemtime(ACYM_MEDIA.'js'.DS.'libraries'.DS.'spectrum.min.js'));
176 + acym_addStyle(false, ACYM_CSS.'libraries/spectrum.min.css?v='.filemtime(ACYM_MEDIA.'css'.DS.'libraries'.DS.'spectrum.min.css'));
177 + }
178 +
179 + if (in_array('datepicker', $scripts)) {
180 + if (ACYM_CMS === 'joomla') {
181 + acym_addScript(false, ACYM_JS.'libraries/moment.min.js?v='.filemtime(ACYM_MEDIA.'js'.DS.'libraries'.DS.'moment.min.js'));
182 + } else {
183 + wp_enqueue_script('moment');
184 + }
185 + acym_addScript(true, 'window.ACYM_DATE_NOW = "'.gmdate('Y-m-d\TH:i', time() + acym_getTimeOffsetCMS()).'";');
186 + }
187 +
188 + if (in_array('dtextPicker', $scripts)) {
189 + acym_addScript(false, ACYM_JS.'dtext_picker.min.js?v='.filemtime(ACYM_MEDIA.'js'.DS.'dtext_picker.min.js'));
190 + acym_addStyle(false, ACYM_CSS.'dtext_picker.min.css?v='.filemtime(ACYM_MEDIA.'css'.DS.'dtext_picker.min.css'));
191 + }
192 +
193 + if (in_array('thumbnail', $scripts)) {
194 + acym_addScript(false, ACYM_JS.'libraries/html2canvas.min.js?v='.filemtime(ACYM_MEDIA.'js'.DS.'libraries'.DS.'html2canvas.min.js'));
195 + }
196 +
197 + if (in_array('foundation-email', $scripts)) {
198 + acym_addStyle(false, ACYM_CSS.'libraries/foundation_email.min.css?v='.filemtime(ACYM_MEDIA.'css'.DS.'libraries'.DS.'foundation_email.min.css'));
199 + acym_addStyle(true, acym_getEmailCssFixes());
200 + }
201 +
202 + if (in_array('parse-css', $scripts)) {
203 + acym_addScript(false, ACYM_JS.'libraries/parse-css.min.js?v='.filemtime(ACYM_MEDIA.'js'.DS.'libraries'.DS.'parse-css.min.js'));
204 + }
205 +
206 + if (in_array('masonry', $scripts)) {
207 + acym_addScript(false, ACYM_JS.'libraries/masonry.min.js?v='.filemtime(ACYM_MEDIA.'js'.DS.'libraries'.DS.'masonry.min.js'));
208 + }
209 +
210 + if (!empty($scripts['vue-applications'])) {
211 + //vuejs javascript library
212 + acym_addScript(false, ACYM_JS.'libraries/vuejs.min.js?v='.filemtime(ACYM_MEDIA.'js'.DS.'libraries'.DS.'vuejs.min.js'));
213 + acym_addScript(false, ACYM_JS.'libraries/vue-infinite-scroll.min.js?v='.filemtime(ACYM_MEDIA.'js'.DS.'libraries'.DS.'vue-infinite-scroll.min.js'));
214 + //All the component created to use in vue app (ex: select2 component)
215 + acym_addScript(false, ACYM_JS.'vue/vue_components.min.js?v='.filemtime(ACYM_MEDIA.'js'.DS.'vue'.DS.'vue_components.min.js'));
216 + foreach ($scripts['vue-applications'] as $script) {
217 + acym_addScript(false, ACYM_JS.'vue/'.$script.'.min.js?v='.filemtime(ACYM_MEDIA.'js'.DS.'vue'.DS.$script.'.min.js'));
218 + }
219 + }
220 +
221 + if (in_array('vue-prism-editor', $scripts)) {
222 + acym_addScript(false, ACYM_JS.'libraries/prism-editor.min.js?v='.filemtime(ACYM_MEDIA.'js'.DS.'libraries'.DS.'prism-editor.min.js'));
223 + acym_addScript(false, ACYM_JS.'libraries/prism.min.js?v='.filemtime(ACYM_MEDIA.'js'.DS.'libraries'.DS.'prism.min.js'));
224 + acym_addStyle(false, ACYM_CSS.'libraries/prism.min.css?v='.filemtime(ACYM_MEDIA.'css'.DS.'libraries'.DS.'prism.min.css'));
225 + acym_addScript(false, ACYM_JS.'libraries/beautify-html.min.js?v='.filemtime(ACYM_MEDIA.'js'.DS.'libraries'.DS.'beautify-html.min.js'));
226 + }
227 + }
228 +
229 + public function setDefaultTask(string $task): void
230 + {
231 + $this->defaulttask = $task;
232 + }
233 +
234 + public function getName(): string
235 + {
236 + return $this->name;
237 + }
238 +
239 + public function display(array $data = []): void
240 + {
241 + if (acym_isAdmin()) {
242 + if (!acym_isNoTemplate()) {
243 + $data['breadcrumb'] = $this->breadcrumb;
244 + }
245 + $viewNamespace = 'AcyMailing\\Views\\';
246 + } else {
247 + $viewNamespace = 'AcyMailing\\FrontViews\\';
248 + }
249 +
250 + $viewName = ucfirst($this->getName());
251 + $viewNamespace .= $viewName.'\\'.$viewName.'View';
252 + $view = new $viewNamespace();
253 + $view->display($this, $data);
254 + }
255 +
256 + /**
257 + * Called using data-task
258 + */
259 + public function cancel(): void
260 + {
261 + acym_setVar('layout', 'listing');
262 + $this->display();
263 + }
264 +
265 + public function listing(): void
266 + {
267 + acym_setVar('layout', 'listing');
268 +
269 + $this->display();
270 + }
271 +
272 + public function edit(): void
273 + {
274 + $nextstep = acym_getVar('string', 'nextstep', '');
275 + if (empty($nextstep)) {
276 + $nextstep = acym_getVar('string', 'step', '');
277 + }
278 +
279 + if (empty($nextstep)) {
280 + acym_setVar('layout', 'edit');
281 +
282 + $this->display();
283 + } else {
284 + if (!is_callable([$this, $nextstep])) {
285 + acym_enqueueMessage(acym_translation('ACYM_NON_EXISTING_PAGE'), 'warning');
286 + $this->listing();
287 +
288 + return;
289 + }
290 +
291 + acym_setVar('step', $nextstep);
292 +
293 + $this->$nextstep();
294 + }
295 + }
296 +
297 + public function apply(): void
298 + {
299 + if (method_exists($this, 'store')) {
300 + $this->store();
301 + }
302 +
303 + $this->edit();
304 + }
305 +
306 + public function add(): void
307 + {
308 + acym_setVar('cid', []);
309 + acym_setVar('layout', 'form');
310 +
311 + $this->display();
312 + }
313 +
314 + public function save(): void
315 + {
316 + $step = acym_getVar('string', 'step', '');
317 +
318 + if (!empty($step)) {
319 + $saveMethod = 'save'.ucfirst($step);
320 + if (!method_exists($this, $saveMethod)) {
321 + die('Save method '.esc_html($saveMethod).' not found');
322 + }
323 +
324 + $this->$saveMethod();
325 +
326 + return;
327 + }
328 +
329 + if (method_exists($this, 'store')) {
330 + $this->store();
331 + }
332 +
333 + $this->listing();
334 + }
335 +
336 + public function delete(): void
337 + {
338 + wp_verify_nonce(acym_getVar('cmd', '_wpnonce'), 'acymnonce') || die('Invalid Token');
339 + $ids = acym_getVar('array', 'elements_checked', []);
340 + $allChecked = acym_getVar('string', 'checkbox_all');
341 + $currentPage = explode('_', acym_getVar('string', 'page', ''));
342 + $pageNumber = $this->getVarFiltersListing('int', end($currentPage).'_pagination_page', 1);
343 +
344 + if (!empty($ids) && !empty($this->currentClass)) {
345 + $this->currentClass->delete($ids);
346 + if ($allChecked === 'on') {
347 + $this->setVarFiltersListing(end($currentPage).'_pagination_page', $pageNumber - 1);
348 + }
349 + }
350 +
351 + if (!acym_getVar('bool', 'no_listing', false)) {
352 + $this->listing();
353 + }
354 + }
355 +
356 + public function setActive(): void
357 + {
358 + wp_verify_nonce(acym_getVar('cmd', '_wpnonce'), 'acymnonce') || die('Invalid Token');
359 + $ids = acym_getVar('array', 'elements_checked', []);
360 +
361 + if (!empty($ids) && !empty($this->currentClass)) {
362 + $this->currentClass->setActive($ids);
363 + }
364 +
365 + $this->listing();
366 + }
367 +
368 + public function setInactive(): void
369 + {
370 + wp_verify_nonce(acym_getVar('cmd', '_wpnonce'), 'acymnonce') || die('Invalid Token');
371 + $ids = acym_getVar('array', 'elements_checked', []);
372 +
373 + if (!empty($ids) && !empty($this->currentClass)) {
374 + $this->currentClass->setInactive($ids);
375 + }
376 +
377 + $this->listing();
378 + }
379 +
380 + public function getMatchingElementsFromData(array $requestData, string &$status, int &$page, string $class = ''): array
381 + {
382 + $className = 'AcyMailing\\Classes\\'.ucfirst(strtolower($class)).'Class';
383 + $classElement = empty($class) ? $this->currentClass : new $className();
384 + $matchingElement = $classElement->getMatchingElements($requestData);
385 +
386 + // No result and no search used, we revert to default listing (all)
387 + if (empty($matchingElement['elements'])) {
388 + if (!empty($status) && empty($requestData['search']) && empty($requestData['tag'])) {
389 + $status = '';
390 + $requestData['status'] = $status;
391 + } elseif (!empty($requestData['offset'])) {
392 + $page = 1;
393 + $requestData['offset'] = 0;
394 + } else {
395 + return $matchingElement;
396 + }
397 +
398 + $matchingElement = $classElement->getMatchingElements($requestData);
399 + }
400 +
401 + $matchingElement['total']->total = intval($matchingElement['total']->total);
402 +
403 + return $matchingElement;
404 + }
405 +
406 + /**
407 + * Used in front/acym.php
408 + */
409 + public function checkTaskFront(string $task = ''): void
410 + {
411 + // For cron tasks created by users on their own server, for Joomla 4
412 + if ($this->getName() === 'cron') {
413 + $task = 'cron';
414 + }
415 +
416 + if (empty($task) && !empty($this->defaulttask)) {
417 + $task = $this->defaulttask;
418 + }
419 +
420 + // Handle whitelisted tasks
421 + if (in_array($task, $this->publicFrontTasks)) {
422 + $this->$task();
423 +
424 + return;
425 + }
426 +
427 + // No front-end management for WordPress users
428 + if (empty(acym_currentUserId()) || ACYM_CMS !== 'joomla' || !acym_level(ACYM_ENTERPRISE)) {
429 + acym_redirect(acym_rootURI(), 'Front-end management not available');
430 + }
431 +
432 + // If there is no menu, someone typed the URL manually
433 + $currentMenu = acym_getMenu();
434 + if (empty($currentMenu)) {
435 + acym_redirect(acym_rootURI(), 'Direct access denied');
436 + }
437 +
438 + // We whitelist specific routes when having access to specific menus
439 + if ($this->isTaskAllowed($currentMenu->link, $task)) {
440 + $this->$task();
441 +
442 + return;
443 + }
444 +
445 + // Blacklist tasks by default
446 + acym_redirect(acym_rootURI(), 'Unknown route, access denied');
447 + }
448 +
449 + private function isTaskAllowed(string $menuUrl, string $task): bool
450 + {
451 + if (!empty($this->allowedTasks[$menuUrl]) && in_array($task, $this->allowedTasks[$menuUrl])) {
452 + return true;
453 + }
454 +
455 + if (!empty($this->menuAlias[$menuUrl])) {
456 + $menuUrl = $this->menuAlias[$menuUrl];
457 +
458 + return $this->isTaskAllowed($menuUrl, $task);
459 + }
460 +
461 + return false;
462 + }
463 +
464 + protected function prepareMultilingualOption(array &$data): void
465 + {
466 + if (!acym_isMultilingual()) return;
467 +
468 + $data['translation_languages'] = acym_getMultilingualLanguages();
469 + }
470 +}