From 86a569afe3d09ce2eafa6a3491ef44f328ad8e6d Mon Sep 17 00:00:00 2001 From: bim-g Date: Thu, 29 Dec 2022 13:47:49 +0200 Subject: [PATCH] [ENH] Impelement OptionsResolver module --- .gitignore | 1 + .idea/.gitignore | 8 +++ composer.json | 21 ++++++ demo/Database.php | 27 ++++++++ demo/index.php | 23 +++++++ src/Option.php | 84 +++++++++++++++++++++++ src/OptionsResolver.php | 122 +++++++++++++++++++++++++++++++++ src/Traits/ExceptionTraits.php | 15 ++++ 8 files changed, 301 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 composer.json create mode 100644 demo/Database.php create mode 100644 demo/index.php create mode 100644 src/Option.php create mode 100644 src/OptionsResolver.php create mode 100644 src/Traits/ExceptionTraits.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5657f6e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +vendor \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..9c82354 --- /dev/null +++ b/composer.json @@ -0,0 +1,21 @@ +{ + "name": "wepesi/optionsresolver", + "description": "The OptionsResolver component helps you configure objects with option arrays. It supports default values, option constraints and lazy options.", + "type": "library", + "license": "Apache-2.0", + "autoload": { + "psr-4": { + "Wepesi\\Resolver\\": "src/" + } + }, + "authors": [ + { + "name": "bim-g", + "email": "ibmussafb@gmail.com" + } + ], + "minimum-stability": "dev", + "require": { + "php" : ">=7.4" + } +} diff --git a/demo/Database.php b/demo/Database.php new file mode 100644 index 0000000..32dcc16 --- /dev/null +++ b/demo/Database.php @@ -0,0 +1,27 @@ +setDefaultValue('localhost'), + new Option('username'), + new Option('password'), + new Option('dbname'), + ]); + + $this->options = $resolver->resolve($options); + } +} diff --git a/demo/index.php b/demo/index.php new file mode 100644 index 0000000..c2d7cd0 --- /dev/null +++ b/demo/index.php @@ -0,0 +1,23 @@ + 'app', +]); +// Uncaught InvalidArgumentException: The required option "username" is missing. + +// $database = new Database([ +// 'host' => 'localhost', +// 'dbname' => 'app', +// 'username' => 'root', +// 'password' => 'root', +// ]); +var_dump($database->options); \ No newline at end of file diff --git a/src/Option.php b/src/Option.php new file mode 100644 index 0000000..89d01d3 --- /dev/null +++ b/src/Option.php @@ -0,0 +1,84 @@ +name = $name; + } + + public function getName(): string + { + $this->hasDefaultValue = false; + return $this->name; + } + + /** + * @return mixed + */ + public function getDefaultValue() + { + return $this->defaultValue; + } + + /** + * @param mixed $defaultValue + * @return Option + */ + public function setDefaultValue($defaultValue): self + { + $this->hasDefaultValue = true; + $this->defaultValue = $defaultValue; + return $this; + } + + public function hasDefaultValue(): bool + { + return $this->hasDefaultValue; + } + + public function validator(\Closure $closure): self + { + $this->validator = $closure; + return $this; + } + + public function isValid($value): bool + { + if ($this->validator instanceof \Closure) { + $validator = $this->validator; + return $validator($value); + } + return true; + } +} \ No newline at end of file diff --git a/src/OptionsResolver.php b/src/OptionsResolver.php new file mode 100644 index 0000000..d3508b1 --- /dev/null +++ b/src/OptionsResolver.php @@ -0,0 +1,122 @@ +options = new \ArrayObject(); + foreach ($options as $option) { + $this->add($option); + } + } + + /** + * @param array $options + * @return array + */ + public function resolve(array $options): array + { + try { + $checkDiff = $this->checkDiff($options); + if(isset($checkDiff['exception'])){ + return $checkDiff; + } + /** + * @var Option $option + */ + $optionsResolved = []; + foreach ($this->options as $option) { + $optionName = $option->getName(); + if (\array_key_exists($optionName, $options)) { + $value = $options[$optionName]; + if ($option->isValid($value) === false) { + throw new \InvalidArgumentException(sprintf('The option "%s" with value %s is invalid.', $optionName, self::formatValue($value))); + } + $optionsResolved[$optionName] = $value; + continue; + } + + if ($option->hasDefaultValue()) { + $optionsResolved[$optionName] = $option->getDefaultValue(); + continue; + } + throw new \InvalidArgumentException(sprintf('The required option "%s" is missing.', $optionName)); + } + return $optionsResolved; + } catch (\Exception $ex) { + return $this->exception($ex); + } + } + + /** + * @param Option $option + * @return void + */ + private function add(Option $option): void + { + $this->options->offsetSet($option->getName(), $option); + } + + /** + * @param array $options + * @return array + */ + private function checkDiff(array $options): array + { + try { + $defined = $this->options->getArrayCopy(); + $diff = array_diff_key($options, $defined); + if (count($diff) > 0) { + $arr_diff = implode(', ', array_keys($diff)); + $arr_defined = implode('", "', array_keys($defined)); + $error_message = sprintf('The option(s) "%s" do(es) not exist. Defined options are: "%s".',$arr_diff ,$arr_defined); + throw new \InvalidArgumentException($error_message); + } + return []; + } catch (\Exception $ex) { + return $this->exception($ex); + } + } + + /** + * @param $value + * @return string + */ + private static function formatValue($value): string + { + if (is_object($value)) { + return \get_class($value); + } + + if (is_string($value)) { + return '"' . $value . '"'; + } + + if (false === $value) { + return 'false'; + } + + if (true === $value) { + return 'true'; + } + return \gettype($value); + } +} \ No newline at end of file diff --git a/src/Traits/ExceptionTraits.php b/src/Traits/ExceptionTraits.php new file mode 100644 index 0000000..00a5827 --- /dev/null +++ b/src/Traits/ExceptionTraits.php @@ -0,0 +1,15 @@ + $ex->getMessage()]; + } +} \ No newline at end of file