From 3d6c3ba836e6755100915846c797fde572e976b2 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Thu, 25 Jan 2018 20:21:40 +0100 Subject: [PATCH] Don't stop PSR-4 service discovery if a parent class is missing. --- .../DependencyInjection/Loader/FileLoader.php | 25 ++++++++++++++++--- .../Prototype/BadClasses/MissingParent.php | 7 ++++++ .../Tests/Fixtures/config/prototype.php | 2 +- .../Tests/Fixtures/xml/services_prototype.xml | 2 +- .../Fixtures/yaml/services_prototype.yml | 2 +- .../Tests/Loader/FileLoaderTest.php | 21 ++++++++++++++++ 6 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/BadClasses/MissingParent.php diff --git a/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php index c61acdf065183..fa8c636edcd1f 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php @@ -60,11 +60,16 @@ public function registerClasses(Definition $prototype, $namespace, $resource, $e $interfaces = array(); $singlyImplemented = array(); - foreach ($classes as $class) { + foreach ($classes as $class => $errorMessage) { if (interface_exists($class, false)) { $interfaces[] = $class; } 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) { $singlyImplemented[$interface] = isset($singlyImplemented[$interface]) ? false : $class; } @@ -139,13 +144,25 @@ private function findClasses($namespace, $pattern, $excludePattern) 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; } + + 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 - 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)); } if ($r->isInstantiable() || $r->isInterface()) { - $classes[] = $class; + $classes[$class] = null; } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/BadClasses/MissingParent.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/BadClasses/MissingParent.php new file mode 100644 index 0000000000000..53c97249cf3f2 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/BadClasses/MissingParent.php @@ -0,0 +1,7 @@ +tag('baz'); $di->load(Prototype::class.'\\', '../Prototype') ->autoconfigure() - ->exclude('../Prototype/{OtherDir}') + ->exclude('../Prototype/{OtherDir,BadClasses}') ->factory('f') ->deprecate('%service_id%') ->args(array(0)) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_prototype.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_prototype.xml index 333e71ce57d5a..381f95dd00fa5 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_prototype.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_prototype.xml @@ -1,6 +1,6 @@ - + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_prototype.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_prototype.yml index fb47bcb7e7a52..8c0b202aab2b7 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_prototype.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_prototype.yml @@ -1,4 +1,4 @@ services: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\: resource: ../Prototype - exclude: '../Prototype/{OtherDir}' + exclude: '../Prototype/{OtherDir,BadClasses}' diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/FileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/FileLoaderTest.php index 4cba7443e8ce9..8a271a818a475 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/FileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/FileLoaderTest.php @@ -25,6 +25,7 @@ use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; 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\Baz; use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo; @@ -163,6 +164,26 @@ public function testNestedRegisterClasses() $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 * @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/ pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy