Skip to content

Commit 395fc87

Browse files
committed
Add an url EnvProcessor
1 parent a96308f commit 395fc87

File tree

6 files changed

+330
-0
lines changed

6 files changed

+330
-0
lines changed

src/Symfony/Component/DependencyInjection/CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ CHANGELOG
66

77
* added `%env(trim:...)%` processor to trim a string value
88
* added `%env(default:param_name:...)%` processor to fallback to a parameter or to null when using `%env(default::...)%`
9+
* added `%env(url:...)%` processor to convert an URL or DNS into an array of components
10+
* added `%env(query_string:...)%` processor to convert a query string into an array of key values
911
* added support for deprecating aliases
1012
* made `ContainerParametersResource` final and not implement `Serializable` anymore
1113
* added ability to define an index for a tagged collection

src/Symfony/Component/DependencyInjection/EnvVarProcessor.php

+32
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ public static function getProvidedTypes()
4141
'int' => 'int',
4242
'json' => 'array',
4343
'key' => 'bool|int|float|string|array',
44+
'url' => 'array',
45+
'query_string' => 'array',
4446
'resolve' => 'string',
4547
'default' => 'bool|int|float|string|array',
4648
'string' => 'string',
@@ -183,6 +185,36 @@ public function getEnv($prefix, $name, \Closure $getEnv)
183185
return $env;
184186
}
185187

