From 175f944f93c8d515627173a5fea792da956198bf Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 26 Apr 2011 12:31:40 +0200 Subject: [PATCH] [DependencyInjection] added NonExistentParameterException that indicates where a non-existent parameter is being used --- .../ResolveParameterPlaceHoldersPass.php | 35 +++++--- .../NonExistentParameterException.php | 80 +++++++++++++++++++ .../ParameterBag/ParameterBag.php | 12 ++- .../ParameterBag/ParameterBagInterface.php | 4 +- .../DependencyInjection/ContainerTest.php | 2 +- .../ParameterBag/ParameterBagTest.php | 37 +++++++-- 6 files changed, 147 insertions(+), 23 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Exception/NonExistentParameterException.php diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php index bb784eac7e..938dc2f9cb 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php @@ -12,6 +12,7 @@ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\NonExistentParameterException; /** * Resolves all parameter placeholders "%somevalue%" to their real values. @@ -31,18 +32,24 @@ class ResolveParameterPlaceHoldersPass implements CompilerPassInterface { $this->parameterBag = $container->getParameterBag(); - foreach ($container->getDefinitions() as $definition) { - $definition->setClass($this->resolveValue($definition->getClass())); - $definition->setFile($this->resolveValue($definition->getFile())); - $definition->setArguments($this->resolveValue($definition->getArguments())); + foreach ($container->getDefinitions() as $id => $definition) { + try { + $definition->setClass($this->resolveValue($definition->getClass())); + $definition->setFile($this->resolveValue($definition->getFile())); + $definition->setArguments($this->resolveValue($definition->getArguments())); - $calls = array(); - foreach ($definition->getMethodCalls() as $name => $arguments) { - $calls[$this->resolveValue($name)] = $this->resolveValue($arguments); + $calls = array(); + foreach ($definition->getMethodCalls() as $name => $arguments) { + $calls[$this->resolveValue($name)] = $this->resolveValue($arguments); + } + $definition->setMethodCalls($calls); + + $definition->setProperties($this->resolveValue($definition->getProperties())); + } catch (NonExistentParameterException $e) { + $e->setSourceId($id); + + throw $e; } - $definition->setMethodCalls($calls); - - $definition->setProperties($this->resolveValue($definition->getProperties())); } $aliases = array(); @@ -53,7 +60,13 @@ class ResolveParameterPlaceHoldersPass implements CompilerPassInterface $parameterBag = $container->getParameterBag(); foreach ($parameterBag->all() as $key => $value) { - $parameterBag->set($key, $this->resolveValue($value)); + try { + $parameterBag->set($key, $this->resolveValue($value)); + } catch (NonExistentParameterException $e) { + $e->setSourceKey($key); + + throw $e; + } } } diff --git a/src/Symfony/Component/DependencyInjection/Exception/NonExistentParameterException.php b/src/Symfony/Component/DependencyInjection/Exception/NonExistentParameterException.php new file mode 100644 index 0000000000..3e187730b4 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Exception/NonExistentParameterException.php @@ -0,0 +1,80 @@ + + * + * 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 a non-existent parameter is used. + * + * @author Fabien Potencier + */ +class NonExistentParameterException extends InvalidArgumentException +{ + private $key; + private $sourceId; + private $sourceKey; + + /** + * Constructor. + * + * @param string $key The requested parameter key + * @param string $sourceId The service id that references the non-existent parameter + * @param string $sourceKey The parameter key that references the non-existent parameter + */ + public function __construct($key, $sourceId = null, $sourceKey = null) + { + $this->key = $key; + $this->sourceId = $sourceId; + $this->sourceKey = $sourceKey; + + $this->updateRepr(); + } + + public function updateRepr() + { + if (null !== $this->sourceId) { + $this->message = sprintf('The service "%s" has a dependency on a non-existent parameter "%s".', $this->sourceId, $this->key); + } elseif (null !== $this->sourceKey) { + $this->message = sprintf('The parameter "%s" has a dependency on a non-existent parameter "%s".', $this->sourceKey, $this->key); + } else { + $this->message = sprintf('You have requested a non-existent parameter "%s".', $this->key); + } + } + + public function getKey() + { + return $this->key; + } + + public function getSourceId() + { + return $this->sourceId; + } + + public function getSourceKey() + { + return $this->sourceKey; + } + + public function setSourceId($sourceId) + { + $this->sourceId = $sourceId; + + $this->updateRepr(); + } + + public function setSourceKey($sourceKey) + { + $this->sourceKey = $sourceKey; + + $this->updateRepr(); + } +} diff --git a/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php b/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php index 6948ac38f9..fff9a4148c 100644 --- a/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php +++ b/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php @@ -11,6 +11,8 @@ namespace Symfony\Component\DependencyInjection\ParameterBag; +use Symfony\Component\DependencyInjection\Exception\NonExistentParameterException; + /** * * @author Fabien Potencier @@ -74,7 +76,7 @@ class ParameterBag implements ParameterBagInterface $name = strtolower($name); if (!array_key_exists($name, $this->parameters)) { - throw new \InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); + throw new NonExistentParameterException($name); } return $this->parameters[$name]; @@ -109,7 +111,13 @@ class ParameterBag implements ParameterBagInterface public function resolve() { foreach ($this->parameters as $key => $value) { - $this->parameters[$key] = $this->resolveValue($value); + try { + $this->parameters[$key] = $this->resolveValue($value); + } catch (NonExistentParameterException $e) { + $e->setSourceKey($key); + + throw $e; + } } } diff --git a/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBagInterface.php b/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBagInterface.php index 603f414da9..852b99b30d 100644 --- a/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBagInterface.php +++ b/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBagInterface.php @@ -11,6 +11,8 @@ namespace Symfony\Component\DependencyInjection\ParameterBag; +use Symfony\Component\DependencyInjection\Exception\NonExistentParameterException; + /** * ParameterBagInterface. * @@ -44,7 +46,7 @@ interface ParameterBagInterface * * @return mixed The parameter value * - * @throws \InvalidArgumentException if the parameter is not defined + * @throws NonExistentParameterException if the parameter is not defined */ function get($name); diff --git a/tests/Symfony/Tests/Component/DependencyInjection/ContainerTest.php b/tests/Symfony/Tests/Component/DependencyInjection/ContainerTest.php index fc307babbb..835a2de040 100644 --- a/tests/Symfony/Tests/Component/DependencyInjection/ContainerTest.php +++ b/tests/Symfony/Tests/Component/DependencyInjection/ContainerTest.php @@ -83,7 +83,7 @@ class ContainerTest extends \PHPUnit_Framework_TestCase $this->fail('->getParameter() thrown an \InvalidArgumentException if the key does not exist'); } catch (\Exception $e) { $this->assertInstanceOf('\InvalidArgumentException', $e, '->getParameter() thrown an \InvalidArgumentException if the key does not exist'); - $this->assertEquals('The parameter "baba" must be defined.', $e->getMessage(), '->getParameter() thrown an \InvalidArgumentException if the key does not exist'); + $this->assertEquals('You have requested a non-existent parameter "baba".', $e->getMessage(), '->getParameter() thrown an \InvalidArgumentException if the key does not exist'); } } diff --git a/tests/Symfony/Tests/Component/DependencyInjection/ParameterBag/ParameterBagTest.php b/tests/Symfony/Tests/Component/DependencyInjection/ParameterBag/ParameterBagTest.php index 1342d6f07b..889c82eeb1 100644 --- a/tests/Symfony/Tests/Component/DependencyInjection/ParameterBag/ParameterBagTest.php +++ b/tests/Symfony/Tests/Component/DependencyInjection/ParameterBag/ParameterBagTest.php @@ -12,6 +12,7 @@ namespace Symfony\Tests\Component\DependencyInjection\ParameterBag; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; +use Symfony\Component\DependencyInjection\Exception\NonExistentParameterException; class ParameterBagTest extends \PHPUnit_Framework_TestCase { @@ -62,7 +63,7 @@ class ParameterBagTest extends \PHPUnit_Framework_TestCase $this->fail('->get() throws an \InvalidArgumentException if the key does not exist'); } catch (\Exception $e) { $this->assertInstanceOf('\InvalidArgumentException', $e, '->get() throws an \InvalidArgumentException if the key does not exist'); - $this->assertEquals('The parameter "baba" must be defined.', $e->getMessage(), '->get() throws an \InvalidArgumentException if the key does not exist'); + $this->assertEquals('You have requested a non-existent parameter "baba".', $e->getMessage(), '->get() throws an \InvalidArgumentException if the key does not exist'); } } @@ -99,17 +100,37 @@ class ParameterBagTest extends \PHPUnit_Framework_TestCase try { $bag->resolveValue('%foobar%', array()); $this->fail('->resolveValue() throws an InvalidArgumentException if a placeholder references a non-existent parameter'); - } catch (\Exception $e) { - $this->assertInstanceOf('\InvalidArgumentException', $e, '->resolveValue() throws an InvalidArgumentException if a placeholder references a non-existent parameter'); - $this->assertEquals('The parameter "foobar" must be defined.', $e->getMessage(), '->resolveValue() throws an InvalidArgumentException if a placeholder references a non-existent parameter'); + } catch (NonExistentParameterException $e) { + $this->assertEquals('You have requested a non-existent parameter "foobar".', $e->getMessage(), '->resolveValue() throws a NonExistentParameterException if a placeholder references a non-existent parameter'); } try { $bag->resolveValue('foo %foobar% bar', array()); - $this->fail('->resolveValue() throws an InvalidArgumentException if a placeholder references a non-existent parameter'); - } catch (\Exception $e) { - $this->assertInstanceOf('\InvalidArgumentException', $e, '->resolveValue() throws an InvalidArgumentException if a placeholder references a non-existent parameter'); - $this->assertEquals('The parameter "foobar" must be defined.', $e->getMessage(), '->resolveValue() throws an InvalidArgumentException if a placeholder references a non-existent parameter'); + $this->fail('->resolveValue() throws a NonExistentParameterException if a placeholder references a non-existent parameter'); + } catch (NonExistentParameterException $e) { + $this->assertEquals('You have requested a non-existent parameter "foobar".', $e->getMessage(), '->resolveValue() throws a NonExistentParameterException if a placeholder references a non-existent parameter'); + } + } + + /** + * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::resolve + */ + public function testResolveIndicatesWhyAParameterIsNeeded() + { + $bag = new ParameterBag(array('foo' => '%bar%')); + + try { + $bag->resolve(); + } catch (NonExistentParameterException $e) { + $this->assertEquals('The parameter "foo" has a dependency on a non-existent parameter "bar".', $e->getMessage()); + } + + $bag = new ParameterBag(array('foo' => '%bar%')); + + try { + $bag->resolve(); + } catch (NonExistentParameterException $e) { + $this->assertEquals('The parameter "foo" has a dependency on a non-existent parameter "bar".', $e->getMessage()); } } }