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