1
0
Fork 0

Merge remote-tracking branch 'hason/classgenerator'

pull/1231/head
Jordi Boggiano 2012-10-17 17:19:23 +02:00
commit e79e7dcd8d
6 changed files with 123 additions and 57 deletions

View File

@ -117,8 +117,6 @@ EOF;
// flatten array // flatten array
$classMap = array(); $classMap = array();
$autoloads['classmap'] = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($autoloads['classmap']));
if ($scanPsr0Packages) { if ($scanPsr0Packages) {
foreach ($autoloads['psr-0'] as $namespace => $paths) { foreach ($autoloads['psr-0'] as $namespace => $paths) {
foreach ($paths as $dir) { foreach ($paths as $dir) {
@ -139,12 +137,16 @@ EOF;
} }
} }
} }
$autoloads['classmap'] = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($autoloads['classmap']));
foreach ($autoloads['classmap'] as $dir) { foreach ($autoloads['classmap'] as $dir) {
foreach (ClassMapGenerator::createMap($dir) as $class => $path) { foreach (ClassMapGenerator::createMap($dir) as $class => $path) {
$path = '/'.$filesystem->findShortestPath(getcwd(), $path, true); $path = '/'.$filesystem->findShortestPath(getcwd(), $path, true);
$classMap[$class] = '$baseDir . '.var_export($path, true).",\n"; $classMap[$class] = '$baseDir . '.var_export($path, true).",\n";
} }
} }
ksort($classMap);
foreach ($classMap as $class => $code) { foreach ($classMap as $class => $code) {
$classmapFile .= ' '.var_export($class, true).' => '.$code; $classmapFile .= ' '.var_export($class, true).' => '.$code;
} }
@ -170,28 +172,13 @@ EOF;
{ {
// build package => install path map // build package => install path map
$packageMap = array(); $packageMap = array();
$packages[] = $mainPackage; array_unshift($packages, $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) { foreach ($packages as $package) {
if ($package instanceof AliasPackage) { if ($package instanceof AliasPackage) {
continue; continue;
} }
if ($package === $mainPackage) { if ($package === $mainPackage) {
$packageMap[] = array($mainPackage, ''); $packageMap[] = array($mainPackage, '');
continue; continue;
@ -213,32 +200,15 @@ EOF;
*/ */
public function parseAutoloads(array $packageMap) public function parseAutoloads(array $packageMap)
{ {
$autoloads = array('classmap' => array(), 'psr-0' => array(), 'files' => array()); $sortedPackageMap = $this->sortPackageMap($packageMap);
foreach ($packageMap as $item) {
list($package, $installPath) = $item;
if (null !== $package->getTargetDir()) { $psr0 = $this->parseAutoloadsType($packageMap, 'psr-0');
$installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir())); $classmap = $this->parseAutoloadsType($sortedPackageMap, 'classmap');
} $files = $this->parseAutoloadsType($sortedPackageMap, 'files');
foreach ($package->getAutoload() as $type => $mapping) { krsort($psr0);
// skip misconfigured packages
if (!is_array($mapping)) {
continue;
}
foreach ($mapping as $namespace => $paths) { return array('psr-0' => $psr0, 'classmap' => $classmap, 'files' => $files);
foreach ((array) $paths as $path) {
$autoloads[$type][$namespace][] = empty($installPath) ? $path : $installPath.'/'.$path;
}
}
}
}
krsort($autoloads['classmap']);
krsort($autoloads['psr-0']);
return $autoloads;
} }
/** /**
@ -445,4 +415,79 @@ FOOTER;
} }
protected function parseAutoloadsType(array $packageMap, $type)
{
$autoloads = array();
foreach ($packageMap as $item) {
list($package, $installPath) = $item;
$autoload = $package->getAutoload();
// skip misconfigured packages
if (!isset($autoload[$type]) || !is_array($autoload[$type])) {
continue;
}
if (null !== $package->getTargetDir()) {
$installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
}
foreach ($autoload[$type] as $namespace => $paths) {
foreach ((array) $paths as $path) {
$autoloads[$namespace][] = empty($installPath) ? $path : $installPath.'/'.$path;
}
}
}
return $autoloads;
}
protected function sortPackageMap(array $packageMap)
{
$groups = array();
$names = array();
foreach ($packageMap as $key => $item) {
$groups[$key] = array($item);
$mainName = $item[0]->getName();
foreach ($item[0]->getNames() as $name) {
if (!isset($names[$name])) {
$names[$name] = $name == $mainName ? $key : $mainName;
}
}
}
foreach ($packageMap as $item) {
foreach (array_merge($item[0]->getRequires(), $item[0]->getDevRequires()) as $link) {
$target = $link->getTarget();
if (!isset($names[$target])) {
continue;
}
$targetKey = $names[$target];
if (is_string($targetKey)) {
if (!isset($names[$targetKey])) {
continue;
}
$targetKey = $names[$targetKey];
}
$packageKey = $names[$item[0]->getName()];
if ($targetKey <= $packageKey || !isset($groups[$packageKey])) {
continue;
}
foreach ($groups[$packageKey] as $originalItem) {
$groups[$targetKey][] = $originalItem;
$names[$originalItem[0]->getName()] = $targetKey;
}
unset($groups[$packageKey]);
}
}
$sortedPackageMap = array();
foreach ($groups as $group) {
$sortedPackageMap = array_merge($sortedPackageMap, $group);
}
return $sortedPackageMap;
}
} }

View File

@ -238,9 +238,9 @@ class AutoloadGeneratorTest extends TestCase
$this->assertTrue(file_exists($this->vendorDir.'/composer/autoload_classmap.php'), "ClassMap file needs to be generated."); $this->assertTrue(file_exists($this->vendorDir.'/composer/autoload_classmap.php'), "ClassMap file needs to be generated.");
$this->assertEquals( $this->assertEquals(
array( array(
'ClassMapFoo' => $this->workingDir.'/composer-test-autoload/a/a/src/a.php',
'ClassMapBar' => $this->workingDir.'/composer-test-autoload/b/b/src/b.php', 'ClassMapBar' => $this->workingDir.'/composer-test-autoload/b/b/src/b.php',
'ClassMapBaz' => $this->workingDir.'/composer-test-autoload/b/b/lib/c.php', 'ClassMapBaz' => $this->workingDir.'/composer-test-autoload/b/b/lib/c.php',
'ClassMapFoo' => $this->workingDir.'/composer-test-autoload/a/a/src/a.php',
), ),
include ($this->vendorDir.'/composer/autoload_classmap.php') include ($this->vendorDir.'/composer/autoload_classmap.php')
); );
@ -275,9 +275,9 @@ class AutoloadGeneratorTest extends TestCase
$this->assertTrue(file_exists($this->vendorDir.'/composer/autoload_classmap.php'), "ClassMap file needs to be generated."); $this->assertTrue(file_exists($this->vendorDir.'/composer/autoload_classmap.php'), "ClassMap file needs to be generated.");
$this->assertEquals( $this->assertEquals(
array( array(
'ClassMapFoo' => $this->workingDir.'/composer-test-autoload/a/a/src/a.php',
'ClassMapBar' => $this->workingDir.'/composer-test-autoload/b/b/test.php', 'ClassMapBar' => $this->workingDir.'/composer-test-autoload/b/b/test.php',
'ClassMapBaz' => $this->workingDir.'/composer-test-autoload/c/c/foo/test.php', 'ClassMapBaz' => $this->workingDir.'/composer-test-autoload/c/c/foo/test.php',
'ClassMapFoo' => $this->workingDir.'/composer-test-autoload/a/a/src/a.php',
), ),
include ($this->vendorDir.'/composer/autoload_classmap.php') include ($this->vendorDir.'/composer/autoload_classmap.php')
); );
@ -322,31 +322,42 @@ class AutoloadGeneratorTest extends TestCase
{ {
$package = new Package('a', '1.0', '1.0'); $package = new Package('a', '1.0', '1.0');
$package->setAutoload(array('files' => array('root.php'))); $package->setAutoload(array('files' => array('root.php')));
$package->setRequires(array(new Link('a', 'a/foo'))); $package->setRequires(array(new Link('a', 'z/foo')));
$packages = array(); $packages = array();
$packages[] = $a = new Package('a/foo', '1.0', '1.0'); $packages[] = $z = new Package('z/foo', '1.0', '1.0');
$packages[] = $b = new Package('b/bar', '1.0', '1.0'); $packages[] = $b = new Package('b/bar', '1.0', '1.0');
$packages[] = $c = new Package('c/lorem', '1.0', '1.0'); $packages[] = $c = new Package('c/lorem', '1.0', '1.0');
$packages[] = $d = new Package('d/d', '1.0', '1.0');
$packages[] = $e = new Package('e/e', '1.0', '1.0');
$a->setAutoload(array('files' => array('testA.php'))); $z->setAutoload(array('files' => array('testA.php')));
$a->setRequires(array(new Link('a/foo', 'c/lorem'))); $z->setRequires(array(new Link('z/foo', 'c/lorem')));
$b->setAutoload(array('files' => array('testB.php'))); $b->setAutoload(array('files' => array('testB.php')));
$b->setRequires(array(new Link('b/bar', 'c/lorem'))); $b->setRequires(array(new Link('b/bar', 'c/lorem')));
$c->setAutoload(array('files' => array('testC.php'))); $c->setAutoload(array('files' => array('testC.php')));
$d->setAutoload(array('files' => array('testD.php')));
$e->setAutoload(array('files' => array('testE.php')));
$e->setRequires(array(new Link('e/e', 'c/lorem')));
$this->repository->expects($this->once()) $this->repository->expects($this->once())
->method('getPackages') ->method('getPackages')
->will($this->returnValue($packages)); ->will($this->returnValue($packages));
$this->fs->ensureDirectoryExists($this->vendorDir . '/a/foo'); $this->fs->ensureDirectoryExists($this->vendorDir . '/z/foo');
$this->fs->ensureDirectoryExists($this->vendorDir . '/b/bar'); $this->fs->ensureDirectoryExists($this->vendorDir . '/b/bar');
$this->fs->ensureDirectoryExists($this->vendorDir . '/c/lorem'); $this->fs->ensureDirectoryExists($this->vendorDir . '/c/lorem');
file_put_contents($this->vendorDir . '/a/foo/testA.php', '<?php function testFilesAutoloadOrderByDependency1() {}'); $this->fs->ensureDirectoryExists($this->vendorDir . '/d/d');
$this->fs->ensureDirectoryExists($this->vendorDir . '/e/e');
file_put_contents($this->vendorDir . '/z/foo/testA.php', '<?php function testFilesAutoloadOrderByDependency1() {}');
file_put_contents($this->vendorDir . '/b/bar/testB.php', '<?php function testFilesAutoloadOrderByDependency2() {}'); file_put_contents($this->vendorDir . '/b/bar/testB.php', '<?php function testFilesAutoloadOrderByDependency2() {}');
file_put_contents($this->vendorDir . '/c/lorem/testC.php', '<?php function testFilesAutoloadOrderByDependency3() {}'); file_put_contents($this->vendorDir . '/c/lorem/testC.php', '<?php function testFilesAutoloadOrderByDependency3() {}');
file_put_contents($this->vendorDir . '/d/d/testD.php', '<?php function testFilesAutoloadOrderByDependency4() {}');
file_put_contents($this->vendorDir . '/e/e/testE.php', '<?php function testFilesAutoloadOrderByDependency5() {}');
file_put_contents($this->workingDir . '/root.php', '<?php function testFilesAutoloadOrderByDependencyRoot() {}'); file_put_contents($this->workingDir . '/root.php', '<?php function testFilesAutoloadOrderByDependencyRoot() {}');
$this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', false, 'FilesAutoloadOrder'); $this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', false, 'FilesAutoloadOrder');
@ -361,18 +372,21 @@ class AutoloadGeneratorTest extends TestCase
$this->assertTrue(function_exists('testFilesAutoloadOrderByDependency1')); $this->assertTrue(function_exists('testFilesAutoloadOrderByDependency1'));
$this->assertTrue(function_exists('testFilesAutoloadOrderByDependency2')); $this->assertTrue(function_exists('testFilesAutoloadOrderByDependency2'));
$this->assertTrue(function_exists('testFilesAutoloadOrderByDependency3')); $this->assertTrue(function_exists('testFilesAutoloadOrderByDependency3'));
$this->assertTrue(function_exists('testFilesAutoloadOrderByDependency4'));
$this->assertTrue(function_exists('testFilesAutoloadOrderByDependency5'));
$this->assertTrue(function_exists('testFilesAutoloadOrderByDependencyRoot')); $this->assertTrue(function_exists('testFilesAutoloadOrderByDependencyRoot'));
} }
public function testOverrideVendorsAutoloading() public function testOverrideVendorsAutoloading()
{ {
$package = new Package('a', '1.0', '1.0'); $package = new Package('z', '1.0', '1.0');
$package->setAutoload(array('psr-0' => array('A\\B' => $this->workingDir.'/lib'))); $package->setAutoload(array('psr-0' => array('A\\B' => $this->workingDir.'/lib'), 'classmap' => array($this->workingDir.'/src')));
$package->setRequires(array(new Link('z', 'a/a')));
$packages = array(); $packages = array();
$packages[] = $a = new Package('a/a', '1.0', '1.0'); $packages[] = $a = new Package('a/a', '1.0', '1.0');
$packages[] = $b = new Package('b/b', '1.0', '1.0'); $packages[] = $b = new Package('b/b', '1.0', '1.0');
$a->setAutoload(array('psr-0' => array('A' => 'src/', 'A\\B' => 'lib/'))); $a->setAutoload(array('psr-0' => array('A' => 'src/', 'A\\B' => 'lib/'), 'classmap' => array('classmap')));
$b->setAutoload(array('psr-0' => array('B\\Sub\\Name' => 'src/'))); $b->setAutoload(array('psr-0' => array('B\\Sub\\Name' => 'src/')));
$this->repository->expects($this->once()) $this->repository->expects($this->once())
@ -380,12 +394,16 @@ class AutoloadGeneratorTest extends TestCase
->will($this->returnValue($packages)); ->will($this->returnValue($packages));
$this->fs->ensureDirectoryExists($this->workingDir.'/lib/A/B'); $this->fs->ensureDirectoryExists($this->workingDir.'/lib/A/B');
$this->fs->ensureDirectoryExists($this->workingDir.'/src/');
$this->fs->ensureDirectoryExists($this->vendorDir.'/composer'); $this->fs->ensureDirectoryExists($this->vendorDir.'/composer');
$this->fs->ensureDirectoryExists($this->vendorDir.'/a/a/classmap');
$this->fs->ensureDirectoryExists($this->vendorDir.'/a/a/src'); $this->fs->ensureDirectoryExists($this->vendorDir.'/a/a/src');
$this->fs->ensureDirectoryExists($this->vendorDir.'/a/a/lib/A/B'); $this->fs->ensureDirectoryExists($this->vendorDir.'/a/a/lib/A/B');
$this->fs->ensureDirectoryExists($this->vendorDir.'/b/b/src'); $this->fs->ensureDirectoryExists($this->vendorDir.'/b/b/src');
file_put_contents($this->workingDir.'/lib/A/B/C.php', '<?php namespace A\\B; class C {}'); file_put_contents($this->workingDir.'/lib/A/B/C.php', '<?php namespace A\\B; class C {}');
file_put_contents($this->workingDir.'/src/classes.php', '<?php namespace Foo; class Bar {}');
file_put_contents($this->vendorDir.'/a/a/lib/A/B/C.php', '<?php namespace A\\B; class C {}'); file_put_contents($this->vendorDir.'/a/a/lib/A/B/C.php', '<?php namespace A\\B; class C {}');
file_put_contents($this->vendorDir.'/a/a/classmap/classes.php', '<?php namespace Foo; class Bar {}');
$workDir = strtr($this->workingDir, '\\', '/'); $workDir = strtr($this->workingDir, '\\', '/');
$expectedNamespace = <<<EOF $expectedNamespace = <<<EOF
@ -414,6 +432,7 @@ EOF;
return array( return array(
'A\\\\B\\\\C' => \$baseDir . '/lib/A/B/C.php', 'A\\\\B\\\\C' => \$baseDir . '/lib/A/B/C.php',
'Foo\\\\Bar' => \$baseDir . '/src/classes.php',
); );
EOF; EOF;

View File

@ -6,6 +6,6 @@ $vendorDir = dirname(__DIR__);
$baseDir = $vendorDir; $baseDir = $vendorDir;
return array( return array(
'Main\\Foo' => $baseDir . '/src/Main/Foo.php',
'ClassMapFoo' => $baseDir . '/composersrc/foo.php', 'ClassMapFoo' => $baseDir . '/composersrc/foo.php',
'Main\\Foo' => $baseDir . '/src/Main/Foo.php',
); );

View File

@ -6,7 +6,7 @@ $vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir); $baseDir = dirname($vendorDir);
return array( return array(
'ClassMapBar' => $baseDir . '/composer-test-autoload/b/b/src/b.php',
'ClassMapBaz' => $baseDir . '/composer-test-autoload/b/b/lib/c.php', 'ClassMapBaz' => $baseDir . '/composer-test-autoload/b/b/lib/c.php',
'ClassMapFoo' => $baseDir . '/composer-test-autoload/a/a/src/a.php', 'ClassMapFoo' => $baseDir . '/composer-test-autoload/a/a/src/a.php',
'ClassMapBar' => $baseDir . '/composer-test-autoload/b/b/src/b.php',
); );

View File

@ -6,7 +6,7 @@ $vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir); $baseDir = dirname($vendorDir);
return array( return array(
'ClassMapFoo' => $baseDir . '/composer-test-autoload/a/a/src/a.php',
'ClassMapBar' => $baseDir . '/composer-test-autoload/b/b/test.php', 'ClassMapBar' => $baseDir . '/composer-test-autoload/b/b/test.php',
'ClassMapBaz' => $baseDir . '/composer-test-autoload/c/c/foo/test.php', 'ClassMapBaz' => $baseDir . '/composer-test-autoload/c/c/foo/test.php',
'ClassMapFoo' => $baseDir . '/composer-test-autoload/a/a/src/a.php',
); );

View File

@ -31,9 +31,11 @@ class ComposerAutoloaderInitFilesAutoloadOrder
$loader->register(); $loader->register();
require $vendorDir . '/c/lorem/testC.php'; require $vendorDir . '/c/lorem/testC.php';
require $vendorDir . '/a/foo/testA.php'; require $vendorDir . '/z/foo/testA.php';
require $baseDir . '/root.php'; require $baseDir . '/root.php';
require $vendorDir . '/b/bar/testB.php'; require $vendorDir . '/b/bar/testB.php';
require $vendorDir . '/d/d/testD.php';
require $vendorDir . '/e/e/testE.php';
return $loader; return $loader;
} }