PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / 11.1.0
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress v11.1.0
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/Controllers/Mails/Edition.php +278 -199 10.0.1 → 11.1.0 View file →
@@ -14,12 +14,12 @@
14 14 use AcyMailing\Types\UploadFileType;
15 15
16 16 trait Edition
17 17 {
18 - public function edit()
18 + public function edit(): void
19 19 {
20 20 if (!acym_isAdmin()) {
21 - acym_checkToken();
21 + wp_verify_nonce(acym_getVar('cmd', '_wpnonce'), 'acymnonce') || die('Invalid Token');
22 22 }
23 23
24 24 $tempId = acym_getVar('int', 'id');
25 25 $mailClass = new MailClass();
@@ -62,8 +62,12 @@
62 62 $isAutomationAdmin = false;
63 63 $fromMail = '';
64 64
65 65 if (!empty($fromId)) {
66 + if (!$mailClass->hasUserAccess($fromId)) {
67 + die('Access denied for this email');
68 + }
69 +
66 70 $fromMail = $mailClass->getOneById($fromId);
67 71 }
68 72
69 73 if ($type === 'automation_admin') {
@@ -70,8 +74,9 @@
70 74 $type = MailClass::TYPE_AUTOMATION;
71 75 $isAutomationAdmin = true;
72 76 }
73 77
78 + // new mails
74 79 if (empty($tempId)) {
75 80 if (empty($fromId)) {
76 81 $mail = new \stdClass();
77 82 $mail->name = '';
@@ -131,8 +136,9 @@
131 136
132 137 $breadcrumbTitle = acym_translation($breadcrumbTitle);
133 138 $breadcrumbUrl = 'mails&task=edit&type_editor='.$typeEditor.(!empty($fromId) ? '&from='.$fromId : '').'&type='.$type;
134 139 } else {
140 + // Existing mails and notifications
135 141 if (!$mailClass->hasUserAccess($tempId)) {
136 142 die('Access denied for this email');
137 143 }
138 144
@@ -181,14 +187,14 @@
181 187
182 188 $breadcrumbUrl = 'mails&task=edit&id='.$mail->id;
183 189 } else {
184 190 if (empty($return)) {
185 - $return = empty($_SERVER['HTTP_REFERER']) ? '' : $_SERVER['HTTP_REFERER'];
191 + $httpReferer = acym_getVar('string', 'HTTP_REFERER', '', 'SERVER');
192 + $return = empty($httpReferer) ? '' : $httpReferer;
186 193 }
187 194
188 195 $notifName = acym_translation('ACYM_NOTIFICATIION_'.strtoupper(substr($mail->name, 4)));
189 196 if (strpos($notifName, 'ACYM_NOTIFICATIION_') !== false) {
190 -
191 197 array_pop($this->breadcrumb);
192 198 $this->breadcrumb[acym_translation('ACYM_CONFIGURATION')] = acym_completeLink('configuration');
193 199
194 200 $notifName = $mail->name;
@@ -221,9 +227,9 @@
221 227
222 228 if (!empty($return)) {
223 229 $breadcrumbUrl .= '&return='.urlencode(base64_encode($return));
224 230 }
225 - $this->breadcrumb[acym_escape($breadcrumbTitle)] = acym_completeLink($breadcrumbUrl);
231 + $this->breadcrumb[$breadcrumbTitle] = acym_completeLink($breadcrumbUrl);
226 232
227 233 $lists = [];
228 234
229 235 if (in_array($mail->type, [MailClass::TYPE_WELCOME, MailClass::TYPE_UNSUBSCRIBE])) {
@@ -236,14 +242,17 @@
236 242 }
237 243 }
238 244
239 245 if (!empty($mail->attachments) && !is_array($mail->attachments)) {
240 - $mail->attachments = json_decode($mail->attachments);
246 + $mail->attachments = json_decode($mail->attachments, true);
241 247 } elseif (empty($mail->attachments)) {
242 248 $mail->attachments = [];
243 249 }
244 250
251 + $mail->thumbnail = $mail->thumbnail ?? '';
252 +
245 253 $tagClass = new TagClass();
254 + $languages = acym_getLanguages(true, true);
246 255 $data = [
247 256 'mail' => $mail,
248 257 'allTags' => $tagClass->getAllTagsByType(TagClass::TYPE_MAIL),
249 258 'isAutomationAdmin' => $isAutomationAdmin,
@@ -248,9 +257,14 @@
248 257 'allTags' => $tagClass->getAllTagsByType(TagClass::TYPE_MAIL),
249 258 'isAutomationAdmin' => $isAutomationAdmin,
250 259 'social_icons' => $this->config->get('social_icons', '{}'),
251 260 'fromId' => $fromId,
252 - 'langChoice' => acym_languageOption($mail->links_language, 'mail[links_language]'),
261 + 'langChoice' => count($languages) < 2
262 + ? []
263 + : [
264 + 'links' => $mail->links_language,
265 + 'name' => 'mail[links_language]',
266 + ],
253 267 'list_id' => $listIds,
254 268 'lists' => $lists,
255 269 'delay_unit' => $followupClass->getDelayUnits(),
256 270 'default_delay_unit' => FollowupClass::DEFAULT_DELAY_UNIT,
@@ -278,17 +292,17 @@
278 292
279 293 parent::display($data);
280 294 }
281 295
282 - private function prepareMailMultilingual(&$data)
296 + private function prepareMailMultilingual(array &$data): void
283 297 {
284 298 $mail = $data['mail'];
285 - if (in_array($mail->type, [$data['mailClass']::TYPE_WELCOME, $data['mailClass']::TYPE_UNSUBSCRIBE, $data['mailClass']::TYPE_NOTIFICATION]) && acym_isMultilingual()) {
299 + if (in_array($mail->type, [MailClass::TYPE_WELCOME, MailClass::TYPE_UNSUBSCRIBE, MailClass::TYPE_NOTIFICATION]) && acym_isMultilingual()) {
286 300 $data['multilingual'] = true;
287 301 }
288 302 }
289 303
290 - private function prepareEditorEdit(&$data)
304 + private function prepareEditorEdit(array &$data): void
291 305 {
292 306 $data['editor'] = new EditorHelper();
293 307 $data['editor']->content = $data['mail']->body;
294 308 $data['editor']->autoSave = empty($data['mail']->autosave) ? '' : $data['mail']->autosave;
@@ -341,26 +355,33 @@
341 355 $this->loadScripts['edit'][] = 'dtextPicker';
342 356 }
343 357 }
344 358
345 - public function store($ajax = false)
359 + /**
360 + * Spaghetti code, needs refactoring.
361 + *
362 + * 1 - Save the main mail
363 + * 2 - Save the alternate versions if any
364 + */
365 + public function store(bool $ajax = false): int
346 366 {
347 - acym_checkToken();
367 + wp_verify_nonce(acym_getVar('cmd', '_wpnonce'), 'acymnonce') || die('Invalid Token');
348 368
349 369 $mailClass = new MailClass();
350 370 $formData = acym_getVar('array', 'mail', []);
351 371 $versions = acym_getVar('array', 'versions', [], 'REQUEST', ACYM_ALLOWRAW);
352 372 $versionType = acym_getVar('string', 'version_type', '');
353 - $mail = new \stdClass();
354 - $allowedFields = acym_getColumns('mail');
355 - $fromId = acym_getVar('int', 'fromId', '');
373 + $currentVersion = acym_getVar('string', 'current_version', 'main');
374 + $allowedFields = array_diff(acym_getColumns('mail'), ['creator_id']);
375 + $fromId = acym_getVar('int', 'fromId', 0);
356 376 $return = acym_getVar('string', 'return');
357 377
358 378 $fromAutomation = false;
359 -
360 379 if (!empty($return) && strpos($return, 'automation') !== false) {
361 380 $fromAutomation = true;
362 381 }
382 +
383 + $mail = new \stdClass();
363 384 foreach ($formData as $name => $data) {
364 385 if (!in_array($name, $allowedFields)) {
365 386 continue;
366 387 }
@@ -368,11 +389,12 @@
368 389 $mail->{$name} = $data;
369 390 }
370 391
371 392 if (!empty($mail->id)) {
372 - if (!$mailClass->hasUserAccess($mail->id)) {
393 + if (!$mailClass->hasUserAccess($mail->id, true)) {
373 394 die('Cannot save this mail');
374 395 }
396 +
375 397 $previousMail = $mailClass->getOneById($mail->id);
376 398 }
377 399
378 400 $saveAsTmpl = acym_getVar('int', 'saveAsTmpl', 0);
@@ -386,10 +408,8 @@
386 408
387 409 if ($versionType === 'multilingual') {
388 410 $mail->links_language = $this->config->get('multilingual_default');
389 411 }
390 -
391 - unset($versions['main']);
392 412 }
393 413
394 414 if ($saveAsTmpl === 1) {
395 415 unset($mail->id);
@@ -401,9 +421,9 @@
401 421 acym_setVar('type', MailClass::TYPE_AUTOMATION);
402 422 acym_setVar('type_editor', 'acyEditor');
403 423 }
404 424
405 - if (empty($mail->subject) && !empty($mail->type) && $mail->type != MailClass::TYPE_TEMPLATE) {
425 + if (empty($mail->subject) && !empty($mail->type) && $mail->type !== MailClass::TYPE_TEMPLATE) {
406 426 $mail->subject = acym_translation('ACYM_EMAIL_SUBJECT');
407 427 }
408 428
409 429 $inputNameBody = $saveAsTmpl === 1 ? 'editor_content_template' : 'editor_content';
@@ -416,11 +436,13 @@
416 436 $mail->settings = acym_getVar('string', $inputNameSettings, '', 'REQUEST', ACYM_ALLOWRAW);
417 437 $mail->stylesheet = acym_getVar('string', $inputNameStylesheet, '', 'REQUEST', ACYM_ALLOWRAW);
418 438 $mail->headers = acym_getVar('string', 'editor_headers', '', 'REQUEST', ACYM_ALLOWRAW);
419 439 $mail->drag_editor = strpos($mail->body, 'acym__wysid__template') === false ? 0 : 1;
440 + $mail->thumbnail = '';
420 441
421 - $mail->thumbnail = '';
422 - if (!$fromAutomation) {
442 + if ($fromAutomation) {
443 + $mail->type = MailClass::TYPE_AUTOMATION;
444 + } else {
423 445 $thumbnailName = acym_getVar('string', 'editor_thumbnail', '', 'REQUEST', ACYM_ALLOWRAW);
424 446
425 447 if (preg_match('#^thumbnail_([0-9]*)\.png$#', $thumbnailName)) {
426 448 $mail->thumbnail = $thumbnailName;
@@ -426,9 +448,8 @@
426 448 $mail->thumbnail = $thumbnailName;
427 449 }
428 450 }
429 451
430 - if ($fromAutomation) $mail->type = MailClass::TYPE_AUTOMATION;
431 452 if (empty($mail->id)) {
432 453 $mail->creation_date = acym_date('now', 'Y-m-d H:i:s', false);
433 454 }
434 455
@@ -451,11 +472,13 @@
451 472 $mailSettings = json_decode($previousMail->mail_settings, false);
452 473 } else {
453 474 $mailSettings = new \stdClass();
454 475 }
476 +
455 477 $mailSettings->mainColors = acym_getVar('string', $inputNameColors, '', 'REQUEST', ACYM_ALLOWRAW);
456 478 $mail->mail_settings = json_encode($mailSettings);
457 479
480 + // Use the thumbnail of the source mail if not modified
458 481 if (!empty($fromId) && empty($mail->thumbnail) && !$fromAutomation) {
459 482 $thumbnail = $this->setThumbnailFrom($fromId);
460 483 if (!empty($thumbnail)) {
461 484 if (!empty($previousMail->thumbnail)) {
@@ -471,98 +494,115 @@
471 494 }
472 495
473 496 $this->setAttachmentToMail($mail);
474 497
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, $mailID, $mail->type);
481 - } elseif (!empty($mail->type) && $mail->type == MailClass::TYPE_FOLLOWUP) {
482 - acym_setVar('return', acym_getVar('string', 'return').'&newEmailId='.$mailID);
498 + if ($versionType === 'multilingual' && $currentVersion !== 'main') {
499 + if (empty($mail->id)) {
500 + $mail->subject = $versions['main']['subject'];
501 + $mail->body = $versions['main']['content'];
502 + $mail->preheader = $versions['main']['preview'];
503 + $mail->settings = $versions['main']['settings'];
504 + $mail->stylesheet = $versions['main']['stylesheet'];
483 505
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 - }
506 + $mailID = $mailClass->save($mail);
507 + } else {
508 + $mailID = $mail->id;
492 509 }
510 + } else {
511 + $mailID = $mailClass->save($mail);
512 + }
493 513
514 + if (empty($mailID)) {
494 515 if (!$ajax) {
495 - acym_enqueueMessage(acym_translation('ACYM_SUCCESSFULLY_SAVED'), 'success');
516 + acym_enqueueMessage(acym_translation('ACYM_ERROR_SAVING'), 'error');
496 517 }
497 518
498 - if ($fromAutomation) {
499 - acym_setVar('type', MailClass::TYPE_AUTOMATION);
500 - acym_setVar('type_editor', 'acyEditor');
501 - } else {
502 - acym_setVar('mailID', $mailID);
519 + if (!empty($mailClass->errors)) {
520 + if (!$ajax) acym_enqueueMessage($mailClass->errors, 'error');
503 521 }
504 522
505 - if (!empty($versions) && in_array($versionType, ['multilingual', 'abtest']) && $saveAsTmpl !== 1) {
506 - $abTestSendingParams = empty($campaign->sending_params['abtest']) ? [] : $campaign->sending_params['abtest'];
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 - }
523 + return 0;
524 + }
516 525
517 - unset($mail->id);
518 - $versionId = null;
526 + if (!empty($mail->type) && in_array($mail->type, [MailClass::TYPE_WELCOME, MailClass::TYPE_UNSUBSCRIBE])) {
527 + $listIds = acym_getVar('array', 'list_ids', []);
528 + $listClass = new ListClass();
529 + $listClass->setWelcomeUnsubEmail($listIds, (int)$mailID, $mail->type);
530 + } elseif (!empty($mail->type) && $mail->type === MailClass::TYPE_FOLLOWUP) {
531 + // Pass the new email ID in the return URL to ask user if we should add it to the queue
532 + acym_setVar('return', acym_getVar('string', 'return').'&newEmailId='.$mailID);
533 +
534 + $followupData = acym_getVar('array', 'followup', []);
535 + $followupClass = new FollowupClass();
536 + if (!$followupClass->saveDelaySettings($followupData, $mailID)) {
537 + acym_enqueueMessage(acym_translation('ACYM_COULD_NOT_SAVE_DELAY_SETTINGS'), 'error');
538 + }
539 + if (!empty($followupData['id'])) {
540 + acym_setVar('followup_id', $followupData['id']);
541 + }
542 + }
543 +
544 + if (!$ajax) {
545 + acym_enqueueMessage(acym_translation('ACYM_SUCCESSFULLY_SAVED'));
546 + }
547 +
548 + if ($fromAutomation) {
549 + acym_setVar('type', MailClass::TYPE_AUTOMATION);
550 + acym_setVar('type_editor', 'acyEditor');
551 + } else {
552 + acym_setVar('mailID', $mailID);
553 + }
554 +
555 + if (!empty($versions) && in_array($versionType, ['multilingual', 'abtest']) && $saveAsTmpl !== 1) {
556 + $abTestSendingParams = [];
557 +
558 + unset($versions['main']);
559 + foreach ($versions as $code => $version) {
560 + if (empty($version['subject'])) {
519 561 if ($versionType === 'multilingual') {
520 - $versionId = $mailClass->getTranslationId($mailID, $code);
562 + $mailClass->delete([$mailClass->getTranslationId($mailID, $code)]);
521 563 } elseif (!empty($abTestSendingParams[$code])) {
522 - $versionId = $abTestSendingParams[$code];
564 + $mailClass->delete([$abTestSendingParams[$code]]);
523 565 }
524 - if (!empty($versionId)) {
525 - $mail->id = $versionId;
526 - }
566 + continue;
567 + }
527 568
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'];
569 + unset($mail->id);
570 + $versionId = null;
571 + if ($versionType === 'multilingual') {
572 + $versionId = $mailClass->getTranslationId($mailID, $code);
573 + } elseif (!empty($abTestSendingParams[$code])) {
574 + $versionId = $abTestSendingParams[$code];
575 + }
534 576
535 - if ($versionType === 'multilingual') {
536 - $mail->links_language = $code;
537 - $mail->language = $code;
538 - }
577 + if (!empty($versionId)) {
578 + $mail->id = $versionId;
579 + }
539 580
540 - $versionMailId = $mailClass->save($mail);
541 - $abTestSendingParams[$code] = $versionMailId;
542 - }
581 + $mail->subject = $version['subject'];
582 + $mail->preheader = $version['preview'];
583 + $mail->body = $version['content'];
584 + $mail->parent_id = $mailID;
585 + $mail->settings = $version['settings'];
586 + $mail->stylesheet = $version['stylesheet'];
543 587
544 - if ($versionType === 'abtest') {
545 - $campaign->sending_params['abtest'] = $abTestSendingParams;
588 + if ($versionType === 'multilingual') {
589 + $mail->links_language = $code;
590 + $mail->language = $code;
546 591 }
547 - }
548 592
549 - return $mailID;
550 - } else {
551 - if (!$ajax) acym_enqueueMessage(acym_translation('ACYM_ERROR_SAVING'), 'error');
552 - if (!empty($mailClass->errors)) {
553 - if (!$ajax) acym_enqueueMessage($mailClass->errors, 'error');
593 + $abTestSendingParams[$code] = $mailClass->save($mail);
554 594 }
595 + }
555 596
556 - return false;
557 - }
597 + return (int)$mailID;
558 598 }
559 599
560 - protected function setThumbnailFromInput()
600 + private function setThumbnailFromInput(): string
561 601 {
562 602 $thumbnailFile = acym_getVar('array', 'custom_thumbnail', [], 'FILES');
563 603 if (empty($thumbnailFile['name'])) {
564 - return false;
604 + return '';
565 605 }
566 606
567 607 $extension = acym_fileGetExt($thumbnailFile['name']);
568 608
@@ -567,26 +607,24 @@
567 607 $extension = acym_fileGetExt($thumbnailFile['name']);
568 608
569 609 $thumbNb = $this->config->get('numberThumbnail', 2);
570 610 $filename = 'thumbnail_custom_'.($thumbNb + 1).'.'.$extension;
571 - $newConfig = new \stdClass();
572 - $newConfig->numberThumbnail = $thumbNb + 1;
573 - $this->config->save($newConfig);
611 + $this->config->saveConfig(['numberThumbnail' => $thumbNb + 1]);
574 612 $thumbnailFile['name'] = $filename;
575 613
576 614 ob_start();
577 615 $uploaded = acym_importFile($thumbnailFile, ACYM_UPLOAD_FOLDER_THUMBNAIL, true);
578 616 ob_end_clean();
579 - if ($uploaded) {
617 + if (!empty($uploaded)) {
580 618 return $uploaded;
581 619 }
582 620
583 621 acym_enqueueMessage(acym_translation('ACYM_UPLOADED_FILE_IS_NOT_IMAGE'), 'error');
584 622
585 - return false;
623 + return '';
586 624 }
587 625
588 - public function setAttachmentToMail(&$mail)
626 + public function setAttachmentToMail(object $mail): void
589 627 {
590 628 if (!empty($mail->id)) {
591 629 $mailClass = new MailClass();
592 630 $mail->attachments = $mailClass->getMailAttachments($mail->id);
@@ -591,14 +629,17 @@
591 629 $mailClass = new MailClass();
592 630 $mail->attachments = $mailClass->getMailAttachments($mail->id);
593 631 }
594 632
595 - if (!empty($mail->attachments) && !is_array($mail->attachments)) {
596 - $mail->attachments = json_decode($mail->attachments);
633 + if (!empty($mail->attachments)) {
634 + if (!is_array($mail->attachments)) {
635 + $mail->attachments = json_decode($mail->attachments, true);
636 + }
597 637 } else {
598 638 $mail->attachments = [];
599 639 }
600 640
641 + // Attachments
601 642 $newAttachments = [];
602 643 $attachments = acym_getVar('array', 'attachments', []);
603 644 if (!empty($attachments)) {
604 645 foreach ($attachments as $filepath) {
@@ -603,17 +644,19 @@
603 644 if (!empty($attachments)) {
604 645 foreach ($attachments as $filepath) {
605 646 if (empty($filepath)) continue;
606 647
607 - $attachment = new \stdClass();
608 - $attachment->filename = $filepath;
609 - $attachment->size = filesize(ACYM_ROOT.$filepath);
648 + $attachment = [
649 + 'filename' => $filepath,
650 + 'size' => filesize(ACYM_ROOT.$filepath),
651 + ];
610 652
611 - if (preg_match('#\.(php.?|.?htm.?|pl|py|jsp|asp|sh|cgi)#Ui', $attachment->filename)) {
653 + //We will never allow some files to be uploaded...
654 + if (acym_isForbiddenFileExtension($attachment['filename'])) {
612 655 acym_enqueueMessage(
613 656 acym_translationSprintf(
614 657 'ACYM_ACCEPTED_TYPE',
615 - substr($attachment->filename, strrpos($attachment->filename, '.') + 1),
658 + esc_html(substr($attachment['filename'], strrpos($attachment['filename'], '.') + 1)),
616 659 $this->config->get('allowed_files')
617 660 ),
618 661 'notice'
619 662 );
@@ -619,13 +662,14 @@
619 662 );
620 663 continue;
621 664 }
622 665
623 - if (in_array((array)$attachment, $mail->attachments)) continue;
666 + if (in_array($attachment, $mail->attachments)) continue;
624 667
625 668 $newAttachments[] = $attachment;
626 669 }
627 - if (!empty($mail->attachments) && is_array($mail->attachments)) {
670 + // Add to previous attachments
671 + if (!empty($mail->attachments)) {
628 672 $newAttachments = array_merge($mail->attachments, $newAttachments);
629 673 }
630 674 $mail->attachments = $newAttachments;
631 675 }
@@ -631,22 +675,18 @@
631 675 }
632 676
633 677 if (empty($mail->attachments)) {
634 678 unset($mail->attachments);
635 - }
636 -
637 - if (!empty($mail->attachments) && !is_string($mail->attachments)) {
679 + } else {
638 680 $mail->attachments = json_encode($mail->attachments);
639 681 }
640 682 }
641 683
642 - protected function setThumbnailFrom($fromId)
684 + private function setThumbnailFrom(int $fromId): string
643 685 {
644 686 $thumbNb = $this->config->get('numberThumbnail', 2);
645 687 $fileName = 'thumbnail_'.($thumbNb + 1).'.png';
646 - $newConfig = new \stdClass();
647 - $newConfig->numberThumbnail = $thumbNb + 1;
648 - $this->config->save($newConfig);
688 + $this->config->saveConfig(['numberThumbnail' => $thumbNb + 1]);
649 689
650 690 $mailClass = new MailClass();
651 691 $fromMail = $mailClass->getOneById($fromId);
652 692 $fromThumbnail = $fromMail->thumbnail;
@@ -651,12 +691,16 @@
651 691 $fromMail = $mailClass->getOneById($fromId);
652 692 $fromThumbnail = $fromMail->thumbnail;
653 693
654 694 $ret = acym_createFolder(ACYM_UPLOAD_FOLDER_THUMBNAIL);
655 - if (!$ret) return '';
695 + if (!$ret) {
696 + return '';
697 + }
656 698
657 699 $fromThumbnailSource = acym_fileGetContent(acym_getMailThumbnail($fromThumbnail));
658 - if (empty($fromThumbnailSource)) return '';
700 + if (empty($fromThumbnailSource)) {
701 + return '';
702 + }
659 703
660 704 file_put_contents(ACYM_UPLOAD_FOLDER_THUMBNAIL.$fileName, $fromThumbnailSource);
661 705
662 706 return $fileName;
@@ -661,9 +705,9 @@
661 705
662 706 return $fileName;
663 707 }
664 708
665 - public function apply()
709 + public function apply(): void
666 710 {
667 711 $mailId = $this->store();
668 712 acym_setVar('id', $mailId);
669 713 $this->edit();
@@ -668,13 +712,19 @@
668 712 acym_setVar('id', $mailId);
669 713 $this->edit();
670 714 }
671 715
672 - public function save()
716 + public function save(): void
673 717 {
674 718 $mailId = $this->store();
675 719
676 - $return = str_replace('{mailid}', empty($mailId) ? '' : $mailId, acym_getVar('string', 'return', ''));
720 + // When saving notifications, we return to page where we clicked the "Edit email" button
721 + $return = str_replace(
722 + '{mailid}',
723 + empty($mailId) ? '' : $mailId,
724 + acym_getVar('string', 'return', '')
725 + );
726 +
677 727 if (empty($return)) {
678 728 $this->listing();
679 729 } else {
680 730 acym_redirect($return);
@@ -680,29 +730,29 @@
680 730 acym_redirect($return);
681 731 }
682 732 }
683 733
684 - public function autoSave()
734 + public function autoSave(): void
685 735 {
736 + wp_verify_nonce(acym_getVar('cmd', '_wpnonce'), 'acymnonce') || die('Invalid Token');
737 +
686 738 $mailClass = new MailClass();
687 739 $mail = new \stdClass();
688 740
689 741 $language = acym_getVar('string', 'language', 'main');
690 742 $mail->id = acym_getVar('int', 'mailId', 0);
691 - $mail->autosave = acym_getVar('string', 'autoSave', '', 'REQUEST', ACYM_ALLOWRAW);
743 + $mail->autosave = base64_decode(acym_getVar('string', 'autoSave', '', 'REQUEST', ACYM_ALLOWRAW));
692 744
693 - if (empty($mail->id) || !$mailClass->hasUserAccess($mail->id) || !$mailClass->autoSave($mail, $language)) {
694 - echo 'error';
745 + if (empty($mail->id) || !$mailClass->hasUserAccess($mail->id, true) || !$mailClass->autoSave($mail, $language)) {
746 + acym_sendAjaxResponse('', [], false);
695 747 } else {
696 - echo 'saved';
748 + acym_sendAjaxResponse();
697 749 }
698 -
699 - exit;
700 750 }
701 751
702 - public function ajaxCheckVideoUrl()
752 + public function ajaxCheckVideoUrl(): void
703 753 {
704 - acym_checkToken();
754 + wp_verify_nonce(acym_getVar('cmd', '_wpnonce'), 'acymnonce') || die('Invalid Token');
705 755 $videoUrl = acym_getVar('string', 'url', '');
706 756
707 757 if (!acym_isValidUrl($videoUrl)) {
708 758 acym_sendAjaxResponse('', [], false);
@@ -739,9 +789,9 @@
739 789
740 790 acym_sendAjaxResponse('', ['new_image_name' => $this->saveVideoPreview($image, urlencode($imageName).'.jpg')]);
741 791 }
742 792
743 - public function saveVideoPreview($image, $fileName): string
793 + private function saveVideoPreview(string $image, string $fileName): string
744 794 {
745 795 if (!$this->config->get('add_play_button_video', 1)) {
746 796 return $image;
747 797 }
@@ -758,11 +808,12 @@
758 808
759 809 $left = round(($imageWidth - $logoWidth) / 2);
760 810 $top = round(($imageHeight - $logoHeight) / 2);
761 811 imagecopy($imageVideo, $playButton, $left, $top, 0, 0, $logoWidth, $logoHeight);
762 - imagepng($imageVideo, 'tmp.jpg', 9);
763 -
764 - $input = imagecreatefrompng('tmp.jpg');
812 + $tmpFilePath = ACYM_TMP_FOLDER.'tmp.jpg';
813 + acym_createFolder(ACYM_TMP_FOLDER);
814 + imagepng($imageVideo, $tmpFilePath, 9);
815 + $input = imagecreatefrompng($tmpFilePath);
765 816 $output = imagecreatetruecolor($imageWidth, $imageHeight);
766 817 $white = imagecolorallocate($output, 255, 255, 255);
767 818
768 819 imagefilledrectangle($output, 0, 0, $imageWidth, $imageHeight, $white);
@@ -771,17 +822,22 @@
771 822 ob_start();
772 823 $status = imagejpeg($output, null, 95);
773 824 $imageContent = ob_get_clean();
774 825 if ($status && acym_writeFile(ACYM_ROOT.ACYM_UPLOAD_FOLDER.$fileName, $imageContent)) {
826 + acym_deleteFile($tmpFilePath);
827 +
775 828 return ACYM_UPLOADS_URL.$fileName;
776 829 }
777 830
831 + acym_deleteFile($tmpFilePath);
832 +
778 833 return '';
779 834 }
780 835
781 - public function getTemplateAjax()
836 + public function getTemplateAjax(): void
782 837 {
783 - acym_checkToken();
838 + wp_verify_nonce(acym_getVar('cmd', '_wpnonce'), 'acymnonce') || die('Invalid Token');
839 +
784 840 $pagination = new PaginationHelper();
785 841 $id = acym_getVar('int', 'id');
786 842 $id = empty($id) ? '' : '&id='.$id;
787 843 $searchFilter = acym_getVar('string', 'search', '');
@@ -795,9 +851,11 @@
795 851 $fromMultilingual = acym_getVar('int', 'is_multilingual_edition', 0);
796 852
797 853 $mailsPerPage = $pagination->getListLimit();
798 854 $page = acym_getVar('int', 'pagination_page_ajax', 1);
799 - $page != 'undefined' ? : $page = '1';
855 + if ($page === 'undefined') {
856 + $page = 1;
857 + }
800 858
801 859 $mailClass = new MailClass();
802 860 $matchingMails = $mailClass->getMatchingElements(
803 861 [
@@ -825,9 +883,9 @@
825 883 if (in_array($type, [MailClass::TYPE_WELCOME, MailClass::TYPE_UNSUBSCRIBE])) {
826 884 $listId = acym_getVar('int', 'list_id', 0);
827 885 }
828 886 foreach ($matchingMails['elements'] as $oneTemplate) {
829 - $return .= '<div class="cell grid-x acym__templates__oneTpl acym__listing__block" id="'.acym_escape($oneTemplate->id).'">
887 + $return .= '<div class="cell grid-x acym__templates__oneTpl acym__listing__block" id="'.esc_attr($oneTemplate->id).'">
830 888 <div class="cell acym__templates__pic text-center">';
831 889
832 890 $url = acym_getVar('cmd', 'ctrl').'&task=edit&step=editEmail&from='.intval($oneTemplate->id).$returnUrl.'&type='.$type.$id.'&'.acym_getFormToken();
833 891 if (!empty($followup_id)) {
@@ -839,20 +897,20 @@
839 897 if (!empty($this->data['campaignInformation'])) {
840 898 $url .= '&id='.intval($this->data['campaignInformation']);
841 899 }
842 900 if (!$automation || !empty($returnUrl)) {
843 - $return .= '<a href="'.acym_completeLink($url, false, false, true).'">';
901 + $return .= '<a href="'.esc_url(acym_completeLink($url, false, false, true)).'">';
844 902 }
845 903
846 - $return .= '<img src="'.acym_escape(acym_getMailThumbnail($oneTemplate->thumbnail)).'" alt="template thumbnail"/>';
904 + $return .= '<img src="'.esc_url(acym_getMailThumbnail($oneTemplate->thumbnail)).'" alt="template thumbnail"/>';
847 905 if (!$automation || !empty($returnUrl)) {
848 906 $return .= '</a>';
849 907 }
850 908
851 909 if ($oneTemplate->drag_editor) {
852 - $return .= '<div class="acym__templates__choose__ribbon acyeditor">'.acym_translation('ACYM_DD_EDITOR').'</div>';
910 + $return .= '<div class="acym__templates__choose__ribbon acyeditor">'.esc_html(acym_translation('ACYM_DD_EDITOR')).'</div>';
853 911 } else {
854 - $return .= '<div class="acym__templates__choose__ribbon htmleditor">'.acym_translation('ACYM_HTML_EDITOR').'</div>';
912 + $return .= '<div class="acym__templates__choose__ribbon htmleditor">'.esc_html(acym_translation('ACYM_HTML_EDITOR')).'</div>';
855 913 }
856 914
857 915 if (strlen($oneTemplate->name) > 55) {
858 916 $oneTemplate->name = substr($oneTemplate->name, 0, 50).'...';
@@ -857,32 +915,35 @@
857 915 if (strlen($oneTemplate->name) > 55) {
858 916 $oneTemplate->name = substr($oneTemplate->name, 0, 50).'...';
859 917 }
860 918 $return .= '</div>
861 - <div class="cell grid-x acym__templates__footer text-center">
862 - <div class="cell acym__templates__footer__title acym_text_ellipsis" title="'.acym_escape($oneTemplate->name).'">'.acym_escape($oneTemplate->name).'</div>
863 - <div class="cell">'.acym_date($oneTemplate->creation_date, 'ACYM_DATE_FORMAT_LC3').'</div>
864 - </div>
865 - </div>';
919 + <div class="cell grid-x acym__templates__footer text-center">
920 + <div class="cell acym__templates__footer__title acym_text_ellipsis" title="'.esc_attr($oneTemplate->name).'">';
921 + $return .= esc_html($oneTemplate->name).'</div>
922 + <div class="cell">'.esc_html(acym_date($oneTemplate->creation_date, 'ACYM_DATE_FORMAT_LC3')).'</div>
923 + </div>
924 + </div>';
866 925 }
867 926
868 927 $return .= '</div>';
869 928
870 - $pagination->setStatus($matchingMails['total'], $page, $mailsPerPage);
929 + $pagination->setStatus((int)$matchingMails['total']->total, $page, $mailsPerPage);
871 930
872 - $return .= $pagination->displayAjax();
931 + ob_start();
932 + $pagination->display('', '__ajax');
933 + $return .= ob_get_clean();
873 934
874 - echo $return;
935 + acym_sendAjaxResponse('', ['pagination' => $return]);
875 936 exit;
876 937 }
877 938
878 - public function setNewThumbnail()
939 + public function setNewThumbnail(): void
879 940 {
880 - if (!acym_isAdmin()) {
941 + if (!acym_isAdmin() || (!acym_isAllowed('mails') && !acym_isAllowed('campaigns'))) {
881 942 die('Access denied for thumbnail creation');
882 943 }
883 944
884 - acym_checkToken();
945 + wp_verify_nonce(acym_getVar('cmd', '_wpnonce'), 'acymnonce') || die('Invalid Token');
885 946 $contentThumbnail = acym_getVar('string', 'content', '');
886 947 if (strpos($contentThumbnail, 'data:image/png') !== 0) {
887 948 acym_sendAjaxResponse('This file is not allowed.', [], false);
888 949 }
@@ -898,11 +959,9 @@
898 959
899 960 if (empty($file) || strpos($file, 'http') === 0) {
900 961 $thumbNb = $this->config->get('numberThumbnail', 2);
901 962 $file = 'thumbnail_'.($thumbNb + 1).'.png';
902 - $newConfig = new \stdClass();
903 - $newConfig->numberThumbnail = $thumbNb + 1;
904 - $this->config->save($newConfig);
963 + $this->config->saveConfig(['numberThumbnail' => $thumbNb + 1]);
905 964 }
906 965
907 966 $extension = acym_fileGetExt($file);
908 967 if (strpos($file, 'thumbnail_') === false || !in_array($extension, ['png', 'jpeg', 'jpg', 'gif', 'webp'])) {
@@ -914,11 +973,11 @@
914 973
915 974 acym_sendAjaxResponse('', ['fileName' => $file]);
916 975 }
917 976
918 - public function setNewIconShare()
977 + public function setNewIconShare(): void
919 978 {
920 - acym_checkToken();
979 + wp_verify_nonce(acym_getVar('cmd', '_wpnonce'), 'acymnonce') || die('Invalid Token');
921 980 $socialName = acym_getVar('string', 'social', '');
922 981 $socialMedias = acym_getSocialMedias();
923 982 if (!in_array($socialName, $socialMedias)) {
924 983 acym_sendAjaxResponse(acym_translationSprintf('ACYM_UNKNOWN_SOCIAL', $socialName), [], false);
@@ -923,17 +982,21 @@
923 982 if (!in_array($socialName, $socialMedias)) {
924 983 acym_sendAjaxResponse(acym_translationSprintf('ACYM_UNKNOWN_SOCIAL', $socialName), [], false);
925 984 }
926 985
927 - $extension = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
986 + $file = acym_getVar('array', 'file', [], 'FILES');
987 + $extension = pathinfo($file['name'], PATHINFO_EXTENSION);
928 988 $newPath = ACYM_UPLOAD_FOLDER.'socials'.DS.$socialName;
929 989 $newPathComplete = $newPath.'.'.$extension;
930 990
931 - $allowedExtensions = acym_getImageFileExtensions();
991 + $allowedExtensions = acym_getImageFileExtensions(true);
932 992 if (!in_array($extension, $allowedExtensions)) {
933 - $errorMessage = acym_translationSprintf('ACYM_ACCEPTED_TYPE', $extension, implode(', ', $allowedExtensions));
934 - } elseif (!acym_uploadFile($_FILES['file']['tmp_name'], ACYM_ROOT.$newPathComplete)) {
993 + $errorMessage = acym_translationSprintf('ACYM_ACCEPTED_TYPE', esc_html($extension), implode(', ', $allowedExtensions));
994 + } elseif (!acym_uploadFile($file['tmp_name'], ACYM_ROOT.$newPathComplete)) {
935 995 $errorMessage = acym_translationSprintf('ACYM_ERROR_UPLOADING_FILE_X', $newPathComplete);
996 + } elseif (strtolower($extension) === 'svg' && !acym_isSvgFileSafe(ACYM_ROOT.$newPathComplete)) {
997 + acym_deleteFile(ACYM_ROOT.$newPathComplete);
998 + $errorMessage = acym_translationSprintf('ACYM_ERROR_UPLOADING_FILE_X', $newPathComplete);
936 999 }
937 1000
938 1001 if (!empty($errorMessage)) {
939 1002 acym_sendAjaxResponse($errorMessage, [], false);
@@ -938,17 +1001,14 @@
938 1001 if (!empty($errorMessage)) {
939 1002 acym_sendAjaxResponse($errorMessage, [], false);
940 1003 }
941 1004
942 - $newConfig = new \stdClass();
943 - $newConfig->social_icons = json_decode($this->config->get('social_icons', '{}'), true);
944 -
945 1005 $newImg = acym_rootURI().$newPathComplete;
946 1006 $newImgWithoutExtension = acym_rootURI().$newPath;
947 1007
948 - $newConfig->social_icons[$socialName] = $newImg;
949 - $newConfig->social_icons = json_encode($newConfig->social_icons);
950 - $this->config->save($newConfig);
1008 + $socialIcons = json_decode($this->config->get('social_icons', '{}'), true);
1009 + $socialIcons[$socialName] = $newImg;
1010 + $this->config->saveConfig(['social_icons' => json_encode($socialIcons)]);
951 1011
952 1012 acym_sendAjaxResponse(
953 1013 acym_translation('ACYM_ICON_IMPORTED'),
954 1014 [
@@ -957,19 +1017,20 @@
957 1017 ]
958 1018 );
959 1019 }
960 1020
961 - public function saveAjax()
1021 + public function saveAjax(): void
962 1022 {
963 - $result = $this->store(true);
964 - if ($result) {
965 - acym_sendAjaxResponse('', ['result' => $result]);
1023 + $mailId = $this->store(true);
1024 +
1025 + if (!empty($mailId)) {
1026 + acym_sendAjaxResponse('', ['result' => $mailId]);
966 1027 } else {
967 1028 acym_sendAjaxResponse(acym_translation('ACYM_ERROR_SAVING'), [], false);
968 1029 }
969 1030 }
970 1031
971 - public function loadCSS()
1032 + public function loadCSS(): void
972 1033 {
973 1034 header('Content-Type: text/css');
974 1035 $idMail = acym_getVar('int', 'id', 0);
975 1036 if (empty($idMail)) {
@@ -978,13 +1039,21 @@
978 1039
979 1040 $mailClass = new MailClass();
980 1041 $mail = $mailClass->getOneById($idMail);
981 1042
1043 + if (empty($mail)) {
1044 + exit;
1045 + }
1046 +
1047 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Returning content as text/css, need to output raw content.
982 1048 echo $mailClass->buildCSS($mail->stylesheet);
983 1049 exit;
984 1050 }
985 1051
986 - public function test()
1052 + /*
1053 + * Method used to send a test when editing a notification email
1054 + */
1055 + public function test(): void
987 1056 {
988 1057 $mailId = $this->store();
989 1058 $return = acym_getVar('string', 'return', '');
990 1059 acym_setVar('return', $return);
@@ -1008,22 +1077,29 @@
1008 1077 $options = ['isTest' => true];
1009 1078 if ($mailerHelper->sendOne($mailId, $currentEmail, $options)) {
1010 1079 acym_enqueueMessage(acym_translationSprintf('ACYM_SEND_SUCCESS', $mail->name, $currentEmail), 'info');
1011 1080 } else {
1012 - acym_enqueueMessage(acym_translationSprintf('ACYM_SEND_ERROR', $mail->name, $currentEmail), 'error');
1081 + $notification = [
1082 + 'name' => 'send_error',
1083 + 'removable' => 1,
1084 + ];
1085 + acym_enqueueMessage(acym_translationSprintf('ACYM_SEND_ERROR', $mail->name, $currentEmail), 'error', true, [$notification]);
1013 1086 }
1014 1087
1015 1088 $this->edit();
1016 1089 }
1017 1090
1018 - public function sendTest()
1091 + public function sendTest(): void
1019 1092 {
1020 - acym_checkToken();
1093 + wp_verify_nonce(acym_getVar('cmd', '_wpnonce'), 'acymnonce') || die('Invalid Token');
1021 1094 $controller = acym_getVar('string', 'controller', 'mails');
1022 1095 $level = 'info';
1023 1096
1024 1097 $testNote = acym_getVar('string', 'test_note', '');
1025 1098 $mailClass = new MailClass();
1099 + $mailerHelper = new MailerHelper();
1100 + $mailerHelper->autoAddUser = true;
1101 + $mailerHelper->report = false;
1026 1102
1027 1103 if (in_array($controller, ['mails', 'frontmails'])) {
1028 1104 $mailId = acym_getVar('int', 'id', 0);
1029 1105 } else {
@@ -1037,13 +1113,24 @@
1037 1113 die('A test of this campaign cannot be sent');
1038 1114 }
1039 1115
1040 1116 $mailId = $campaign->mail_id;
1117 + $mailerHelper->isAbTest = $campaignClass->isAbTestMail($mailId);
1041 1118
1042 - $languageVersion = acym_getVar('string', 'lang_version', 'main');
1043 - if (!empty($languageVersion) && $languageVersion !== 'main') {
1044 - $translationId = $mailClass->getTranslationId($mailId, $languageVersion);
1045 - if (!empty($translationId)) $mailId = $translationId;
1119 + $campaignVersion = acym_getVar('string', 'lang_version', 'main');
1120 + if (!empty($campaignVersion) && $campaignVersion !== 'main') {
1121 + if ($campaignVersion === 'B') {
1122 + $versions = $mailClass->getVersionsById($mailId);
1123 + if (!empty($versions)) {
1124 + $mailIds = array_keys($versions);
1125 + $mailId = array_pop($mailIds);
1126 + }
1127 + } else {
1128 + $translationId = $mailClass->getTranslationId($mailId, $campaignVersion);
1129 + if (!empty($translationId)) {
1130 + $mailId = $translationId;
1131 + }
1132 + }
1046 1133 }
1047 1134 }
1048 1135
1049 1136 $mail = $mailClass->getOneById($mailId);
@@ -1051,13 +1138,8 @@
1051 1138 if (empty($mail) || !$mailClass->hasUserAccess($mailId)) {
1052 1139 acym_sendAjaxResponse('', ['level' => 'error', 'message' => acym_translation('ACYM_EMAIL_NOT_FOUND')], false);
1053 1140 }
1054 1141
1055 - $mailerHelper = new MailerHelper();
1056 - $mailerHelper->autoAddUser = true;
1057 - $mailerHelper->report = false;
1058 -
1059 -
1060 1142 $report = [];
1061 1143
1062 1144 $testEmails = explode(',', acym_getVar('string', 'test_emails'));
1063 1145 $options = [
@@ -1076,40 +1158,37 @@
1076 1158
1077 1159 acym_sendAjaxResponse('', ['level' => $level, 'message' => implode('<br/>', $report)], $level !== 'error');
1078 1160 }
1079 1161
1080 - public function getMailContent()
1162 + public function getMailContent(): void
1081 1163 {
1082 - $mailClass = new MailClass();
1083 - $from = acym_getVar('string', 'from', '');
1164 + $from = acym_getVar('int', 'from', 0);
1084 1165
1085 1166 if (empty($from)) {
1086 - echo 'error';
1087 - exit;
1167 + acym_sendAjaxResponse(acym_translation('ACYM_EMAIL_NOT_FOUND'), [], false);
1088 1168 }
1089 1169
1090 - $echo = $mailClass->getOneById($from);
1170 + $mailClass = new MailClass();
1171 + $mail = $mailClass->getOneById($from);
1091 1172
1092 - if ($echo->drag_editor == 0) {
1093 - echo 'no_new_editor';
1094 - exit;
1173 + if (empty($mail)) {
1174 + acym_sendAjaxResponse(acym_translation('ACYM_EMAIL_NOT_FOUND'), [], false);
1095 1175 }
1096 1176
1097 - $echo = ['mailSettings' => $echo->settings, 'content' => $echo->body, 'stylesheet' => $echo->stylesheet];
1177 + if ($mail->drag_editor == 0) {
1178 + acym_sendAjaxResponse('Only available for the drag and drop editor.', [], false);
1179 + }
1098 1180
1099 - $echo = json_encode($echo);
1100 -
1101 - echo $echo;
1102 - exit;
1181 + acym_sendAjaxResponse();
1103 1182 }
1104 1183
1105 - protected function setFrontEndParamsForTemplateChoose()
1184 + protected function setFrontEndParamsForTemplateChoose(): int
1106 1185 {
1107 - return '';
1186 + return 0;
1108 1187 }
1109 1188
1110 - public function saveAsTmplAjax()
1189 + public function saveAsTmplAjax(): void
1111 1190 {
1112 - $isWellSaved = $this->store(true);
1113 - acym_sendAjaxResponse($isWellSaved ? '' : acym_translation('ACYM_ERROR_SAVING'), ['result' => $isWellSaved], $isWellSaved);
1191 + $mailId = $this->store(true);
1192 + acym_sendAjaxResponse(!empty($mailId) ? '' : acym_translation('ACYM_ERROR_SAVING'), ['result' => $mailId], !empty($mailId));
1114 1193 }
1115 1194 }