Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 1f92e45

Browse filesBrowse files
[DI] Allow processing env vars
1 parent 2fde094 commit 1f92e45
Copy full SHA for 1f92e45

18 files changed

+977
-25
lines changed

‎src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
use Symfony\Component\DependencyInjection\ContainerBuilder;
3737
use Symfony\Component\DependencyInjection\ContainerInterface;
3838
use Symfony\Component\DependencyInjection\Definition;
39+
use Symfony\Component\DependencyInjection\EnvVarProcessorInterface;
3940
use Symfony\Component\DependencyInjection\Exception\LogicException;
4041
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
4142
use Symfony\Component\DependencyInjection\Reference;
@@ -283,6 +284,8 @@ public function load(array $configs, ContainerBuilder $container)
283284
->addTag('console.command');
284285
$container->registerForAutoconfiguration(ResourceCheckerInterface::class)
285286
->addTag('config_cache.resource_checker');
287+
$container->registerForAutoconfiguration(EnvVarProcessorInterface::class)
288+
->addTag('container.env_var_processor');
286289
$container->registerForAutoconfiguration(ServiceSubscriberInterface::class)
287290
->addTag('container.service_subscriber');
288291
$container->registerForAutoconfiguration(ArgumentValueResolverInterface::class)

‎src/Symfony/Component/DependencyInjection/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ CHANGELOG
44
3.4.0
55
-----
66

7+
* added `EnvVarProcessorInterface` and corresponding "container.env_var_processor" tag for processing env vars
78
* added support for ignore-on-uninitialized references
89
* deprecated service auto-registration while autowiring
910
* deprecated the ability to check for the initialization of a private service with the `Container::initialized()` method

‎src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public function __construct()
4343
100 => array(
4444
$resolveClassPass = new ResolveClassPass(),
4545
new ResolveInstanceofConditionalsPass(),
46+
new RegisterEnvVarProcessorsPass(),
4647
),
4748
);
4849

+72Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Compiler;
13+
14+
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
15+
use Symfony\Component\DependencyInjection\ContainerBuilder;
16+
use Symfony\Component\DependencyInjection\EnvVarProcessorInterface;
17+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
18+
use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
19+
use Symfony\Component\DependencyInjection\ServiceLocator;
20+
use Symfony\Component\DependencyInjection\Reference;
21+
22+
/**
23+
* Creates the container.env_var_processors_locator service.
24+
*
25+
* @author Nicolas Grekas <p@tchwork.com>
26+
*/
27+
class RegisterEnvVarProcessorsPass implements CompilerPassInterface
28+
{
29+
private static $allowedTypes = array('array', 'bool', 'float', 'int', 'string');
30+
31+
public function process(ContainerBuilder $container)
32+
{
33+
$bag = $container->getParameterBag();
34+
$types = array();
35+
$processors = array();
36+
foreach ($container->findTaggedServiceIds('container.env_var_processor') as $id => $tags) {
37+
foreach ($tags as $attr) {
38+
if (!$r = $container->getReflectionClass($class = $container->getDefinition($id)->getClass())) {
39+
throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
40+
} elseif (!$r->isSubclassOf(EnvVarProcessorInterface::class)) {
41+
throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, EnvVarProcessorInterface::class));
42+
}
43+
foreach ($class::getProvidedTypes() as $prefix => $type) {
44+
$processors[$prefix] = new ServiceClosureArgument(new Reference($id));
45+
$types[$prefix] = self::validateProvidedTypes($type, $class);
46+
}
47+
}
48+
}
49+
50+
if ($processors) {
51+
if ($bag instanceof EnvPlaceholderParameterBag) {
52+
$bag->setProvidedTypes($types);
53+
}
54+
$container->register('container.env_var_processors_locator', ServiceLocator::class)
55+
->setArguments(array($processors))
56+
;
57+
}
58+
}
59+
60+
private static function validateProvidedTypes($types, $class)
61+
{
62+
$types = explode('|', $types);
63+
64+
foreach ($types as $type) {
65+
if (!in_array($type, self::$allowedTypes)) {
66+
throw new InvalidArgumentException(sprintf('Invalid type "%s" returned by "%s::getProvidedTypes()", expected one of "%s".', $type, $class, implode('", "', self::$allowedTypes)));
67+
}
68+
}
69+
70+
return $types;
71+
}
72+
}

‎src/Symfony/Component/DependencyInjection/Container.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Container.php
+27-10Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException;
1515
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
16+
use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException;
1617
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
1718
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
1819
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
@@ -48,6 +49,7 @@ class Container implements ResettableContainerInterface
4849
protected $methodMap = array();
4950
protected $aliases = array();
5051
protected $loading = array();
52+
protected $resolving = array();
5153

