From 7fc2c595d7c3a85caeaccb540e9806d427630296 Mon Sep 17 00:00:00 2001 From: mokaddem Date: Tue, 27 Jul 2021 10:40:58 +0200 Subject: [PATCH] chg: [instance:settings] Integrated actually save of settings --- src/Controller/InstanceController.php | 6 +-- src/Model/Table/SettingsProviderTable.php | 53 ++++++++++++++++------- src/Model/Table/SettingsTable.php | 38 ++++++++++++++-- templates/Instance/settings.php | 6 +-- 4 files changed, 77 insertions(+), 26 deletions(-) diff --git a/src/Controller/InstanceController.php b/src/Controller/InstanceController.php index 10604a2..c5a9556 100644 --- a/src/Controller/InstanceController.php +++ b/src/Controller/InstanceController.php @@ -7,6 +7,7 @@ use Cake\Utility\Hash; use Cake\Utility\Text; use \Cake\Database\Expression\QueryExpression; use Cake\Event\EventInterface; +use Cake\Core\Configure; class InstanceController extends AppController { @@ -125,11 +126,6 @@ class InstanceController extends AppController if (empty($errors)) { $message = __('Setting `{0}` saved', $data['name']); $data = $this->Settings->getSetting($data['name']); - // TO DEL - $data['errorMessage'] = 'Test test test'; - $data['error'] = true; - $data['error'] = false; - // TO DEL } $this->CRUD->setResponseForController('saveSetting', empty($errors), $message, $data, $errors); $responsePayload = $this->CRUD->getResponsePayload(); diff --git a/src/Model/Table/SettingsProviderTable.php b/src/Model/Table/SettingsProviderTable.php index c32100f..8c97f77 100644 --- a/src/Model/Table/SettingsProviderTable.php +++ b/src/Model/Table/SettingsProviderTable.php @@ -124,22 +124,12 @@ class SettingsProviderTable extends AppTable } } if (!$skipValidation) { - $validationResult = false; + $validationResult = true; if (!isset($setting['value'])) { $validationResult = $this->settingValidator->testEmptyBecomesDefault(null, $setting); } else if (isset($setting['test'])) { $setting['value'] = $setting['value'] ?? ''; - if (is_callable($setting['test'])) { // Validate with anonymous function - $validationResult = $setting['test']($setting['value'], $setting, new Validator()); - } else if (method_exists($this->settingValidator, $setting['test'])) { // Validate with function defined in settingValidator class - $validationResult = $this->settingValidator->{$setting['test']}($setting['value'], $setting); - } else { - $validator = new Validator(); - if (method_exists($validator, $setting['test'])) { // Validate with cake's validator function - $validator->{$setting['test']}; - $validationResult = $validator->validate($setting['value']); - } - } + $validationResult = $this->evaluateFunctionForSetting($setting['test'], $setting); } if ($validationResult !== true) { $setting['severity'] = $setting['severity'] ?? 'warning'; @@ -152,12 +142,37 @@ class SettingsProviderTable extends AppTable } return $setting; } + + /** + * evaluateFunctionForSetting - evaluate the provided function. If function could not be evaluated, its result is defaulted to true + * + * @param mixed $fun + * @param array $setting + * @return mixed + */ + public function evaluateFunctionForSetting($fun, $setting) + { + $functionResult = true; + if (is_callable($fun)) { // Validate with anonymous function + $functionResult = $fun($setting['value'], $setting, new Validator()); + } else if (method_exists($this->settingValidator, $fun)) { // Validate with function defined in settingValidator class + $functionResult = $this->settingValidator->{$fun}($setting['value'], $setting); + } else { + $validator = new Validator(); + if (method_exists($validator, $fun)) { // Validate with cake's validator function + $validator->{$fun}; + $functionResult = $validator->validate($setting['value']); + } + } + return $functionResult; + } /** * Support up to 3 level: * Application -> Network -> Proxy -> Proxy.URL * - * Leave errorMessage empty to let the validator generate the error message + * - Leave errorMessage empty to let the validator generate the error message + * - Default severity level is `info` if a `default` value is provided otherwise it becomes `critical` */ private function generateSettingsConfiguration() { @@ -188,8 +203,16 @@ class SettingsProviderTable extends AppTable 'errorMessage' => 'to del', 'default' => 'A-default-value', 'name' => 'To DEL', - 'test' => function ($value) { - return empty($value) ? __('Oh not! it\'s not valid!') : ''; + 'test' => function($value) { + return empty($value) ? __('Oh not! it\'s not valid!') : true; + }, + 'beforeSave' => function($value, $setting) { + if ($value != 'foo') { + return 'value must be `foo`!'; + } + return true; + }, + 'afterSave' => function($value, $setting) { }, 'type' => 'string' ], diff --git a/src/Model/Table/SettingsTable.php b/src/Model/Table/SettingsTable.php index cdc1796..0fe4784 100644 --- a/src/Model/Table/SettingsTable.php +++ b/src/Model/Table/SettingsTable.php @@ -9,6 +9,9 @@ use Cake\ORM\TableRegistry; class SettingsTable extends AppTable { + private static $FILENAME = 'cerebrate'; + private static $CONFIG_KEY = 'Cerebrate'; + public function initialize(array $config): void { parent::initialize($config); @@ -18,7 +21,7 @@ class SettingsTable extends AppTable public function getSettings($full=false): array { - $settings = Configure::read()['Cerebrate']; + $settings = $this->readSettings(); if (empty($full)) { return $settings; } else { @@ -36,7 +39,7 @@ class SettingsTable extends AppTable public function getSetting($name=false): array { - $settings = Configure::read()['Cerebrate']; + $settings = $this->readSettings(); $settingsProvider = $this->SettingsProvider->getSettingsConfiguration($settings); $settingsFlattened = $this->SettingsProvider->flattenSettingsConfiguration($settingsProvider); return $settingsFlattened[$name] ?? []; @@ -45,7 +48,36 @@ class SettingsTable extends AppTable public function saveSetting(string $name, string $value): array { $errors = []; - // Save setting here! + $setting = $this->getSetting($name); + if (!empty($setting['beforeSave'])) { + $setting['value'] = $value ?? ''; + $beforeSaveResult = $this->SettingsProvider->evaluateFunctionForSetting($setting['beforeSave'], $setting); + if ($beforeSaveResult !== true) { + $errors[] = $beforeSaveResult; + } + } + if (empty($errors)) { + $saveResult = $this->saveSettingOnDisk($name, $value); + if ($saveResult) { + if (!empty($setting['afterSave'])) { + $this->SettingsProvider->evaluateFunctionForSetting($setting['afterSave'], $setting); + } + } + } return $errors; } + + private function readSettings() + { + return Configure::read()[$this::$CONFIG_KEY]; + } + + private function saveSettingOnDisk($name, $value) + { + $settings = $this->readSettings(); + $settings[$name] = $value; + Configure::write($this::$CONFIG_KEY, $settings); + Configure::dump($this::$FILENAME, 'default', [$this::$CONFIG_KEY]); + return true; + } } diff --git a/templates/Instance/settings.php b/templates/Instance/settings.php index a01b9bd..100d6a8 100644 --- a/templates/Instance/settings.php +++ b/templates/Instance/settings.php @@ -170,7 +170,7 @@ function isLeaf($setting) $input.val(result.data.value) } handleSettingValueChange($input) - }) + }).catch((e) => {}) } function handleSettingValueChange($input) { @@ -187,7 +187,7 @@ function isLeaf($setting) const $inputGroup = $input.closest('.input-group') const $inputGroupAppend = $inputGroup.find('.input-group-append') const $saveButton = $inputGroup.find('button.btn-save-setting') - $input.removeClass(['is-invalid', 'border-warning', 'border-danger', 'border-info']) + $input.removeClass(['is-invalid', 'border-warning', 'border-danger', 'border-info', 'warning', 'info']) $inputGroupAppend.removeClass('d-none') if ($input.is('select') && $input.find('option:selected').data('is-empty-option') == 1) { $inputGroupAppend.addClass('d-none') // hide save button if empty selection picked @@ -202,7 +202,7 @@ function isLeaf($setting) const setting = settingsFlattened[$input.data('setting-name')] if (setting.error) { borderVariant = setting.severity !== undefined ? variantFromSeverity[setting.severity] : 'warning' - $input.addClass(['is-invalid', `border-${borderVariant}`]) + $input.addClass(['is-invalid', `border-${borderVariant}`, borderVariant]) if (setting.severity == 'warning') { $input.addClass('warning') }