PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / 10.2.2
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress v10.2.2
11.1.1 11.1.0 11.0.5 11.0.4 11.0.3 11.0.2 11.0.1 11.0.0 10.11.1 10.11.0 10.10.2 10.10.1 10.10.0 10.9.1 trunk 10.0.0 10.0.1 10.1.0 10.1.1 10.1.2 10.1.3 10.1.4 10.2.0 10.2.1 10.2.2 All 62 releases
acymailing / back / Controllers / Mails / Edition.php

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

1,123 lines 44.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace AcyMailing\Controllers\Mails;
4
5 use AcyMailing\Classes\CampaignClass;
6 use AcyMailing\Classes\FollowupClass;
7 use AcyMailing\Classes\ListClass;
8 use AcyMailing\Classes\MailClass;
9 use AcyMailing\Classes\TagClass;
10 use AcyMailing\Controllers\CampaignsController;
11 use AcyMailing\Helpers\EditorHelper;
12 use AcyMailing\Helpers\MailerHelper;
13 use AcyMailing\Helpers\PaginationHelper;
14 use AcyMailing\Types\UploadFileType;
15
16 trait Edition
17 {
18 public function edit(): void
19 {
20 if (!acym_isAdmin()) {
21 acym_checkToken();
22 }
23
24 $tempId = acym_getVar('int', 'id');
25 $mailClass = new MailClass();
26 $typeEditor = acym_getVar('string', 'type_editor');
27 $notification = acym_getVar('cmd', 'notification');
28 $return = acym_getVar('string', 'return', '');
29 $followupId = acym_getVar('int', 'followup_id', 0);
30 $followupClass = new FollowupClass();
31
32 $campaignController = new CampaignsController();
33
34 if (base64_decode($return, true) === false) {
35 $return = empty($return) ? '' : $return;
36 } else {
37 $return = empty($return) ? '' : urldecode(base64_decode($return));
38 }
39
40 $type = acym_getVar('string', 'type', '');
41 $fromId = acym_getVar('int', 'from');
42 $listIds = acym_getVar('int', 'list_id', []);
43
44 if (in_array($type, [MailClass::TYPE_WELCOME, MailClass::TYPE_UNSUBSCRIBE])) {
45 array_pop($this->breadcrumb);
46 $this->breadcrumb[acym_translation('ACYM_LISTS')] = acym_completeLink('lists');
47 $campaignController->setTaskListing($type);
48
49 if (!empty($listIds)) {
50 $listIds = [$listIds];
51 }
52 }
53
54
55 if (!empty($notification)) {
56 $mail = $mailClass->getOneByName($notification);
57 if (!empty($mail->id)) {
58 $tempId = $mail->id;
59 }
60 }
61
62 $isAutomationAdmin = false;
63 $fromMail = '';
64
65 if (!empty($fromId)) {
66 $fromMail = $mailClass->getOneById($fromId);
67 }
68
69 if ($type === 'automation_admin') {
70 $type = MailClass::TYPE_AUTOMATION;
71 $isAutomationAdmin = true;
72 }
73
74 if (empty($tempId)) {
75 if (empty($fromId)) {
76 $mail = new \stdClass();
77 $mail->name = '';
78 $mail->subject = '';
79 $mail->preheader = '';
80 $mail->tags = [];
81 $mail->type = $type;
82 $mail->body = '';
83 $mail->editor = in_array($type, [MailClass::TYPE_AUTOMATION, MailClass::TYPE_FOLLOWUP, MailClass::TYPE_SCENARIO]) ? 'acyEditor' : $typeEditor;
84 $mail->headers = '';
85 $mail->thumbnail = null;
86 $mail->links_language = '';
87 $mail->from_email = '';
88 $mail->from_name = '';
89 $mail->reply_to_email = '';
90 $mail->reply_to_name = '';
91 } else {
92 $mail = $fromMail;
93 $mail->id = 0;
94 $mail->from_email = $fromMail->from_email;
95 $mail->from_name = $fromMail->from_name;
96 $mail->reply_to_email = $fromMail->reply_to_email;
97 $mail->reply_to_name = $fromMail->reply_to_name;
98 if (0 == $mail->drag_editor) {
99 $mail->editor = 'html';
100 } else {
101 $mail->editor = !empty($typeEditor) ? $typeEditor : 'acyEditor';
102 }
103 }
104 $mail->access = [];
105 $mail->delay = 0;
106 $mail->delay_unit = FollowupClass::DEFAULT_DELAY_UNIT;
107
108 if (!empty($type)) $mail->type = $type;
109
110 if (MailClass::TYPE_AUTOMATION != $type || empty($fromId)) $mail->id = 0;
111
112 switch ($type) {
113 case MailClass::TYPE_WELCOME:
114 $breadcrumbTitle = 'ACYM_CREATE_WELCOME_MAIL';
115 break;
116 case MailClass::TYPE_UNSUBSCRIBE:
117 $breadcrumbTitle = 'ACYM_CREATE_UNSUBSCRIBE_MAIL';
118 break;
119 case MailClass::TYPE_AUTOMATION:
120 $breadcrumbTitle = 'ACYM_NEW_EMAIL';
121 break;
122 case MailClass::TYPE_FOLLOWUP:
123 $breadcrumbTitle = 'ACYM_NEW_FOLLOW_UP_EMAIL';
124 break;
125 case MailClass::TYPE_SCENARIO:
126 $breadcrumbTitle = 'ACYM_SCENARIO_EMAIL';
127 break;
128 default:
129 $breadcrumbTitle = 'ACYM_CREATE_TEMPLATE';
130 }
131
132 $breadcrumbTitle = acym_translation($breadcrumbTitle);
133 $breadcrumbUrl = 'mails&task=edit&type_editor='.$typeEditor.(!empty($fromId) ? '&from='.$fromId : '').'&type='.$type;
134 } else {
135 if (!$mailClass->hasUserAccess($tempId)) {
136 die('Access denied for this email');
137 }
138
139 $mail = $mailClass->getOneById($tempId);
140
141 if (!empty($fromMail)) {
142 $mail->drag_editor = $fromMail->drag_editor;
143 $mail->body = $fromMail->body;
144 $mail->stylesheet = $fromMail->stylesheet;
145 $mail->settings = $fromMail->settings;
146 $mail->from_email = $fromMail->from_email;
147 $mail->from_name = $fromMail->from_name;
148 $mail->reply_to_email = $fromMail->reply_to_email;
149 $mail->reply_to_name = $fromMail->reply_to_name;
150 }
151
152 if (!empty($followupId)) $followupClass->getDelaySettingToMail($mail, $followupId);
153
154 $mail->editor = $mail->drag_editor == 0 ? 'html' : 'acyEditor';
155 if (!empty($typeEditor)) $mail->editor = $typeEditor;
156
157 if (empty($notification)) {
158 if (in_array($mail->type, [MailClass::TYPE_WELCOME, MailClass::TYPE_UNSUBSCRIBE])) {
159 array_pop($this->breadcrumb);
160 $this->breadcrumb[acym_translation('ACYM_LISTS')] = acym_completeLink('lists');
161 }
162
163 if ($mail->type === MailClass::TYPE_OVERRIDE) {
164 array_pop($this->breadcrumb);
165 $this->breadcrumb[acym_translation('ACYM_EMAILS_OVERRIDE')] = acym_completeLink('override');
166 acym_loadLanguageFile('plg_user_joomla', ACYM_BASE);
167 acym_loadLanguageFile('com_users');
168 acym_loadLanguageFile('com_contact');
169 $breadcrumbTitle = acym_translationSprintf(
170 preg_replace(
171 '#^{trans:([A-Z_]+)(|.+)*}$#',
172 '$1',
173 $mail->subject
174 ),
175 '{param1}',
176 '{param2}'
177 );
178 } else {
179 $breadcrumbTitle = $mail->name;
180 }
181
182 $breadcrumbUrl = 'mails&task=edit&id='.$mail->id;
183 } else {
184 if (empty($return)) {
185 $return = empty($_SERVER['HTTP_REFERER']) ? '' : $_SERVER['HTTP_REFERER'];
186 }
187
188 $notifName = acym_translation('ACYM_NOTIFICATIION_'.strtoupper(substr($mail->name, 4)));
189 if (strpos($notifName, 'ACYM_NOTIFICATIION_') !== false) {
190
191 array_pop($this->breadcrumb);
192 $this->breadcrumb[acym_translation('ACYM_CONFIGURATION')] = acym_completeLink('configuration');
193
194 $notifName = $mail->name;
195
196 if ($notifName === 'acy_confirm') {
197 $notifName = acym_translation('ACYM_CONFIRMATION_EMAIL');
198 } elseif ($notifName === 'acy_notification_create') {
199 $notifName = acym_translation('ACYM_NOTIFICATION_CREATE_EMAIL');
200 } elseif ($notifName === 'acy_notification_unsub') {
201 $notifName = acym_translation('ACYM_NOTIFICATION_UNSUB_EMAIL');
202 } elseif ($notifName === 'acy_notification_unsuball') {
203 $notifName = acym_translation('ACYM_NOTIFICATION_UNSUBALL_EMAIL');
204 } elseif ($notifName === 'acy_notification_subform') {
205 $notifName = acym_translation('ACYM_NOTIFICATION_SUBFORM_EMAIL');
206 } elseif ($notifName === 'acy_notification_profile') {
207 $notifName = acym_translation('ACYM_NOTIFICATION_PROFILE_EMAIL');
208 } elseif ($notifName === 'acy_notification_confirm') {
209 $notifName = acym_translation('ACYM_NOTIFICATION_CONFIRM_EMAIL');
210 }
211 }
212
213 $breadcrumbTitle = $notifName;
214 $breadcrumbUrl = 'mails&task=edit&notification='.$mail->name;
215 }
216
217 if (!empty($mail->stylesheet) && strpos($mail->stylesheet, '[class="') !== false) {
218 acym_enqueueMessage(acym_translation('ACYM_WARNING_STYLESHEET_NOT_CORRECT'), 'warning');
219 }
220 }
221
222 if (!empty($return)) {
223 $breadcrumbUrl .= '&return='.urlencode(base64_encode($return));
224 }
225 $this->breadcrumb[acym_escape($breadcrumbTitle)] = acym_completeLink($breadcrumbUrl);
226
227 $lists = [];
228
229 if (in_array($mail->type, [MailClass::TYPE_WELCOME, MailClass::TYPE_UNSUBSCRIBE])) {
230 $listClass = new ListClass();
231 $lists = $listClass->getAllWithIdName();
232
233 if (empty($listIds) && !empty($mail->id)) $listIds = $listClass->getListIdsByWelcomeUnsub($mail->id, $mail->type == MailClass::TYPE_WELCOME);
234 if (!is_array($listIds)) {
235 $listIds = [$listIds];
236 }
237 }
238
239 if (!empty($mail->attachments) && !is_array($mail->attachments)) {
240 $mail->attachments = json_decode($mail->attachments);
241 } elseif (empty($mail->attachments)) {
242 $mail->attachments = [];
243 }
244
245 $tagClass = new TagClass();
246 $data = [
247 'mail' => $mail,
248 'allTags' => $tagClass->getAllTagsByType(TagClass::TYPE_MAIL),
249 'isAutomationAdmin' => $isAutomationAdmin,
250 'social_icons' => $this->config->get('social_icons', '{}'),
251 'fromId' => $fromId,
252 'langChoice' => acym_languageOption($mail->links_language, 'mail[links_language]'),
253 'list_id' => $listIds,
254 'lists' => $lists,
255 'delay_unit' => $followupClass->getDelayUnits(),
256 'default_delay_unit' => FollowupClass::DEFAULT_DELAY_UNIT,
257 'followup_id' => $followupId,
258 'uploadFileType' => new UploadFileType(),
259 'mailClass' => $mailClass,
260 ];
261 $followup = $followupClass->getOneById($data['followup_id']);
262
263 if (!empty($followup)) {
264 $data['followup_trigger'] = $followup->trigger;
265 }
266
267 $this->prepareMailMultilingual($data);
268 $this->prepareEditorEdit($data);
269
270 $campaignController->prepareMaxUpload($data);
271
272 if (!empty($return)) {
273 $data['return'] = $return;
274 }
275
276 acym_setVar('layout', 'edit');
277 $data['menuClass'] = $this->menuClass;
278
279 parent::display($data);
280 }
281
282 private function prepareMailMultilingual(array &$data): void
283 {
284 $mail = $data['mail'];
285 if (in_array($mail->type, [MailClass::TYPE_WELCOME, MailClass::TYPE_UNSUBSCRIBE, MailClass::TYPE_NOTIFICATION]) && acym_isMultilingual()) {
286 $data['multilingual'] = true;
287 }
288 }
289
290 private function prepareEditorEdit(array &$data): void
291 {
292 $data['editor'] = new EditorHelper();
293 $data['editor']->content = $data['mail']->body;
294 $data['editor']->autoSave = empty($data['mail']->autosave) ? '' : $data['mail']->autosave;
295 $data['editor']->editor = empty($data['mail']->editor) ? '' : $data['mail']->editor;
296 if (!empty($data['mail']->id)) $data['editor']->mailId = $data['mail']->id;
297 if (!empty($data['mail']->type)) $data['editor']->automation = $data['isAutomationAdmin'];
298 if (!empty($data['mail']->settings)) $data['editor']->settings = $data['mail']->settings;
299 if (!empty($data['mail']->stylesheet)) $data['editor']->stylesheet = $data['mail']->stylesheet;
300
301 $data['editor']->data = [
302 'mail' => $data['mail'],
303 'mailClass' => new MailClass(),
304 ];
305
306 if (!empty($data['multilingual'])) {
307 $data['editor']->data['tagClass'] = new TagClass();
308 $data['editor']->data['main_language'] = $this->config->get('multilingual_default');
309 $data['editor']->data['languages'] = explode(',', $this->config->get('multilingual_languages'));
310 $data['editor']->data['multilingual'] = true;
311
312 $allLanguages = acym_getLanguages();
313
314 $mainLang = new \stdClass();
315 $mainLang->code = $data['editor']->data['main_language'];
316 $mainLang->name = empty($allLanguages[$data['editor']->data['main_language']]) ? $data['editor']->data['main_language']
317 : $allLanguages[$data['editor']->data['main_language']]->name;
318 $data['editor']->data['main_language'] = $mainLang;
319 $mailClass = new MailClass();
320 $mailId = empty($data['mail']->id) ? -1 : $data['mail']->id;
321 $translations = $mailClass->getTranslationsById($mailId, true);
322 foreach ($data['editor']->data['languages'] as $i => $oneLangCode) {
323 $data['editor']->data['languages'][$i] = new \stdClass();
324 $data['editor']->data['languages'][$i]->code = $oneLangCode;
325 $data['editor']->data['languages'][$i]->name = empty($allLanguages[$oneLangCode]) ? $oneLangCode : $allLanguages[$oneLangCode]->name;
326 $data['editor']->data['languages'][$i]->subject = empty($translations[$oneLangCode]->subject) ? '' : $translations[$oneLangCode]->subject;
327 $data['editor']->data['languages'][$i]->preview = empty($translations[$oneLangCode]->preheader) ? '' : $translations[$oneLangCode]->preheader;
328 $data['editor']->data['languages'][$i]->content = empty($translations[$oneLangCode]->body) ? '' : $translations[$oneLangCode]->body;
329 $data['editor']->data['languages'][$i]->autosave = empty($translations[$oneLangCode]->autosave) ? '' : $translations[$oneLangCode]->autosave;
330 $data['editor']->data['languages'][$i]->settings = empty($translations[$oneLangCode]->settings) ? '' : $translations[$oneLangCode]->settings;
331 $data['editor']->data['languages'][$i]->stylesheet = empty($translations[$oneLangCode]->stylesheet) ? '' : $translations[$oneLangCode]->stylesheet;
332 }
333 $data['editor']->data['editor'] = new \stdClass();
334 $data['editor']->data['editor']->editor = 'acyEditor';
335 }
336
337 if ($data['editor']->isDragAndDrop()) {
338 $this->loadScripts['edit'][] = 'editor-wysid';
339 $this->loadScripts['edit']['vue-applications'] = ['custom_view'];
340 } else {
341 $this->loadScripts['edit'][] = 'dtextPicker';
342 }
343 }
344
345 public function store(bool $ajax = false): int
346 {
347 acym_checkToken();
348
349 $mailClass = new MailClass();
350 $formData = acym_getVar('array', 'mail', []);
351 $versions = acym_getVar('array', 'versions', [], 'REQUEST', ACYM_ALLOWRAW);
352 $versionType = acym_getVar('string', 'version_type', '');
353 $mail = new \stdClass();
354 $allowedFields = acym_getColumns('mail');
355 $fromId = acym_getVar('int', 'fromId', 0);
356 $return = acym_getVar('string', 'return');
357
358 $fromAutomation = false;
359
360 if (!empty($return) && strpos($return, 'automation') !== false) {
361 $fromAutomation = true;
362 }
363 foreach ($formData as $name => $data) {
364 if (!in_array($name, $allowedFields)) {
365 continue;
366 }
367
368 $mail->{$name} = $data;
369 }
370
371 if (!empty($mail->id)) {
372 if (!$mailClass->hasUserAccess($mail->id)) {
373 die('Cannot save this mail');
374 }
375 $previousMail = $mailClass->getOneById($mail->id);
376 }
377
378 $saveAsTmpl = acym_getVar('int', 'saveAsTmpl', 0);
379 if (!empty($versions)) {
380 $saveAsTmplVersion = $saveAsTmpl === 1 ? acym_getVar('string', 'saveAsTmplVersion', 'main') : 'main';
381 if (!empty($versions[$saveAsTmplVersion]['subject'])) $mail->subject = $versions[$saveAsTmplVersion]['subject'];
382 if (!empty($versions[$saveAsTmplVersion]['preview'])) $mail->preheader = $versions[$saveAsTmplVersion]['preview'];
383 if (!empty($versions[$saveAsTmplVersion]['content'])) $mail->body = $versions[$saveAsTmplVersion]['content'];
384 if (!empty($versions[$saveAsTmplVersion]['settings'])) $mail->settings = $versions[$saveAsTmplVersion]['settings'];
385 if (!empty($versions[$saveAsTmplVersion]['stylesheet'])) $mail->stylesheet = $versions[$saveAsTmplVersion]['stylesheet'];
386
387 if ($versionType === 'multilingual') {
388 $mail->links_language = $this->config->get('multilingual_default');
389 }
390
391 unset($versions['main']);
392 }
393
394 if ($saveAsTmpl === 1) {
395 unset($mail->id);
396 $mail->type = MailClass::TYPE_TEMPLATE;
397 }
398
399 if ($fromAutomation) {
400 acym_setVar('from', $mail->id);
401 acym_setVar('type', MailClass::TYPE_AUTOMATION);
402 acym_setVar('type_editor', 'acyEditor');
403 }
404
405 if (empty($mail->subject) && !empty($mail->type) && $mail->type != MailClass::TYPE_TEMPLATE) {
406 $mail->subject = acym_translation('ACYM_EMAIL_SUBJECT');
407 }
408
409 $inputNameBody = $saveAsTmpl === 1 ? 'editor_content_template' : 'editor_content';
410 $inputNameSettings = $saveAsTmpl === 1 ? 'editor_settings_template' : 'editor_settings';
411 $inputNameStylesheet = $saveAsTmpl === 1 ? 'editor_stylesheet_template' : 'editor_stylesheet';
412 $inputNameColors = $saveAsTmpl === 1 ? 'main_colors_template' : 'main_colors';
413
414 $mail->tags = acym_getVar('array', 'template_tags', []);
415 $mail->body = acym_getVar('string', $inputNameBody, '', 'REQUEST', ACYM_ALLOWRAW);
416 $mail->settings = acym_getVar('string', $inputNameSettings, '', 'REQUEST', ACYM_ALLOWRAW);
417 $mail->stylesheet = acym_getVar('string', $inputNameStylesheet, '', 'REQUEST', ACYM_ALLOWRAW);
418 $mail->headers = acym_getVar('string', 'editor_headers', '', 'REQUEST', ACYM_ALLOWRAW);
419 $mail->drag_editor = strpos($mail->body, 'acym__wysid__template') === false ? 0 : 1;
420
421 $mail->thumbnail = '';
422 if (!$fromAutomation) {
423 $thumbnailName = acym_getVar('string', 'editor_thumbnail', '', 'REQUEST', ACYM_ALLOWRAW);
424
425 if (preg_match('#^thumbnail_([0-9]*)\.png$#', $thumbnailName)) {
426 $mail->thumbnail = $thumbnailName;
427 }
428 }
429
430 if ($fromAutomation) $mail->type = MailClass::TYPE_AUTOMATION;
431 if (empty($mail->id)) {
432 $mail->creation_date = acym_date('now', 'Y-m-d H:i:s', false);
433 }
434
435 $uploadedThumbnail = $this->setThumbnailFromInput();
436 if (!empty($uploadedThumbnail)) {
437 if (!empty($previousMail->thumbnail)) {
438 acym_deleteFile(ACYM_UPLOAD_FOLDER_THUMBNAIL.$previousMail->thumbnail);
439 }
440
441 $mail->thumbnail = $uploadedThumbnail;
442 } elseif (acym_getVar('bool', 'custom_thumbnail_reset', false)) {
443 if (!empty($previousMail->thumbnail)) {
444 acym_deleteFile(ACYM_UPLOAD_FOLDER_THUMBNAIL.$previousMail->thumbnail);
445 }
446
447 $mail->thumbnail = null;
448 }
449
450 if (!empty($previousMail->mail_settings)) {
451 $mailSettings = json_decode($previousMail->mail_settings, false);
452 } else {
453 $mailSettings = new \stdClass();
454 }
455 $mailSettings->mainColors = acym_getVar('string', $inputNameColors, '', 'REQUEST', ACYM_ALLOWRAW);
456 $mail->mail_settings = json_encode($mailSettings);
457
458 if (!empty($fromId) && empty($mail->thumbnail) && !$fromAutomation) {
459 $thumbnail = $this->setThumbnailFrom($fromId);
460 if (!empty($thumbnail)) {
461 if (!empty($previousMail->thumbnail)) {
462 acym_deleteFile(ACYM_UPLOAD_FOLDER_THUMBNAIL.$previousMail->thumbnail);
463 }
464
465 $mail->thumbnail = $thumbnail;
466 }
467 }
468
469 if (empty($mail->name) && !in_array($mail->type, MailClass::TYPES_NO_NAME) && empty($mail->id)) {
470 $mail->name = empty($mail->subject) ? acym_translation('ACYM_TEMPLATE_NAME') : $mail->subject;
471 }
472
473 $this->setAttachmentToMail($mail);
474
475 $mailID = $mailClass->save($mail);
476 if (!empty($mailID)) {
477 if (!empty($mail->type) && in_array($mail->type, [MailClass::TYPE_WELCOME, MailClass::TYPE_UNSUBSCRIBE])) {
478 $listIds = acym_getVar('array', 'list_ids', []);
479 $listClass = new ListClass();
480 $listClass->setWelcomeUnsubEmail($listIds, (int)$mailID, $mail->type);
481 } elseif (!empty($mail->type) && $mail->type == MailClass::TYPE_FOLLOWUP) {
482 acym_setVar('return', acym_getVar('string', 'return').'&newEmailId='.$mailID);
483
484 $followupData = acym_getVar('array', 'followup', []);
485 $followupClass = new FollowupClass();
486 if (!$followupClass->saveDelaySettings($followupData, $mailID)) {
487 acym_enqueueMessage(acym_translation('ACYM_COULD_NOT_SAVE_DELAY_SETTINGS'), 'error');
488 }
489 if (!empty($followupData['id'])) {
490 acym_setVar('followup_id', $followupData['id']);
491 }
492 }
493
494 if (!$ajax) {
495 acym_enqueueMessage(acym_translation('ACYM_SUCCESSFULLY_SAVED'), 'success');
496 }
497
498 if ($fromAutomation) {
499 acym_setVar('type', MailClass::TYPE_AUTOMATION);
500 acym_setVar('type_editor', 'acyEditor');
501 } else {
502 acym_setVar('mailID', $mailID);
503 }
504
505 if (!empty($versions) && in_array($versionType, ['multilingual', 'abtest']) && $saveAsTmpl !== 1) {
506 $abTestSendingParams = [];
507 foreach ($versions as $code => $version) {
508 if (empty($version['subject'])) {
509 if ($versionType === 'multilingual') {
510 $mailClass->delete($mailClass->getTranslationId($mailID, $code));
511 } elseif (!empty($abTestSendingParams[$code])) {
512 $mailClass->delete($abTestSendingParams[$code]);
513 }
514 continue;
515 }
516
517 unset($mail->id);
518 $versionId = null;
519 if ($versionType === 'multilingual') {
520 $versionId = $mailClass->getTranslationId($mailID, $code);
521 } elseif (!empty($abTestSendingParams[$code])) {
522 $versionId = $abTestSendingParams[$code];
523 }
524 if (!empty($versionId)) {
525 $mail->id = $versionId;
526 }
527
528 $mail->subject = $version['subject'];
529 $mail->preheader = $version['preview'];
530 $mail->body = $version['content'];
531 $mail->parent_id = $mailID;
532 $mail->settings = $version['settings'];
533 $mail->stylesheet = $version['stylesheet'];
534
535 if ($versionType === 'multilingual') {
536 $mail->links_language = $code;
537 $mail->language = $code;
538 }
539
540 $abTestSendingParams[$code] = $mailClass->save($mail);
541 }
542 }
543
544 return (int)$mailID;
545 } else {
546 if (!$ajax) acym_enqueueMessage(acym_translation('ACYM_ERROR_SAVING'), 'error');
547 if (!empty($mailClass->errors)) {
548 if (!$ajax) acym_enqueueMessage($mailClass->errors, 'error');
549 }
550
551 return 0;
552 }
553 }
554
555 private function setThumbnailFromInput(): string
556 {
557 $thumbnailFile = acym_getVar('array', 'custom_thumbnail', [], 'FILES');
558 if (empty($thumbnailFile['name'])) {
559 return '';
560 }
561
562 $extension = acym_fileGetExt($thumbnailFile['name']);
563
564 $thumbNb = $this->config->get('numberThumbnail', 2);
565 $filename = 'thumbnail_custom_'.($thumbNb + 1).'.'.$extension;
566 $newConfig = new \stdClass();
567 $newConfig->numberThumbnail = $thumbNb + 1;
568 $this->config->save($newConfig);
569 $thumbnailFile['name'] = $filename;
570
571 ob_start();
572 $uploaded = acym_importFile($thumbnailFile, ACYM_UPLOAD_FOLDER_THUMBNAIL, true);
573 ob_end_clean();
574 if (!empty($uploaded)) {
575 return $uploaded;
576 }
577
578 acym_enqueueMessage(acym_translation('ACYM_UPLOADED_FILE_IS_NOT_IMAGE'), 'error');
579
580 return '';
581 }
582
583 public function setAttachmentToMail(object &$mail): void
584 {
585 if (!empty($mail->id)) {
586 $mailClass = new MailClass();
587 $mail->attachments = $mailClass->getMailAttachments($mail->id);
588 }
589
590 if (!empty($mail->attachments) && !is_array($mail->attachments)) {
591 $mail->attachments = json_decode($mail->attachments);
592 } else {
593 $mail->attachments = [];
594 }
595
596 $newAttachments = [];
597 $attachments = acym_getVar('array', 'attachments', []);
598 if (!empty($attachments)) {
599 foreach ($attachments as $filepath) {
600 if (empty($filepath)) continue;
601
602 $attachment = new \stdClass();
603 $attachment->filename = $filepath;
604 $attachment->size = filesize(ACYM_ROOT.$filepath);
605
606 if (preg_match('#\.(php.?|.?htm.?|pl|py|jsp|asp|sh|cgi)#Ui', $attachment->filename)) {
607 acym_enqueueMessage(
608 acym_translationSprintf(
609 'ACYM_ACCEPTED_TYPE',
610 substr($attachment->filename, strrpos($attachment->filename, '.') + 1),
611 $this->config->get('allowed_files')
612 ),
613 'notice'
614 );
615 continue;
616 }
617
618 if (in_array((array)$attachment, $mail->attachments)) continue;
619
620 $newAttachments[] = $attachment;
621 }
622 if (!empty($mail->attachments) && is_array($mail->attachments)) {
623 $newAttachments = array_merge($mail->attachments, $newAttachments);
624 }
625 $mail->attachments = $newAttachments;
626 }
627
628 if (empty($mail->attachments)) {
629 unset($mail->attachments);
630 }
631
632 if (!empty($mail->attachments) && !is_string($mail->attachments)) {
633 $mail->attachments = json_encode($mail->attachments);
634 }
635 }
636
637 private function setThumbnailFrom(int $fromId): string
638 {
639 $thumbNb = $this->config->get('numberThumbnail', 2);
640 $fileName = 'thumbnail_'.($thumbNb + 1).'.png';
641 $this->config->save(['numberThumbnail' => $thumbNb + 1]);
642
643 $mailClass = new MailClass();
644 $fromMail = $mailClass->getOneById($fromId);
645 $fromThumbnail = $fromMail->thumbnail;
646
647 $ret = acym_createFolder(ACYM_UPLOAD_FOLDER_THUMBNAIL);
648 if (!$ret) {
649 return '';
650 }
651
652 $fromThumbnailSource = acym_fileGetContent(acym_getMailThumbnail($fromThumbnail));
653 if (empty($fromThumbnailSource)) {
654 return '';
655 }
656
657 file_put_contents(ACYM_UPLOAD_FOLDER_THUMBNAIL.$fileName, $fromThumbnailSource);
658
659 return $fileName;
660 }
661
662 public function apply(): void
663 {
664 $mailId = $this->store();
665 acym_setVar('id', $mailId);
666 $this->edit();
667 }
668
669 public function save(): void
670 {
671 $mailId = $this->store();
672
673 $return = str_replace('{mailid}', empty($mailId) ? '' : $mailId, acym_getVar('string', 'return', ''));
674 if (empty($return)) {
675 $this->listing();
676 } else {
677 acym_redirect($return);
678 }
679 }
680
681 public function autoSave(): void
682 {
683 $mailClass = new MailClass();
684 $mail = new \stdClass();
685
686 $language = acym_getVar('string', 'language', 'main');
687 $mail->id = acym_getVar('int', 'mailId', 0);
688 $mail->autosave = acym_getVar('string', 'autoSave', '', 'REQUEST', ACYM_ALLOWRAW);
689
690 if (empty($mail->id) || !$mailClass->hasUserAccess($mail->id) || !$mailClass->autoSave($mail, $language)) {
691 acym_sendAjaxResponse('', [], false);
692 } else {
693 acym_sendAjaxResponse();
694 }
695 }
696
697 public function ajaxCheckVideoUrl(): void
698 {
699 acym_checkToken();
700 $videoUrl = acym_getVar('string', 'url', '');
701
702 if (!acym_isValidUrl($videoUrl)) {
703 acym_sendAjaxResponse('', [], false);
704 }
705
706 $image = '';
707 $imageName = '';
708
709 $youtubeMatch = '';
710 $vimeoMatch = '';
711 $dailymotionMatch = '';
712
713 preg_match('/(?:https?:\/{2})?(?:w{3}\.)?youtu(?:be)?\.(?:com|be)(?:\/watch\?v=|\/)([^\s&]+)/', $videoUrl, $youtubeMatch);
714 preg_match('/^.*(vimeo\.com\/)((channels\/[A-z]+\/)|(groups\/[A-z]+\/videos\/))?([0-9]+)/', $videoUrl, $vimeoMatch);
715 preg_match('/^(?:(?:http|https):\/\/)?(?:www.)?(dailymotion\.com|dai\.ly)\/((video\/([^_]+))|(hub\/([^_]+)|([^\/_]+)))$/', $videoUrl, $dailymotionMatch);
716
717 if (!empty($youtubeMatch)) {
718 $image = 'https://img.youtube.com/vi/'.$youtubeMatch[1].'/0.jpg';
719 $imageName = $youtubeMatch[1];
720 } elseif (!empty($dailymotionMatch)) {
721 $dailymotionImage = $dailymotionMatch[4] ?? $dailymotionMatch[2];
722
723 $image = 'https://www.dailymotion.com/thumbnail/video/'.$dailymotionImage;
724 $imageName = $dailymotionMatch[2];
725 } elseif (!empty($vimeoMatch)) {
726 $image = unserialize(file_get_contents('https://vimeo.com/api/v2/video/'.$vimeoMatch[5].'.php'));
727 $image = $image[0]['thumbnail_large'];
728 $imageName = $vimeoMatch[5];
729 }
730
731 if (empty($image) || !acym_isValidUrl($image)) {
732 acym_sendAjaxResponse('', [], false);
733 }
734
735 acym_sendAjaxResponse('', ['new_image_name' => $this->saveVideoPreview($image, urlencode($imageName).'.jpg')]);
736 }
737
738 private function saveVideoPreview(string $image, string $fileName): string
739 {
740 if (!$this->config->get('add_play_button_video', 1)) {
741 return $image;
742 }
743
744 $imageVideo = imagecreatefromjpeg($image);
745 $playButton = @imagecreatefrompng(ACYM_ROOT.ACYM_MEDIA_FOLDER.'images'.DS.'editor'.DS.'video_insertion'.DS.'play_button.png');
746 if ($playButton === false || $imageVideo === false) {
747 return $image;
748 }
749 $imageWidth = imagesx($imageVideo);
750 $imageHeight = imagesy($imageVideo);
751 $logoWidth = imagesx($playButton);
752 $logoHeight = imagesy($playButton);
753
754 $left = round(($imageWidth - $logoWidth) / 2);
755 $top = round(($imageHeight - $logoHeight) / 2);
756 imagecopy($imageVideo, $playButton, $left, $top, 0, 0, $logoWidth, $logoHeight);
757 imagepng($imageVideo, 'tmp.jpg', 9);
758
759 $input = imagecreatefrompng('tmp.jpg');
760 $output = imagecreatetruecolor($imageWidth, $imageHeight);
761 $white = imagecolorallocate($output, 255, 255, 255);
762
763 imagefilledrectangle($output, 0, 0, $imageWidth, $imageHeight, $white);
764 imagecopy($output, $input, 0, 0, 0, 0, $imageWidth, $imageHeight);
765
766 ob_start();
767 $status = imagejpeg($output, null, 95);
768 $imageContent = ob_get_clean();
769 if ($status && acym_writeFile(ACYM_ROOT.ACYM_UPLOAD_FOLDER.$fileName, $imageContent)) {
770 return ACYM_UPLOADS_URL.$fileName;
771 }
772
773 return '';
774 }
775
776 public function getTemplateAjax(): void
777 {
778 acym_checkToken();
779 $pagination = new PaginationHelper();
780 $id = acym_getVar('int', 'id');
781 $id = empty($id) ? '' : '&id='.$id;
782 $searchFilter = acym_getVar('string', 'search', '');
783 $tagFilter = acym_getVar('string', 'tag', 0);
784 $ordering = 'creation_date';
785 $orderingSortOrder = 'DESC';
786 $type = acym_getVar('string', 'type', 'custom');
787 $automation = acym_getVar('boolean', 'automation', false);
788 $returnUrl = acym_getVar('string', 'return');
789 $returnUrl = empty($returnUrl) || 'undefined' == $returnUrl ? '' : '&return='.urlencode(base64_encode($returnUrl));
790 $fromMultilingual = acym_getVar('int', 'is_multilingual_edition', 0);
791
792 $mailsPerPage = $pagination->getListLimit();
793 $page = acym_getVar('int', 'pagination_page_ajax', 1);
794 if ($page === 'undefined') {
795 $page = 1;
796 }
797
798 $mailClass = new MailClass();
799 $matchingMails = $mailClass->getMatchingElements(
800 [
801 'ordering' => $ordering,
802 'ordering_sort_order' => $orderingSortOrder,
803 'search' => $searchFilter,
804 'elementsPerPage' => $mailsPerPage,
805 'offset' => ($page - 1) * $mailsPerPage,
806 'tag' => $tagFilter,
807 'automation' => $automation,
808 'onlyStandard' => true,
809 'creator_id' => $this->setFrontEndParamsForTemplateChoose(),
810 'drag_editor' => !empty($fromMultilingual),
811 'gettingTemplates' => !$automation,
812 ]
813 );
814
815 $return = '<div class="grid-x grid-padding-x grid-padding-y grid-margin-x grid-margin-y xxlarge-up-6 large-up-4 medium-up-3 small-up-1 cell acym__template__choose__list margin-top-1">';
816
817 $followup_id = '';
818 if ($type == MailClass::TYPE_FOLLOWUP) {
819 $followup_id = acym_getVar('int', 'followup_id', 0);
820 }
821 $listId = 0;
822 if (in_array($type, [MailClass::TYPE_WELCOME, MailClass::TYPE_UNSUBSCRIBE])) {
823 $listId = acym_getVar('int', 'list_id', 0);
824 }
825 foreach ($matchingMails['elements'] as $oneTemplate) {
826 $return .= '<div class="cell grid-x acym__templates__oneTpl acym__listing__block" id="'.acym_escape($oneTemplate->id).'">
827 <div class="cell acym__templates__pic text-center">';
828
829 $url = acym_getVar('cmd', 'ctrl').'&task=edit&step=editEmail&from='.intval($oneTemplate->id).$returnUrl.'&type='.$type.$id.'&'.acym_getFormToken();
830 if (!empty($followup_id)) {
831 $url .= '&followup_id='.$followup_id;
832 }
833 if (!empty($listId)) {
834 $url .= '&list_id='.$listId;
835 }
836 if (!empty($this->data['campaignInformation'])) {
837 $url .= '&id='.intval($this->data['campaignInformation']);
838 }
839 if (!$automation || !empty($returnUrl)) {
840 $return .= '<a href="'.acym_completeLink($url, false, false, true).'">';
841 }
842
843 $return .= '<img src="'.acym_escape(acym_getMailThumbnail($oneTemplate->thumbnail)).'" alt="template thumbnail"/>';
844 if (!$automation || !empty($returnUrl)) {
845 $return .= '</a>';
846 }
847
848 if ($oneTemplate->drag_editor) {
849 $return .= '<div class="acym__templates__choose__ribbon acyeditor">'.acym_translation('ACYM_DD_EDITOR').'</div>';
850 } else {
851 $return .= '<div class="acym__templates__choose__ribbon htmleditor">'.acym_translation('ACYM_HTML_EDITOR').'</div>';
852 }
853
854 if (strlen($oneTemplate->name) > 55) {
855 $oneTemplate->name = substr($oneTemplate->name, 0, 50).'...';
856 }
857 $return .= '</div>
858 <div class="cell grid-x acym__templates__footer text-center">
859 <div class="cell acym__templates__footer__title acym_text_ellipsis" title="'.acym_escape($oneTemplate->name).'">'.acym_escape($oneTemplate->name).'</div>
860 <div class="cell">'.acym_date($oneTemplate->creation_date, 'ACYM_DATE_FORMAT_LC3').'</div>
861 </div>
862 </div>';
863 }
864
865 $return .= '</div>';
866
867 $pagination->setStatus((int)$matchingMails['total']->total, $page, $mailsPerPage);
868
869 $return .= $pagination->displayAjax();
870
871 echo $return;
872 exit;
873 }
874
875 public function setNewThumbnail(): void
876 {
877 if (!acym_isAdmin()) {
878 die('Access denied for thumbnail creation');
879 }
880
881 acym_checkToken();
882 $contentThumbnail = acym_getVar('string', 'content', '');
883 if (strpos($contentThumbnail, 'data:image/png') !== 0) {
884 acym_sendAjaxResponse('This file is not allowed.', [], false);
885 }
886
887 $mailId = acym_getVar('int', 'mailId', 0);
888 if (!empty($mailId)) {
889 $mailClass = new MailClass();
890 $mail = $mailClass->getOneById($mailId);
891 if (!empty($mail)) {
892 $file = $mail->thumbnail;
893 }
894 }
895
896 if (empty($file) || strpos($file, 'http') === 0) {
897 $thumbNb = $this->config->get('numberThumbnail', 2);
898 $file = 'thumbnail_'.($thumbNb + 1).'.png';
899 $newConfig = new \stdClass();
900 $newConfig->numberThumbnail = $thumbNb + 1;
901 $this->config->save($newConfig);
902 }
903
904 $extension = acym_fileGetExt($file);
905 if (strpos($file, 'thumbnail_') === false || !in_array($extension, ['png', 'jpeg', 'jpg', 'gif', 'webp'])) {
906 acym_sendAjaxResponse('This file is not allowed.', [], false);
907 }
908
909 acym_createFolder(ACYM_UPLOAD_FOLDER_THUMBNAIL);
910 file_put_contents(ACYM_UPLOAD_FOLDER_THUMBNAIL.$file, base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $contentThumbnail)));
911
912 acym_sendAjaxResponse('', ['fileName' => $file]);
913 }
914
915 public function setNewIconShare(): void
916 {
917 acym_checkToken();
918 $socialName = acym_getVar('string', 'social', '');
919 $socialMedias = acym_getSocialMedias();
920 if (!in_array($socialName, $socialMedias)) {
921 acym_sendAjaxResponse(acym_translationSprintf('ACYM_UNKNOWN_SOCIAL', $socialName), [], false);
922 }
923
924 $extension = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
925 $newPath = ACYM_UPLOAD_FOLDER.'socials'.DS.$socialName;
926 $newPathComplete = $newPath.'.'.$extension;
927
928 $allowedExtensions = acym_getImageFileExtensions();
929 if (!in_array($extension, $allowedExtensions)) {
930 $errorMessage = acym_translationSprintf('ACYM_ACCEPTED_TYPE', $extension, implode(', ', $allowedExtensions));
931 } elseif (!acym_uploadFile($_FILES['file']['tmp_name'], ACYM_ROOT.$newPathComplete)) {
932 $errorMessage = acym_translationSprintf('ACYM_ERROR_UPLOADING_FILE_X', $newPathComplete);
933 }
934
935 if (!empty($errorMessage)) {
936 acym_sendAjaxResponse($errorMessage, [], false);
937 }
938
939 $newConfig = new \stdClass();
940 $newConfig->social_icons = json_decode($this->config->get('social_icons', '{}'), true);
941
942 $newImg = acym_rootURI().$newPathComplete;
943 $newImgWithoutExtension = acym_rootURI().$newPath;
944
945 $newConfig->social_icons[$socialName] = $newImg;
946 $newConfig->social_icons = json_encode($newConfig->social_icons);
947 $this->config->save($newConfig);
948
949 acym_sendAjaxResponse(
950 acym_translation('ACYM_ICON_IMPORTED'),
951 [
952 'url' => $newImgWithoutExtension,
953 'extension' => $extension,
954 ]
955 );
956 }
957
958 public function saveAjax(): void
959 {
960 $mailId = $this->store(true);
961 if (!empty($mailId)) {
962 acym_sendAjaxResponse('', ['result' => $mailId]);
963 } else {
964 acym_sendAjaxResponse(acym_translation('ACYM_ERROR_SAVING'), [], false);
965 }
966 }
967
968 public function loadCSS(): void
969 {
970 header('Content-Type: text/css');
971 $idMail = acym_getVar('int', 'id', 0);
972 if (empty($idMail)) {
973 exit;
974 }
975
976 $mailClass = new MailClass();
977 $mail = $mailClass->getOneById($idMail);
978
979 echo $mailClass->buildCSS($mail->stylesheet);
980 exit;
981 }
982
983 public function test(): void
984 {
985 $mailId = $this->store();
986 $return = acym_getVar('string', 'return', '');
987 acym_setVar('return', $return);
988 acym_setVar('id', $mailId);
989
990 $mailClass = new MailClass();
991 $mail = $mailClass->getOneById($mailId);
992
993 if (empty($mail)) {
994 acym_enqueueMessage(acym_translation('ACYM_CAMPAIGN_NOT_FOUND'), 'error');
995 $this->edit();
996
997 return;
998 }
999
1000 $mailerHelper = new MailerHelper();
1001 $mailerHelper->autoAddUser = true;
1002 $mailerHelper->report = false;
1003
1004 $currentEmail = acym_currentUserEmail();
1005 $options = ['isTest' => true];
1006 if ($mailerHelper->sendOne($mailId, $currentEmail, $options)) {
1007 acym_enqueueMessage(acym_translationSprintf('ACYM_SEND_SUCCESS', $mail->name, $currentEmail), 'info');
1008 } else {
1009 $notification = [
1010 'name' => 'send_error',
1011 'removable' => 1,
1012 ];
1013 acym_enqueueMessage(acym_translationSprintf('ACYM_SEND_ERROR', $mail->name, $currentEmail), 'error', true, [$notification]);
1014 }
1015
1016 $this->edit();
1017 }
1018
1019 public function sendTest(): void
1020 {
1021 acym_checkToken();
1022 $controller = acym_getVar('string', 'controller', 'mails');
1023 $level = 'info';
1024
1025 $testNote = acym_getVar('string', 'test_note', '');
1026 $mailClass = new MailClass();
1027 $mailerHelper = new MailerHelper();
1028 $mailerHelper->autoAddUser = true;
1029 $mailerHelper->report = false;
1030
1031 if (in_array($controller, ['mails', 'frontmails'])) {
1032 $mailId = acym_getVar('int', 'id', 0);
1033 } else {
1034 $campaignId = acym_getVar('int', 'id', 0);
1035 $campaignClass = new CampaignClass();
1036 $campaign = $campaignClass->getOneById($campaignId);
1037 if (empty($campaign)) {
1038 acym_sendAjaxResponse('', ['level' => 'error', 'message' => acym_translation('ACYM_CAMPAIGN_NOT_FOUND')], false);
1039 }
1040 if (!$campaignClass->hasUserAccess($campaignId)) {
1041 die('A test of this campaign cannot be sent');
1042 }
1043
1044 $mailId = $campaign->mail_id;
1045 $mailerHelper->isAbTest = $campaignClass->isAbTestMail($mailId);
1046
1047 $campaignVersion = acym_getVar('string', 'lang_version', 'main');
1048 if (!empty($campaignVersion) && $campaignVersion !== 'main') {
1049 if ($campaignVersion === 'B') {
1050 $versions = $mailClass->getVersionsById($mailId);
1051 if (!empty($versions)) {
1052 $mailIds = array_keys($versions);
1053 $mailId = array_pop($mailIds);
1054 }
1055 } else {
1056 $translationId = $mailClass->getTranslationId($mailId, $campaignVersion);
1057 if (!empty($translationId)) {
1058 $mailId = $translationId;
1059 }
1060 }
1061 }
1062 }
1063
1064 $mail = $mailClass->getOneById($mailId);
1065
1066 if (empty($mail) || !$mailClass->hasUserAccess($mailId)) {
1067 acym_sendAjaxResponse('', ['level' => 'error', 'message' => acym_translation('ACYM_EMAIL_NOT_FOUND')], false);
1068 }
1069
1070 $report = [];
1071
1072 $testEmails = explode(',', acym_getVar('string', 'test_emails'));
1073 $options = [
1074 'isTest' => true,
1075 'testNote' => $testNote,
1076 ];
1077 foreach ($testEmails as $oneAddress) {
1078 if (!$mailerHelper->sendOne($mail->id, $oneAddress, $options)) {
1079 $level = 'error';
1080 }
1081
1082 if (!empty($mailerHelper->reportMessage)) {
1083 $report[] = $mailerHelper->reportMessage;
1084 }
1085 }
1086
1087 acym_sendAjaxResponse('', ['level' => $level, 'message' => implode('<br/>', $report)], $level !== 'error');
1088 }
1089
1090 public function getMailContent(): void
1091 {
1092 $from = acym_getVar('int', 'from', 0);
1093
1094 if (empty($from)) {
1095 acym_sendAjaxResponse(acym_translation('ACYM_EMAIL_NOT_FOUND'), [], false);
1096 }
1097
1098 $mailClass = new MailClass();
1099 $mail = $mailClass->getOneById($from);
1100
1101 if (empty($mail)) {
1102 acym_sendAjaxResponse(acym_translation('ACYM_EMAIL_NOT_FOUND'), [], false);
1103 }
1104
1105 if ($mail->drag_editor == 0) {
1106 acym_sendAjaxResponse('Only available for the drag and drop editor.', [], false);
1107 }
1108
1109 acym_sendAjaxResponse();
1110 }
1111
1112 protected function setFrontEndParamsForTemplateChoose(): int
1113 {
1114 return 0;
1115 }
1116
1117 public function saveAsTmplAjax(): void
1118 {
1119 $mailId = $this->store(true);
1120 acym_sendAjaxResponse(!empty($mailId) ? '' : acym_translation('ACYM_ERROR_SAVING'), ['result' => $mailId], !empty($mailId));
1121 }
1122 }
1123