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 / Core / AcymPlugin.php

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

1,575 lines 59.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace AcyMailing\Core;
4
5 use AcyMailing\Classes\CampaignClass;
6 use AcyMailing\Classes\PluginClass;
7 use AcyMailing\Helpers\PluginHelper;
8 use Joomla\CMS\HTML\HTMLHelper;
9
10 class AcymPlugin extends AcymObject
11 {
12 public string $cms = 'all';
13 public string $name = '';
14 public bool $installed = true;
15
16 protected array $addonDefinition;
17 protected PluginHelper $pluginHelper;
18
19 protected int $rootCategoryId = 1;
20 protected array $categories;
21 protected array $catvalues = [];
22 private array $cats = [];
23 private array $subCategories = [];
24
25 protected array $tagvalues = [];
26
27 protected array $tags = [];
28 protected object $pageInfo;
29 protected array $searchFields = [];
30 protected string $querySelect = '';
31 protected string $query = '';
32 protected array $filters = [];
33 protected string $elementIdTable = '';
34 protected string $elementIdColumn = '';
35
36 public object $pluginDescription;
37 public object $generateCampaignResult;
38
39 protected ?object $defaultValues;
40 protected string $emailLanguage = '';
41 private int $campaignId;
42 private string $campaignType;
43
44 protected array $displayOptions = [];
45 protected array $replaceOptions = [];
46 protected array $elementOptions = [];
47 protected array $customOptions = [];
48
49 private array $sendingPlugins = [
50 'wp_mail_smtp' => 'WP Mail SMTP',
51 ];
52
53 public array $errors = [];
54 public string $logFilename = '';
55 protected int $responseCode;
56
57 private $active;
58 public $settings;
59 private array $savedSettings = [];
60
61 public function __construct()
62 {
63 parent::__construct();
64
65 $this->elementOptions = ['wrappedText' => [acym_translation('ACYM_WRAPPED_TEXT')]];
66
67 $this->pluginHelper = new PluginHelper();
68 $this->pageInfo = new \stdClass();
69
70 $this->pluginDescription = new \stdClass();
71 $this->pluginDescription->plugin = get_class($this);
72
73 $this->name = strtolower(substr($this->pluginDescription->plugin, 7));
74
75 $this->generateCampaignResult = new \stdClass();
76 $this->generateCampaignResult->status = true;
77 $this->generateCampaignResult->message = '';
78
79 $this->campaignId = acym_getVar('int', 'campaignId', 0);
80 $this->campaignType = acym_getVar('string', 'campaign_type', '');
81
82 $pluginClass = new PluginClass();
83 $currentAddon = $pluginClass->getOnePluginByFolderName($this->name);
84 $this->active = empty($currentAddon) || $currentAddon->active;
85
86 if (!empty($currentAddon->settings)) {
87 if (is_string($currentAddon->settings)) {
88 $this->savedSettings = json_decode($currentAddon->settings, true);
89 } else {
90 $this->savedSettings = $currentAddon->settings;
91 }
92 }
93
94 $this->logFilename = acym_getErrorLogFilename(empty($this->name) ? get_class($this) : $this->name);
95 }
96
97 protected function displaySelectionZone($zoneContent)
98 {
99 $output = '<p class="acym__wysid__right__toolbar__p acym__wysid__right__toolbar__p__open acym__title">';
100 $output .= acym_translation('ACYM_CONTENT_TO_INSERT').'<i class="acymicon-keyboard-arrow-up"></i>';
101 $output .= '</p>';
102 $output .= '<div class="acym__wysid__right__toolbar__design--show acym__wysid__right__toolbar__design acym__wysid__context__modal__container">';
103 $output .= $zoneContent;
104 $output .= '</div>';
105
106 return $output;
107 }
108
109 public function displayListing()
110 {
111 echo $this->prepareListing();
112 }
113
114 public function prepareListing()
115 {
116 $this->pageInfo->limit = 10;
117 $this->pageInfo->page = acym_getVar('int', 'pagination_page_ajax', 1);
118 $this->pageInfo->start = ($this->pageInfo->page - 1) * $this->pageInfo->limit;
119 $this->pageInfo->search = acym_getVar('string', 'plugin_search', '');
120 $this->pageInfo->filter_cat = acym_getVar('int', 'plugin_category', 0);
121 $this->pageInfo->orderdir = 'DESC';
122 $this->pageInfo->loadMore = acym_getVar('boolean', 'loadMore', false);
123
124 if (!empty($this->pageInfo->search) && !empty($this->searchFields)) {
125 $searchVal = '%'.acym_getEscaped($this->pageInfo->search, true).'%';
126 $this->filters[] = implode(' LIKE '.acym_escapeDB($searchVal).' OR ', $this->searchFields).' LIKE '.acym_escapeDB($searchVal);
127 }
128
129 return '';
130 }
131
132 public function getElements()
133 {
134 $conditions = '';
135 if (!empty($this->filters)) {
136 $conditions = ' WHERE ('.implode(') AND (', $this->filters).')';
137 }
138
139 $ordering = '';
140 if (!empty($this->pageInfo->order)) {
141 $ordering = ' ORDER BY '.acym_secureDBColumn($this->pageInfo->order).' '.acym_secureDBColumn($this->pageInfo->orderdir);
142 }
143
144 $rows = acym_loadObjectList($this->querySelect.$this->query.$conditions.$ordering, '', $this->pageInfo->start, $this->pageInfo->limit);
145 $this->pageInfo->total = acym_loadResult('SELECT COUNT(*) '.$this->query.$conditions.$ordering);
146
147 if (!empty($this->defaultValues->id) && $this->defaultValues->defaultPluginTab === $this->name) {
148 $found = false;
149 foreach ($rows as $oneRow) {
150 if (intval($oneRow->{$this->elementIdColumn}) === intval($this->defaultValues->id)) {
151 $found = true;
152 }
153 }
154
155 if (!$found) {
156 $conditions = ' WHERE '.$this->elementIdTable.'.'.$this->elementIdColumn.' = '.intval($this->defaultValues->id);
157 $row = acym_loadObject($this->querySelect.$this->query.$conditions);
158 if (!empty($row)) {
159 $rows[] = $row;
160 }
161 }
162 }
163
164 return $rows;
165 }
166
167 protected function getFilteringZone($categoryFilter = true): string
168 {
169 $result = '<div class="grid-x" id="plugin_listing_filters">
170 <div class="cell medium-6">
171 <input type="text" name="plugin_search" placeholder="'.acym_escape(acym_translation('ACYM_SEARCH')).'"/>
172 </div>
173 <div class="cell medium-6 grid-x">
174 <div class="cell hide-for-small-only medium-auto"></div>
175 <div class="cell medium-shrink">';
176
177 if ($categoryFilter) {
178 $result .= $this->getCategoryFilter();
179 }
180
181 $result .= '</div>
182 </div>
183 </div>';
184
185 return $result;
186 }
187
188 public function prepareWPCategories($type)
189 {
190 $this->categories = acym_loadObjectList(
191 'SELECT cat.term_taxonomy_id AS id, parent.term_taxonomy_id AS parent_id, catdetails.name AS title
192 FROM `#__term_taxonomy` AS cat
193 JOIN `#__terms` AS catdetails ON cat.term_id = catdetails.term_id
194 LEFT JOIN `#__term_taxonomy` AS parent ON cat.parent = parent.term_id
195 WHERE cat.taxonomy = '.acym_escapeDB($type)
196 );
197 foreach ($this->categories as $i => $oneCat) {
198 if (empty($oneCat->parent_id)) {
199 $this->categories[$i]->parent_id = $this->rootCategoryId;
200 }
201 }
202 }
203
204 protected function getCategoryFilter()
205 {
206 $filter_cat = acym_getVar('int', 'plugin_category', 0);
207 $this->catvalues = [];
208 $this->catvalues[] = acym_selectOption(0, 'ACYM_ALL');
209
210 $this->cats = [];
211 $this->subCategories = [];
212 if (!empty($this->categories)) {
213 foreach ($this->categories as $oneCat) {
214 $this->cats[$oneCat->parent_id][] = $oneCat;
215 }
216 $this->handleChildrenCategories($this->rootCategoryId);
217 foreach ($this->categories as $oneCat) {
218 $this->subCategories[$oneCat->id] = $this->getSubCats($oneCat->id);
219 }
220 }
221
222 return acym_select(
223 $this->catvalues,
224 'plugin_category',
225 intval($filter_cat),
226 ['class' => 'plugin_category_select']
227 );
228 }
229
230 private function getSubCats($categoryId)
231 {
232 $result = [$categoryId];
233 if (empty($this->cats[$categoryId])) return $result;
234
235 foreach ($this->cats[$categoryId] as $oneSubCategory) {
236 $result = array_merge($result, $this->getSubCats($oneSubCategory->id));
237 }
238
239 return $result;
240 }
241
242 protected function handleChildrenCategories($parent_id, $level = 0)
243 {
244 if (empty($this->cats[$parent_id])) return;
245
246 foreach ($this->cats[$parent_id] as $cat) {
247 $this->catvalues[] = acym_selectOption($cat->id, str_repeat(' - - ', $level).$cat->title);
248 $this->handleChildrenCategories($cat->id, $level + 1);
249 }
250 }
251
252 protected function getSubCategories($categoryId)
253 {
254 $this->getCategoryFilter();
255
256 return $this->subCategories[$categoryId];
257 }
258
259 protected function autoContentOptions(&$options, $type = null)
260 {
261 if ($type === 'event') {
262 $options[] = [
263 'title' => 'ACYM_FROM',
264 'type' => 'date',
265 'name' => 'from',
266 'default' => time(),
267 'relativeDate' => '+',
268 ];
269
270 $options[] = [
271 'title' => 'ACYM_TO',
272 'type' => 'date',
273 'name' => 'to',
274 'default' => '',
275 'relativeDate' => '+',
276 ];
277 } elseif ($type !== 'simple') {
278 $options[] = [
279 'title' => 'ACYM_MIN_PUBLISH_DATE',
280 'tooltip' => 'ACYM_MIN_PUBLISH_DATE_DESC',
281 'type' => 'date',
282 'name' => 'min_publish',
283 'default' => '',
284 'relativeDate' => '-',
285 ];
286 }
287
288 $options[] = [
289 'title' => 'ACYM_COLUMNS',
290 'type' => 'number',
291 'name' => 'cols',
292 'default' => 1,
293 ];
294
295 $options[] = [
296 'title' => 'ACYM_COLUMN_HORIZONTAL_PADDING',
297 'type' => 'number',
298 'name' => 'hpadding',
299 'default' => 10,
300 ];
301
302 $options[] = [
303 'title' => 'ACYM_COLUMN_VERTICAL_PADDING',
304 'type' => 'number',
305 'name' => 'vpadding',
306 'default' => 10,
307 ];
308
309 $options[] = [
310 'title' => 'ACYM_MAX_NB_ELEMENTS',
311 'type' => 'number',
312 'name' => 'max',
313 'default' => 20,
314 ];
315 }
316
317 protected function autoCampaignOptions(&$options, $modified = false)
318 {
319 if (empty($this->campaignId) && empty($this->campaignType)) {
320 return;
321 } elseif (!empty($this->campaignId) && (empty($this->campaignType) || $this->campaignType !== 'auto')) {
322 $campaignClass = new CampaignClass();
323 $campaign = $campaignClass->getOneById($this->campaignId);
324 if ($campaign->sending_type !== 'auto') return;
325 } elseif (empty($this->campaignId) && !empty($this->campaignType) && $this->campaignType !== 'auto') {
326 return;
327 }
328
329 $options[] = [
330 'title' => 'ACYM_DOCUMENTATION',
331 'type' => 'custom',
332 'name' => 'documentation',
333 'output' => '<a target="_blank" href="'.ACYM_DOCUMENTATION.'main-pages/campaigns/automatic-campaigns#dont-send-twice-the-same-content"><i class="acymicon-book"></i></a>',
334 'js' => '',
335 'section' => 'ACYM_AUTO_CAMPAIGNS_OPTIONS',
336 ];
337
338 if ($modified) {
339 $options[] = [
340 'title' => 'ACYM_DATE',
341 'type' => 'select',
342 'name' => 'datefilter',
343 'default' => 'onlynew',
344 'tooltip' => 'ACYM_ONLY_NEWLY_CREATED_DESC',
345 'options' => [
346 '' => 'ACYM_NO_FILTER',
347 'onlynew' => 'ACYM_ONLY_NEWLY_CREATED',
348 'onlymodified' => 'ACYM_ONLY_NEWLY_MODIFIED',
349 ],
350 'section' => 'ACYM_AUTO_CAMPAIGNS_OPTIONS',
351 ];
352 } else {
353 $options[] = [
354 'title' => 'ACYM_ONLY_NEWLY_CREATED',
355 'type' => 'boolean',
356 'name' => 'onlynew',
357 'default' => true,
358 'tooltip' => 'ACYM_ONLY_NEWLY_CREATED_DESC',
359 'section' => 'ACYM_AUTO_CAMPAIGNS_OPTIONS',
360 ];
361 }
362
363 $options[] = [
364 'title' => 'ACYM_MIN_NB_ELEMENTS',
365 'type' => 'number',
366 'name' => 'min',
367 'default' => 0,
368 'tooltip' => 'ACYM_MIN_NB_ELEMENTS_DESC',
369 'section' => 'ACYM_AUTO_CAMPAIGNS_OPTIONS',
370 ];
371 }
372
373 protected function getElementsListing($options): string
374 {
375 if ($this->pageInfo->loadMore) {
376 return $this->getInnerListing($options);
377 }
378 $listing = '<div id="plugin_listing" class="acym__popup__listing">';
379 $listing .= '<input type="hidden" name="plugin" value="'.acym_escape(get_class($this)).'" />';
380
381 $listing .= '<div class="cell grid-x hide-for-small-only plugin_listing_headers">';
382 foreach ($options['header'] as $oneColumn) {
383 $class = empty($oneColumn['class']) ? '' : ' '.$oneColumn['class'];
384 $listing .= '<div class="cell plugin_listing_headers__title medium-'.$oneColumn['size'].$class.'">'.acym_translation($oneColumn['label']).'</div>';
385 }
386 $listing .= '</div>';
387
388 $listing .= $this->getInnerListing($options);
389
390 $listing .= '<input type="hidden" value="1" id="acym_pagination__ajax__load-more" name="acym_pagination__ajax__load-more">';
391 $listing .= '</div>';
392
393 return $listing;
394 }
395
396 private function getInnerListing($options): string
397 {
398 if (empty($options['rows']) && $this->pageInfo->loadMore) {
399 $listing = '<h3 class="cell acym__listing__empty__load-more text-center">'.acym_translation('ACYM_NO_MORE_RESULTS').'</h3>';
400 } elseif (empty($options['rows'])) {
401 $listing = '<h1 class="cell acym__listing__empty__search__modal text-center">'.acym_translation('ACYM_NO_RESULTS_FOUND').'</h1>';
402 } else {
403 $selected = explode(',', acym_getVar('string', 'selected', ''));
404 if (!empty($this->defaultValues->id)) {
405 $selected = [$this->defaultValues->id];
406 }
407
408 $listing = '';
409 foreach ($options['rows'] as $row) {
410 $class = 'cell grid-x acym__row__no-listing acym__listing__row__popup';
411 if (in_array($row->{$options['id']}, $selected)) {
412 $class .= ' selected_row';
413 }
414
415 $listing .= '<div
416 class="'.$class.'"
417 data-id="'.acym_escape($row->{$options['id']}).'"
418 onclick="applyContent'.acym_escape($this->name).'(\''.acym_escape($row->{$options['id']}).'\', this);">';
419
420 foreach ($options['header'] as $column => $oneColumn) {
421 $value = $row->$column;
422
423 if (!empty($oneColumn['type'])) {
424 if ($oneColumn['type'] === 'date') {
425 if (empty($value)) {
426 $value = '-';
427 } else {
428 if (!is_numeric($value) && $value != '0000-00-00 00:00:00') {
429 $value = strtotime($value);
430 }
431 $tooltip = acym_date($value, acym_translation('ACYM_DATE_FORMAT_LC2'));
432 $value = acym_tooltip(
433 [
434 'hoveredText' => acym_date($value, acym_translation('ACYM_DATE_FORMAT_LC5')),
435 'textShownInTooltip' => $tooltip,
436 ]
437 );
438 }
439 } elseif ($oneColumn['type'] === 'int') {
440 $value = intval($value);
441 }
442 }
443
444 $class = empty($oneColumn['class']) ? '' : ' '.$oneColumn['class'];
445 $listing .= '<div class="cell medium-'.$oneColumn['size'].$class.'">'.$value.'</div>';
446 }
447
448 $listing .= '</div>';
449 }
450 }
451
452 return $listing;
453 }
454
455 protected function getCategoryListing(): string
456 {
457 $listing = '';
458 if (empty($this->catvalues)) {
459 $listing .= '<h1 class="cell acym__listing__empty__search__modal text-center">'.acym_translation('ACYM_NO_RESULTS_FOUND').'</h1>';
460
461 return $listing;
462 }
463
464 $listing .= '<div class="acym__popup__listing padding-0">';
465 $selected = [];
466 if (!empty($this->defaultValues->id) && strpos($this->defaultValues->id, '-')) {
467 $selected = explode('-', $this->defaultValues->id);
468 }
469 foreach ($this->catvalues as $oneCat) {
470 if (empty($oneCat->value)) continue;
471
472 $classes = 'cell grid-x acym__row__no-listing acym__listing__row__popup';
473 if (in_array($oneCat->value, $selected)) {
474 $classes .= ' selected_row';
475 }
476 $listing .= '<div class="'.$classes.'" data-id="'.intval($oneCat->value).'" onclick="applyContentauto'.acym_escape($this->name).'('.intval($oneCat->value).', this);">
477 <div class="cell medium-5">'.acym_escape($oneCat->text).'</div>
478 </div>';
479 }
480 $listing .= '</div>';
481
482 return $listing;
483 }
484
485 protected function getTagListing(): string
486 {
487 $listing = '';
488 if (empty($this->tagvalues)) {
489 $listing .= '<h1 class="cell acym__listing__empty__search__modal text-center">'.acym_translation('ACYM_NO_RESULTS_FOUND').'</h1>';
490
491 return $listing;
492 }
493
494 $listing .= '<div class="acym__popup__listing padding-0">';
495 $selected = [];
496 if (!empty($this->defaultValues->id) && strpos($this->defaultValues->id, '-')) {
497 $selected = explode('-', $this->defaultValues->id);
498 }
499 $termIdName = 'term_id';
500 if ('wordpress' === ACYM_CMS) {
501 $termIdName = 'term_taxonomy_id';
502 }
503 foreach ($this->tagvalues as $oneTag) {
504 if (empty($oneTag->$termIdName)) continue;
505
506 $class = 'cell grid-x acym__row__no-listing acym__listing__row__popup';
507 if (in_array($oneTag->$termIdName, $selected)) $class .= ' selected_row';
508 $listing .= '<div class="'.$class.'" data-id="'.intval($oneTag->$termIdName).'" onclick="applyContent'.acym_escape($this->name).'_tags('.intval($oneTag->$termIdName).', this);">
509 <div class="cell medium-5">'.acym_escape($oneTag->name).'</div>
510 </div>';
511 }
512 $listing .= '</div>';
513
514 return $listing;
515 }
516
517 protected function replaceMultiple(&$email)
518 {
519 $this->generateByCategory($email);
520 if (empty($this->tags)) return;
521
522 $this->pluginHelper->replaceTags($email, $this->tags, true);
523 }
524
525 protected function handleOrderBy(&$query, $parameter, $table = null)
526 {
527 if (empty($parameter->order)) return;
528
529 $ordering = explode(',', $parameter->order);
530 if ($ordering[0] === 'rand') {
531 $query .= ' ORDER BY rand()';
532 } else {
533 $table = null === $table ? '' : $table.'.';
534 $column = $ordering[0];
535
536 if (strpos($column, '.') !== false) {
537 $parts = explode('.', $column, 2);
538 $table = acym_secureDBColumn($parts[0]).'.';
539 $column = $parts[1];
540 }
541
542 $query .= ' ORDER BY '.$table.'`'.acym_secureDBColumn(trim($column)).'` '.acym_secureDBColumn(trim($ordering[1]));
543 }
544 }
545
546 protected function handleMax(&$query, $parameter)
547 {
548 if (empty($parameter->max)) $parameter->max = 20;
549 $query .= ' LIMIT '.intval($parameter->max);
550 }
551
552 protected function handleMin($elements, $parameter)
553 {
554 if (!empty($parameter->min) && count($elements) < $parameter->min) {
555 $this->generateCampaignResult->status = false;
556 $this->generateCampaignResult->message = acym_translationSprintf(
557 'ACYM_GENERATE_CAMPAIGN_NOT_ENOUGH_CONTENT',
558 $this->pluginDescription->name,
559 count($elements),
560 $parameter->min
561 );
562 }
563 }
564
565 protected function getLastGenerated($mailId)
566 {
567 $campaignClass = new CampaignClass();
568
569 return $campaignClass->getLastGenerated($mailId);
570 }
571
572 protected function finalizeCategoryFormat($query, $parameter, $table = null)
573 {
574 $this->handleOrderBy($query, $parameter, $table);
575 $this->handleMax($query, $parameter);
576
577 $elements = acym_loadResultArray($query);
578
579 return $this->formatIndividualTags($elements, $parameter);
580 }
581
582 protected function formatIndividualTags($elements, $parameter)
583 {
584 $this->handleMin($elements, $parameter);
585
586 if (empty($elements)) return '';
587
588 $elements = $this->groupByCategory($elements);
589
590 $customLayout = ACYM_CUSTOM_PLUGIN_LAYOUT.$this->name.'_auto.php';
591 if (file_exists($customLayout)) {
592 ob_start();
593 require $customLayout;
594
595 return ob_get_clean();
596 }
597
598 $arrayElements = $this->buildIndividualTags($elements, $parameter);
599
600 return $this->pluginHelper->getFormattedResult($arrayElements, $parameter);
601 }
602
603 protected function buildIndividualTags($elements, $parameter): array
604 {
605 $arrayElements = [];
606 unset($parameter->id);
607
608 $i = 0;
609 foreach ($elements as $oneElementId) {
610 $args = [];
611 $args[] = $this->name.':'.$oneElementId;
612
613 foreach ($parameter as $oneParam => $val) {
614 if (is_bool($val)) {
615 $args[] = $oneParam;
616 } else {
617 $args[] = $oneParam.':'.$val;
618 }
619 }
620
621 if ($i % 2 === 1 && !empty($parameter->alternate)) {
622 $args[] = 'invert';
623 }
624
625 $arrayElements[] = '{'.implode('| ', $args).'}';
626
627 $i++;
628 }
629
630 return $arrayElements;
631 }
632
633 protected function groupByCategory($elements)
634 {
635 return $elements;
636 }
637
638 protected function getSelectedArea($parameter)
639 {
640 $allcats = explode('-', $parameter->id);
641 $selectedArea = [];
642 foreach ($allcats as $oneCat) {
643 if (empty($oneCat)) continue;
644 $selectedArea[] = intval($oneCat);
645 }
646
647 return $selectedArea;
648 }
649
650 protected function replaceOne(&$email)
651 {
652 $tags = $this->pluginHelper->extractTags($email, $this->name);
653 if (empty($tags)) return;
654
655 $newConfiguration = [
656 'dcontent_default_'.get_class($this) => json_encode(end($tags)),
657 ];
658 $this->config->save($newConfiguration);
659
660 if (false === $this->loadLibraries($email)) return;
661 $this->emailLanguage = $email->links_language;
662 $translationTool = $this->config->get('translate_content', 'no');
663
664 $tagsReplaced = [];
665 foreach ($tags as $i => $oneTag) {
666 if (isset($tagsReplaced[$i])) continue;
667
668 if (!empty($this->emailLanguage) && $translationTool !== 'no' && acym_isMultilingual()) {
669 $oneTag->id = $this->getTranslationId($oneTag->id, $translationTool);
670 }
671 $tagsReplaced[$i] = $this->replaceIndividualContent($oneTag, $email);
672 }
673
674 $email->custom_view = file_exists(ACYM_CUSTOM_PLUGIN_LAYOUT.$this->name.'.html');
675
676 $this->pluginHelper->replaceTags($email, $tagsReplaced, true);
677 }
678
679 protected function loadLibraries($email)
680 {
681 return true;
682 }
683
684 protected function initIndividualContent(&$tag, $query)
685 {
686 $element = acym_loadObject($query);
687
688 if (empty($element)) {
689 if (acym_isAdmin()) {
690 acym_enqueueMessage(acym_translationSprintf('ACYM_CONTENT_NOT_FOUND', $tag->id), 'notice');
691 }
692
693 return false;
694 }
695
696 if (empty($tag->display)) {
697 $tag->display = [];
698 } else {
699 $tag->display = explode(',', $tag->display);
700 }
701
702 return $element;
703 }
704
705 protected function getCustomLayoutVars($element)
706 {
707 $varFields = [];
708 $varFields['{picthtml}'] = '';
709 foreach ($element as $fieldName => $oneField) {
710 if (is_object($oneField) || is_array($oneField)) {
711 $varFields['{'.$fieldName.'}'] = json_encode($oneField);
712 } else {
713 $varFields['{'.$fieldName.'}'] = $oneField;
714 }
715 }
716
717 return $varFields;
718 }
719
720 protected function finalizeElementFormat(string $htmlResult, object $insertionOptions, array $dataShortcodes): string
721 {
722 $fullCustomLayoutPath = ACYM_CUSTOM_PLUGIN_LAYOUT.$this->name.'.php';
723 if ($this->config->get('php_overrides', 0) == 1 && file_exists($fullCustomLayoutPath)) {
724 ob_start();
725 require $fullCustomLayoutPath;
726 $viewContent = ob_get_clean();
727 $htmlResult = str_replace(array_keys($dataShortcodes), $dataShortcodes, $viewContent);
728 } else {
729 $customLayoutPath = ACYM_CUSTOM_PLUGIN_LAYOUT.$this->name.'.html';
730 if (file_exists($customLayoutPath)) {
731 $dataShortcodes['{wrappedText}'] = $this->pluginHelper->wrappedText;
732 $viewContent = acym_fileGetContent($customLayoutPath);
733 $viewContentReplace = str_replace(array_keys($dataShortcodes), $dataShortcodes, $viewContent);
734 if ($viewContent !== $viewContentReplace) {
735 $htmlResult = $viewContentReplace;
736 }
737 }
738 }
739
740 return $this->pluginHelper->managePicts($insertionOptions, $htmlResult);
741 }
742
743 protected function filtersFromConditions(&$filters)
744 {
745 $newFilters = [];
746
747 $this->onAcymDeclareConditions($newFilters);
748 foreach ($newFilters as $oneType) {
749 foreach ($oneType as $oneFilterName => $oneFilter) {
750 if (!empty($oneFilter->option)) $oneFilter->option = str_replace(['acym_condition', '[conditions]'], ['acym_action', '[filters]'], $oneFilter->option);
751 $filters[$oneFilterName] = $oneFilter;
752 }
753 }
754 }
755
756 protected function getElementTags($type, $id)
757 {
758 $tags = acym_loadObjectList(
759 'SELECT tags.`title`, tags.`alias`, tags.`id`
760 FROM #__tags AS tags
761 JOIN #__contentitem_tag_map AS map ON tags.`id` = map.`tag_id`
762 WHERE map.`type_alias` = '.acym_escapeDB($type).'
763 AND map.`content_item_id` = '.intval($id)
764 );
765
766 if (empty($tags)) return [];
767
768 $displayTags = [];
769 foreach ($tags as $oneTag) {
770 $displayTags[] = '<a href="index.php?option=com_tags&view=tag&id='.$oneTag->id.':'.$oneTag->alias.'" target="_blank">'.$oneTag->title.'</a>';
771 }
772
773 return $displayTags;
774 }
775
776 protected function getFormattedValue($fieldValues)
777 {
778 $field = $fieldValues[0];
779
780 if (!empty($field->fieldparams) && !is_array($field->fieldparams)) {
781 $field->fieldparams = json_decode($field->fieldparams, true);
782 }
783
784 switch ($field->type) {
785 case 'calendar':
786 $format = acym_translation($field->fieldparams['showtime'] == '1' ? 'ACYM_DATE_FORMAT_LC2' : 'ACYM_DATE_FORMAT_LC1');
787 $field->value = HTMLHelper::_('date', $field->value, $format);
788 break;
789
790 case 'checkboxes':
791 case 'list':
792 case 'radio':
793 $values = [];
794 foreach ($fieldValues as $oneValue) {
795 foreach ($field->fieldparams['options'] as $oneOPT) {
796 if ($oneOPT['value'] == $oneValue->value) {
797 $values[] = $oneOPT['name'];
798 break;
799 }
800 }
801 }
802
803 $field->value = implode(', ', $values);
804 break;
805
806 case 'dpcalendar':
807 if (empty($field->value)) {
808 $field->value = '';
809 break;
810 }
811
812 $title = acym_loadResult('SELECT `title` FROM #__categories WHERE `id` = '.intval($field->value));
813 if (empty($title)) {
814 $field->value = '';
815 } else {
816 $date = '#year='.acym_date('now', 'Y').'&month='.acym_date('now', 'm').'&day='.acym_date('now', 'd').'&view=month';
817 $field->value = '<a target="_blank" href="index.php?option=com_dpcalendar&view=calendar&id='.intval($field->value).$date.'">'.$title.'</a>';
818 }
819 break;
820
821 case 'imagelist':
822 if (!empty($field->fieldparams['directory']) && strlen($field->fieldparams['directory']) > 1) {
823 $field->value = '/'.$field->value;
824 } else {
825 $field->fieldparams['directory'] = '';
826 }
827 $field->value = '<img src="images/'.$field->fieldparams['directory'].$field->value.'" />';
828 break;
829
830 case 'media':
831 $value = '';
832 if (!empty($field->value)) {
833 if (substr($field->value, 0, 1) === '{') {
834 $value = json_decode($field->value, true);
835 if (!empty($value['imagefile'])) {
836 $alt = empty($value['alt_text']) ? '' : ' alt="'.acym_escape($value['alt_text']).'"';
837 $value = '<img src="'.$value['imagefile'].'"'.$alt.' />';
838 }
839 } else {
840 $value = '<img src="'.$field->value.'" alt="" />';
841 }
842 }
843
844 $field->value = $value;
845 break;
846
847 case 'repeatable':
848 if (!empty($field->value)) {
849 $values = json_decode($field->value);
850 $formattedValues = [];
851 foreach ($values as $oneSetOfValues) {
852 $formattedSet = [];
853 foreach ($oneSetOfValues as $oneLabel => $oneValue) {
854 if (empty($oneValue)) continue;
855
856 foreach ($field->fieldparams['fields'] as $oneField) {
857 if ($oneField['fieldname'] !== $oneLabel) continue;
858
859 if ($oneField['fieldtype'] === 'media') {
860 $oneValue = '<img src="'.$oneValue.'" alt="" />';
861 }
862
863 $formattedSet[] = $oneValue;
864 break;
865 }
866 }
867
868 if (empty($formattedSet)) continue;
869 $formattedValues[] = implode(', ', $formattedSet);
870 }
871
872 $field->value = empty($formattedSet) ? '' : '<ul><li>'.implode('</li><li>', $formattedValues).'</li></ul>';
873 }
874 break;
875
876 case 'sql':
877 if (empty($field->options)) {
878 $field->options = acym_loadObjectList($field->fieldparams['query'], 'value');
879 }
880
881 $field->value = $field->options[$field->value]->text;
882 break;
883
884 case 'url':
885 $field->value = '<a target="_blank" href="'.$field->value.'">'.$field->value.'</a>';
886 break;
887
888 case 'user':
889 $field->value = acym_currentUserName($field->value);
890 break;
891
892 case 'usergrouplist':
893 if (empty($field->usergroups)) {
894 $field->usergroups = acym_loadObjectList('SELECT id, title FROM #__usergroups', 'id');
895 }
896
897 if (empty($field->usergroups[$field->value])) {
898 $field->value = '';
899 break;
900 }
901 $field->value = $field->usergroups[$field->value]->title;
902 break;
903 case 'subform':
904 if (!empty($field->value)) {
905 $rows = json_decode($field->value, true);
906
907 $formattedValues = [];
908 foreach ($rows as $values) {
909 $fieldValues = [];
910 foreach ($values as $fieldIdentifier => $fieldValue) {
911 $fieldId = str_replace('field', '', $fieldIdentifier);
912 $oneFieldDefinition = acym_loadObject(
913 'SELECT `field`.*
914 FROM #__fields AS `field`
915 WHERE `field`.`id` = '.intval($fieldId)
916 );
917
918 if (empty($oneFieldDefinition)) {
919 break 3;
920 }
921
922 $multiCompatibleValues = [];
923 if (is_array($fieldValue)) {
924 foreach ($fieldValue as $oneFieldValue) {
925 $oneValue = clone $oneFieldDefinition;
926 $oneValue->value = $oneFieldValue;
927 $multiCompatibleValues[] = $oneValue;
928 }
929 } else {
930 $oneFieldDefinition->value = $fieldValue;
931 $multiCompatibleValues[] = $oneFieldDefinition;
932 }
933
934 $fieldValues[] = $oneFieldDefinition->label.': '.$this->getFormattedValue($multiCompatibleValues);
935 }
936 $formattedValues[] = implode(', ', $fieldValues);
937 }
938
939 $field->value = empty($formattedValues) ? '' : '<ul><li>'.implode('</li><li>', $formattedValues).'</li></ul>';
940 }
941 }
942
943 return $field->value;
944 }
945
946 protected function getLanguage(?string $elementLanguage = null, bool $onlyValue = false): string
947 {
948 $value = $this->emailLanguage;
949 if (!empty($elementLanguage) && $elementLanguage !== '*') {
950 $value = $elementLanguage;
951 }
952
953 if (empty($value)) {
954 return '';
955 }
956
957 if (ACYM_CMS === 'joomla' && acym_isPluginActive('languagefilter')) {
958 $languages = acym_loadObjectList('SELECT * FROM #__languages', 'lang_code');
959 if (isset($languages[$value])) {
960 $value = $languages[$value]->sef;
961 } else {
962 $value = substr($value, 0, strpos($value, '-'));
963 }
964
965 if ($onlyValue) {
966 return $value;
967 }
968
969 return '&lang='.$value;
970 } else {
971 if ($onlyValue) {
972 return $value;
973 }
974
975 return '&language='.$value;
976 }
977 }
978
979 protected function finalizeLink(string $link, $tag = null, $sef = true): string
980 {
981 if (acym_isPluginActive('languagefilter')) {
982 if (strpos($link, 'lang=') === false && !empty($this->emailLanguage)) {
983 $link .= strpos($link, '?') === false ? '?' : '&';
984 $link .= 'lang='.substr($this->emailLanguage, 0, strpos($this->emailLanguage, '-'));
985 }
986 } else {
987 if (strpos($link, 'language=') === false && !empty($this->emailLanguage)) {
988 $link .= strpos($link, '?') === false ? '?' : '&';
989 $link .= 'language='.$this->emailLanguage;
990 }
991 }
992
993 if (!empty($tag->autologin)) {
994 $link .= (strpos($link, '?') ? '&' : '?').'autoSubId={subscriber:id}&subKey={subscriber:key|urlencode}';
995 }
996
997 if (is_bool($tag)) {
998 $sef = $tag;
999 }
1000
1001 return acym_frontendLink($link, false, $sef);
1002 }
1003
1004 protected function handleCustomFields($tag, &$customFields)
1005 {
1006 if (empty($tag->custom)) {
1007 return;
1008 }
1009
1010 $tag->custom = explode(',', $tag->custom);
1011 acym_arrayToInteger($tag->custom);
1012
1013 $rawfields = acym_loadObjectList(
1014 'SELECT `field`.*, `values`.`value`
1015 FROM #__fields_values AS `values`
1016 JOIN #__fields AS `field` ON `values`.`field_id` = `field`.`id`
1017 WHERE `values`.`item_id` = '.intval($tag->id).' AND `field`.`id` IN ('.implode(', ', $tag->custom).')'
1018 );
1019
1020 $fields = [];
1021 foreach ($rawfields as $field) {
1022 $fields[$field->id][] = $field;
1023 }
1024
1025 usort($fields, function ($a, $b) {
1026 return $a[0]->ordering <=> $b[0]->ordering;
1027 });
1028
1029 foreach ($fields as $fieldValues) {
1030 $value = $this->getFormattedValue($fieldValues);
1031
1032 if (empty($value)) continue;
1033
1034 $customFields[] = [
1035 $value,
1036 $fieldValues[0]->label,
1037 ];
1038 }
1039 }
1040
1041 protected function getIntro($text)
1042 {
1043 $pageBreak = null;
1044 $possibleBreaks = [
1045 '<!--more-->',
1046 '<hr id="system-readmore" />',
1047 '<!--nextpage-->',
1048 ];
1049
1050 foreach ($possibleBreaks as $oneBreak) {
1051 if (strpos($text, $oneBreak) !== false) {
1052 $pageBreak = $oneBreak;
1053 break;
1054 }
1055 }
1056
1057 if (empty($pageBreak)) return $text;
1058
1059 $split = explode($pageBreak, $text, 2);
1060
1061 return array_shift($split);
1062 }
1063
1064 public function displayCustomViewEditor(&$output)
1065 {
1066 $plugin = new \stdClass();
1067 $plugin->folder_name = $this->name;
1068 $plugin->settings = $this->settings;
1069 $this->generateSettings($plugin);
1070
1071 if (empty($plugin->settings['custom_view'])) {
1072 return;
1073 }
1074
1075 $output .= '<p class="acym__wysid__right__toolbar__p acym__wysid__right__toolbar__p__open acym__title">';
1076 $output .= acym_translation('ACYM_ADDON_SETTINGS');
1077 $output .= '<i class="acymicon-keyboard-arrow-up"></i></p>';
1078 $output .= '<div class="acym__wysid__right__toolbar__design--show acym__wysid__right__toolbar__design acym__wysid__context__modal__container">';
1079 $output .= $plugin->settings['custom_view'];
1080 $output .= '</div>';
1081 }
1082
1083 public function generateSettings(&$plugin)
1084 {
1085 if (empty($plugin->settings)) return false;
1086
1087 if (array_key_exists('not_installed', $plugin->settings)) {
1088 $plugin->settings = 'not_installed';
1089
1090 return true;
1091 }
1092
1093 foreach ($plugin->settings as $key => $field) {
1094 $text = '';
1095 if (empty($field['type'])) {
1096 $plugin->settings[$key] = $text;
1097 continue;
1098 }
1099
1100 $id = $plugin->folder_name.'_'.$key;
1101 $name = $plugin->folder_name.'['.$key.']';
1102 if (!empty($field['label'])) {
1103 $field['label'] = acym_translation($field['label']);
1104 }
1105
1106 if (!empty($field['info'])) {
1107 $field['label'] .= acym_info(
1108 acym_translation($field['info']),
1109 '',
1110 '',
1111 'wysid_tooltip',
1112 !empty($field['info_warning'])
1113 );
1114 }
1115
1116 if ($field['type'] == 'checkbox') {
1117 $classLabel = 'shrink';
1118 $text .= '<label for="'.$id.'" class="cell '.$classLabel.'">'.$field['label'].'</label>';
1119 $text .= '<input id="'.$id.'" class="cell shrink" type="checkbox" name="'.$name.'" '.(empty($field['value']) ? '' : 'checked').'>';
1120 } elseif ($field['type'] == 'switch') {
1121 $text .= acym_switch(
1122 $name,
1123 $field['value'],
1124 $field['label'],
1125 [],
1126 'large-7'
1127 );
1128 } elseif ($field['type'] == 'select') {
1129 $text .= '<label class="cell shrink">'.$field['label'].'</label>';
1130 $text .= acym_select(
1131 $field['data'],
1132 $name,
1133 $field['value'],
1134 ['class' => 'acym__select'],
1135 'value',
1136 'text',
1137 false,
1138 true
1139 );
1140 } elseif ($field['type'] == 'multiple_select') {
1141 $text .= '<label class="cell shrink">'.$field['label'].'</label>';
1142 $text .= acym_selectMultiple(
1143 $field['data'],
1144 $name,
1145 empty($field['value']) ? [] : $field['value'],
1146 ['class' => 'acym__select']
1147 );
1148 } elseif ($field['type'] == 'text') {
1149 $text .= '<label class="cell shrink">'.$field['label'].'</label>';
1150 $text .= '<input type="text" name="'.$name.'" value="'.acym_escape($field['value']).'" class="cell shrink">';
1151 } elseif ($field['type'] == 'number') {
1152 $text .= '<label class="cell shrink">'.$field['label'].'</label>';
1153 $text .= '<input type="number" name="'.$name.'" value="'.acym_escape($field['value']).'" class="cell large-2 medium-5">';
1154 if (!empty($field['post_text'])) $text .= '<span class="cell shrink">'.strtolower($field['post_text']).'</span>';
1155 } elseif ($field['type'] == 'radio') {
1156 $text .= '<p class="cell">'.$field['label'].'</p>';
1157 $text .= acym_radio(
1158 $field['data'],
1159 $name,
1160 $field['value']
1161 );
1162 } elseif ($field['type'] == 'date') {
1163 $text .= '<label class="cell shrink">'.$field['label'].'</label>';
1164 $text .= acym_dateField(
1165 $name,
1166 $field['value'],
1167 'cell shrink'
1168 );
1169 } elseif ($field['type'] === 'custom_view' && acym_isAdmin()) {
1170 $idCustomView = 'acym__plugins__installed__custom-view__'.$this->name;
1171 $ctrl = acym_getVar('string', 'ctrl', '');
1172 $classTooltip = $ctrl == 'dynamics' ? '' : 'wysid_tooltip';
1173 $text .= '<label class="cell">'.acym_translation('ACYM_CUSTOM_VIEW').acym_info('ACYM_CUSTOM_VIEW_DESC', '', '', $classTooltip).'</label>';
1174 if (empty($field['tags'])) $field['tags'] = [];
1175 $modalContent = '<div id="'.$idCustomView.'" class="cell grid-x acym__plugins__installed__custom-view" acym-data-tags="'.acym_escape(json_encode($field['tags'])).'">
1176 <h2 class="cell text-center acym__title__primary__color">'.acym_translationSprintf('ACYM_CUSTOM_VIEW_FOR_X', $this->pluginDescription->name).'</h2>
1177 <div class="cell grid-x acym__plugins__installed__custom-view__edit-container">
1178 <div class="acym__plugins__installed__custom-view__editor-loader grid-x cell align-center acym_vcenter" v-if="loading">'.acym_loaderLogo().'</div>
1179 <vue-prism-editor :emitEvents="true" class="cell acym__plugins__installed__custom-view__code cell auto" v-model="code" :language="language" lineNumbers="true"></vue-prism-editor>
1180 <div class="cell grid-x medium-3 margin-left-1 acym__plugins__installed__custom-view__tags">
1181 <h3 class="acym__title acym__title__secondary cell text-center">'.acym_translation('ACYM_DYNAMIC_CONTENT').acym_info(
1182 'ACYM_DYNAMIC_CONTENT_DESC'
1183 ).'</h3>
1184 <div class="cell acym__plugins__installed__custom-view__tag" v-for="(trad, tag) in tags" :key="tag" @click.prevent="insertTag(tag)">{{ trad }}</div>
1185 </div>
1186 </div>
1187 <div class="cell grid-x acym__plugins__installed__custom-view__actions acym_vcenter margin-top-1 padding-bottom-1">
1188 <div class="cell auto grid-x">
1189 <button type="button" class="cell shrink button-secondary button" @click="resetView">'.acym_translation('ACYM_RESET_VIEW').'</button>
1190 <div class="cell shrink margin-right-2 acym_vcenter margin-left-1">
1191 <i v-if="deleting" class="acymicon-spin acymicon-circle-o-notch" style="margin-bottom: 0; line-height: 26px;"></i>
1192 <span v-if="deleted">{{ messageDeleted }}</span>
1193 </div>
1194 </div>
1195 <div class="cell auto align-right grid-x">
1196 <div class="cell shrink margin-right-2 acym_vcenter">
1197 <i v-if="saving" class="acymicon-spin acymicon-circle-o-notch" style="margin-bottom: 0; line-height: 26px;"></i>
1198 <span v-if="saved">{{ messageSaved }}</span>
1199 </div>
1200 <button @click="save()" class="cell shrink button" type="button">'.acym_translation('ACYM_SAVE_NEW_CUSTOM_VIEW_VERSION').'</button>
1201 </div>
1202 </div>
1203 </div>';
1204 $text .= acym_modal(
1205 acym_translation('ACYM_EDIT_CUSTOM_VIEW'),
1206 $modalContent,
1207 null,
1208 'acym-data-plugins-id="'.$idCustomView.'" acym-data-plugin-class="'.get_class($this).'" acym-data-plugin-folder="'.$this->name.'"',
1209 'class="cell button"'
1210 );
1211 } elseif ($field['type'] == 'multikeyvalue') {
1212 $text .= '<label class="cell shrink">'.$field['label'].'</label>';
1213
1214 $text .= '<div class="multikeyvalue_container grid-x">';
1215
1216 if (!empty($field['value'])) {
1217 $headers = json_decode($field['value'], true);
1218 foreach ($headers as $headerKey => $headerValue) {
1219 $text .= '<input type="text" class="cell" placeholder="'.acym_translation('ACYM_DKIM_KEY', true).'" value="'.acym_escape($headerKey).'"/>';
1220 $text .= '<input type="text" class="cell" placeholder="'.acym_translation('ACYM_VALUE', true).'" value="'.acym_escape($headerValue).'" />';
1221 $text .= '<div class="multikeyvalue_container_separator cell small-6"></div>';
1222 }
1223 }
1224
1225 $text .= '<input type="text" class="cell" placeholder="'.acym_translation('ACYM_DKIM_KEY', true).'" value=""/>';
1226 $text .= '<input type="text" class="cell" placeholder="'.acym_translation('ACYM_VALUE', true).'" value="" />';
1227
1228 $text .= '<button class="button multikeyvalue_container_new">'.acym_translation('ACYM_ADD_NEW').'</button>';
1229
1230 $text .= '<input type="hidden" name="'.$name.'" value="" />';
1231 $text .= '</div>';
1232 } elseif ($field['type'] == 'custom') {
1233 $text .= $field['content'];
1234 }
1235 $plugin->settings[$key] = $text;
1236 }
1237
1238 return true;
1239 }
1240
1241 public function loadCSS($css, $raw = false, $path = null)
1242 {
1243 if (!$raw) {
1244 if (empty($path)) $path = ACYM_DYNAMICS_URL.$this->name;
1245 $css = $path.'/css/'.$css.'.css';
1246 }
1247 acym_addStyle($raw, $css);
1248 }
1249
1250 public function loadJavascript($js, $raw = false, $path = null)
1251 {
1252 if (!$raw) {
1253 if (empty($path)) $path = ACYM_DYNAMICS_URL.$this->name;
1254 $js = $path.'/js/'.$js.'.js';
1255 }
1256 acym_addScript($raw, $js);
1257 }
1258
1259 public function includeView($view, $data = [], $path = null)
1260 {
1261 if (empty($path)) {
1262 $path = ACYM_ADDONS_FOLDER_PATH.$this->name.DS.'views'.DS.$view.'.php';
1263 } else {
1264 $path = $path.DS.'views'.DS.$view.'.php';
1265 }
1266
1267 if (!file_exists($path)) return false;
1268
1269 ob_start();
1270 include $path;
1271
1272 return ob_get_clean();
1273 }
1274
1275 public function onAcymAddSettings(&$plugins)
1276 {
1277 foreach ($plugins as $key => $plugin) {
1278 if ($plugin->folder_name === $this->name) {
1279 if (!empty($plugin->settings)) {
1280 foreach ($plugin->settings as $keySettings => $value) {
1281 if (isset($this->settings[$keySettings]['value'])) {
1282 $this->settings[$keySettings]['value'] = $plugin->settings[$keySettings]['value'];
1283 }
1284 }
1285 }
1286 $plugins[$key]->settings = $this->settings;
1287
1288 $this->generateSettings($plugins[$key]);
1289 break;
1290 }
1291 }
1292 }
1293
1294 protected function getParam($name, $default = '')
1295 {
1296 return $this->savedSettings[$name]['value'] ?? $default;
1297 }
1298
1299 protected function getTranslationId($elementId, $translationTool, $defaultLanguage = false)
1300 {
1301 return $elementId;
1302 }
1303
1304 public function filterSpecialMailsDailySend(&$specialMails, $time, $mailType)
1305 {
1306 $dailyHour = $this->config->get('daily_hour', '12');
1307 $dailyMinute = $this->config->get('daily_minute', '00');
1308 $dayBasedOnCMSTimezone = acym_date('now', 'Y-m-d');
1309 $dayBasedOnCMSTimezoneAtSpecifiedHour = acym_getTimeFromCMSDate($dayBasedOnCMSTimezone.' '.$dailyHour.':'.$dailyMinute);
1310
1311 $campaignClass = new CampaignClass();
1312
1313 $tmpMails = [];
1314 foreach ($specialMails as $oneMail) {
1315 if ($oneMail->sending_type === $mailType) {
1316 $noNextTrigger = empty($oneMail->next_trigger);
1317 $nextTriggerIsNow = date('m-d', $oneMail->next_trigger) == date('m-d', $dayBasedOnCMSTimezoneAtSpecifiedHour);
1318 $nextTriggerIsInPast = $oneMail->next_trigger < $time;
1319 if ($time >= $dayBasedOnCMSTimezoneAtSpecifiedHour && ($noNextTrigger || $nextTriggerIsNow || $nextTriggerIsInPast)) {
1320 $oneMail->next_trigger = acym_getTime('tomorrow '.$dailyHour.':'.$dailyMinute);
1321 $oneMail->last_generated = $time;
1322 $campaignClass->save($oneMail);
1323 $tmpMails[] = $oneMail;
1324 }
1325 } else {
1326 $tmpMails[] = $oneMail;
1327 }
1328 }
1329 $specialMails = $tmpMails;
1330 }
1331
1332 protected function getIdsSelectAjax()
1333 {
1334 $ids = acym_getVar('string', 'id');
1335 if (is_null($ids)) {
1336 return false;
1337 } elseif (strpos($ids, ',') !== false) {
1338 $ids = explode(',', $ids);
1339 } elseif (!empty($ids)) {
1340 $ids = [$ids];
1341 } else {
1342 echo json_encode([]);
1343 exit;
1344 }
1345
1346 acym_arrayToInteger($ids);
1347
1348 return $ids;
1349 }
1350
1351 protected function cleanExtensionContent($text)
1352 {
1353 if (ACYM_CMS === 'wordpress') {
1354 if (!acym_isExtensionActive('classic-editor/classic-editor.php') || strpos($text, '<!-- wp:') !== false) {
1355 return $text;
1356 }
1357
1358 return nl2br($text);
1359 } else {
1360 return preg_replace('#\{igallery[^}]+\}#Ui', '', $text);
1361 }
1362 }
1363
1364 protected function callApiSendingMethod($url, $data = [], $headers = [], $type = 'GET', $authentication = [], $dataDecoded = false)
1365 {
1366 if (!empty($headers) && empty($headers[0])) {
1367 $newHeaders = [];
1368 foreach ($headers as $key => $value) {
1369 $newHeaders[] = $key.': '.$value;
1370 }
1371 $headers = $newHeaders;
1372 }
1373
1374 $curl = curl_init();
1375
1376 $optionsArray = [
1377 CURLOPT_URL => $url,
1378 CURLOPT_RETURNTRANSFER => true,
1379 CURLOPT_ENCODING => '',
1380 CURLOPT_MAXREDIRS => 10,
1381 CURLOPT_TIMEOUT => 30,
1382 CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
1383 CURLOPT_CUSTOMREQUEST => $type,
1384 CURLOPT_HTTPHEADER => $headers,
1385 CURLOPT_SSL_VERIFYHOST => 0,
1386 CURLOPT_SSL_VERIFYPEER => 0,
1387 ];
1388
1389 if (!empty($data)) {
1390 if (empty($dataDecoded)) {
1391 $optionsArray[CURLOPT_POSTFIELDS] = json_encode($data);
1392 } elseif ($dataDecoded === true) {
1393 $optionsArray[CURLOPT_POSTFIELDS] = $data;
1394 }
1395 }
1396
1397 if (!empty($authentication)) {
1398 $optionsArray[CURLOPT_USERPWD] = $authentication['name'].':'.$authentication['pwd'];
1399 }
1400
1401 curl_setopt_array(
1402 $curl,
1403 $optionsArray
1404 );
1405
1406 $response = curl_exec($curl);
1407 $error = curl_error($curl);
1408 $this->responseCode = (int)curl_getinfo($curl, CURLINFO_HTTP_CODE);
1409 curl_close($curl);
1410
1411 if ($error) {
1412 return ['error_curl' => $error];
1413 } else {
1414 $response = json_decode($response, true);
1415
1416 return $response === null ? ['error_curl' => 'Malformed response'] : $response;
1417 }
1418 }
1419
1420 protected function getTestCredentialsSendingMethodButton($sendingMethodId)
1421 {
1422 return '<div class="cell grid-x margin-top-1 acym__sending__methods__credentials__test">
1423 <button type="button" sending-method-id="'.$sendingMethodId.'" class="acym__configuration__sending__method-test cell shrink button button-secondary">
1424 '.acym_translation('ACYM_TEST_CREDENTIALS').'
1425 </button>
1426 <span class="acym__configuration__sending__method-icon cell shrink margin-left-1 acym_vcenter"></span>
1427 <span class="acym__configuration__sending__method-test__message cell shrink margin-left-1 acym_vcenter"></span>
1428 </div>';
1429 }
1430
1431 public function getCopySettingsButton(array $data, string $sendingMethodId, string $fromPlugin, bool $withContainer = true): string
1432 {
1433 if (empty($data[$fromPlugin.'_installed'])) {
1434 return '';
1435 }
1436
1437 $button = '<button
1438 type="button"
1439 class="cell shrink button button-secondary acym__configuration__copy__mail__settings"
1440 acym-data-plugin="'.acym_escape($fromPlugin).'"
1441 acym-data-method="'.acym_escape($sendingMethodId).'">
1442 '.acym_translationSprintf('ACYM_COPY_SETTINGS_FROM', $this->sendingPlugins[$fromPlugin]).'
1443 </button>
1444 <span class="acym__configuration__sending__method-icon cell shrink margin-left-1 acym_vcenter"></span>';
1445
1446 if ($withContainer) {
1447 $button = '<div class="cell grid-x margin-top-1">'.$button.'</div>';
1448 }
1449
1450 return $button;
1451 }
1452
1453 protected function getLinks($account = '', $pricing = '')
1454 {
1455 if (empty($account) && empty($pricing)) return '';
1456
1457 $html = '<div class="cell grid-x acym-grid-margin-x shrink acym_vcenter"><p class="cell shrink">'.acym_translation('ACYM_DONT_HAVE_ACCOUNT').'</p>';
1458 if (!empty($account)) $html .= '<a target="_blank" class="cell shrink" href="'.$account.'">'.acym_translation('ACYM_CREATE_ONE').'</a>';
1459 if (!empty($account) && !empty($pricing)) $html .= '<p class="cell shrink">'.strtolower(acym_translation('ACYM_OR')).'</p>';
1460 if (!empty($pricing)) $html .= '<a target="_blank" class="cell shrink" href="'.$pricing.'">'.acym_translation('ACYM_CHECK_THEIR_PRICING').'</a>';
1461 $html .= '</div>';
1462
1463 return $html;
1464 }
1465
1466 public function onAcymGetSendingMethodsSelected(&$data)
1467 {
1468 if (ACYM_CMS == 'wordpress') {
1469 $this->config->load();
1470 }
1471
1472 $mailerMethod = $this->config->get('mailer_method', 'phpmail');
1473 foreach ($data['sendingMethods'] as $key => $sendingMethod) {
1474 $data['sendingMethods'][$key]['selected'] = $key == $mailerMethod;
1475 }
1476 }
1477
1478 public function errorCallback()
1479 {
1480 foreach ($this->errors as $error) {
1481 acym_logError($error, empty($this->name) ? get_class($this) : $this->name);
1482 }
1483
1484 $this->errors = [];
1485 }
1486
1487 public function isLogFileEmpty(): bool
1488 {
1489 return !acym_isLogFileErrorExist(empty($this->name) ? get_class($this) : $this->name);
1490 }
1491
1492 public function initCustomView($customFields = false)
1493 {
1494 $page = acym_getVar('cmd', 'page');
1495 if (is_array($page)) return;
1496 if (!empty($page) && is_string($page)) {
1497 $page = str_replace(ACYM_COMPONENT.'_', '', $page);
1498 }
1499 $ctrl = acym_getVar('cmd', 'ctrl', $page);
1500 if (!in_array($ctrl, ['plugins', 'dynamics'])) return;
1501
1502 $task = acym_getVar('cmd', 'task', 'installed');
1503
1504 if (($ctrl === 'plugins' && $task === 'installed') || ($this->active && $ctrl === 'dynamics' && $task === 'trigger')) {
1505 $this->initElementOptionsCustomView();
1506 $this->initReplaceOptionsCustomView();
1507 if ($customFields) $this->initCustomOptionsCustomView();
1508 }
1509 }
1510
1511 public function processDateToCheck($options)
1512 {
1513 $dateNowWithTimeZone = acym_date('now', 'Y-m-d h:i:s');
1514 $dateToCheck = new \DateTime($dateNowWithTimeZone);
1515 $interval = new \DateInterval('P'.intval($options['days']).'D');
1516 if ($options['relative'] === 'before') {
1517 $dateToCheck->add($interval);
1518 } else {
1519 $dateToCheck->sub($interval);
1520 }
1521
1522 return $dateToCheck;
1523 }
1524
1525 public function onAcymCheckInstalled(&$installed)
1526 {
1527 $installed = $this->installed;
1528 }
1529
1530 protected function getLinkTranslated($link)
1531 {
1532 if (empty($this->emailLanguage)) return $link;
1533 if (!acym_isMultilingual()) return $link;
1534
1535 $translationTool = $this->config->get('translate_content', 'no');
1536 if ($translationTool !== 'wpml') return $link;
1537
1538 if (!acym_isExtensionActive('sitepress-multilingual-cms/sitepress.php')) return $link;
1539
1540 $languageCode = substr($this->emailLanguage, 0, 2);
1541
1542 return apply_filters('wpml_permalink', $link, $languageCode);
1543 }
1544
1545 protected function replaceShortcode($content)
1546 {
1547 $content = do_shortcode($content);
1548
1549 return preg_replace('#<!-- wp:shortcode -->(.*)<!-- /wp:shortcode -->#Uis', '$1', $content);
1550 }
1551
1552 protected function fixDivStructure(string $text): string
1553 {
1554 $nbOpeningDivs = substr_count($text, '<div');
1555 $nbClosingDivs = substr_count($text, '</div>');
1556
1557 if ($nbOpeningDivs > $nbClosingDivs) {
1558 $text .= str_repeat('</div>', $nbOpeningDivs - $nbClosingDivs);
1559 } elseif ($nbOpeningDivs < $nbClosingDivs) {
1560 $text = str_repeat('<div>', $nbClosingDivs - $nbOpeningDivs).$text;
1561 }
1562
1563 return $text;
1564 }
1565
1566 protected function getBounceAddress(object $mailerHelper): string
1567 {
1568 if (method_exists($mailerHelper, 'getSendSettings')) {
1569 return $mailerHelper->getSendSettings('bounce_email');
1570 } else {
1571 return $this->config->get('bounce_email');
1572 }
1573 }
1574 }
1575