[DI] Allow injecting ENV parameters at runtime using %env(MY_ENV_VAR)% syntax
This commit is contained in:
parent
0cf50e2788
commit
bac2132aeb
@ -12,6 +12,7 @@
|
||||
namespace Symfony\Component\DependencyInjection\Compiler;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Exception\EnvParameterException;
|
||||
|
||||
/**
|
||||
* This class is used to remove circular dependencies between individual passes.
|
||||
@ -108,8 +109,29 @@ class Compiler
|
||||
*/
|
||||
public function compile(ContainerBuilder $container)
|
||||
{
|
||||
foreach ($this->passConfig->getPasses() as $pass) {
|
||||
$pass->process($container);
|
||||
try {
|
||||
foreach ($this->passConfig->getPasses() as $pass) {
|
||||
$pass->process($container);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$usedEnvs = array();
|
||||
$prev = $e;
|
||||
|
||||
do {
|
||||
$msg = $prev->getMessage();
|
||||
|
||||
if ($msg !== $resolvedMsg = $container->resolveEnvPlaceholders($msg, null, $usedEnvs)) {
|
||||
$r = new \ReflectionProperty($prev, 'message');
|
||||
$r->setAccessible(true);
|
||||
$r->setValue($prev, $resolvedMsg);
|
||||
}
|
||||
} while ($prev = $prev->getPrevious());
|
||||
|
||||
if ($usedEnvs) {
|
||||
$e = new EnvParameterException($usedEnvs, $e);
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,11 +11,12 @@
|
||||
|
||||
namespace Symfony\Component\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
|
||||
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
|
||||
|
||||
/**
|
||||
@ -70,13 +71,14 @@ class Container implements ResettableContainerInterface
|
||||
protected $loading = array();
|
||||
|
||||
private $underscoreMap = array('_' => '', '.' => '_', '\\' => '_');
|
||||
private $envCache = array();
|
||||
|
||||
/**
|
||||
* @param ParameterBagInterface $parameterBag A ParameterBagInterface instance
|
||||
*/
|
||||
public function __construct(ParameterBagInterface $parameterBag = null)
|
||||
{
|
||||
$this->parameterBag = $parameterBag ?: new ParameterBag();
|
||||
$this->parameterBag = $parameterBag ?: new EnvPlaceholderParameterBag();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -372,6 +374,33 @@ class Container implements ResettableContainerInterface
|
||||
return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), str_replace('_', '.', $id)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a variable from the environment.
|
||||
*
|
||||
* @param string The name of the environment variable
|
||||
*
|
||||
* @return scalar The value to use for the provided environment variable name
|
||||
*
|
||||
* @throws EnvNotFoundException When the environment variable is not found and has no default value
|
||||
*/
|
||||
protected function getEnv($name)
|
||||
{
|
||||
if (isset($this->envCache[$name]) || array_key_exists($name, $this->envCache)) {
|
||||
return $this->envCache[$name];
|
||||
}
|
||||
if (isset($_ENV[$name])) {
|
||||
return $this->envCache[$name] = $_ENV[$name];
|
||||
}
|
||||
if (false !== $env = getenv($name)) {
|
||||
return $this->envCache[$name] = $env;
|
||||
}
|
||||
if (!$this->hasParameter("env($name)")) {
|
||||
throw new EnvNotFoundException($name);
|
||||
}
|
||||
|
||||
return $this->envCache[$name] = $this->getParameter("env($name)");
|
||||
}
|
||||
|
||||
private function __clone()
|
||||
{
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
|
||||
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
|
||||
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
|
||||
use Symfony\Component\Config\Resource\FileResource;
|
||||
use Symfony\Component\Config\Resource\ResourceInterface;
|
||||
use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface;
|
||||
@ -89,6 +90,16 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
*/
|
||||
private $usedTags = array();
|
||||
|
||||
/**
|
||||
* @var string[][] A map of env var names to their placeholders
|
||||
*/
|
||||
private $envPlaceholders = array();
|
||||
|
||||
/**
|
||||
* @var int[] A map of env vars to their resolution counter.
|
||||
*/
|
||||
private $envCounters = array();
|
||||
|
||||
private $compiled = false;
|
||||
|
||||
/**
|
||||
@ -481,6 +492,18 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
|
||||
$this->extensionConfigs[$name] = array_merge($this->extensionConfigs[$name], $container->getExtensionConfig($name));
|
||||
}
|
||||
|
||||
if ($this->getParameterBag() instanceof EnvPlaceholderParameterBag && $container->getParameterBag() instanceof EnvPlaceholderParameterBag) {
|
||||
$this->getParameterBag()->mergeEnvPlaceholders($container->getParameterBag());
|
||||
}
|
||||
|
||||
foreach ($container->envCounters as $env => $count) {
|
||||
if (!isset($this->envCounters[$env])) {
|
||||
$this->envCounters[$env] = $count;
|
||||
} else {
|
||||
$this->envCounters[$env] += $count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -551,8 +574,11 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
}
|
||||
|
||||
$this->extensionConfigs = array();
|
||||
$bag = $this->getParameterBag();
|
||||
|
||||
parent::compile();
|
||||
|
||||
$this->envPlaceholders = $bag instanceof EnvPlaceholderParameterBag ? $bag->getEnvPlaceholders() : array();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -995,6 +1021,56 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
return $this->expressionLanguageProviders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves env parameter placeholders in a string.
|
||||
*
|
||||
* @param string $string The string to resolve
|
||||
* @param string|null $format A sprintf() format to use as replacement for env placeholders or null to use the default parameter format
|
||||
* @param array &$usedEnvs Env vars found while resolving are added to this array
|
||||
*
|
||||
* @return string The string with env parameters resolved
|
||||
*/
|
||||
public function resolveEnvPlaceholders($string, $format = null, array &$usedEnvs = null)
|
||||
{
|
||||
$bag = $this->getParameterBag();
|
||||
$envPlaceholders = $bag instanceof EnvPlaceholderParameterBag ? $bag->getEnvPlaceholders() : $this->envPlaceholders;
|
||||
|
||||
if (null === $format) {
|
||||
$format = '%%env(%s)%%';
|
||||
}
|
||||
|
||||
foreach ($envPlaceholders as $env => $placeholders) {
|
||||
foreach ($placeholders as $placeholder) {
|
||||
if (false !== stripos($string, $placeholder)) {
|
||||
$string = str_ireplace($placeholder, sprintf($format, $env), $string);
|
||||
$usedEnvs[$env] = $env;
|
||||
$this->envCounters[$env] = isset($this->envCounters[$env]) ? 1 + $this->envCounters[$env] : 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get statistics about env usage.
|
||||
*
|
||||
* @return int[] The number of time each env vars has been resolved
|
||||
*/
|
||||
public function getEnvCounters()
|
||||
{
|
||||
$bag = $this->getParameterBag();
|
||||
$envPlaceholders = $bag instanceof EnvPlaceholderParameterBag ? $bag->getEnvPlaceholders() : $this->envPlaceholders;
|
||||
|
||||
foreach ($envPlaceholders as $env => $placeholders) {
|
||||
if (!isset($this->envCounters[$env])) {
|
||||
$this->envCounters[$env] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->envCounters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Service Conditionals.
|
||||
*
|
||||
|
@ -81,7 +81,7 @@ class GraphvizDumper extends Dumper
|
||||
}
|
||||
}
|
||||
|
||||
return $this->startDot().$this->addNodes().$this->addEdges().$this->endDot();
|
||||
return $this->container->resolveEnvPlaceholders($this->startDot().$this->addNodes().$this->addEdges().$this->endDot(), '__ENV_%s__');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -18,6 +18,7 @@ use Symfony\Component\DependencyInjection\Container;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\DependencyInjection\Parameter;
|
||||
use Symfony\Component\DependencyInjection\Exception\EnvParameterException;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
|
||||
@ -98,6 +99,8 @@ class PhpDumper extends Dumper
|
||||
* @param array $options An array of options
|
||||
*
|
||||
* @return string A PHP class representing of the service container
|
||||
*
|
||||
* @throws EnvParameterException When an env var exists but has not been dumped
|
||||
*/
|
||||
public function dump(array $options = array())
|
||||
{
|
||||
@ -156,6 +159,16 @@ class PhpDumper extends Dumper
|
||||
;
|
||||
$this->targetDirRegex = null;
|
||||
|
||||
$unusedEnvs = array();
|
||||
foreach ($this->container->getEnvCounters() as $env => $use) {
|
||||
if (!$use) {
|
||||
$unusedEnvs[] = $env;
|
||||
}
|
||||
}
|
||||
if ($unusedEnvs) {
|
||||
throw new EnvParameterException($unusedEnvs);
|
||||
}
|
||||
|
||||
return $code;
|
||||
}
|
||||
|
||||
@ -384,7 +397,7 @@ class PhpDumper extends Dumper
|
||||
|
||||
$class = $this->dumpValue($class);
|
||||
|
||||
if (0 === strpos($class, "'") && !preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
|
||||
if (0 === strpos($class, "'") && false === strpos($class, '$') && !preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
|
||||
throw new InvalidArgumentException(sprintf('"%s" is not a valid class name for the "%s" service.', $class, $id));
|
||||
}
|
||||
|
||||
@ -539,7 +552,7 @@ class PhpDumper extends Dumper
|
||||
|
||||
$class = $this->dumpValue($callable[0]);
|
||||
// If the class is a string we can optimize call_user_func away
|
||||
if (strpos($class, "'") === 0) {
|
||||
if (0 === strpos($class, "'") && false === strpos($class, '$')) {
|
||||
return sprintf(" %s::%s(\$%s);\n", $this->dumpLiteralClass($class), $callable[1], $variableName);
|
||||
}
|
||||
|
||||
@ -572,6 +585,7 @@ class PhpDumper extends Dumper
|
||||
if ($definition->isSynthetic()) {
|
||||
$return[] = '@throws RuntimeException always since this service is expected to be injected dynamically';
|
||||
} elseif ($class = $definition->getClass()) {
|
||||
$class = $this->container->resolveEnvPlaceholders($class);
|
||||
$return[] = sprintf('@return %s A %s instance', 0 === strpos($class, '%') ? 'object' : '\\'.ltrim($class, '\\'), ltrim($class, '\\'));
|
||||
} elseif ($definition->getFactory()) {
|
||||
$factory = $definition->getFactory();
|
||||
@ -595,6 +609,7 @@ class PhpDumper extends Dumper
|
||||
}
|
||||
|
||||
$return = str_replace("\n * \n", "\n *\n", implode("\n * ", $return));
|
||||
$return = $this->container->resolveEnvPlaceholders($return);
|
||||
|
||||
$doc = '';
|
||||
if ($definition->isShared()) {
|
||||
@ -654,7 +669,7 @@ EOF;
|
||||
$code .= sprintf(" throw new RuntimeException('You have requested a synthetic service (\"%s\"). The DIC does not know how to construct this service.');\n }\n", $id);
|
||||
} else {
|
||||
if ($definition->isDeprecated()) {
|
||||
$code .= sprintf(" @trigger_error(%s, E_USER_DEPRECATED);\n\n", var_export($definition->getDeprecationMessage($id), true));
|
||||
$code .= sprintf(" @trigger_error(%s, E_USER_DEPRECATED);\n\n", $this->export($definition->getDeprecationMessage($id)));
|
||||
}
|
||||
|
||||
$code .=
|
||||
@ -720,7 +735,7 @@ EOF;
|
||||
|
||||
$class = $this->dumpValue($callable[0]);
|
||||
// If the class is a string we can optimize call_user_func away
|
||||
if (strpos($class, "'") === 0) {
|
||||
if (0 === strpos($class, "'") && false === strpos($class, '$')) {
|
||||
if ("''" === $class) {
|
||||
throw new RuntimeException(sprintf('Cannot dump definition: The "%s" service is defined to be created by a factory but is missing the service reference, did you forget to define the factory service id or class?', $id));
|
||||
}
|
||||
@ -735,7 +750,7 @@ EOF;
|
||||
return sprintf(" $return{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? ', '.implode(', ', $arguments) : '');
|
||||
}
|
||||
|
||||
return sprintf(" $return{$instantiation}\\%s(%s);\n", $callable, $arguments ? implode(', ', $arguments) : '');
|
||||
return sprintf(" $return{$instantiation}%s(%s);\n", $this->dumpLiteralClass($this->dumpValue($callable)), $arguments ? implode(', ', $arguments) : '');
|
||||
}
|
||||
|
||||
if (false !== strpos($class, '$')) {
|
||||
@ -904,7 +919,7 @@ EOF;
|
||||
$code = " \$this->methodMap = array(\n";
|
||||
ksort($definitions);
|
||||
foreach ($definitions as $id => $definition) {
|
||||
$code .= ' '.var_export($id, true).' => '.var_export($this->generateMethodName($id), true).",\n";
|
||||
$code .= ' '.$this->export($id).' => '.$this->export($this->generateMethodName($id)).",\n";
|
||||
}
|
||||
|
||||
return $code." );\n";
|
||||
@ -925,7 +940,7 @@ EOF;
|
||||
ksort($definitions);
|
||||
foreach ($definitions as $id => $definition) {
|
||||
if (!$definition->isPublic()) {
|
||||
$code .= ' '.var_export($id, true)." => true,\n";
|
||||
$code .= ' '.$this->export($id)." => true,\n";
|
||||
}
|
||||
}
|
||||
|
||||
@ -962,7 +977,7 @@ EOF;
|
||||
while (isset($aliases[$id])) {
|
||||
$id = (string) $aliases[$id];
|
||||
}
|
||||
$code .= ' '.var_export($alias, true).' => '.var_export($id, true).",\n";
|
||||
$code .= ' '.$this->export($alias).' => '.$this->export($id).",\n";
|
||||
}
|
||||
|
||||
return $code." );\n";
|
||||
@ -979,7 +994,23 @@ EOF;
|
||||
return '';
|
||||
}
|
||||
|
||||
$parameters = $this->exportParameters($this->container->getParameterBag()->all());
|
||||
$php = array();
|
||||
$dynamicPhp = array();
|
||||
|
||||
foreach ($this->container->getParameterBag()->all() as $key => $value) {
|
||||
if ($key !== $resolvedKey = $this->container->resolveEnvPlaceholders($key)) {
|
||||
throw new InvalidArgumentException(sprintf('Parameter name cannot use env parameters: %s.', $resolvedKey));
|
||||
}
|
||||
$export = $this->exportParameters(array($value));
|
||||
$export = explode('0 => ', substr(rtrim($export, " )\n"), 7, -1), 2);
|
||||
|
||||
if (preg_match("/\\\$this->(?:getEnv\('\w++'\)|targetDirs\[\d++\])/", $export[1])) {
|
||||
$dynamicPhp[$key] = sprintf('%scase %s: $value = %s; break;', $export[0], $this->export($key), $export[1]);
|
||||
} else {
|
||||
$php[] = sprintf('%s%s => %s,', $export[0], $this->export($key), $export[1]);
|
||||
}
|
||||
}
|
||||
$parameters = sprintf("array(\n%s\n%s)", implode("\n", $php), str_repeat(' ', 8));
|
||||
|
||||
$code = '';
|
||||
if ($this->container->isFrozen()) {
|
||||
@ -992,9 +1023,12 @@ EOF;
|
||||
{
|
||||
$name = strtolower($name);
|
||||
|
||||
if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters))) {
|
||||
if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]))) {
|
||||
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];
|
||||
}
|
||||
@ -1006,7 +1040,7 @@ EOF;
|
||||
{
|
||||
$name = strtolower($name);
|
||||
|
||||
return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters);
|
||||
return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1023,7 +1057,11 @@ EOF;
|
||||
public function getParameterBag()
|
||||
{
|
||||
if (null === $this->parameterBag) {
|
||||
$this->parameterBag = new FrozenParameterBag($this->parameters);
|
||||
$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;
|
||||
@ -1033,6 +1071,46 @@ EOF;
|
||||
if ('' === $this->docStar) {
|
||||
$code = str_replace('/**', '/*', $code);
|
||||
}
|
||||
|
||||
if ($dynamicPhp) {
|
||||
$loadedDynamicParameters = $this->exportParameters(array_combine(array_keys($dynamicPhp), array_fill(0, count($dynamicPhp), false)), '', 8);
|
||||
$getDynamicParameter = <<<'EOF'
|
||||
switch ($name) {
|
||||
%s
|
||||
default: throw new InvalidArgumentException(sprintf('The dynamic parameter "%%s" must be defined.', $name));
|
||||
}
|
||||
$this->loadedDynamicParameters[$name] = true;
|
||||
|
||||
return $this->dynamicParameters[$name] = $value;
|
||||
EOF;
|
||||
$getDynamicParameter = sprintf($getDynamicParameter, implode("\n", $dynamicPhp));
|
||||
} else {
|
||||
$loadedDynamicParameters = 'array()';
|
||||
$getDynamicParameter = str_repeat(' ', 8).'throw new InvalidArgumentException(sprintf(\'The dynamic parameter "%s" must be defined.\', $name));';
|
||||
}
|
||||
|
||||
$code .= <<<EOF
|
||||
|
||||
private \$loadedDynamicParameters = {$loadedDynamicParameters};
|
||||
private \$dynamicParameters = array();
|
||||
|
||||
/*{$this->docStar}
|
||||
* 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)
|
||||
{
|
||||
{$getDynamicParameter}
|
||||
}
|
||||
|
||||
EOF;
|
||||
} elseif ($dynamicPhp) {
|
||||
throw new RuntimeException('You cannot dump a not-frozen container with dynamic parameters.');
|
||||
}
|
||||
|
||||
$code .= <<<EOF
|
||||
@ -1081,7 +1159,7 @@ EOF;
|
||||
$value = $this->export($value);
|
||||
}
|
||||
|
||||
$php[] = sprintf('%s%s => %s,', str_repeat(' ', $indent), var_export($key, true), $value);
|
||||
$php[] = sprintf('%s%s => %s,', str_repeat(' ', $indent), $this->export($key), $value);
|
||||
}
|
||||
|
||||
return sprintf("array(\n%s\n%s)", implode("\n", $php), str_repeat(' ', $indent - 4));
|
||||
@ -1283,7 +1361,7 @@ EOF;
|
||||
$factory = $value->getFactory();
|
||||
|
||||
if (is_string($factory)) {
|
||||
return sprintf('\\%s(%s)', $factory, implode(', ', $arguments));
|
||||
return sprintf('%s(%s)', $this->dumpLiteralClass($this->dumpValue($factory)), implode(', ', $arguments));
|
||||
}
|
||||
|
||||
if (is_array($factory)) {
|
||||
@ -1358,7 +1436,7 @@ EOF;
|
||||
private function dumpLiteralClass($class)
|
||||
{
|
||||
if (false !== strpos($class, '$')) {
|
||||
throw new RuntimeException('Cannot dump definitions which have a variable class name.');
|
||||
return sprintf('${($_ = %s) && false ?: "_"}', $class);
|
||||
}
|
||||
if (0 !== strpos($class, "'") || !preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
|
||||
throw new RuntimeException(sprintf('Cannot dump definition because of invalid class name (%s)', $class ?: 'n/a'));
|
||||
@ -1529,9 +1607,9 @@ EOF;
|
||||
private function export($value)
|
||||
{
|
||||
if (null !== $this->targetDirRegex && is_string($value) && preg_match($this->targetDirRegex, $value, $matches, PREG_OFFSET_CAPTURE)) {
|
||||
$prefix = $matches[0][1] ? var_export(substr($value, 0, $matches[0][1]), true).'.' : '';
|
||||
$prefix = $matches[0][1] ? $this->doExport(substr($value, 0, $matches[0][1])).'.' : '';
|
||||
$suffix = $matches[0][1] + strlen($matches[0][0]);
|
||||
$suffix = isset($value[$suffix]) ? '.'.var_export(substr($value, $suffix), true) : '';
|
||||
$suffix = isset($value[$suffix]) ? '.'.$this->doExport(substr($value, $suffix)) : '';
|
||||
$dirname = '__DIR__';
|
||||
|
||||
if (0 < $offset = 1 + $this->targetDirMaxMatches - count($matches)) {
|
||||
@ -1545,6 +1623,23 @@ EOF;
|
||||
return $dirname;
|
||||
}
|
||||
|
||||
return var_export($value, true);
|
||||
return $this->doExport($value);
|
||||
}
|
||||
|
||||
private function doExport($value)
|
||||
{
|
||||
$export = var_export($value, true);
|
||||
|
||||
if ("'" === $export[0] && $export !== $resolvedExport = $this->container->resolveEnvPlaceholders($export, "'.\$this->getEnv('%s').'")) {
|
||||
$export = $resolvedExport;
|
||||
if ("'" === $export[1]) {
|
||||
$export = substr($export, 3);
|
||||
}
|
||||
if (".''" === substr($export, -3)) {
|
||||
$export = substr($export, 0, -3);
|
||||
}
|
||||
}
|
||||
|
||||
return $export;
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ class XmlDumper extends Dumper
|
||||
$xml = $this->document->saveXML();
|
||||
$this->document = null;
|
||||
|
||||
return $xml;
|
||||
return $this->container->resolveEnvPlaceholders($xml);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -46,7 +46,7 @@ class YamlDumper extends Dumper
|
||||
$this->dumper = new YmlDumper();
|
||||
}
|
||||
|
||||
return $this->addParameters()."\n".$this->addServices();
|
||||
return $this->container->resolveEnvPlaceholders($this->addParameters()."\n".$this->addServices());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,25 @@
|
||||
<?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\Exception;
|
||||
|
||||
/**
|
||||
* This exception is thrown when an environment variable is not found.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class EnvNotFoundException extends InvalidArgumentException
|
||||
{
|
||||
public function __construct($name)
|
||||
{
|
||||
parent::__construct(sprintf('Environment variable not found: "%s".', $name));
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
<?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\Exception;
|
||||
|
||||
/**
|
||||
* This exception wraps exceptions whose messages contain a reference to an env parameter.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class EnvParameterException extends InvalidArgumentException
|
||||
{
|
||||
public function __construct(array $usedEnvs, \Exception $previous = null)
|
||||
{
|
||||
parent::__construct(sprintf('Incompatible use of dynamic environment variables "%s" found in parameters.', implode('", "', $usedEnvs)), 0, $previous);
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
<?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\ParameterBag;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class EnvPlaceholderParameterBag extends ParameterBag
|
||||
{
|
||||
private $envPlaceholders = array();
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get($name)
|
||||
{
|
||||
if (0 === strpos($name, 'env(') && ')' === substr($name, -1) && 'env()' !== $name) {
|
||||
$env = substr($name, 4, -1);
|
||||
|
||||
if (isset($this->envPlaceholders[$env])) {
|
||||
return $this->envPlaceholders[$env][0];
|
||||
}
|
||||
if (preg_match('/\W/', $env)) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid %s name: only "word" characters are allowed.', $name));
|
||||
}
|
||||
|
||||
if ($this->has($name)) {
|
||||
$defaultValue = parent::get($name);
|
||||
|
||||
if (!is_scalar($defaultValue)) {
|
||||
throw new RuntimeException(sprintf('The default value of an env() parameter must be scalar, but "%s" given to "%s".', gettype($defaultValue), $name));
|
||||
}
|
||||
}
|
||||
|
||||
return $this->envPlaceholders[$env][] = sprintf('env_%s_%s', $env, md5($name.uniqid(mt_rand(), true)));
|
||||
}
|
||||
|
||||
return parent::get($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the map of env vars used in the resolved parameter values to their placeholders.
|
||||
*
|
||||
* @return string[][] A map of env var names to their placeholders
|
||||
*/
|
||||
public function getEnvPlaceholders()
|
||||
{
|
||||
return $this->envPlaceholders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges the env placeholders of another EnvPlaceholderParameterBag.
|
||||
*/
|
||||
public function mergeEnvPlaceholders(self $bag)
|
||||
{
|
||||
$this->envPlaceholders = array_merge_recursive($this->envPlaceholders, $bag->getEnvPlaceholders());
|
||||
}
|
||||
}
|
@ -189,13 +189,14 @@ class ParameterBag implements ParameterBagInterface
|
||||
// as the preg_replace_callback throw an exception when trying
|
||||
// a non-string in a parameter value
|
||||
if (preg_match('/^%([^%\s]+)%$/', $value, $match)) {
|
||||
$key = strtolower($match[1]);
|
||||
$key = $match[1];
|
||||
$lcKey = strtolower($key);
|
||||
|
||||
if (isset($resolving[$key])) {
|
||||
if (isset($resolving[$lcKey])) {
|
||||
throw new ParameterCircularReferenceException(array_keys($resolving));
|
||||
}
|
||||
|
||||
$resolving[$key] = true;
|
||||
$resolving[$lcKey] = true;
|
||||
|
||||
return $this->resolved ? $this->get($key) : $this->resolveValue($this->get($key), $resolving);
|
||||
}
|
||||
@ -206,8 +207,9 @@ class ParameterBag implements ParameterBagInterface
|
||||
return '%%';
|
||||
}
|
||||
|
||||
$key = strtolower($match[1]);
|
||||
if (isset($resolving[$key])) {
|
||||
$key = $match[1];
|
||||
$lcKey = strtolower($key);
|
||||
if (isset($resolving[$lcKey])) {
|
||||
throw new ParameterCircularReferenceException(array_keys($resolving));
|
||||
}
|
||||
|
||||
@ -218,7 +220,7 @@ class ParameterBag implements ParameterBagInterface
|
||||
}
|
||||
|
||||
$resolved = (string) $resolved;
|
||||
$resolving[$key] = true;
|
||||
$resolving[$lcKey] = true;
|
||||
|
||||
return $this->isResolved() ? $resolved : $this->resolveString($resolved, $resolving);
|
||||
}, $value);
|
||||
|
@ -26,6 +26,7 @@ use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
|
||||
use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
|
||||
use Symfony\Component\Config\Resource\FileResource;
|
||||
use Symfony\Component\ExpressionLanguage\Expression;
|
||||
|
||||
@ -505,6 +506,14 @@ class ContainerBuilderTest extends \PHPUnit_Framework_TestCase
|
||||
$config->setDefinition('foo', new Definition('BazClass'));
|
||||
$container->merge($config);
|
||||
$this->assertEquals('BazClass', $container->getDefinition('foo')->getClass(), '->merge() overrides already defined services');
|
||||
|
||||
$container = new ContainerBuilder();
|
||||
$bag = new EnvPlaceholderParameterBag();
|
||||
$bag->get('env(Foo)');
|
||||
$config = new ContainerBuilder($bag);
|
||||
$config->resolveEnvPlaceholders($bag->get('env(Bar)'));
|
||||
$container->merge($config);
|
||||
$this->assertEquals(array('Foo' => 0, 'Bar' => 1), $container->getEnvCounters());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -11,11 +11,13 @@
|
||||
|
||||
namespace Symfony\Component\DependencyInjection\Tests\Dumper;
|
||||
|
||||
use Symfony\Component\Config\FileLocator;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
|
||||
use Symfony\Component\DependencyInjection\Variable;
|
||||
use Symfony\Component\ExpressionLanguage\Expression;
|
||||
|
||||
@ -285,6 +287,30 @@ class PhpDumperTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(file_get_contents(self::$fixturesPath.'/php/services24.php'), $dumper->dump());
|
||||
}
|
||||
|
||||
public function testEnvParameter()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
|
||||
$loader->load('services26.yml');
|
||||
$container->compile();
|
||||
$dumper = new PhpDumper($container);
|
||||
|
||||
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services26.php', $dumper->dump(), '->dump() dumps inline definitions which reference service_container');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\EnvParameterException
|
||||
* @expectedExceptionMessage Incompatible use of dynamic environment variables "FOO" found in parameters.
|
||||
*/
|
||||
public function testUnusedEnvParameter()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->getParameter('env(FOO)');
|
||||
$container->compile();
|
||||
$dumper = new PhpDumper($container);
|
||||
$dumper->dump();
|
||||
}
|
||||
|
||||
public function testInlinedDefinitionReferencingServiceContainer()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
|
@ -69,9 +69,12 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
$name = strtolower($name);
|
||||
|
||||
if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters))) {
|
||||
if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]))) {
|
||||
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];
|
||||
}
|
||||
@ -83,7 +86,7 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
$name = strtolower($name);
|
||||
|
||||
return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters);
|
||||
return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -100,12 +103,33 @@ class ProjectServiceContainer extends Container
|
||||
public function getParameterBag()
|
||||
{
|
||||
if (null === $this->parameterBag) {
|
||||
$this->parameterBag = new FrozenParameterBag($this->parameters);
|
||||
$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();
|
||||
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)
|
||||
{
|
||||
throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default parameters.
|
||||
*
|
||||
|
@ -73,9 +73,12 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
$name = strtolower($name);
|
||||
|
||||
if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters))) {
|
||||
if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]))) {
|
||||
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];
|
||||
}
|
||||
@ -87,7 +90,7 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
$name = strtolower($name);
|
||||
|
||||
return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters);
|
||||
return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -104,12 +107,43 @@ class ProjectServiceContainer extends Container
|
||||
public function getParameterBag()
|
||||
{
|
||||
if (null === $this->parameterBag) {
|
||||
$this->parameterBag = new FrozenParameterBag($this->parameters);
|
||||
$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(
|
||||
'foo' => false,
|
||||
'buz' => 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 'foo': $value = ('wiz'.$this->targetDirs[1]); break;
|
||||
case 'buz': $value = $this->targetDirs[2]; 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.
|
||||
*
|
||||
@ -118,10 +152,8 @@ class ProjectServiceContainer extends Container
|
||||
protected function getDefaultParameters()
|
||||
{
|
||||
return array(
|
||||
'foo' => ('wiz'.$this->targetDirs[1]),
|
||||
'bar' => __DIR__,
|
||||
'baz' => (__DIR__.'/PhpDumperTest.php'),
|
||||
'buz' => $this->targetDirs[2],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* ProjectServiceContainer.
|
||||
*
|
||||
* This class has been auto-generated
|
||||
* by the Symfony Dependency Injection Component.
|
||||
*/
|
||||
class ProjectServiceContainer extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->parameters = $this->getDefaultParameters();
|
||||
|
||||
$this->services = array();
|
||||
$this->methodMap = array(
|
||||
'test' => 'getTestService',
|
||||
);
|
||||
|
||||
$this->aliases = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function compile()
|
||||
{
|
||||
throw new LogicException('You cannot compile a dumped frozen container.');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isFrozen()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the 'test' service.
|
||||
*
|
||||
* This service is shared.
|
||||
* This method always returns the same instance of the service.
|
||||
*
|
||||
* @return object A %env(FOO)% instance
|
||||
*/
|
||||
protected function getTestService()
|
||||
{
|
||||
$class = $this->getEnv('FOO');
|
||||
|
||||
return $this->services['test'] = new $class($this->getEnv('Bar'), 'foo'.$this->getEnv('FOO').'baz');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getParameter($name)
|
||||
{
|
||||
$name = strtolower($name);
|
||||
|
||||
if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]))) {
|
||||
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];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasParameter($name)
|
||||
{
|
||||
$name = strtolower($name);
|
||||
|
||||
return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setParameter($name, $value)
|
||||
{
|
||||
throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
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(
|
||||
'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 'bar': $value = $this->getEnv('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(
|
||||
'env(foo)' => 'foo',
|
||||
);
|
||||
}
|
||||
}
|
@ -357,9 +357,12 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
$name = strtolower($name);
|
||||
|
||||
if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters))) {
|
||||
if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]))) {
|
||||
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];
|
||||
}
|
||||
@ -371,7 +374,7 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
$name = strtolower($name);
|
||||
|
||||
return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters);
|
||||
return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -388,12 +391,33 @@ class ProjectServiceContainer extends Container
|
||||
public function getParameterBag()
|
||||
{
|
||||
if (null === $this->parameterBag) {
|
||||
$this->parameterBag = new FrozenParameterBag($this->parameters);
|
||||
$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();
|
||||
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)
|
||||
{
|
||||
throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default parameters.
|
||||
*
|
||||
|
@ -0,0 +1,10 @@
|
||||
parameters:
|
||||
env(FOO): foo
|
||||
bar: '%env(FOO)%'
|
||||
|
||||
services:
|
||||
test:
|
||||
class: '%env(FOO)%'
|
||||
arguments:
|
||||
- '%env(Bar)%'
|
||||
- 'foo%bar%baz'
|
@ -16,7 +16,6 @@ use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
|
||||
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
|
||||
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
|
||||
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
|
||||
@ -611,7 +610,8 @@ abstract class Kernel implements KernelInterface, TerminableInterface
|
||||
*/
|
||||
protected function getContainerBuilder()
|
||||
{
|
||||
$container = new ContainerBuilder(new ParameterBag($this->getKernelParameters()));
|
||||
$container = new ContainerBuilder();
|
||||
$container->getParameterBag()->add($this->getKernelParameters());
|
||||
|
||||
if (class_exists('ProxyManager\Configuration') && class_exists('Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator')) {
|
||||
$container->setProxyInstantiator(new RuntimeInstantiator());
|
||||
|
Reference in New Issue
Block a user