Skip to content

Commit bc04e9a

Browse files
silvesterweaverryan
authored andcommitted
Get the autoloader class from current registered autoload functions
1 parent 8713152 commit bc04e9a

File tree

3 files changed

+57
-40
lines changed

3 files changed

+57
-40
lines changed

src/Resources/config/services.xml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@
1313
<argument>%kernel.project_dir%</argument>
1414
</service>
1515

16-
<service id="maker.autoloader_util" class="Symfony\Bundle\MakerBundle\Util\AutoloaderUtil">
17-
<argument>%kernel.project_dir%</argument>
18-
</service>
16+
<service id="maker.autoloader_util" class="Symfony\Bundle\MakerBundle\Util\AutoloaderUtil" />
1917

2018
<service id="maker.event_registry" class="Symfony\Bundle\MakerBundle\EventRegistry">
2119
<argument type="service" id="event_dispatcher" />

src/Util/AutoloaderUtil.php

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Bundle\MakerBundle\Util;
1313

1414
use Composer\Autoload\ClassLoader;
15+
use Symfony\Component\Debug\DebugClassLoader;
1516

1617
/**
1718
* @author Ryan Weaver <[email protected]>
@@ -20,13 +21,10 @@
2021
*/
2122
class AutoloaderUtil
2223
{
23-
private static $classLoader;
24-
private $rootDir;
25-
26-
public function __construct(string $rootDir)
27-
{
28-
$this->rootDir = $rootDir;
29-
}
24+
/**
25+
* @var ClassLoader
26+
*/
27+
private $classLoader;
3028

3129
/**
3230
* Returns the relative path to where a new class should live.
@@ -76,16 +74,27 @@ public function getNamespacePrefixForClass(string $className): string
7674

7775
private function getClassLoader(): ClassLoader
7876
{
79-
if (null === self::$classLoader) {
80-
$autoloadPath = $this->rootDir.'/vendor/autoload.php';
81-
82-
if (!file_exists($autoloadPath)) {
83-
throw new \Exception(sprintf('Could not find the autoload file: "%s"', $autoloadPath));
77+
if (null === $this->classLoader) {
78+
$autoloadFunctions = spl_autoload_functions();
79+
foreach ($autoloadFunctions as $autoloader) {
80+
if (is_array($autoloader) && isset($autoloader[0]) && is_object($autoloader[0])) {
81+
if ($autoloader[0] instanceof ClassLoader) {
82+
$this->classLoader = $autoloader[0];
83+
break;
84+
}
85+
if ($autoloader[0] instanceof DebugClassLoader
86+
&& is_array($autoloader[0]->getClassLoader())
87+
&& $autoloader[0]->getClassLoader()[0] instanceof ClassLoader) {
88+
$this->classLoader = $autoloader[0]->getClassLoader()[0];
89+
break;
90+
}
91+
}
92+
}
93+
if (null === $this->classLoader) {
94+
throw new \Exception('Composer ClassLoader not found!');
8495
}
85-
86-
self::$classLoader = require $autoloadPath;
8796
}
8897

89-
return self::$classLoader;
98+
return $this->classLoader;
9099
}
91100
}

tests/Util/AutoloaderUtilTest.php

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
namespace Symfony\Bundle\MakerBundle\Tests\Util;
44

5+
use Composer\Autoload\ClassLoader;
56
use PHPUnit\Framework\TestCase;
67
use Symfony\Bundle\MakerBundle\Util\AutoloaderUtil;
78
use Symfony\Component\Filesystem\Filesystem;
8-
use Symfony\Component\Process\Process;
99

1010
class AutoloaderUtilTest extends TestCase
1111
{
@@ -28,49 +28,59 @@ public static function setupPaths()
2828

2929
public function testGetPathForFutureClass()
3030
{
31+
$classLoader = new ClassLoader();
3132
$composerJson = [
3233
'autoload' => [
3334
'psr-4' => [
34-
'Also\\In\\Src\\' => 'src/SubDir',
35-
'App\\' => 'src/',
36-
'Other\\Namespace\\' => 'lib',
37-
'' => 'fallback_dir',
35+
'Also\\In\\Src\\' => '/src/SubDir',
36+
'App\\' => '/src',
37+
'Other\\Namespace\\' => '/lib',
38+
'' => '/fallback_dir',
3839
],
3940
'psr-0' => [
40-
'Psr0\\Package' => 'lib/other',
41+
'Psr0\\Package' => '/lib/other',
4142
],
4243
],
4344
];
4445

45-
$fs = new Filesystem();
46-
if (!file_exists(self::$currentRootDir)) {
47-
$fs->mkdir(self::$currentRootDir);
46+
foreach ($composerJson['autoload'] as $psr => $dirs) {
47+
foreach ($dirs as $prefix => $path) {
48+
if ($psr == 'psr-4') {
49+
$classLoader->addPsr4($prefix, self::$currentRootDir.$path);
50+
} else {
51+
$classLoader->add($prefix, self::$currentRootDir.$path);
52+
}
53+
}
4854
}
4955

50-
$fs->remove(self::$currentRootDir.'/vendor');
51-
file_put_contents(
52-
self::$currentRootDir.'/composer.json',
53-
json_encode($composerJson, JSON_PRETTY_PRINT)
54-
);
55-
$process = new Process('composer dump-autoload', self::$currentRootDir);
56-
$process->run();
57-
if (!$process->isSuccessful()) {
58-
throw new \Exception('Error running composer dump-autoload: '.$process->getErrorOutput());
59-
}
56+
$reflection = new \ReflectionClass(AutoloaderUtil::class);
57+
$property = $reflection->getProperty('classLoader');
58+
$property->setAccessible(true);
59+
60+
$autoloaderUtil = new AutoloaderUtil();
6061

62+
$property->setValue($autoloaderUtil, $classLoader);
6163

62-
$autoloaderUtil = new AutoloaderUtil(self::$currentRootDir);
6364
foreach ($this->getPathForFutureClassTests() as $className => $expectedPath) {
6465
$this->assertSame(
65-
// the paths will start in vendor/composer and be relative
66-
str_replace('\\', '/', self::$currentRootDir.'/vendor/composer/../../'.$expectedPath),
66+
str_replace('\\', '/', self::$currentRootDir.'/'.$expectedPath),
6767
// normalize slashes for Windows comparison
6868
str_replace('\\', '/', $autoloaderUtil->getPathForFutureClass($className)),
6969
sprintf('class "%s" should have been in path "%s"', $className, $expectedPath)
7070
);
7171
}
7272
}
7373

74+
public function testCanFindClassLoader()
75+
{
76+
$reflection = new \ReflectionClass(AutoloaderUtil::class);
77+
$method = $reflection->getMethod('getClassLoader');
78+
$method->setAccessible(true);
79+
$autoloaderUtil = new AutoloaderUtil();
80+
$autoloader = $method->invoke($autoloaderUtil);
81+
$this->assertInstanceOf(ClassLoader::class, $autoloader, 'Wrong ClassLoader found');
82+
}
83+
7484
public function getPathForFutureClassTests()
7585
{
7686
return [

0 commit comments

Comments
 (0)