Browse Source

[DependencyInjection] fixed regression when a parameter contains an escaped %

Notice that this is still not perfect, but I don't see how to fix the remaining
potential problems.
Fabien Potencier 14 years ago
parent
commit
3bdb7c2b57

+ 2 - 1
src/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php

@@ -31,7 +31,6 @@ class ResolveParameterPlaceHoldersPass implements CompilerPassInterface
     public function process(ContainerBuilder $container)
     {
         $parameterBag = $container->getParameterBag();
-        $parameterBag->resolve();
 
         foreach ($container->getDefinitions() as $id => $definition) {
             try {
@@ -58,5 +57,7 @@ class ResolveParameterPlaceHoldersPass implements CompilerPassInterface
             $aliases[$parameterBag->resolveValue($name)] = $parameterBag->resolveValue($target);
         }
         $container->setAliases($aliases);
+
+        $parameterBag->resolve();
     }
 }

+ 1 - 0
src/Symfony/Component/DependencyInjection/ParameterBag/FrozenParameterBag.php

@@ -30,6 +30,7 @@ class FrozenParameterBag extends ParameterBag
     public function __construct(array $parameters = array())
     {
         $this->parameters = $parameters;
+        $this->resolved = true;
     }
 
     /**

+ 21 - 6
src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php

@@ -22,6 +22,7 @@ use Symfony\Component\DependencyInjection\Exception\RuntimeException;
 class ParameterBag implements ParameterBagInterface
 {
     protected $parameters;
+    protected $resolved;
 
     /**
      * Constructor.
@@ -32,6 +33,7 @@ class ParameterBag implements ParameterBagInterface
     {
         $this->parameters = array();
         $this->add($parameters);
+        $this->resolved = false;
     }
 
     /**
@@ -112,15 +114,24 @@ class ParameterBag implements ParameterBagInterface
      */
     public function resolve()
     {
+        if ($this->resolved) {
+            return;
+        }
+
+        $parameters = array();
         foreach ($this->parameters as $key => $value) {
             try {
-                $this->parameters[$key] = $this->resolveValue($value);
+                $value = $this->resolveValue($value);
+                $parameters[$key] = is_string($value) ? str_replace('%%', '%', $value) : $value;
             } catch (ParameterNotFoundException $e) {
                 $e->setSourceKey($key);
 
                 throw $e;
             }
         }
+
+        $this->parameters = $parameters;
+        $this->resolved = true;
     }
 
     /**
@@ -179,13 +190,12 @@ class ParameterBag implements ParameterBagInterface
 
             $resolving[$key] = true;
 
-            return $this->resolveValue($this->get($key), $resolving);
+            return $this->resolved ? $this->get($key) : $this->resolveValue($this->get($key), $resolving);
         }
 
         $self = $this;
-        return str_replace('%%', '%', preg_replace_callback('/(?<!%)%([^%]+)%/', function ($match) use ($self, $resolving) {
+        return preg_replace_callback('/(?<!%)%([^%]+)%/', function ($match) use ($self, $resolving) {
             $key = strtolower($match[1]);
-
             if (isset($resolving[$key])) {
                 throw new ParameterCircularReferenceException(array_keys($resolving));
             }
@@ -198,7 +208,12 @@ class ParameterBag implements ParameterBagInterface
 
             $resolving[$key] = true;
 
-            return $self->resolveString($resolved, $resolving);
-        }, $value));
+            return $self->isResolved() ? $resolved : $self->resolveString($resolved, $resolving);
+        }, $value);
+    }
+
+    public function isResolved()
+    {
+        return $this->resolved;
     }
 }

+ 2 - 2
tests/Symfony/Tests/Component/DependencyInjection/ParameterBag/ParameterBagTest.php

@@ -92,8 +92,8 @@ class ParameterBagTest extends \PHPUnit_Framework_TestCase
         $this->assertEquals('I\'m a bar', $bag->resolveValue('I\'m a %foo%'), '->resolveValue() replaces placeholders by their values');
         $this->assertEquals(array('bar' => 'bar'), $bag->resolveValue(array('%foo%' => '%foo%')), '->resolveValue() replaces placeholders in keys and values of arrays');
         $this->assertEquals(array('bar' => array('bar' => array('bar' => 'bar'))), $bag->resolveValue(array('%foo%' => array('%foo%' => array('%foo%' => '%foo%')))), '->resolveValue() replaces placeholders in nested arrays');
-        $this->assertEquals('I\'m a %foo%', $bag->resolveValue('I\'m a %%foo%%'), '->resolveValue() supports % escaping by doubling it');
-        $this->assertEquals('I\'m a bar %foo bar', $bag->resolveValue('I\'m a %foo% %%foo %foo%'), '->resolveValue() supports % escaping by doubling it');
+        $this->assertEquals('I\'m a %%foo%%', $bag->resolveValue('I\'m a %%foo%%'), '->resolveValue() supports % escaping by doubling it');
+        $this->assertEquals('I\'m a bar %%foo bar', $bag->resolveValue('I\'m a %foo% %%foo %foo%'), '->resolveValue() supports % escaping by doubling it');
 
         $bag = new ParameterBag(array('foo' => true));
         $this->assertSame(true, $bag->resolveValue('%foo%'), '->resolveValue() replaces arguments that are just a placeholder by their value without casting them to strings');