5254
/**
5355
* @internal
@@ -62,6 +64,7 @@ class Container implements ResettableContainerInterface
6264
private $underscoreMap = array('_' => '', '.' => '_', '\\' => '_');
6365
private $envCache = array();
6466
private $compiled = false;
67+
private $getEnv;
6568

6669
/**
6770
* @param ParameterBagInterface $parameterBag A ParameterBagInterface instance
@@ -438,23 +441,37 @@ protected function load($file)
438441
*/
439442
protected function getEnv($name)
440443
{
444+
if (isset($this->resolving[$envName = "env($name)"])) {
445+
throw new ParameterCircularReferenceException(array_keys($this->resolving));
446+
}
441447
if (isset($this->envCache[$name]) || array_key_exists($name, $this->envCache)) {
442448
return $this->envCache[$name];
443449
}
444-
if (isset($_SERVER[$name]) && 0 !== strpos($name, 'HTTP_')) {
445-
return $this->envCache[$name] = $_SERVER[$name];
446-
}
447-
if (isset($_ENV[$name])) {
448-
return $this->envCache[$name] = $_ENV[$name];
450+
if (!$this->has($id = 'container.env_var_processors_locator')) {
451+
$this->set($id, new ServiceLocator(array()));
449452
}
450-
if (false !== ($env = getenv($name)) && null !== $env) { // null is a possible value because of thread safety issues
451-
return $this->envCache[$name] = $env;
453+
if (!$this->getEnv) {
454+
$this->getEnv = new \ReflectionMethod($this, __FUNCTION__);
455+
$this->getEnv->setAccessible(true);
456+
$this->getEnv = $this->getEnv->getClosure($this);
452457
}
453-
if (!$this->hasParameter("env($name)")) {
454-
throw new EnvNotFoundException($name);
458+
$processors = $this->get($id);
459+
460+
if (false !== $i = strpos($name, ':')) {
461+
$prefix = substr($name, 0, $i);
462+
$localName = substr($name, 1 + $i);
463+
} else {
464+
$prefix = 'string';
465+
$localName = $name;
455466
}
467+
$processor = $processors->has($prefix) ? $processors->get($prefix) : new EnvVarProcessor($this);
456468

457-
return $this->envCache[$name] = $this->getParameter("env($name)");
469+
$this->resolving[$envName] = true;
470+
try {
471+
return $this->envCache[$name] = $processor->getEnv($prefix, $localName, $this->getEnv);
472+
} finally {
473+
unset($this->resolving[$envName]);
474+
}
458475
}
459476

460477
/**

‎src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/ContainerBuilder.php
+10-4Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,20 +1472,26 @@ public static function hash($value)
14721472
protected function getEnv($name)
14731473
{
14741474
$value = parent::getEnv($name);
1475+
$bag = $this->getParameterBag();
14751476

1476-
if (!is_string($value) || !$this->getParameterBag() instanceof EnvPlaceholderParameterBag) {
1477+
if (!is_string($value) || !$bag instanceof EnvPlaceholderParameterBag) {
14771478
return $value;
14781479
}
14791480

1480-
foreach ($this->getParameterBag()->getEnvPlaceholders() as $env => $placeholders) {
1481+
foreach ($bag->getEnvPlaceholders() as $env => $placeholders) {
14811482
if (isset($placeholders[$value])) {
1482-
$bag = new ParameterBag($this->getParameterBag()->all());
1483+
$bag = new ParameterBag($bag->all());
14831484

14841485
return $bag->unescapeValue($bag->get("env($name)"));
14851486
}
14861487
}
14871488

1488-
return $value;
1489+
$this->resolving["env($name)"] = true;
1490+
try {
1491+
return $bag->unescapeValue($this->resolveEnvPlaceholders($bag->escapeValue($value), true));
1492+
} finally {
1493+
unset($this->resolving["env($name)"]);
1494+
}
14891495
}
14901496

14911497
/**

‎src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
+9-6Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,7 +1112,7 @@ private function addDefaultParametersMethod()
11121112
$export = $this->exportParameters(array($value));
11131113
$export = explode('0 => ', substr(rtrim($export, " )\n"), 7, -1), 2);
11141114

1115-
if (preg_match("/\\\$this->(?:getEnv\('\w++'\)|targetDirs\[\d++\])/", $export[1])) {
1115+
if (preg_match("/\\\$this->(?:getEnv\('(?:\w++:)*+\w++'\)|targetDirs\[\d++\])/", $export[1])) {
11161116
$dynamicPhp[$key] = sprintf('%scase %s: $value = %s; break;', $export[0], $this->export($key), $export[1]);
11171117
} else {
11181118
$php[] = sprintf('%s%s => %s,', $export[0], $this->export($key), $export[1]);
@@ -1685,7 +1685,7 @@ private function dumpParameter($name)
16851685
return $dumpedValue;
16861686
}
16871687

1688-
if (!preg_match("/\\\$this->(?:getEnv\('\w++'\)|targetDirs\[\d++\])/", $dumpedValue)) {
1688+
if (!preg_match("/\\\$this->(?:getEnv\('(?:\w++:)*+\w++'\)|targetDirs\[\d++\])/", $dumpedValue)) {
16891689
return sprintf("\$this->parameters['%s']", $name);
16901690
}
16911691
}
@@ -1880,13 +1880,16 @@ private function doExport($value)
18801880
{
18811881
$export = var_export($value, true);
18821882

1883-
if ("'" === $export[0] && $export !== $resolvedExport = $this->container->resolveEnvPlaceholders($export, "'.\$this->getEnv('%s').'")) {
1883+
if ("'" === $export[0] && $export !== $resolvedExport = $this->container->resolveEnvPlaceholders($export, "'.\$this->getEnv('string:%s').'")) {
18841884
$export = $resolvedExport;
1885-
if ("'" === $export[1]) {
1886-
$export = substr($export, 3);
1887-
}
18881885
if (".''" === substr($export, -3)) {
18891886
$export = substr($export, 0, -3);
1887+
if ("'" === $export[1]) {
1888+
$export = substr_replace($export, '', 18, 7);
1889+
}
1890+
}
1891+
if ("'" === $export[1]) {
1892+
$export = substr($export, 3);
18901893
}
18911894
}
18921895

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.