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

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

1,558 lines 58.5 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)
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($dataDecoded)) {
1390 $optionsArray[CURLOPT_POSTFIELDS] = json_encode($data);
1391 } elseif ($dataDecoded === true) {
1392 $optionsArray[CURLOPT_POSTFIELDS] = $data;
1393 }
1394
1395 if (!empty($authentication)) {
1396 $optionsArray[CURLOPT_USERPWD] = $authentication['name'].':'.$authentication['pwd'];
1397 }
1398
1399 curl_setopt_array(
1400 $curl,
1401 $optionsArray
1402 );
1403
1404 $response = curl_exec($curl);
1405 $error = curl_error($curl);
1406 $this->responseCode = (int)curl_getinfo($curl, CURLINFO_HTTP_CODE);
1407 curl_close($curl);
1408
1409 if ($error) {
1410 return ['error_curl' => $error];
1411 } else {
1412 $response = json_decode($response, true);
1413
1414 return empty($response) ? ['error_curl' => 'Malformed response'] : $response;
1415 }
1416 }
1417
1418 protected function getTestCredentialsSendingMethodButton($sendingMethodId)
1419 {
1420 return '<div class="cell grid-x margin-top-1 acym__sending__methods__credentials__test">
1421 <button type="button" sending-method-id="'.$sendingMethodId.'" class="acym__configuration__sending__method-test cell shrink button button-secondary">
1422 '.acym_translation('ACYM_TEST_CREDENTIALS').'
1423 </button>
1424 <span class="acym__configuration__sending__method-icon cell shrink margin-left-1 acym_vcenter"></span>
1425 <span class="acym__configuration__sending__method-test__message cell shrink margin-left-1 acym_vcenter"></span>
1426 </div>';
1427 }
1428
1429 public function getCopySettingsButton(array $data, string $sendingMethodId, string $fromPlugin): string
1430 {
1431 if (empty($data[$fromPlugin.'_installed'])) return '';
1432
1433 return '<div class="cell grid-x margin-top-1 acym__sending__methods__copy__data">
1434 <button
1435 type="button"
1436 class="cell shrink button button-secondary acym__configuration__copy__mail__settings"
1437 acym-data-plugin="'.acym_escape($fromPlugin).'"
1438 acym-data-method="'.acym_escape($sendingMethodId).'">
1439 '.acym_translationSprintf('ACYM_COPY_SETTINGS_FROM', $this->sendingPlugins[$fromPlugin]).'
1440 </button>
1441 <span class="acym__configuration__sending__method-icon cell shrink margin-left-1 acym_vcenter"></span>
1442 </div>';
1443 }
1444
1445 protected function getLinks($account = '', $pricing = '')
1446 {
1447 if (empty($account) && empty($pricing)) return '';
1448
1449 $html = '<div class="cell grid-x acym-grid-margin-x shrink acym_vcenter"><p class="cell shrink">'.acym_translation('ACYM_DONT_HAVE_ACCOUNT').'</p>';
1450 if (!empty($account)) $html .= '<a target="_blank" class="cell shrink" href="'.$account.'">'.acym_translation('ACYM_CREATE_ONE').'</a>';
1451 if (!empty($account) && !empty($pricing)) $html .= '<p class="cell shrink">'.strtolower(acym_translation('ACYM_OR')).'</p>';
1452 if (!empty($pricing)) $html .= '<a target="_blank" class="cell shrink" href="'.$pricing.'">'.acym_translation('ACYM_CHECK_THEIR_PRICING').'</a>';
1453 $html .= '</div>';
1454
1455 return $html;
1456 }
1457
1458 public function onAcymGetSendingMethodsSelected(&$data)
1459 {
1460 if (ACYM_CMS == 'wordpress') {
1461 $this->config->load();
1462 }
1463
1464 $mailerMethod = $this->config->get('mailer_method', 'phpmail');
1465 foreach ($data['sendingMethods'] as $key => $sendingMethod) {
1466 $data['sendingMethods'][$key]['selected'] = $key == $mailerMethod;
1467 }
1468 }
1469
1470 public function errorCallback()
1471 {
1472 foreach ($this->errors as $error) {
1473 acym_logError($error, empty($this->name) ? get_class($this) : $this->name);
1474 }
1475
1476 $this->errors = [];
1477 }
1478
1479 public function isLogFileEmpty(): bool
1480 {
1481 return !acym_isLogFileErrorExist(empty($this->name) ? get_class($this) : $this->name);
1482 }
1483
1484 public function initCustomView($customFields = false)
1485 {
1486 $page = acym_getVar('cmd', 'page');
1487 if (is_array($page)) return;
1488 if (!empty($page) && is_string($page)) {
1489 $page = str_replace(ACYM_COMPONENT.'_', '', $page);
1490 }
1491 $ctrl = acym_getVar('cmd', 'ctrl', $page);
1492 if (!in_array($ctrl, ['plugins', 'dynamics'])) return;
1493
1494 $task = acym_getVar('cmd', 'task', 'installed');
1495
1496 if (($ctrl === 'plugins' && $task === 'installed') || ($this->active && $ctrl === 'dynamics' && $task === 'trigger')) {
1497 $this->initElementOptionsCustomView();
1498 $this->initReplaceOptionsCustomView();
1499 if ($customFields) $this->initCustomOptionsCustomView();
1500 }
1501 }
1502
1503 public function processDateToCheck($options)
1504 {
1505 $dateNowWithTimeZone = acym_date('now', 'Y-m-d h:i:s');
1506 $dateToCheck = new \DateTime($dateNowWithTimeZone);
1507 $interval = new \DateInterval('P'.intval($options['days']).'D');
1508 if ($options['relative'] === 'before') {
1509 $dateToCheck->add($interval);
1510 } else {
1511 $dateToCheck->sub($interval);
1512 }
1513
1514 return $dateToCheck;
1515 }
1516
1517 public function onAcymCheckInstalled(&$installed)
1518 {
1519 $installed = $this->installed;
1520 }
1521
1522 protected function getLinkTranslated($link)
1523 {
1524 if (empty($this->emailLanguage)) return $link;
1525 if (!acym_isMultilingual()) return $link;
1526
1527 $translationTool = $this->config->get('translate_content', 'no');
1528 if ($translationTool !== 'wpml') return $link;
1529
1530 if (!acym_isExtensionActive('sitepress-multilingual-cms/sitepress.php')) return $link;
1531
1532 $languageCode = substr($this->emailLanguage, 0, 2);
1533
1534 return apply_filters('wpml_permalink', $link, $languageCode);
1535 }
1536
1537 protected function replaceShortcode($content)
1538 {
1539 $content = do_shortcode($content);
1540
1541 return preg_replace('#<!-- wp:shortcode -->(.*)<!-- /wp:shortcode -->#Uis', '$1', $content);
1542 }
1543
1544 protected function fixDivStructure(string $text): string
1545 {
1546 $nbOpeningDivs = substr_count($text, '<div');
1547 $nbClosingDivs = substr_count($text, '</div>');
1548
1549 if ($nbOpeningDivs > $nbClosingDivs) {
1550 $text .= str_repeat('</div>', $nbOpeningDivs - $nbClosingDivs);
1551 } elseif ($nbOpeningDivs < $nbClosingDivs) {
1552 $text = str_repeat('<div>', $nbClosingDivs - $nbOpeningDivs).$text;
1553 }
1554
1555 return $text;
1556 }
1557 }
1558