-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[DependencyInjection] added a way to reference dynamic environment variables in service definitions #16403
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DependencyInjection] added a way to reference dynamic environment variables in service definitions #16403
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ | |
use Symfony\Component\DependencyInjection\Alias; | ||
use Symfony\Component\DependencyInjection\ContainerInterface; | ||
use Symfony\Component\DependencyInjection\Definition; | ||
use Symfony\Component\DependencyInjection\EnvVariable; | ||
use Symfony\Component\DependencyInjection\Parameter; | ||
use Symfony\Component\DependencyInjection\Reference; | ||
use Symfony\Component\DependencyInjection\Exception\RuntimeException; | ||
|
@@ -274,6 +275,8 @@ private function dumpValue($value) | |
return $code; | ||
} elseif ($value instanceof Reference) { | ||
return $this->getServiceCall((string) $value, $value); | ||
} elseif ($value instanceof EnvVariable) { | ||
return sprintf('$%s$', (string) $value); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
} elseif ($value instanceof Parameter) { | ||
return $this->getParameterCall((string) $value); | ||
} elseif ($value instanceof Expression) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <fabien@symfony.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\DependencyInjection; | ||
|
||
/** | ||
* Represents an environment variable value. | ||
* | ||
* @author Fabien Potencier <fabien@symfony.com> | ||
*/ | ||
class EnvVariable | ||
{ | ||
private $id; | ||
|
||
/** | ||
* Constructor. | ||
* | ||
* @param string $id The environment variable name | ||
*/ | ||
public function __construct($id) | ||
{ | ||
$this->id = $id; | ||
} | ||
|
||
/** | ||
* __toString. | ||
* | ||
* @return string The environment variable name | ||
*/ | ||
public function __toString() | ||
{ | ||
return (string) $this->id; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO is better to cast to a string in the constructor. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. or dont cast at all. The parameter is already defined as string. |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,7 @@ | |
|
||
namespace Symfony\Component\DependencyInjection\ParameterBag; | ||
|
||
use Symfony\Component\DependencyInjection\EnvVariable; | ||
use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; | ||
use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException; | ||
use Symfony\Component\DependencyInjection\Exception\RuntimeException; | ||
|
@@ -167,12 +168,12 @@ public function resolve() | |
* @throws ParameterCircularReferenceException if a circular reference if detected | ||
* @throws RuntimeException when a given parameter has a type problem. | ||
*/ | ||
public function resolveValue($value, array $resolving = array()) | ||
public function resolveValue($value, array $resolving = array(), $protectEnvVariables = false) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The new |
||
{ | ||
if (is_array($value)) { | ||
$args = array(); | ||
foreach ($value as $k => $v) { | ||
$args[$this->resolveValue($k, $resolving)] = $this->resolveValue($v, $resolving); | ||
$args[$this->resolveValue($k, $resolving, $protectEnvVariables)] = $this->resolveValue($v, $resolving, $protectEnvVariables); | ||
} | ||
|
||
return $args; | ||
|
@@ -182,7 +183,7 @@ public function resolveValue($value, array $resolving = array()) | |
return $value; | ||
} | ||
|
||
return $this->resolveString($value, $resolving); | ||
return $this->resolveString($value, $resolving, $protectEnvVariables); | ||
} | ||
|
||
/** | ||
|
@@ -197,7 +198,7 @@ public function resolveValue($value, array $resolving = array()) | |
* @throws ParameterCircularReferenceException if a circular reference if detected | ||
* @throws RuntimeException when a given parameter has a type problem. | ||
*/ | ||
public function resolveString($value, array $resolving = array()) | ||
public function resolveString($value, array $resolving = array(), $protectEnvVariables = false) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here |
||
{ | ||
// we do this to deal with non string values (Boolean, integer, ...) | ||
// as the preg_replace_callback throw an exception when trying | ||
|
@@ -211,12 +212,20 @@ public function resolveString($value, array $resolving = array()) | |
|
||
$resolving[$key] = true; | ||
|
||
return $this->resolved ? $this->get($key) : $this->resolveValue($this->get($key), $resolving); | ||
return $this->resolved ? $this->get($key) : $this->resolveValue($this->get($key), $resolving, $protectEnvVariables); | ||
} | ||
|
||
if (preg_match('/^\$([^\$\s]+)\$$/', $value, $match)) { | ||
if ($protectEnvVariables) { | ||
return new EnvVariable($match[1]); | ||
} | ||
|
||
return getenv($match[1]); | ||
} | ||
|
||
$self = $this; | ||
|
||
return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($self, $resolving, $value) { | ||
return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($self, $resolving, $value, $protectEnvVariables) { | ||
// skip %% | ||
if (!isset($match[1])) { | ||
return '%%'; | ||
|
@@ -236,7 +245,7 @@ public function resolveString($value, array $resolving = array()) | |
$resolved = (string) $resolved; | ||
$resolving[$key] = true; | ||
|
||
return $self->isResolved() ? $resolved : $self->resolveString($resolved, $resolving); | ||
return $self->isResolved() ? $resolved : $self->resolveString($resolved, $resolving, $protectEnvVariables); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The variable is missing from the |
||
}, $value); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <fabien@symfony.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\DependencyInjection\Tests; | ||
|
||
use Symfony\Component\DependencyInjection\EnvVariable; | ||
|
||
class EnvVariableTest extends \PHPUnit_Framework_TestCase | ||
{ | ||
public function testConstructor() | ||
{ | ||
$ref = new EnvVariable('foo'); | ||
$this->assertEquals('foo', (string) $ref, '__construct() sets the id of the env variable, which is used for the __toString() method'); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is will also match
$foo'boom$
making it possible to unwillingly inject PHP code (as the value is not escaped or anything when it's used indumpEnvVariable
).And the $$ will not match, but is not normalized to a single $ in the else-block.