PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / 10.10.2
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress v10.10.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.10.2, at back/Controllers/Mails/Edition.php

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