From d3d1d35980b3e6da1f49c0eeed76654389a404f9 Mon Sep 17 00:00:00 2001 From: Michal Kleiner Date: Sat, 21 Dec 2024 02:35:03 +1300 Subject: [PATCH] Ensure empty plugin settings are saved correctly (#22891) * Send and process empty setting arrays as __empty__ value * Add integration test for an empty settings array --- plugins/CorePluginsAdmin/SettingsMetadata.php | 7 ++++ .../tests/Integration/ApiTest.php | 26 +++++++++++++++ .../vue/dist/CorePluginsAdmin.umd.js | 32 +++++++++++-------- .../vue/dist/CorePluginsAdmin.umd.min.js | 2 +- .../vue/src/PluginSettings/PluginSettings.vue | 4 +++ 5 files changed, 56 insertions(+), 15 deletions(-) diff --git a/plugins/CorePluginsAdmin/SettingsMetadata.php b/plugins/CorePluginsAdmin/SettingsMetadata.php index 96907b7d79b..6afe240ebc3 100644 --- a/plugins/CorePluginsAdmin/SettingsMetadata.php +++ b/plugins/CorePluginsAdmin/SettingsMetadata.php @@ -20,6 +20,8 @@ class SettingsMetadata { public const PASSWORD_PLACEHOLDER = '******'; + public const EMPTY_ARRAY = '__empty__'; + /** * @param Settings[] $settingsInstances * @param array $settingValues array('pluginName' => array('settingName' => 'settingValue')) @@ -34,6 +36,11 @@ public function setPluginSettings($settingsInstances, $settingValues) $fieldConfig = $setting->configureField(); + // empty arrays are sent as __empty__ value, so we need to convert it here back to an array + if ($setting->getType() === FieldConfig::TYPE_ARRAY && $value === self::EMPTY_ARRAY) { + $value = []; + } + if ( isset($value) && ( $fieldConfig->uiControl !== FieldConfig::UI_CONTROL_PASSWORD || diff --git a/plugins/CorePluginsAdmin/tests/Integration/ApiTest.php b/plugins/CorePluginsAdmin/tests/Integration/ApiTest.php index ac7dce821fe..18e2d5f3c7c 100644 --- a/plugins/CorePluginsAdmin/tests/Integration/ApiTest.php +++ b/plugins/CorePluginsAdmin/tests/Integration/ApiTest.php @@ -29,6 +29,12 @@ class ApiTest extends IntegrationTestCase ], ]; + private $testSystemSettingsEmptyValuePayload = [ + 'ExampleSettingsPlugin' => [ + ['name' => 'browsers', 'value' => '__empty__'], + ], + ]; + protected static function beforeTableDataCached() { parent::beforeTableDataCached(); @@ -113,6 +119,26 @@ public function testGetSystemSettingsRedactsPasswordValues() self::assertTrue(password_verify('newPassword', $pluginSettings->getSetting('password')->getValue())); } + public function testSetSystemSettingsCorrectlySetsEmptyValue() + { + $pluginSettings = StaticContainer::get(\Piwik\Plugins\ExampleSettingsPlugin\SystemSettings::class); + $settings = $this->getPluginSettings('ExampleSettingsPlugin', 'browsers'); + $defaultValue = ['firefox', 'chromium', 'safari']; + + self::assertEquals('browsers', $settings['name']); + self::assertEquals($defaultValue, $settings['value']); + self::assertEquals($defaultValue, $pluginSettings->getSetting('browsers')->getValue()); + + $settingValues = $this->testSystemSettingsEmptyValuePayload; + \Piwik\Plugins\CorePluginsAdmin\API::getInstance()->setSystemSettings($settingValues, self::TEST_PASSWORD); + + $newSettings = $this->getPluginSettings('ExampleSettingsPlugin', 'browsers'); + + self::assertEquals('browsers', $newSettings['name']); + self::assertEquals([], $newSettings['value']); + self::assertEquals([], $pluginSettings->getSetting('browsers')->getValue()); + } + private function getPluginSettings(string $pluginName, string $settingName): array { $settings = \Piwik\Plugins\CorePluginsAdmin\API::getInstance()->getSystemSettings(); diff --git a/plugins/CorePluginsAdmin/vue/dist/CorePluginsAdmin.umd.js b/plugins/CorePluginsAdmin/vue/dist/CorePluginsAdmin.umd.js index de81481c5dc..8a5a535d3bc 100644 --- a/plugins/CorePluginsAdmin/vue/dist/CorePluginsAdmin.umd.js +++ b/plugins/CorePluginsAdmin/vue/dist/CorePluginsAdmin.umd.js @@ -17267,34 +17267,34 @@ var UI_CONTROLS_TO_TYPE = { Fieldvue_type_script_lang_ts.render = Fieldvue_type_template_id_5f883444_render /* harmony default export */ var Field = (Fieldvue_type_script_lang_ts); -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CorePluginsAdmin/vue/src/PluginSettings/PluginSettings.vue?vue&type=template&id=919e3cb4 +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CorePluginsAdmin/vue/src/PluginSettings/PluginSettings.vue?vue&type=template&id=601e4fc6 -var PluginSettingsvue_type_template_id_919e3cb4_hoisted_1 = { +var PluginSettingsvue_type_template_id_601e4fc6_hoisted_1 = { class: "pluginSettings", ref: "root" }; -var PluginSettingsvue_type_template_id_919e3cb4_hoisted_2 = ["id"]; -var PluginSettingsvue_type_template_id_919e3cb4_hoisted_3 = { +var PluginSettingsvue_type_template_id_601e4fc6_hoisted_2 = ["id"]; +var PluginSettingsvue_type_template_id_601e4fc6_hoisted_3 = { class: "card-content" }; -var PluginSettingsvue_type_template_id_919e3cb4_hoisted_4 = ["id"]; -var PluginSettingsvue_type_template_id_919e3cb4_hoisted_5 = ["onClick", "disabled", "value"]; -function PluginSettingsvue_type_template_id_919e3cb4_render(_ctx, _cache, $props, $setup, $data, $options) { +var PluginSettingsvue_type_template_id_601e4fc6_hoisted_4 = ["id"]; +var PluginSettingsvue_type_template_id_601e4fc6_hoisted_5 = ["onClick", "disabled", "value"]; +function PluginSettingsvue_type_template_id_601e4fc6_render(_ctx, _cache, $props, $setup, $data, $options) { var _component_GroupedSettings = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("GroupedSettings"); var _component_ActivityIndicator = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("ActivityIndicator"); var _component_PasswordConfirmation = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("PasswordConfirmation"); - return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", PluginSettingsvue_type_template_id_919e3cb4_hoisted_1, [(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(_ctx.settingsPerPlugin, function (settings) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", PluginSettingsvue_type_template_id_601e4fc6_hoisted_1, [(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(_ctx.settingsPerPlugin, function (settings) { return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", { class: "card", id: "".concat(settings.pluginName, "PluginSettings"), key: "".concat(settings.pluginName, "PluginSettings") - }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", PluginSettingsvue_type_template_id_919e3cb4_hoisted_3, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h2", { + }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", PluginSettingsvue_type_template_id_601e4fc6_hoisted_3, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h2", { class: "card-title", id: settings.pluginName - }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(settings.title), 9, PluginSettingsvue_type_template_id_919e3cb4_hoisted_4), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_GroupedSettings, { + }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(settings.title), 9, PluginSettingsvue_type_template_id_601e4fc6_hoisted_4), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_GroupedSettings, { "group-name": settings.pluginName, settings: settings.settings, "all-setting-values": _ctx.settingValues, @@ -17309,9 +17309,9 @@ function PluginSettingsvue_type_template_id_919e3cb4_render(_ctx, _cache, $props disabled: _ctx.isLoading, class: "pluginsSettingsSubmit btn", value: _ctx.translate('General_Save') - }, null, 8, PluginSettingsvue_type_template_id_919e3cb4_hoisted_5), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_ActivityIndicator, { + }, null, 8, PluginSettingsvue_type_template_id_601e4fc6_hoisted_5), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_ActivityIndicator, { loading: _ctx.isLoading || _ctx.isSaving[settings.pluginName] - }, null, 8, ["loading"])])], 8, PluginSettingsvue_type_template_id_919e3cb4_hoisted_2); + }, null, 8, ["loading"])])], 8, PluginSettingsvue_type_template_id_601e4fc6_hoisted_2); }), 128)), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_PasswordConfirmation, { modelValue: _ctx.showPasswordConfirmModal, "onUpdate:modelValue": _cache[0] || (_cache[0] = function ($event) { @@ -17320,7 +17320,7 @@ function PluginSettingsvue_type_template_id_919e3cb4_render(_ctx, _cache, $props onConfirmed: _ctx.confirmPassword }, null, 8, ["modelValue", "onConfirmed"])], 512); } -// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/PluginSettings/PluginSettings.vue?vue&type=template&id=919e3cb4 +// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/PluginSettings/PluginSettings.vue?vue&type=template&id=601e4fc6 // CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CorePluginsAdmin/vue/src/GroupedSettings/GroupedSettings.vue?vue&type=template&id=566a93cc @@ -17807,6 +17807,10 @@ var PluginSettingsvue_type_script_lang_ts_window = window, postValue = '1'; } + if (Array.isArray(postValue) && postValue.length === 0) { + postValue = '__empty__'; + } + values[pluginName].push({ name: settingName, value: postValue @@ -17822,7 +17826,7 @@ var PluginSettingsvue_type_script_lang_ts_window = window, -PluginSettingsvue_type_script_lang_ts.render = PluginSettingsvue_type_template_id_919e3cb4_render +PluginSettingsvue_type_script_lang_ts.render = PluginSettingsvue_type_template_id_601e4fc6_render /* harmony default export */ var PluginSettings = (PluginSettingsvue_type_script_lang_ts); // CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/Plugins/PluginFilter.ts diff --git a/plugins/CorePluginsAdmin/vue/dist/CorePluginsAdmin.umd.min.js b/plugins/CorePluginsAdmin/vue/dist/CorePluginsAdmin.umd.min.js index 67cd1775982..e0380c67b2c 100644 --- a/plugins/CorePluginsAdmin/vue/dist/CorePluginsAdmin.umd.min.js +++ b/plugins/CorePluginsAdmin/vue/dist/CorePluginsAdmin.umd.min.js @@ -4,7 +4,7 @@ * * @link https://matomo.org * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */function Xs(e,t){if(!e)return[];var n=[];return Object.entries(e).forEach((function(e){var r=Ws(e,2),o=r[0],i=r[1];if(i&&"object"===zs(i)&&"undefined"!==typeof i.key)n.push(i);else{var a=o;"integer"===t&&"string"===typeof o&&(a=parseInt(a,10)),n.push({key:a,value:i})}})),n}function Qs(e){return Qs="function"===typeof Symbol&&"symbol"===typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"===typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Qs(e)}var el=["password","url","search","email"],tl=["textarea","checkbox","text"],nl={checkbox:"FieldCheckbox","expandable-select":"FieldExpandableSelect","field-array":"FieldFieldArray",file:"FieldFile",hidden:"FieldHidden",multiselect:"FieldSelect",multituple:"FieldMultituple",number:"FieldNumber",radio:"FieldRadio",select:"FieldSelect",site:"FieldSite",text:"FieldText",textarea:"FieldTextarea"},rl={FieldSelect:ms,FieldCheckboxArray:Xs,FieldRadio:Xs,FieldExpandableSelect:oa},ol=Object(Oi["defineComponent"])({props:{modelValue:null,modelModifiers:Object,formField:{type:Object,required:!0}},emits:["update:modelValue"],components:{FieldCheckbox:Mi,FieldCheckboxArray:zi,FieldExpandableSelect:aa,FieldFieldArray:ua,FieldFile:ya,FieldHidden:wa,FieldMultituple:Ca,FieldNumber:Pa,FieldRadio:Fa,FieldSelect:bs,FieldSite:ws,FieldText:Cs,FieldTextArray:Ps,FieldTextarea:Fs,FieldTextareaArray:Rs},setup:function(e){var t=Object(Oi["ref"])(null),n=function(e){var n;e&&t.value&&"function"!==typeof e.render&&(n="string"===typeof e?0===e.indexOf("#")?window.$(e):window.vueSanitize(e):e,window.$(t.value).html("").append(n))};return Object(Oi["watch"])((function(){return e.formField.inlineHelp}),n),Object(Oi["onMounted"])((function(){n(e.formField.inlineHelp)})),{inlineHelp:t}},computed:{inlineHelpComponent:function(){var e=this.formField,t=e.inlineHelp;if(t&&"function"===typeof t.render)return e.inlineHelp},inlineHelpBind:function(){return this.inlineHelpComponent?this.formField.inlineHelpBind:void 0},childComponent:function(){var e=this.formField;if(e.component){var t=e.component;if(e.component.plugin){var n=e.component,r=n.plugin,o=n.name;if(!r||!o)throw new Error("Invalid component property given to FormField directive, must be {plugin: '...',name: '...'}");t=Object(Ci["useExternalPluginComponent"])(r,o)}return Object(Oi["markRaw"])(t)}var i=e.uiControl,a=nl[i];return-1!==el.indexOf(i)&&(a="FieldText"),"array"===this.formField.type&&-1!==tl.indexOf(i)&&(a="".concat(a,"Array")),a},extraChildComponentParams:function(){return"multiselect"===this.formField.uiControl?{multiple:!0}:{}},showFormHelp:function(){return this.formField.description||this.formField.inlineHelp||this.showDefaultValue||this.hasInlineHelpSlot},showDefaultValue:function(){return this.defaultValuePretty&&"checkbox"!==this.formField.uiControl&&"radio"!==this.formField.uiControl},processedModelValue:function(){var e=this.formField;if("boolean"===e.type){var t=this.modelValue&&this.modelValue>0&&"0"!==this.modelValue;if("checkbox"===e.uiControl)return t;if("radio"===e.uiControl)return t?"1":"0"}return this.modelValue},defaultValue:function(){var e=this.formField.defaultValue;return Array.isArray(e)?e.join(","):e},availableOptions:function(){var e=this.childComponent;if("string"!==typeof e)return null;var t=this.formField;return t.availableValues&&rl[e]?rl[e](t.availableValues,t.type,t.uiControlAttributes):null},defaultValuePretty:function(){var e=this.formField,t=e.defaultValue,n=this.availableOptions;if("string"===typeof t&&t){var r=null;try{r=JSON.parse(t)}catch(i){}if(null!==r&&"object"===Qs(r))return""}if(!Array.isArray(n))return Array.isArray(t)?"":t?"".concat(t):"";var o=[];return Array.isArray(t)||(t=[t]),(n||[]).forEach((function(e){"undefined"!==typeof e.value&&-1!==t.indexOf(e.key)&&o.push(e.value)})),o.join(", ")},defaultValuePrettyTruncated:function(){return this.defaultValuePretty.substring(0,50)},hasInlineHelpSlot:function(){var e,t;if(!this.$slots["inline-help"])return!1;var n=this.$slots["inline-help"]();return!(null===n||void 0===n||null===(e=n[0])||void 0===e||null===(t=e.children)||void 0===t||!t.length)}},methods:{onChange:function(e){this.$emit("update:modelValue",e)}}});ol.render=Ei;var il=ol;function al(e,t,n,r,o,i){var a=Object(Oi["resolveComponent"])("FormField");return Object(Oi["openBlock"])(),Object(Oi["createBlock"])(a,{"form-field":e.field,"model-value":e.modelValue,"onUpdate:modelValue":t[0]||(t[0]=function(t){return e.onChange(t)}),"model-modifiers":e.modelModifiers},{"inline-help":Object(Oi["withCtx"])((function(){return[Object(Oi["renderSlot"])(e.$slots,"inline-help")]})),_:3},8,["form-field","model-value","model-modifiers"])}var sl={multiselect:"array",checkbox:"boolean",site:"object",number:"integer"},ll=Object(Oi["defineComponent"])({props:{modelValue:null,modelModifiers:Object,uicontrol:String,name:String,defaultValue:null,options:[Object,Array],description:String,introduction:String,title:String,inlineHelp:[String,Object],inlineHelpBind:Object,disabled:Boolean,uiControlAttributes:{type:Object,default:function(){return{}}},uiControlOptions:{type:Object,default:function(){return{}}},autocomplete:String,varType:String,autofocus:Boolean,tabindex:Number,fullWidth:Boolean,maxlength:Number,required:Boolean,placeholder:String,rows:Number,min:Number,max:Number,component:null},emits:["update:modelValue"],components:{FormField:il},computed:{type:function(){if(this.varType)return this.varType;var e=this.uicontrol;return e&&sl[e]?sl[e]:"string"},field:function(){return{uiControl:this.uicontrol,type:this.type,name:this.name,defaultValue:this.defaultValue,availableValues:this.options,description:this.description,introduction:this.introduction,inlineHelp:this.inlineHelp,inlineHelpBind:this.inlineHelpBind,title:this.title,component:this.component,uiControlAttributes:Object.assign(Object.assign({},this.uiControlAttributes),{},{disabled:this.disabled,autocomplete:this.autocomplete,tabindex:this.tabindex,autofocus:this.autofocus,rows:this.rows,required:this.required,maxlength:this.maxlength,placeholder:this.placeholder,min:this.min,max:this.max}),fullWidth:this.fullWidth,uiControlOptions:this.uiControlOptions}}},methods:{onChange:function(e){this.$emit("update:modelValue",e)}}});ll.render=al;var cl=ll,ul={class:"pluginSettings",ref:"root"},pl=["id"],dl={class:"card-content"},fl=["id"],ml=["onClick","disabled","value"];function hl(e,t,n,r,o,i){var a=Object(Oi["resolveComponent"])("GroupedSettings"),s=Object(Oi["resolveComponent"])("ActivityIndicator"),l=Object(Oi["resolveComponent"])("PasswordConfirmation");return Object(Oi["openBlock"])(),Object(Oi["createElementBlock"])("div",ul,[(Object(Oi["openBlock"])(!0),Object(Oi["createElementBlock"])(Oi["Fragment"],null,Object(Oi["renderList"])(e.settingsPerPlugin,(function(t){return Object(Oi["openBlock"])(),Object(Oi["createElementBlock"])("div",{class:"card",id:"".concat(t.pluginName,"PluginSettings"),key:"".concat(t.pluginName,"PluginSettings")},[Object(Oi["createElementVNode"])("div",dl,[Object(Oi["createElementVNode"])("h2",{class:"card-title",id:t.pluginName},Object(Oi["toDisplayString"])(t.title),9,fl),Object(Oi["createVNode"])(a,{"group-name":t.pluginName,settings:t.settings,"all-setting-values":e.settingValues,onChange:function(n){return e.settingValues["".concat(t.pluginName,".").concat(n.name)]=n.value}},null,8,["group-name","settings","all-setting-values","onChange"]),Object(Oi["createElementVNode"])("input",{type:"button",onClick:function(n){return e.saveSetting(t.pluginName)},disabled:e.isLoading,class:"pluginsSettingsSubmit btn",value:e.translate("General_Save")},null,8,ml),Object(Oi["createVNode"])(s,{loading:e.isLoading||e.isSaving[t.pluginName]},null,8,["loading"])])],8,pl)})),128)),Object(Oi["createVNode"])(l,{modelValue:e.showPasswordConfirmModal,"onUpdate:modelValue":t[0]||(t[0]=function(t){return e.showPasswordConfirmModal=t}),onConfirmed:e.confirmPassword},null,8,["modelValue","onConfirmed"])],512)}function gl(e,t,n,r,o,i){var a=Object(Oi["resolveComponent"])("GroupedSetting");return Object(Oi["openBlock"])(!0),Object(Oi["createElementBlock"])(Oi["Fragment"],null,Object(Oi["renderList"])(e.settings,(function(t){return Object(Oi["openBlock"])(),Object(Oi["createElementBlock"])("div",{key:"".concat(e.groupPrefix).concat(t.name)},[Object(Oi["createVNode"])(a,{"model-value":e.allSettingValues["".concat(e.groupPrefix).concat(t.name)],"onUpdate:modelValue":function(n){return e.$emit("change",{name:t.name,value:n})},setting:t,"condition-values":e.settingValues},null,8,["model-value","onUpdate:modelValue","setting","condition-values"])])})),128)}function bl(e,t,n,r,o,i){var a=Object(Oi["resolveComponent"])("FormField");return Object(Oi["withDirectives"])((Object(Oi["openBlock"])(),Object(Oi["createElementBlock"])("div",null,[Object(Oi["createVNode"])(a,{"model-value":e.modelValue,"onUpdate:modelValue":t[0]||(t[0]=function(t){return e.changeValue(t)}),"form-field":e.setting},null,8,["model-value","form-field"])],512)),[[Oi["vShow"],e.showField]])}var yl=Object(Oi["defineComponent"])({props:{setting:{type:Object,required:!0},modelValue:null,conditionValues:{type:Object,required:!0}},components:{FormField:il},emits:["update:modelValue"],computed:{showField:function(){var e=this.setting.condition;if(!e)return!0;e=e.replace(/&&/g," and "),e=e.replace(/\|\|/g," or "),e=e.replace(/!/g," not ");try{return vi.evaluate(e,this.conditionValues)}catch(t){return console.log("failed to parse setting condition '".concat(e,"': ").concat(t.message)),console.log(this.conditionValues),!1}}},methods:{changeValue:function(e){this.$emit("update:modelValue",e)}}});yl.render=bl;var vl=yl;function Ol(e,t){return kl(e)||xl(e,t)||wl(e,t)||jl()}function jl(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function wl(e,t){if(e){if("string"===typeof e)return Nl(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Nl(e,t):void 0}}function Nl(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n').concat(t.introduction," "))})):e.append('').concat(n.replace(/([A-Z])/g," $1").trim()," ")))}))}},confirmPassword:function(e){this.showPasswordConfirmModal=!1,this.save(this.settingsToSave,e)},saveSetting:function(e){"admin"===this.mode?(this.settingsToSave=e,this.showPasswordConfirmModal=!0):this.save(e)},save:function(e,t){var n=this,r=this.saveApiMethod;this.isSaving[e]=!0;var o=this.getValuesForPlugin(e);Ci["AjaxHelper"].post({method:r},{settingValues:o,passwordConfirmation:t}).then((function(){n.isSaving[e]=!1;var t=Ci["NotificationsStore"].show({message:Object(Ci["translate"])("CoreAdminHome_PluginSettingsSaveSuccess"),id:"generalSettings",context:"success",type:"transient"});Ci["NotificationsStore"].scrollToNotification(t)})).catch((function(){n.isSaving[e]=!1})),this.settingsToSave=null},getValuesForPlugin:function(e){var t={};return t[e]||(t[e]=[]),Object.entries(this.settingValues).forEach((function(n){var r=Hl(n,2),o=r[0],i=r[1],a=o.split("."),s=Hl(a,2),l=s[0],c=s[1];if(l===e){var u=i;!1===u?u="0":!0===u&&(u="1"),t[l].push({name:c,value:u})}})),t}}});Yl.render=hl;var Zl=Yl,Xl=window,Ql=Xl.$; + */function Xs(e,t){if(!e)return[];var n=[];return Object.entries(e).forEach((function(e){var r=Ws(e,2),o=r[0],i=r[1];if(i&&"object"===zs(i)&&"undefined"!==typeof i.key)n.push(i);else{var a=o;"integer"===t&&"string"===typeof o&&(a=parseInt(a,10)),n.push({key:a,value:i})}})),n}function Qs(e){return Qs="function"===typeof Symbol&&"symbol"===typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"===typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Qs(e)}var el=["password","url","search","email"],tl=["textarea","checkbox","text"],nl={checkbox:"FieldCheckbox","expandable-select":"FieldExpandableSelect","field-array":"FieldFieldArray",file:"FieldFile",hidden:"FieldHidden",multiselect:"FieldSelect",multituple:"FieldMultituple",number:"FieldNumber",radio:"FieldRadio",select:"FieldSelect",site:"FieldSite",text:"FieldText",textarea:"FieldTextarea"},rl={FieldSelect:ms,FieldCheckboxArray:Xs,FieldRadio:Xs,FieldExpandableSelect:oa},ol=Object(Oi["defineComponent"])({props:{modelValue:null,modelModifiers:Object,formField:{type:Object,required:!0}},emits:["update:modelValue"],components:{FieldCheckbox:Mi,FieldCheckboxArray:zi,FieldExpandableSelect:aa,FieldFieldArray:ua,FieldFile:ya,FieldHidden:wa,FieldMultituple:Ca,FieldNumber:Pa,FieldRadio:Fa,FieldSelect:bs,FieldSite:ws,FieldText:Cs,FieldTextArray:Ps,FieldTextarea:Fs,FieldTextareaArray:Rs},setup:function(e){var t=Object(Oi["ref"])(null),n=function(e){var n;e&&t.value&&"function"!==typeof e.render&&(n="string"===typeof e?0===e.indexOf("#")?window.$(e):window.vueSanitize(e):e,window.$(t.value).html("").append(n))};return Object(Oi["watch"])((function(){return e.formField.inlineHelp}),n),Object(Oi["onMounted"])((function(){n(e.formField.inlineHelp)})),{inlineHelp:t}},computed:{inlineHelpComponent:function(){var e=this.formField,t=e.inlineHelp;if(t&&"function"===typeof t.render)return e.inlineHelp},inlineHelpBind:function(){return this.inlineHelpComponent?this.formField.inlineHelpBind:void 0},childComponent:function(){var e=this.formField;if(e.component){var t=e.component;if(e.component.plugin){var n=e.component,r=n.plugin,o=n.name;if(!r||!o)throw new Error("Invalid component property given to FormField directive, must be {plugin: '...',name: '...'}");t=Object(Ci["useExternalPluginComponent"])(r,o)}return Object(Oi["markRaw"])(t)}var i=e.uiControl,a=nl[i];return-1!==el.indexOf(i)&&(a="FieldText"),"array"===this.formField.type&&-1!==tl.indexOf(i)&&(a="".concat(a,"Array")),a},extraChildComponentParams:function(){return"multiselect"===this.formField.uiControl?{multiple:!0}:{}},showFormHelp:function(){return this.formField.description||this.formField.inlineHelp||this.showDefaultValue||this.hasInlineHelpSlot},showDefaultValue:function(){return this.defaultValuePretty&&"checkbox"!==this.formField.uiControl&&"radio"!==this.formField.uiControl},processedModelValue:function(){var e=this.formField;if("boolean"===e.type){var t=this.modelValue&&this.modelValue>0&&"0"!==this.modelValue;if("checkbox"===e.uiControl)return t;if("radio"===e.uiControl)return t?"1":"0"}return this.modelValue},defaultValue:function(){var e=this.formField.defaultValue;return Array.isArray(e)?e.join(","):e},availableOptions:function(){var e=this.childComponent;if("string"!==typeof e)return null;var t=this.formField;return t.availableValues&&rl[e]?rl[e](t.availableValues,t.type,t.uiControlAttributes):null},defaultValuePretty:function(){var e=this.formField,t=e.defaultValue,n=this.availableOptions;if("string"===typeof t&&t){var r=null;try{r=JSON.parse(t)}catch(i){}if(null!==r&&"object"===Qs(r))return""}if(!Array.isArray(n))return Array.isArray(t)?"":t?"".concat(t):"";var o=[];return Array.isArray(t)||(t=[t]),(n||[]).forEach((function(e){"undefined"!==typeof e.value&&-1!==t.indexOf(e.key)&&o.push(e.value)})),o.join(", ")},defaultValuePrettyTruncated:function(){return this.defaultValuePretty.substring(0,50)},hasInlineHelpSlot:function(){var e,t;if(!this.$slots["inline-help"])return!1;var n=this.$slots["inline-help"]();return!(null===n||void 0===n||null===(e=n[0])||void 0===e||null===(t=e.children)||void 0===t||!t.length)}},methods:{onChange:function(e){this.$emit("update:modelValue",e)}}});ol.render=Ei;var il=ol;function al(e,t,n,r,o,i){var a=Object(Oi["resolveComponent"])("FormField");return Object(Oi["openBlock"])(),Object(Oi["createBlock"])(a,{"form-field":e.field,"model-value":e.modelValue,"onUpdate:modelValue":t[0]||(t[0]=function(t){return e.onChange(t)}),"model-modifiers":e.modelModifiers},{"inline-help":Object(Oi["withCtx"])((function(){return[Object(Oi["renderSlot"])(e.$slots,"inline-help")]})),_:3},8,["form-field","model-value","model-modifiers"])}var sl={multiselect:"array",checkbox:"boolean",site:"object",number:"integer"},ll=Object(Oi["defineComponent"])({props:{modelValue:null,modelModifiers:Object,uicontrol:String,name:String,defaultValue:null,options:[Object,Array],description:String,introduction:String,title:String,inlineHelp:[String,Object],inlineHelpBind:Object,disabled:Boolean,uiControlAttributes:{type:Object,default:function(){return{}}},uiControlOptions:{type:Object,default:function(){return{}}},autocomplete:String,varType:String,autofocus:Boolean,tabindex:Number,fullWidth:Boolean,maxlength:Number,required:Boolean,placeholder:String,rows:Number,min:Number,max:Number,component:null},emits:["update:modelValue"],components:{FormField:il},computed:{type:function(){if(this.varType)return this.varType;var e=this.uicontrol;return e&&sl[e]?sl[e]:"string"},field:function(){return{uiControl:this.uicontrol,type:this.type,name:this.name,defaultValue:this.defaultValue,availableValues:this.options,description:this.description,introduction:this.introduction,inlineHelp:this.inlineHelp,inlineHelpBind:this.inlineHelpBind,title:this.title,component:this.component,uiControlAttributes:Object.assign(Object.assign({},this.uiControlAttributes),{},{disabled:this.disabled,autocomplete:this.autocomplete,tabindex:this.tabindex,autofocus:this.autofocus,rows:this.rows,required:this.required,maxlength:this.maxlength,placeholder:this.placeholder,min:this.min,max:this.max}),fullWidth:this.fullWidth,uiControlOptions:this.uiControlOptions}}},methods:{onChange:function(e){this.$emit("update:modelValue",e)}}});ll.render=al;var cl=ll,ul={class:"pluginSettings",ref:"root"},pl=["id"],dl={class:"card-content"},fl=["id"],ml=["onClick","disabled","value"];function hl(e,t,n,r,o,i){var a=Object(Oi["resolveComponent"])("GroupedSettings"),s=Object(Oi["resolveComponent"])("ActivityIndicator"),l=Object(Oi["resolveComponent"])("PasswordConfirmation");return Object(Oi["openBlock"])(),Object(Oi["createElementBlock"])("div",ul,[(Object(Oi["openBlock"])(!0),Object(Oi["createElementBlock"])(Oi["Fragment"],null,Object(Oi["renderList"])(e.settingsPerPlugin,(function(t){return Object(Oi["openBlock"])(),Object(Oi["createElementBlock"])("div",{class:"card",id:"".concat(t.pluginName,"PluginSettings"),key:"".concat(t.pluginName,"PluginSettings")},[Object(Oi["createElementVNode"])("div",dl,[Object(Oi["createElementVNode"])("h2",{class:"card-title",id:t.pluginName},Object(Oi["toDisplayString"])(t.title),9,fl),Object(Oi["createVNode"])(a,{"group-name":t.pluginName,settings:t.settings,"all-setting-values":e.settingValues,onChange:function(n){return e.settingValues["".concat(t.pluginName,".").concat(n.name)]=n.value}},null,8,["group-name","settings","all-setting-values","onChange"]),Object(Oi["createElementVNode"])("input",{type:"button",onClick:function(n){return e.saveSetting(t.pluginName)},disabled:e.isLoading,class:"pluginsSettingsSubmit btn",value:e.translate("General_Save")},null,8,ml),Object(Oi["createVNode"])(s,{loading:e.isLoading||e.isSaving[t.pluginName]},null,8,["loading"])])],8,pl)})),128)),Object(Oi["createVNode"])(l,{modelValue:e.showPasswordConfirmModal,"onUpdate:modelValue":t[0]||(t[0]=function(t){return e.showPasswordConfirmModal=t}),onConfirmed:e.confirmPassword},null,8,["modelValue","onConfirmed"])],512)}function gl(e,t,n,r,o,i){var a=Object(Oi["resolveComponent"])("GroupedSetting");return Object(Oi["openBlock"])(!0),Object(Oi["createElementBlock"])(Oi["Fragment"],null,Object(Oi["renderList"])(e.settings,(function(t){return Object(Oi["openBlock"])(),Object(Oi["createElementBlock"])("div",{key:"".concat(e.groupPrefix).concat(t.name)},[Object(Oi["createVNode"])(a,{"model-value":e.allSettingValues["".concat(e.groupPrefix).concat(t.name)],"onUpdate:modelValue":function(n){return e.$emit("change",{name:t.name,value:n})},setting:t,"condition-values":e.settingValues},null,8,["model-value","onUpdate:modelValue","setting","condition-values"])])})),128)}function bl(e,t,n,r,o,i){var a=Object(Oi["resolveComponent"])("FormField");return Object(Oi["withDirectives"])((Object(Oi["openBlock"])(),Object(Oi["createElementBlock"])("div",null,[Object(Oi["createVNode"])(a,{"model-value":e.modelValue,"onUpdate:modelValue":t[0]||(t[0]=function(t){return e.changeValue(t)}),"form-field":e.setting},null,8,["model-value","form-field"])],512)),[[Oi["vShow"],e.showField]])}var yl=Object(Oi["defineComponent"])({props:{setting:{type:Object,required:!0},modelValue:null,conditionValues:{type:Object,required:!0}},components:{FormField:il},emits:["update:modelValue"],computed:{showField:function(){var e=this.setting.condition;if(!e)return!0;e=e.replace(/&&/g," and "),e=e.replace(/\|\|/g," or "),e=e.replace(/!/g," not ");try{return vi.evaluate(e,this.conditionValues)}catch(t){return console.log("failed to parse setting condition '".concat(e,"': ").concat(t.message)),console.log(this.conditionValues),!1}}},methods:{changeValue:function(e){this.$emit("update:modelValue",e)}}});yl.render=bl;var vl=yl;function Ol(e,t){return kl(e)||xl(e,t)||wl(e,t)||jl()}function jl(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function wl(e,t){if(e){if("string"===typeof e)return Nl(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Nl(e,t):void 0}}function Nl(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n').concat(t.introduction," "))})):e.append('').concat(n.replace(/([A-Z])/g," $1").trim()," ")))}))}},confirmPassword:function(e){this.showPasswordConfirmModal=!1,this.save(this.settingsToSave,e)},saveSetting:function(e){"admin"===this.mode?(this.settingsToSave=e,this.showPasswordConfirmModal=!0):this.save(e)},save:function(e,t){var n=this,r=this.saveApiMethod;this.isSaving[e]=!0;var o=this.getValuesForPlugin(e);Ci["AjaxHelper"].post({method:r},{settingValues:o,passwordConfirmation:t}).then((function(){n.isSaving[e]=!1;var t=Ci["NotificationsStore"].show({message:Object(Ci["translate"])("CoreAdminHome_PluginSettingsSaveSuccess"),id:"generalSettings",context:"success",type:"transient"});Ci["NotificationsStore"].scrollToNotification(t)})).catch((function(){n.isSaving[e]=!1})),this.settingsToSave=null},getValuesForPlugin:function(e){var t={};return t[e]||(t[e]=[]),Object.entries(this.settingValues).forEach((function(n){var r=Hl(n,2),o=r[0],i=r[1],a=o.split("."),s=Hl(a,2),l=s[0],c=s[1];if(l===e){var u=i;!1===u?u="0":!0===u&&(u="1"),Array.isArray(u)&&0===u.length&&(u="__empty__"),t[l].push({name:c,value:u})}})),t}}});Yl.render=hl;var Zl=Yl,Xl=window,Ql=Xl.$; /*! * Matomo - free/libre analytics platform * diff --git a/plugins/CorePluginsAdmin/vue/src/PluginSettings/PluginSettings.vue b/plugins/CorePluginsAdmin/vue/src/PluginSettings/PluginSettings.vue index 0e47b71eab3..914f68cc194 100644 --- a/plugins/CorePluginsAdmin/vue/src/PluginSettings/PluginSettings.vue +++ b/plugins/CorePluginsAdmin/vue/src/PluginSettings/PluginSettings.vue @@ -199,6 +199,10 @@ export default defineComponent({ postValue = '1'; } + if (Array.isArray(postValue) && postValue.length === 0) { + postValue = '__empty__'; + } + values[pluginName].push({ name: settingName, value: postValue,