PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / 10.2.2
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress v10.2.2
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
acymailing / back / Classes / ListClass.php

ListClass.php in AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress 10.2.2, at back/Classes/ListClass.php

1,018 lines 34.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace AcyMailing\Classes;
4
5 use AcyMailing\Helpers\MailerHelper;
6 use AcyMailing\Helpers\PaginationHelper;
7 use AcyMailing\Core\AcymClass;
8
9 class ListClass extends AcymClass
10 {
11 const LIST_TYPE_STANDARD = 'standard';
12 const LIST_TYPE_FRONT = 'front';
13 const LIST_TYPE_FOLLOWUP = 'followup';
14
15 public function __construct()
16 {
17 parent::__construct();
18
19 $this->table = 'list';
20 $this->pkey = 'id';
21 }
22
23 public function getMatchingElements(array $settings = []): array
24 {
25 $columns = 'list.*';
26 if (!empty($settings['columns'])) {
27 foreach ($settings['columns'] as $key => $value) {
28 if ($value == 'lists.list_id') {
29 unset($settings['columns'][$key]);
30 continue;
31 }
32 $settings['columns'][$key] = $key === 'join' ? $value : 'list.'.$value;
33 }
34 $columns = implode(', ', $settings['columns']);
35 }
36
37 $query = 'SELECT '.$columns.' FROM #__acym_list AS list';
38 $queryCount = 'SELECT COUNT(list.id) AS total FROM #__acym_list AS list';
39 if (!empty($settings['join'])) $query .= $this->getJoinForQuery($settings['join']);
40 $queryStatus = 'SELECT COUNT(id) AS number, active + (visible*2) AS score FROM #__acym_list AS list';
41 $filters = [];
42 $listsId = [];
43
44 if (!empty($settings['tag'])) {
45 $tagJoin = ' JOIN #__acym_tag AS tag ON list.id = tag.id_element';
46 $query .= $tagJoin;
47 $queryCount .= $tagJoin;
48 $queryStatus .= $tagJoin;
49 $filters[] = 'tag.name = '.acym_escapeDB($settings['tag']);
50 $filters[] = 'tag.type = "list"';
51 }
52
53 if (!empty($settings['search'])) {
54 $filters[] = 'list.name LIKE '.acym_escapeDB('%'.$settings['search'].'%');
55 }
56
57 if (!empty($settings['creator_id']) && !acym_isAdmin()) {
58 $userGroups = acym_getGroupsByUser($settings['creator_id']);
59 $groupCondition = '(list.access LIKE "%,'.implode(',%" OR list.access LIKE "%,', $userGroups).',%")';
60
61 $filters[] = 'list.cms_user_id = '.intval($settings['creator_id']).' OR '.$groupCondition.'';
62 }
63
64 $filters[] = 'list.type = '.acym_escapeDB(self::LIST_TYPE_STANDARD);
65
66 if (!empty($filters)) {
67 $queryStatus .= ' WHERE ('.implode(') AND (', $filters).')';
68 }
69
70 if (!empty($settings['status'])) {
71 $allowedStatus = [
72 'active' => 'active = 1',
73 'inactive' => 'active = 0',
74 'visible' => 'visible = 1',
75 'invisible' => 'visible = 0',
76 ];
77 if (empty($allowedStatus[$settings['status']])) {
78 die('Injection denied');
79 }
80 $filters[] = 'list.'.$allowedStatus[$settings['status']];
81 }
82
83 if (!empty($settings['where'])) {
84 $filters[] = $settings['where'];
85 }
86
87
88 if (!empty($filters)) {
89 $query .= ' WHERE ('.implode(') AND (', $filters).')';
90 $queryCount .= ' WHERE ('.implode(') AND (', $filters).')';
91 }
92
93 if (!empty($settings['ordering']) && !empty($settings['ordering_sort_order'])) {
94 $query .= ' ORDER BY list.'.acym_secureDBColumn($settings['ordering']).' '.acym_secureDBColumn(strtoupper($settings['ordering_sort_order']));
95 }
96
97 if (empty($settings['offset']) || $settings['offset'] < 0) {
98 $settings['offset'] = 0;
99 }
100
101 if (empty($settings['elementsPerPage']) || $settings['elementsPerPage'] < 1) {
102 $pagination = new PaginationHelper();
103 $settings['elementsPerPage'] = $pagination->getListLimit();
104 }
105
106 $results['elements'] = acym_loadObjectList($query, '', $settings['offset'], $settings['elementsPerPage']);
107 if (!empty($settings['join'])) {
108 $this->setSelectedList($results['elements'], $settings['join']);
109 }
110 foreach ($results['elements'] as $i => $oneList) {
111 array_push($listsId, $oneList->id);
112 $results['elements'][$i]->sendable_users = 0;
113 $results['elements'][$i]->unconfirmed_users = 0;
114 $results['elements'][$i]->unsubscribed_users = 0;
115 $results['elements'][$i]->inactive_users = 0;
116 $results['elements'][$i]->newSub = 0;
117 $results['elements'][$i]->newUnsub = 0;
118 }
119
120 $countUserByList = [];
121 $countEvolByList = [];
122 if (!empty($listsId) && empty($settings['entitySelect'])) {
123 $countUserByList = $this->getSubscribersCountPerStatusByListId($listsId);
124 $countEvolByList = $this->getSubscribersEvolutionByList($listsId);
125 }
126
127 foreach ($results['elements'] as $i => $list) {
128 $results['elements'][$i]->tags = [];
129 foreach ($countUserByList as $userList) {
130 if ($list->id == $userList->list_id) {
131 $results['elements'][$i]->sendable_users = $userList->sendable_users;
132 $results['elements'][$i]->unconfirmed_users = $userList->unconfirmed_users;
133 $results['elements'][$i]->unsubscribed_users = $userList->unsubscribed_users;
134 $results['elements'][$i]->inactive_users = $userList->inactive_users;
135 }
136 }
137 if (isset($countEvolByList[$list->id]->newSub)) $results['elements'][$i]->newSub = $countEvolByList[$list->id]->newSub;
138 if (isset($countEvolByList[$list->id]->newUnsub)) $results['elements'][$i]->newUnsub = $countEvolByList[$list->id]->newUnsub;
139 }
140
141 $results['total'] = acym_loadObject($queryCount);
142
143 $listsPerStatus = acym_loadObjectList($queryStatus.' GROUP BY score', 'score');
144 for ($i = 0 ; $i < 4 ; $i++) {
145 $listsPerStatus[$i] = empty($listsPerStatus[$i]) ? 0 : $listsPerStatus[$i]->number;
146 }
147
148 $results['status'] = [
149 'all' => array_sum($listsPerStatus),
150 'active' => $listsPerStatus[1] + $listsPerStatus[3],
151 'inactive' => $listsPerStatus[0] + $listsPerStatus[2],
152 'visible' => $listsPerStatus[2] + $listsPerStatus[3],
153 'invisible' => $listsPerStatus[0] + $listsPerStatus[1],
154 ];
155
156 return $results;
157 }
158
159 public function getOneById($id)
160 {
161 $list = parent::getOneById($id);
162
163 if (!empty($list)) {
164 $list->translation = empty($list->translation) ? [] : json_decode($list->translation, true);
165 }
166
167 return $list;
168 }
169
170 private function setSelectedList(&$elements, $join)
171 {
172 if (strpos($join, 'join_list') !== false) {
173 $listsIds = explode('-', $join);
174 $listsIds = $listsIds[1];
175 $listsIds = explode(',', $listsIds);
176 foreach ($elements as $key => $element) {
177 $elements[$key]->list_id = in_array($element->id, $listsIds) ? $element->id : null;
178 }
179 }
180 }
181
182 public function getJoinForQuery($joinType)
183 {
184 if (strpos($joinType, 'join_mail') !== false) {
185 $mailId = explode('-', $joinType);
186
187 return ' LEFT JOIN #__acym_mail_has_list as maillist ON list.id = maillist.list_id AND maillist.mail_id = '.intval($mailId[1]);
188 }
189 if (strpos($joinType, 'join_user') !== false) {
190 $userId = explode('-', $joinType);
191
192 return ' LEFT JOIN #__acym_user_has_list as userlist ON list.id = userlist.list_id AND userlist.status = 1 AND userlist.user_id = '.intval($userId[1]);
193 }
194
195 return '';
196 }
197
198 public function getListsWithIdNameCount(array $settings): array
199 {
200 $filters = [];
201
202 if (isset($settings['ids'])) {
203 if (empty($settings['ids'])) {
204 return ['lists' => [], 'total' => 0];
205 } else {
206 acym_arrayToInteger($settings['ids']);
207 $filters[] = 'list.id IN ('.implode(',', $settings['ids']).')';
208 }
209 }
210
211 $query = 'SELECT list.id, list.name, list.color, list.active, COUNT(user.id) AS subscribers
212 FROM #__acym_list AS list
213 LEFT JOIN #__acym_user_has_list AS userList
214 ON list.id = userList.list_id
215 AND userList.status = 1
216 LEFT JOIN #__acym_user AS user
217 ON user.id = userList.user_id
218 AND user.active = 1 ';
219
220 if (intval($this->config->get('require_confirmation', 1)) === 1) {
221 $query .= ' AND user.confirmed = 1 ';
222 }
223
224 $queryCount = 'SELECT COUNT(list.id) FROM #__acym_list AS list';
225
226 if (!acym_isAdmin()) {
227 $currentUserId = acym_currentUserId();
228 if (empty($currentUserId)) {
229 return [
230 'lists' => [],
231 'total' => 0,
232 ];
233 }
234
235 $userGroups = acym_getGroupsByUser($currentUserId);
236 $groupCondition = '(list.access LIKE "%,'.implode(',%" OR list.access LIKE "%,', $userGroups).',%")';
237
238 $filters[] = 'list.cms_user_id = '.intval($currentUserId).' OR '.$groupCondition;
239 }
240
241 if (!empty($settings['search'])) {
242 $filters[] = 'list.name LIKE '.acym_escapeDB('%'.$settings['search'].'%');
243 }
244
245 if (!empty($settings['already'])) {
246 acym_arrayToInteger($settings['already']);
247 $filters[] = 'list.id NOT IN('.implode(',', $settings['already']).')';
248 }
249 $filters[] = 'list.type = '.acym_escapeDB(self::LIST_TYPE_STANDARD);
250
251 if (!empty($filters)) {
252 $query .= ' WHERE ('.implode(') AND (', $filters).')';
253 $queryCount .= ' WHERE ('.implode(') AND (', $filters).')';
254 }
255
256 $query .= ' GROUP BY list.id ';
257
258 return [
259 'lists' => acym_loadObjectList($query, '', $settings['offset'], $settings['listsPerPage']),
260 'total' => (int)acym_loadResult($queryCount),
261 ];
262 }
263
264 public function getOneByName($name)
265 {
266 return acym_loadObject('SELECT * FROM #__acym_list WHERE `name` = '.acym_escapeDB($name));
267 }
268
269 public function getListsByIds($ids)
270 {
271 if (!is_array($ids)) $ids = [$ids];
272 acym_arrayToInteger($ids);
273 if (empty($ids)) return [];
274
275 $query = 'SELECT * FROM #__acym_list WHERE id IN ('.implode(', ', $ids).')';
276
277 return acym_loadObjectList($query);
278 }
279
280 public function getAllListUsers()
281 {
282 $query = 'SELECT #__acym_user_has_list.list_id, count(*)
283 FROM #__acym_list AS list
284 JOIN #__acym_user_has_list
285 ON list.id = #__acym_user_has_list.list_id
286 JOIN #__acym_user
287 ON #__acym_user.id = #__acym_user_has_list.user_id
288 GROUP BY list.id';
289
290 return acym_loadObjectList($query);
291 }
292
293 public function getSubscribersCountByListId($id)
294 {
295 $confirmed = $this->config->get('require_confirmation', 1) == 1 ? ' AND users.confirmed = 1 ' : '';
296
297 $query = 'SELECT COUNT(userLists.user_id) AS subscribers
298 FROM #__acym_user_has_list AS userLists
299 JOIN #__acym_user AS users ON userLists.user_id = users.id
300 WHERE userLists.list_id = '.intval($id).'
301 AND userLists.status = 1
302 AND users.active = 1 '.$confirmed.'
303 GROUP BY userLists.list_id';
304
305 $result = acym_loadResult($query);
306
307 return empty($result) ? 0 : $result;
308 }
309
310 public function getSubscribersCount($listsIds)
311 {
312 acym_arrayToInteger($listsIds);
313 if (empty($listsIds)) return 0;
314
315 $query = 'SELECT COUNT(DISTINCT user.id)
316 FROM #__acym_user AS user
317 JOIN #__acym_user_has_list AS userList ON user.id = userList.user_id
318 WHERE userList.list_id IN ('.implode(",", $listsIds).') AND userList.status = 1 AND user.active = 1';
319
320 if ($this->config->get('require_confirmation', 1) == 1) {
321 $query .= ' AND user.confirmed = 1';
322 }
323
324 return acym_loadResult($query);
325 }
326
327 public function getSubscribersIdsById($listId, $returnUnsubscribed = false)
328 {
329 $query = 'SELECT user_id FROM #__acym_user_has_list WHERE list_id = '.intval($listId);
330
331 if (!$returnUnsubscribed) {
332 $query .= ' AND status = 1';
333 }
334
335 return acym_loadResultArray($query);
336 }
337
338 public function getSubscribersForList(array $options = [])
339 {
340 $listIds = $options['listIds'] ?? [];
341 $offset = $options['offset'] ?? 0;
342 $limit = $options['limit'] ?? 100;
343 $status = $options['status'] ?? null;
344 $orderBy = $options['orderBy'] ?? '';
345 $orderBySort = $options['orderBySort'] ?? '';
346 $subscribedAfter = $options['subscribed_after'] ?? null;
347 $unsubscribedAfter = $options['unsubscribed_after'] ?? null;
348
349 if (empty($listIds)) {
350 return [];
351 }
352
353 acym_arrayToInteger($listIds);
354
355 $statusCondition = '';
356 if (!is_null($status)) {
357 $statusCondition .= ' AND user_list.status = '.intval($status);
358 }
359
360 if (!empty($subscribedAfter)) {
361 $statusCondition .= ' AND user_list.subscription_date > '.acym_escapeDB($subscribedAfter);
362 }
363
364 if (!empty($unsubscribedAfter)) {
365 $statusCondition .= ' AND user_list.unsubscribe_date > '.acym_escapeDB($unsubscribedAfter);
366 }
367
368 $requestSub = 'SELECT user.*, user_list.status, user_list.subscription_date, user_list.unsubscribe_date FROM #__acym_user AS user';
369 $requestSub .= ' LEFT JOIN #__acym_user_has_list AS user_list ON user.id = user_list.user_id';
370 $requestSub .= ' WHERE user.active = 1 AND user_list.list_id IN ('.implode(', ', $listIds).')'.$statusCondition;
371
372 if (!empty($orderBy)) {
373 if (empty($orderBySort)) $orderBySort = 'desc';
374 $requestSub .= ' ORDER BY '.acym_secureDBColumn($orderBy).' '.acym_secureDBColumn($orderBySort);
375 }
376
377 return acym_loadObjectList(
378 $requestSub,
379 '',
380 $offset,
381 $limit
382 );
383 }
384
385 public function delete($elements, $force = false)
386 {
387 if (!is_array($elements)) $elements = [$elements];
388 if (!$force) {
389 $this->onlyManageableLists($elements);
390 }
391
392 if (empty($elements)) return 0;
393
394 foreach ($elements as $id) {
395 acym_query('DELETE FROM #__acym_mail_has_list WHERE list_id = '.intval($id));
396 acym_query('DELETE FROM #__acym_user_has_list WHERE list_id = '.intval($id));
397 acym_query('DELETE FROM #__acym_tag WHERE `id_element` = '.intval($id).' AND `type` = "list"');
398 }
399
400 return parent::delete($elements);
401 }
402
403 public function synchDeleteCmsList($userId)
404 {
405 $query = 'SELECT * FROM #__acym_list WHERE type = "'.self::LIST_TYPE_FRONT.'" AND cms_user_id = '.intval($userId);
406 $listFrontManagement = acym_loadObject($query);
407 if (!empty($listFrontManagement)) $this->delete([$listFrontManagement->id]);
408 }
409
410 public function save($list)
411 {
412 if (isset($list->tags)) {
413 $tags = $list->tags;
414 unset($list->tags);
415 }
416
417 $oldList = null;
418
419 if (empty($list->id)) {
420 if (empty($list->cms_user_id)) {
421 $list->cms_user_id = acym_currentUserId();
422 }
423
424 $list->creation_date = acym_date('now', 'Y-m-d H:i:s', false);
425 } else {
426 $oldList = $this->getOneById($list->id);
427 }
428
429 if (!empty($list->translation)) {
430 if (is_array($list->translation)) $list->translation = json_encode($list->translation);
431 } else {
432 $list->translation = '';
433 }
434
435 foreach ($list as $oneAttribute => $value) {
436 if (empty($value)) continue;
437
438 $list->$oneAttribute = strip_tags($value);
439 }
440
441 if (empty($list->description)) {
442 $list->description = '';
443 }
444
445 if (!isset($list->access) && empty($list->id)) {
446 $list->access = '';
447 }
448
449 if (empty($list->id)) {
450 acym_trigger('onAcymBeforeListCreate', [&$list]);
451 } else {
452 acym_trigger('onAcymBeforeListModify', [&$list]);
453 }
454
455 $listID = parent::save($list);
456
457 if (!empty($listID) && isset($tags)) {
458 $tagClass = new TagClass();
459 $tagClass->setTags(TagClass::TYPE_LIST, intval($listID), $tags);
460 }
461
462 $list->id = $listID;
463
464 if (is_null($oldList)) {
465 acym_trigger('onAcymAfterListCreate', [&$list]);
466 } else {
467 acym_trigger('onAcymAfterListModify', [&$list, &$oldList]);
468 }
469
470 return $listID;
471 }
472
473 public function getAllWithIdName(): array
474 {
475 $endQuery = '';
476 if (!acym_isAdmin()) {
477 $creatorId = acym_currentUserId();
478
479 $userGroups = acym_getGroupsByUser($creatorId);
480 $groupCondition = '(access LIKE "%,'.implode(',%" OR access LIKE "%,', $userGroups).',%")';
481
482 $endQuery = ' AND (cms_user_id = '.intval($creatorId).' OR '.$groupCondition.')';
483 }
484 $lists = acym_loadObjectList('SELECT id, name FROM #__acym_list WHERE type = '.acym_escapeDB(self::LIST_TYPE_STANDARD).$endQuery, 'id');
485
486 $listsToReturn = [];
487
488 foreach ($lists as $key => $list) {
489 $listsToReturn[$key] = $list->name;
490 }
491
492 return $listsToReturn;
493 }
494
495 public function getAllForSelect($emptyFirst = true, $userFrontID = 0, $needTranslation = false, $needFrontLabel = false)
496 {
497 $groupCondition = '';
498 if (!empty($userFrontID)) {
499 $userGroups = acym_getGroupsByUser($userFrontID);
500 $groupCondition = ' AND (cms_user_id = '.intval($userFrontID).' OR (access LIKE "%,'.implode(',%" OR access LIKE "%,', $userGroups).',%"))';
501 }
502
503 $lists = acym_loadObjectList('SELECT * FROM #__acym_list WHERE type = '.acym_escapeDB(self::LIST_TYPE_STANDARD).$groupCondition, 'id');
504
505 if (acym_isMultilingual() && $needTranslation) {
506 $lists = $this->getTranslatedNameDescription($lists);
507 }
508
509 $return = [];
510
511 if ($emptyFirst) $return[''] = acym_translation('ACYM_SELECT_A_LIST');
512
513 foreach ($lists as $key => $list) {
514 $return[$key] = $needFrontLabel && !empty($list->display_name) ? $list->display_name : $list->name;
515 }
516
517 return $return;
518 }
519
520 public function getAllWithoutManagement($needTranslation = false)
521 {
522 $lists = acym_loadObjectList('SELECT * FROM #__acym_list WHERE `type` = '.acym_escapeDB(self::LIST_TYPE_STANDARD), 'id');
523
524 if (acym_isMultilingual() && $needTranslation) {
525 $lists = $this->getTranslatedNameDescription($lists);
526 }
527
528 return $lists;
529 }
530
531 public function getTranslatedNameDescription($lists)
532 {
533 $currentLanguageTag = acym_getLanguageTag();
534 foreach ($lists as $id => $list) {
535 if (empty($list->translation)) continue;
536
537 $list->translation = json_decode($list->translation, true);
538 if (!empty($list->translation[$currentLanguageTag])) {
539 if (!empty($list->translation[$currentLanguageTag]['name'])) {
540 $lists[$id]->name = $list->translation[$currentLanguageTag]['name'];
541 }
542
543 if (!empty($list->translation[$currentLanguageTag]['display_name'])) {
544 $lists[$id]->display_name = $list->translation[$currentLanguageTag]['display_name'];
545 }
546
547 if (!empty($list->translation[$currentLanguageTag]['description'])) {
548 $lists[$id]->description = $list->translation[$currentLanguageTag]['description'];
549 }
550 }
551 }
552
553 return $lists;
554 }
555
556 public function sendWelcome(int $userID, array $listIDs, bool $forceFront = false)
557 {
558 if (!$forceFront && acym_isAdmin()) {
559 return;
560 }
561
562 acym_arrayToInteger($listIDs);
563 if (empty($listIDs)) {
564 return;
565 }
566
567 $messages = acym_loadObjectList('SELECT `welcome_id` FROM #__acym_list WHERE `id` IN ('.implode(',', $listIDs).') AND `active` = 1');
568
569 if (empty($messages)) {
570 return;
571 }
572
573 $alreadySent = [];
574 $mailerHelper = new MailerHelper();
575 $mailerHelper->report = (bool)$this->config->get('welcome_message', 1);
576 foreach ($messages as $oneMessage) {
577 $mailid = $oneMessage->welcome_id;
578 if (empty($mailid)) continue;
579
580 if (isset($alreadySent[$mailid])) {
581 continue;
582 }
583
584 $mailerHelper->trackEmail = true;
585 $mailerHelper->sendOne($mailid, $userID);
586 $alreadySent[$mailid] = true;
587 }
588 }
589
590 public function sendUnsubscribe($userID, $listIDs)
591 {
592 if (acym_isAdmin()) {
593 return;
594 }
595
596 acym_arrayToInteger($listIDs);
597 if (empty($listIDs)) {
598 return;
599 }
600
601 $messages = acym_loadObjectList('SELECT `unsubscribe_id` FROM #__acym_list WHERE `id` IN ('.implode(',', $listIDs).') AND `active` = 1');
602
603 if (empty($messages)) {
604 return;
605 }
606
607 $alreadySent = [];
608 $mailerHelper = new MailerHelper();
609 $mailerHelper->report = (bool)$this->config->get('unsub_message', 1);
610 foreach ($messages as $oneMessage) {
611 if (!empty($oneMessage->unsubscribe_id)) {
612 $mailid = $oneMessage->unsubscribe_id;
613
614 if (isset($alreadySent[$mailid])) {
615 continue;
616 }
617
618 $mailerHelper->trackEmail = true;
619 $mailerHelper->sendOne($mailid, $userID);
620 $alreadySent[$mailid] = true;
621 }
622 }
623 }
624
625 public function addDefaultList()
626 {
627 $listId = acym_loadResult('SELECT `id` FROM #__acym_list LIMIT 1');
628 if (empty($listId)) {
629 $defaultList = new \stdClass();
630 $defaultList->name = 'Newsletters';
631 $defaultList->color = '#3366ff';
632 $defaultList->description = '';
633
634 $this->save($defaultList);
635 }
636 }
637
638
639 public function getTotalSubCount($ids)
640 {
641 if (empty($ids)) {
642 return 0;
643 }
644
645 acym_arrayToInteger($ids);
646 $this->onlyManageableLists($ids);
647 $query = 'SELECT COUNT(DISTINCT hasList.user_id)
648 FROM #__acym_user_has_list AS hasList
649 JOIN #__acym_user AS user
650 ON hasList.user_id = user.id
651 WHERE hasList.status = 1
652 AND user.active = 1
653 AND hasList.list_id IN ('.implode(',', $ids).')';
654
655
656 if ($this->config->get('require_confirmation', 1) == 1) {
657 $query .= ' AND user.confirmed = 1 ';
658 }
659
660 return intval(acym_loadResult($query));
661 }
662
663 public function getMailsByListId($listId)
664 {
665 $query = 'SELECT mail_id FROM #__acym_mail_has_list WHERE list_id = '.intval($listId);
666
667 return acym_loadResultArray($query);
668 }
669
670 public function getSubscribersCountPerStatusByListId($listIds = [])
671 {
672 $condList = '';
673 if (!empty($listIds)) {
674 if (!is_array($listIds)) $listIds = [$listIds];
675 acym_arrayToInteger($listIds);
676 $condList = 'AND userList.list_id IN ('.implode(',', $listIds).')';
677 }
678
679 $query = 'SELECT userList.list_id, COUNT(userList.user_id) AS users, acyuser.confirmed + acyuser.active*2 AS score
680 FROM #__acym_user_has_list AS userList
681 JOIN #__acym_user AS acyuser
682 ON acyuser.id = userList.user_id
683 WHERE userList.status = 1
684 '.$condList.'
685 GROUP BY score, userList.list_id';
686 $results = acym_loadObjectList($query);
687
688 $confirmationRequired = $this->config->get('require_confirmation', 1);
689 $listsUserStats = [];
690 foreach ($results as $oneResult) {
691 if (!isset($listsUserStats[$oneResult->list_id])) {
692 $listsUserStats[$oneResult->list_id] = $this->initList($oneResult->list_id);
693 }
694
695 $oneResult->score = (string)$oneResult->score;
696
697 if (in_array($oneResult->score, ['0', '1'])) {
698 $listsUserStats[$oneResult->list_id]->inactive_users += $oneResult->users;
699 }
700
701 if (in_array($oneResult->score, ['0', '2'])) {
702 $listsUserStats[$oneResult->list_id]->unconfirmed_users += $oneResult->users;
703 }
704
705 if ($oneResult->score === '3' || ($confirmationRequired != 1 && $oneResult->score == '2')) {
706 $listsUserStats[$oneResult->list_id]->sendable_users += $oneResult->users;
707 }
708 }
709
710 $query = 'SELECT userList.list_id, COUNT(userList.user_id) AS users
711 FROM #__acym_user_has_list AS userList
712 WHERE userList.status = 0
713 '.$condList.'
714 GROUP BY userList.list_id';
715 $unsubscribed = acym_loadObjectList($query);
716
717 foreach ($unsubscribed as $oneList) {
718 if (!isset($listsUserStats[$oneList->list_id])) {
719 $listsUserStats[$oneList->list_id] = $this->initList($oneList->list_id);
720 }
721 $listsUserStats[$oneList->list_id]->unsubscribed_users = $oneList->users;
722 }
723
724 return $listsUserStats;
725 }
726
727 public function getSubscribersEvolutionByList($listIds)
728 {
729 $condList = '';
730 if (!empty($listIds)) {
731 if (!is_array($listIds)) $listIds = [$listIds];
732 acym_arrayToInteger($listIds);
733 $condList = ' AND list_id IN ('.implode(',', $listIds).')';
734 }
735 $dateNow = acym_loadResult('SELECT DATE_SUB(NOW(), INTERVAL 1 MONTH)');
736 $queryEvolSub = 'SELECT list_id, COUNT(*) AS newSub FROM #__acym_user_has_list';
737 $queryEvolSub .= ' WHERE subscription_date > '.acym_escapeDB($dateNow).' '.$condList;
738 $queryEvolSub .= ' GROUP BY list_id';
739 $evolSubscibers = acym_loadObjectList($queryEvolSub, 'list_id');
740
741 $queryEvolUnsub = 'SELECT list_id, COUNT(*) AS newUnsub FROM #__acym_user_has_list';
742 $queryEvolUnsub .= ' WHERE unsubscribe_date > '.acym_escapeDB($dateNow).' '.$condList;
743 $queryEvolUnsub .= ' GROUP BY list_id';
744 $newUnsubscribers = acym_loadObjectList($queryEvolUnsub, 'list_id');
745
746 foreach ($newUnsubscribers as $listId => $oneUnsub) {
747 if (empty($evolSubscibers[$listId])) $evolSubscibers[$listId] = new \stdClass();
748 $evolSubscibers[$listId]->newUnsub = $oneUnsub->newUnsub;
749 }
750
751 return $evolSubscibers;
752 }
753
754 public function getYearSubEvolutionPerList($listId)
755 {
756 $listId = intval($listId);
757 $month = date('n') + 1;
758 $year = date('Y') - 1;
759 $initDate = $year.'-'.$month.'-01';
760 if ($month == 13) {
761 $initDate = date('Y').'-01-01';
762 }
763
764 $queryEvolSub = 'SELECT MONTH(subscription_date) as monthSub, DATE_FORMAT(subscription_date,"%Y_%m") AS unit, COUNT(user_id) AS nbUser';
765 $queryEvolSub .= ' FROM `#__acym_user_has_list`';
766 $queryEvolSub .= ' WHERE subscription_date >= "'.$initDate.'" AND list_id = '.$listId;
767 $queryEvolSub .= ' GROUP BY unit';
768 $evolSubscibers = acym_loadObjectList($queryEvolSub, 'unit');
769
770 $queryEvolUnsub = 'SELECT MONTH(unsubscribe_date) as monthUnsub, DATE_FORMAT(unsubscribe_date,"%Y_%m") AS unit, COUNT(user_id) AS nbUser';
771 $queryEvolUnsub .= ' FROM `#__acym_user_has_list`';
772 $queryEvolUnsub .= ' WHERE unsubscribe_date >= "'.$initDate.'" AND list_id = '.$listId;
773 $queryEvolUnsub .= ' GROUP BY unit';
774 $evolUnsubscibers = acym_loadObjectList($queryEvolUnsub, 'unit');
775
776 return [
777 'subscribers' => $evolSubscibers,
778 'unsubscribers' => $evolUnsubscibers,
779 ];
780 }
781
782 private function initList($listId)
783 {
784 $list = new \stdClass();
785 $list->list_id = $listId;
786 $list->sendable_users = 0;
787 $list->unconfirmed_users = 0;
788 $list->inactive_users = 0;
789 $list->unsubscribed_users = 0;
790
791 return $list;
792 }
793
794 public function getManageableLists()
795 {
796 $idCurrentUser = acym_currentUserId();
797 if (empty($idCurrentUser)) return [];
798
799 $userGroups = acym_getGroupsByUser($idCurrentUser);
800
801 return acym_loadResultArray(
802 'SELECT id
803 FROM #__acym_list
804 WHERE cms_user_id = '.intval($idCurrentUser).'
805 OR (access LIKE "%,'.implode(',%" OR access LIKE "%,', $userGroups).',%")'
806 );
807 }
808
809 public function onlyManageableLists(&$elements)
810 {
811 if (acym_isAdmin()) return;
812
813 $manageableLists = $this->getManageableLists();
814 $elements = array_intersect($elements, $manageableLists);
815 }
816
817 public function hasUserAccess($listId): bool
818 {
819 if (acym_isAdmin()) {
820 return true;
821 }
822
823 return in_array($listId, $this->getManageableLists());
824 }
825
826 public function getfrontManagementList()
827 {
828 $idCurrentUser = acym_currentUserId();
829 if (empty($idCurrentUser)) return 0;
830
831 $frontListId = acym_loadResult('SELECT id FROM #__acym_list WHERE type = '.acym_escapeDB(self::LIST_TYPE_FRONT).' AND cms_user_id = '.intval($idCurrentUser));
832
833 if (!empty($frontListId)) return $frontListId;
834
835 $frontList = new \stdClass();
836 $frontList->name = 'frontlist_'.$idCurrentUser;
837 $frontList->active = 1;
838 $frontList->visible = 0;
839 $frontList->cms_user_id = $idCurrentUser;
840 $frontList->type = self::LIST_TYPE_FRONT;
841
842 return $this->save($frontList);
843 }
844
845 public function setWelcomeUnsubEmail(array $listIds, int $mailId, string $type): bool
846 {
847 if (!in_array($type, [MailClass::TYPE_WELCOME, MailClass::TYPE_UNSUBSCRIBE]) || empty($mailId)) {
848 return false;
849 }
850
851 $column = acym_escape($type).'_id';
852 $columnsList = acym_getColumns('list');
853 if (!in_array($column, $columnsList)) {
854 return false;
855 }
856
857 if (!$this->removeWelcomeUnsubByMailId($mailId, $listIds, $column)) {
858 return false;
859 }
860
861 foreach ($listIds as $listId) {
862 $list = $this->getOneById($listId);
863 if (empty($list)) {
864 return false;
865 }
866
867 $list->{$column} = $mailId;
868
869 if (!$this->save($list)) {
870 return false;
871 }
872 }
873
874 return true;
875 }
876
877 private function removeWelcomeUnsubByMailId(int $mailId, array $listIds, string $column): bool
878 {
879 if (empty($mailId)) {
880 return false;
881 }
882
883 $query = 'SELECT * FROM #__acym_list WHERE '.acym_secureDBColumn($column).' = '.$mailId;
884
885 if (!empty($listIds)) {
886 acym_arrayToInteger($listIds);
887 $query .= ' AND `id` NOT IN ('.implode(',', $listIds).')';
888 }
889
890 $lists = acym_loadObjectList($query);
891 if (empty($lists)) {
892 return true;
893 }
894
895 foreach ($lists as $list) {
896 $list->{$column} = null;
897
898 if (!$this->save($list)) {
899 return false;
900 }
901 }
902
903 return true;
904 }
905
906 public function getListIdsByWelcomeUnsub($mailId, $welcome = true)
907 {
908 $type = $welcome ? 'welcome_id' : 'unsubscribe_id';
909
910 $return = acym_loadResultArray('SELECT id FROM #__acym_list WHERE '.$type.' = '.intval($mailId));
911
912 return empty($return) ? [] : $return;
913 }
914
915 public function getUsersForSummaryModal($id, $offset, $limit, $search)
916 {
917 $whereQuery = ' AND user_list.status = 1 AND user.active = 1';
918
919 if (!empty($search)) {
920 $search = acym_escapeDB('%'.$search.'%');
921 $whereQuery .= ' AND (user.email LIKE '.$search.' OR user.name LIKE '.$search.' OR user.id LIKE '.$search.') ';
922 }
923
924 if ($this->config->get('require_confirmation', '1') === '1') {
925 $whereQuery .= ' AND user.confirmed = 1';
926 }
927
928 $query = 'SELECT user.email, user.name, user.id
929 FROM #__acym_user as user
930 JOIN #__acym_user_has_list as user_list ON user.id = user_list.user_id
931 WHERE user_list.list_id = '.intval($id).$whereQuery.' LIMIT '.intval($offset).', '.intval($limit);
932
933
934 return acym_loadObjectList($query, 'id');
935 }
936
937 public function getXLists(array $options = [])
938 {
939 $limit = $options['limit'] ?? 10;
940 $offset = $options['offset'] ?? 0;
941 $filters = $options['filters'] ?? ['type' => self::LIST_TYPE_STANDARD];
942
943 $conditions = [];
944 foreach ($filters as $column => $filter) {
945 switch ($column) {
946 case 'id':
947 case 'active':
948 case 'visible':
949 case 'clean':
950 case 'welcome_id':
951 case 'unsubscribe_id':
952 case 'cms_user_id':
953 case 'tracking':
954 $conditions[] = acym_secureDBColumn($column).' = '.intval($filter);
955 break;
956 default:
957 $conditions[] = acym_secureDBColumn($column).' LIKE '.acym_escapeDB('%'.$filter.'%');
958 }
959 }
960
961 $query = 'SELECT * FROM #__acym_list';
962 if (!empty($conditions)) {
963 $query .= ' WHERE '.implode(' AND ', $conditions);
964 }
965
966 return acym_loadObjectList($query, $this->pkey, $offset, $limit);
967 }
968
969 public function getOneList(): bool
970 {
971 $firstList = acym_loadObject('SELECT * FROM #__acym_list WHERE `id` != 1');
972
973 return !empty($firstList);
974 }
975
976 public function getMostUsedLists(): array
977 {
978 return acym_loadObjectList(
979 'SELECT list_id
980 FROM #__acym_mail_has_list
981 GROUP BY list_id
982 ORDER BY COUNT(*) DESC
983 LIMIT 5'
984 );
985 }
986
987 public function getListsSubscribersAndUnsubscribeUsersFromUserHasList(): array
988 {
989 $query = 'SELECT list_id,
990 SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) AS subscribers,
991 SUM(CASE WHEN status = 0 THEN 1 ELSE 0 END) AS unsubscribed_users
992 FROM `#__acym_user_has_list`
993 GROUP BY list_id';
994
995 return acym_loadObjectList($query);
996 }
997
998 public function updateListsSubscribersAndUnsubscribeUsers(int $listId, int $subscribers, int $unsubscribeUsers, int $new_sub, int $new_unsub)
999 {
1000 $query = 'UPDATE `#__acym_list` SET `subscribers` = '.$subscribers.', `unsubscribed_users` = '.$unsubscribeUsers.', `new_sub` = '.$new_sub.', `new_unsub` = '.$new_unsub.' WHERE id = '.$listId;
1001
1002 return acym_query($query);
1003 }
1004
1005 public function getMostUsedListsByIdsWithSubscribersData(array $ids = []): array
1006 {
1007 if (empty($ids)) {
1008 return [];
1009 }
1010 acym_arrayToInteger($ids);
1011 $query = 'SELECT name, subscribers, unsubscribed_users, new_sub, new_unsub FROM `#__acym_list` WHERE id IN ('.implode(', ', $ids).')';
1012
1013 return acym_loadObjectList($query);
1014 }
1015
1016
1017 }
1018