Merge pull request #3610 from bd808/feature/classmap-authoritative
Add classmap-authoritative config settingpull/3688/head
commit
0543a32d39
|
@ -790,6 +790,9 @@ The following options are supported:
|
|||
the generated Composer autoloader. When null a random one will be generated.
|
||||
* **optimize-autoloader** Defaults to `false`. Always optimize when dumping
|
||||
the autoloader.
|
||||
* **classmap-authoritative:** Defaults to `false`. If true, the composer
|
||||
autoloader will not scan the filesystem for classes that are not found in
|
||||
the class map. Implies 'optimize-autoloader'.
|
||||
* **github-domains:** Defaults to `["github.com"]`. A list of domains to use in
|
||||
github mode. This is used for GitHub Enterprise setups.
|
||||
* **github-expose-hostname:** Defaults to `true`. If set to false, the OAuth
|
||||
|
|
|
@ -197,6 +197,10 @@
|
|||
"type": "boolean",
|
||||
"description": "If false, the composer autoloader will not be prepended to existing autoloaders, defaults to true."
|
||||
},
|
||||
"classmap-authoritative": {
|
||||
"type": "boolean",
|
||||
"description": "If true, the composer autoloader will not scan the filesystem for classes that are not found in the class map, defaults to false."
|
||||
},
|
||||
"github-domains": {
|
||||
"type": "array",
|
||||
"description": "A list of domains to use in github mode. This is used for GitHub Enterprise setups, defaults to [\"github.com\"].",
|
||||
|
|
|
@ -63,6 +63,7 @@ class AutoloadGenerator
|
|||
$vendorPath = $filesystem->normalizePath(realpath($config->get('vendor-dir')));
|
||||
$useGlobalIncludePath = (bool) $config->get('use-include-path');
|
||||
$prependAutoloader = $config->get('prepend-autoloader') === false ? 'false' : 'true';
|
||||
$classMapAuthoritative = $config->get('classmap-authoritative');
|
||||
$targetDir = $vendorPath.'/'.$targetDir;
|
||||
$filesystem->ensureDirectoryExists($targetDir);
|
||||
|
||||
|
@ -226,7 +227,7 @@ EOF;
|
|||
file_put_contents($targetDir.'/autoload_files.php', $includeFilesFile);
|
||||
}
|
||||
file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix));
|
||||
file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFile, $targetDirLoader, (bool) $includeFilesFile, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader));
|
||||
file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFile, $targetDirLoader, (bool) $includeFilesFile, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $classMapAuthoritative));
|
||||
|
||||
// use stream_copy_to_stream instead of copy
|
||||
// to work around https://bugs.php.net/bug.php?id=64634
|
||||
|
@ -443,7 +444,7 @@ return ComposerAutoloaderInit$suffix::getLoader();
|
|||
AUTOLOAD;
|
||||
}
|
||||
|
||||
protected function getAutoloadRealFile($useClassMap, $useIncludePath, $targetDirLoader, $useIncludeFiles, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader)
|
||||
protected function getAutoloadRealFile($useClassMap, $useIncludePath, $targetDirLoader, $useIncludeFiles, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $classMapAuthoritative)
|
||||
{
|
||||
// TODO the class ComposerAutoloaderInit should be revert to a closure
|
||||
// when APC has been fixed:
|
||||
|
@ -520,6 +521,13 @@ PSR4;
|
|||
CLASSMAP;
|
||||
}
|
||||
|
||||
if ($classMapAuthoritative) {
|
||||
$file .= <<<'CLASSMAPAUTHORITATIVE'
|
||||
$loader->setClassMapAuthoritative(true);
|
||||
|
||||
CLASSMAPAUTHORITATIVE;
|
||||
}
|
||||
|
||||
if ($useGlobalIncludePath) {
|
||||
$file .= <<<'INCLUDEPATH'
|
||||
$loader->setUseIncludePath(true);
|
||||
|
|
|
@ -54,6 +54,8 @@ class ClassLoader
|
|||
private $useIncludePath = false;
|
||||
private $classMap = array();
|
||||
|
||||
private $classMapAuthoritative = false;
|
||||
|
||||
public function getPrefixes()
|
||||
{
|
||||
if (!empty($this->prefixesPsr0)) {
|
||||
|
@ -248,6 +250,27 @@ class ClassLoader
|
|||
return $this->useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns off searching the prefix and fallback directories for classes
|
||||
* that have not been registered with the class map.
|
||||
*
|
||||
* @param bool $classMapAuthoritative
|
||||
*/
|
||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||
{
|
||||
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should class lookup fail if not found in the current class map?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isClassMapAuthoritative()
|
||||
{
|
||||
return $this->classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
|
@ -299,6 +322,9 @@ class ClassLoader
|
|||
if (isset($this->classMap[$class])) {
|
||||
return $this->classMap[$class];
|
||||
}
|
||||
if ($this->classMapAuthoritative) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$file = $this->findFileWithExtension($class, '.php');
|
||||
|
||||
|
|
|
@ -325,6 +325,7 @@ EOT
|
|||
),
|
||||
'autoloader-suffix' => array('is_string', function ($val) { return $val === 'null' ? null : $val; }),
|
||||
'optimize-autoloader' => array($booleanValidator, $booleanNormalizer),
|
||||
'classmap-authoritative' => array($booleanValidator, $booleanNormalizer),
|
||||
'prepend-autoloader' => array($booleanValidator, $booleanNormalizer),
|
||||
'github-expose-hostname' => array($booleanValidator, $booleanNormalizer),
|
||||
);
|
||||
|
|
|
@ -52,7 +52,7 @@ EOT
|
|||
$package = $composer->getPackage();
|
||||
$config = $composer->getConfig();
|
||||
|
||||
$optimize = $input->getOption('optimize') || $config->get('optimize-autoloader');
|
||||
$optimize = $input->getOption('optimize') || $config->get('optimize-autoloader') || $config->get('classmap-authoritative');
|
||||
|
||||
if ($optimize) {
|
||||
$output->writeln('<info>Generating optimized autoload files</info>');
|
||||
|
|
|
@ -106,7 +106,7 @@ EOT
|
|||
$preferDist = $input->getOption('prefer-dist');
|
||||
}
|
||||
|
||||
$optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
|
||||
$optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader') || $config->get('classmap-authoritative');
|
||||
|
||||
$install
|
||||
->setDryRun($input->getOption('dry-run'))
|
||||
|
|
|
@ -110,7 +110,7 @@ EOT
|
|||
$preferDist = $input->getOption('prefer-dist');
|
||||
}
|
||||
|
||||
$optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
|
||||
$optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader') || $config->get('classmap-authoritative');
|
||||
|
||||
$install
|
||||
->setDryRun($input->getOption('dry-run'))
|
||||
|
|
|
@ -39,6 +39,7 @@ class Config
|
|||
'discard-changes' => false,
|
||||
'autoloader-suffix' => null,
|
||||
'optimize-autoloader' => false,
|
||||
'classmap-authoritative' => false,
|
||||
'prepend-autoloader' => true,
|
||||
'github-domains' => array('github.com'),
|
||||
'github-expose-hostname' => true,
|
||||
|
|
|
@ -67,6 +67,17 @@ class AutoloadGeneratorTest extends TestCase
|
|||
*/
|
||||
private $eventDispatcher;
|
||||
|
||||
/**
|
||||
* Map of setting name => return value configuration for the stub Config
|
||||
* object.
|
||||
*
|
||||
* Note: must be public for compatibility with PHP 5.3 runtimes where
|
||||
* closures cannot access private members of the classes they are created
|
||||
* in.
|
||||
* @var array
|
||||
*/
|
||||
public $configValueMap;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->fs = new Filesystem;
|
||||
|
@ -79,18 +90,23 @@ class AutoloadGeneratorTest extends TestCase
|
|||
|
||||
$this->config = $this->getMock('Composer\Config');
|
||||
|
||||
$this->config->expects($this->at(0))
|
||||
->method('get')
|
||||
->with($this->equalTo('vendor-dir'))
|
||||
->will($this->returnCallback(function () use ($that) {
|
||||
$this->configValueMap = array(
|
||||
'vendor-dir' => function () use ($that) {
|
||||
return $that->vendorDir;
|
||||
}));
|
||||
},
|
||||
);
|
||||
|
||||
$this->config->expects($this->at(1))
|
||||
$this->config->expects($this->atLeastOnce())
|
||||
->method('get')
|
||||
->with($this->equalTo('vendor-dir'))
|
||||
->will($this->returnCallback(function () use ($that) {
|
||||
return $that->vendorDir;
|
||||
->will($this->returnCallback(function ($arg) use ($that) {
|
||||
$ret = null;
|
||||
if (isset($that->configValueMap[$arg])) {
|
||||
$ret = $that->configValueMap[$arg];
|
||||
if (is_callable($ret)) {
|
||||
$ret = $ret();
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}));
|
||||
|
||||
$this->origDir = getcwd();
|
||||
|
@ -483,6 +499,48 @@ class AutoloadGeneratorTest extends TestCase
|
|||
include $this->vendorDir.'/composer/autoload_classmap.php'
|
||||
);
|
||||
$this->assertAutoloadFiles('classmap5', $this->vendorDir.'/composer', 'classmap');
|
||||
$this->assertNotContains('$loader->setClassMapAuthoritative(true);', file_get_contents($this->vendorDir.'/composer/autoload_real.php'));
|
||||
}
|
||||
|
||||
public function testClassMapAutoloadingAuthoritative()
|
||||
{
|
||||
$package = new Package('a', '1.0', '1.0');
|
||||
|
||||
$packages = array();
|
||||
$packages[] = $a = new Package('a/a', '1.0', '1.0');
|
||||
$packages[] = $b = new Package('b/b', '1.0', '1.0');
|
||||
$packages[] = $c = new Package('c/c', '1.0', '1.0');
|
||||
$a->setAutoload(array('classmap' => array('')));
|
||||
$b->setAutoload(array('classmap' => array('test.php')));
|
||||
$c->setAutoload(array('classmap' => array('./')));
|
||||
|
||||
$this->repository->expects($this->once())
|
||||
->method('getCanonicalPackages')
|
||||
->will($this->returnValue($packages));
|
||||
|
||||
$this->configValueMap['classmap-authoritative'] = true;
|
||||
|
||||
$this->fs->ensureDirectoryExists($this->vendorDir.'/composer');
|
||||
$this->fs->ensureDirectoryExists($this->vendorDir.'/a/a/src');
|
||||
$this->fs->ensureDirectoryExists($this->vendorDir.'/b/b');
|
||||
$this->fs->ensureDirectoryExists($this->vendorDir.'/c/c/foo');
|
||||
file_put_contents($this->vendorDir.'/a/a/src/a.php', '<?php class ClassMapFoo {}');
|
||||
file_put_contents($this->vendorDir.'/b/b/test.php', '<?php class ClassMapBar {}');
|
||||
file_put_contents($this->vendorDir.'/c/c/foo/test.php', '<?php class ClassMapBaz {}');
|
||||
|
||||
$this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', false, '_7');
|
||||
$this->assertTrue(file_exists($this->vendorDir.'/composer/autoload_classmap.php'), "ClassMap file needs to be generated.");
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'ClassMapBar' => $this->vendorDir.'/b/b/test.php',
|
||||
'ClassMapBaz' => $this->vendorDir.'/c/c/foo/test.php',
|
||||
'ClassMapFoo' => $this->vendorDir.'/a/a/src/a.php',
|
||||
),
|
||||
include $this->vendorDir.'/composer/autoload_classmap.php'
|
||||
);
|
||||
$this->assertAutoloadFiles('classmap5', $this->vendorDir.'/composer', 'classmap');
|
||||
|
||||
$this->assertContains('$loader->setClassMapAuthoritative(true);', file_get_contents($this->vendorDir.'/composer/autoload_real.php'));
|
||||
}
|
||||
|
||||
public function testFilesAutoloadGeneration()
|
||||
|
@ -829,10 +887,7 @@ EOF;
|
|||
->method('getCanonicalPackages')
|
||||
->will($this->returnValue(array()));
|
||||
|
||||
$this->config->expects($this->at(2))
|
||||
->method('get')
|
||||
->with($this->equalTo('use-include-path'))
|
||||
->will($this->returnValue(true));
|
||||
$this->configValueMap['use-include-path'] = true;
|
||||
|
||||
$this->fs->ensureDirectoryExists($this->vendorDir.'/a');
|
||||
|
||||
|
|
Loading…
Reference in New Issue