[DI] Fix AutowirePass fatal error with classes that have non-existing parents

This commit is contained in:
Nicolas Grekas 2016-04-20 14:06:08 +02:00
parent 1735b85c04
commit 202cc7724e
2 changed files with 41 additions and 7 deletions

View File

@ -34,19 +34,32 @@ class AutowirePass implements CompilerPassInterface
*/
public function process(ContainerBuilder $container)
{
$this->container = $container;
foreach ($container->getDefinitions() as $id => $definition) {
if ($definition->isAutowired()) {
$this->completeDefinition($id, $definition);
$throwingAutoloader = function ($class) { throw new \ReflectionException(sprintf('Class %s does not exist', $class)); };
spl_autoload_register($throwingAutoloader);
try {
$this->container = $container;
foreach ($container->getDefinitions() as $id => $definition) {
if ($definition->isAutowired()) {
$this->completeDefinition($id, $definition);
}
}
} catch (\Error $e) {
} catch (\Exception $e) {
}
spl_autoload_unregister($throwingAutoloader);
// Free memory and remove circular reference to container
$this->container = null;
$this->reflectionClasses = array();
$this->definedTypes = array();
$this->types = null;
$this->notGuessableTypes = array();
if (isset($e)) {
throw $e;
}
}
/**
@ -107,11 +120,11 @@ class AutowirePass implements CompilerPassInterface
}
}
}
} catch (\ReflectionException $reflectionException) {
} catch (\ReflectionException $e) {
// Typehint against a non-existing class
if (!$parameter->isDefaultValueAvailable()) {
throw new RuntimeException(sprintf('Cannot autowire argument %s for %s because the type-hinted class does not exist (%s).', $index + 1, $definition->getClass(), $reflectionException->getMessage()), 0, $reflectionException);
throw new RuntimeException(sprintf('Cannot autowire argument %s for %s because the type-hinted class does not exist (%s).', $index + 1, $definition->getClass(), $e->getMessage()), 0, $e);
}
$value = $parameter->getDefaultValue();
@ -245,7 +258,7 @@ class AutowirePass implements CompilerPassInterface
try {
$reflector = new \ReflectionClass($class);
} catch (\ReflectionException $reflectionException) {
} catch (\ReflectionException $e) {
$reflector = false;
}

View File

@ -268,6 +268,21 @@ class AutowirePassTest extends \PHPUnit_Framework_TestCase
$pass->process($container);
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedExceptionMessage Cannot autowire argument 2 for Symfony\Component\DependencyInjection\Tests\Compiler\BadParentTypeHintedArgument because the type-hinted class does not exist (Class Symfony\Component\DependencyInjection\Tests\Compiler\OptionalServiceClass does not exist).
*/
public function testParentClassNotFoundThrowsException()
{
$container = new ContainerBuilder();
$aDefinition = $container->register('a', __NAMESPACE__.'\BadParentTypeHintedArgument');
$aDefinition->setAutowired(true);
$pass = new AutowirePass();
$pass->process($container);
}
public function testDontUseAbstractServices()
{
$container = new ContainerBuilder();
@ -524,6 +539,12 @@ class BadTypeHintedArgument
{
}
}
class BadParentTypeHintedArgument
{
public function __construct(Dunglas $k, OptionalServiceClass $r)
{
}
}
class NotGuessableArgument
{
public function __construct(Foo $k)