bug #25932 Don't stop PSR-4 service discovery if a parent class is missing (derrabus)
This PR was merged into the 3.4 branch.
Discussion
----------
Don't stop PSR-4 service discovery if a parent class is missing
| Q | A
| ------------- | ---
| Branch? | 3.4
| Bug fix? | yes
| New feature? | no
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | #25929
| License | MIT
| Doc PR | N/A
Commits
-------
3d6c3ba836
Don't stop PSR-4 service discovery if a parent class is missing.
This commit is contained in:
commit
a956a76867
@ -60,11 +60,16 @@ abstract class FileLoader extends BaseFileLoader
|
|||||||
$interfaces = array();
|
$interfaces = array();
|
||||||
$singlyImplemented = array();
|
$singlyImplemented = array();
|
||||||
|
|
||||||
foreach ($classes as $class) {
|
foreach ($classes as $class => $errorMessage) {
|
||||||
if (interface_exists($class, false)) {
|
if (interface_exists($class, false)) {
|
||||||
$interfaces[] = $class;
|
$interfaces[] = $class;
|
||||||
} else {
|
} else {
|
||||||
$this->setDefinition($class, unserialize($serializedPrototype));
|
$this->setDefinition($class, $definition = unserialize($serializedPrototype));
|
||||||
|
if (null !== $errorMessage) {
|
||||||
|
$definition->addError($errorMessage);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
foreach (class_implements($class, false) as $interface) {
|
foreach (class_implements($class, false) as $interface) {
|
||||||
$singlyImplemented[$interface] = isset($singlyImplemented[$interface]) ? false : $class;
|
$singlyImplemented[$interface] = isset($singlyImplemented[$interface]) ? false : $class;
|
||||||
}
|
}
|
||||||
@ -139,13 +144,25 @@ abstract class FileLoader extends BaseFileLoader
|
|||||||
if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+$/', $class)) {
|
if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+$/', $class)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$r = $this->container->getReflectionClass($class);
|
||||||
|
} catch (\ReflectionException $e) {
|
||||||
|
$classes[$class] = sprintf(
|
||||||
|
'While discovering services from namespace "%s", an error was thrown when processing the class "%s": "%s".',
|
||||||
|
$namespace,
|
||||||
|
$class,
|
||||||
|
$e->getMessage()
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// check to make sure the expected class exists
|
// check to make sure the expected class exists
|
||||||
if (!$r = $this->container->getReflectionClass($class)) {
|
if (!$r) {
|
||||||
throw new InvalidArgumentException(sprintf('Expected to find class "%s" in file "%s" while importing services from resource "%s", but it was not found! Check the namespace prefix used with the resource.', $class, $path, $pattern));
|
throw new InvalidArgumentException(sprintf('Expected to find class "%s" in file "%s" while importing services from resource "%s", but it was not found! Check the namespace prefix used with the resource.', $class, $path, $pattern));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($r->isInstantiable() || $r->isInterface()) {
|
if ($r->isInstantiable() || $r->isInterface()) {
|
||||||
$classes[] = $class;
|
$classes[$class] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\BadClasses;
|
||||||
|
|
||||||
|
class MissingParent extends MissingClass
|
||||||
|
{
|
||||||
|
}
|
@ -9,7 +9,7 @@ return function (ContainerConfigurator $c) {
|
|||||||
->tag('baz');
|
->tag('baz');
|
||||||
$di->load(Prototype::class.'\\', '../Prototype')
|
$di->load(Prototype::class.'\\', '../Prototype')
|
||||||
->autoconfigure()
|
->autoconfigure()
|
||||||
->exclude('../Prototype/{OtherDir}')
|
->exclude('../Prototype/{OtherDir,BadClasses}')
|
||||||
->factory('f')
|
->factory('f')
|
||||||
->deprecate('%service_id%')
|
->deprecate('%service_id%')
|
||||||
->args(array(0))
|
->args(array(0))
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
|
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||||
<services>
|
<services>
|
||||||
<prototype namespace="Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\" resource="../Prototype/*" exclude="../Prototype/{OtherDir}" />
|
<prototype namespace="Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\" resource="../Prototype/*" exclude="../Prototype/{OtherDir,BadClasses}" />
|
||||||
</services>
|
</services>
|
||||||
</container>
|
</container>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
services:
|
services:
|
||||||
Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\:
|
Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\:
|
||||||
resource: ../Prototype
|
resource: ../Prototype
|
||||||
exclude: '../Prototype/{OtherDir}'
|
exclude: '../Prototype/{OtherDir,BadClasses}'
|
||||||
|
@ -25,6 +25,7 @@ use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
|
|||||||
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
|
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
|
||||||
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
|
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
|
||||||
use Symfony\Component\DependencyInjection\Reference;
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\BadClasses\MissingParent;
|
||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\OtherDir\AnotherSub\DeeperBaz;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\OtherDir\AnotherSub\DeeperBaz;
|
||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\OtherDir\Baz;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\OtherDir\Baz;
|
||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo;
|
||||||
@ -163,6 +164,26 @@ class FileLoaderTest extends TestCase
|
|||||||
$this->assertFalse($alias->isPrivate());
|
$this->assertFalse($alias->isPrivate());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testMissingParentClass()
|
||||||
|
{
|
||||||
|
$container = new ContainerBuilder();
|
||||||
|
$container->setParameter('bad_classes_dir', 'BadClasses');
|
||||||
|
$loader = new TestFileLoader($container, new FileLocator(self::$fixturesPath.'/Fixtures'));
|
||||||
|
|
||||||
|
$loader->registerClasses(
|
||||||
|
(new Definition())->setPublic(false),
|
||||||
|
'Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\BadClasses\\',
|
||||||
|
'Prototype/%bad_classes_dir%/*'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertTrue($container->has(MissingParent::class));
|
||||||
|
|
||||||
|
$this->assertSame(
|
||||||
|
array('While discovering services from namespace "Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\BadClasses\", an error was thrown when processing the class "Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\BadClasses\MissingParent": "Class Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\BadClasses\MissingClass not found".'),
|
||||||
|
$container->getDefinition(MissingParent::class)->getErrors()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
||||||
* @expectedExceptionMessageRegExp /Expected to find class "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\Prototype\\Bar" in file ".+" while importing services from resource "Prototype\/Sub\/\*", but it was not found\! Check the namespace prefix used with the resource/
|
* @expectedExceptionMessageRegExp /Expected to find class "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\Prototype\\Bar" in file ".+" while importing services from resource "Prototype\/Sub\/\*", but it was not found\! Check the namespace prefix used with the resource/
|
||||||
|
Reference in New Issue
Block a user