diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 20a8e43df..f03f85293 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -170,14 +170,32 @@ EOF; { // build package => install path map $packageMap = array(); + $packages[] = $mainPackage; - // add main package - $packageMap[] = array($mainPackage, ''); + // sort packages by dependencies + usort($packages, function (PackageInterface $a, PackageInterface $b) { + foreach (array_merge($a->getRequires(), $a->getDevRequires()) as $link) { + if (in_array($link->getTarget(), $b->getNames())) { + return 1; + } + } + foreach (array_merge($b->getRequires(), $b->getDevRequires()) as $link) { + if (in_array($link->getTarget(), $a->getNames())) { + return -1; + } + } + + return strcmp($a->getName(), $b->getName()); + }); foreach ($packages as $package) { if ($package instanceof AliasPackage) { continue; } + if ($package === $mainPackage) { + $packageMap[] = array($mainPackage, ''); + continue; + } $packageMap[] = array( $package, $installationManager->getInstallPath($package) @@ -217,9 +235,8 @@ EOF; } } - foreach ($autoloads as $type => $maps) { - krsort($autoloads[$type]); - } + krsort($autoloads['classmap']); + krsort($autoloads['psr-0']); return $autoloads; } diff --git a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php index 3c832995b..b6cb99a6b 100644 --- a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php +++ b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php @@ -13,6 +13,7 @@ namespace Composer\Test\Autoload; use Composer\Autoload\AutoloadGenerator; +use Composer\Package\Link; use Composer\Util\Filesystem; use Composer\Package\AliasPackage; use Composer\Package\Package; @@ -317,6 +318,52 @@ class AutoloadGeneratorTest extends TestCase $this->assertTrue(function_exists('testFilesAutoloadGenerationRoot')); } + public function testFilesAutoloadOrderByDependencies() + { + $package = new Package('a', '1.0', '1.0'); + $package->setAutoload(array('files' => array('root.php'))); + $package->setRequires(array(new Link('a', 'a/foo'))); + + $packages = array(); + $packages[] = $a = new Package('a/foo', '1.0', '1.0'); + $packages[] = $b = new Package('b/bar', '1.0', '1.0'); + $packages[] = $c = new Package('c/lorem', '1.0', '1.0'); + + $a->setAutoload(array('files' => array('testA.php'))); + $a->setRequires(array(new Link('a/foo', 'c/lorem'))); + + $b->setAutoload(array('files' => array('testB.php'))); + $b->setRequires(array(new Link('b/bar', 'c/lorem'))); + + $c->setAutoload(array('files' => array('testC.php'))); + + $this->repository->expects($this->once()) + ->method('getPackages') + ->will($this->returnValue($packages)); + + $this->fs->ensureDirectoryExists($this->vendorDir . '/a/foo'); + $this->fs->ensureDirectoryExists($this->vendorDir . '/b/bar'); + $this->fs->ensureDirectoryExists($this->vendorDir . '/c/lorem'); + file_put_contents($this->vendorDir . '/a/foo/testA.php', 'vendorDir . '/b/bar/testB.php', 'vendorDir . '/c/lorem/testC.php', 'workingDir . '/root.php', 'generator->dump($this->config, $this->repository, $package, $this->im, 'composer', false, 'FilesAutoloadOrder'); + $this->assertFileEquals(__DIR__ . '/Fixtures/autoload_functions_by_dependency.php', $this->vendorDir . '/autoload.php'); + $this->assertFileEquals(__DIR__ . '/Fixtures/autoload_real_files_by_dependency.php', $this->vendorDir . '/composer/autoload_realFilesAutoloadOrder.php'); + + // suppress the class loader to avoid fatals if the class is redefined + file_put_contents($this->vendorDir . '/composer/ClassLoader.php', ''); + + include $this->vendorDir . '/autoload.php'; + + $this->assertTrue(function_exists('testFilesAutoloadOrderByDependency1')); + $this->assertTrue(function_exists('testFilesAutoloadOrderByDependency2')); + $this->assertTrue(function_exists('testFilesAutoloadOrderByDependency3')); + $this->assertTrue(function_exists('testFilesAutoloadOrderByDependencyRoot')); + } + public function testOverrideVendorsAutoloading() { $package = new Package('a', '1.0', '1.0'); diff --git a/tests/Composer/Test/Autoload/Fixtures/autoload_functions_by_dependency.php b/tests/Composer/Test/Autoload/Fixtures/autoload_functions_by_dependency.php new file mode 100644 index 000000000..c643a7462 --- /dev/null +++ b/tests/Composer/Test/Autoload/Fixtures/autoload_functions_by_dependency.php @@ -0,0 +1,7 @@ + $path) { + $loader->add($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + + $loader->register(); + + require $vendorDir . '/c/lorem/testC.php'; + require $vendorDir . '/a/foo/testA.php'; + require $baseDir . '/root.php'; + require $vendorDir . '/b/bar/testB.php'; + + return $loader; + } +}