diff --git a/src/DependencyInjection/MakerExtension.php b/src/DependencyInjection/MakerExtension.php
index 575408fa1..8051d8919 100644
--- a/src/DependencyInjection/MakerExtension.php
+++ b/src/DependencyInjection/MakerExtension.php
@@ -39,6 +39,9 @@ public function load(array $configs, ContainerBuilder $container)
$rootNamespace = trim($config['root_namespace'], '\\');
+ $autoloaderFinderDefinition = $container->getDefinition('maker.autoloader_finder');
+ $autoloaderFinderDefinition->replaceArgument(0, $rootNamespace);
+
$makeCommandDefinition = $container->getDefinition('maker.generator');
$makeCommandDefinition->replaceArgument(1, $rootNamespace);
diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml
index 6440feb70..1031517e4 100644
--- a/src/Resources/config/services.xml
+++ b/src/Resources/config/services.xml
@@ -13,7 +13,9 @@
%kernel.project_dir%
-
+
+
+
diff --git a/src/Util/ComposerAutoloaderFinder.php b/src/Util/ComposerAutoloaderFinder.php
index 00d28d58e..db68dbe2d 100644
--- a/src/Util/ComposerAutoloaderFinder.php
+++ b/src/Util/ComposerAutoloaderFinder.php
@@ -19,11 +19,21 @@
*/
class ComposerAutoloaderFinder
{
+ private $rootNamespace;
+
/**
* @var ClassLoader|null
*/
private $classLoader = null;
+ public function __construct(string $rootNamespace)
+ {
+ $this->rootNamespace = [
+ 'psr0' => rtrim($rootNamespace, '\\'),
+ 'psr4' => rtrim($rootNamespace, '\\').'\\',
+ ];
+ }
+
public function getClassLoader(): ClassLoader
{
if (null === $this->classLoader) {
@@ -31,7 +41,7 @@ public function getClassLoader(): ClassLoader
}
if (null === $this->classLoader) {
- throw new \Exception('Composer ClassLoader not found!');
+ throw new \Exception("Could not find a Composer autoloader that autoloads from '{$this->rootNamespace['psr4']}'");
}
return $this->classLoader;
@@ -45,19 +55,61 @@ private function findComposerClassLoader()
$autoloadFunctions = spl_autoload_functions();
foreach ($autoloadFunctions as $autoloader) {
- if (\is_array($autoloader) && isset($autoloader[0]) && \is_object($autoloader[0])) {
- if ($autoloader[0] instanceof ClassLoader) {
- return $autoloader[0];
- }
-
- if ($autoloader[0] instanceof DebugClassLoader
- && \is_array($autoloader[0]->getClassLoader())
- && $autoloader[0]->getClassLoader()[0] instanceof ClassLoader) {
- return $autoloader[0]->getClassLoader()[0];
- }
+ $classLoader = $this->extractComposerClassLoader($autoloader);
+ if (null === $classLoader) {
+ continue;
+ }
+
+ $finalClassLoader = $this->locateMatchingClassLoader($classLoader);
+ if (null !== $finalClassLoader) {
+ return $finalClassLoader;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @return ClassLoader|null
+ */
+ private function extractComposerClassLoader(array $autoloader)
+ {
+ if (isset($autoloader[0]) && \is_object($autoloader[0])) {
+ if ($autoloader[0] instanceof ClassLoader) {
+ return $autoloader[0];
+ }
+ if ($autoloader[0] instanceof DebugClassLoader
+ && \is_array($autoloader[0]->getClassLoader())
+ && $autoloader[0]->getClassLoader()[0] instanceof ClassLoader) {
+ return $autoloader[0]->getClassLoader()[0];
}
}
return null;
}
+
+ /**
+ * @return ClassLoader|null
+ */
+ private function locateMatchingClassLoader(ClassLoader $classLoader)
+ {
+ $makerClassLoader = null;
+ foreach ($classLoader->getPrefixesPsr4() as $prefix => $paths) {
+ if ('Symfony\\Bundle\\MakerBundle\\' === $prefix) {
+ $makerClassLoader = $classLoader;
+ }
+ if (0 === strpos($this->rootNamespace['psr4'], $prefix)) {
+ return $classLoader;
+ }
+ }
+
+ foreach ($classLoader->getPrefixes() as $prefix => $paths) {
+ if (0 === strpos($this->rootNamespace['psr0'], $prefix)) {
+ return $classLoader;
+ }
+ }
+
+ // We can default to using the autoloader containing this component if none are matching.
+ return $makerClassLoader ?: null;
+ }
}
diff --git a/tests/Maker/FunctionalTest.php b/tests/Maker/FunctionalTest.php
index 64f765d7a..ff7e45312 100644
--- a/tests/Maker/FunctionalTest.php
+++ b/tests/Maker/FunctionalTest.php
@@ -205,7 +205,7 @@ public function getCommandTests()
])
->addExtraDependencies('orm')
->setFixtureFilesPath(__DIR__.'/../fixtures/MakeFormForEntity')
- ];
+ ];
yield 'form_for_non_entity_dto' => [MakerTestDetails::createTest(
$this->getMakerInstance(MakeForm::class),
diff --git a/tests/Util/AutoloaderUtilTest.php b/tests/Util/AutoloaderUtilTest.php
index f07e8c2c9..c95ba77a2 100644
--- a/tests/Util/AutoloaderUtilTest.php
+++ b/tests/Util/AutoloaderUtilTest.php
@@ -87,6 +87,7 @@ private function createComposerAutoloaderFinder(array $composerJsonParams = null
/** @var \PHPUnit_Framework_MockObject_MockObject|ComposerAutoloaderFinder $finder */
$finder = $this
->getMockBuilder(ComposerAutoloaderFinder::class)
+ ->setConstructorArgs(['App\\'])
->getMock();
$finder
diff --git a/tests/Util/ComposerAutoloaderFinderTest.php b/tests/Util/ComposerAutoloaderFinderTest.php
index d76c473e3..5adc155cc 100644
--- a/tests/Util/ComposerAutoloaderFinderTest.php
+++ b/tests/Util/ComposerAutoloaderFinderTest.php
@@ -10,6 +10,8 @@ class ComposerAutoloaderFinderTest extends TestCase
{
public static $getSplAutoloadFunctions = 'spl_autoload_functions';
+ private static $rootNamespace = 'Fake\\It\\Till\\You\\Make\\It\\';
+
/**
* @after
*/
@@ -18,9 +20,20 @@ public function resetAutoloadFunction()
self::$getSplAutoloadFunctions = 'spl_autoload_functions';
}
- public function testGetClassLoader()
+ public function providerNamespaces(): \Generator
{
- $loader = (new ComposerAutoloaderFinder())->getClassLoader();
+ yield 'Configured PSR-0' => [rtrim(static::$rootNamespace, '\\'), null];
+ yield 'Configured PSR-4' => [null, static::$rootNamespace];
+ yield 'Fallback default' => [null, 'Symfony\\Bundle\\MakerBundle\\'];
+ }
+
+ /**
+ * @dataProvider providerNamespaces
+ */
+ public function testGetClassLoader($psr0, $psr4)
+ {
+ $this->setupAutoloadFunctions($psr0, $psr4);
+ $loader = (new ComposerAutoloaderFinder(static::$rootNamespace))->getClassLoader();
$this->assertInstanceOf(ClassLoader::class, $loader, 'Wrong ClassLoader found');
}
@@ -35,7 +48,26 @@ public function testGetClassLoaderWhenItIsEmpty()
};
// throws \Exception
- (new ComposerAutoloaderFinder())->getClassLoader();
+ (new ComposerAutoloaderFinder(static::$rootNamespace))->getClassLoader();
+ }
+
+ /**
+ * @param string|null $psr0
+ * @param string|null $psr4
+ */
+ private function setupAutoloadFunctions($psr0, $psr4)
+ {
+ self::$getSplAutoloadFunctions = function () use ($psr0, $psr4) {
+ $loader = new ClassLoader();
+ if ($psr0) {
+ $loader->add($psr0, __DIR__);
+ }
+ if ($psr4) {
+ $loader->addPsr4($psr4, __DIR__);
+ }
+
+ return [[$loader, 'loadClass']];
+ };
}
}