'WP Mail SMTP',
];
public array $errors = [];
public string $logFilename = '';
protected int $responseCode;
private bool $active;
public array $settings = [];
private array $savedSettings = [];
public array $automationTriggers = [];
public array $automationActions = [];
public array $automationConditions = [];
public array $automationFilters = [];
public array $mailboxActions = [];
public function __construct()
{
parent::__construct();
$this->elementOptions = ['wrappedText' => [acym_translation('ACYM_WRAPPED_TEXT')]];
//TODO only load this helper once even if 50 plugins are loaded
$this->pluginHelper = new PluginHelper();
$this->pageInfo = new \stdClass();
$this->pluginDescription = new \stdClass();
$this->pluginDescription->plugin = get_class($this);
$this->name = strtolower(substr($this->pluginDescription->plugin, 7));
$this->generateCampaignResult = new \stdClass();
$this->generateCampaignResult->status = true;
$this->generateCampaignResult->message = '';
$this->campaignId = acym_getVar('int', 'campaignId', 0);
$this->campaignType = acym_getVar('string', 'campaign_type', '');
$pluginClass = new PluginClass();
$currentAddon = $pluginClass->getOnePluginByFolderName($this->name);
$this->active = empty($currentAddon) || $currentAddon->active;
if (!empty($currentAddon->settings)) {
if (is_string($currentAddon->settings)) {
$this->savedSettings = json_decode($currentAddon->settings, true);
} else {
$this->savedSettings = $currentAddon->settings;
}
}
$this->logFilename = acym_getErrorLogFilename(empty($this->name) ? get_class($this) : $this->name);
}
protected function displaySelectionZone(string $zoneContent): void
{
?>
prepareListing();
}
public function prepareListing()
{
$this->pageInfo->limit = 10;
$this->pageInfo->page = acym_getVar('int', 'pagination_page_ajax', 1);
$this->pageInfo->start = ($this->pageInfo->page - 1) * $this->pageInfo->limit;
$this->pageInfo->search = acym_getVar('string', 'plugin_search', '');
$this->pageInfo->filter_cat = acym_getVar('int', 'plugin_category', 0);
$this->pageInfo->orderdir = 'DESC';
$this->pageInfo->loadMore = acym_getVar('boolean', 'loadMore', false);
if (!empty($this->pageInfo->search) && !empty($this->searchFields)) {
$searchVal = '%'.acym_getEscaped($this->pageInfo->search, true).'%';
$this->filters[] = implode(' LIKE '.acym_escapeDB($searchVal).' OR ', $this->searchFields).' LIKE '.acym_escapeDB($searchVal);
}
return '';
}
public function getElements(): array
{
$conditions = '';
if (!empty($this->filters)) {
$conditions = ' WHERE ('.implode(') AND (', $this->filters).')';
}
$ordering = '';
if (!empty($this->pageInfo->order)) {
$ordering = ' ORDER BY '.acym_secureDBColumn($this->pageInfo->order).' '.acym_secureDBColumn($this->pageInfo->orderdir);
}
$rows = acym_loadObjectList($this->querySelect.$this->query.$conditions.$ordering, '', $this->pageInfo->start, $this->pageInfo->limit);
$this->pageInfo->total = acym_loadResult('SELECT COUNT(*) '.$this->query.$conditions.$ordering);
if (!empty($this->defaultValues->id) && $this->defaultValues->defaultPluginTab === $this->name) {
$found = false;
foreach ($rows as $oneRow) {
if (intval($oneRow->{$this->elementIdColumn}) === intval($this->defaultValues->id)) {
$found = true;
}
}
if (!$found) {
$conditions = ' WHERE '.$this->elementIdTable.'.'.$this->elementIdColumn.' = '.intval($this->defaultValues->id);
$row = acym_loadObject($this->querySelect.$this->query.$conditions);
if (!empty($row)) {
$rows[] = $row;
}
}
}
return $rows;
}
protected function getFilteringZone(bool $categoryFilter = true): string
{
$result = '
';
if ($categoryFilter) {
$result .= $this->getCategoryFilter();
}
$result .= '
';
return $result;
}
public function prepareWPCategories(string $type): void
{
$this->categories = acym_loadObjectList(
'SELECT cat.term_taxonomy_id AS id, parent.term_taxonomy_id AS parent_id, catdetails.name AS title
FROM `#__term_taxonomy` AS cat
JOIN `#__terms` AS catdetails ON cat.term_id = catdetails.term_id
LEFT JOIN `#__term_taxonomy` AS parent ON cat.parent = parent.term_id
WHERE cat.taxonomy = '.acym_escapeDB($type)
);
foreach ($this->categories as $i => $oneCat) {
if (empty($oneCat->parent_id)) {
$this->categories[$i]->parent_id = $this->rootCategoryId;
}
}
}
protected function getCategoryFilter()
{
$filter_cat = acym_getVar('int', 'plugin_category', 0);
$this->catvalues = [];
$this->catvalues[] = acym_selectOption(0, 'ACYM_ALL');
$this->cats = [];
$this->subCategories = [];
if (!empty($this->categories)) {
foreach ($this->categories as $oneCat) {
$this->cats[$oneCat->parent_id][] = $oneCat;
}
$this->handleChildrenCategories($this->rootCategoryId);
foreach ($this->categories as $oneCat) {
$this->subCategories[$oneCat->id] = $this->getSubCats($oneCat->id);
}
}
return acym_select(
$this->catvalues,
'plugin_category',
intval($filter_cat),
['class' => 'plugin_category_select']
);
}
private function getSubCats(int $categoryId): array
{
$result = [$categoryId];
if (empty($this->cats[$categoryId])) {
return $result;
}
foreach ($this->cats[$categoryId] as $oneSubCategory) {
$result = array_merge($result, $this->getSubCats($oneSubCategory->id));
}
return $result;
}
protected function handleChildrenCategories(int $parent_id, int $level = 0): void
{
if (empty($this->cats[$parent_id])) return;
foreach ($this->cats[$parent_id] as $cat) {
$this->catvalues[] = acym_selectOption($cat->id, str_repeat(' - - ', $level).$cat->title);
$this->handleChildrenCategories($cat->id, $level + 1);
}
}
protected function getSubCategories(int $categoryId): array
{
$this->getCategoryFilter();
return $this->subCategories[$categoryId];
}
protected function autoContentOptions(array &$options, ?string $type = null): void
{
if ($type === 'event') {
$options[] = [
'title' => 'ACYM_FROM',
'type' => 'date',
'name' => 'from',
'default' => time(),
'relativeDate' => '+',
];
$options[] = [
'title' => 'ACYM_TO',
'type' => 'date',
'name' => 'to',
'default' => '',
'relativeDate' => '+',
];
} elseif ($type !== 'simple') {
$options[] = [
'title' => 'ACYM_MIN_PUBLISH_DATE',
'tooltip' => 'ACYM_MIN_PUBLISH_DATE_DESC',
'type' => 'date',
'name' => 'min_publish',
'default' => '',
'relativeDate' => '-',
];
}
$options[] = [
'title' => 'ACYM_COLUMNS',
'type' => 'number',
'name' => 'cols',
'default' => 1,
];
$options[] = [
'title' => 'ACYM_COLUMN_HORIZONTAL_PADDING',
'type' => 'number',
'name' => 'hpadding',
'default' => 10,
];
$options[] = [
'title' => 'ACYM_COLUMN_VERTICAL_PADDING',
'type' => 'number',
'name' => 'vpadding',
'default' => 10,
];
$options[] = [
'title' => 'ACYM_MAX_NB_ELEMENTS',
'type' => 'number',
'name' => 'max',
'default' => 20,
];
}
protected function autoCampaignOptions(array &$options, bool $modified = false): void
{
if (empty($this->campaignId) && empty($this->campaignType)) {
return;
} elseif (!empty($this->campaignId) && (empty($this->campaignType) || $this->campaignType !== 'auto')) {
$campaignClass = new CampaignClass();
$campaign = $campaignClass->getOneById($this->campaignId);
if ($campaign->sending_type !== 'auto') return;
} elseif (empty($this->campaignId) && !empty($this->campaignType) && $this->campaignType !== 'auto') {
return;
}
$options[] = [
'title' => 'ACYM_DOCUMENTATION',
'type' => 'custom',
'name' => 'documentation',
'output' => static function (): void {
echo ' ';
},
'js' => '',
'section' => 'ACYM_AUTO_CAMPAIGNS_OPTIONS',
];
if ($modified) {
$options[] = [
'title' => 'ACYM_DATE',
'type' => 'select',
'name' => 'datefilter',
'default' => 'onlynew',
'tooltip' => 'ACYM_ONLY_NEWLY_CREATED_DESC',
'options' => [
'' => 'ACYM_NO_FILTER',
'onlynew' => 'ACYM_ONLY_NEWLY_CREATED',
'onlymodified' => 'ACYM_ONLY_NEWLY_MODIFIED',
],
'section' => 'ACYM_AUTO_CAMPAIGNS_OPTIONS',
];
} else {
$options[] = [
'title' => 'ACYM_ONLY_NEWLY_CREATED',
'type' => 'boolean',
'name' => 'onlynew',
'default' => true,
'tooltip' => 'ACYM_ONLY_NEWLY_CREATED_DESC',
'section' => 'ACYM_AUTO_CAMPAIGNS_OPTIONS',
];
}
$options[] = [
'title' => 'ACYM_MIN_NB_ELEMENTS',
'type' => 'number',
'name' => 'min',
'default' => 0,
'tooltip' => 'ACYM_MIN_NB_ELEMENTS_DESC',
'section' => 'ACYM_AUTO_CAMPAIGNS_OPTIONS',
];
}
protected function getElementsListing(array $options): string
{
if ($this->pageInfo->loadMore) {
ob_start();
$this->displayInnerListing($options);
return ob_get_clean();
}
$listing = '';
return $listing;
}
private function displayInnerListing(array $options): void
{
if (empty($options['rows'])) {
if ($this->pageInfo->loadMore) {
echo ''.esc_html(acym_translation('ACYM_NO_MORE_RESULTS')).' ';
} else {
echo ''.esc_html(acym_translation('ACYM_NO_RESULTS_FOUND')).' ';
}
return;
}
$selected = explode(',', acym_getVar('string', 'selected', ''));
if (!empty($this->defaultValues->id)) {
$selected = [$this->defaultValues->id];
}
foreach ($options['rows'] as $row) {
$class = 'cell grid-x acym__row__no-listing acym__listing__row__popup';
if (in_array($row->{$options['id']}, $selected)) {
$class .= ' selected_row';
}
echo '';
foreach ($options['header'] as $column => $oneColumn) {
$value = $row->$column;
$class = empty($oneColumn['class']) ? '' : ' '.$oneColumn['class'];
echo '
';
if (!empty($oneColumn['type'])) {
if ($oneColumn['type'] === 'date') {
if (empty($value)) {
echo '-';
} else {
if (!is_numeric($value) && $value != '0000-00-00 00:00:00') {
$value = strtotime($value);
}
$tooltip = acym_date($value, acym_translation('ACYM_DATE_FORMAT_LC2'));
acym_tooltip(
[
'hoveredText' => acym_date($value, acym_translation('ACYM_DATE_FORMAT_LC5')),
'textShownInTooltip' => $tooltip,
]
);
}
} elseif ($oneColumn['type'] === 'int') {
echo intval($value);
} else {
echo esc_html($value);
}
} else {
echo esc_html($value);
}
echo '
';
}
echo '
';
}
}
protected function getCategoryListing(): string
{
$listing = '';
if (empty($this->catvalues)) {
$listing .= ''.acym_translation('ACYM_NO_RESULTS_FOUND').' ';
return $listing;
}
$listing .= '';
return $listing;
}
protected function getTagListing(): string
{
$listing = '';
if (empty($this->tagvalues)) {
$listing .= ''.acym_translation('ACYM_NO_RESULTS_FOUND').' ';
return $listing;
}
$listing .= '';
return $listing;
}
protected function replaceMultiple(object &$email)
{
$this->generateByCategory($email);
if (empty($this->tags)) return;
$this->pluginHelper->replaceTags($email, $this->tags, true);
}
protected function handleOrderBy(string &$query, object $parameter, ?string $table = null)
{
if (empty($parameter->order)) return;
$ordering = explode(',', $parameter->order);
if ($ordering[0] === 'rand') {
$query .= ' ORDER BY rand()';
} else {
$table = null === $table ? '' : $table.'.';
$column = $ordering[0];
if (strpos($column, '.') !== false) {
$parts = explode('.', $column, 2);
$table = acym_secureDBColumn($parts[0]).'.';
$column = $parts[1];
}
$query .= ' ORDER BY '.$table.'`'.acym_secureDBColumn(trim($column)).'` '.acym_secureDBColumn(trim($ordering[1]));
}
}
protected function handleMax(string &$query, object $parameter): void
{
if (empty($parameter->max)) {
$parameter->max = 20;
}
$query .= ' LIMIT '.intval($parameter->max);
}
protected function handleMin(array $elements, object $parameter): void
{
if (!empty($parameter->min) && count($elements) < $parameter->min) {
$this->generateCampaignResult->status = false;
$this->generateCampaignResult->message = acym_translationSprintf(
'ACYM_GENERATE_CAMPAIGN_NOT_ENOUGH_CONTENT',
$this->pluginDescription->name,
count($elements),
$parameter->min
);
}
}
protected function getLastGenerated(int $mailId): int
{
$campaignClass = new CampaignClass();
return $campaignClass->getLastGenerated($mailId);
}
/**
* Returns the individual elements tags based on a query result
*/
protected function finalizeCategoryFormat(string $query, object $parameter, ?string $table = null): string
{
$this->handleOrderBy($query, $parameter, $table);
$this->handleMax($query, $parameter);
$elements = acym_loadResultArray($query);
return $this->formatIndividualTags($elements, $parameter);
}
protected function formatIndividualTags(array $elements, object $parameter): string
{
$this->handleMin($elements, $parameter);
if (empty($elements)) return '';
$elements = $this->groupByCategory($elements);
$customLayout = ACYM_CUSTOM_PLUGIN_LAYOUT.$this->name.'_auto.php';
if (file_exists($customLayout)) {
ob_start();
require $customLayout;
return ob_get_clean();
}
$arrayElements = $this->buildIndividualTags($elements, $parameter);
return $this->pluginHelper->getFormattedResult($arrayElements, $parameter);
}
protected function buildIndividualTags(array $elements, object $parameter): array
{
$arrayElements = [];
unset($parameter->id);
$i = 0;
foreach ($elements as $oneElementId) {
$args = [];
$args[] = $this->name.':'.$oneElementId;
foreach ($parameter as $oneParam => $val) {
if (is_bool($val)) {
$args[] = $oneParam;
} else {
$args[] = $oneParam.':'.$val;
}
}
if ($i % 2 === 1 && !empty($parameter->alternate)) {
$args[] = 'invert';
}
$arrayElements[] = '{'.implode('| ', $args).'}';
$i++;
}
return $arrayElements;
}
/**
* This method can be overridden in the add-on when a group by category option is added
*/
protected function groupByCategory(array $elements)
{
return $elements;
}
protected function getSelectedArea(object $parameter): array
{
$allcats = explode('-', $parameter->id);
$selectedArea = [];
foreach ($allcats as $oneCat) {
if (empty($oneCat)) continue;
$selectedArea[] = intval($oneCat);
}
return $selectedArea;
}
protected function replaceOne(object &$email): void
{
$tags = $this->pluginHelper->extractTags($email, $this->name);
if (empty($tags)) return;
$newConfiguration = [
'dcontent_default_'.get_class($this) => json_encode(end($tags)),
];
$this->config->saveConfig($newConfiguration);
if (method_exists($this, 'loadLibraries') && !$this->loadLibraries($email)) {
return;
}
$this->emailLanguage = $email->links_language;
$translationTool = $this->config->get('translate_content', 'no');
$tagsReplaced = [];
foreach ($tags as $i => $oneTag) {
if (isset($tagsReplaced[$i])) continue;
if (!empty($this->emailLanguage) && $translationTool !== 'no' && acym_isMultilingual()) {
$oneTag->id = $this->getTranslationId($oneTag->id, $translationTool);
}
$tagsReplaced[$i] = $this->replaceIndividualContent($oneTag);
}
$email->custom_view = file_exists(ACYM_CUSTOM_PLUGIN_LAYOUT.$this->name.'.html');
$this->pluginHelper->replaceTags($email, $tagsReplaced, true);
}
protected function initIndividualContent(object &$tag, string $query)
{
$element = acym_loadObject($query);
if (empty($element)) {
if (acym_isAdmin()) {
acym_enqueueMessage(acym_translationSprintf('ACYM_CONTENT_NOT_FOUND', $tag->id), 'notice');
}
return null;
}
if (empty($tag->display)) {
$tag->display = [];
} else {
$tag->display = explode(',', $tag->display);
}
return $element;
}
protected function getCustomLayoutVars(object $element): array
{
$varFields = [];
$varFields['{picthtml}'] = '';
foreach ($element as $fieldName => $oneField) {
if (is_object($oneField) || is_array($oneField)) {
$varFields['{'.$fieldName.'}'] = json_encode($oneField);
} else {
$varFields['{'.$fieldName.'}'] = $oneField;
}
}
return $varFields;
}
/**
* Handles the custom layouts and the pictures management
*
* @param string $htmlResult What will be inserted in the email
* @param object $insertionOptions Selected options when inserting dcontent
* @param array $dataShortcodes Data used as shortcodes in custom layouts
*/
protected function finalizeElementFormat(string $htmlResult, object $insertionOptions, array $dataShortcodes): string
{
// Hidden feature, users can do a PHP custom view
$fullCustomLayoutPath = ACYM_CUSTOM_PLUGIN_LAYOUT.$this->name.'.php';
if ($this->config->get('php_overrides', 0) == 1 && file_exists($fullCustomLayoutPath)) {
ob_start();
require $fullCustomLayoutPath;
$viewContent = ob_get_clean();
$htmlResult = str_replace(array_keys($dataShortcodes), $dataShortcodes, $viewContent);
} else {
// Default custom view feature with only HTML for security reasons
$customLayoutPath = ACYM_CUSTOM_PLUGIN_LAYOUT.$this->name.'.html';
if (file_exists($customLayoutPath)) {
$dataShortcodes['{wrappedText}'] = $this->pluginHelper->wrappedText;
$viewContent = acym_fileGetContent($customLayoutPath);
$viewContentReplace = str_replace(array_keys($dataShortcodes), $dataShortcodes, $viewContent);
if ($viewContent !== $viewContentReplace) {
$htmlResult = $viewContentReplace;
}
}
}
$allShortcodesList = 'Shortcode Value ';
foreach ($dataShortcodes as $name => $value) {
if (!is_string($value)) {
continue;
}
$allShortcodesList .= ''.trim($name, '{}').' '.$value.' ';
}
$allShortcodesList .= '
';
$htmlResult = str_replace('{allshortcodes}', $allShortcodesList, $htmlResult);
// Resize/remove pictures if needed
return $this->pluginHelper->managePicts($insertionOptions, $htmlResult);
}
/**
* Keep this method untyped until v12
*/
public function onAcymDeclareTriggers(&$triggers, &$defaultValues)
{
if (empty($this->automationTriggers) && method_exists($this, 'initAutomationTriggers')) {
$this->initAutomationTriggers();
}
foreach ($this->automationTriggers as $group => $groupTriggers) {
foreach ($groupTriggers as $key => $name) {
$triggers[$group][$key] = $this->declareTrigger($key, $name, $defaultValues, $group);
}
}
}
/**
* Keep this method untyped until v12
*/
public function onAcymDeclareTriggersScenario(&$triggers, &$defaultValues)
{
$this->onAcymDeclareTriggers($triggers, $defaultValues);
}
/**
* Declares name and options callbacks for automation/scenario triggers
*/
protected function declareTrigger(string $key, string $name, $defaultValues = [], string $group = 'user'): object
{
$trigger = new \stdClass();
$trigger->name = $name;
if (!is_array($defaultValues)) {
$defaultValues = [];
}
$method = 'displayTriggerOptions_'.$key;
if (!method_exists($this, $method)) {
$method = 'displayTriggerOptions';
}
if (method_exists($this, $method)) {
$automationFieldName = '[triggers]['.$group.']['.$key.']';
$trigger->displayOptions = function (?string $fieldName = null) use ($method, $defaultValues, $key, $automationFieldName): void {
$this->$method($fieldName === null ? $automationFieldName : $fieldName, $defaultValues, $key);
};
}
return $trigger;
}
public function onAcymDeclareActions(array &$actions): void
{
if (empty($this->automationActions) && method_exists($this, 'initAutomationActions')) {
$this->initAutomationActions();
}
foreach ($this->automationActions as $key => $name) {
$actions[$key] = $this->declareAction($key, $name);
}
}
public function onAcymDeclareActionsScenario(array &$actions): void
{
$this->onAcymDeclareActions($actions);
}
/**
* Declares name and options callbacks for an automation/scenario action
*/
protected function declareAction(string $key, string $name): object
{
$action = new \stdClass();
$action->name = $name;
$method = 'displayActionOptions_'.$key;
if (!method_exists($this, $method)) {
$method = 'displayActionOptions';
}
if (method_exists($this, $method)) {
$action->displayOptions = function () use ($method, $key): void {
$this->$method($key);
};
}
return $action;
}
public function onAcymDeclareConditions(array &$conditions): void
{
if (empty($this->automationConditions) && method_exists($this, 'initAutomationConditions')) {
$this->initAutomationConditions();
}
foreach ($this->automationConditions as $group => $groupConditions) {
foreach ($groupConditions as $key => $name) {
$conditions[$group][$key] = $this->declareCondition($key, $name);
}
}
}
public function onAcymDeclareConditionsScenario(array &$conditions): void
{
$this->onAcymDeclareConditions($conditions);
}
public function onAcymDeclareFilters(array &$filters): void
{
if (empty($this->automationFilters) && method_exists($this, 'initAutomationFilters')) {
$this->initAutomationFilters();
}
foreach ($this->automationFilters as $key => $name) {
$filters[$key] = $this->declareFilter($key, $name);
}
}
/**
* Returns a field name without its acym_condition / acym_action prefix.
*/
protected function getFieldNameWithoutPrefix(string $fieldName): string
{
return str_replace(['acym_condition', 'acym_action'], '', $fieldName);
}
protected function declareCondition(string $key, string $name): object
{
$condition = new \stdClass();
$condition->name = $name;
$renderer = $this->getOptionsRenderer('displayConditionOptions', $key, self::CONDITION_FIELD_NAME.'['.$key.']');
if ($renderer !== null) {
$condition->displayOptions = $renderer;
}
return $condition;
}
public function onAcymMailboxActionDefine(&$actions)
{
if (empty($this->mailboxActions) && method_exists($this, 'initMailboxActions')) {
$this->initMailboxActions();
}
foreach ($this->mailboxActions as $key => $name) {
$actions[$key] = $this->declareMailboxAction($key, $name);
}
}
/**
* A follow-up condition row: a translated sentence holding the selectors the add-on built.
*/
protected function followupConditionRow(string $translationKey, string ...$fields): callable
{
return static function () use ($translationKey, $fields): void {
echo acym_translationSprintf($translationKey, ...$fields);
};
}
protected function declareMailboxAction(string $key, string $name): object
{
$action = new \stdClass();
$action->name = $name;
$renderer = $this->getOptionsRenderer('displayMailboxActionOptions', $key, self::MAILBOX_ACTION_FIELD_NAME.'['.$key.']');
if ($renderer !== null) {
$action->displayOptions = $renderer;
}
return $action;
}
protected function declareFilter(string $key, string $name): object
{
$filter = new \stdClass();
$filter->name = $name;
$renderer = $this->getOptionsRenderer('displayFilterOptions', $key, self::FILTER_FIELD_NAME.'['.$key.']');
if ($renderer !== null) {
$filter->displayOptions = $renderer;
}
return $filter;
}
/**
* Builds the callback that displays the option fields of a declaration.
*/
private function getOptionsRenderer(string $methodPrefix, string $key, string $defaultFieldName): ?callable
{
$method = $methodPrefix.'_'.$key;
if (!method_exists($this, $method)) {
$method = $methodPrefix;
}
if (!method_exists($this, $method)) {
return null;
}
return function (?string $fieldName = null) use ($method, $key, $defaultFieldName): void {
$this->$method($fieldName === null ? $defaultFieldName : $fieldName, $key);
};
}
/**
* Most add-ons offer the same choices as conditions and as filters, the only difference being the name the fields are nested under
*/
protected function filtersFromConditions(array &$filters): void
{
$conditions = [];
$this->onAcymDeclareConditions($conditions);
foreach ($conditions as $oneGroup) {
foreach ($oneGroup as $oneFilterName => $oneFilter) {
$renderer = $this->getOptionsRenderer('displayConditionOptions', $oneFilterName, self::FILTER_FIELD_NAME.'['.$oneFilterName.']');
if ($renderer !== null) {
$oneFilter->displayOptions = $renderer;
} elseif (!empty($oneFilter->option)) {
// TODO: remove this on version 12, only there for retro-compat of add-ons/plugins not updated along with AcyMailing
$oneFilter->option = str_replace(['acym_condition', '[conditions]'], ['acym_action', '[filters]'], $oneFilter->option);
}
$filters[$oneFilterName] = $oneFilter;
}
}
}
protected function getElementTags(string $type, int $id): array
{
$tags = acym_loadObjectList(
'SELECT tags.`title`, tags.`alias`, tags.`id`
FROM #__tags AS tags
JOIN #__contentitem_tag_map AS map ON tags.`id` = map.`tag_id`
WHERE map.`type_alias` = '.acym_escapeDB($type).'
AND map.`content_item_id` = '.intval($id)
);
if (empty($tags)) return [];
$displayTags = [];
foreach ($tags as $oneTag) {
$displayTags[] = ''.$oneTag->title.' ';
}
return $displayTags;
}
/**
* @return mixed
*/
protected function getFormattedValue(array $fieldValues)
{
$field = $fieldValues[0];
if (!empty($field->fieldparams) && !is_array($field->fieldparams)) {
$field->fieldparams = json_decode($field->fieldparams, true);
}
switch ($field->type) {
case 'calendar':
$format = acym_translation($field->fieldparams['showtime'] == '1' ? 'ACYM_DATE_FORMAT_LC2' : 'ACYM_DATE_FORMAT_LC1');
$field->value = HTMLHelper::_('date', $field->value, $format);
break;
case 'checkboxes':
case 'list':
case 'radio':
$values = [];
foreach ($fieldValues as $oneValue) {
foreach ($field->fieldparams['options'] as $oneOPT) {
if ($oneOPT['value'] == $oneValue->value) {
$values[] = $oneOPT['name'];
break;
}
}
}
$field->value = implode(', ', $values);
break;
case 'dpcalendar':
if (empty($field->value)) {
$field->value = '';
break;
}
$title = acym_loadResult('SELECT `title` FROM #__categories WHERE `id` = '.intval($field->value));
if (empty($title)) {
$field->value = '';
} else {
$date = '#year='.acym_date('now', 'Y').'&month='.acym_date('now', 'm').'&day='.acym_date('now', 'd').'&view=month';
$field->value = ''.$title.' ';
}
break;
case 'imagelist':
if (!empty($field->fieldparams['directory']) && strlen($field->fieldparams['directory']) > 1) {
$field->value = '/'.$field->value;
} else {
$field->fieldparams['directory'] = '';
}
$field->value = ' ';
break;
case 'media':
$value = '';
if (!empty($field->value)) {
if (substr($field->value, 0, 1) === '{') {
$value = json_decode($field->value, true);
if (!empty($value['imagefile'])) {
$alt = empty($value['alt_text']) ? '' : ' alt="'.esc_attr($value['alt_text']).'"';
$value = ' ';
}
} else {
$value = ' ';
}
}
$field->value = $value;
break;
case 'repeatable':
if (!empty($field->value)) {
$values = is_string($field->value) ? json_decode($field->value) : $field->value;
$formattedValues = [];
foreach ($values as $oneSetOfValues) {
$formattedSet = [];
foreach ($oneSetOfValues as $oneLabel => $oneValue) {
if (empty($oneValue)) continue;
foreach ($field->fieldparams['fields'] as $oneField) {
if ($oneField['fieldname'] !== $oneLabel) continue;
if ($oneField['fieldtype'] === 'media') {
$oneValue = ' ';
}
$formattedSet[] = $oneValue;
break;
}
}
if (empty($formattedSet)) continue;
$formattedValues[] = implode(', ', $formattedSet);
}
$field->value = empty($formattedSet) ? '' : ''.implode(' ', $formattedValues).' ';
}
break;
case 'sql':
if (empty($field->options)) {
$field->options = acym_loadObjectList($field->fieldparams['query'], 'value');
}
$field->value = $field->options[$field->value]->text;
break;
case 'url':
$field->value = ''.$field->value.' ';
break;
case 'user':
$field->value = acym_currentUserName($field->value);
break;
case 'usergrouplist':
if (empty($field->usergroups)) {
$field->usergroups = acym_loadObjectList('SELECT id, title FROM #__usergroups', 'id');
}
if (empty($field->usergroups[$field->value])) {
$field->value = '';
break;
}
$field->value = $field->usergroups[$field->value]->title;
break;
case 'subform':
if (!empty($field->value)) {
$rows = is_string($field->value) ? json_decode($field->value, true) : $field->value;
$formattedValues = [];
foreach ($rows as $values) {
$fieldValues = [];
foreach ($values as $fieldIdentifier => $fieldValue) {
$fieldId = str_replace('field', '', $fieldIdentifier);
$oneFieldDefinition = acym_loadObject(
'SELECT `field`.*
FROM #__fields AS `field`
WHERE `field`.`id` = '.intval($fieldId)
);
if (empty($oneFieldDefinition)) {
break 3;
}
$multiCompatibleValues = [];
if (is_array($fieldValue)) {
foreach ($fieldValue as $oneFieldValue) {
$oneValue = clone $oneFieldDefinition;
$oneValue->value = $oneFieldValue;
$multiCompatibleValues[] = $oneValue;
}
} else {
$oneFieldDefinition->value = $fieldValue;
$multiCompatibleValues[] = $oneFieldDefinition;
}
$fieldValues[] = $oneFieldDefinition->label.': '.$this->getFormattedValue($multiCompatibleValues);
}
$formattedValues[] = implode(', ', $fieldValues);
}
$field->value = empty($formattedValues) ? '' : ''.implode(' ', $formattedValues).' ';
}
}
return $field->value;
}
protected function getLanguage(?string $elementLanguage = null, bool $onlyValue = false): string
{
$value = $this->emailLanguage;
if (!empty($elementLanguage) && $elementLanguage !== '*') {
$value = $elementLanguage;
}
if (empty($value)) {
return '';
}
if (ACYM_CMS === 'joomla' && acym_isPluginActive('languagefilter')) {
$languages = acym_loadObjectList('SELECT * FROM #__languages', 'lang_code');
if (isset($languages[$value])) {
$value = $languages[$value]->sef;
} else {
$value = substr($value, 0, strpos($value, '-'));
}
if ($onlyValue) {
return $value;
}
return '&lang='.$value;
} else {
if ($onlyValue) {
return $value;
}
return '&language='.$value;
}
}
// Don't add types for $tag and $sef, for retro-compatibility
protected function finalizeLink(string $link, $tag = null, $sef = true): string
{
if (acym_isPluginActive('languagefilter')) {
if (strpos($link, 'lang=') === false && !empty($this->emailLanguage)) {
$link .= strpos($link, '?') === false ? '?' : '&';
$link .= 'lang='.substr($this->emailLanguage, 0, strpos($this->emailLanguage, '-'));
}
} else {
if (strpos($link, 'language=') === false && !empty($this->emailLanguage)) {
$link .= strpos($link, '?') === false ? '?' : '&';
$link .= 'language='.$this->emailLanguage;
}
}
if (!empty($tag->autologin)) {
$link .= (strpos($link, '?') ? '&' : '?').'autoSubId={subscriber:id}&subKey={subscriber:autologin_token|urlencode}';
}
// Retro-compatibility for add-on versions before the v8.6.0
if (is_bool($tag)) {
$sef = $tag;
}
return acym_frontendLink($link, false, $sef);
}
protected function handleCustomFields(object $tag, array &$customFields): void
{
if (empty($tag->custom)) {
return;
}
$tag->custom = explode(',', $tag->custom);
acym_arrayToInteger($tag->custom);
$rawfields = acym_loadObjectList(
'SELECT `field`.*, `values`.`value`
FROM #__fields_values AS `values`
JOIN #__fields AS `field` ON `values`.`field_id` = `field`.`id`
WHERE `values`.`item_id` = '.intval($tag->id).' AND `field`.`id` IN ('.implode(', ', $tag->custom).')'
);
$fields = [];
foreach ($rawfields as $field) {
$fields[$field->id][] = $field;
}
usort($fields, function ($a, $b) {
return $a[0]->ordering <=> $b[0]->ordering;
});
foreach ($fields as $fieldValues) {
$value = $this->getFormattedValue($fieldValues);
if (empty($value)) continue;
$customFields[] = [
$value,
$fieldValues[0]->label,
];
}
}
protected function getIntro(string $text): string
{
$pageBreak = null;
$possibleBreaks = [
'',
' ',
'',
];
foreach ($possibleBreaks as $oneBreak) {
if (strpos($text, $oneBreak) !== false) {
$pageBreak = $oneBreak;
break;
}
}
if (empty($pageBreak)) {
return $text;
}
$split = explode($pageBreak, $text, 2);
return array_shift($split);
}
public function displayCustomViewEditor(): void
{
if (empty($this->settings['custom_view']) || !acym_isAdmin()) {
return;
}
echo '';
echo esc_html(acym_translation('ACYM_ADDON_SETTINGS'));
echo '
';
echo '';
$this->displayCustomView($this->settings['custom_view']);
echo '
';
}
public function generateSettings(object $plugin): bool
{
if (empty($plugin->settings)) {
return false;
}
if (array_key_exists('not_installed', $plugin->settings)) {
$plugin->settings = 'not_installed';
return true;
}
foreach ($plugin->settings as $key => $field) {
$text = '';
if (empty($field['type'])) {
$plugin->settings[$key] = $text;
continue;
}
$id = $plugin->folder_name.'_'.$key;
$name = $plugin->folder_name.'['.$key.']';
if (!empty($field['label'])) {
$field['label'] = acym_translation($field['label']);
}
if (!empty($field['info'])) {
ob_start();
acym_info(
[
'textShownInTooltip' => acym_translation($field['info']),
'classText' => 'wysid_tooltip',
'isWarning' => !empty($field['info_warning']),
]
);
$field['label'] .= ob_get_clean();
}
if ($field['type'] === 'checkbox') {
$classLabel = 'shrink';
$text .= ''.esc_html($field['label']).' ';
$text .= ' ';
} elseif ($field['type'] === 'switch') {
ob_start();
acym_switch([
'name' => $name,
'value' => $field['value'],
'label' => $field['label'],
'labelClass' => 'large-7',
]);
$text .= ob_get_clean();
} elseif ($field['type'] === 'select') {
$text .= ''.$field['label'].' ';
$text .= acym_select(
$field['data'],
$name,
$field['value'],
['class' => 'acym__select'],
'value',
'text',
false,
true
);
} elseif ($field['type'] === 'multiple_select') {
$text .= ''.$field['label'].' ';
$text .= acym_selectMultiple(
$field['data'],
$name,
empty($field['value']) ? [] : $field['value'],
['class' => 'acym__select']
);
} elseif ($field['type'] === 'text') {
$text .= ''.$field['label'].' ';
$text .= ' ';
} elseif ($field['type'] === 'number') {
$text .= ''.$field['label'].' ';
$text .= ' ';
if (!empty($field['post_text'])) $text .= ''.strtolower($field['post_text']).' ';
} elseif ($field['type'] === 'radio') {
$text .= ''.$field['label'].'
';
ob_start();
acym_radio(
$field['data'],
$name,
$field['value']
);
$text .= ob_get_clean();
} elseif ($field['type'] === 'date') {
$text .= ''.$field['label'].' ';
$text .= acym_dateField(
$name,
$field['value'],
'cell shrink'
);
} elseif ($field['type'] === 'custom_view') {
ob_start();
$this->displayCustomView($field);
$text .= ob_get_clean();
} elseif ($field['type'] === 'multikeyvalue') {
$text .= ''.$field['label'].' ';
$text .= '';
} elseif ($field['type'] === 'custom') {
$text .= $field['content'];
}
$plugin->settings[$key] = $text;
}
return true;
}
protected function displayCustomView(array $field): void
{
if (!acym_isAdmin()) {
return;
}
$idCustomView = 'acym__plugins__installed__custom-view__'.$this->name;
$ctrl = acym_getVar('string', 'ctrl', '');
$classTooltip = $ctrl === 'dynamics' ? '' : 'wysid_tooltip';
echo '';
echo esc_html(acym_translation('ACYM_CUSTOM_VIEW'));
acym_info(
[
'textShownInTooltip' => 'ACYM_CUSTOM_VIEW_DESC',
'classText' => $classTooltip,
]
);
echo ' ';
if (empty($field['tags'])) {
$field['tags'] = [];
}
ob_start();
acym_info(
[
'textShownInTooltip' => acym_translation('ACYM_DYNAMIC_CONTENT_DESC'),
]
);
$tooltip = ob_get_clean();
$modalContent = '
'.esc_html(acym_translationSprintf('ACYM_CUSTOM_VIEW_FOR_X', $this->pluginDescription->name)).'
'.acym_fileGetContent(ACYM_IMAGES.'logos/logo_grey.svg').'
'.esc_html(acym_translation('ACYM_RESET_VIEW')).'
{{ messageDeleted }}
{{ messageSaved }}
'.esc_html(acym_translation('ACYM_SAVE_NEW_CUSTOM_VIEW_VERSION')).'
';
acym_modal(
acym_translation('ACYM_EDIT_CUSTOM_VIEW'),
$modalContent,
null,
[
'acym-data-plugins-id' => $idCustomView,
'acym-data-plugin-class' => get_class($this),
'acym-data-plugin-folder' => $this->name,
],
['class' => 'cell button']
);
}
/**
* Called using ajax
*
* @param string $css This attribute is the name of the file in the folder css of the plugin OR it can be raw CSS
*/
public function loadCSS(string $css, bool $raw = false, ?string $path = null): void
{
if (!$raw) {
if (empty($path)) $path = ACYM_DYNAMICS_URL.$this->name;
$css = $path.'/css/'.$css.'.css';
}
acym_addStyle($raw, $css);
}
/**
* @param string $js This attribute is the name of the file in the folder js of the plugin OR it can be raw Javascript
*/
public function loadJavascript(string $js, bool $raw = false, ?string $path = null): void
{
if (!$raw) {
if (empty($path)) $path = ACYM_DYNAMICS_URL.$this->name;
$js = $path.'/js/'.$js.'.js';
}
acym_addScript($raw, $js);
}
public function includeView(string $view, array $data = [], ?string $path = null): string
{
if (empty($path)) {
$path = ACYM_ADDONS_FOLDER_PATH.$this->name.DS.'views'.DS.$view.'.php';
} else {
$path = $path.DS.'views'.DS.$view.'.php';
}
if (!file_exists($path)) {
throw new \Exception(esc_attr(acym_translation('ACYM_NON_EXISTING_PAGE')));
}
ob_start();
include $path;
return ob_get_clean();
}
/**
* This function will parse and show all settings
*/
public function onAcymAddSettings(array &$plugins): void
{
if (method_exists($this, 'initSettings')) {
$this->initSettings();
}
foreach ($plugins as $key => $plugin) {
if ($plugin->folder_name === $this->name) {
if (!empty($plugin->settings)) {
foreach ($plugin->settings as $keySettings => $value) {
if (isset($this->settings[$keySettings]['value'])) {
$this->settings[$keySettings]['value'] = $plugin->settings[$keySettings]['value'];
}
}
}
$plugins[$key]->settings = $this->settings;
$this->generateSettings($plugins[$key]);
break;
}
}
}
/**
* @param mixed $default
*
* @return mixed
*/
protected function getParam(string $name, $default = '')
{
return $this->savedSettings[$name]['value'] ?? $default;
}
protected function getTranslationId(int $elementId, string $translationTool, bool $defaultLanguage = false)
{
return $elementId;
}
public function filterSpecialMailsDailySend(array &$specialMails, int $time, string $mailType): void
{
// Only once a day
$dailyHour = $this->config->get('daily_hour', '12');
$dailyMinute = $this->config->get('daily_minute', '00');
// The day it is currently based on the timezone specified in the CMS configuration
$dayBasedOnCMSTimezone = acym_date('now', 'Y-m-d');
// The UTC timestamp of the current day based on the CMS timezone, at the specified hour
$dayBasedOnCMSTimezoneAtSpecifiedHour = acym_getTimeFromCMSDate($dayBasedOnCMSTimezone.' '.$dailyHour.':'.$dailyMinute);
$campaignClass = new CampaignClass();
$tmpMails = [];
foreach ($specialMails as $oneMail) {
if ($oneMail->sending_type === $mailType) {
$noNextTrigger = empty($oneMail->next_trigger);
$nextTriggerIsNow = gmdate('m-d', $oneMail->next_trigger) == gmdate('m-d', $dayBasedOnCMSTimezoneAtSpecifiedHour);
$nextTriggerIsInPast = $oneMail->next_trigger < $time;
if ($time >= $dayBasedOnCMSTimezoneAtSpecifiedHour && ($noNextTrigger || $nextTriggerIsNow || $nextTriggerIsInPast)) {
$oneMail->next_trigger = acym_getTime('tomorrow '.$dailyHour.':'.$dailyMinute);
$oneMail->last_generated = $time;
$campaignClass->save($oneMail);
$tmpMails[] = $oneMail;
}
} else {
$tmpMails[] = $oneMail;
}
}
$specialMails = $tmpMails;
}
protected function getIdsSelectAjax(): array
{
$ids = acym_getVar('string', 'id');
if (empty($ids)) {
return [];
}
$ids = explode(',', $ids);
acym_arrayToInteger($ids);
return $ids;
}
protected function cleanExtensionContent(string $text)
{
if (ACYM_CMS === 'wordpress') {
if (!acym_isExtensionActive('classic-editor/classic-editor.php') || strpos($text, '(.*)#Uis', '$1', $content);
}
protected function fixDivStructure(string $text): string
{
$nbOpeningDivs = substr_count($text, '');
if ($nbOpeningDivs > $nbClosingDivs) {
$text .= str_repeat('
', $nbOpeningDivs - $nbClosingDivs);
} elseif ($nbOpeningDivs < $nbClosingDivs) {
$text = str_repeat('', $nbClosingDivs - $nbOpeningDivs).$text;
}
return $text;
}
protected function getBounceAddress(object $mailerHelper): string
{
if (method_exists($mailerHelper, 'getSendSettings')) {
return $mailerHelper->getSendSettings('bounce_email');
} else {
return $this->config->get('bounce_email');
}
}
}