-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ENH] Impelement OptionsResolver module
- Loading branch information
0 parents
commit 86a569a
Showing
8 changed files
with
301 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
vendor |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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": "[email protected]" | ||
} | ||
], | ||
"minimum-stability": "dev", | ||
"require": { | ||
"php" : ">=7.4" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<?php | ||
/* | ||
* Copyright (c) 2022. | ||
* The OptionsResolver component helps you configure objects with option arrays. It supports default values, option constraints and lazy options. | ||
*/ | ||
|
||
namespace Wepesi\Demo; | ||
|
||
use Wepesi\Resolver\Option; | ||
use Wepesi\Resolver\OptionsResolver; | ||
|
||
class Database | ||
{ | ||
public array $options; | ||
|
||
public function __construct(array $options = []) | ||
{ | ||
$resolver = new OptionsResolver([ | ||
(new Option('host'))->setDefaultValue('localhost'), | ||
new Option('username'), | ||
new Option('password'), | ||
new Option('dbname'), | ||
]); | ||
|
||
$this->options = $resolver->resolve($options); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<?php | ||
/* | ||
* Copyright (c) 2022. | ||
* The OptionsResolver component helps you configure objects with option arrays. It supports default values, option constraints and lazy options. | ||
*/ | ||
|
||
use Wepesi\Demo\Database; | ||
|
||
include __DIR__."/../vendor/autoload.php"; | ||
include __DIR__."/Database.php"; | ||
|
||
$database = new Database([ | ||
'dbname' => 'app', | ||
]); | ||
// Uncaught InvalidArgumentException: The required option "username" is missing. | ||
|
||
// $database = new Database([ | ||
// 'host' => 'localhost', | ||
// 'dbname' => 'app', | ||
// 'username' => 'root', | ||
// 'password' => 'root', | ||
// ]); | ||
var_dump($database->options); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
<?php | ||
/* | ||
* Copyright (c) 2022. | ||
* The OptionsResolver component helps you configure objects with option arrays. It supports default values, option constraints and lazy options. | ||
*/ | ||
|
||
namespace Wepesi\Resolver; | ||
|
||
final class Option | ||
{ | ||
/** | ||
* @var string | ||
*/ | ||
private string $name; | ||
|
||
/** | ||
* @var mixed | ||
*/ | ||
private $defaultValue; | ||
|
||
/** | ||
* @var bool | ||
*/ | ||
private bool $hasDefaultValue; | ||
|
||
/** | ||
* @var \Closure|null | ||
*/ | ||
private ?\Closure $validator; | ||
|
||
/** | ||
* Option constructor. | ||
* @param string $name | ||
*/ | ||
public function __construct(string $name) | ||
{ | ||
$this->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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
<?php | ||
/* | ||
* Copyright (c) 2022. | ||
* The OptionsResolver component helps you configure objects with option arrays. It supports default values, option constraints and lazy options. | ||
*/ | ||
|
||
namespace Wepesi\Resolver; | ||
|
||
use Wepesi\Resolver\Traits\ExceptionTraits; | ||
|
||
final class OptionsResolver | ||
{ | ||
/** | ||
* @var \ArrayObject | ||
*/ | ||
private \ArrayObject $options; | ||
|
||
use ExceptionTraits; | ||
|
||
/** | ||
* @param array $options | ||
*/ | ||
public function __construct(array $options) | ||
{ | ||
$this->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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?php | ||
/* | ||
* Copyright (c) 2022. | ||
* The OptionsResolver component helps you configure objects with option arrays. It supports default values, option constraints and lazy options. | ||
*/ | ||
|
||
namespace Wepesi\Resolver\Traits; | ||
|
||
trait ExceptionTraits | ||
{ | ||
protected function exception($ex):array | ||
{ | ||
return [get_class($ex) => $ex->getMessage()]; | ||
} | ||
} |