From 12798b40b88c262cb17e54a96a2be47dc0624182 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 13 Nov 2019 08:28:17 +1100 Subject: [PATCH] Fixes for transforming and saving company settings. (#3059) * Cleanup for settings remove from entities * Fixes for saving and transforming company settings * CompanySettingsSaver --- app/Utils/Traits/CompanySettingsSaver.php | 199 ++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 app/Utils/Traits/CompanySettingsSaver.php diff --git a/app/Utils/Traits/CompanySettingsSaver.php b/app/Utils/Traits/CompanySettingsSaver.php new file mode 100644 index 000000000000..e92f7ce27198 --- /dev/null +++ b/app/Utils/Traits/CompanySettingsSaver.php @@ -0,0 +1,199 @@ +checkSettingType($settings); + + $company_settings = CompanySettings::defaults(); + + //Iterate and set CURRENT settings + foreach($this->settings as $key => $value) + $company_settings->{$key} = $value; + + //Iterate and set NEW settings + foreach($settings as $key => $value) + $company_settings->{$key} = $value; + + $entity->settings = $company_settings; + $entity->save(); + } + + /** + * Used for custom validation of inbound + * settings request. + * + * Returns an array of errors, or boolean TRUE + * on successful validation + * @param array $settings The request() settings array + * @return array|bool Array on failure, boolean TRUE on success + */ + public function validateSettings($settings) + { + $settings = (object)$settings; + $casts = CompanySettings::$casts; + + ksort($casts); + + foreach ($casts as $key => $value){ + + /*Separate loop if it is a _id field which is an integer cast as a string*/ + if(substr($key, -3) == '_id' || substr($key, -14) == 'number_counter'){ + $value = "integer"; + + if(!property_exists($settings, $key)){ + continue; + } + else if(!$this->checkAttribute($value, $settings->{$key})){ + return [$key, $value]; + } + + continue; + } + + /* Handles unset settings or blank strings */ + if(!property_exists($settings, $key) || is_null($settings->{$key}) || !isset($settings->{$key}) || $settings->{$key} == '') + continue; + + + /*Catch all filter */ + if(!$this->checkAttribute($value, $settings->{$key})) + return [$key, $value]; + + + } + + return true; + } + + /** + * Checks the settings object for + * correct property types. + * + * The method will drop invalid types from + * the object and will also settype() the property + * so that it can be saved cleanly + * + * @param array $settings The settings request() array + * @return object stdClass object + */ + private function checkSettingType($settings) : \stdClass + { + $settings = (object)$settings; + $casts = CompanySettings::$casts; + + foreach ($casts as $key => $value){ + + /*Separate loop if it is a _id field which is an integer cast as a string*/ + if(substr($key, -3) == '_id' || substr($key, -14) == 'number_counter'){ + $value = "integer"; + + if(!property_exists($settings, $key)){ + continue; + } + elseif($this->checkAttribute($value, $settings->{$key})){ + + if(substr($key, -3) == '_id') + settype($settings->{$key}, 'string'); + else + settype($settings->{$key}, $value); + + } + else { + unset($settings->{$key}); + } + + continue; + } + + /* Handles unset settings or blank strings */ + if(!property_exists($settings, $key) || is_null($settings->{$key}) || !isset($settings->{$key}) || $settings->{$key} == ''){ + continue; + } + + /*Catch all filter */ + if($this->checkAttribute($value, $settings->{$key})){ + + if($value == 'string' && is_null($settings->{$key})) + $settings->{$key} = ''; + + settype($settings->{$key}, $value); + } + else { + unset($settings->{$key}); + } + + } + return $settings; + } + + /** + * Type checks a object property. + * @param string $key The type + * @param string $value The object property + * @return bool TRUE if the property is the expected type + */ + private function checkAttribute($key, $value) :bool + { + switch ($key) + { + case 'int': + case 'integer': + return ctype_digit(strval($value)); + case 'real': + case 'float': + case 'double': + return is_float($value) || is_numeric(strval($value)); + case 'string': + return method_exists($value, '__toString' ) || is_null($value) || is_string($value); + case 'bool': + case 'boolean': + return is_bool($value) || (int) filter_var($value, FILTER_VALIDATE_BOOLEAN); + case 'object': + return is_object($value); + case 'array': + return is_array($value); + case 'json': + json_decode($string); + return (json_last_error() == JSON_ERROR_NONE); + default: + return false; + } + } + +} \ No newline at end of file