| @@ -8,8 +8,13 @@ | ||
| 8 | 8 | use Joomla\CMS\HTML\HTMLHelper; |
| 9 | 9 | |
| 10 | 10 | class AcymPlugin extends AcymObject |
| 11 | 11 | { |
| 12 | + // The row placeholders are replaced by the JS when a row is added to the form | |
| 13 | + const CONDITION_FIELD_NAME = 'acym_condition[conditions][__numor__][__numand__]'; | |
| 14 | + const FILTER_FIELD_NAME = 'acym_action[filters][__numor__][__numand__]'; | |
| 15 | + const MAILBOX_ACTION_FIELD_NAME = 'acym_action[__num__]'; | |
| 16 | + | |
| 12 | 17 | public string $cms = 'all'; |
| 13 | 18 | public string $name = ''; |
| 14 | 19 | public bool $installed = true; |
| 15 | 20 | |
| @@ -57,8 +62,14 @@ | ||
| 57 | 62 | private bool $active; |
| 58 | 63 | public array $settings = []; |
| 59 | 64 | private array $savedSettings = []; |
| 60 | 65 | |
| 66 | + public array $automationTriggers = []; | |
| 67 | + public array $automationActions = []; | |
| 68 | + public array $automationConditions = []; | |
| 69 | + public array $automationFilters = []; | |
| 70 | + public array $mailboxActions = []; | |
| 71 | + | |
| 61 | 72 | public function __construct() |
| 62 | 73 | { |
| 63 | 74 | parent::__construct(); |
| 64 | 75 | |
| @@ -335,9 +346,13 @@ | ||
| 335 | 346 | $options[] = [ |
| 336 | 347 | 'title' => 'ACYM_DOCUMENTATION', |
| 337 | 348 | 'type' => 'custom', |
| 338 | 349 | 'name' => 'documentation', |
| 339 | - 'output' => '<a target="_blank" href="'.ACYM_DOCUMENTATION.'main-pages/campaigns/automatic-campaigns#dont-send-twice-the-same-content"><i class="acymicon-book"></i></a>', | |
| 350 | + 'output' => static function (): void { | |
| 351 | + echo '<a target="_blank" href="'.esc_url( | |
| 352 | + ACYM_DOCUMENTATION.'main-pages/campaigns/automatic-campaigns#dont-send-twice-the-same-content' | |
| 353 | + ).'"><i class="acymicon-book"></i></a>'; | |
| 354 | + }, | |
| 340 | 355 | 'js' => '', |
| 341 | 356 | 'section' => 'ACYM_AUTO_CAMPAIGNS_OPTIONS', |
| 342 | 357 | ]; |
| 343 | 358 | |
| @@ -789,16 +804,231 @@ | ||
| 789 | 804 | // Resize/remove pictures if needed |
| 790 | 805 | return $this->pluginHelper->managePicts($insertionOptions, $htmlResult); |
| 791 | 806 | } |
| 792 | 807 | |
| 808 | + /** | |
| 809 | + * Keep this method untyped until v12 | |
| 810 | + */ | |
| 811 | + public function onAcymDeclareTriggers(&$triggers, &$defaultValues) | |
| 812 | + { | |
| 813 | + if (empty($this->automationTriggers) && method_exists($this, 'initAutomationTriggers')) { | |
| 814 | + $this->initAutomationTriggers(); | |
| 815 | + } | |
| 816 | + | |
| 817 | + foreach ($this->automationTriggers as $group => $groupTriggers) { | |
| 818 | + foreach ($groupTriggers as $key => $name) { | |
| 819 | + $triggers[$group][$key] = $this->declareTrigger($key, $name, $defaultValues, $group); | |
| 820 | + } | |
| 821 | + } | |
| 822 | + } | |
| 823 | + | |
| 824 | + /** | |
| 825 | + * Keep this method untyped until v12 | |
| 826 | + */ | |
| 827 | + public function onAcymDeclareTriggersScenario(&$triggers, &$defaultValues) | |
| 828 | + { | |
| 829 | + $this->onAcymDeclareTriggers($triggers, $defaultValues); | |
| 830 | + } | |
| 831 | + | |
| 832 | + /** | |
| 833 | + * Declares name and options callbacks for automation/scenario triggers | |
| 834 | + */ | |
| 835 | + protected function declareTrigger(string $key, string $name, $defaultValues = [], string $group = 'user'): object | |
| 836 | + { | |
| 837 | + $trigger = new \stdClass(); | |
| 838 | + $trigger->name = $name; | |
| 839 | + | |
| 840 | + if (!is_array($defaultValues)) { | |
| 841 | + $defaultValues = []; | |
| 842 | + } | |
| 843 | + | |
| 844 | + $method = 'displayTriggerOptions_'.$key; | |
| 845 | + if (!method_exists($this, $method)) { | |
| 846 | + $method = 'displayTriggerOptions'; | |
| 847 | + } | |
| 848 | + | |
| 849 | + if (method_exists($this, $method)) { | |
| 850 | + $automationFieldName = '[triggers]['.$group.']['.$key.']'; | |
| 851 | + $trigger->displayOptions = function (?string $fieldName = null) use ($method, $defaultValues, $key, $automationFieldName): void { | |
| 852 | + $this->$method($fieldName === null ? $automationFieldName : $fieldName, $defaultValues, $key); | |
| 853 | + }; | |
| 854 | + } | |
| 855 | + | |
| 856 | + return $trigger; | |
| 857 | + } | |
| 858 | + | |
| 859 | + public function onAcymDeclareActions(array &$actions): void | |
| 860 | + { | |
| 861 | + if (empty($this->automationActions) && method_exists($this, 'initAutomationActions')) { | |
| 862 | + $this->initAutomationActions(); | |
| 863 | + } | |
| 864 | + | |
| 865 | + foreach ($this->automationActions as $key => $name) { | |
| 866 | + $actions[$key] = $this->declareAction($key, $name); | |
| 867 | + } | |
| 868 | + } | |
| 869 | + | |
| 870 | + public function onAcymDeclareActionsScenario(array &$actions): void | |
| 871 | + { | |
| 872 | + $this->onAcymDeclareActions($actions); | |
| 873 | + } | |
| 874 | + | |
| 875 | + /** | |
| 876 | + * Declares name and options callbacks for an automation/scenario action | |
| 877 | + */ | |
| 878 | + protected function declareAction(string $key, string $name): object | |
| 879 | + { | |
| 880 | + $action = new \stdClass(); | |
| 881 | + $action->name = $name; | |
| 882 | + | |
| 883 | + $method = 'displayActionOptions_'.$key; | |
| 884 | + if (!method_exists($this, $method)) { | |
| 885 | + $method = 'displayActionOptions'; | |
| 886 | + } | |
| 887 | + | |
| 888 | + if (method_exists($this, $method)) { | |
| 889 | + $action->displayOptions = function () use ($method, $key): void { | |
| 890 | + $this->$method($key); | |
| 891 | + }; | |
| 892 | + } | |
| 893 | + | |
| 894 | + return $action; | |
| 895 | + } | |
| 896 | + | |
| 897 | + public function onAcymDeclareConditions(array &$conditions): void | |
| 898 | + { | |
| 899 | + if (empty($this->automationConditions) && method_exists($this, 'initAutomationConditions')) { | |
| 900 | + $this->initAutomationConditions(); | |
| 901 | + } | |
| 902 | + | |
| 903 | + foreach ($this->automationConditions as $group => $groupConditions) { | |
| 904 | + foreach ($groupConditions as $key => $name) { | |
| 905 | + $conditions[$group][$key] = $this->declareCondition($key, $name); | |
| 906 | + } | |
| 907 | + } | |
| 908 | + } | |
| 909 | + | |
| 910 | + public function onAcymDeclareConditionsScenario(array &$conditions): void | |
| 911 | + { | |
| 912 | + $this->onAcymDeclareConditions($conditions); | |
| 913 | + } | |
| 914 | + | |
| 915 | + public function onAcymDeclareFilters(array &$filters): void | |
| 916 | + { | |
| 917 | + if (empty($this->automationFilters) && method_exists($this, 'initAutomationFilters')) { | |
| 918 | + $this->initAutomationFilters(); | |
| 919 | + } | |
| 920 | + | |
| 921 | + foreach ($this->automationFilters as $key => $name) { | |
| 922 | + $filters[$key] = $this->declareFilter($key, $name); | |
| 923 | + } | |
| 924 | + } | |
| 925 | + | |
| 926 | + /** | |
| 927 | + * Returns a field name without its acym_condition / acym_action prefix. | |
| 928 | + */ | |
| 929 | + protected function getFieldNameWithoutPrefix(string $fieldName): string | |
| 930 | + { | |
| 931 | + return str_replace(['acym_condition', 'acym_action'], '', $fieldName); | |
| 932 | + } | |
| 933 | + | |
| 934 | + protected function declareCondition(string $key, string $name): object | |
| 935 | + { | |
| 936 | + $condition = new \stdClass(); | |
| 937 | + $condition->name = $name; | |
| 938 | + | |
| 939 | + $renderer = $this->getOptionsRenderer('displayConditionOptions', $key, self::CONDITION_FIELD_NAME.'['.$key.']'); | |
| 940 | + if ($renderer !== null) { | |
| 941 | + $condition->displayOptions = $renderer; | |
| 942 | + } | |
| 943 | + | |
| 944 | + return $condition; | |
| 945 | + } | |
| 946 | + | |
| 947 | + public function onAcymMailboxActionDefine(&$actions) | |
| 948 | + { | |
| 949 | + if (empty($this->mailboxActions) && method_exists($this, 'initMailboxActions')) { | |
| 950 | + $this->initMailboxActions(); | |
| 951 | + } | |
| 952 | + | |
| 953 | + foreach ($this->mailboxActions as $key => $name) { | |
| 954 | + $actions[$key] = $this->declareMailboxAction($key, $name); | |
| 955 | + } | |
| 956 | + } | |
| 957 | + | |
| 958 | + /** | |
| 959 | + * A follow-up condition row: a translated sentence holding the selectors the add-on built. | |
| 960 | + */ | |
| 961 | + protected function followupConditionRow(string $translationKey, string ...$fields): callable | |
| 962 | + { | |
| 963 | + return static function () use ($translationKey, $fields): void { | |
| 964 | + echo acym_translationSprintf($translationKey, ...$fields); | |
| 965 | + }; | |
| 966 | + } | |
| 967 | + | |
| 968 | + protected function declareMailboxAction(string $key, string $name): object | |
| 969 | + { | |
| 970 | + $action = new \stdClass(); | |
| 971 | + $action->name = $name; | |
| 972 | + | |
| 973 | + $renderer = $this->getOptionsRenderer('displayMailboxActionOptions', $key, self::MAILBOX_ACTION_FIELD_NAME.'['.$key.']'); | |
| 974 | + if ($renderer !== null) { | |
| 975 | + $action->displayOptions = $renderer; | |
| 976 | + } | |
| 977 | + | |
| 978 | + return $action; | |
| 979 | + } | |
| 980 | + | |
| 981 | + protected function declareFilter(string $key, string $name): object | |
| 982 | + { | |
| 983 | + $filter = new \stdClass(); | |
| 984 | + $filter->name = $name; | |
| 985 | + | |
| 986 | + $renderer = $this->getOptionsRenderer('displayFilterOptions', $key, self::FILTER_FIELD_NAME.'['.$key.']'); | |
| 987 | + if ($renderer !== null) { | |
| 988 | + $filter->displayOptions = $renderer; | |
| 989 | + } | |
| 990 | + | |
| 991 | + return $filter; | |
| 992 | + } | |
| 993 | + | |
| 994 | + /** | |
| 995 | + * Builds the callback that displays the option fields of a declaration. | |
| 996 | + */ | |
| 997 | + private function getOptionsRenderer(string $methodPrefix, string $key, string $defaultFieldName): ?callable | |
| 998 | + { | |
| 999 | + $method = $methodPrefix.'_'.$key; | |
| 1000 | + if (!method_exists($this, $method)) { | |
| 1001 | + $method = $methodPrefix; | |
| 1002 | + } | |
| 1003 | + | |
| 1004 | + if (!method_exists($this, $method)) { | |
| 1005 | + return null; | |
| 1006 | + } | |
| 1007 | + | |
| 1008 | + return function (?string $fieldName = null) use ($method, $key, $defaultFieldName): void { | |
| 1009 | + $this->$method($fieldName === null ? $defaultFieldName : $fieldName, $key); | |
| 1010 | + }; | |
| 1011 | + } | |
| 1012 | + | |
| 1013 | + /** | |
| 1014 | + * Most add-ons offer the same choices as conditions and as filters, the only difference being the name the fields are nested under | |
| 1015 | + */ | |
| 793 | 1016 | protected function filtersFromConditions(array &$filters): void |
| 794 | 1017 | { |
| 795 | - $newFilters = []; | |
| 1018 | + $conditions = []; | |
| 1019 | + $this->onAcymDeclareConditions($conditions); | |
| 796 | 1020 | |
| 797 | - $this->onAcymDeclareConditions($newFilters); | |
| 798 | - foreach ($newFilters as $oneType) { | |
| 799 | - foreach ($oneType as $oneFilterName => $oneFilter) { | |
| 800 | - if (!empty($oneFilter->option)) $oneFilter->option = str_replace(['acym_condition', '[conditions]'], ['acym_action', '[filters]'], $oneFilter->option); | |
| 1021 | + foreach ($conditions as $oneGroup) { | |
| 1022 | + foreach ($oneGroup as $oneFilterName => $oneFilter) { | |
| 1023 | + $renderer = $this->getOptionsRenderer('displayConditionOptions', $oneFilterName, self::FILTER_FIELD_NAME.'['.$oneFilterName.']'); | |
| 1024 | + if ($renderer !== null) { | |
| 1025 | + $oneFilter->displayOptions = $renderer; | |
| 1026 | + } elseif (!empty($oneFilter->option)) { | |
| 1027 | + // TODO: remove this on version 12, only there for retro-compat of add-ons/plugins not updated along with AcyMailing | |
| 1028 | + $oneFilter->option = str_replace(['acym_condition', '[conditions]'], ['acym_action', '[filters]'], $oneFilter->option); | |
| 1029 | + } | |
| 1030 | + | |
| 801 | 1031 | $filters[$oneFilterName] = $oneFilter; |
| 802 | 1032 | } |
| 803 | 1033 | } |
| 804 | 1034 | } |
| @@ -1119,14 +1349,9 @@ | ||
| 1119 | 1349 | } |
| 1120 | 1350 | |
| 1121 | 1351 | public function displayCustomViewEditor(): void |
| 1122 | 1352 | { |
| 1123 | - $plugin = new \stdClass(); | |
| 1124 | - $plugin->folder_name = $this->name; | |
| 1125 | - $plugin->settings = $this->settings; | |
| 1126 | - $this->generateSettings($plugin); | |
| 1127 | - | |
| 1128 | - if (empty($plugin->settings['custom_view'])) { | |
| 1353 | + if (empty($this->settings['custom_view']) || !acym_isAdmin()) { | |
| 1129 | 1354 | return; |
| 1130 | 1355 | } |
| 1131 | 1356 | |
| 1132 | 1357 | echo '<p class="acym__wysid__right__toolbar__p acym__wysid__right__toolbar__p__open acym__title">'; |
| @@ -1132,9 +1357,9 @@ | ||
| 1132 | 1357 | echo '<p class="acym__wysid__right__toolbar__p acym__wysid__right__toolbar__p__open acym__title">'; |
| 1133 | 1358 | echo esc_html(acym_translation('ACYM_ADDON_SETTINGS')); |
| 1134 | 1359 | echo '<i class="acymicon-keyboard-arrow-up"></i></p>'; |
| 1135 | 1360 | echo '<div class="acym__wysid__right__toolbar__design--show acym__wysid__right__toolbar__design acym__wysid__context__modal__container">'; |
| 1136 | - echo $plugin->settings['custom_view']; | |
| 1361 | + $this->displayCustomView($this->settings['custom_view']); | |
| 1137 | 1362 | echo '</div>'; |
| 1138 | 1363 | } |
| 1139 | 1364 | |
| 1140 | 1365 | public function generateSettings(object $plugin): bool |
| @@ -1176,9 +1401,9 @@ | ||
| 1176 | 1401 | |
| 1177 | 1402 | if ($field['type'] === 'checkbox') { |
| 1178 | 1403 | $classLabel = 'shrink'; |
| 1179 | 1404 | $text .= '<label for="'.esc_attr($id).'" class="cell '.esc_attr($classLabel).'">'.esc_html($field['label']).'</label>'; |
| 1180 | - $text .= '<input id="'.esc_attr($id).'" class="cell shrink" type="checkbox" name="'.esc_attr($name).'" '.acym_checked( | |
| 1405 | + $text .= '<input id="'.esc_attr($id).'" class="cell shrink" type="checkbox" name="'.esc_attr($name).'" '.checked( | |
| 1181 | 1406 | !empty($field['value']), |
| 1182 | 1407 | true, |
| 1183 | 1408 | false |
| 1184 | 1409 | ).'>'; |
| @@ -1233,83 +1458,13 @@ | ||
| 1233 | 1458 | $name, |
| 1234 | 1459 | $field['value'], |
| 1235 | 1460 | 'cell shrink' |
| 1236 | 1461 | ); |
| 1237 | - } elseif ($field['type'] === 'custom_view' && acym_isAdmin()) { | |
| 1238 | - $idCustomView = 'acym__plugins__installed__custom-view__'.$this->name; | |
| 1239 | - $ctrl = acym_getVar('string', 'ctrl', ''); | |
| 1240 | - $classTooltip = $ctrl === 'dynamics' ? '' : 'wysid_tooltip'; | |
| 1241 | - $text .= '<label class="cell">'; | |
| 1242 | - $text .= acym_translation('ACYM_CUSTOM_VIEW'); | |
| 1462 | + } elseif ($field['type'] === 'custom_view') { | |
| 1243 | 1463 | ob_start(); |
| 1244 | - acym_info( | |
| 1245 | - [ | |
| 1246 | - 'textShownInTooltip' => 'ACYM_CUSTOM_VIEW_DESC', | |
| 1247 | - 'classText' => $classTooltip, | |
| 1248 | - ] | |
| 1249 | - ); | |
| 1464 | + $this->displayCustomView($field); | |
| 1250 | 1465 | $text .= ob_get_clean(); |
| 1251 | - $text .= '</label>'; | |
| 1252 | - | |
| 1253 | - if (empty($field['tags'])) { | |
| 1254 | - $field['tags'] = []; | |
| 1255 | - } | |
| 1256 | - | |
| 1257 | - ob_start(); | |
| 1258 | - acym_info( | |
| 1259 | - [ | |
| 1260 | - 'textShownInTooltip' => acym_translation('ACYM_DYNAMIC_CONTENT_DESC'), | |
| 1261 | - ] | |
| 1262 | - ); | |
| 1263 | - $tooltip = ob_get_clean(); | |
| 1264 | - | |
| 1265 | - $modalContent = '<div id="'.esc_attr($idCustomView).'" class="cell grid-x acym__plugins__installed__custom-view" acym-data-tags="'.esc_attr( | |
| 1266 | - json_encode($field['tags']) | |
| 1267 | - ).'"> | |
| 1268 | - <h2 class="cell text-center acym__title__primary__color">'.acym_translationSprintf('ACYM_CUSTOM_VIEW_FOR_X', $this->pluginDescription->name).'</h2> | |
| 1269 | - <div class="cell grid-x acym__plugins__installed__custom-view__edit-container"> | |
| 1270 | - <div class="acym__plugins__installed__custom-view__editor-loader grid-x cell align-center acym_vcenter" v-if="loading"> | |
| 1271 | - <div class="cell shrink acym_loader_logo"> | |
| 1272 | - '.acym_fileGetContent(ACYM_IMAGES.'logos/logo_grey.svg').' | |
| 1273 | - </div> | |
| 1274 | - </div> | |
| 1275 | - <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> | |
| 1276 | - <div class="cell grid-x medium-3 margin-left-1 acym__plugins__installed__custom-view__tags"> | |
| 1277 | - <h3 class="acym__title acym__title__secondary cell text-center">'.esc_html(acym_translation('ACYM_DYNAMIC_CONTENT')).$tooltip.'</h3> | |
| 1278 | - <div class="cell acym__plugins__installed__custom-view__tag" v-for="(trad, tag) in tags" :key="tag" @click.prevent="insertTag(tag)">{{ trad }}</div> | |
| 1279 | - </div> | |
| 1280 | - </div> | |
| 1281 | - <div class="cell grid-x acym__plugins__installed__custom-view__actions acym_vcenter margin-top-1 padding-bottom-1"> | |
| 1282 | - <div class="cell auto grid-x"> | |
| 1283 | - <button type="button" class="cell shrink button-secondary button" @click="resetView">'.esc_html(acym_translation('ACYM_RESET_VIEW')).'</button> | |
| 1284 | - <div class="cell shrink margin-right-2 acym_vcenter margin-left-1"> | |
| 1285 | - <i v-if="deleting" class="acymicon-spin acymicon-circle-o-notch" style="margin-bottom: 0; line-height: 26px;"></i> | |
| 1286 | - <span v-if="deleted">{{ messageDeleted }}</span> | |
| 1287 | - </div> | |
| 1288 | - </div> | |
| 1289 | - <div class="cell auto align-right grid-x"> | |
| 1290 | - <div class="cell shrink margin-right-2 acym_vcenter"> | |
| 1291 | - <i v-if="saving" class="acymicon-spin acymicon-circle-o-notch" style="margin-bottom: 0; line-height: 26px;"></i> | |
| 1292 | - <span v-if="saved">{{ messageSaved }}</span> | |
| 1293 | - </div> | |
| 1294 | - <button @click="save()" class="cell shrink button" type="button">'.esc_html(acym_translation('ACYM_SAVE_NEW_CUSTOM_VIEW_VERSION')).'</button> | |
| 1295 | - </div> | |
| 1296 | - </div> | |
| 1297 | - </div>'; | |
| 1298 | - ob_start(); | |
| 1299 | - acym_modal( | |
| 1300 | - acym_translation('ACYM_EDIT_CUSTOM_VIEW'), | |
| 1301 | - $modalContent, | |
| 1302 | - null, | |
| 1303 | - [ | |
| 1304 | - 'acym-data-plugins-id' => $idCustomView, | |
| 1305 | - 'acym-data-plugin-class' => get_class($this), | |
| 1306 | - 'acym-data-plugin-folder' => $this->name, | |
| 1307 | - ], | |
| 1308 | - ['class' => 'cell button'] | |
| 1309 | - ); | |
| 1310 | - $text .= ob_get_clean(); | |
| 1311 | - } elseif ($field['type'] == 'multikeyvalue') { | |
| 1466 | + } elseif ($field['type'] === 'multikeyvalue') { | |
| 1312 | 1467 | $text .= '<label class="cell shrink">'.$field['label'].'</label>'; |
| 1313 | 1468 | |
| 1314 | 1469 | $text .= '<div class="multikeyvalue_container grid-x">'; |
| 1315 | 1470 | |
| @@ -1315,22 +1470,22 @@ | ||
| 1315 | 1470 | |
| 1316 | 1471 | if (!empty($field['value'])) { |
| 1317 | 1472 | $headers = json_decode($field['value'], true); |
| 1318 | 1473 | foreach ($headers as $headerKey => $headerValue) { |
| 1319 | - $text .= '<input type="text" class="cell" placeholder="'.acym_translation('ACYM_DKIM_KEY', true).'" value="'.esc_attr($headerKey).'"/>'; | |
| 1320 | - $text .= '<input type="text" class="cell" placeholder="'.acym_translation('ACYM_VALUE', true).'" value="'.esc_attr($headerValue).'" />'; | |
| 1474 | + $text .= '<input type="text" class="cell" placeholder="'.esc_attr(acym_translation('ACYM_DKIM_KEY')).'" value="'.esc_attr($headerKey).'"/>'; | |
| 1475 | + $text .= '<input type="text" class="cell" placeholder="'.esc_attr(acym_translation('ACYM_VALUE')).'" value="'.esc_attr($headerValue).'" />'; | |
| 1321 | 1476 | $text .= '<div class="multikeyvalue_container_separator cell small-6"></div>'; |
| 1322 | 1477 | } |
| 1323 | 1478 | } |
| 1324 | 1479 | |
| 1325 | - $text .= '<input type="text" class="cell" placeholder="'.acym_translation('ACYM_DKIM_KEY', true).'" value=""/>'; | |
| 1326 | - $text .= '<input type="text" class="cell" placeholder="'.acym_translation('ACYM_VALUE', true).'" value="" />'; | |
| 1480 | + $text .= '<input type="text" class="cell" placeholder="'.esc_attr(acym_translation('ACYM_DKIM_KEY')).'" value=""/>'; | |
| 1481 | + $text .= '<input type="text" class="cell" placeholder="'.esc_attr(acym_translation('ACYM_VALUE')).'" value="" />'; | |
| 1327 | 1482 | |
| 1328 | - $text .= '<button class="button multikeyvalue_container_new">'.acym_translation('ACYM_ADD_NEW').'</button>'; | |
| 1483 | + $text .= '<button class="button multikeyvalue_container_new">'.esc_html(acym_translation('ACYM_ADD_NEW')).'</button>'; | |
| 1329 | 1484 | |
| 1330 | - $text .= '<input type="hidden" name="'.$name.'" value="" />'; | |
| 1485 | + $text .= '<input type="hidden" name="'.esc_attr($name).'" value="" />'; | |
| 1331 | 1486 | $text .= '</div>'; |
| 1332 | - } elseif ($field['type'] == 'custom') { | |
| 1487 | + } elseif ($field['type'] === 'custom') { | |
| 1333 | 1488 | $text .= $field['content']; |
| 1334 | 1489 | } |
| 1335 | 1490 | $plugin->settings[$key] = $text; |
| 1336 | 1491 | } |
| @@ -1335,8 +1490,87 @@ | ||
| 1335 | 1490 | $plugin->settings[$key] = $text; |
| 1336 | 1491 | } |
| 1337 | 1492 | |
| 1338 | 1493 | return true; |
| 1494 | + } | |
| 1495 | + | |
| 1496 | + protected function displayCustomView(array $field): void | |
| 1497 | + { | |
| 1498 | + if (!acym_isAdmin()) { | |
| 1499 | + return; | |
| 1500 | + } | |
| 1501 | + | |
| 1502 | + $idCustomView = 'acym__plugins__installed__custom-view__'.$this->name; | |
| 1503 | + $ctrl = acym_getVar('string', 'ctrl', ''); | |
| 1504 | + $classTooltip = $ctrl === 'dynamics' ? '' : 'wysid_tooltip'; | |
| 1505 | + | |
| 1506 | + echo '<label class="cell">'; | |
| 1507 | + echo esc_html(acym_translation('ACYM_CUSTOM_VIEW')); | |
| 1508 | + acym_info( | |
| 1509 | + [ | |
| 1510 | + 'textShownInTooltip' => 'ACYM_CUSTOM_VIEW_DESC', | |
| 1511 | + 'classText' => $classTooltip, | |
| 1512 | + ] | |
| 1513 | + ); | |
| 1514 | + echo '</label>'; | |
| 1515 | + | |
| 1516 | + if (empty($field['tags'])) { | |
| 1517 | + $field['tags'] = []; | |
| 1518 | + } | |
| 1519 | + | |
| 1520 | + ob_start(); | |
| 1521 | + acym_info( | |
| 1522 | + [ | |
| 1523 | + 'textShownInTooltip' => acym_translation('ACYM_DYNAMIC_CONTENT_DESC'), | |
| 1524 | + ] | |
| 1525 | + ); | |
| 1526 | + $tooltip = ob_get_clean(); | |
| 1527 | + | |
| 1528 | + $modalContent = '<div id="'.esc_attr($idCustomView).'" class="cell grid-x acym__plugins__installed__custom-view" acym-data-tags="'.esc_attr( | |
| 1529 | + json_encode($field['tags']) | |
| 1530 | + ).'"> | |
| 1531 | + <h2 class="cell text-center acym__title__primary__color">'.esc_html(acym_translationSprintf('ACYM_CUSTOM_VIEW_FOR_X', $this->pluginDescription->name)).'</h2> | |
| 1532 | + <div class="cell grid-x acym__plugins__installed__custom-view__edit-container"> | |
| 1533 | + <div class="acym__plugins__installed__custom-view__editor-loader grid-x cell align-center acym_vcenter" v-if="loading"> | |
| 1534 | + <div class="cell shrink acym_loader_logo"> | |
| 1535 | + '.acym_fileGetContent(ACYM_IMAGES.'logos/logo_grey.svg').' | |
| 1536 | + </div> | |
| 1537 | + </div> | |
| 1538 | + <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> | |
| 1539 | + <div class="cell grid-x medium-3 margin-left-1 acym__plugins__installed__custom-view__tags"> | |
| 1540 | + <h3 class="acym__title acym__title__secondary cell text-center">'.esc_html(acym_translation('ACYM_DYNAMIC_CONTENT')).$tooltip.'</h3> | |
| 1541 | + <div class="cell acym__plugins__installed__custom-view__tag" v-for="(trad, tag) in tags" :key="tag" @click.prevent="insertTag(tag)">{{ trad }}</div> | |
| 1542 | + </div> | |
| 1543 | + </div> | |
| 1544 | + <div class="cell grid-x acym__plugins__installed__custom-view__actions acym_vcenter margin-top-1 padding-bottom-1"> | |
| 1545 | + <div class="cell auto grid-x"> | |
| 1546 | + <button type="button" class="cell shrink button-secondary button" @click="resetView">'.esc_html(acym_translation('ACYM_RESET_VIEW')).'</button> | |
| 1547 | + <div class="cell shrink margin-right-2 acym_vcenter margin-left-1"> | |
| 1548 | + <i v-if="deleting" class="acymicon-spin acymicon-circle-o-notch" style="margin-bottom: 0; line-height: 26px;"></i> | |
| 1549 | + <span v-if="deleted">{{ messageDeleted }}</span> | |
| 1550 | + </div> | |
| 1551 | + </div> | |
| 1552 | + <div class="cell auto align-right grid-x"> | |
| 1553 | + <div class="cell shrink margin-right-2 acym_vcenter"> | |
| 1554 | + <i v-if="saving" class="acymicon-spin acymicon-circle-o-notch" style="margin-bottom: 0; line-height: 26px;"></i> | |
| 1555 | + <span v-if="saved">{{ messageSaved }}</span> | |
| 1556 | + </div> | |
| 1557 | + <button @click="save()" class="cell shrink button" type="button">'.esc_html(acym_translation('ACYM_SAVE_NEW_CUSTOM_VIEW_VERSION')).'</button> | |
| 1558 | + </div> | |
| 1559 | + </div> | |
| 1560 | + </div>'; | |
| 1561 | + | |
| 1562 | + acym_modal( | |
| 1563 | + acym_translation('ACYM_EDIT_CUSTOM_VIEW'), | |
| 1564 | + $modalContent, | |
| 1565 | + null, | |
| 1566 | + [ | |
| 1567 | + 'acym-data-plugins-id' => $idCustomView, | |
| 1568 | + 'acym-data-plugin-class' => get_class($this), | |
| 1569 | + 'acym-data-plugin-folder' => $this->name, | |
| 1570 | + ], | |
| 1571 | + ['class' => 'cell button'] | |
| 1572 | + ); | |
| 1339 | 1573 | } |
| 1340 | 1574 | |
| 1341 | 1575 | /** |
| 1342 | 1576 | * Called using ajax |