From bc04e9adacd6e2e677fcccbc1bbcc240efc26993 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Silvester=20Mara=C5=BE?= Date: Sun, 22 Apr 2018 14:43:39 +0200 Subject: [PATCH] Get the autoloader class from current registered autoload functions --- src/Resources/config/services.xml | 4 +-- src/Util/AutoloaderUtil.php | 39 +++++++++++++--------- tests/Util/AutoloaderUtilTest.php | 54 ++++++++++++++++++------------- 3 files changed, 57 insertions(+), 40 deletions(-) diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml index d5829dd48..6109a2299 100644 --- a/src/Resources/config/services.xml +++ b/src/Resources/config/services.xml @@ -13,9 +13,7 @@ %kernel.project_dir% - - %kernel.project_dir% - + diff --git a/src/Util/AutoloaderUtil.php b/src/Util/AutoloaderUtil.php index 942711d07..02b973e3e 100644 --- a/src/Util/AutoloaderUtil.php +++ b/src/Util/AutoloaderUtil.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\MakerBundle\Util; use Composer\Autoload\ClassLoader; +use Symfony\Component\Debug\DebugClassLoader; /** * @author Ryan Weaver @@ -20,13 +21,10 @@ */ class AutoloaderUtil { - private static $classLoader; - private $rootDir; - - public function __construct(string $rootDir) - { - $this->rootDir = $rootDir; - } + /** + * @var ClassLoader + */ + private $classLoader; /** * Returns the relative path to where a new class should live. @@ -76,16 +74,27 @@ public function getNamespacePrefixForClass(string $className): string private function getClassLoader(): ClassLoader { - if (null === self::$classLoader) { - $autoloadPath = $this->rootDir.'/vendor/autoload.php'; - - if (!file_exists($autoloadPath)) { - throw new \Exception(sprintf('Could not find the autoload file: "%s"', $autoloadPath)); + if (null === $this->classLoader) { + $autoloadFunctions = spl_autoload_functions(); + foreach ($autoloadFunctions as $autoloader) { + if (is_array($autoloader) && isset($autoloader[0]) && is_object($autoloader[0])) { + if ($autoloader[0] instanceof ClassLoader) { + $this->classLoader = $autoloader[0]; + break; + } + if ($autoloader[0] instanceof DebugClassLoader + && is_array($autoloader[0]->getClassLoader()) + && $autoloader[0]->getClassLoader()[0] instanceof ClassLoader) { + $this->classLoader = $autoloader[0]->getClassLoader()[0]; + break; + } + } + } + if (null === $this->classLoader) { + throw new \Exception('Composer ClassLoader not found!'); } - - self::$classLoader = require $autoloadPath; } - return self::$classLoader; + return $this->classLoader; } } diff --git a/tests/Util/AutoloaderUtilTest.php b/tests/Util/AutoloaderUtilTest.php index 286b3392b..d9d1b0ed0 100644 --- a/tests/Util/AutoloaderUtilTest.php +++ b/tests/Util/AutoloaderUtilTest.php @@ -2,10 +2,10 @@ namespace Symfony\Bundle\MakerBundle\Tests\Util; +use Composer\Autoload\ClassLoader; use PHPUnit\Framework\TestCase; use Symfony\Bundle\MakerBundle\Util\AutoloaderUtil; use Symfony\Component\Filesystem\Filesystem; -use Symfony\Component\Process\Process; class AutoloaderUtilTest extends TestCase { @@ -28,42 +28,42 @@ public static function setupPaths() public function testGetPathForFutureClass() { + $classLoader = new ClassLoader(); $composerJson = [ 'autoload' => [ 'psr-4' => [ - 'Also\\In\\Src\\' => 'src/SubDir', - 'App\\' => 'src/', - 'Other\\Namespace\\' => 'lib', - '' => 'fallback_dir', + 'Also\\In\\Src\\' => '/src/SubDir', + 'App\\' => '/src', + 'Other\\Namespace\\' => '/lib', + '' => '/fallback_dir', ], 'psr-0' => [ - 'Psr0\\Package' => 'lib/other', + 'Psr0\\Package' => '/lib/other', ], ], ]; - $fs = new Filesystem(); - if (!file_exists(self::$currentRootDir)) { - $fs->mkdir(self::$currentRootDir); + foreach ($composerJson['autoload'] as $psr => $dirs) { + foreach ($dirs as $prefix => $path) { + if ($psr == 'psr-4') { + $classLoader->addPsr4($prefix, self::$currentRootDir.$path); + } else { + $classLoader->add($prefix, self::$currentRootDir.$path); + } + } } - $fs->remove(self::$currentRootDir.'/vendor'); - file_put_contents( - self::$currentRootDir.'/composer.json', - json_encode($composerJson, JSON_PRETTY_PRINT) - ); - $process = new Process('composer dump-autoload', self::$currentRootDir); - $process->run(); - if (!$process->isSuccessful()) { - throw new \Exception('Error running composer dump-autoload: '.$process->getErrorOutput()); - } + $reflection = new \ReflectionClass(AutoloaderUtil::class); + $property = $reflection->getProperty('classLoader'); + $property->setAccessible(true); + + $autoloaderUtil = new AutoloaderUtil(); + $property->setValue($autoloaderUtil, $classLoader); - $autoloaderUtil = new AutoloaderUtil(self::$currentRootDir); foreach ($this->getPathForFutureClassTests() as $className => $expectedPath) { $this->assertSame( - // the paths will start in vendor/composer and be relative - str_replace('\\', '/', self::$currentRootDir.'/vendor/composer/../../'.$expectedPath), + str_replace('\\', '/', self::$currentRootDir.'/'.$expectedPath), // normalize slashes for Windows comparison str_replace('\\', '/', $autoloaderUtil->getPathForFutureClass($className)), sprintf('class "%s" should have been in path "%s"', $className, $expectedPath) @@ -71,6 +71,16 @@ public function testGetPathForFutureClass() } } + public function testCanFindClassLoader() + { + $reflection = new \ReflectionClass(AutoloaderUtil::class); + $method = $reflection->getMethod('getClassLoader'); + $method->setAccessible(true); + $autoloaderUtil = new AutoloaderUtil(); + $autoloader = $method->invoke($autoloaderUtil); + $this->assertInstanceOf(ClassLoader::class, $autoloader, 'Wrong ClassLoader found'); + } + public function getPathForFutureClassTests() { return [