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/Controllers/Lists/Edition.php +0 -475 11.0.1 → 11.1.1 View file →
@@ -1,475 +1,0 @@
1 -<?php
2 -
3 -namespace AcyMailing\Controllers\Lists;
4 -
5 -use AcyMailing\Classes\HistoryClass;
6 -use AcyMailing\Classes\ListClass;
7 -use AcyMailing\Classes\MailClass;
8 -use AcyMailing\Classes\MailStatClass;
9 -use AcyMailing\Classes\TagClass;
10 -use AcyMailing\Classes\UrlClickClass;
11 -use AcyMailing\Controllers\ListsController;
12 -use AcyMailing\Helpers\EntitySelectHelper;
13 -use AcyMailing\Helpers\WorkflowHelper;
14 -
15 -trait Edition
16 -{
17 - public function settings(): void
18 - {
19 - acym_setVar('layout', 'settings');
20 -
21 - $tab = acym_getVar('string', 'step', ListsController::LIST_EDITION_TABS_GENERAL);
22 -
23 - // In the front with the SEF activated, the tab is not always set
24 - if (empty($tab)) {
25 - $tab = ListsController::LIST_EDITION_TABS_GENERAL;
26 - }
27 -
28 - $data = [];
29 - $data['workflowHelper'] = new WorkflowHelper();
30 - $data['currentTab'] = $tab;
31 - $data['tabs'] = [
32 - 'general' => ListsController::LIST_EDITION_TABS_GENERAL,
33 - 'subscribers' => ListsController::LIST_EDITION_TABS_SUBSCRIBERS,
34 - 'unsubscriptions' => ListsController::LIST_EDITION_TABS_UNSUBSCRIPTIONS,
35 - ];
36 -
37 - $listId = acym_getVar('int', 'listId', 0);
38 -
39 - if (!$this->prepareListSettings($data, $listId)) return;
40 -
41 - if ($tab === ListsController::LIST_EDITION_TABS_GENERAL) {
42 - $this->prepareTagsSettings($data, $listId);
43 - $this->prepareListStat($data, $listId);
44 - $this->prepareListStatEvolution($data, $listId);
45 - $this->prepareWelcomeUnsubData($data);
46 - $this->prepareMultilingualOption($data);
47 - } elseif ($tab === ListsController::LIST_EDITION_TABS_SUBSCRIBERS) {
48 - $this->prepareSubscribersEntitySelect($data, $listId);
49 - $this->prepareSubscribersSettings($data, $listId);
50 - } elseif ($tab === ListsController::LIST_EDITION_TABS_UNSUBSCRIPTIONS) {
51 - $this->prepareUnsubReasons($data);
52 - }
53 -
54 - parent::display($data);
55 - }
56 -
57 - private function prepareListSettings(array &$data, int $listId): bool
58 - {
59 - if (empty($listId)) {
60 - $listInformation = new \stdClass();
61 - $listInformation->id = '';
62 - $listInformation->name = '';
63 - $listInformation->frontLabel = '';
64 - $listInformation->description = '';
65 - $listInformation->active = 1;
66 - $listInformation->visible = 1;
67 - $listInformation->color = '#'.implode('', [
68 - ListClass::COLOR_PARTS[acym_rand(0, 15)],
69 - ListClass::COLOR_PARTS[acym_rand(0, 15)],
70 - ListClass::COLOR_PARTS[acym_rand(0, 15)],
71 - ListClass::COLOR_PARTS[acym_rand(0, 15)],
72 - ListClass::COLOR_PARTS[acym_rand(0, 15)],
73 - ListClass::COLOR_PARTS[acym_rand(0, 15)],
74 - ]);
75 - $listInformation->welcome_id = '';
76 - $listInformation->unsubscribe_id = '';
77 - $listInformation->access = [];
78 - $listInformation->tracking = 1;
79 - $listInformation->translation = [];
80 - $listInformation->display_name = '';
81 -
82 - $this->breadcrumb[acym_translation('ACYM_NEW_LIST')] = acym_completeLink('lists&task=settings');
83 - } else {
84 - $listClass = new ListClass();
85 - $listInformation = $listClass->getOneById($listId);
86 - if (is_null($listInformation)) {
87 - acym_enqueueMessage(acym_translation('ACYM_LIST_DOESNT_EXIST'), 'error');
88 - $this->listing();
89 -
90 - return false;
91 - }
92 -
93 -
94 - $subscribersCount = $listClass->getSubscribersCountPerStatusByListIds([$listId]);
95 -
96 - $this->breadcrumb[$listInformation->name] = acym_completeLink('lists&task=settings&listId='.$listId);
97 -
98 - $listInformation->access = empty($listInformation->access) ? [] : explode(',', $listInformation->access);
99 -
100 - $currentUser = acym_currentUserId();
101 - if (!acym_isAdmin() && ($listInformation->cms_user_id != $currentUser)) {
102 - $userGroups = acym_getGroupsByUser($currentUser);
103 - $canAccess = false;
104 -
105 - foreach ($userGroups as $group) {
106 - if (in_array($group, $listInformation->access)) $canAccess = true;
107 - }
108 -
109 - if (!$canAccess) {
110 - acym_enqueueMessage(acym_translation('ACYM_YOU_DONT_HAVE_ACCESS_TO_THIS_LIST'), 'error');
111 -
112 - $this->listing();
113 -
114 - return false;
115 - }
116 - }
117 - }
118 -
119 - $listInformation->subscribers = [
120 - 'unsubscribed_users' => 0,
121 - 'sendable_users' => 0,
122 - 'unconfirmed_users' => 0,
123 - 'inactive_users' => 0,
124 - ];
125 - if (!empty($subscribersCount)) {
126 - $listStats = array_shift($subscribersCount);
127 - $listInformation->subscribers = [
128 - 'unsubscribed_users' => $listStats->unsubscribed_users,
129 - 'sendable_users' => $listStats->sendable_users,
130 - 'unconfirmed_users' => $listStats->unconfirmed_users,
131 - 'inactive_users' => $listStats->inactive_users,
132 - ];
133 - }
134 -
135 - $data['listInformation'] = $listInformation;
136 -
137 - return true;
138 - }
139 -
140 - private function prepareTagsSettings(array &$data, int $listId): void
141 - {
142 - $tagClass = new TagClass();
143 - $data['allTags'] = $tagClass->getAllTagsByType(TagClass::TYPE_LIST);
144 - $data['listTagsName'] = [];
145 - $listsTags = $tagClass->getAllTagsByElementId(TagClass::TYPE_LIST, $listId);
146 - foreach ($listsTags as $oneTag) {
147 - $data['listTagsName'][] = $oneTag;
148 - }
149 - }
150 -
151 - private function prepareSubscribersSettings(array &$data, int $listId): void
152 - {
153 - $data['ordering'] = acym_getVar('string', 'users_ordering', 'id');
154 - $data['orderingSortOrder'] = acym_getVar('string', 'users_ordering_sort_order', 'desc');
155 - $data['classSortOrder'] = $data['orderingSortOrder'] == 'asc' ? 'acymicon-sort-amount-asc' : 'acymicon-sort-amount-desc';
156 - $listClass = new ListClass();
157 - $data['subscribers'] = $listClass->getSubscribersForList(
158 - [
159 - 'listIds' => [$listId],
160 - 'offset' => 0,
161 - 'limit' => 500,
162 - 'status' => 1,
163 - 'orderBy' => $data['ordering'],
164 - 'orderBySort' => $data['orderingSortOrder'],
165 - ]
166 - );
167 - foreach ($data['subscribers'] as &$oneSub) {
168 - if ($oneSub->subscription_date == '0000-00-00 00:00:00') continue;
169 - $oneSub->subscription_date = acym_date(strtotime($oneSub->subscription_date), acym_translation('ACYM_DATE_FORMAT_LC2'));
170 - }
171 - }
172 -
173 - private function prepareSubscribersEntitySelect(array &$data, int $listId): void
174 - {
175 - if (empty($listId)) {
176 - $data['subscribersEntitySelect'] = '';
177 -
178 - return;
179 - }
180 -
181 - $data['subscribersEntitySelect'] = $listId;
182 - }
183 -
184 - private function prepareListStat(array &$data, int $listId): void
185 - {
186 - $data['listStats'] = ['deliveryRate' => 0, 'openRate' => 0, 'clickRate' => 0, 'failRate' => 0, 'bounceRate' => 0];
187 - if (empty($listId)) return;
188 - $listClass = new ListClass();
189 - $mails = $listClass->getMailsByListId($listId);
190 - if (empty($mails)) return;
191 -
192 - $mailStatClass = new MailStatClass();
193 - $mailsStat = $mailStatClass->getCumulatedStatsByMailIds($mails);
194 -
195 - if (intval($mailsStat->sent) + intval($mailsStat->fails) === 0) return;
196 -
197 - $totalSent = intval($mailsStat->sent) + intval($mailsStat->fails);
198 - if (empty($mailsStat->open)) $mailsStat->open = 0;
199 - if (empty($mailsStat->fails)) $mailsStat->fails = 0;
200 - if (empty($mailsStat->bounces)) $mailsStat->bounces = 0;
201 -
202 - $data['listStats']['openRate'] = number_format($mailsStat->open / $totalSent * 100, 2);
203 - $data['listStats']['deliveryRate'] = number_format(($mailsStat->sent - $mailsStat->bounces) / $totalSent * 100, 2);
204 - $data['listStats']['failRate'] = number_format($mailsStat->fails / $totalSent * 100, 2);
205 - $data['listStats']['bounceRate'] = number_format($mailsStat->bounces / $totalSent * 100, 2);
206 -
207 - $urlClickClass = new UrlClickClass();
208 - $nbClicks = $urlClickClass->getClickRateByMailIds($mails);
209 - $data['listStats']['clickRate'] = number_format($nbClicks / $totalSent * 100, 2);
210 - }
211 -
212 - private function prepareListStatEvolution(array &$data, int $listId): void
213 - {
214 - $data['evol'] = [];
215 - $listClass = new ListClass();
216 - $subEvolStat = $listClass->getYearSubEvolutionPerList($listId);
217 - if (empty($subEvolStat['subscribers']) && empty($subEvolStat['unsubscribers'])) return;
218 -
219 - // Init tables ordered by month number starting on month from one year ago
220 - $firstMonth = gmdate('n') + 1;
221 - $zeroReached = false;
222 - $evolSub = [];
223 - $evolUnsub = [];
224 - for ($i = 0; $i < 12; $i++) {
225 - $month = ($firstMonth + $i) % 13;
226 - if ($month == 0) $zeroReached = true;
227 - if ($zeroReached) $month += 1;
228 - $evolSub[$month] = $month.'_0';
229 - $evolUnsub[$month] = $month.'_0';
230 - }
231 -
232 - foreach ($subEvolStat['subscribers'] as $unit => $monthData) {
233 - $evolSub[$monthData->monthSub] = $monthData->monthSub.'_'.$monthData->nbUser;
234 - }
235 -
236 - foreach ($subEvolStat['unsubscribers'] as $unit => $monthData) {
237 - $evolUnsub[$monthData->monthUnsub] = $monthData->monthUnsub.'_'.$monthData->nbUser;
238 - }
239 -
240 - foreach ($evolSub as $month => $oneEvol) {
241 - $data['evol'][0][] = $oneEvol;
242 - $data['evol'][1][] = $evolUnsub[$month];
243 - }
244 - }
245 -
246 - protected function prepareWelcomeUnsubData(array &$data): void
247 - {
248 - $data['tmpls'] = [];
249 - if (empty($data['listInformation']->id)) return;
250 - $listClass = new ListClass();
251 - $mailClass = new MailClass();
252 -
253 - foreach ([MailClass::TYPE_WELCOME => 'welcome', MailClass::TYPE_UNSUBSCRIBE => 'unsub'] as $full => $short) {
254 - $mailId = acym_getVar('int', $short.'mailid', 0);
255 - if (empty($data['listInformation']->{$full.'_id'}) && !empty($mailId)) {
256 - $data['listInformation']->{$full.'_id'} = $mailId;
257 - $listInfoSave = clone $data['listInformation'];
258 - unset($listInfoSave->subscribers);
259 - $savedListId = $listClass->save($listInfoSave);
260 - if (empty($savedListId)) {
261 - acym_enqueueMessage(acym_translation('ACYM_ERROR_SAVE_LIST'), 'error');
262 - }
263 - }
264 -
265 - $returnLink = acym_completeLink('lists&task=settings&listId='.$data['listInformation']->id.'&edition=1&'.$short.'mailid={mailid}');
266 - $favoriteTemplate = $this->config->get('favorite_template', 0);
267 - $startFrom = empty($favoriteTemplate) ? '' : '&from='.$favoriteTemplate;
268 -
269 - if (empty($data['listInformation']->{$full.'_id'})) {
270 - $data['tmpls'][$short.'TmplUrl'] = acym_completeLink(
271 - 'mails&task=edit&step=editEmail&type='.$full.'&type_editor=acyEditor&list_id='.$data['listInformation']->id.'&return='.urlencode(
272 - base64_encode($returnLink)
273 - ).$startFrom
274 - );
275 - } else {
276 - $data['tmpls'][$short.'TmplUrl'] = acym_completeLink(
277 - 'mails&task=edit&id='.$data['listInformation']->{$full.'_id'}.'&type='.$full.'&list_id='.$data['listInformation']->id.'&return='.urlencode(
278 - base64_encode($returnLink)
279 - ).$startFrom
280 - );
281 - }
282 -
283 - $data['tmpls'][$full] = !empty($data['listInformation']->{$full.'_id'}) ? $mailClass->getOneById($data['listInformation']->{$full.'_id'}) : '';
284 - }
285 - }
286 -
287 - public function unsetMail(string $type): void
288 - {
289 - wp_verify_nonce(acym_getVar('cmd', '_wpnonce'), 'acymnonce') || die('Invalid Token');
290 -
291 - $listClass = new ListClass();
292 - $id = acym_getVar('int', 'listId', 0);
293 - $list = $listClass->getOneById($id);
294 -
295 - if (empty($list)) {
296 - acym_enqueueMessage(acym_translation('ACYM_ERROR_SAVE_LIST'), 'error');
297 - $this->listing();
298 -
299 - return;
300 - }
301 -
302 - if (!$listClass->hasUserAccess($id)) {
303 - die('Access denied for list '.esc_html($id));
304 - }
305 -
306 - $list->$type = null;
307 -
308 - $savedListId = $listClass->save($list);
309 - if (!empty($savedListId)) {
310 - acym_setVar('listId', $id);
311 - $this->settings();
312 - } else {
313 - acym_enqueueMessage(acym_translation('ACYM_ERROR_SAVE_LIST'), 'error');
314 - $this->listing();
315 - }
316 - }
317 -
318 - public function unsetWelcome(): void
319 - {
320 - $this->unsetMail('welcome_id');
321 - }
322 -
323 - public function unsetUnsubscribe(): void
324 - {
325 - $this->unsetMail('unsubscribe_id');
326 - }
327 -
328 - public function apply(): void
329 - {
330 - $this->save(false);
331 - }
332 -
333 - public function save(bool $goToListing = true): void
334 - {
335 - wp_verify_nonce(acym_getVar('cmd', '_wpnonce'), 'acymnonce') || die('Invalid Token');
336 -
337 - $step = acym_getVar('string', 'step');
338 - if ($step === self::LIST_EDITION_TABS_GENERAL) {
339 - $listClass = new ListClass();
340 - $formData = (object)acym_getVar('array', 'list', []);
341 -
342 - $listId = acym_getVar('int', 'listId', 0);
343 - if (!empty($listId)) {
344 - $formData->id = $listId;
345 - }
346 -
347 - $allowedFields = acym_getColumns('list');
348 - $listInformation = new \stdClass();
349 - if (empty($formData->welcome_id)) unset($formData->welcome_id);
350 - if (empty($formData->unsubscribe_id)) unset($formData->unsubscribe_id);
351 - foreach ($formData as $name => $data) {
352 - if (!in_array($name, $allowedFields)) {
353 - continue;
354 - }
355 - $listInformation->{$name} = $data;
356 - }
357 -
358 - $listInformation->tags = acym_getVar('array', 'list_tags', []);
359 -
360 - if (acym_isAdmin()) {
361 - $listInformation->access = empty($listInformation->access) ? '' : ','.implode(',', $listInformation->access).',';
362 - } elseif (!empty($formData->id) && !$listClass->hasUserAccess($formData->id)) {
363 - die('Cannot save list '.esc_html($formData->id));
364 - }
365 -
366 - $listId = $listClass->save($listInformation);
367 -
368 - if (!empty($listId)) {
369 - acym_setVar('listId', $listId);
370 - acym_enqueueMessage(acym_translationSprintf('ACYM_LIST_IS_SAVED', $listInformation->name), 'success');
371 - $this->saveSubscribersTolist();
372 - } else {
373 - acym_enqueueMessage(acym_translation('ACYM_ERROR_SAVING'), 'error');
374 - if (!empty($listClass->errors)) {
375 - acym_enqueueMessage($listClass->errors, 'error');
376 - }
377 - }
378 - }
379 -
380 - if ($goToListing) {
381 - $this->listing();
382 - } else {
383 - $this->settings();
384 - }
385 - }
386 -
387 - private function saveSubscribersTolist(): bool
388 - {
389 - $selected = acym_getVar('string', 'acym__entity_select__selected', '[]');
390 - $unselected = acym_getVar('string', 'acym__entity_select__unselected', '[]');
391 - $usersIds = json_decode(empty($selected) ? '[]' : $selected, true);
392 - $usersIdsUnselected = json_decode(empty($unselected) ? '[]' : $unselected, true);
393 - $listId = acym_getVar('int', 'listId', 0);
394 -
395 - $listClass = new ListClass();
396 - if (empty($listId) || !$listClass->hasUserAccess($listId)) return false;
397 -
398 - acym_arrayToInteger($usersIdsUnselected);
399 - if (!empty($usersIdsUnselected)) {
400 - acym_query(
401 - 'UPDATE #__acym_user_has_list
402 - SET status = 0, unsubscribe_date = '.acym_escapeDB(acym_date(time(), 'Y-m-d H:i:s')).'
403 - WHERE list_id = '.intval($listId).'
404 - AND user_id IN ('.implode(', ', $usersIdsUnselected).')'
405 - );
406 - }
407 -
408 - acym_arrayToInteger($usersIds);
409 - if (!empty($usersIds)) {
410 - acym_query(
411 - 'INSERT IGNORE #__acym_user_has_list (`user_id`, `list_id`, `status`, `subscription_date`) (SELECT id, '.intval($listId).', 1, '.acym_escapeDB(
412 - acym_date(time(), 'Y-m-d H:i:s')
413 - ).' FROM #__acym_user AS user WHERE user.id IN ('.implode(', ', $usersIds).')) ON DUPLICATE KEY UPDATE status = 1'
414 - );
415 - }
416 -
417 - return true;
418 - }
419 -
420 - public function saveSubscribers(): void
421 - {
422 - wp_verify_nonce(acym_getVar('cmd', '_wpnonce'), 'acymnonce') || die('Invalid Token');
423 -
424 - $this->saveSubscribersTolist();
425 - $listId = acym_getVar('int', 'listId', 0);
426 - acym_setVar('listId', $listId);
427 -
428 - $this->settings();
429 - }
430 -
431 - private function sortDataByList(array $data): array
432 - {
433 - $sortedData = [];
434 -
435 - foreach ($data as $entry) {
436 - $pattern = '/(?<!EXECUTED_BY::)\b\d+\b/';
437 - preg_match_all($pattern, $entry->data, $listNumbers);
438 -
439 - foreach ($listNumbers[0] as $listNumber) {
440 - if (!isset($sortedData[$listNumber])) {
441 - $sortedData[$listNumber] = [];
442 - }
443 -
444 - $sortedData[$listNumber][] = $entry->unsubscribe_reason;
445 - }
446 - }
447 -
448 - return $sortedData;
449 - }
450 -
451 - private function prepareUnsubReasons(array &$data): void
452 - {
453 - $historyClass = new HistoryClass();
454 - $allReasonsData = $historyClass->getAllUnsubReasons();
455 -
456 - $sortedData = $this->sortDataByList($allReasonsData);
457 - $listId = acym_getVar('int', 'listId', 0);
458 - $currentListData = $sortedData[$listId] ?? [];
459 - $reasonCounts = array_count_values($currentListData);
460 -
461 - $allAnswers = $historyClass->getAllMainLanguageUnsubReasons();
462 - $newReasonCounts = [];
463 - foreach ($reasonCounts as $key => $value) {
464 - if (is_numeric($key) && isset($allAnswers[$key - 1])) {
465 - $newReasonCounts[$allAnswers[$key - 1]] = $value;
466 - } else {
467 - $newReasonCounts[$key] = $value;
468 - }
469 - }
470 -
471 - arsort($newReasonCounts);
472 -
473 - $data['unsubReasons'] = $newReasonCounts;
474 - }
475 -}