188+
if ('url' === $prefix) {
189+
$parsedEnv = parse_url($env);
190+
191+
if (false === $parsedEnv) {
192+
throw new RuntimeException(sprintf('Invalid URL in env var "%s"', $name));
193+
}
194+
if (!isset($parsedEnv['scheme'], $parsedEnv['host'])) {
195+
throw new RuntimeException(sprintf('Invalid URL env var "%s": schema and host expected, %s given.', $name, $env));
196+
}
197+
$parsedEnv += [
198+
'port' => null,
199+
'user' => null,
200+
'pass' => null,
201+
'path' => null,
202+
'query' => null,
203+
'fragment' => null,
204+
];
205+
206+
// remove the '/' separator
207+
$parsedEnv['path'] = '/' === $parsedEnv['path'] ? null : substr($parsedEnv['path'], 1);
208+
209+
return $parsedEnv;
210+
}
211+
212+
if ('query_string' === $prefix) {
213+
parse_str($env, $result);
214+
215+
return $result;
216+
}
217+
186218
if ('resolve' === $prefix) {
187219
return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($name) {
188220
if (!isset($match[1])) {

src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterEnvVarProcessorsPassTest.php

+2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ public function testSimpleProcessor()
3939
'int' => ['int'],
4040
'json' => ['array'],
4141
'key' => ['bool', 'int', 'float', 'string', 'array'],
42+
'url' => ['array'],
43+
'query_string' => ['array'],
4244
'resolve' => ['string'],
4345
'default' => ['bool', 'int', 'float', 'string', 'array'],
4446
'string' => ['string'],

src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php

+46
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,52 @@ public function testDumpedDefaultEnvParameters()
497497
$this->assertSame('foobaz', $container->getParameter('hello-bar'));
498498
}
499499

500+
public function testDumpedUrlEnvParameters()
501+
{
502+
$container = new ContainerBuilder();
503+
$container->setParameter('env(foo)', 'postgres://user@localhost:5432/database?sslmode=disable');
504+
$container->setParameter('hello', '%env(url:foo)%');
505+
$container->compile();
506+
507+
$dumper = new PhpDumper($container);
508+
$dumper->dump();
509+
510+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_url_env.php', $dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_UrlParameters']));
511+
512+
require self::$fixturesPath.'/php/services_url_env.php';
513+
$container = new \Symfony_DI_PhpDumper_Test_UrlParameters();
514+
$this->assertSame([
515+
'scheme' => 'postgres',
516+
'host' => 'localhost',
517+
'port' => 5432,
518+
'user' => 'user',
519+
'path' => 'database',
520+
'query' => 'sslmode=disable',
521+
'pass' => null,
522+
'fragment' => null,
523+
], $container->getParameter('hello'));
524+
}
525+
526+
public function testDumpedQueryEnvParameters()
527+
{
528+
$container = new ContainerBuilder();
529+
$container->setParameter('env(foo)', 'foo=bar&baz[]=qux');
530+
$container->setParameter('hello', '%env(query_string:foo)%');
531+
$container->compile();
532+
533+
$dumper = new PhpDumper($container);
534+
$dumper->dump();
535+
536+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_query_string_env.php', $dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_QueryStringParameters']));
537+
538+
require self::$fixturesPath.'/php/services_query_string_env.php';
539+
$container = new \Symfony_DI_PhpDumper_Test_QueryStringParameters();
540+
$this->assertSame([
541+
'foo' => 'bar',
542+
'baz' => ['qux'],
543+
], $container->getParameter('hello'));
544+
}
545+
500546
public function testDumpedJsonEnvParameters()
501547
{
502548
$container = new ContainerBuilder();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<?php
2+
3+
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
4+
use Symfony\Component\DependencyInjection\ContainerInterface;
5+
use Symfony\Component\DependencyInjection\Container;
6+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
7+
use Symfony\Component\DependencyInjection\Exception\LogicException;
8+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
9+
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
10+
11+
/**
12+
* This class has been auto-generated
13+
* by the Symfony Dependency Injection Component.
14+
*
15+
* @final since Symfony 3.3
16+
*/
17+
class Symfony_DI_PhpDumper_Test_QueryStringParameters extends Container
18+
{
19+
private $parameters;
20+
private $targetDirs = [];
21+
22+
public function __construct()
23+
{
24+
$this->parameters = $this->getDefaultParameters();
25+
26+
$this->services = $this->privates = [];
27+
28+
$this->aliases = [];
29+
}
30+
31+
public function compile()
32+
{
33+
throw new LogicException('You cannot compile a dumped container that was already compiled.');
34+
}
35+
36+
public function isCompiled()
37+
{
38+
return true;
39+
}
40+
41+
public function getRemovedIds()
42+
{
43+
return [
44+
'Psr\\Container\\ContainerInterface' => true,
45+
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
46+
];
47+
}
48+
49+
public function getParameter($name)
50+
{
51+
$name = (string) $name;
52+
53+
if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) {
54+
throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name));
55+
}
56+
if (isset($this->loadedDynamicParameters[$name])) {
57+
return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
58+
}
59+
60+
return $this->parameters[$name];
61+
}
62+
63+
public function hasParameter($name)
64+
{
65+
$name = (string) $name;
66+
67+
return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters);
68+
}
69+
70+
public function setParameter($name, $value)
71+
{
72+
throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
73+
}
74+
75+
public function getParameterBag()
76+
{
77+
if (null === $this->parameterBag) {
78+
$parameters = $this->parameters;
79+
foreach ($this->loadedDynamicParameters as $name => $loaded) {
80+
$parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
81+
}
82+
$this->parameterBag = new FrozenParameterBag($parameters);
83+
}
84+
85+
return $this->parameterBag;
86+
}
87+
88+
private $loadedDynamicParameters = [
89+
'hello' => false,
90+
];
91+
private $dynamicParameters = [];
92+
93+
/**
94+
* Computes a dynamic parameter.
95+
*
96+
* @param string $name The name of the dynamic parameter to load
97+
*
98+
* @return mixed The value of the dynamic parameter
99+
*
100+
* @throws InvalidArgumentException When the dynamic parameter does not exist
101+
*/
102+
private function getDynamicParameter($name)
103+
{
104+
switch ($name) {
105+
case 'hello': $value = $this->getEnv('query_string:foo'); break;
106+
default: throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name));
107+
}
108+
$this->loadedDynamicParameters[$name] = true;
109+
110+
return $this->dynamicParameters[$name] = $value;
111+
}
112+
113+
/**
114+
* Gets the default parameters.
115+
*
116+
* @return array An array of the default parameters
117+
*/
118+
protected function getDefaultParameters()
119+
{
120+
return [
121+
'env(foo)' => 'foo=bar&baz[]=qux',
122+
];
123+
}
124+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<?php
2+
3+
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
4+
use Symfony\Component\DependencyInjection\ContainerInterface;
5+
use Symfony\Component\DependencyInjection\Container;
6+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
7+
use Symfony\Component\DependencyInjection\Exception\LogicException;
8+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
9+
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
10+
11+
/**
12+
* This class has been auto-generated
13+
* by the Symfony Dependency Injection Component.
14+
*
15+
* @final since Symfony 3.3
16+
*/
17+
class Symfony_DI_PhpDumper_Test_UrlParameters extends Container
18+
{
19+
private $parameters;
20+
private $targetDirs = [];
21+
22+
public function __construct()
23+
{
24+
$this->parameters = $this->getDefaultParameters();
25+
26+
$this->services = $this->privates = [];
27+
28+
$this->aliases = [];
29+
}
30+
31+
public function compile()
32+
{
33+
throw new LogicException('You cannot compile a dumped container that was already compiled.');
34+
}
35+
36+
public function isCompiled()
37+
{
38+
return true;
39+
}
40+
41+
public function getRemovedIds()
42+
{
43+
return [
44+
'Psr\\Container\\ContainerInterface' => true,
45+
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
46+
];
47+
}
48+
49+
public function getParameter($name)
50+
{
51+
$name = (string) $name;
52+
53+
if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) {
54+
throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name));
55+
}
56+
if (isset($this->loadedDynamicParameters[$name])) {
57+
return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
58+
}
59+
60+
return $this->parameters[$name];
61+
}
62+
63+
public function hasParameter($name)
64+
{
65+
$name = (string) $name;
66+
67+
return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters);
68+
}
69+
70+
public function setParameter($name, $value)
71+
{
72+
throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
73+
}
74+
75+
public function getParameterBag()
76+
{
77+
if (null === $this->parameterBag) {
78+
$parameters = $this->parameters;
79+
foreach ($this->loadedDynamicParameters as $name => $loaded) {
80+
$parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
81+
}
82+
$this->parameterBag = new FrozenParameterBag($parameters);
83+
}
84+
85+
return $this->parameterBag;
86+
}
87+
88+
private $loadedDynamicParameters = [
89+
'hello' => false,
90+
];
91+
private $dynamicParameters = [];
92+
93+
/**
94+
* Computes a dynamic parameter.
95+
*
96+
* @param string $name The name of the dynamic parameter to load
97+
*
98+
* @return mixed The value of the dynamic parameter
99+
*
100+
* @throws InvalidArgumentException When the dynamic parameter does not exist
101+
*/
102+
private function getDynamicParameter($name)
103+
{
104+
switch ($name) {
105+
case 'hello': $value = $this->getEnv('url:foo'); break;
106+
default: throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name));
107+
}
108+
$this->loadedDynamicParameters[$name] = true;
109+
110+
return $this->dynamicParameters[$name] = $value;
111+
}
112+
113+
/**
114+
* Gets the default parameters.
115+
*
116+
* @return array An array of the default parameters
117+
*/
118+
protected function getDefaultParameters()
119+
{
120+
return [
121+
'env(foo)' => 'postgres://user@localhost:5432/database?sslmode=disable',
122+
];
123+
}
124+
}

0 commit comments

Comments
 (0)