diff --git a/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php b/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php index 43022ddb7b..e91df9670b 100644 --- a/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php +++ b/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php @@ -41,6 +41,7 @@ class EnvVarProcessor implements EnvVarProcessorInterface 'float' => 'float', 'int' => 'int', 'json' => 'array', + 'key' => 'bool|int|float|string|array', 'resolve' => 'string', 'string' => 'string', ); @@ -53,6 +54,25 @@ class EnvVarProcessor implements EnvVarProcessorInterface { $i = strpos($name, ':'); + if ('key' === $prefix) { + if (false === $i) { + throw new RuntimeException(sprintf('Invalid configuration: env var "key:%s" does not contain a key specifier.', $name)); + } + + $next = substr($name, $i + 1); + $key = substr($name, 0, $i); + $array = $getEnv($next); + + if (!is_array($array)) { + throw new RuntimeException(sprintf('Resolved value of "%s" did not result in an array value.', $next)); + } + if (!array_key_exists($key, $array)) { + throw new RuntimeException(sprintf('Key "%s" not found in "%s" (resolved from "%s")', $key, json_encode($array), $next)); + } + + return $array[$key]; + } + if ('file' === $prefix) { if (!is_scalar($file = $getEnv($name))) { throw new RuntimeException(sprintf('Invalid file name: env var "%s" is non-scalar.', $name)); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterEnvVarProcessorsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterEnvVarProcessorsPassTest.php index e330017bcd..4681092ca7 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterEnvVarProcessorsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterEnvVarProcessorsPassTest.php @@ -38,6 +38,7 @@ class RegisterEnvVarProcessorsPassTest extends TestCase 'float' => array('float'), 'int' => array('int'), 'json' => array('array'), + 'key' => array('bool', 'int', 'float', 'string', 'array'), 'resolve' => array('string'), 'string' => array('string'), ); diff --git a/src/Symfony/Component/DependencyInjection/Tests/EnvVarProcessorTest.php b/src/Symfony/Component/DependencyInjection/Tests/EnvVarProcessorTest.php index 79b3e47c79..5cd3a68b21 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/EnvVarProcessorTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/EnvVarProcessorTest.php @@ -314,4 +314,110 @@ class EnvVarProcessorTest extends TestCase return 'foo'; }); } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedExceptionMessage Invalid configuration: env var "key:foo" does not contain a key specifier. + */ + public function testGetEnvKeyInvalidKey() + { + $processor = new EnvVarProcessor(new Container()); + + $processor->getEnv('key', 'foo', function ($name) { + $this->fail('Should not get here'); + }); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedExceptionMessage Resolved value of "foo" did not result in an array value. + * @dataProvider noArrayValues + */ + public function testGetEnvKeyNoArrayResult($value) + { + $processor = new EnvVarProcessor(new Container()); + + $processor->getEnv('key', 'index:foo', function ($name) use ($value) { + $this->assertSame('foo', $name); + + return $value; + }); + } + + public function noArrayValues() + { + return array( + array(null), + array('string'), + array(1), + array(true), + ); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedExceptionMessage Key "index" not found in + * @dataProvider invalidArrayValues + */ + public function testGetEnvKeyArrayKeyNotFound($value) + { + $processor = new EnvVarProcessor(new Container()); + + $processor->getEnv('key', 'index:foo', function ($name) use ($value) { + $this->assertSame('foo', $name); + + return $value; + }); + } + + public function invalidArrayValues() + { + return array( + array(array()), + array(array('index2' => 'value')), + array(array('index', 'index2')), + ); + } + + /** + * @dataProvider arrayValues + */ + public function testGetEnvKey($value) + { + $processor = new EnvVarProcessor(new Container()); + + $this->assertSame($value['index'], $processor->getEnv('key', 'index:foo', function ($name) use ($value) { + $this->assertSame('foo', $name); + + return $value; + })); + } + + public function arrayValues() + { + return array( + array(array('index' => 'password')), + array(array('index' => 'true')), + array(array('index' => false)), + array(array('index' => '1')), + array(array('index' => 1)), + array(array('index' => '1.1')), + array(array('index' => 1.1)), + array(array('index' => array())), + array(array('index' => array('val1', 'val2'))), + ); + } + + public function testGetEnvKeyChained() + { + $processor = new EnvVarProcessor(new Container()); + + $this->assertSame('password', $processor->getEnv('key', 'index:file:foo', function ($name) { + $this->assertSame('file:foo', $name); + + return array( + 'index' => 'password', + ); + })); + } }