|
@@ -12,6 +12,7 @@
|
|
namespace Symfony\Component\DependencyInjection\ParameterBag;
|
|
namespace Symfony\Component\DependencyInjection\ParameterBag;
|
|
|
|
|
|
use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
|
|
use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
|
|
|
|
+use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException;
|
|
|
|
|
|
/**
|
|
/**
|
|
*
|
|
*
|
|
@@ -125,18 +126,20 @@ class ParameterBag implements ParameterBagInterface
|
|
* Replaces parameter placeholders (%name%) by their values.
|
|
* Replaces parameter placeholders (%name%) by their values.
|
|
*
|
|
*
|
|
* @param mixed $value A value
|
|
* @param mixed $value A value
|
|
|
|
+ * @param array $resolving An array of keys that are being resolved (used internally to detect circular references)
|
|
*
|
|
*
|
|
* @return mixed The resolved value
|
|
* @return mixed The resolved value
|
|
*
|
|
*
|
|
* @throws ParameterNotFoundException if a placeholder references a parameter that does not exist
|
|
* @throws ParameterNotFoundException if a placeholder references a parameter that does not exist
|
|
|
|
+ * @throws ParameterCircularReferenceException if a circular reference if detected
|
|
* @throws \LogicException when a given parameter has a type problem.
|
|
* @throws \LogicException when a given parameter has a type problem.
|
|
*/
|
|
*/
|
|
- public function resolveValue($value)
|
|
|
|
|
|
+ public function resolveValue($value, array $resolving = array())
|
|
{
|
|
{
|
|
if (is_array($value)) {
|
|
if (is_array($value)) {
|
|
$args = array();
|
|
$args = array();
|
|
foreach ($value as $k => $v) {
|
|
foreach ($value as $k => $v) {
|
|
- $args[$this->resolveValue($k)] = $this->resolveValue($v);
|
|
|
|
|
|
+ $args[$this->resolveValue($k, $resolving)] = $this->resolveValue($v, $resolving);
|
|
}
|
|
}
|
|
|
|
|
|
return $args;
|
|
return $args;
|
|
@@ -146,36 +149,55 @@ class ParameterBag implements ParameterBagInterface
|
|
return $value;
|
|
return $value;
|
|
}
|
|
}
|
|
|
|
|
|
- return $this->resolveString($value);
|
|
|
|
|
|
+ return $this->resolveString($value, $resolving);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
* Resolves parameters inside a string
|
|
* Resolves parameters inside a string
|
|
*
|
|
*
|
|
- * @param string $value The string to resolve
|
|
|
|
|
|
+ * @param string $value The string to resolve
|
|
|
|
+ * @param array $resolving An array of keys that are being resolved (used internally to detect circular references)
|
|
|
|
+ *
|
|
* @return string The resolved string
|
|
* @return string The resolved string
|
|
*
|
|
*
|
|
* @throws ParameterNotFoundException if a placeholder references a parameter that does not exist
|
|
* @throws ParameterNotFoundException if a placeholder references a parameter that does not exist
|
|
|
|
+ * @throws ParameterCircularReferenceException if a circular reference if detected
|
|
* @throws \LogicException when a given parameter has a type problem.
|
|
* @throws \LogicException when a given parameter has a type problem.
|
|
*/
|
|
*/
|
|
- public function resolveString($value)
|
|
|
|
|
|
+ public function resolveString($value, array $resolving = array())
|
|
{
|
|
{
|
|
|
|
+ // we do this to deal with non string values (Boolean, integer, ...)
|
|
|
|
+ // as the preg_replace_callback throw an exception when trying
|
|
|
|
+ // a non-string in a parameter value
|
|
if (preg_match('/^%([^%]+)%$/', $value, $match)) {
|
|
if (preg_match('/^%([^%]+)%$/', $value, $match)) {
|
|
- // we do this to deal with non string values (Boolean, integer, ...)
|
|
|
|
- // as the preg_replace_callback throw an exception when trying
|
|
|
|
- // a non-string in a parameter value
|
|
|
|
- return $this->resolveValue($this->get(strtolower($match[1])));
|
|
|
|
|
|
+ $key = strtolower($match[1]);
|
|
|
|
+
|
|
|
|
+ if (isset($resolving[$key])) {
|
|
|
|
+ throw new ParameterCircularReferenceException(array_keys($resolving));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ $resolving[$key] = true;
|
|
|
|
+
|
|
|
|
+ return $this->resolveValue($this->get($key), $resolving);
|
|
}
|
|
}
|
|
|
|
|
|
$self = $this;
|
|
$self = $this;
|
|
- return str_replace('%%', '%', preg_replace_callback('/(?<!%)%([^%]+)%/', function ($match) use ($self) {
|
|
|
|
- $resolved = $self->get(strtolower($match[1]));
|
|
|
|
|
|
+ return str_replace('%%', '%', preg_replace_callback('/(?<!%)%([^%]+)%/', function ($match) use ($self, $resolving) {
|
|
|
|
+ $key = strtolower($match[1]);
|
|
|
|
+
|
|
|
|
+ if (isset($resolving[$key])) {
|
|
|
|
+ throw new ParameterCircularReferenceException(array_keys($resolving));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ $resolved = $self->get($key);
|
|
|
|
|
|
if (!is_string($resolved)) {
|
|
if (!is_string($resolved)) {
|
|
throw new \LogicException('A parameter cannot contain a non-string parameter.');
|
|
throw new \LogicException('A parameter cannot contain a non-string parameter.');
|
|
}
|
|
}
|
|
|
|
|
|
- return $self->resolveString($resolved);
|
|
|
|
|
|
+ $resolving[$key] = true;
|
|
|
|
+
|
|
|
|
+ return $self->resolveString($resolved, $resolving);
|
|
}, $value));
|
|
}, $value));
|
|
}
|
|
}
|
|
}
|
|
}
|