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/MailClass.php +0 -1602 10.11.1 → 11.1.1 View file →
@@ -1,1602 +1,0 @@
1 -<?php
2 -
3 -namespace AcyMailing\Classes;
4 -
5 -use AcyMailing\Helpers\MailerHelper;
6 -use AcyMailing\Helpers\PaginationHelper;
7 -use AcyMailing\Helpers\PluginHelper;
8 -use AcyMailing\Core\AcymClass;
9 -
10 -class MailClass extends AcymClass
11 -{
12 - const FIELDS_ENCODING = [
13 - 'name',
14 - 'subject',
15 - 'body',
16 - 'autosave',
17 - 'preheader',
18 - ];
19 -
20 - const TYPE_STANDARD = 'standard';
21 - const TYPE_NOTIFICATION = 'notification';
22 - const TYPE_OVERRIDE = 'override';
23 - const TYPE_WELCOME = 'welcome';
24 - const TYPE_UNSUBSCRIBE = 'unsubscribe';
25 - const TYPE_AUTOMATION = 'automation';
26 - const TYPE_FOLLOWUP = 'followup';
27 - const TYPE_MAILBOX_ACTION = 'mailbox_action';
28 - const TYPE_TEMPLATE = 'template';
29 - const TYPE_SCENARIO = 'scenario';
30 -
31 - const ALL_TYPES = [
32 - self::TYPE_STANDARD,
33 - self::TYPE_NOTIFICATION,
34 - self::TYPE_OVERRIDE,
35 - self::TYPE_WELCOME,
36 - self::TYPE_UNSUBSCRIBE,
37 - self::TYPE_AUTOMATION,
38 - self::TYPE_FOLLOWUP,
39 - self::TYPE_MAILBOX_ACTION,
40 - self::TYPE_TEMPLATE,
41 - self::TYPE_SCENARIO,
42 - ];
43 -
44 - const TYPES_TRANSACTIONAL = [
45 - self::TYPE_NOTIFICATION,
46 - self::TYPE_OVERRIDE,
47 - self::TYPE_WELCOME,
48 - self::TYPE_UNSUBSCRIBE,
49 - self::TYPE_TEMPLATE,
50 - self::TYPE_SCENARIO,
51 - ];
52 -
53 - const TYPES_WITH_STATS = [
54 - self::TYPE_STANDARD,
55 - self::TYPE_AUTOMATION,
56 - self::TYPE_WELCOME,
57 - self::TYPE_UNSUBSCRIBE,
58 - self::TYPE_FOLLOWUP,
59 - self::TYPE_MAILBOX_ACTION,
60 - self::TYPE_SCENARIO,
61 - ];
62 -
63 - const TYPES_NO_NAME = [
64 - self::TYPE_NOTIFICATION,
65 - self::TYPE_OVERRIDE,
66 - ];
67 -
68 - const MAX_ALLOWED_TEMPLATE_FILES = 100;
69 - const MAX_ALLOWED_TEMPLATE_SIZE = 20971520;
70 - const ALLOWED_TEMPLATE_FILE_TYPES = [
71 - 'image/jpeg',
72 - 'image/png',
73 - 'image/gif',
74 - 'text/html',
75 - 'image/x-ms-bmp',
76 - 'image/bmp',
77 - 'text/plain',
78 - 'image/vnd.microsoft.icon',
79 - ];
80 -
81 - private array $templateNames = [];
82 - public array $exceptKeysDecode = [];
83 -
84 - public function __construct()
85 - {
86 - parent::__construct();
87 -
88 - $this->table = 'mail';
89 - $this->pkey = 'id';
90 - }
91 -
92 - public function getMatchingElements(array $settings = []): array
93 - {
94 - $query = 'SELECT mail.* FROM #__acym_mail AS mail';
95 - $queryCount = 'SELECT COUNT(mail.id) AS total FROM #__acym_mail AS mail';
96 -
97 - $filters = [];
98 - $tagJoin = '';
99 -
100 - if (!empty($settings['tag'])) {
101 - $tagJoin = ' JOIN #__acym_tag AS tag ON mail.id = tag.id_element ';
102 - $filters[] = 'tag.name = '.acym_escapeDB($settings['tag']);
103 - $filters[] = 'tag.type = "mail"';
104 - }
105 - $query .= $tagJoin;
106 - $queryCount .= $tagJoin;
107 -
108 - if (!empty($settings['search'])) {
109 - $filters[] = 'mail.name LIKE '.acym_escapeDB('%'.acym_utf8Encode($settings['search']).'%');
110 - }
111 -
112 - if (!empty($settings['gettingTemplates'])) {
113 - $filters[] = 'mail.type = '.acym_escapeDB(self::TYPE_TEMPLATE);
114 - if (!acym_isAdmin()) {
115 - $currentUserId = acym_currentUserId();
116 - $condition = 'mail.creator_id = '.intval($currentUserId);
117 -
118 - $userGroups = acym_getGroupsByUser($currentUserId);
119 - if (!empty($userGroups)) {
120 - $condition .= ' OR access LIKE "%,'.implode(',%" OR access LIKE "%,', $userGroups).',%"';
121 - }
122 -
123 - $filters[] = $condition;
124 - }
125 - } else {
126 - if (!empty($settings['automation']) || empty($settings['onlyStandard'])) {
127 - $filters[] = 'mail.type != '.acym_escapeDB(self::TYPE_NOTIFICATION);
128 - $filters[] = 'mail.type != '.acym_escapeDB(self::TYPE_OVERRIDE);
129 - } else {
130 - $filters[] = 'mail.type IN ('.acym_escapeDB(self::TYPE_STANDARD).', '.acym_escapeDB(self::TYPE_TEMPLATE).')';
131 - }
132 -
133 - if (empty($settings['automation'])) {
134 - $filters[] = 'mail.type IN ('.acym_escapeDB(self::TYPE_TEMPLATE).', '.acym_escapeDB(self::TYPE_WELCOME).', '.acym_escapeDB(self::TYPE_UNSUBSCRIBE).')';
135 - }
136 -
137 - if (!empty($settings['creator_id'])) {
138 - $mailTypeCondition = 'mail.type IN ('.acym_escapeDB(self::TYPE_TEMPLATE).', '.acym_escapeDB(self::TYPE_WELCOME).', '.acym_escapeDB(self::TYPE_UNSUBSCRIBE).')';
139 - $userGroups = acym_getGroupsByUser($settings['creator_id']);
140 - $groupCondition = '(mail.access LIKE "%,'.implode(',%" OR mail.access LIKE "%,', $userGroups).',%")';
141 - $filter = 'mail.creator_id = '.intval($settings['creator_id']).' OR ('.$mailTypeCondition.' AND '.$groupCondition.')';
142 -
143 - if (!acym_isAdmin() && !empty($settings['element_tab'])) {
144 - $filter = '('.$filter.')
145 - OR list.cms_user_id = '.intval($settings['creator_id']).'
146 - OR (list.access LIKE "%,'.implode(',%" OR list.access LIKE "%,', $userGroups).',%")';
147 - }
148 -
149 - $filters['list'] = '('.$filter.')';
150 - }
151 - }
152 -
153 - $filters[] = 'mail.parent_id IS NULL';
154 -
155 - if (!empty($settings['drag_editor'])) {
156 - $filters[] = 'mail.drag_editor = 1';
157 - }
158 -
159 - if (!empty($settings['element_tab'])) {
160 - $query = 'SELECT DISTINCT mail.*, mail_stat.sent as subscribers, mail_stat.open_unique FROM #__acym_mail AS mail';
161 - $query .= ' LEFT JOIN #__acym_mail_stat AS mail_stat ON mail.id = mail_stat.mail_id ';
162 - if (!empty($settings['tag'])) {
163 - $query .= ' JOIN #__acym_tag AS tag ON mail.id = tag.id_element ';
164 - }
165 - if (!acym_isAdmin()) {
166 - $query .= ' LEFT JOIN #__acym_list AS list ON list.'.acym_secureDBColumn($settings['element_tab']).'_id = mail.id';
167 - }
168 - $filters[] = 'mail.type = '.acym_escapeDB($settings['element_tab']);
169 - }
170 -
171 - if (!empty($filters)) {
172 - $query .= ' WHERE ('.implode(') AND (', $filters).')';
173 - if (!acym_isAdmin()) {
174 - unset($filters['list']);
175 - }
176 - $queryCount .= ' WHERE ('.implode(') AND (', $filters).')';
177 - }
178 -
179 - if (!empty($settings['ordering']) && !empty($settings['ordering_sort_order'])) {
180 - $query .= ' ORDER BY mail.'.acym_secureDBColumn($settings['ordering']).' '.acym_secureDBColumn(strtoupper($settings['ordering_sort_order']));
181 - }
182 -
183 - if (empty($settings['offset']) || $settings['offset'] < 0) {
184 - $settings['offset'] = 0;
185 - }
186 -
187 - if (empty($settings['elementsPerPage']) || $settings['elementsPerPage'] < 1) {
188 - $pagination = new PaginationHelper();
189 - $settings['elementsPerPage'] = $pagination->getListLimit();
190 - }
191 -
192 - $results['elements'] = $this->decode(acym_loadObjectList($query, '', $settings['offset'], $settings['elementsPerPage']));
193 - $results['total'] = acym_loadObject($queryCount);
194 -
195 - if (!empty($settings['element_tab'])) {
196 - $this->getAllListIdsForWelcomeUnsub($results['elements'], $settings['element_tab']);
197 - }
198 -
199 - $results['status'] = [];
200 -
201 - if (!empty($settings['element_tab'])) {
202 - $urlClickClass = new UrlClickClass();
203 - for ($i = 0; $i < count($results['elements']); $i++) {
204 - $results['elements'][$i]->open = 0;
205 - if (!empty($results['elements'][$i]->subscribers)) {
206 - $results['elements'][$i]->open = number_format($results['elements'][$i]->open_unique / $results['elements'][$i]->subscribers * 100, 2);
207 -
208 - $clicksNb = $urlClickClass->getNumberUsersClicked([$results['elements'][$i]->id]);
209 - $results['elements'][$i]->click = number_format($clicksNb / $results['elements'][$i]->subscribers * 100, 2);
210 - }
211 - }
212 - }
213 -
214 - return $results;
215 - }
216 -
217 - private function getAllListIdsForWelcomeUnsub(array $elements, string $type): void
218 - {
219 - if (empty($elements)) {
220 - return;
221 - }
222 -
223 - $column = $type === self::TYPE_WELCOME ? 'welcome_id' : 'unsubscribe_id';
224 -
225 - foreach ($elements as $element) {
226 - $element->lists = acym_loadObjectList('SELECT color, name FROM #__acym_list WHERE '.acym_secureDBColumn($column).' = '.intval($element->id));
227 - }
228 - }
229 -
230 - public function getAll(?string $key = null): array
231 - {
232 - $allMails = parent::getAll($key);
233 -
234 - return $this->decode($allMails);
235 - }
236 -
237 - public function getOneById(int $id, bool $needTranslatedSettings = false): ?object
238 - {
239 - $mail = $this->decode(parent::getOneById($id));
240 -
241 - if (!empty($mail)) {
242 - $tagsClass = new TagClass();
243 - $mail->tags = $tagsClass->getAllTagsByElementId(TagClass::TYPE_MAIL, intval($id));
244 - }
245 -
246 - if (isset($mail->access) && !is_array($mail->access)) $mail->access = explode(',', $mail->access);
247 -
248 - if (!empty($mail->parent_id) && $needTranslatedSettings) {
249 - $this->getTranslatedSettingsMail($mail);
250 - }
251 -
252 - return $mail;
253 - }
254 -
255 - private function getTranslatedSettingsMail(object $mail): void
256 - {
257 - $parentMailTranslation = acym_loadResult('SELECT translation FROM #__acym_mail WHERE id = '.intval($mail->parent_id));
258 - $parentMailTranslation = empty($parentMailTranslation) ? [] : json_decode($parentMailTranslation, true);
259 -
260 - $translationConfig = $this->config->get('sender_info_translation', '');
261 - $translationConfig = empty($translationConfig) ? [] : json_decode($translationConfig, true);
262 -
263 - if (!empty($parentMailTranslation[$mail->language])) {
264 - $senderTranslation = $parentMailTranslation[$mail->language];
265 - } elseif (!empty($translationConfig[$mail->language])) {
266 - $senderTranslation = $translationConfig[$mail->language];
267 - $senderTranslation['reply_to_email'] = $senderTranslation['replyto_email'];
268 - $senderTranslation['reply_to_name'] = $senderTranslation['replyto_name'];
269 - } else {
270 - return;
271 - }
272 -
273 - $mail->from_name = $senderTranslation['from_name'];
274 - $mail->from_email = $senderTranslation['from_email'];
275 - $mail->reply_to_name = $senderTranslation['reply_to_name'];
276 - $mail->reply_to_email = $senderTranslation['reply_to_email'];
277 - }
278 -
279 - public function getOneByName(string $name, bool $needTranslatedSettings = false, string $type = ''): ?object
280 - {
281 - $query = 'SELECT * FROM #__acym_mail WHERE `parent_id` IS NULL AND `name` = '.acym_escapeDB(acym_utf8Encode($name));
282 - if (!empty($type)) {
283 - $query .= ' AND `type` = '.acym_escapeDB($type);
284 - }
285 -
286 - $mail = acym_loadObject($query);
287 -
288 - if (empty($mail)) {
289 - return null;
290 - }
291 -
292 - $mail = $this->decode($mail);
293 -
294 - if (!empty($mail)) {
295 - $tagsClass = new TagClass();
296 - $mail->tags = $tagsClass->getAllTagsByElementId(TagClass::TYPE_MAIL, intval($mail->id));
297 - }
298 -
299 - if (!empty($mail->parent_id) && $needTranslatedSettings) {
300 - $this->getTranslatedSettingsMail($mail);
301 - }
302 -
303 - return $mail;
304 - }
305 -
306 - public function getMailsByType(?string $typeMail, array $settings): array
307 - {
308 - if (empty($settings['key'])) {
309 - $settings['key'] = '';
310 - }
311 - if (empty($settings['offset'])) {
312 - $settings['offset'] = 0;
313 - }
314 - if (empty($settings['mailsPerPage'])) {
315 - $settings['mailsPerPage'] = 12;
316 - }
317 - $search = $settings['filters']['search'] ?? '';
318 -
319 - $query = 'SELECT * FROM #__acym_mail AS mail';
320 - $queryCount = 'SELECT count(*) FROM #__acym_mail AS mail';
321 -
322 - $filters = [];
323 - if (!empty($typeMail)) {
324 - $filters[] = 'mail.type = '.acym_escapeDB($typeMail);
325 - }
326 -
327 - if (!empty($search)) {
328 - $filters[] = 'mail.name LIKE '.acym_escapeDB('%'.$search.'%');
329 - }
330 -
331 - if (!empty($filters)) {
332 - $query .= ' WHERE ('.implode(') AND (', $filters).')';
333 - $queryCount .= ' WHERE ('.implode(') AND (', $filters).')';
334 - }
335 -
336 - $query .= ' ORDER BY id DESC';
337 -
338 - $results['mails'] = $this->decode(acym_loadObjectList($query, $settings['key'], $settings['offset'], $settings['mailsPerPage']));
339 - $results['total'] = acym_loadResult($queryCount);
340 -
341 - return $results;
342 - }
343 -
344 - public function getAllListsWithCountSubscribersByMailIds(array $ids): array
345 - {
346 - acym_arrayToInteger($ids);
347 - if (empty($ids)) {
348 - return [];
349 - }
350 -
351 - $query = 'SELECT mailLists.list_id, mailLists.mail_id, list.*, COUNT(userLists.user_id) AS subscribers
352 - FROM #__acym_mail_has_list AS mailLists
353 - JOIN #__acym_list AS list ON mailLists.list_id = list.id
354 - LEFT JOIN #__acym_user_has_list AS userLists
355 - JOIN #__acym_user AS acyuser ON userLists.user_id = acyuser.id
356 - AND userLists.status = 1
357 - AND acyuser.active = 1 ';
358 -
359 - if ($this->config->get('require_confirmation', 1) == 1) {
360 - $query .= ' AND acyuser.confirmed = 1 ';
361 - }
362 -
363 - $query .= 'ON list.id = userLists.list_id
364 - WHERE mailLists.mail_id IN ('.implode(',', $ids).')
365 - GROUP BY mailLists.list_id, mailLists.mail_id';
366 -
367 - acym_query('SET SQL_BIG_SELECTS=1');
368 -
369 - return acym_loadObjectList($query);
370 - }
371 -
372 - public function getAllListsByMailIds(array $ids): array
373 - {
374 - acym_arrayToInteger($ids);
375 - if (empty($ids)) {
376 - return [];
377 - }
378 -
379 - $query = 'SELECT mailLists.mail_id, list.name, list.color
380 - FROM #__acym_mail_has_list AS mailLists
381 - JOIN #__acym_list AS list ON mailLists.list_id = list.id
382 - WHERE mailLists.mail_id IN ('.implode(',', $ids).')';
383 -
384 - return acym_loadObjectList($query);
385 - }
386 -
387 - public function getAllListsByMailId(int $id): array
388 - {
389 - $mail = $this->getOneById($id);
390 - if (empty($mail)) {
391 - return [];
392 - }
393 -
394 - if (self::TYPE_WELCOME === $mail->type) {
395 - $query = 'SELECT * FROM #__acym_list WHERE welcome_id = '.intval($id);
396 - } elseif (self::TYPE_FOLLOWUP === $mail->type) {
397 - $query = 'SELECT list.* FROM #__acym_followup_has_mail AS followup_mail
398 - JOIN #__acym_followup AS followup ON followup.id = followup_mail.followup_id AND followup_mail.mail_id = '.intval($id).'
399 - JOIN #__acym_list AS list ON list.id = followup.list_id';
400 - } else {
401 - $query = 'SELECT list.*
402 - FROM #__acym_mail_has_list AS mailLists
403 - JOIN #__acym_mail AS mail ON (mailLists.mail_id = mail.id OR mailLists.mail_id = mail.parent_id) AND mail.id = '.intval($id).'
404 - JOIN #__acym_list AS list ON mailLists.list_id = list.id';
405 - }
406 -
407 - return acym_loadObjectList($query, 'id');
408 - }
409 -
410 - public function getAllListsByMailIdAndUserId(int $mailId, int $userId): array
411 - {
412 - if (empty($mailId) || empty($userId)) {
413 - return [];
414 - }
415 -
416 - $query = 'SELECT list.* FROM #__acym_list AS list';
417 - $query .= ' JOIN #__acym_user_has_list AS userlist ON list.id = userlist.list_id AND userlist.user_id = '.intval($userId);
418 - $query .= ' JOIN #__acym_mail_has_list AS maillist ON maillist.list_id = list.id AND maillist.mail_id = '.intval($mailId);
419 -
420 - return acym_loadObjectList($query);
421 - }
422 -
423 - public function save(object $element): ?int
424 - {
425 - $mail = clone $element;
426 -
427 - if (isset($mail->tags)) {
428 - $tags = $mail->tags;
429 - unset($mail->tags);
430 - }
431 -
432 - if (empty($mail->id)) {
433 - $mail->creation_date = acym_date('now', 'Y-m-d H:i:s', false);
434 - if (empty($mail->creator_id)) $mail->creator_id = acym_currentUserId();
435 - }
436 -
437 - $mail = $this->encode($mail);
438 -
439 - $mail->autosave = null;
440 -
441 -
442 - if (isset($mail->thumbnail) && ((empty($mail->thumbnail) && !is_null($mail->thumbnail)) || strpos($mail->thumbnail, 'data:image/png;base64') !== false)) {
443 - unset($mail->thumbnail);
444 - }
445 -
446 - if (!isset($mail->access)) {
447 - $mail->access = '';
448 - }
449 -
450 - foreach ($mail as $oneAttribute => $value) {
451 - if (empty($value) || in_array($oneAttribute, ['thumbnail', 'settings'])) {
452 - continue;
453 - }
454 -
455 - if ($oneAttribute === 'access' && is_array($mail->$oneAttribute)) {
456 - $value = ','.trim(implode(',', $mail->$oneAttribute), ',').',';
457 - $mail->$oneAttribute = $value;
458 - }
459 -
460 - if (is_array($value)) {
461 - $mail->$oneAttribute = json_encode($value);
462 - }
463 -
464 - if (in_array($oneAttribute, ['body', 'headers'])) {
465 - $mail->$oneAttribute = preg_replace('#<input[^>]*value="[^"]*"[^>]*>#Uis', '', $mail->$oneAttribute);
466 - $mail->$oneAttribute = preg_replace('#<script.*</script>#Uis', '', $mail->$oneAttribute);
467 -
468 - $mail->$oneAttribute = str_replace(' contenteditable="true"', '', $mail->$oneAttribute);
469 - } else {
470 - $mail->$oneAttribute = strip_tags($mail->$oneAttribute);
471 - }
472 - }
473 -
474 - $mailID = parent::save($mail);
475 -
476 - if (!empty($mailID) && isset($tags)) {
477 - $tagClass = new TagClass();
478 - $tagClass->setTags(TagClass::TYPE_MAIL, intval($mailID), $tags);
479 - }
480 -
481 - return $mailID;
482 - }
483 -
484 - public function autoSave(object $mail, string $language = 'main'): bool
485 - {
486 - if (empty($mail->id)) {
487 - return false;
488 - }
489 -
490 - $mail->autosave = str_replace(' contenteditable="true"', '', $mail->autosave);
491 -
492 - if (acym_isMultilingual() && $language !== 'main') {
493 - $translationId = $this->getTranslationId($mail->id, $language);
494 - if (empty($translationId)) {
495 - $parentCopy = $this->getOneById($mail->id);
496 - if (empty($parentCopy)) {
497 - return false;
498 - }
499 -
500 - unset($parentCopy->id);
501 - $parentCopy->parent_id = $mail->id;
502 - $parentCopy->language = $language;
503 - $translationId = $this->save($parentCopy);
504 - }
505 - $mail->id = $translationId;
506 - }
507 -
508 - $mail = $this->encode($mail);
509 -
510 - return (bool)parent::save($mail);
511 - }
512 -
513 - public function delete(array $elements): int
514 - {
515 - if (empty($elements)) return 0;
516 -
517 - $this->deleteMediaFolder($elements);
518 - acym_arrayToInteger($elements);
519 -
520 - $favoriteTemplate = (int)$this->config->get('favorite_template', 0);
521 - if (in_array($favoriteTemplate, $elements)) {
522 - $this->config->saveConfig(['favorite_template' => 0]);
523 - }
524 -
525 - $allThumbnailToDelete = acym_loadResultArray('SELECT DISTINCT thumbnail FROM #__acym_mail WHERE id IN ('.implode(',', $elements).')');
526 -
527 - $translations = acym_loadResultArray('SELECT id FROM #__acym_mail WHERE parent_id IN ('.implode(',', $elements).')');
528 - $elements = array_merge($elements, $translations);
529 - if (!empty($translations)) {
530 - acym_query('UPDATE #__acym_mail SET `parent_id` = null WHERE `id` IN ('.implode(',', $translations).')');
531 - }
532 -
533 - acym_query('UPDATE #__acym_list SET welcome_id = null WHERE welcome_id IN ('.implode(',', $elements).')');
534 - acym_query('UPDATE #__acym_list SET unsubscribe_id = null WHERE unsubscribe_id IN ('.implode(',', $elements).')');
535 - acym_query('DELETE FROM #__acym_queue WHERE mail_id IN ('.implode(',', $elements).')');
536 - acym_query('DELETE FROM #__acym_mail_has_list WHERE mail_id IN ('.implode(',', $elements).')');
537 - acym_query('DELETE FROM #__acym_tag WHERE `type` = "mail" AND `id_element` IN ('.implode(',', $elements).')');
538 - acym_query('DELETE FROM #__acym_user_stat WHERE mail_id IN ('.implode(',', $elements).')');
539 - acym_query('DELETE FROM #__acym_url_click WHERE mail_id IN ('.implode(',', $elements).')');
540 - acym_query('DELETE FROM #__acym_mail_stat WHERE mail_id IN ('.implode(',', $elements).')');
541 - acym_query('DELETE FROM #__acym_followup_has_mail WHERE mail_id IN ('.implode(',', $elements).')');
542 - acym_query('DELETE FROM #__acym_mail_archive WHERE mail_id IN ('.implode(',', $elements).')');
543 -
544 - $return = parent::delete($elements);
545 -
546 - $this->deleteUnusedThumbnails($allThumbnailToDelete);
547 -
548 - return $return;
549 - }
550 -
551 - public function deleteMediaFolder(array $elements): void
552 - {
553 - if (empty($elements)) {
554 - return;
555 - }
556 -
557 - acym_arrayToInteger($elements);
558 - $results = acym_loadResultArray('SELECT mail_settings FROM #__acym_mail WHERE mail_settings IS NOT NULL AND id IN ('.implode(',', $elements).')');
559 -
560 - foreach ($results as $template) {
561 - $settings = json_decode($template, true);
562 -
563 - if (empty($settings['media_folder']) || !file_exists(ACYM_TEMPLATE.$settings['media_folder'])) {
564 - continue;
565 - }
566 - acym_deleteFolder(ACYM_TEMPLATE.$settings['media_folder']);
567 - }
568 - }
569 -
570 - public function deleteUnusedThumbnails(array $thumbnails): void
571 - {
572 - if (empty($thumbnails)) {
573 - return;
574 - }
575 -
576 - foreach ($thumbnails as $key => $oneThumb) {
577 - $thumbnails[$key] = acym_escapeDB($oneThumb);
578 - }
579 -
580 - $stillUsedThumbnails = acym_loadResultArray('SELECT thumbnail FROM #__acym_mail WHERE thumbnail IN ('.implode(',', $thumbnails).')');
581 - $thumbnailToDelete = array_diff($thumbnails, $stillUsedThumbnails);
582 - foreach ($thumbnailToDelete as $one) {
583 - if (!empty($one) && file_exists(ACYM_UPLOAD_FOLDER_THUMBNAIL.$one)) {
584 - unlink(ACYM_UPLOAD_FOLDER_THUMBNAIL.$one);
585 - }
586 - }
587 - }
588 -
589 - public function deleteOneAttachment(int $mailId, int $idAttachment): bool
590 - {
591 - if (empty($mailId)) {
592 - return false;
593 - }
594 -
595 - $mail = $this->getOneById($mailId);
596 -
597 - $attachments = $mail->attachments;
598 - if (empty($attachments)) {
599 - return false;
600 - }
601 - $decodedAttach = json_decode($attachments, true);
602 - unset($decodedAttach[$idAttachment]);
603 - $newAttachments = [];
604 - if (!empty($decodedAttach)) {
605 - foreach ($decodedAttach as $oneAttach) {
606 - $newAttachments[] = $oneAttach;
607 - }
608 - }
609 - $attachDb = json_encode($newAttachments);
610 -
611 - return (bool)acym_query('UPDATE #__acym_mail SET attachments = '.acym_escapeDB($attachDb).' WHERE id = '.intval($mailId).' OR parent_id = '.intval($mailId));
612 - }
613 -
614 - public function createTemplateFile(int $id): string
615 - {
616 - if (empty($id)) {
617 - return '';
618 - }
619 -
620 - $template = $this->getOneById($id);
621 - if (empty($template->id)) {
622 - return '';
623 - }
624 -
625 - $css = $this->buildCSS($template->stylesheet);
626 - if (empty($css)) {
627 - return '';
628 - }
629 -
630 - acym_createDir(ACYM_TEMPLATE.'css');
631 -
632 - $cssfile = ACYM_TEMPLATE.'css'.DS.'template_'.$id.'.css';
633 - if (acym_writeFile($cssfile, $css)) {
634 - return $cssfile;
635 - } else {
636 - acym_enqueueMessage('Could not create the file '.$cssfile, 'error');
637 -
638 - return '';
639 - }
640 - }
641 -
642 - public function buildCSS(?string $stylesheet): string
643 - {
644 - if (empty($stylesheet)) {
645 - return '';
646 - }
647 -
648 - $inline = '';
649 -
650 - if (preg_match_all('#@import[^;]*;#is', $stylesheet, $results)) {
651 - foreach ($results[0] as $oneResult) {
652 - $inline .= trim($oneResult)."\n";
653 - $stylesheet = str_replace($oneResult, '', $stylesheet);
654 - }
655 - }
656 -
657 - $inline .= $stylesheet;
658 -
659 - return $inline;
660 - }
661 -
662 - public function doupload(): bool
663 - {
664 - $zipFilePath = $this->uploadTemplate();
665 - if (empty($zipFilePath)) {
666 - return false;
667 - }
668 -
669 - $templateFolder = $this->extractTemplate($zipFilePath);
670 - if (empty($templateFolder)) {
671 - return false;
672 - }
673 -
674 - if (!$this->installExtractedTemplate($templateFolder)) {
675 - return false;
676 - }
677 -
678 - return true;
679 - }
680 -
681 - private function uploadTemplate(): ?string
682 - {
683 - $importFile = acym_getVar('file', 'uploadedfile', '', 'files');
684 -
685 - $fileError = $importFile['error'];
686 - if ($fileError > 0) {
687 - switch ($fileError) {
688 - case 1:
689 - acym_enqueueMessage(acym_translation('ACYM_FILE_UPLOAD_ERROR_1'), 'error');
690 -
691 - return null;
692 - case 2:
693 - acym_enqueueMessage(acym_translation('ACYM_FILE_UPLOAD_ERROR_2'), 'error');
694 -
695 - return null;
696 - case 3:
697 - acym_enqueueMessage(acym_translation('ACYM_FILE_UPLOAD_ERROR_3'), 'error');
698 -
699 - return null;
700 - case 4:
701 - acym_enqueueMessage(acym_translation('ACYM_FILE_UPLOAD_ERROR_4'), 'error');
702 -
703 - return null;
704 - default:
705 - acym_enqueueMessage(acym_translationSprintf('ACYM_FILE_UPLOAD_ERROR_5', $fileError), 'error');
706 -
707 - return null;
708 - }
709 - }
710 -
711 - if (empty($importFile['name'])) {
712 - acym_enqueueMessage(acym_translation('ACYM_BROWSE_FILE'), 'error');
713 -
714 - return null;
715 - }
716 -
717 - $uploadPath = acym_cleanPath(ACYM_ROOT.ACYM_MEDIA_FOLDER.'templates');
718 -
719 - if (!is_writable($uploadPath)) {
720 - @chmod($uploadPath, '0755');
721 - if (!is_writable($uploadPath)) {
722 - acym_enqueueMessage(acym_translationSprintf('ACYM_WRITABLE_FOLDER', $uploadPath), 'warning');
723 - }
724 - }
725 -
726 - if (!(bool)ini_get('file_uploads')) {
727 - acym_enqueueMessage(acym_translationSprintf('ACYM_FILE_UPLOAD_ERROR_6'), 'error');
728 -
729 - return null;
730 - }
731 -
732 - if (!extension_loaded('zlib')) {
733 - acym_raiseError(500, acym_translation('ACYM_MISSING_ZLIB'));
734 -
735 - return null;
736 - }
737 -
738 - $filename = strtolower(acym_makeSafeFile($importFile['name']));
739 - $extension = strtolower(substr($filename, strrpos($filename, '.') + 1));
740 -
741 - $allowedFileType = true;
742 - if ($extension !== 'zip') {
743 - $allowedFileType = false;
744 - } elseif (!in_array($importFile['type'], ['application/zip', 'application/x-zip-compressed'])) {
745 - $allowedFileType = false;
746 - } elseif (function_exists('mime_content_type') && !in_array(mime_content_type($importFile['tmp_name']), ['application/zip', 'application/x-zip-compressed'])) {
747 - $allowedFileType = false;
748 - }
749 -
750 - if (!$allowedFileType) {
751 - acym_enqueueMessage(acym_translationSprintf('ACYM_ACCEPTED_TYPE', $extension, 'zip'), 'error');
752 -
753 - return null;
754 - }
755 -
756 - if (class_exists('ZipArchive')) {
757 - $zip = new \ZipArchive();
758 - if (filesize($importFile['tmp_name']) > self::MAX_ALLOWED_TEMPLATE_SIZE || !$zip->open($importFile['tmp_name']) || $zip->count() > self::MAX_ALLOWED_TEMPLATE_FILES) {
759 - acym_enqueueMessage(acym_translation('ACYM_UPLOADED_ARCHIVE_NOT_ALLOWED'), 'error');
760 -
761 - return null;
762 - }
763 -
764 - $zip->close();
765 - }
766 -
767 - $tmpPath = acym_getCMSConfig('tmp_path', ACYM_MEDIA.'tmp'.DS);
768 - $zipFilePath = acym_cleanPath($tmpPath.DS.$filename);
769 -
770 - $uploaded = acym_uploadFile($importFile['tmp_name'], $zipFilePath);
771 - if (!$uploaded) {
772 - acym_enqueueMessage(acym_translationSprintf('ACYM_FILE_UPLOAD_ERROR_7', $importFile['tmp_name'], $zipFilePath), 'error');
773 -
774 - return null;
775 - }
776 -
777 - return $zipFilePath;
778 - }
779 -
780 - private function extractTemplate(string $zipFilePath, bool $deleteZip = true): ?string
781 - {
782 - $extractdir = acym_cleanPath(dirname($zipFilePath).DS.uniqid().uniqid().uniqid().'_template');
783 -
784 - $result = acym_extractArchive($zipFilePath, $extractdir);
785 -
786 - if (!$result) {
787 - acym_enqueueMessage(acym_translationSprintf('ACYM_FILE_UPLOAD_ERROR_9', $zipFilePath, $extractdir), 'error');
788 -
789 - return null;
790 - }
791 -
792 - if ($deleteZip) {
793 - acym_deleteFile($zipFilePath);
794 - }
795 -
796 - $allFiles = acym_getFiles($extractdir, '.', true, true, [], []);
797 - foreach ($allFiles as $oneFile) {
798 - if (function_exists('mime_content_type')) {
799 - $fileType = mime_content_type($oneFile);
800 - if (in_array($fileType, self::ALLOWED_TEMPLATE_FILE_TYPES) && preg_match('#\.(jpg|gif|png|jpeg|ico|bmp|html|htm|css|webp)$#i', $oneFile)) {
801 - continue;
802 - }
803 - } elseif (preg_match('#\.(jpg|gif|png|jpeg|ico|bmp|html|htm|css|webp)$#i', $oneFile)) {
804 - continue;
805 - }
806 -
807 - if (acym_deleteFile($oneFile)) {
808 - acym_enqueueMessage(acym_translationSprintf('ACYM_FILE_UPLOAD_ERROR_8', $oneFile), 'warning');
809 - }
810 - }
811 -
812 - return $extractdir;
813 - }
814 -
815 - public function installExtractedTemplate(string $templateFolder, bool $deleteFolder = true): bool
816 - {
817 - if ($this->detectTemplates($templateFolder)) {
818 - $messages = $this->templateNames;
819 - array_unshift($messages, acym_translationSprintf('ACYM_TEMPLATES_INSTALL', count($this->templateNames)));
820 - acym_enqueueMessage($messages);
821 - if ($deleteFolder && is_dir($templateFolder)) {
822 - acym_deleteFolder($templateFolder);
823 - }
824 -
825 - return true;
826 - }
827 -
828 - acym_enqueueMessage(acym_translationSprintf('ACYM_FILE_UPLOAD_ERROR_10'), 'error');
829 - if ($deleteFolder && is_dir($templateFolder)) {
830 - acym_deleteFolder($templateFolder);
831 - }
832 -
833 - return false;
834 - }
835 -
836 - public function detectTemplates(string $folder): bool
837 - {
838 - $allFiles = acym_getFiles($folder);
839 - if (!empty($allFiles)) {
840 - $keyTmpl = array_search('template.html', $allFiles);
841 - if ($keyTmpl !== false) {
842 - if ($this->installTemplate($folder.DS.$allFiles[$keyTmpl])) {
843 - return true;
844 - }
845 - }
846 - foreach ($allFiles as $oneFile) {
847 - if (preg_match('#^.*(html|htm)$#i', $oneFile)) {
848 - if ($this->installTemplate($folder.DS.$oneFile)) {
849 - return true;
850 - }
851 - }
852 - }
853 - }
854 -
855 - $status = false;
856 - $allFolders = acym_getFolders($folder);
857 - if (!empty($allFolders)) {
858 - foreach ($allFolders as $oneFolder) {
859 - $status = $this->detectTemplates($folder.DS.$oneFolder) || $status;
860 - }
861 - }
862 -
863 - return $status;
864 - }
865 -
866 - private function installTemplate(string $filepath): bool
867 - {
868 - $fileContent = acym_fileGetContent($filepath);
869 -
870 - $newTemplate = new \stdClass();
871 -
872 - if (strpos($filepath, '_template') === false) {
873 - $newTemplate->name = basename(dirname($filepath));
874 - } else {
875 - $newTemplate->name = basename($filepath);
876 - $newTemplate->name = substr($newTemplate->name, 0, strrpos($newTemplate->name, '.'));
877 - }
878 -
879 - $newTemplate->name = trim(preg_replace('#[^a-z0-9]#i', ' ', $newTemplate->name));
880 -
881 - if (preg_match('#< *title[^>]*>(.*)< */ *title *>#Uis', $fileContent, $results) && !empty($results[1])) $newTemplate->name = $results[1];
882 -
883 - if (preg_match('#< *meta *name="fromname" *content="([^"]*)"#Uis', $fileContent, $results) && !empty($results[1])) $newTemplate->fromname = $results[1];
884 - if (preg_match('#< *meta *name="fromemail" *content="([^"]*)"#Uis', $fileContent, $results) && !empty($results[1])) $newTemplate->fromemail = $results[1];
885 - if (preg_match('#< *meta *name="replyname" *content="([^"]*)"#Uis', $fileContent, $results) && !empty($results[1])) $newTemplate->replyname = $results[1];
886 - if (preg_match('#< *meta *name="replyemail" *content="([^"]*)"#Uis', $fileContent, $results) && !empty($results[1])) $newTemplate->replyemail = $results[1];
887 - if (preg_match('#< *meta *name="subject" *content="([^"]*)"#Uis', $fileContent, $results) && !empty($results[1])) $newTemplate->subject = $results[1];
888 - if (preg_match('#< *meta *name="settings" *content="([^"]*)"#Uis', $fileContent, $results) && !empty($results[1])) {
889 - $newTemplate->settings = htmlspecialchars_decode($results[1]);
890 - }
891 -
892 - $newFolder = preg_replace('#[^a-z0-9]#i', '_', strtolower($newTemplate->name));
893 - $newTemplateFolder = $newFolder;
894 - $i = 1;
895 - while (is_dir(ACYM_TEMPLATE.$newTemplateFolder)) {
896 - $newTemplateFolder = $newFolder.'_'.$i;
897 - $i++;
898 - }
899 - $newTemplate->mail_settings = ['media_folder' => $newTemplateFolder];
900 -
901 - $moveResult = acym_copyFolder(dirname($filepath), ACYM_TEMPLATE.$newTemplateFolder);
902 - if ($moveResult !== true) {
903 - acym_display([acym_translationSprintf('ACYM_ERROR_COPYING_FOLDER_TO', dirname($filepath), ACYM_TEMPLATE.$newTemplateFolder), $moveResult], 'error');
904 -
905 - return false;
906 - }
907 -
908 - if (!file_exists(ACYM_TEMPLATE.$newTemplateFolder.DS.'index.html')) {
909 - $indexFile = '<html><body bgcolor="#FFFFFF"></body></html>';
910 - acym_writeFile(ACYM_TEMPLATE.$newTemplateFolder.DS.'index.html', $indexFile);
911 - }
912 -
913 - $fileContent = str_replace(
914 - [
915 - 'src="./',
916 - 'src="../',
917 - 'src="images/',
918 - 'url("images/',
919 - 'url(&quot;images/',
920 - ],
921 - [
922 - 'src="'.ACYM_TEMPLATE_URL.$newTemplateFolder.'/',
923 - 'src="'.ACYM_TEMPLATE_URL,
924 - 'src="'.ACYM_TEMPLATE_URL.$newTemplateFolder.'/images/',
925 - 'url("'.ACYM_TEMPLATE_URL.$newTemplateFolder.'/images/',
926 - 'url(&quot;'.ACYM_TEMPLATE_URL.$newTemplateFolder.'/images/',
927 - ],
928 - $fileContent
929 - );
930 -
931 - $fileContent = preg_replace('#(src|background)[ ]*=[ ]*\"(?!(https?://|/))(?:\.\./|\./)?#', '$1="'.ACYM_TEMPLATE_URL.$newTemplateFolder.'/', $fileContent);
932 -
933 - if (preg_match('#< *body[^>]*>(.*)< */ *body *>#Uis', $fileContent, $results)) {
934 - $newTemplate->body = $results[1];
935 - } else {
936 - $newTemplate->body = $fileContent;
937 - }
938 -
939 - $newTemplate->stylesheet = '';
940 - if (preg_match_all('#< *style[^>]*>(.*)< */ *style *>#Uis', $fileContent, $results)) {
941 - $newTemplate->stylesheet .= preg_replace('#(<!--|-->)#s', '', implode("\n", $results[1]));
942 - }
943 - $cssFiles = [];
944 - $cssFiles[ACYM_TEMPLATE.$newTemplateFolder] = acym_getFiles(ACYM_TEMPLATE.$newTemplateFolder, '\.css$');
945 - $subFolders = acym_getFolders(ACYM_TEMPLATE.$newTemplateFolder);
946 - foreach ($subFolders as $oneFolder) {
947 - $cssFiles[ACYM_TEMPLATE.$newTemplateFolder.DS.$oneFolder] = acym_getFiles(ACYM_TEMPLATE.$newTemplateFolder.DS.$oneFolder, '\.css$');
948 - }
949 -
950 - foreach ($cssFiles as $cssFolder => $cssFile) {
951 - if (empty($cssFile)) continue;
952 - $newTemplate->stylesheet .= "\n".acym_fileGetContent($cssFolder.DS.reset($cssFile));
953 - }
954 -
955 - if (!empty($newTemplate->stylesheet)) {
956 - if (preg_match('#body *\{[^\}]*background-color:([^;\}]*)[;\}]#Uis', $newTemplate->stylesheet, $backgroundresults)) {
957 - $newTemplate->stylesheet = preg_replace('#(body *\{[^\}]*)background-color:[^;\}]*[;\}]#Uis', '$1', $newTemplate->stylesheet);
958 - }
959 -
960 - $quickstyle = [
961 - 'tag_h1' => 'h1',
962 - 'tag_h2' => 'h2',
963 - 'tag_h3' => 'h3',
964 - 'tag_h4' => 'h4',
965 - 'tag_h5' => 'h5',
966 - 'tag_h6' => 'h6',
967 - 'tag_a' => 'a',
968 - 'tag_ul' => 'ul',
969 - 'tag_li' => 'li',
970 - 'acym_unsub' => '\.acym_unsub',
971 - 'acym_online' => '\.acym_online',
972 - 'acym_title' => '\.acym_title',
973 - 'acym_content' => '\.acym_content',
974 - 'acym_readmore' => '\.acym_readmore',
975 - ];
976 - foreach ($quickstyle as $styledb => $oneStyle) {
977 - if (preg_match('#[^a-z\. ,] *'.$oneStyle.' *{([^}]*)}#Uis', $newTemplate->stylesheet, $quickstyleresults)) {
978 - $newTemplate->stylesheet = str_replace($quickstyleresults[0], '', $newTemplate->stylesheet);
979 - }
980 - }
981 - }
982 -
983 - $foldersForPicts = [$newTemplateFolder];
984 - $otherFolders = acym_getFolders(ACYM_TEMPLATE.$newTemplateFolder);
985 - foreach ($otherFolders as $oneFold) {
986 - $foldersForPicts[] = $newTemplateFolder.DS.$oneFold;
987 - }
988 - $allPictures = [];
989 - foreach ($foldersForPicts as $oneFolder) {
990 - $allPictures[$oneFolder] = acym_getFiles(ACYM_TEMPLATE.$oneFolder);
991 - }
992 -
993 - $uploadsFolder = ACYM_UPLOAD_FOLDER_THUMBNAIL;
994 -
995 - $thumbNb = intval($this->config->get('numberThumbnail', 2));
996 -
997 - foreach ($allPictures as $folder => $pictfolders) {
998 - foreach ($pictfolders as $onePict) {
999 - if (!preg_match('#\.(jpg|gif|png|jpeg|ico|bmp)$#i', $onePict)) continue;
1000 - if (preg_match('#(thumbnail|screenshot|muestra)#i', $onePict)) {
1001 - $thumbNb++;
1002 - $newNamePict = 'thumbnail_'.$thumbNb.'.png';
1003 - copy(ACYM_TEMPLATE.str_replace(DS, '/', $folder).'/'.$onePict, $uploadsFolder.$newNamePict);
1004 - $newTemplate->thumbnail = $newNamePict;
1005 - }
1006 - }
1007 - }
1008 -
1009 - $this->config->saveConfig(['numberThumbnail' => $thumbNb]);
1010 -
1011 - $newTemplate->drag_editor = strpos($newTemplate->body, 'acym__wysid__template__content') !== false ? 1 : 0;
1012 - $newTemplate->type = self::TYPE_TEMPLATE;
1013 - $newTemplate->creation_date = acym_date('now', 'Y-m-d H:i:s', false);
1014 -
1015 - $this->save($newTemplate);
1016 -
1017 - $this->templateNames[] = $newTemplate->name;
1018 -
1019 - return true;
1020 - }
1021 -
1022 - public function sendAutomation(int $mailId, array $userIds, string $sendingDate, array $automationAdmin = [])
1023 - {
1024 - if (empty($mailId)) {
1025 - return acym_translationSprintf('ACYM_EMAILS_ADDED_QUEUE', 0);
1026 - }
1027 -
1028 - if (empty($sendingDate)) {
1029 - return acym_translation('ACYM_WRONG_DATE');
1030 - }
1031 -
1032 - if (empty($userIds)) {
1033 - return acym_translation('ACYM_USER_NOT_FOUND');
1034 - }
1035 -
1036 - acym_arrayToInteger($userIds);
1037 -
1038 - $nbSent = $this->sendNotification($mailId, $userIds, $automationAdmin);
1039 - if (!is_null($nbSent)) {
1040 - return $nbSent;
1041 - }
1042 -
1043 - $result = acym_query(
1044 - 'INSERT IGNORE INTO #__acym_queue (`mail_id`, `user_id`, `sending_date`)
1045 - SELECT '.intval($mailId).', user.id, '.acym_escapeDB($sendingDate).'
1046 - FROM #__acym_user AS user
1047 - WHERE user.active = 1 AND user.id IN ('.implode(',', $userIds).')'
1048 - );
1049 -
1050 - if ($result === 0) {
1051 - return acym_translation('ACYM_CAMPAIGN_ALREADY_QUEUED');
1052 - }
1053 -
1054 - $mailStatClass = new MailStatClass();
1055 - $mailStat = $mailStatClass->getOneRowByMailId($mailId);
1056 -
1057 - $newMailStat = new \stdClass();
1058 - $newMailStat->mail_id = intval($mailId);
1059 - $newMailStat->total_subscribers = intval($result);
1060 - if (empty($mailStat)) {
1061 - $newMailStat->send_date = $sendingDate;
1062 - }
1063 -
1064 - $mailStatClass->save($newMailStat);
1065 -
1066 - return $result;
1067 - }
1068 -
1069 - private function sendNotification(int $mailId, array $userIds, array $automationAdmin): ?int
1070 - {
1071 - if (empty($automationAdmin['user_id'])) {
1072 - return null;
1073 - }
1074 -
1075 - $userClass = new UserClass();
1076 - $mail = $this->getOneById($mailId);
1077 - $user = $userClass->getOneById($automationAdmin['user_id']);
1078 -
1079 - if (empty($mail) || empty($user)) {
1080 - return 0;
1081 - }
1082 -
1083 - $mailerHelper = new MailerHelper();
1084 - $pluginHelper = new PluginHelper();
1085 - $extractedTags = $pluginHelper->extractTags($mail, 'subscriber');
1086 -
1087 - $isNotification = false;
1088 - foreach ($extractedTags as $dtext => $oneTag) {
1089 - if (empty($oneTag->info) || $oneTag->info !== 'current') {
1090 - continue;
1091 - }
1092 -
1093 - $isNotification = true;
1094 -
1095 - if (!empty($user->{$oneTag->id})) {
1096 - $mailerHelper->addParam(str_replace(['{', '}'], '', $dtext), $user->{$oneTag->id});
1097 - }
1098 - }
1099 -
1100 - if (!$isNotification) {
1101 - if (isset($automationAdmin['automationAdmin']) && $automationAdmin['automationAdmin']) {
1102 - return 0;
1103 - } else {
1104 - return null;
1105 - }
1106 - }
1107 -
1108 - $userFields = $userClass->getAllUserFields($user);
1109 - foreach ($userFields as $map => $value) {
1110 - $mailerHelper->addParam('subscriber:'.$map.'|info:current', $value);
1111 - $mailerHelper->addParam('user:'.$map, $value);
1112 - }
1113 -
1114 - $emailsSent = 0;
1115 - foreach ($userIds as $userId) {
1116 - if ($mailerHelper->sendOne($mail->id, $userId)) {
1117 - $emailsSent++;
1118 - }
1119 - }
1120 -
1121 - return $emailsSent;
1122 - }
1123 -
1124 - public function encode($mails = [])
1125 - {
1126 - $isArray = true;
1127 - if (!is_array($mails)) {
1128 - $mails = [$mails];
1129 -
1130 - $isArray = false;
1131 - }
1132 -
1133 - $encodedMails = array_map([$this, 'removePoweredByAcyMailing'], $mails);
1134 -
1135 - $encodedMails = array_map([$this, 'utf8Encode'], $encodedMails);
1136 -
1137 - return $isArray ? $encodedMails : $encodedMails[0];
1138 - }
1139 -
1140 - public function decode($mails = [])
1141 - {
1142 - if (is_null($mails)) {
1143 - return null;
1144 - }
1145 -
1146 - $isArray = true;
1147 - if (!is_array($mails)) {
1148 - $mails = [$mails];
1149 -
1150 - $isArray = false;
1151 - }
1152 -
1153 - $decodedMails = array_map([$this, 'utf8Decode'], $mails);
1154 -
1155 - $decodedMails = array_map([$this, 'addPoweredByAcyMailing'], $decodedMails);
1156 -
1157 - foreach ($decodedMails as $i => $oneMail) {
1158 - if (!isset($oneMail->access) || is_array($oneMail->access)) continue;
1159 - $decodedMails[$i]->access = empty($oneMail->access) ? '' : explode(',', $oneMail->access);
1160 - }
1161 -
1162 - return $isArray ? $decodedMails : $decodedMails[0];
1163 - }
1164 -
1165 - protected function utf8Decode($mail)
1166 - {
1167 - if (!empty($mail)) {
1168 - foreach (self::FIELDS_ENCODING as $oneField) {
1169 - if (in_array($oneField, $this->exceptKeysDecode)) {
1170 - continue;
1171 - }
1172 -
1173 - if (is_array($mail)) {
1174 - if (empty($mail[$oneField])) continue;
1175 - $value = &$mail[$oneField];
1176 - } else {
1177 - if (empty($mail->$oneField)) continue;
1178 - $value = &$mail->$oneField;
1179 - }
1180 -
1181 - $value = acym_utf8Decode($value);
1182 - }
1183 - }
1184 -
1185 - return $mail;
1186 - }
1187 -
1188 - private function addPoweredByAcyMailing(object $mail): object
1189 - {
1190 - if (empty($mail->body)) {
1191 - return $mail;
1192 - }
1193 -
1194 - if ($this->config->get('display_built_by', 0) != 1) {
1195 - if (strpos($mail->body, 'acym__powered_by_acymailing') !== false) {
1196 - $mailBodyDom = new \DOMDocument();
1197 - @$mailBodyDom->loadHTML('<?xml encoding="utf-8" ?>'.$mail->body);
1198 - $tables = $mailBodyDom->getElementsByTagName('table');
1199 - foreach ($tables as $table) {
1200 - if ($table->getAttribute('id') != 'acym__powered_by_acymailing') continue;
1201 - $table->parentNode->removeChild($table);
1202 - break;
1203 - }
1204 - $mail->body = $mailBodyDom->saveHTML();
1205 - }
1206 -
1207 - return $mail;
1208 - }
1209 -
1210 - if (strpos($mail->body, 'acym__powered_by_acymailing') !== false) {
1211 - return $mail;
1212 - }
1213 -
1214 - $isWysidEditor = strpos($mail->body, 'acym__wysid__template') !== false;
1215 - $urlPoweredByImage = ACYM_IMAGES.'editor/poweredby_black.png';
1216 -
1217 - if (!$isWysidEditor) {
1218 - $poweredByHTML = '<p id="acym__powered_by_acymailing">';
1219 - $poweredByHTML .= '<a href="'.ACYM_ACYMAILING_WEBSITE.'?utm_campaign=powered_by_v7&utm_source=acymailing_plugin&utm_medium=built_with_footer" target="blank">';
1220 - $poweredByHTML .= '<img alt="Email built with AcyMailing" height="40" width="199" style="height: 40px; width:199px; max-width: 100%; height: auto; box-sizing: border-box; padding: 0 5px; display: block; margin-left: auto; margin-right: auto;" src="'.$urlPoweredByImage.'"/>';
1221 - $poweredByHTML .= '</a></p>';
1222 -
1223 - $mail->body = $mail->body.$poweredByHTML;
1224 - } else {
1225 - $poweredByWYSID = '<table id="acym__powered_by_acymailing" class="row" bgcolor="#ffffff" style="background-color: transparent" cellpadding="0" cellspacing="0" border="0">
1226 - <tbody bgcolor style="background-color: inherit;">
1227 - <tr>
1228 - <th class="small-12 medium-12 large-12 columns" valign="top" style="height: auto;">
1229 - <table border="0" cellpadding="0" cellspacing="0"
1230 - style="min-height: 0px; display: table; height: auto;">
1231 - <tbody style="min-height: 0px; display: table-row-group;">
1232 - <tr
1233 - style="position: relative; top: inherit; left: inherit; right: inherit; bottom: inherit; height: auto;">
1234 - <td class="large-12">
1235 - <div style="position: relative;">
1236 - <p style="word-break: break-word; text-align: center;">
1237 - <a href="'.ACYM_ACYMAILING_WEBSITE.'?utm_campaign=powered_by_v7&utm_source=acymailing_plugin&utm_medium=built_with_footer" target="_blank">
1238 - <img src="'.$urlPoweredByImage.'"
1239 - title="poweredby" alt="Email built with AcyMailing"
1240 - style="height: 40px; width:199px; max-width: 100%; height: auto; box-sizing: border-box; padding: 0px 5px; display: inline-block; margin-left: auto; margin-right: auto;"
1241 - height="40" width="199">
1242 - </a>
1243 - </p>
1244 - </div>
1245 - </td>
1246 - </tr>
1247 - </tbody>
1248 - </table>
1249 - </th>
1250 - </tr>
1251 - </tbody>
1252 -</table>';
1253 -
1254 - $mailBodyDom = new \DOMDocument();
1255 - @$mailBodyDom->loadHTML('<?xml encoding="utf-8" ?>'.$mail->body);
1256 -
1257 - $htmlToAddDom = new \DOMDocument();
1258 - @$htmlToAddDom->loadHTML('<?xml encoding="utf-8" ?>'.$poweredByWYSID);
1259 - $tableToAdd = $htmlToAddDom->getElementById('acym__powered_by_acymailing');
1260 -
1261 - $tds = $mailBodyDom->getElementsByTagName('td');
1262 - foreach ($tds as $td) {
1263 - $classes = explode(' ', $td->getAttribute('class'));
1264 - if (!in_array('acym__wysid__row', $classes)) continue;
1265 - if (!empty($tableToAdd)) $td->appendChild($mailBodyDom->importNode($tableToAdd, true));
1266 - break;
1267 - }
1268 - $mail->body = $mailBodyDom->saveHTML();
1269 - }
1270 -
1271 - return $mail;
1272 - }
1273 -
1274 - protected function removePoweredByAcyMailing(object $mail): object
1275 - {
1276 - if (empty($mail->body) || strpos($mail->body, 'acym__wysid__template') !== false) {
1277 - return $mail;
1278 - }
1279 -
1280 - $regexPoweredByAcyMailing = '#<p id="acym__powered_by_acymailing.*<\/p>#U';
1281 -
1282 - $mail->body = preg_replace($regexPoweredByAcyMailing, '', $mail->body);
1283 -
1284 - return $mail;
1285 - }
1286 -
1287 - protected function utf8Encode($mail)
1288 - {
1289 - if (!empty($mail)) {
1290 - foreach (self::FIELDS_ENCODING as $oneField) {
1291 - if (is_array($mail)) {
1292 - if (empty($mail[$oneField])) continue;
1293 - $value = &$mail[$oneField];
1294 - } else {
1295 - if (empty($mail->$oneField)) continue;
1296 - $value = &$mail->$oneField;
1297 - }
1298 -
1299 - $value = acym_utf8Encode($value);
1300 - }
1301 - }
1302 -
1303 - return $mail;
1304 - }
1305 -
1306 - public function getTranslationId(int $parentId, string $langCode): int
1307 - {
1308 - return (int)acym_loadResult(
1309 - 'SELECT `id`
1310 - FROM #__acym_mail
1311 - WHERE `parent_id` = '.intval($parentId).'
1312 - AND `language` = '.acym_escapeDB($langCode)
1313 - );
1314 - }
1315 -
1316 - public function getTranslationsById(int $mailId, bool $full = false, bool $includeParent = false)
1317 - {
1318 - $data = $full ? '*' : '`language`, `subject`, `preheader`, `body`, `autosave`';
1319 - $where = $includeParent ? ' OR `id` = '.intval($mailId) : '';
1320 -
1321 - return $this->decode(
1322 - acym_loadObjectList(
1323 - 'SELECT '.$data.'
1324 - FROM #__acym_mail
1325 - WHERE `parent_id` = '.intval($mailId).$where,
1326 - 'language'
1327 - )
1328 - );
1329 - }
1330 -
1331 - public function deleteByTranslationLang(array $languageCodes): void
1332 - {
1333 - if (empty($languageCodes)) {
1334 - return;
1335 - }
1336 -
1337 - foreach ($languageCodes as $key => $oneLangCode) {
1338 - $languageCodes[$key] = acym_escapeDB($oneLangCode);
1339 - }
1340 -
1341 - $this->delete(
1342 - acym_loadResultArray(
1343 - 'SELECT `id`
1344 - FROM #__acym_mail
1345 - WHERE `parent_id` IS NOT NULL
1346 - AND `language` IN ('.implode(', ', $languageCodes).')'
1347 - )
1348 - );
1349 - }
1350 -
1351 - public function getMultilingualMails(int $parentId): array
1352 - {
1353 - $mails = $this->decode(
1354 - acym_loadObjectList(
1355 - 'SELECT * FROM #__acym_mail WHERE parent_id = '.intval($parentId).' OR id = '.intval($parentId),
1356 - 'language'
1357 - )
1358 - );
1359 -
1360 - return $this->translateMailSettings($mails);
1361 - }
1362 -
1363 - private function translateMailSettings(array $mails): array
1364 - {
1365 - if (empty($mails)) {
1366 - return $mails;
1367 - }
1368 -
1369 - $defaultLanguage = $this->config->get('multilingual_default');
1370 -
1371 - if (empty($mails[$defaultLanguage])) {
1372 - $firstMail = reset($mails);
1373 - if (empty($firstMail) || empty($firstMail->parent_id)) {
1374 - return $mails;
1375 - }
1376 - $mainMail = $this->getOneById($firstMail->parent_id);
1377 - } else {
1378 - $mainMail = $mails[$defaultLanguage];
1379 - }
1380 -
1381 - if (!empty($mainMail->translation)) {
1382 - $translation = json_decode($mainMail->translation, true);
1383 -
1384 - foreach ($mails as $lang => $mail) {
1385 - if (empty($mail->parent_id) || empty($translation[$lang])) {
1386 - continue;
1387 - }
1388 -
1389 - if (!empty($translation[$lang]['from_name'])) $mail->from_name = $translation[$lang]['from_name'];
1390 - if (!empty($translation[$lang]['from_email'])) $mail->from_email = $translation[$lang]['from_email'];
1391 - if (!empty($translation[$lang]['reply_to_name'])) $mail->reply_to_name = $translation[$lang]['reply_to_name'];
1392 - if (!empty($translation[$lang]['reply_to_email'])) $mail->reply_to_email = $translation[$lang]['reply_to_email'];
1393 - }
1394 - }
1395 -
1396 - return $mails;
1397 - }
1398 -
1399 - public function getMailAttachments(int $mailId)
1400 - {
1401 - return acym_loadResult('SELECT attachments FROM #__acym_mail WHERE id = '.intval($mailId));
1402 - }
1403 -
1404 - public function isTransactionalMail(object $mail): bool
1405 - {
1406 - return $mail->type !== self::TYPE_STANDARD;
1407 - }
1408 -
1409 - public function isOneTimeMail(object $mail): bool
1410 - {
1411 - return in_array(
1412 - $mail->type,
1413 - [
1414 - self::TYPE_NOTIFICATION,
1415 - self::TYPE_OVERRIDE,
1416 - self::TYPE_WELCOME,
1417 - self::TYPE_UNSUBSCRIBE,
1418 - self::TYPE_TEMPLATE,
1419 - ]
1420 - );
1421 - }
1422 -
1423 - public function getAutomaticMailIds(array $mailIds): array
1424 - {
1425 - acym_arrayToInteger($mailIds);
1426 -
1427 - $query = 'SELECT DISTINCT campaign2.mail_id
1428 - FROM #__acym_campaign AS campaign1
1429 - JOIN #__acym_campaign AS campaign2 ON campaign1.id = campaign2.parent_id
1430 - WHERE campaign1.mail_id IN ('.implode(',', $mailIds).')';
1431 - $generatedMailIds = acym_loadResultArray($query);
1432 -
1433 - if (empty($generatedMailIds)) return [];
1434 -
1435 - acym_arrayToInteger($generatedMailIds);
1436 -
1437 - return $generatedMailIds;
1438 - }
1439 -
1440 - public function getMultilingualMailIds(array $mailIds): array
1441 - {
1442 - acym_arrayToInteger($mailIds);
1443 -
1444 - $query = 'SELECT DISTINCT mail2.id
1445 - FROM #__acym_mail AS mail1
1446 - JOIN #__acym_mail AS mail2 ON mail1.id = mail2.parent_id
1447 - WHERE mail1.id IN ('.implode(',', $mailIds).')';
1448 -
1449 - $multipleMailIds = acym_loadResultArray($query);
1450 -
1451 - if (empty($multipleMailIds)) return [];
1452 -
1453 - acym_arrayToInteger($multipleMailIds);
1454 -
1455 - return $multipleMailIds;
1456 - }
1457 -
1458 - public function duplicateMail(int $mailId, ?string $type = null): ?object
1459 - {
1460 - $mail = $this->getOneById($mailId);
1461 -
1462 - if (empty($mail)) {
1463 - return null;
1464 - }
1465 -
1466 - $newMail = new \stdClass();
1467 - $newMail->name = $mail->name.'_copy';
1468 - $newMail->thumbnail = '';
1469 - $newMail->type = empty($type) ? $mail->type : $type;
1470 - $newMail->drag_editor = $mail->drag_editor;
1471 - $newMail->body = $mail->body;
1472 - $newMail->subject = $mail->subject;
1473 - $newMail->from_name = $mail->from_name;
1474 - $newMail->from_email = $mail->from_email;
1475 - $newMail->reply_to_name = $mail->reply_to_name;
1476 - $newMail->reply_to_email = $mail->reply_to_email;
1477 - $newMail->bcc = $mail->bcc;
1478 - $newMail->settings = $mail->settings;
1479 - $newMail->stylesheet = $mail->stylesheet;
1480 - $newMail->attachments = $mail->attachments;
1481 - $newMail->headers = $mail->headers;
1482 - $newMail->preheader = $mail->preheader;
1483 -
1484 - $newMail->id = $this->save($newMail);
1485 -
1486 - return $newMail;
1487 - }
1488 -
1489 - public function getTemplatesForMailboxAction(): array
1490 - {
1491 - return $this->decode(
1492 - acym_loadObjectList(
1493 - 'SELECT `id`, `name`
1494 - FROM #__acym_mail
1495 - WHERE `type` = '.acym_escapeDB(self::TYPE_TEMPLATE).'
1496 - AND `body` LIKE '.acym_escapeDB('%'.acym_utf8Encode('{emailcontent}').'%')
1497 - )
1498 - );
1499 - }
1500 -
1501 - public function hasUserAccess(int $mailId): bool
1502 - {
1503 - $userId = acym_currentUserId();
1504 - if (empty($userId)) {
1505 - return false;
1506 - }
1507 -
1508 - if (acym_isAdmin()) {
1509 - return true;
1510 - }
1511 -
1512 - return acym_loadResult(
1513 - 'SELECT COUNT(*)
1514 - FROM #__acym_mail
1515 - WHERE id = '.intval($mailId).'
1516 - AND (creator_id = '.intval($userId).'
1517 - OR type = '.acym_escapeDB(self::TYPE_TEMPLATE).')'
1518 - ) > 0;
1519 - }
1520 -
1521 - public function getVersionsById(int $mailId, bool $includeParent = false): array
1522 - {
1523 - $where = $includeParent ? ' OR `id` = '.intval($mailId) : '';
1524 -
1525 - return $this->decode(
1526 - acym_loadObjectList(
1527 - 'SELECT *
1528 - FROM #__acym_mail
1529 - WHERE `parent_id` = '.intval($mailId).$where.' ORDER BY id ASC',
1530 - 'id'
1531 - )
1532 - );
1533 - }
1534 -
1535 - public function getParentAndChildMails(int $parentId): array
1536 - {
1537 - return $this->decode(
1538 - acym_loadObjectList(
1539 - 'SELECT * FROM #__acym_mail WHERE parent_id = '.intval($parentId).' OR id = '.intval($parentId),
1540 - 'id'
1541 - )
1542 - );
1543 - }
1544 -
1545 - public function getAllTemplatesByType(array $options): array
1546 - {
1547 - $limit = $options['limit'] ?? 10;
1548 - $offset = $options['offset'] ?? 0;
1549 - $filters = $options['filters'] ?? [];
1550 - $search = $filters['search'] ?? '';
1551 - $templateType = $filters['templateType'] ?? '';
1552 -
1553 - $conditions = ['`type` = '.acym_escapeDB(self::TYPE_TEMPLATE)];
1554 -
1555 - if (!empty($search)) {
1556 - $conditions[] = '(name LIKE '.acym_escapeDB('%'.$search.'%').' OR subject LIKE '.acym_escapeDB('%'.$search.'%').')';
1557 - }
1558 -
1559 - if (!empty($templateType)) {
1560 - if ($templateType === 'drag') {
1561 - $conditions[] = 'drag_editor = 1';
1562 - } else {
1563 - $conditions[] = 'drag_editor = 0';
1564 - }
1565 - }
1566 -
1567 - $query = 'SELECT * FROM #__acym_mail WHERE '.implode(' AND ', $conditions);
1568 -
1569 - return $this->decode(acym_loadObjectList($query, '', $offset, $limit));
1570 - }
1571 -
1572 - public function updateFollowupPriority(bool $previouslyActive, bool $active): void
1573 - {
1574 - if (!$previouslyActive && $active) {
1575 - acym_query(
1576 - 'UPDATE `#__acym_queue` AS `queue`
1577 - INNER JOIN `#__acym_mail` AS `mail` ON `queue`.`mail_id` = `mail`.`id`
1578 - SET `queue`.`priority` = 1
1579 - WHERE `mail`.`type` = '.acym_escapeDB(self::TYPE_FOLLOWUP)
1580 - );
1581 - }
1582 - }
1583 -
1584 - public function getCampaignIdByMailId(int $mailId): int
1585 - {
1586 - $mainMailId = $this->getMainMailId($mailId);
1587 -
1588 - return intval(acym_loadResult('SELECT id FROM #__acym_campaign WHERE mail_id = '.intval($mainMailId)));
1589 - }
1590 -
1591 - public function getMainMailId(int $mailId): int
1592 - {
1593 - $parentId = acym_loadResult('SELECT parent_id FROM #__acym_mail WHERE id = '.intval($mailId));
1594 -
1595 - return empty($parentId) ? $mailId : intval($parentId);
1596 - }
1597 -
1598 - public function getMailType(int $mailId): string
1599 - {
1600 - return acym_loadResult('SELECT type FROM #__acym_mail WHERE id = '.intval($mailId));
1601 - }
1602 -}