From adb73b8031e3ba4fce2b6c4a523eae89961bd55b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20B=C3=B6sing?= Date: Tue, 15 Jan 2019 11:11:48 +0100 Subject: [PATCH 1/6] Added feature to provide parameters which referencing parameters --- README.md | 19 +++++++++---- docs/book/usage.md | 20 ++++++++++---- src/ParameterPostProcessor.php | 29 +++++++++++++------- test/ParameterPostProcessorTest.php | 41 +++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 1793a96..ed2c8cf 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ $aggregator = new ConfigAggregator( 'parameter_usage' => '%foo%', 'parameter_name' => '%%foo%%', 'recursive_parameter_usage' => '%bar.baz%', + 'parameterized_parameter_usage' => '%bar.quux%', ]), ], null, @@ -26,6 +27,7 @@ $aggregator = new ConfigAggregator( 'foo' => 'bar', 'bar' => [ 'baz' => 'qoo', + 'quux' => '%foo%', ], ]), ] @@ -37,26 +39,33 @@ var_dump($aggregator->getMergedConfig()); Result: ```php -array(3) { +array(5) { 'parameter_usage' => string(3) "bar" 'parameter_name' => string(5) "%foo%" 'recursive_parameter_usage' => string(3) "qoo" + 'parameterized_parameter_usage' => + string(3) "qoo" 'parameters' => - array(3) { - 'foo' => - string(3) "bar" + array(4) { + 'foo' => + string(3) "bar" 'bar' => - array(1) { + array(2) { 'baz' => string(3) "qoo" + 'quux' => + string(3) "qoo" } 'bar.baz' => string(3) "qoo" + 'bar.quux' => + string(3) "bar" } } + ``` For more details, please refer to the [documentation](https://docs.zendframework.com/zend-config-aggregator-parameters/). diff --git a/docs/book/usage.md b/docs/book/usage.md index 6b9e787..8843c6d 100644 --- a/docs/book/usage.md +++ b/docs/book/usage.md @@ -15,6 +15,8 @@ Parameters may be defined as nested associative arrays as well; in such cases, a `.` character references an additional layer of hierarchy to dereference: `%foo.bar%` refers to the paramter found at `'foo' => [ 'bar' => 'value' ]`. +You can use parameters which referencing other parameters aswell. + If you wish to use a literal `%name%` within your configuration, you **must** double-escape the percentage signs: `%%name%%`. Failure to do so will result in an exception when post-processing the configuration. @@ -32,6 +34,7 @@ $aggregator = new ConfigAggregator( 'parameter_usage' => '%foo%', 'parameter_name' => '%%foo%%', 'recursive_parameter_usage' => '%bar.baz%', + 'parameterized_parameter_usage' => '%bar.quux%', ]), ], null, @@ -40,6 +43,7 @@ $aggregator = new ConfigAggregator( 'foo' => 'bar', 'bar' => [ 'baz' => 'qoo', + 'quux' => '%foo%', ], ]), ] @@ -51,24 +55,30 @@ var_dump($aggregator->getMergedConfig()); The result of the above will be: ```php -array(3) { +array(5) { 'parameter_usage' => string(3) "bar" 'parameter_name' => string(5) "%foo%" 'recursive_parameter_usage' => string(3) "qoo" + 'parameterized_parameter_usage' => + string(3) "qoo" 'parameters' => - array(3) { - 'foo' => - string(3) "bar" + array(4) { + 'foo' => + string(3) "bar" 'bar' => - array(1) { + array(2) { 'baz' => string(3) "qoo" + 'quux' => + string(3) "qoo" } 'bar.baz' => string(3) "qoo" + 'bar.quux' => + string(3) "bar" } } ``` diff --git a/src/ParameterPostProcessor.php b/src/ParameterPostProcessor.php index 7b231e2..8971260 100644 --- a/src/ParameterPostProcessor.php +++ b/src/ParameterPostProcessor.php @@ -11,11 +11,12 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException as SymfonyParameterNotFoundException; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; class ParameterPostProcessor { /** - * @var ParameterBag + * @var array */ private $parameters; @@ -24,17 +25,12 @@ class ParameterPostProcessor */ public function __construct(array $parameters) { - $this->parameters = new ParameterBag($parameters); + $this->parameters = $parameters; } public function __invoke(array $config) : array { - $parameters = $this->parameters; - - // First, convert values to needed parameters - $convertedParameters = $this->convertValues($parameters->all()); - $parameters->clear(); - $parameters->add($convertedParameters); + $parameters = $this->getResolvedParameters(); try { array_walk_recursive($config, function (&$value) use ($parameters) { @@ -49,7 +45,7 @@ public function __invoke(array $config) : array return $config; } - private function convertValues(array $values, string $prefix = '') : array + private function resolveNestedParameters(array $values, string $prefix = '') : array { $convertedValues = []; foreach ($values as $key => $value) { @@ -60,10 +56,23 @@ private function convertValues(array $values, string $prefix = '') : array $convertedValues[$prefix . $key] = $value; if (is_array($value)) { - $convertedValues += $this->convertValues($value, $prefix . $key . '.'); + $convertedValues += $this->resolveNestedParameters($value, $prefix . $key . '.'); } } return $convertedValues; } + + private function getResolvedParameters(): ParameterBagInterface + { + $resolved = $this->resolveNestedParameters($this->parameters); + $bag = new ParameterBag($resolved); + try { + $bag->resolve(); + } catch (SymfonyParameterNotFoundException $exception) { + throw ParameterNotFoundException::fromException($exception); + } + + return $bag; + } } diff --git a/test/ParameterPostProcessorTest.php b/test/ParameterPostProcessorTest.php index 2e06cdd..17666f0 100644 --- a/test/ParameterPostProcessorTest.php +++ b/test/ParameterPostProcessorTest.php @@ -74,4 +74,45 @@ public function testCanDetectMissingParameter() $this->expectException(ParameterNotFoundException::class); $processor(['foo' => '%foo%']); } + + public function testResolvesParameterizedParameters() + { + $processor = new ParameterPostProcessor([ + 'foo' => 'bar', + 'bar' => 'baz', + 'baz' => '%foo%', + 'nested' => [ + 'foo' => '%bar%', + 'bar' => '%nested.foo%', + ], + ]); + + $processed = $processor(['foo' => '%nested.bar%']); + + $this->assertArraySubset([ + 'foo' => 'baz', + 'parameters' => [ + 'nested' => [ + 'bar' => 'baz', + ], + ], + ], $processed); + } + + public function testResolvesParameterizedParametersInReversedOrder() + { + $processor = new ParameterPostProcessor([ + 'foo' => '%bar%', + 'bar' => '%baz%', + 'baz' => 'qux', + ]); + + $processed = $processor([]); + + $this->assertArraySubset([ + 'parameters' => [ + 'foo' => 'qux', + ], + ], $processed); + } } From 586305de61f76290c40630b2ef8813a5136a5bd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20B=C3=B6sing?= Date: Tue, 15 Jan 2019 11:28:45 +0100 Subject: [PATCH 2/6] Added early return, removed interface usage in private method and applied codestyle --- src/ParameterPostProcessor.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/ParameterPostProcessor.php b/src/ParameterPostProcessor.php index 8971260..3f194cc 100644 --- a/src/ParameterPostProcessor.php +++ b/src/ParameterPostProcessor.php @@ -11,7 +11,6 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException as SymfonyParameterNotFoundException; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; class ParameterPostProcessor { @@ -63,16 +62,15 @@ private function resolveNestedParameters(array $values, string $prefix = '') : a return $convertedValues; } - private function getResolvedParameters(): ParameterBagInterface + private function getResolvedParameters() : ParameterBag { $resolved = $this->resolveNestedParameters($this->parameters); $bag = new ParameterBag($resolved); try { $bag->resolve(); + return $bag; } catch (SymfonyParameterNotFoundException $exception) { throw ParameterNotFoundException::fromException($exception); } - - return $bag; } } From 99401aeab3c6901d8825a4cef0ffd1ffc77eb6fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20B=C3=B6sing?= Date: Tue, 15 Jan 2019 11:33:15 +0100 Subject: [PATCH 3/6] Fixed typo in --- docs/book/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/book/usage.md b/docs/book/usage.md index 8843c6d..ba1078c 100644 --- a/docs/book/usage.md +++ b/docs/book/usage.md @@ -15,7 +15,7 @@ Parameters may be defined as nested associative arrays as well; in such cases, a `.` character references an additional layer of hierarchy to dereference: `%foo.bar%` refers to the paramter found at `'foo' => [ 'bar' => 'value' ]`. -You can use parameters which referencing other parameters aswell. +You can use parameters which referencing other parameters as well. If you wish to use a literal `%name%` within your configuration, you **must** double-escape the percentage signs: `%%name%%`. Failure to do so will result in From ab22412a2bd19d4f10b797ee9d108fd12fb3b0dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20B=C3=B6sing?= Date: Tue, 15 Jan 2019 11:58:49 +0100 Subject: [PATCH 4/6] Re-arranged code so we do not catch the same exception twice --- src/ParameterPostProcessor.php | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/ParameterPostProcessor.php b/src/ParameterPostProcessor.php index 3f194cc..98cdb44 100644 --- a/src/ParameterPostProcessor.php +++ b/src/ParameterPostProcessor.php @@ -29,9 +29,10 @@ public function __construct(array $parameters) public function __invoke(array $config) : array { - $parameters = $this->getResolvedParameters(); try { + $parameters = $this->getResolvedParameters(); + array_walk_recursive($config, function (&$value) use ($parameters) { $value = $parameters->unescapeValue($parameters->resolveValue($value)); }); @@ -66,11 +67,8 @@ private function getResolvedParameters() : ParameterBag { $resolved = $this->resolveNestedParameters($this->parameters); $bag = new ParameterBag($resolved); - try { - $bag->resolve(); - return $bag; - } catch (SymfonyParameterNotFoundException $exception) { - throw ParameterNotFoundException::fromException($exception); - } + + $bag->resolve(); + return $bag; } } From 4a88872eb78e2216b973ab034eb4cabba6cda433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20B=C3=B6sing?= Date: Wed, 16 Jan 2019 14:49:09 +0100 Subject: [PATCH 5/6] Change typo --- docs/book/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/book/usage.md b/docs/book/usage.md index ba1078c..ecdcd5d 100644 --- a/docs/book/usage.md +++ b/docs/book/usage.md @@ -15,7 +15,7 @@ Parameters may be defined as nested associative arrays as well; in such cases, a `.` character references an additional layer of hierarchy to dereference: `%foo.bar%` refers to the paramter found at `'foo' => [ 'bar' => 'value' ]`. -You can use parameters which referencing other parameters as well. +You can use parameters which reference other parameters as well. If you wish to use a literal `%name%` within your configuration, you **must** double-escape the percentage signs: `%%name%%`. Failure to do so will result in From 05d9a55f846fed96f03e03810561cfd7cbd66d4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20B=C3=B6sing?= Date: Wed, 16 Jan 2019 14:51:39 +0100 Subject: [PATCH 6/6] Fixed documentation as it was written manually before --- README.md | 5 ++--- docs/book/usage.md | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ed2c8cf..2b192ff 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ array(5) { 'recursive_parameter_usage' => string(3) "qoo" 'parameterized_parameter_usage' => - string(3) "qoo" + string(3) "bar" 'parameters' => array(4) { 'foo' => @@ -57,7 +57,7 @@ array(5) { 'baz' => string(3) "qoo" 'quux' => - string(3) "qoo" + string(3) "bar" } 'bar.baz' => string(3) "qoo" @@ -65,7 +65,6 @@ array(5) { string(3) "bar" } } - ``` For more details, please refer to the [documentation](https://docs.zendframework.com/zend-config-aggregator-parameters/). diff --git a/docs/book/usage.md b/docs/book/usage.md index ecdcd5d..070c30d 100644 --- a/docs/book/usage.md +++ b/docs/book/usage.md @@ -63,7 +63,7 @@ array(5) { 'recursive_parameter_usage' => string(3) "qoo" 'parameterized_parameter_usage' => - string(3) "qoo" + string(3) "bar" 'parameters' => array(4) { 'foo' => @@ -73,7 +73,7 @@ array(5) { 'baz' => string(3) "qoo" 'quux' => - string(3) "qoo" + string(3) "bar" } 'bar.baz' => string(3) "qoo"