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/UserClass.php +0 -1647 10.0.1 → 11.1.1 View file →
@@ -1,1647 +1,0 @@
1 -<?php
2 -
3 -namespace AcyMailing\Classes;
4 -
5 -use AcyMailing\Helpers\AutomationHelper;
6 -use AcyMailing\Helpers\MailerHelper;
7 -use AcyMailing\Helpers\PaginationHelper;
8 -use AcyMailing\Core\AcymClass;
9 -
10 -class UserClass extends AcymClass
11 -{
12 - var $checkVisitor = true;
13 - var $restrictedFields = ['id', 'key', 'confirmed', 'active', 'cms_id', 'creation_date'];
14 - var $allowModif = false;
15 - var $requireId = false;
16 - var $sendConf = true;
17 - var $forceConf = false;
18 - public bool $confirmationSentSuccess = false;
19 - var $newUser = false;
20 - var $blockNotifications = false;
21 - var $subscribed = false;
22 - var $confirmationSentError;
23 - var $triggers = true;
24 -
25 - var $forceConfAdmin = false;
26 -
27 - public $sendWelcomeEmail = true;
28 - public $sendUnsubscribeEmail = true;
29 -
30 - public function __construct()
31 - {
32 - parent::__construct();
33 -
34 - $this->table = 'user';
35 - $this->pkey = 'id';
36 - }
37 -
38 - public function getMatchingElements(array $settings = []): array
39 - {
40 - $columns = '`user`.*';
41 - if (!empty($settings['columns'])) {
42 - foreach ($settings['columns'] as $key => $value) {
43 - $settings['columns'][$key] = $key === 'join' ? $value : 'user.'.$value;
44 - }
45 - $columns = implode(', ', $settings['columns']);
46 - }
47 -
48 - $query = $columns.' FROM #__acym_user AS `user`';
49 - $queryCount = 'SELECT COUNT(DISTINCT user.id) FROM #__acym_user AS user';
50 - $queryStatus = 'SELECT COUNT(DISTINCT user.id) AS number, user.confirmed + user.active*2 AS score FROM #__acym_user AS user';
51 - $filters = [];
52 -
53 - if (!empty($settings['join'])) {
54 - $query .= $this->getJoinForQuery($settings['join']);
55 - }
56 - $this->handleSegmentFilter($settings, $filters, $query, $queryCount, $queryStatus);
57 - $this->handleSubscriptionFilter($settings, $filters, $query, $queryCount, $queryStatus);
58 - $this->handleFrontend($settings, $query, $queryCount, $queryStatus);
59 - $this->handleSearchFilter($settings, $query, $queryCount, $queryStatus, $filters);
60 - $results['status'] = $this->handleUserStatusFilter($settings, $queryStatus, $filters);
61 - $entityResult = $this->handleEntitySelect($settings, $filters);
62 -
63 - if (!empty($entityResult)) return $entityResult;
64 -
65 - if (!empty($filters)) {
66 - $query .= ' WHERE ('.implode(') AND (', $filters).')';
67 - $queryCount .= ' WHERE ('.implode(') AND (', $filters).')';
68 - }
69 -
70 - if (!empty($settings['ordering']) && !empty($settings['ordering_sort_order'])) {
71 - $query .= ' ORDER BY user.'.acym_secureDBColumn($settings['ordering']).' '.acym_secureDBColumn(strtoupper($settings['ordering_sort_order']));
72 - }
73 -
74 - if (empty($settings['offset']) || $settings['offset'] < 0) {
75 - $settings['offset'] = 0;
76 - }
77 -
78 - if (empty($settings['elementsPerPage']) || $settings['elementsPerPage'] < 1) {
79 - $pagination = new PaginationHelper();
80 - $settings['elementsPerPage'] = $pagination->getListLimit();
81 - }
82 -
83 - acym_query('SET SQL_BIG_SELECTS=1');
84 - $results['elements'] = acym_loadObjectList('SELECT DISTINCT '.$query, '', $settings['offset'], $settings['elementsPerPage']);
85 - $results['total'] = acym_loadResult($queryCount);
86 -
87 - if (!empty($results['elements']) && !empty($settings['cms_username'])) {
88 - $cmsIds = array_diff(array_column($results['elements'], 'cms_id'), [0, '']);
89 - if (!empty($cmsIds)) {
90 - global $acymCmsUserVars;
91 - $userNames = acym_loadObjectList(
92 - 'SELECT '.$acymCmsUserVars->id.' AS id, '.$acymCmsUserVars->username.' AS `cms_username`
93 - FROM '.$acymCmsUserVars->table.'
94 - WHERE id IN ('.implode(', ', array_values($cmsIds)).')',
95 - 'id'
96 - );
97 - foreach ($results['elements'] as $key => $oneElement) {
98 - if (empty($results['elements'][$key]->cms_id)) continue;
99 - if (empty($userNames[$results['elements'][$key]->cms_id])) {
100 - $oneUser = $this->getOneById($results['elements'][$key]->id);
101 - $oneUser->cms_id = 0;
102 - $this->save($oneUser);
103 - $results['elements'][$key]->cms_id = 0;
104 - continue;
105 - }
106 - $results['elements'][$key]->cms_username = $userNames[$results['elements'][$key]->cms_id]->cms_username;
107 - }
108 - }
109 - }
110 -
111 - return $results;
112 - }
113 -
114 - private function handleSubscriptionFilter($settings, &$filters, &$query, &$queryCount, &$queryStatus)
115 - {
116 - if (empty($settings['list'])) return;
117 -
118 - $listJoin = ' JOIN #__acym_user_has_list AS list ON user.id = list.user_id AND list.list_id = '.intval($settings['list']).' ';
119 -
120 - if ($settings['list_status'] === 'none') {
121 - $listJoin = ' LEFT'.$listJoin;
122 - $filters[] = 'list.user_id IS NULL';
123 - } else {
124 - $filters[] = 'list.status = '.($settings['list_status'] === 'sub' ? 1 : 0);
125 - }
126 -
127 - $query .= $listJoin;
128 - $queryCount .= $listJoin;
129 - $queryStatus .= $listJoin;
130 - }
131 -
132 - private function handleFrontend($settings, &$query, &$queryCount, &$queryStatus)
133 - {
134 - if (!acym_isAdmin()) {
135 - $settings['creator_id'] = acym_currentUserId();
136 - if (empty($settings['creator_id'])) $settings['creator_id'] = '-1';
137 - }
138 -
139 - if (!empty($settings['creator_id'])) {
140 - $userGroups = acym_getGroupsByUser($settings['creator_id']);
141 - $groupCondition = 'list.access LIKE "%,'.implode(',%" OR list.access LIKE "%,', $userGroups).',%"';
142 - $joinList = ' JOIN #__acym_user_has_list as user_list ON user_list.user_id = user.id JOIN #__acym_list AS list ON list.id = user_list.list_id AND (list.cms_user_id = '.intval(
143 - $settings['creator_id']
144 - ).' OR '.$groupCondition.')';
145 -
146 - $query .= $joinList;
147 - $queryCount .= $joinList;
148 - $queryStatus .= $joinList;
149 - }
150 - }
151 -
152 - private function handleSearchFilter($settings, &$query, &$queryCount, &$queryStatus, &$filters)
153 - {
154 - if (empty($settings['search'])) return;
155 -
156 - $searchValue = acym_escapeDB('%'.$settings['search'].'%');
157 - $searchFilter = 'user.email LIKE '.$searchValue.' OR user.name LIKE '.$searchValue.' OR user.id = '.intval($settings['search']);
158 -
159 - $listingFields = acym_loadResultArray('SELECT `id` FROM #__acym_field WHERE `'.(acym_isAdmin() ? 'back' : 'front').'end_listing` = 1');
160 - if (!empty($listingFields)) {
161 - $query = 'DISTINCT '.$query;
162 - $join = ' LEFT JOIN #__acym_user_has_field AS userfield ON user.id = userfield.user_id AND userfield.field_id IN ('.implode(', ', $listingFields).') AND ';
163 - $cfSearch = 'userfield.value LIKE '.$searchValue;
164 -
165 - $fieldsWithMultipleValues = acym_loadObjectList(
166 - 'SELECT *
167 - FROM #__acym_field
168 - WHERE id IN ('.implode(', ', $listingFields).')
169 - AND `value` LIKE '.acym_escapeDB('%"title":"'.$settings['search'].'"%')
170 - );
171 -
172 - if (!empty($fieldsWithMultipleValues)) {
173 - foreach ($fieldsWithMultipleValues as $oneField) {
174 - $oneField->value = json_decode($oneField->value, true);
175 - foreach ($oneField->value as $value) {
176 - if (stripos($value['title'], $settings['search']) !== false) {
177 - $cfSearch .= ' OR (userfield.field_id = '.intval($oneField->id).' AND userfield.value LIKE '.acym_escapeDB('%'.$value['value'].'%').')';
178 - }
179 - }
180 - }
181 - }
182 -
183 - $join .= '('.$cfSearch.')';
184 - $searchFilter .= ' OR userfield.field_id IS NOT NULL';
185 -
186 - $query .= $join;
187 - $queryCount .= $join;
188 - $queryStatus .= $join;
189 - }
190 -
191 - $filters[] = $searchFilter;
192 - }
193 -
194 - private function handleUserStatusFilter($settings, $queryStatus, &$filters)
195 - {
196 - if (!empty($filters)) {
197 - $queryStatus .= ' WHERE ('.implode(') AND (', $filters).')';
198 - }
199 -
200 - $usersPerStatusObject = acym_loadObjectList($queryStatus.' GROUP BY score', 'score');
201 -
202 - $usersPerStatus = [];
203 - for ($i = 0 ; $i < 4 ; $i++) {
204 - $usersPerStatus[$i] = empty($usersPerStatusObject[$i]) ? 0 : $usersPerStatusObject[$i]->number;
205 - }
206 -
207 - if (!empty($settings['status'])) {
208 - $allowedStatus = [
209 - 'active' => 'active = 1',
210 - 'inactive' => 'active = 0',
211 - 'confirmed' => 'confirmed = 1',
212 - 'unconfirmed' => 'confirmed = 0',
213 - ];
214 - if (empty($allowedStatus[$settings['status']])) {
215 - die('Injection denied');
216 - }
217 - $filters[] = 'user.'.$allowedStatus[$settings['status']];
218 - }
219 -
220 - return [
221 - 'all' => array_sum($usersPerStatus),
222 - 'active' => $usersPerStatus[2] + $usersPerStatus[3],
223 - 'inactive' => $usersPerStatus[0] + $usersPerStatus[1],
224 - 'confirmed' => $usersPerStatus[1] + $usersPerStatus[3],
225 - 'unconfirmed' => $usersPerStatus[0] + $usersPerStatus[2],
226 - ];
227 - }
228 -
229 - private function handleEntitySelect($settings, &$filters)
230 - {
231 - if (isset($settings['hiddenElements'])) {
232 - if (empty($settings['hiddenElements'])) {
233 - $filters[] = 'user.id IS NOT NULL';
234 - } else {
235 - acym_arrayToInteger($settings['hiddenElements']);
236 - $filters[] = 'user.id NOT IN('.implode(',', $settings['hiddenElements']).')';
237 - }
238 - }
239 -
240 - if (isset($settings['onlyElements'])) {
241 - if (empty($settings['onlyElements'])) {
242 - $filters[] = 'user.id IS NULL';
243 - } else {
244 - acym_arrayToInteger($settings['onlyElements']);
245 - $filters[] = 'user.id IN('.implode(',', $settings['onlyElements']).')';
246 - }
247 - }
248 -
249 - if (!empty($settings['showOnlySelected'])) {
250 - if (!empty($settings['selectedUsers'])) {
251 - acym_arrayToInteger($settings['selectedUsers']);
252 - $filters[] = 'user.id IN('.implode(',', $settings['selectedUsers']).')';
253 - } else {
254 - return ['users' => [], 'total' => 0];
255 - }
256 - }
257 -
258 - return null;
259 - }
260 -
261 - private function handleSegmentFilter($settings, &$filters, &$query, &$queryCount, &$queryStatus)
262 - {
263 - if (!array_key_exists('segment', $settings)) return;
264 - if ($settings['segment'] == 0) return;
265 -
266 - $segmentClass = (new SegmentClass())->getOneById($settings['segment']);
267 - $automationHelpers = [];
268 - if (!empty($segmentClass) && !empty($segmentClass->filters)) {
269 - foreach ($segmentClass->filters as $or => $orValues) {
270 - if (empty($orValues)) continue;
271 - $automationHelpers[$or] = new AutomationHelper();
272 - foreach ($orValues as $and => $andValues) {
273 - $and = intval($and);
274 - foreach ($andValues as $filterName => $options) {
275 - acym_trigger('onAcymProcessFilter_'.$filterName, [&$automationHelpers[$or], &$options, $and.'_'.$or]);
276 - }
277 - }
278 - }
279 - }
280 -
281 - $where = '';
282 - $join = '';
283 - foreach ($automationHelpers as $index => $automationHelper) {
284 - if (!empty($automationHelper->where)) {
285 - $where .= ' ('.implode(') and (', $automationHelper->where).')';
286 - if ($index != count($automationHelpers) - 1) $where .= ' OR ';
287 - }
288 - if (!empty($automationHelper->join)) $join .= ' JOIN '.implode(' JOIN ', $automationHelper->join);
289 - if (!empty($automationHelper->leftjoin)) $join .= ' LEFT JOIN '.implode(' LEFT JOIN ', $automationHelper->leftjoin);
290 - }
291 - if (!empty($where)) {
292 - $filters[] = $where;
293 - }
294 - $query .= $join;
295 - $queryCount .= $join;
296 - $queryStatus .= $join;
297 - }
298 -
299 - public function getJoinForQuery($joinType)
300 - {
301 - if (strpos($joinType, 'join_list') !== false) {
302 - $listId = explode('-', $joinType);
303 -
304 - return ' LEFT JOIN #__acym_user_has_list AS userlist ON user.id = userlist.user_id AND userlist.status = 1 AND userlist.list_id = '.intval($listId[1]);
305 - }
306 -
307 - return '';
308 - }
309 -
310 - public function getOneByCMSId(?int $id)
311 - {
312 - $query = 'SELECT * FROM #__acym_user WHERE cms_id = '.intval($id);
313 -
314 - return acym_loadObject($query);
315 - }
316 -
317 - public function getOneByEmail(?string $email)
318 - {
319 - $query = 'SELECT * FROM #__acym_user WHERE email = '.acym_escapeDB($email);
320 -
321 - return acym_loadObject($query);
322 - }
323 -
324 - public function getByColumnValue($column, $value)
325 - {
326 - $userColumns = acym_getColumns('user');
327 - if (!in_array($column, $userColumns)) return [];
328 -
329 - $query = 'SELECT * FROM #__acym_user WHERE '.acym_secureDBColumn($column).' = '.acym_escapeDB($value);
330 -
331 - return acym_loadObjectList($query, $this->pkey);
332 - }
333 -
334 - public function getUserSubscriptionById(
335 - $userId,
336 - $key = 'id',
337 - $includeManagement = false,
338 - $visible = false,
339 - $needTranslation = false,
340 - $sortBySubscription = false,
341 - $mailId = 0,
342 - $campaignOnly = false
343 - ) {
344 - $mailType = null;
345 - if (!empty($mailId)) {
346 - $mailType = acym_loadResult('SELECT type FROM #__acym_mail WHERE id = '.intval($mailId));
347 - }
348 -
349 - $query = 'SELECT list.id, list.translation, list.name, list.display_name, list.color, list.active, list.visible, list.description, userlist.status, userlist.subscription_date, userlist.unsubscribe_date
350 - FROM #__acym_list AS list
351 - JOIN #__acym_user_has_list AS userlist
352 - ON list.id = userlist.list_id ';
353 -
354 - if (!empty($mailId) && $campaignOnly && !empty($mailType) && $mailType !== MailClass::TYPE_FOLLOWUP) {
355 - $query .= 'JOIN #__acym_mail_has_list AS mail_list ON list.id = mail_list.list_id AND mail_list.mail_id = '.intval($mailId);
356 - }
357 -
358 - $query .= ' WHERE userlist.user_id = '.intval($userId);
359 -
360 - if (!$includeManagement && !empty($mailType) && $mailType === MailClass::TYPE_FOLLOWUP) {
361 - $query .= ' AND list.type = '.acym_escapeDB(ListClass::LIST_TYPE_FOLLOWUP);
362 - } elseif (!$includeManagement) {
363 - $types = [ListClass::LIST_TYPE_STANDARD, ListClass::LIST_TYPE_FOLLOWUP];
364 - $query .= ' AND list.type in ("'.implode('","', $types).'")';
365 - }
366 -
367 - if ($visible) {
368 - $query .= ' AND list.visible = 1';
369 - }
370 -
371 - if ($sortBySubscription) {
372 - $query .= ' ORDER BY userlist.subscription_date DESC';
373 - }
374 -
375 - $lists = acym_loadObjectList($query, $key);
376 -
377 - if (acym_isMultilingual() && $needTranslation) {
378 - $listClass = new ListClass();
379 - $lists = $listClass->getTranslatedNameDescription($lists);
380 - }
381 -
382 - return $lists;
383 - }
384 -
385 - public function getUserStandardListIdById(int $userId)
386 - {
387 - $query = 'SELECT list.id FROM #__acym_list AS list
388 - JOIN #__acym_user_has_list AS user_list ON list.id = user_list.list_id AND user_list.status = 1 AND user_list.user_id = '.$userId.'
389 - WHERE list.visible = 1 AND list.type = '.acym_escapeDB(ListClass::LIST_TYPE_STANDARD);
390 -
391 - return acym_loadResultArray($query);
392 - }
393 -
394 - public function getAllListsUserSubscriptionById($userId, $key = 'id', $needTranslation = false)
395 - {
396 - $query = 'SELECT list.id, list.translation, list.name, list.color, list.active, list.visible, userlist.status, userlist.subscription_date, userlist.unsubscribe_date
397 - FROM #__acym_list AS list
398 - LEFT JOIN #__acym_user_has_list AS userlist
399 - ON list.id = userlist.list_id
400 - AND userlist.user_id = '.intval($userId);
401 -
402 - $lists = acym_loadObjectList($query, $key);
403 -
404 - if (acym_isMultilingual() && $needTranslation) {
405 - $listClass = new ListClass();
406 - $lists = $listClass->getTranslatedNameDescription($lists);
407 - }
408 -
409 - return $lists;
410 - }
411 -
412 - public function getUsersSubscriptionsByIds($usersId, $creatorId = 0)
413 - {
414 - $query = 'SELECT `list`.`id`, `list`.`color`, `list`.`name`, `userlist`.`user_id`, `userlist`.`status`
415 - FROM #__acym_list AS `list`
416 - JOIN #__acym_user_has_list AS `userlist`
417 - ON `list`.`id` = `userlist`.`list_id`
418 - WHERE `userlist`.`user_id` IN ('.implode(',', $usersId).')
419 - AND `list`.`type` = '.acym_escapeDB(ListClass::LIST_TYPE_STANDARD);
420 -
421 - if (!empty($creatorId)) {
422 - $userGroups = acym_getGroupsByUser($creatorId);
423 - $groupCondition = '`list`.`access` LIKE "%,'.implode(',%" OR `list`.`access` LIKE "%,', $userGroups).',%"';
424 - $query .= ' AND (`list`.`cms_user_id` = '.intval($creatorId).' OR '.$groupCondition.')';
425 - }
426 - $query .= ' ORDER BY `userlist`.`status` DESC, `list`.`id` ASC';
427 -
428 - return acym_loadObjectList($query);
429 - }
430 -
431 - public function getCountTotalUsers()
432 - {
433 - $query = 'SELECT COUNT(id) FROM #__acym_user';
434 -
435 - return acym_loadResult($query);
436 - }
437 -
438 - public function getSubscriptionStatus($userId, $listIds = [], $wantedStatus = null)
439 - {
440 - $query = 'SELECT status, list_id
441 - FROM #__acym_user_has_list
442 - WHERE user_id = '.intval($userId);
443 - if (!empty($listIds)) {
444 - acym_arrayToInteger($listIds);
445 - $query .= ' AND list_id IN ('.implode(',', $listIds).')';
446 - }
447 -
448 - if ($wantedStatus !== null) {
449 - $query .= ' AND status = '.intval($wantedStatus);
450 - }
451 -
452 - return acym_loadObjectList($query, 'list_id');
453 - }
454 -
455 - public function identify(bool $onlyValue = false, $idName = null, $keyName = null)
456 - {
457 - $id = acym_getVar('int', empty($idName) ? 'id' : $idName, 0);
458 - $key = acym_getVar('string', empty($keyName) ? 'key' : $keyName, '');
459 -
460 - if (empty($id) && !empty($idName) && empty($key) && !empty($keyName)) {
461 - $id = acym_getVar('int', 'id', 0);
462 - $key = acym_getVar('string', 'key', 0);
463 - }
464 -
465 - if (empty($id) || empty($key)) {
466 - $currentUserid = acym_currentUserId();
467 - if (!empty($currentUserid)) {
468 - return $this->getOneByCMSId($currentUserid);
469 - }
470 - if (!$onlyValue) {
471 - acym_enqueueMessage(acym_translation('ACYM_LOGIN'), 'error');
472 - }
473 -
474 - return false;
475 - }
476 -
477 - $userIdentified = acym_loadObject('SELECT * FROM #__acym_user WHERE `id` = '.intval($id).' AND `key` = '.acym_escapeDB($key));
478 -
479 - if (!empty($userIdentified)) {
480 - return $userIdentified;
481 - }
482 -
483 - if (!$onlyValue) {
484 - acym_enqueueMessage(acym_translation('ACYM_USER_NOT_FOUND'), 'error');
485 - }
486 -
487 - return false;
488 - }
489 -
490 - public function subscribe($userIds, $addLists, $trigger = true, $forceFront = false)
491 - {
492 - if (empty($addLists)) {
493 - return false;
494 - }
495 -
496 - if (!is_array($userIds)) {
497 - $userIds = [$userIds];
498 - }
499 -
500 - if (!is_array($addLists)) {
501 - $addLists = [$addLists];
502 - }
503 -
504 - $listClass = new ListClass();
505 - $historyClass = new HistoryClass();
506 -
507 - $confirmationRequired = $this->config->get('require_confirmation', 1);
508 - $subscribedToLists = false;
509 - $historyData = acym_translationSprintf('ACYM_LISTS_NUMBERS', implode(', ', $addLists));
510 -
511 - foreach ($userIds as $userId) {
512 - $user = $this->getOneById($userId);
513 - if (empty($user)) continue;
514 - $currentSubscription = $this->getUserSubscriptionById($userId, 'id', true);
515 -
516 - $currentlySubscribed = [];
517 - $currentlyUnsubscribed = [];
518 - foreach ($currentSubscription as $oneList) {
519 - if ($oneList->status == 1) {
520 - $currentlySubscribed[$oneList->id] = $oneList;
521 - }
522 - if ($oneList->status == 0) {
523 - $currentlyUnsubscribed[$oneList->id] = $oneList;
524 - }
525 - }
526 -
527 - $subscribedLists = [];
528 - $listsNotExisting = [];
529 - foreach ($addLists as $oneListId) {
530 - if (empty($oneListId) || !empty($currentlySubscribed[$oneListId])) {
531 - continue;
532 - }
533 -
534 - $list = $listClass->getOneById($oneListId);
535 - if (empty($list)) {
536 - $listsNotExisting[] = $oneListId;
537 - continue;
538 - }
539 -
540 - $subscription = new \stdClass();
541 - $subscription->user_id = $userId;
542 - $subscription->list_id = $oneListId;
543 - $subscription->status = 1;
544 - $subscription->subscription_date = date('Y-m-d H:i:s', time() - date('Z'));
545 -
546 - if (empty($currentSubscription[$oneListId])) {
547 - acym_insertObject('#__acym_user_has_list', $subscription);
548 - } elseif (!empty($currentlyUnsubscribed[$oneListId])) {
549 - acym_updateObject('#__acym_user_has_list', $subscription, ['user_id', 'list_id']);
550 - }
551 -
552 - $subscribedLists[] = $oneListId;
553 - $subscribedToLists = true;
554 - }
555 -
556 - if (!empty($listsNotExisting)) {
557 - $this->errors['list_not_existing'] = acym_translationSprintf('ACYM_LIST_NOT_FOUND', implode(', ', $listsNotExisting));
558 - }
559 -
560 - $historyClass->insert($userId, 'subscribed', [$historyData]);
561 -
562 - if ($trigger) {
563 - acym_trigger('onAcymAfterUserSubscribe', [&$user, &$subscribedLists]);
564 - }
565 -
566 - if ($this->sendWelcomeEmail && ($confirmationRequired == 0 || $user->confirmed == 1) && $user->active == 1) {
567 - $listClass->sendWelcome($userId, $subscribedLists, $forceFront);
568 - }
569 - }
570 -
571 - return $subscribedToLists;
572 - }
573 -
574 - private function registerUnsubUser($userIds)
575 - {
576 - $mailId = acym_getVar('int', 'mail_id', 0);
577 - if (empty($mailId)) return;
578 -
579 - $mailStatClass = new MailStatClass();
580 - $userStatClass = new UserStatClass();
581 -
582 - $countUnsubscribe = 0;
583 -
584 - foreach ($userIds as $id) {
585 - $userStat = $userStatClass->getOneByMailAndUserId($mailId, $id);
586 - if (empty($userStat)) continue;
587 -
588 - $newUserStat = [
589 - 'mail_id' => $mailId,
590 - 'user_id' => $id,
591 - 'unsubscribe' => empty($userStat->unsubscribe) ? 1 : $userStat->unsubscribe + 1,
592 - ];
593 -
594 - if (empty($userStat->unsubscribe)) $countUnsubscribe++;
595 -
596 - $userStatClass->save($newUserStat);
597 - }
598 -
599 - $mailStat = [
600 - 'mail_id' => $mailId,
601 - 'unsubscribe_total' => $countUnsubscribe,
602 - ];
603 -
604 - $mailStatClass->save($mailStat);
605 - }
606 -
607 - public function unsubscribe($userIds, $lists)
608 - {
609 - if (empty($lists)) return false;
610 -
611 - if (!is_array($userIds)) $userIds = [$userIds];
612 - if (!is_array($lists)) $lists = [$lists];
613 -
614 - $listClass = new ListClass();
615 - $unsubscribedFromLists = false;
616 - foreach ($userIds as $userId) {
617 - $user = $this->getOneById($userId);
618 - if (empty($user)) continue;
619 -
620 - $currentSubscription = $this->getUserSubscriptionById($userId);
621 -
622 - $currentlySubscribed = [];
623 - $currentlyUnsubscribed = [];
624 - foreach ($currentSubscription as $oneList) {
625 - if ($oneList->status == 0) {
626 - $currentlyUnsubscribed[$oneList->id] = $oneList;
627 - } elseif ($oneList->status == 1) {
628 - $currentlySubscribed[$oneList->id] = $oneList;
629 - }
630 - }
631 -
632 - $unsubscribedLists = [];
633 - $listsNotExisting = [];
634 - foreach ($lists as $oneListId) {
635 - if (empty($oneListId) || !empty($currentlyUnsubscribed[$oneListId])) continue;
636 -
637 - if (empty($currentlySubscribed[$oneListId])) continue;
638 -
639 - $list = $listClass->getOneById($oneListId);
640 - if (empty($list)) {
641 - $listsNotExisting[] = $oneListId;
642 - continue;
643 - }
644 -
645 - $subscription = new \stdClass();
646 - $subscription->user_id = $userId;
647 - $subscription->list_id = $oneListId;
648 - $subscription->status = 0;
649 - $subscription->unsubscribe_date = date('Y-m-d H:i:s', time() - date('Z'));
650 - if (empty($currentSubscription[$oneListId])) {
651 - acym_insertObject('#__acym_user_has_list', $subscription);
652 - } else {
653 - acym_updateObject('#__acym_user_has_list', $subscription, ['user_id', 'list_id']);
654 - }
655 -
656 - $unsubscribedLists[] = $oneListId;
657 - $unsubscribedFromLists = true;
658 - }
659 -
660 - if (!empty($listsNotExisting)) {
661 - $this->errors['list_not_existing'] = acym_translationSprintf('ACYM_LIST_NOT_FOUND', implode(', ', $listsNotExisting));
662 - }
663 -
664 - acym_query(
665 - 'DELETE FROM #__acym_queue WHERE user_id = '.intval($userId).' AND mail_id IN (
666 - SELECT followup_mail.mail_id FROM #__acym_followup_has_mail AS followup_mail
667 - JOIN #__acym_followup AS followup ON followup.id = followup_mail.followup_id AND followup.list_id IN ('.implode(',', $lists).')
668 - )'
669 - );
670 -
671 - $historyClass = new HistoryClass();
672 - $historyData = acym_translationSprintf('ACYM_LISTS_NUMBERS', implode(', ', $lists));
673 - $historyClass->insert($userId, 'unsubscribed', [$historyData], 0, acym_getVar('string', 'unsubscribe_reason'));
674 -
675 - if ($this->triggers) {
676 - acym_trigger('onAcymAfterUserUnsubscribe', [&$user, &$unsubscribedLists]);
677 - }
678 -
679 - if ($this->sendUnsubscribeEmail) {
680 - $listClass->sendUnsubscribe($userId, $unsubscribedLists);
681 - }
682 -
683 - if (!empty($unsubscribedLists)) {
684 - foreach ($unsubscribedLists as $i => $oneListId) {
685 - $currentList = $listClass->getOneById($oneListId);
686 - $unsubscribedLists[$i] = $currentList->name;
687 - }
688 - $this->sendNotification($user->id, 'acy_notification_unsub', ['lists' => implode(', ', $unsubscribedLists)]);
689 - }
690 - }
691 -
692 - if ($unsubscribedFromLists) $this->registerUnsubUser($userIds);
693 -
694 - return $unsubscribedFromLists;
695 - }
696 -
697 - public function unsubscribeOnSubscriptions($userId, $listIds)
698 - {
699 - if (empty($listIds)) {
700 - return false;
701 - }
702 -
703 - if (!is_array($listIds)) {
704 - $listIds = [$listIds];
705 - }
706 - acym_arrayToInteger($listIds);
707 -
708 - $subscribedLists = acym_loadResultArray('SELECT list_id FROM #__acym_user_has_list WHERE user_id = '.intval($userId).' AND list_id IN ('.implode(',', $listIds).')');
709 -
710 - if (!empty($subscribedLists)) $this->unsubscribe($userId, $subscribedLists);
711 -
712 - return true;
713 - }
714 -
715 - public function removeSubscription($userIds, $listIds = null)
716 - {
717 - if (!is_array($userIds)) $userIds = [$userIds];
718 - if (!is_array($listIds) || empty($listIds) || empty($userIds)) return false;
719 -
720 - acym_arrayToInteger($listIds);
721 - $query = 'DELETE FROM #__acym_user_has_list WHERE user_id IN ('.implode(',', $userIds).')';
722 - if (!empty($listIds)) $query .= ' AND list_id IN ('.implode(',', $listIds).')';
723 -
724 - return acym_query($query);
725 - }
726 -
727 - public function onlyManageableUsers(&$elements)
728 - {
729 - if (acym_isAdmin()) return;
730 -
731 - $listClass = new ListClass();
732 - $manageableLists = $listClass->getManageableLists();
733 - if (empty($manageableLists)) return;
734 -
735 - acym_arrayToInteger($elements);
736 - $elements = acym_loadResultArray(
737 - 'SELECT DISTINCT user_id
738 - FROM #__acym_user_has_list
739 - WHERE `list_id` IN ('.implode(',', $manageableLists).')
740 - AND `user_id` IN ('.implode(',', $elements).')'
741 - );
742 - }
743 -
744 - public function delete($elements, $fromAutomations = false)
745 - {
746 - if (!is_array($elements)) $elements = [$elements];
747 - acym_arrayToInteger($elements);
748 - $this->onlyManageableUsers($elements);
749 -
750 - if (empty($elements)) return 0;
751 -
752 - if (acym_isAdmin() || $fromAutomations || 'delete' === $this->config->get('frontend_delete_button', 'delete')) {
753 - acym_query('DELETE FROM #__acym_user_has_list WHERE user_id IN ('.implode(',', $elements).')');
754 - acym_query('DELETE FROM #__acym_queue WHERE user_id IN ('.implode(',', $elements).')');
755 - acym_query('DELETE FROM #__acym_user_has_field WHERE user_id IN ('.implode(',', $elements).')');
756 - acym_query('DELETE FROM #__acym_history WHERE user_id IN ('.implode(',', $elements).')');
757 - acym_query('DELETE FROM #__acym_user_stat WHERE user_id IN ('.implode(',', $elements).')');
758 -
759 - $scenarioProcessIds = acym_loadResultArray('SELECT id FROM #__acym_scenario_process WHERE user_id IN ('.implode(',', $elements).')');
760 -
761 - if (!empty($scenarioProcessIds)) {
762 - acym_query('DELETE FROM #__acym_scenario_history_line WHERE scenario_process_id IN ('.implode(',', $scenarioProcessIds).')');
763 - acym_query('DELETE FROM #__acym_scenario_queue WHERE scenario_process_id IN ('.implode(',', $scenarioProcessIds).')');
764 - acym_query('DELETE FROM #__acym_scenario_process WHERE id IN ('.implode(',', $scenarioProcessIds).')');
765 - }
766 -
767 - return parent::delete($elements);
768 - } else {
769 - $listClass = new ListClass();
770 - $manageableLists = $listClass->getManageableLists();
771 - $this->removeSubscription($elements, $manageableLists);
772 - acym_query(
773 - 'DELETE queue
774 - FROM #__acym_queue AS queue
775 - JOIN #__acym_mail_has_list AS maillist
776 - ON queue.mail_id = maillist.mail_id
777 - WHERE queue.user_id IN ('.implode(',', $elements).')
778 - AND maillist.list_id IN ('.implode(',', $manageableLists).')'
779 - );
780 -
781 - return count($elements);
782 - }
783 - }
784 -
785 - public function save($user, $customFields = [], $ajax = false)
786 - {
787 - if (empty($user->email) && empty($user->id)) {
788 - return false;
789 - }
790 -
791 - if (isset($user->email)) {
792 - $user->email = strtolower($user->email);
793 - if (!acym_isValidEmail($user->email)) {
794 - $this->errors[] = acym_translation('ACYM_VALID_EMAIL');
795 -
796 - return false;
797 - }
798 - }
799 -
800 - if (empty($user->id)) {
801 - if (!isset($user->active)) {
802 - $user->active = 1;
803 - }
804 -
805 - if (empty($user->language)) {
806 - if (!acym_isAdmin()) {
807 - $cmsUserLanguage = acym_getCmsUserLanguage();
808 - }
809 -
810 - if (!empty($cmsUserLanguage)) {
811 - $user->language = $cmsUserLanguage;
812 - } elseif (acym_isMultilingual()) {
813 - $configUserLanguage = $this->config->get('multilingual_user_default', 'current_language');
814 - $user->language = $configUserLanguage === 'current_language' ? acym_getLanguageTag() : $configUserLanguage;
815 - }
816 - }
817 -
818 - $currentUserid = acym_currentUserId();
819 - $currentEmail = acym_currentUserEmail();
820 - $allowVisitors = $this->config->get('allow_visitor', 1) == 1;
821 - if ($this->checkVisitor && !acym_isAdmin() && !$allowVisitors && (empty($currentUserid) || strtolower($currentEmail) !== $user->email)) {
822 - $this->errors[] = acym_translation('ACYM_ONLY_LOGGED');
823 -
824 - return false;
825 - }
826 -
827 - if (empty($user->name) && $this->config->get('generate_name', 1)) {
828 - $user->name = ucwords(trim(str_replace(['.', '_', ')', ',', '(', '-', 1, 2, 3, 4, 5, 6, 7, 8, 9, 0], ' ', substr($user->email, 0, strpos($user->email, '@')))));
829 - }
830 -
831 - $source = acym_getVar('string', 'acy_source', '');
832 - if (empty($user->source) && !empty($source)) $user->source = $source;
833 -
834 - if (empty($user->key)) $user->key = acym_generateKey(14);
835 -
836 - $user->creation_date = date('Y-m-d H:i:s', time() - date('Z'));
837 - } elseif (!empty($user->confirmed)) {
838 - $oldUser = $this->getOneByIdWithCustomFields($user->id);
839 - if (!empty($oldUser) && empty($oldUser['confirmed'])) {
840 - $user->confirmation_date = date('Y-m-d H:i:s', time() - date('Z'));
841 - $user->confirmation_ip = acym_getIP();
842 -
843 - if ($this->triggers) {
844 - acym_trigger('onAcymAfterUserConfirm', [&$user]);
845 - }
846 - }
847 - } else {
848 - $oldUser = $this->getOneByIdWithCustomFields($user->id);
849 - }
850 -
851 - foreach ($user as $oneAttribute => $value) {
852 - if (empty($value)) continue;
853 -
854 - $oneAttribute = trim(strtolower($oneAttribute));
855 - if (!in_array($oneAttribute, $this->restrictedFields)) {
856 - $user->$oneAttribute = strip_tags($value);
857 - }
858 -
859 - if (is_numeric($user->$oneAttribute)) continue;
860 -
861 - if (function_exists('mb_detect_encoding')) {
862 - if (mb_detect_encoding($user->$oneAttribute, 'UTF-8', true) !== 'UTF-8') {
863 - $user->$oneAttribute = acym_utf8Encode($user->$oneAttribute);
864 - }
865 - } elseif (!preg_match(
866 - '%^(?:[\x09\x0A\x0D\x20-\x7E]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})*$%xs',
867 - $user->$oneAttribute
868 - )) {
869 - $user->$oneAttribute = acym_utf8Encode($user->$oneAttribute);
870 - }
871 - }
872 -
873 - if (empty($user->id)) {
874 - if (empty($user->cms_id) && !empty($user->email)) {
875 - global $acymCmsUserVars;
876 - $userCmsID = acym_loadResult(
877 - 'SELECT '.acym_secureDBColumn($acymCmsUserVars->id).' FROM '.$acymCmsUserVars->table.' WHERE '.acym_secureDBColumn(
878 - $acymCmsUserVars->email
879 - ).' = '.acym_escapeDB($user->email)
880 - );
881 - if (!empty($userCmsID)) $user->cms_id = $userCmsID;
882 - }
883 - if ($this->triggers) {
884 - $result = acym_trigger('onAcymBeforeUserCreate', [&$user]);
885 - if (in_array(false, $result)) {
886 - $acycheckerError = acym_getVar('string', 'acychecker_error');
887 - if (!empty($acycheckerError)) {
888 - if ($ajax) {
889 - $this->errors[] = $acycheckerError;
890 - } else {
891 - acym_enqueueMessage($acycheckerError, 'error');
892 - }
893 - }
894 -
895 - return false;
896 - }
897 - }
898 - } else {
899 - if ($this->triggers) {
900 - acym_trigger('onAcymBeforeUserModify', [&$user]);
901 - }
902 - }
903 -
904 - $userID = parent::save($user);
905 -
906 - $fieldClass = new FieldClass();
907 - if (!empty($customFields)) {
908 - foreach ($customFields as $key => $value) {
909 - if (!is_string($value)) {
910 - continue;
911 - }
912 -
913 - $value = preg_replace('/[\x{10000}-\x{10FFFF}]/u', '', $value);
914 -
915 - $field = $fieldClass->getOneById($key);
916 - if (empty($field) || $field->type !== 'textarea') {
917 - $value = preg_replace('/\s+/', ' ', $value);
918 - }
919 - $customFields[$key] = $value;
920 - }
921 - }
922 - $fieldClass->store($userID, $customFields, $ajax);
923 - if (!empty($fieldClass->errors)) {
924 - $this->errors = array_merge($this->errors, $fieldClass->errors);
925 - }
926 -
927 - $historyClass = new HistoryClass();
928 - if (empty($user->id)) {
929 - $user->id = $userID;
930 - $historyClass->insert($user->id, 'created');
931 - if ($this->triggers) {
932 - acym_trigger('onAcymAfterUserCreate', [&$user]);
933 - acym_triggerCmsHook('onAcymAfterUserSave', [$user, true]);
934 - }
935 - } else {
936 - $historyClass->insert($user->id, 'modified');
937 - if ($this->triggers) {
938 - acym_trigger('onAcymAfterUserModify', [&$user, &$oldUser]);
939 - acym_triggerCmsHook('onAcymAfterUserSave', [$user, false]);
940 - }
941 - }
942 -
943 - $this->sendConfirmation($userID);
944 -
945 - return $userID;
946 - }
947 -
948 - public function saveForm($ajax = false)
949 - {
950 - $allowUserModifications = (bool)($this->config->get('allow_modif', 'data') == 'all') || $this->allowModif;
951 - $allowSubscriptionModifications = (bool)($this->config->get('allow_modif', 'data') != 'none') || $this->allowModif;
952 -
953 - $user = new \stdClass();
954 - $connectedUser = $this->identify(true, 'userId', 'userKey');
955 -
956 - $userData = acym_getVar('array', 'user', []);
957 - if (!empty($userData)) {
958 - foreach ($userData as $attribute => $value) {
959 - $user->$attribute = $value;
960 - }
961 - }
962 -
963 - if (empty($user->email)) {
964 - if (!empty($connectedUser->email)) {
965 - $user->email = $connectedUser->email;
966 - }
967 - }
968 -
969 - if (empty($user->email)) {
970 - $this->errors[] = acym_translation('ACYM_VALID_EMAIL');
971 -
972 - return false;
973 - }
974 -
975 - if (!$allowUserModifications && !empty($connectedUser)) {
976 - if ($connectedUser->email != $user->email) {
977 - $this->errors[] = acym_translation('ACYM_NOT_ALLOWED_MODIFY_USER');
978 -
979 - return false;
980 - }
981 -
982 - $allowUserModifications = true;
983 - $allowSubscriptionModifications = true;
984 - }
985 -
986 - if (!empty($user->email)) {
987 - if (empty($user->id)) {
988 - $user->id = 0;
989 - }
990 - $existUser = acym_loadObject('SELECT * FROM #__acym_user WHERE email = '.acym_escapeDB($user->email).' AND id != '.intval($user->id));
991 - if (!empty($existUser->id)) {
992 - if (!$this->allowModif && !$allowSubscriptionModifications) {
993 - $this->errors[] = acym_translation('ACYM_ADDRESS_TAKEN');
994 -
995 - return false;
996 - } else {
997 - $user->id = $existUser->id;
998 - }
999 - }
1000 - }
1001 -
1002 - if (!empty($user->id) && !empty($user->email)) {
1003 - $existUser = $this->getOneById($user->id);
1004 - if (trim(strtolower($user->email)) != strtolower($existUser->email)) {
1005 - $user->confirmed = 0;
1006 - }
1007 - }
1008 -
1009 - $this->newUser = empty($user->id);
1010 - if (empty($user->id) || $allowUserModifications) {
1011 - if (isset($user->confirmed) && $user->confirmed != 1) {
1012 - $user->confirmed = 0;
1013 - }
1014 - if (isset($user->active) && $user->active != 1) {
1015 - $user->active = 0;
1016 - }
1017 - $customFieldData = acym_getVar('array', 'customField', []);
1018 - $id = $this->save($user, $customFieldData, $ajax);
1019 - $allowSubscriptionModifications = true;
1020 - } else {
1021 - $id = $user->id;
1022 - if (isset($user->confirmed) && empty($user->confirmed)) {
1023 - $this->sendConfirmation($id);
1024 - }
1025 - }
1026 -
1027 - if (empty($id)) return false;
1028 -
1029 - $formData = acym_getVar('array', 'data', []);
1030 - acym_setVar('userId', $id);
1031 -
1032 - if (!acym_isAdmin()) {
1033 - $hiddenlistsString = acym_getVar('string', 'hiddenlists', '');
1034 - $hiddenlists = explode(',', $hiddenlistsString);
1035 - acym_arrayToInteger($hiddenlists);
1036 - $visibleSubscription = acym_getVar('array', 'subscription', []);
1037 - $subscribeLists = array_merge($hiddenlists, $visibleSubscription);
1038 - if (!empty($subscribeLists)) {
1039 - foreach ($subscribeLists as $oneListId) {
1040 - $formData['listsub'][$oneListId] = ['status' => 1];
1041 - }
1042 - }
1043 - }
1044 -
1045 - $fromProfile = acym_getVar('int', 'acyprofile', 0) == 1;
1046 -
1047 - if (empty($formData['listsub'])) {
1048 - if (!$fromProfile) $this->sendNotification($id, 'acy_notification_subform');
1049 -
1050 - $this->sendNotification(
1051 - $id,
1052 - $this->newUser ? 'acy_notification_create' : 'acy_notification_profile'
1053 - );
1054 -
1055 - return true;
1056 - }
1057 -
1058 - if (!$allowSubscriptionModifications) {
1059 - $this->requireId = true;
1060 - $this->errors[] = acym_translation('ACYM_NOT_ALLOWED_MODIFY_USER');
1061 -
1062 - return false;
1063 - }
1064 -
1065 - $addLists = [];
1066 - $unsubLists = [];
1067 - foreach ($formData['listsub'] as $listID => $oneList) {
1068 - if ($oneList['status'] == 1) {
1069 - $addLists[] = $listID;
1070 - } else {
1071 - $unsubLists[] = $listID;
1072 - }
1073 - }
1074 -
1075 - $this->subscribed = $this->subscribe($id, $addLists);
1076 -
1077 - if (!$fromProfile) $this->sendNotification($id, 'acy_notification_subform');
1078 -
1079 - $this->sendNotification(
1080 - $id,
1081 - $this->newUser ? 'acy_notification_create' : 'acy_notification_profile'
1082 - );
1083 -
1084 - if (!$this->newUser) $this->unsubscribe($id, $unsubLists);
1085 -
1086 - return true;
1087 - }
1088 -
1089 - public function sendConfirmation($userID)
1090 - {
1091 - if (!$this->forceConf && !$this->sendConf) {
1092 - return;
1093 - }
1094 -
1095 - if ($this->config->get('require_confirmation', 1) != 1 || (acym_isAdmin() && !$this->forceConfAdmin)) {
1096 - return;
1097 - }
1098 -
1099 - $myUser = $this->getOneById($userID);
1100 -
1101 - if (!empty($myUser->confirmed)) {
1102 - return;
1103 - }
1104 -
1105 - $mailerHelper = new MailerHelper();
1106 - $mailerHelper->report = $this->config->get('confirm_message', 0);
1107 -
1108 - $mailClass = new MailClass();
1109 - $confirmationEmail = $mailClass->getOneByName('acy_confirm');
1110 - $this->confirmationSentSuccess = !empty($confirmationEmail) && $mailerHelper->sendOne($confirmationEmail->id, $myUser);
1111 - $this->confirmationSentError = $mailerHelper->reportMessage;
1112 - }
1113 -
1114 - public function deactivate($userId)
1115 - {
1116 - acym_query('UPDATE `#__acym_user` SET `active` = 0 WHERE `id` = '.intval($userId));
1117 - }
1118 -
1119 - public function confirm($userId)
1120 - {
1121 - $user = $this->getOneById($userId);
1122 - if (empty($user)) return;
1123 -
1124 - $confirmDate = date('Y-m-d H:i:s', time() - date('Z'));
1125 - $ip = acym_getIP();
1126 - $query = 'UPDATE `#__acym_user`';
1127 - $query .= ' SET `confirmed` = 1, `confirmation_date` = '.acym_escapeDB($confirmDate).', `confirmation_ip` = '.acym_escapeDB($ip);
1128 - $query .= ' WHERE `id` = '.intval($userId).' LIMIT 1';
1129 -
1130 - try {
1131 - $res = acym_query($query);
1132 - } catch (\Exception $e) {
1133 - $res = false;
1134 - }
1135 - if ($res === false) {
1136 - $errorMessage = isset($e) ? $e->getMessage() : acym_getDBError();
1137 - $msg = acym_translation('ACYM_CONTACT_ADMIN_ERROR').'<br />'.substr(strip_tags($errorMessage), 0, 200).'...';
1138 - acym_display($msg, 'error');
1139 - exit;
1140 - }
1141 -
1142 - acym_trigger('onAcymAfterUserConfirm', [&$user]);
1143 - $this->sendNotification($userId, 'acy_notification_confirm');
1144 -
1145 - $historyClass = new HistoryClass();
1146 - $historyClass->insert($userId, 'confirmed');
1147 -
1148 - if (empty($this->config->get('require_confirmation', 1))) return;
1149 -
1150 - $listIDs = acym_loadResultArray('SELECT `list_id` FROM `#__acym_user_has_list` WHERE `status` = 1 AND `user_id` = '.intval($userId));
1151 -
1152 - if (empty($listIDs)) return;
1153 -
1154 - $listClass = new ListClass();
1155 - $listClass->sendWelcome($userId, $listIDs);
1156 - }
1157 -
1158 - public function getOneByIdWithCustomFields($id)
1159 - {
1160 - $user = $this->getOneById($id);
1161 - if (empty($user)) {
1162 - return [];
1163 - }
1164 - $user = get_object_vars($user);
1165 -
1166 - $fieldsValue = acym_loadObjectList(
1167 - 'SELECT user_field.`value`, field.`name`
1168 - FROM #__acym_user_has_field AS `user_field`
1169 - LEFT JOIN #__acym_field AS `field` ON user_field.`field_id` = field.`id`
1170 - WHERE user_field.`user_id` = '.intval($id),
1171 - 'name'
1172 - );
1173 -
1174 - foreach ($fieldsValue as $key => $value) {
1175 - $fieldsValue[$key] = $value->value;
1176 - }
1177 -
1178 - return array_merge($user, $fieldsValue);
1179 - }
1180 -
1181 - public function getOneWithCustomFields($column, $value): array
1182 - {
1183 - switch ($column) {
1184 - case 'id':
1185 - $user = $this->getOneById($value);
1186 - break;
1187 - case 'email':
1188 - $user = $this->getOneByEmail($value);
1189 - break;
1190 - case 'cms_id':
1191 - $user = $this->getOneByCMSId($value);
1192 - break;
1193 - default:
1194 - return [];
1195 - }
1196 -
1197 - if (empty($user)) {
1198 - return [];
1199 - }
1200 - $user = get_object_vars($user);
1201 -
1202 - $fieldsValue = acym_loadObjectList(
1203 - 'SELECT user_field.`value`, field.`name`
1204 - FROM #__acym_user_has_field AS `user_field`
1205 - LEFT JOIN #__acym_field AS `field` ON user_field.`field_id` = field.`id`
1206 - WHERE user_field.`user_id` = '.intval($user['id']),
1207 - 'name'
1208 - );
1209 -
1210 - foreach ($fieldsValue as $key => $value) {
1211 - $fieldsValue[$key] = $value->value;
1212 - }
1213 -
1214 - return array_merge($user, $fieldsValue);
1215 - }
1216 -
1217 - public function getCustomFieldValueById($id)
1218 - {
1219 - $fieldsValue = acym_loadObjectList(
1220 - 'SELECT user_field.value AS value, field.name AS name, field.type AS type, field.value AS field_params, field.id AS id
1221 - FROM #__acym_user_has_field as user_field
1222 - LEFT JOIN #__acym_field as field ON user_field.field_id = field.id
1223 - WHERE user_field.user_id = '.intval($id),
1224 - 'id'
1225 - );
1226 -
1227 - $fieldReturn = [];
1228 -
1229 - foreach ($fieldsValue as $fieldId => $field) {
1230 - if (in_array($field->type, ['checkbox', 'radio', 'single_dropdown', 'multiple_dropdown'])) {
1231 - $field->field_params = json_decode($field->field_params, true);
1232 - $field->value = explode(',', $field->value);
1233 - $values = [];
1234 - foreach ($field->value as $oneValue) {
1235 - $key = array_search($oneValue, array_column($field->field_params, 'value'));
1236 - $values[] = $field->field_params[$key]['title'];
1237 - }
1238 - $fieldReturn[$field->name] = implode(',', $values);
1239 - } else {
1240 - $fieldReturn[$field->name] = $field->value;
1241 - }
1242 - }
1243 -
1244 - return $fieldReturn;
1245 - }
1246 -
1247 - public function getAllColumnsUserAndCustomField($inAction = false)
1248 - {
1249 - $return = [];
1250 -
1251 - $userFields = acym_getColumns('user');
1252 - foreach ($userFields as $value) {
1253 - $return[$value] = $value;
1254 - }
1255 -
1256 - $languageFieldId = $this->config->get(FieldClass::LANGUAGE_FIELD_ID_KEY, 0);
1257 -
1258 - $customFields = acym_loadObjectList(
1259 - 'SELECT * FROM #__acym_field WHERE id NOT IN (1, 2, '.intval($languageFieldId).') '.($inAction ? 'AND type != "phone"' : ''),
1260 - 'id'
1261 - );
1262 - if (!empty($customFields)) {
1263 - foreach ($customFields as $key => $value) {
1264 - $return[$key] = $value->name;
1265 - }
1266 - }
1267 -
1268 - return $return;
1269 - }
1270 -
1271 - public function getAllUserFields($user)
1272 - {
1273 - if (empty($user->id)) return $user;
1274 - $query = 'SELECT field.*, field.value AS field_value, userfield.*
1275 - FROM #__acym_field AS field
1276 - LEFT JOIN #__acym_user_has_field AS userfield ON field.id = userfield.field_id AND userfield.user_id = '.intval($user->id).'
1277 - WHERE field.id NOT IN(1, 2)';
1278 -
1279 - $allFields = acym_loadObjectList($query);
1280 -
1281 - foreach ($allFields as $oneField) {
1282 - $fieldOptions = @json_decode(empty($oneField->option) ? '{}' : $oneField->option);
1283 - if (in_array($oneField->type, ['multiple_dropdown', 'radio', 'checkbox', 'single_dropdown'])) {
1284 - $oneField->field_value = json_decode($oneField->field_value, true);
1285 - if (!empty($oneField->value)) {
1286 - $oneField->value = explode(',', $oneField->value);
1287 - $values = [];
1288 - foreach ($oneField->field_value as $oneFieldValue) {
1289 - foreach ($oneField->value as $oneValue) {
1290 - if ($oneFieldValue['value'] == $oneValue) {
1291 - $values[] = $oneFieldValue['title'];
1292 - }
1293 - }
1294 - }
1295 - $oneField->value = implode(',', $values);
1296 - }
1297 - } elseif ($oneField->type === 'file' && !empty($oneField->value)) {
1298 - $oneField->value = json_decode($oneField->value);
1299 - if (!empty($oneField->value)) {
1300 - $oneField->value = $oneField->value[0];
1301 - }
1302 - } elseif ($oneField->type === 'date') {
1303 - if (empty($fieldOptions->format)) {
1304 - acym_logError('Date field with ID '.$oneField->id.' without format option');
1305 - continue;
1306 - }
1307 - $formatToDisplay = explode('%', str_replace('y', 'Y', $fieldOptions->format));
1308 - unset($formatToDisplay[0]);
1309 - if (!empty($oneField->value)) {
1310 - $oneField->value = acym_date($oneField->value, implode('-', $formatToDisplay));
1311 - }
1312 - }
1313 - $user->{$oneField->namekey} = empty($oneField->value) ? '' : $oneField->value;
1314 - }
1315 -
1316 - return $user;
1317 - }
1318 -
1319 - public function getAllSimpleData()
1320 - {
1321 - return acym_loadObjectList('SELECT email, name FROM #__acym_user');
1322 - }
1323 -
1324 - public function synchSaveCmsUser($user, $isnew, $oldUser = null)
1325 - {
1326 - $source = acym_getVar('string', 'acy_source', '');
1327 - if (empty($source)) acym_setVar('acy_source', ACYM_CMS);
1328 -
1329 - if (!$this->config->get('regacy', 0)) return;
1330 -
1331 - $this->checkVisitor = false;
1332 - $this->sendConf = false;
1333 -
1334 - $regacyForceConf = $this->config->get('regacy_forceconf', 0);
1335 - $cmsUser = new \stdClass();
1336 - $cmsUser->email = trim(strip_tags($user['email']));
1337 - if (!acym_isValidEmail($cmsUser->email)) return;
1338 - if (!empty($user['name'])) $cmsUser->name = trim(strip_tags($user['name']));
1339 - if (!$regacyForceConf) $cmsUser->confirmed = 1;
1340 - $cmsUser->active = 1 - intval($user['block']);
1341 - $cmsUser->cms_id = $user['id'];
1342 -
1343 - if (!$isnew && !empty($oldUser['email']) && $user['email'] != $oldUser['email']) {
1344 - $acyUser = $this->getOneByEmail($oldUser['email']);
1345 - if (!empty($acyUser)) $cmsUser->id = $acyUser->id;
1346 - }
1347 -
1348 - if (empty($cmsUser->id) && !empty($cmsUser->cms_id)) {
1349 - $acyUser = $this->getOneByCMSId($cmsUser->cms_id);
1350 - if (!empty($acyUser)) $cmsUser->id = $acyUser->id;
1351 - }
1352 -
1353 - $acyUser = $this->getOneByEmail($cmsUser->email);
1354 - if (!empty($acyUser)) {
1355 - if (empty($cmsUser->id)) {
1356 - $cmsUser->id = $acyUser->id;
1357 - } elseif ($cmsUser->id != $acyUser->id) {
1358 - $this->delete($acyUser->id);
1359 - }
1360 - } else {
1361 - $cmsUser->source = $source;
1362 - }
1363 -
1364 - $isnew = $isnew || empty($cmsUser->id);
1365 -
1366 - $id = $this->save($cmsUser);
1367 -
1368 - $confirmationRequired = $this->config->get('require_confirmation', 1);
1369 - if (!$isnew && !$regacyForceConf && $user['block'] == 0 && !empty($oldUser['block']) && $confirmationRequired == 1) {
1370 - $this->confirm($id);
1371 - }
1372 -
1373 -
1374 - $currentSubscription = $this->getSubscriptionStatus($id);
1375 -
1376 - $autoLists = $isnew ? $this->config->get('regacy_autolists', '') : '';
1377 - $autoLists = explode(',', $autoLists);
1378 - acym_arrayToInteger($autoLists);
1379 -
1380 - $listsClass = new ListClass();
1381 - $allLists = $listsClass->getAll();
1382 -
1383 - $visibleLists = acym_getVar('string', 'regacy_visible_lists', '');
1384 - $visibleLists = explode(',', $visibleLists);
1385 - acym_arrayToInteger($visibleLists);
1386 -
1387 - $visibleListsChecked = acym_getVar('array', 'regacy_visible_lists_checked', []);
1388 - acym_arrayToInteger($visibleListsChecked);
1389 -
1390 -
1391 - if (!$isnew && !empty($visibleLists)) {
1392 - $currentlySubscribedLists = [];
1393 - foreach ($currentSubscription as $oneSubscription) {
1394 - if ($oneSubscription->status == 1) $currentlySubscribedLists[] = $oneSubscription->list_id;
1395 - }
1396 - $unsubscribeLists = array_intersect($currentlySubscribedLists, array_diff($visibleLists, $visibleListsChecked));
1397 - $this->unsubscribe($id, $unsubscribeLists);
1398 - }
1399 -
1400 - $listsToSubscribe = [];
1401 - foreach ($allLists as $oneList) {
1402 - if (!$oneList->active) continue;
1403 - if (!empty($currentSubscription[$oneList->id]) && $currentSubscription[$oneList->id]->status == 1) continue;
1404 -
1405 - if (in_array($oneList->id, $visibleListsChecked) || (in_array($oneList->id, $autoLists) && !in_array(
1406 - $oneList->id,
1407 - $visibleLists
1408 - ) && empty($currentSubscription[$oneList->id]))) {
1409 - $listsToSubscribe[] = $oneList->id;
1410 - }
1411 - }
1412 -
1413 - if (!empty($listsToSubscribe)) $this->subscribe($id, $listsToSubscribe);
1414 -
1415 - if ($isnew) $this->sendNotification($id, 'acy_notification_create');
1416 -
1417 - $acymailingUser = $this->getOneById($id);
1418 - if (!empty($user['block']) || !empty($acymailingUser->confirmed)) return;
1419 -
1420 - if ($isnew || !empty($oldUser['block'])) {
1421 - if ($confirmationRequired && $regacyForceConf) {
1422 - $this->forceConf = true;
1423 - $this->sendConfirmation($id);
1424 - }
1425 -
1426 - if (!$confirmationRequired && !empty($oldUser['email'])) {
1427 - $listIDs = acym_loadResultArray('SELECT `list_id` FROM `#__acym_user_has_list` WHERE `status` = 1 AND `user_id` = '.intval($id));
1428 - if (empty($listIDs)) return;
1429 - $listsClass->sendWelcome($id, $listIDs);
1430 - }
1431 - }
1432 - }
1433 -
1434 - public function synchDeleteCmsUser($userEmail)
1435 - {
1436 - $acyUser = $this->getOneByEmail($userEmail);
1437 -
1438 - if (empty($acyUser)) return;
1439 -
1440 - if ($this->config->get('regacy', '0') == 1 && $this->config->get('regacy_delete', '0') == 1) {
1441 - $this->delete($acyUser->id);
1442 - } else {
1443 - acym_query('UPDATE #__acym_user SET `cms_id` = 0 WHERE `id` = '.intval($acyUser->id));
1444 - }
1445 - }
1446 -
1447 - public function getUsersLikeEmail($pattern)
1448 - {
1449 - $query = 'SELECT id, email FROM #__acym_user WHERE email LIKE '.acym_escapeDB('%'.$pattern.'%');
1450 -
1451 - return acym_loadObjectList($query);
1452 - }
1453 -
1454 - public function sendNotification($userId, string $notification, array $params = [])
1455 - {
1456 - if (empty($userId) || $this->blockNotifications) return;
1457 -
1458 - $notifyUsers = explode(',', $this->config->get($notification));
1459 - if (acym_isAdmin() || empty($notifyUsers)) return;
1460 -
1461 - $mailer = new MailerHelper();
1462 - $mailer->report = false;
1463 - $mailer->autoAddUser = true;
1464 -
1465 - $user = $this->getOneById($userId);
1466 - $userField = $this->getAllUserFields($user);
1467 - if (!empty($userField)) {
1468 - foreach ($userField as $map => $value) {
1469 - $mailer->addParam('user:'.$map, $value);
1470 - }
1471 - }
1472 -
1473 - $rawSubscription = $this->getUserSubscriptionById($userId);
1474 - $subscription = [''];
1475 - foreach ($rawSubscription as $listId => $listData) {
1476 - $currentList = $listData->name.' => ';
1477 - if (intval($listData->status) === 1) {
1478 - $currentList .= acym_translation('ACYM_SUBSCRIBED').' - '.$listData->subscription_date;
1479 - } else {
1480 - $currentList .= acym_translation('ACYM_UNSUBSCRIBED').' - '.$listData->unsubscribe_date;
1481 - }
1482 - $subscription[] = $currentList;
1483 - }
1484 - $mailer->addParam('user:subscription', implode('<br/>', $subscription));
1485 -
1486 - if (!empty($params)) {
1487 - foreach ($params as $name => $value) {
1488 - $mailer->addParam($name, $value);
1489 - }
1490 - }
1491 -
1492 - $mailClass = new MailClass();
1493 - foreach ($notifyUsers as $oneUser) {
1494 - if (!acym_isValidEmail($oneUser)) {
1495 - continue;
1496 - }
1497 -
1498 - $notificationEmail = $mailClass->getOneByName($notification);
1499 - if (!empty($notificationEmail)) {
1500 - $mailer->sendOne($notificationEmail->id, $oneUser);
1501 - }
1502 - }
1503 - }
1504 -
1505 - public function getMailHistory($userId)
1506 - {
1507 - $query = 'SELECT user_stat.*, mail.id, mail.subject, SUM(url_click.click) as click FROM #__acym_user_stat AS user_stat
1508 - JOIN #__acym_mail AS mail ON mail.id = user_stat.mail_id
1509 - LEFT JOIN #__acym_url_click AS url_click ON user_stat.mail_id = url_click.mail_id AND url_click.user_id = '.intval($userId).'
1510 - WHERE user_stat.user_id = '.intval($userId).' GROUP BY mail_id ORDER BY send_date DESC LIMIT 50';
1511 -
1512 - $mailHistory = acym_loadObjectList($query, 'mail_id');
1513 - $mailClass = new MailClass();
1514 -
1515 - return $mailClass->decode($mailHistory);
1516 - }
1517 -
1518 - public function deleteHistoryPeriod()
1519 - {
1520 - if (empty($this->config->get('delete_user_history_enabled', 0))) return;
1521 - $deleteOverSecond = $this->config->get('delete_user_history', 0);
1522 - if (empty($deleteOverSecond)) return;
1523 - $date = time() - $deleteOverSecond;
1524 -
1525 - $query = 'DELETE FROM #__acym_history WHERE date < '.intval($date);
1526 -
1527 - try {
1528 - $status = acym_query($query);
1529 - $message = empty($status) ? '' : acym_translationSprintf('ACYM_DELETE_X_ROWS_TABLE_X', $status, strtolower(acym_translation('ACYM_USER_HISTORY')));
1530 - } catch (\Exception $e) {
1531 - $status = false;
1532 - $message = $e->getMessage();
1533 - }
1534 -
1535 - return ['status' => $status !== false, 'message' => $message];
1536 - }
1537 -
1538 - public function resetSubscription($userIds, $lists)
1539 - {
1540 - if (empty($lists)) return false;
1541 -
1542 - if (!is_array($userIds)) $userIds = [$userIds];
1543 - if (!is_array($lists)) $lists = [$lists];
1544 -
1545 - acym_arrayToInteger($userIds);
1546 - acym_arrayToInteger($lists);
1547 -
1548 - foreach ($userIds as $userId) {
1549 - acym_query(
1550 - 'DELETE FROM `#__acym_user_has_list`
1551 - WHERE user_id = '.$userId.'
1552 - AND list_id IN ('.implode(',', $lists).')'
1553 - );
1554 -
1555 - acym_query(
1556 - 'DELETE FROM #__acym_queue WHERE user_id = '.$userId.' AND mail_id IN (
1557 - SELECT followup_mail.mail_id FROM #__acym_followup_has_mail AS followup_mail
1558 - JOIN #__acym_followup AS followup ON followup.id = followup_mail.followup_id AND followup.list_id IN ('.implode(',', $lists).')
1559 - )'
1560 - );
1561 -
1562 - $historyClass = new HistoryClass();
1563 - $historyData = acym_translationSprintf('ACYM_LISTS_NUMBERS', implode(', ', $lists));
1564 - $historyClass->insert($userId, 'reset_subscription', [$historyData]);
1565 - }
1566 -
1567 - return true;
1568 - }
1569 -
1570 - public function addMissingKeys()
1571 - {
1572 - $usersMissingKey = acym_loadResultArray('SELECT `id` FROM #__acym_user WHERE `key` IS NULL OR `key` = ""');
1573 - foreach ($usersMissingKey as $oneUserId) {
1574 - acym_query('UPDATE #__acym_user SET `key` = '.acym_escapeDB(acym_generateKey(14)).' WHERE `id` = '.intval($oneUserId));
1575 - }
1576 -
1577 - return count($usersMissingKey);
1578 - }
1579 -
1580 - public function hasUserAccess($subscriberId): bool
1581 - {
1582 - $userId = acym_currentUserId();
1583 - if (empty($userId)) {
1584 - return false;
1585 - }
1586 -
1587 - if (acym_isAdmin()) {
1588 - return true;
1589 - }
1590 -
1591 - $user = $this->getOneById($subscriberId);
1592 - $userEmail = acym_currentUserEmail();
1593 - if (!empty($user) && $user->email === $userEmail) {
1594 - return true;
1595 - }
1596 -
1597 - $listClass = new ListClass();
1598 - $allowedListIds = $listClass->getManageableLists();
1599 - if (empty($allowedListIds)) {
1600 - return false;
1601 - }
1602 -
1603 - $query = 'SELECT COUNT(*) FROM #__acym_user AS user
1604 - JOIN #__acym_user_has_list AS map ON map.user_id = user.id
1605 - WHERE map.list_id IN ('.implode(',', $allowedListIds).')
1606 - AND user.id = '.intval($subscriberId);
1607 -
1608 - return acym_loadResult($query) > 0;
1609 - }
1610 -
1611 - public function getXUsers(array $options = [])
1612 - {
1613 - $limit = $options['limit'] ?? 10;
1614 - $offset = $options['offset'] ?? 0;
1615 - $filters = $options['filters'] ?? [];
1616 -
1617 - $conditions = [];
1618 - foreach ($filters as $column => $filter) {
1619 - switch ($column) {
1620 - case 'id':
1621 - case 'cms_id':
1622 - case 'active':
1623 - case 'confirmed':
1624 - case 'tracking':
1625 - $conditions[] = acym_secureDBColumn($column).' = '.intval($filter);
1626 - break;
1627 - default:
1628 - $conditions[] = acym_secureDBColumn($column).' LIKE '.acym_escapeDB('%'.$filter.'%');
1629 - }
1630 - }
1631 -
1632 - if (!empty($options['created_after'])) {
1633 - $conditions[] = 'creation_date > '.acym_escapeDB($options['created_after']);
1634 - }
1635 -
1636 - if (!empty($options['confirmed_after'])) {
1637 - $conditions[] = 'confirmation_date > '.acym_escapeDB($options['confirmed_after']);
1638 - }
1639 -
1640 - $query = 'SELECT * FROM #__acym_user';
1641 - if (!empty($conditions)) {
1642 - $query .= ' WHERE '.implode(' AND ', $conditions);
1643 - }
1644 -
1645 - return acym_loadObjectList($query, $this->pkey, $offset, $limit);
1646 - }
1647 -}