[DependencyInjection] added NonExistentParameterException that indicates where a non-existent parameter is being used

This commit is contained in:
Fabien Potencier 2011-04-26 12:31:40 +02:00
parent e68f8f40b9
commit 175f944f93
6 changed files with 147 additions and 23 deletions

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\DependencyInjection\Compiler; namespace Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\NonExistentParameterException;
/** /**
* Resolves all parameter placeholders "%somevalue%" to their real values. * Resolves all parameter placeholders "%somevalue%" to their real values.
@ -31,18 +32,24 @@ class ResolveParameterPlaceHoldersPass implements CompilerPassInterface
{ {
$this->parameterBag = $container->getParameterBag(); $this->parameterBag = $container->getParameterBag();
foreach ($container->getDefinitions() as $definition) { foreach ($container->getDefinitions() as $id => $definition) {
$definition->setClass($this->resolveValue($definition->getClass())); try {
$definition->setFile($this->resolveValue($definition->getFile())); $definition->setClass($this->resolveValue($definition->getClass()));
$definition->setArguments($this->resolveValue($definition->getArguments())); $definition->setFile($this->resolveValue($definition->getFile()));
$definition->setArguments($this->resolveValue($definition->getArguments()));
$calls = array(); $calls = array();
foreach ($definition->getMethodCalls() as $name => $arguments) { foreach ($definition->getMethodCalls() as $name => $arguments) {
$calls[$this->resolveValue($name)] = $this->resolveValue($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(); $aliases = array();
@ -53,7 +60,13 @@ class ResolveParameterPlaceHoldersPass implements CompilerPassInterface
$parameterBag = $container->getParameterBag(); $parameterBag = $container->getParameterBag();
foreach ($parameterBag->all() as $key => $value) { 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;
}
} }
} }

View File

@ -0,0 +1,80 @@
<?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 a non-existent parameter is used.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
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();
}
}

View File

@ -11,6 +11,8 @@
namespace Symfony\Component\DependencyInjection\ParameterBag; namespace Symfony\Component\DependencyInjection\ParameterBag;
use Symfony\Component\DependencyInjection\Exception\NonExistentParameterException;
/** /**
* *
* @author Fabien Potencier <fabien@symfony.com> * @author Fabien Potencier <fabien@symfony.com>
@ -74,7 +76,7 @@ class ParameterBag implements ParameterBagInterface
$name = strtolower($name); $name = strtolower($name);
if (!array_key_exists($name, $this->parameters)) { 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]; return $this->parameters[$name];
@ -109,7 +111,13 @@ class ParameterBag implements ParameterBagInterface
public function resolve() public function resolve()
{ {
foreach ($this->parameters as $key => $value) { 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;
}
} }
} }

View File

@ -11,6 +11,8 @@
namespace Symfony\Component\DependencyInjection\ParameterBag; namespace Symfony\Component\DependencyInjection\ParameterBag;
use Symfony\Component\DependencyInjection\Exception\NonExistentParameterException;
/** /**
* ParameterBagInterface. * ParameterBagInterface.
* *
@ -44,7 +46,7 @@ interface ParameterBagInterface
* *
* @return mixed The parameter value * @return mixed The parameter value
* *
* @throws \InvalidArgumentException if the parameter is not defined * @throws NonExistentParameterException if the parameter is not defined
*/ */
function get($name); function get($name);

View File

@ -83,7 +83,7 @@ class ContainerTest extends \PHPUnit_Framework_TestCase
$this->fail('->getParameter() thrown an \InvalidArgumentException if the key does not exist'); $this->fail('->getParameter() thrown an \InvalidArgumentException if the key does not exist');
} catch (\Exception $e) { } catch (\Exception $e) {
$this->assertInstanceOf('\InvalidArgumentException', $e, '->getParameter() thrown an \InvalidArgumentException if the key does not exist'); $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');
} }
} }

View File

@ -12,6 +12,7 @@
namespace Symfony\Tests\Component\DependencyInjection\ParameterBag; namespace Symfony\Tests\Component\DependencyInjection\ParameterBag;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\Exception\NonExistentParameterException;
class ParameterBagTest extends \PHPUnit_Framework_TestCase 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'); $this->fail('->get() throws an \InvalidArgumentException if the key does not exist');
} catch (\Exception $e) { } catch (\Exception $e) {
$this->assertInstanceOf('\InvalidArgumentException', $e, '->get() throws an \InvalidArgumentException if the key does not exist'); $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 { try {
$bag->resolveValue('%foobar%', array()); $bag->resolveValue('%foobar%', array());
$this->fail('->resolveValue() throws an InvalidArgumentException if a placeholder references a non-existent parameter'); $this->fail('->resolveValue() throws an InvalidArgumentException if a placeholder references a non-existent parameter');
} catch (\Exception $e) { } catch (NonExistentParameterException $e) {
$this->assertInstanceOf('\InvalidArgumentException', $e, '->resolveValue() throws an InvalidArgumentException if a placeholder references a non-existent parameter'); $this->assertEquals('You have requested a non-existent parameter "foobar".', $e->getMessage(), '->resolveValue() throws a NonExistentParameterException 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');
} }
try { try {
$bag->resolveValue('foo %foobar% bar', array()); $bag->resolveValue('foo %foobar% bar', array());
$this->fail('->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 (\Exception $e) { } catch (NonExistentParameterException $e) {
$this->assertInstanceOf('\InvalidArgumentException', $e, '->resolveValue() throws an InvalidArgumentException if a placeholder references a non-existent parameter'); $this->assertEquals('You have requested a non-existent parameter "foobar".', $e->getMessage(), '->resolveValue() throws a NonExistentParameterException 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'); }
}
/**
* @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());
} }
} }
} }