bug #18600 [DI] Fix AutowirePass fatal error with classes that have non-existing parents (hason, nicolas-grekas)
This PR was merged into the 2.8 branch. Discussion ---------- [DI] Fix AutowirePass fatal error with classes that have non-existing parents | Q | A | ------------- | --- | Branch? | 2.8 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #18188 | License | MIT | Doc PR | - Commits -------202cc77
[DI] Fix AutowirePass fatal error with classes that have non-existing parents1735b85
[DependencyInjection] Tests for AutowirePass with missing parent class
This commit is contained in:
commit
ca5930b3ec
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
@ -397,6 +412,21 @@ class AutowirePassTest extends \PHPUnit_Framework_TestCase
|
||||
$definition->getArguments()
|
||||
);
|
||||
}
|
||||
|
||||
public function testIgnoreServiceWithClassNotExisting()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
|
||||
$container->register('class_not_exist', __NAMESPACE__.'\OptionalServiceClass');
|
||||
|
||||
$barDefinition = $container->register('bar', __NAMESPACE__.'\Bar');
|
||||
$barDefinition->setAutowired(true);
|
||||
|
||||
$pass = new AutowirePass();
|
||||
$pass->process($container);
|
||||
|
||||
$this->assertTrue($container->hasDefinition('bar'));
|
||||
}
|
||||
}
|
||||
|
||||
class Foo
|
||||
@ -509,6 +539,12 @@ class BadTypeHintedArgument
|
||||
{
|
||||
}
|
||||
}
|
||||
class BadParentTypeHintedArgument
|
||||
{
|
||||
public function __construct(Dunglas $k, OptionalServiceClass $r)
|
||||
{
|
||||
}
|
||||
}
|
||||
class NotGuessableArgument
|
||||
{
|
||||
public function __construct(Foo $k)
|
||||
|
@ -0,0 +1,18 @@
|
||||
<?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\Tests\Compiler;
|
||||
|
||||
use Symfony\Bug\NotExistClass;
|
||||
|
||||
class OptionalServiceClass extends NotExistClass
|
||||
{
|
||||
}
|
Reference in New Issue
Block a user