diff --git a/CHANGELOG.md b/CHANGELOG.md index e11ed2552..306521056 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Added caching of repository metadata (faster startup times & failover if packagist is down) * Added include_path support for legacy projects that are full of require_once statements * Added installation notifications API to allow better statistics on Composer repositories + * Added autoloading support for root packages that use target-dir * Improved repository protocol to have large cacheable parts * 1.0.0-alpha2 (2012-04-03) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index d3267e9b1..dd6d1ccc3 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -79,6 +79,36 @@ return array( EOF; + // add custom psr-0 autoloading if the root package has a target dir + $targetDirLoader = null; + $mainAutoload = $mainPackage->getAutoload(); + if ($mainPackage->getTargetDir() && $mainAutoload['psr-0']) { + $levels = count(explode('/', trim(strtr($mainPackage->getTargetDir(), '\\', '/'), '/'))); + $prefixes = implode(', ', array_map(function ($prefix) { + return var_export($prefix, true); + }, array_keys($mainAutoload['psr-0']))); + $baseDirFromTargetDirCode = $filesystem->findShortestPathCode(realpath($targetDir), getcwd(), true); + + $targetDirLoader = <<getIncludePathsFile($packageMap, $filesystem, $relVendorPath, $vendorPath, $vendorDirCode, $appBaseDirCode)) { file_put_contents($targetDir.'/include_paths.php', $includePathFile); } - file_put_contents($targetDir.'/autoload.php', $this->getAutoloadFile(true, true, (Boolean) $includePathFile)); + file_put_contents($targetDir.'/autoload.php', $this->getAutoloadFile(true, true, (Boolean) $includePathFile, $targetDirLoader)); copy(__DIR__.'/ClassLoader.php', $targetDir.'/ClassLoader.php'); // TODO BC feature, add E_DEPRECATED in autoload.php on April 30th, remove after May 30th @@ -243,7 +273,7 @@ EOF; return $baseDir.var_export($path, true); } - protected function getAutoloadFile($usePSR0, $useClassMap, $useIncludePath) + protected function getAutoloadFile($usePSR0, $useClassMap, $useIncludePath, $targetDirLoader) { $file = <<<'HEADER' register(); diff --git a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php index f4feef203..5cabfd2df 100644 --- a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php +++ b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php @@ -141,6 +141,22 @@ class AutoloadGeneratorTest extends TestCase $this->assertAutoloadFiles('classmap2', $this->vendorDir.'/.composer', 'classmap'); } + public function testMainPackageAutoloadingWithTargetDir() + { + $package = new MemoryPackage('a', '1.0', '1.0'); + $package->setAutoload(array( + 'psr-0' => array('Main\\Foo' => '', 'Main\\Bar' => ''), + )); + $package->setTargetDir('Main/Foo/'); + + $this->repository->expects($this->once()) + ->method('getPackages') + ->will($this->returnValue(array())); + + $this->generator->dump($this->repository, $package, $this->im, $this->vendorDir.'/.composer'); + $this->assertFileEquals(__DIR__.'/Fixtures/autoload_target_dir.php', $this->vendorDir.'/.composer/autoload.php'); + } + public function testVendorsAutoloading() { $package = new MemoryPackage('a', '1.0', '1.0'); diff --git a/tests/Composer/Test/Autoload/Fixtures/autoload_target_dir.php b/tests/Composer/Test/Autoload/Fixtures/autoload_target_dir.php new file mode 100644 index 000000000..f2acfcc3b --- /dev/null +++ b/tests/Composer/Test/Autoload/Fixtures/autoload_target_dir.php @@ -0,0 +1,39 @@ + $path) { + $loader->add($namespace, $path); + } + + $classMap = require __DIR__.'/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + + spl_autoload_register(function($class) { + $prefixes = array('Main\\Foo', 'Main\\Bar'); + foreach ($prefixes as $prefix) { + if (0 !== strpos($class, $prefix)) { + continue; + } + $path = dirname(dirname(__DIR__)) . '/' . implode('/', array_slice(explode('\\', $class), 2)).'.php'; + if (!stream_resolve_include_path($path)) { + return false; + } + require_once $path; + return true; + } + }); + + $loader->register(); + + return $loader; +});