diff --git a/README.md b/README.md index 1793a96..2b192ff 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,24 +39,30 @@ 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) "bar" '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) "bar" } 'bar.baz' => string(3) "qoo" + 'bar.quux' => + string(3) "bar" } } ``` diff --git a/docs/book/usage.md b/docs/book/usage.md index 6b9e787..070c30d 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 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 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) "bar" '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) "bar" } 'bar.baz' => string(3) "qoo" + 'bar.quux' => + string(3) "bar" } } ``` diff --git a/src/ParameterPostProcessor.php b/src/ParameterPostProcessor.php index 7b231e2..98cdb44 100644 --- a/src/ParameterPostProcessor.php +++ b/src/ParameterPostProcessor.php @@ -15,7 +15,7 @@ class ParameterPostProcessor { /** - * @var ParameterBag + * @var array */ private $parameters; @@ -24,19 +24,15 @@ 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); try { + $parameters = $this->getResolvedParameters(); + array_walk_recursive($config, function (&$value) use ($parameters) { $value = $parameters->unescapeValue($parameters->resolveValue($value)); }); @@ -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,19 @@ 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() : ParameterBag + { + $resolved = $this->resolveNestedParameters($this->parameters); + $bag = new ParameterBag($resolved); + + $bag->resolve(); + 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); + } }