[DI] Add a \"default\" EnvProcessor
This commit is contained in:
parent
8c24c35fe8
commit
aee4e33cdb
@ -1,6 +1,11 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
4.3.0
|
||||
-----
|
||||
|
||||
* added `%env(default:...)%` processor to fallback to a default value
|
||||
|
||||
4.2.0
|
||||
-----
|
||||
|
||||
|
@ -44,6 +44,7 @@ class EnvVarProcessor implements EnvVarProcessorInterface
|
||||
'json' => 'array',
|
||||
'key' => 'bool|int|float|string|array',
|
||||
'resolve' => 'string',
|
||||
'default' => 'bool|int|float|string|array',
|
||||
'string' => 'string',
|
||||
);
|
||||
}
|
||||
@ -57,7 +58,7 @@ class EnvVarProcessor implements EnvVarProcessorInterface
|
||||
|
||||
if ('key' === $prefix) {
|
||||
if (false === $i) {
|
||||
throw new RuntimeException(sprintf('Invalid configuration: env var "key:%s" does not contain a key specifier.', $name));
|
||||
throw new RuntimeException(sprintf('Invalid env "key:%s": a key specifier should be provided.', $name));
|
||||
}
|
||||
|
||||
$next = substr($name, $i + 1);
|
||||
@ -67,19 +68,39 @@ class EnvVarProcessor implements EnvVarProcessorInterface
|
||||
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));
|
||||
|
||||
if (!isset($array[$key]) && !array_key_exists($key, $array)) {
|
||||
throw new EnvNotFoundException(sprintf('Key "%s" not found in "%s" (resolved from "%s").', $key, json_encode($array), $next));
|
||||
}
|
||||
|
||||
return $array[$key];
|
||||
}
|
||||
|
||||
if ('default' === $prefix) {
|
||||
if (false === $i) {
|
||||
throw new RuntimeException(sprintf('Invalid env "default:%s": a fallback parameter should be provided.', $name));
|
||||
}
|
||||
|
||||
$next = substr($name, $i + 1);
|
||||
$default = substr($name, 0, $i);
|
||||
|
||||
if (!$this->container->hasParameter($default)) {
|
||||
throw new RuntimeException(sprintf('Invalid env fallback in "default:%s": parameter "%s" not found.', $name, $default));
|
||||
}
|
||||
|
||||
try {
|
||||
return $getEnv($next);
|
||||
} catch (EnvNotFoundException $e) {
|
||||
return $this->container->getParameter($default);
|
||||
}
|
||||
}
|
||||
|
||||
if ('file' === $prefix) {
|
||||
if (!is_scalar($file = $getEnv($name))) {
|
||||
throw new RuntimeException(sprintf('Invalid file name: env var "%s" is non-scalar.', $name));
|
||||
}
|
||||
if (!file_exists($file)) {
|
||||
throw new RuntimeException(sprintf('Env "file:%s" not found: %s does not exist.', $name, $file));
|
||||
throw new EnvNotFoundException(sprintf('File "%s" not found (resolved from "%s").', $file, $name));
|
||||
}
|
||||
|
||||
return file_get_contents($file);
|
||||
@ -95,7 +116,7 @@ class EnvVarProcessor implements EnvVarProcessorInterface
|
||||
$env = $_SERVER[$name];
|
||||
} elseif (false === ($env = getenv($name)) || null === $env) { // null is a possible value because of thread safety issues
|
||||
if (!$this->container->hasParameter("env($name)")) {
|
||||
throw new EnvNotFoundException($name);
|
||||
throw new EnvNotFoundException(sprintf('Environment variable not found: "%s".', $name));
|
||||
}
|
||||
|
||||
if (null === $env = $this->container->getParameter("env($name)")) {
|
||||
|
@ -18,8 +18,4 @@ namespace Symfony\Component\DependencyInjection\Exception;
|
||||
*/
|
||||
class EnvNotFoundException extends InvalidArgumentException
|
||||
{
|
||||
public function __construct(string $name)
|
||||
{
|
||||
parent::__construct(sprintf('Environment variable not found: "%s".', $name));
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ class RegisterEnvVarProcessorsPassTest extends TestCase
|
||||
'json' => array('array'),
|
||||
'key' => array('bool', 'int', 'float', 'string', 'array'),
|
||||
'resolve' => array('string'),
|
||||
'default' => array('bool', 'int', 'float', 'string', 'array'),
|
||||
'string' => array('string'),
|
||||
);
|
||||
|
||||
|
@ -439,6 +439,28 @@ class PhpDumperTest extends TestCase
|
||||
$this->assertSame(array('foo', 'bar'), $container->getParameter('hello'));
|
||||
}
|
||||
|
||||
public function testDumpedDefaultEnvParameters()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->setParameter('fallback_param', 'baz');
|
||||
$container->setParameter('fallback_env', '%env(foobar)%');
|
||||
$container->setParameter('env(foobar)', 'foobaz');
|
||||
$container->setParameter('env(foo)', '{"foo": "bar"}');
|
||||
$container->setParameter('hello', '%env(default:fallback_param:bar)%');
|
||||
$container->setParameter('hello-bar', '%env(default:fallback_env:key:baz:json:foo)%');
|
||||
$container->compile();
|
||||
|
||||
$dumper = new PhpDumper($container);
|
||||
$dumper->dump();
|
||||
|
||||
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_default_env.php', $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_DefaultParameters')));
|
||||
|
||||
require self::$fixturesPath.'/php/services_default_env.php';
|
||||
$container = new \Symfony_DI_PhpDumper_Test_DefaultParameters();
|
||||
$this->assertSame('baz', $container->getParameter('hello'));
|
||||
$this->assertSame('foobaz', $container->getParameter('hello-bar'));
|
||||
}
|
||||
|
||||
public function testDumpedJsonEnvParameters()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
|
@ -317,7 +317,7 @@ class EnvVarProcessorTest extends TestCase
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
|
||||
* @expectedExceptionMessage Invalid configuration: env var "key:foo" does not contain a key specifier.
|
||||
* @expectedExceptionMessage Invalid env "key:foo": a key specifier should be provided.
|
||||
*/
|
||||
public function testGetEnvKeyInvalidKey()
|
||||
{
|
||||
@ -355,7 +355,7 @@ class EnvVarProcessorTest extends TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\EnvNotFoundException
|
||||
* @expectedExceptionMessage Key "index" not found in
|
||||
* @dataProvider invalidArrayValues
|
||||
*/
|
||||
|
@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\DependencyInjection\Container;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\DependencyInjection\Exception\LogicException;
|
||||
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
|
||||
|
||||
/**
|
||||
* This class has been auto-generated
|
||||
* by the Symfony Dependency Injection Component.
|
||||
*
|
||||
* @final since Symfony 3.3
|
||||
*/
|
||||
class Symfony_DI_PhpDumper_Test_DefaultParameters extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->parameters = $this->getDefaultParameters();
|
||||
|
||||
$this->services = $this->privates = array();
|
||||
|
||||
$this->aliases = array();
|
||||
}
|
||||
|
||||
public function compile()
|
||||
{
|
||||
throw new LogicException('You cannot compile a dumped container that was already compiled.');
|
||||
}
|
||||
|
||||
public function isCompiled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getRemovedIds()
|
||||
{
|
||||
return array(
|
||||
'Psr\\Container\\ContainerInterface' => true,
|
||||
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
|
||||
);
|
||||
}
|
||||
|
||||
public function getParameter($name)
|
||||
{
|
||||
$name = (string) $name;
|
||||
|
||||
if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) {
|
||||
throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name));
|
||||
}
|
||||
if (isset($this->loadedDynamicParameters[$name])) {
|
||||
return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
|
||||
}
|
||||
|
||||
return $this->parameters[$name];
|
||||
}
|
||||
|
||||
public function hasParameter($name)
|
||||
{
|
||||
$name = (string) $name;
|
||||
|
||||
return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters);
|
||||
}
|
||||
|
||||
public function setParameter($name, $value)
|
||||
{
|
||||
throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
|
||||
}
|
||||
|
||||
public function getParameterBag()
|
||||
{
|
||||
if (null === $this->parameterBag) {
|
||||
$parameters = $this->parameters;
|
||||
foreach ($this->loadedDynamicParameters as $name => $loaded) {
|
||||
$parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
|
||||
}
|
||||
$this->parameterBag = new FrozenParameterBag($parameters);
|
||||
}
|
||||
|
||||
return $this->parameterBag;
|
||||
}
|
||||
|
||||
private $loadedDynamicParameters = array(
|
||||
'fallback_env' => false,
|
||||
'hello' => false,
|
||||
'hello-bar' => false,
|
||||
);
|
||||
private $dynamicParameters = array();
|
||||
|
||||
/**
|
||||
* Computes a dynamic parameter.
|
||||
*
|
||||
* @param string The name of the dynamic parameter to load
|
||||
*
|
||||
* @return mixed The value of the dynamic parameter
|
||||
*
|
||||
* @throws InvalidArgumentException When the dynamic parameter does not exist
|
||||
*/
|
||||
private function getDynamicParameter($name)
|
||||
{
|
||||
switch ($name) {
|
||||
case 'fallback_env': $value = $this->getEnv('foobar'); break;
|
||||
case 'hello': $value = $this->getEnv('default:fallback_param:bar'); break;
|
||||
case 'hello-bar': $value = $this->getEnv('default:fallback_env:key:baz:json:foo'); break;
|
||||
default: throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name));
|
||||
}
|
||||
$this->loadedDynamicParameters[$name] = true;
|
||||
|
||||
return $this->dynamicParameters[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default parameters.
|
||||
*
|
||||
* @return array An array of the default parameters
|
||||
*/
|
||||
protected function getDefaultParameters()
|
||||
{
|
||||
return array(
|
||||
'fallback_param' => 'baz',
|
||||
'env(foobar)' => 'foobaz',
|
||||
'env(foo)' => '{"foo": "bar"}',
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user