* added exclude-from-classmap feature
* updated to latest master versionpull/1607/head
parent
7adc41d02c
commit
b0ec8ee096
|
@ -223,6 +223,10 @@
|
||||||
"files": {
|
"files": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"description": "This is an array of files that are always required on every request."
|
"description": "This is an array of files that are always required on every request."
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "This is an array of patterns to exclude from autoload classmap generation. (e.g. \"exclude-from-classmap\": [\"/test/\", \"/tests/\", \"/Tests/\"]"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -27,6 +27,8 @@ use Composer\Script\ScriptEvents;
|
||||||
*/
|
*/
|
||||||
class AutoloadGenerator
|
class AutoloadGenerator
|
||||||
{
|
{
|
||||||
|
const EXCLUDE_PATTERN = '.*%s';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var EventDispatcher
|
* @var EventDispatcher
|
||||||
*/
|
*/
|
||||||
|
@ -154,6 +156,11 @@ EOF;
|
||||||
EOF;
|
EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$blacklist = '';
|
||||||
|
if(!empty($autoloads['exclude-from-classmap'])) {
|
||||||
|
$blacklist = '{(' . implode('|', $autoloads['exclude-from-classmap']) . ')}';
|
||||||
|
}
|
||||||
|
|
||||||
// flatten array
|
// flatten array
|
||||||
$classMap = array();
|
$classMap = array();
|
||||||
if ($scanPsr0Packages) {
|
if ($scanPsr0Packages) {
|
||||||
|
@ -165,12 +172,7 @@ EOF;
|
||||||
if (!is_dir($dir)) {
|
if (!is_dir($dir)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$whitelist = sprintf(
|
foreach (ClassMapGenerator::createMap($dir, $blacklist) as $class => $path) {
|
||||||
'{%s/%s.+(?<!(?<!/)Test\.php)$}',
|
|
||||||
preg_quote($dir),
|
|
||||||
($psrType === 'psr-4' || strpos($namespace, '_') === false) ? preg_quote(strtr($namespace, '\\', '/')) : ''
|
|
||||||
);
|
|
||||||
foreach (ClassMapGenerator::createMap($dir, $whitelist) as $class => $path) {
|
|
||||||
if ('' === $namespace || 0 === strpos($class, $namespace)) {
|
if ('' === $namespace || 0 === strpos($class, $namespace)) {
|
||||||
if (!isset($classMap[$class])) {
|
if (!isset($classMap[$class])) {
|
||||||
$path = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
|
$path = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
|
||||||
|
@ -185,7 +187,7 @@ EOF;
|
||||||
|
|
||||||
$autoloads['classmap'] = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($autoloads['classmap']));
|
$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, $blacklist) as $class => $path) {
|
||||||
$path = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
|
$path = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
|
||||||
$classMap[$class] = $path.",\n";
|
$classMap[$class] = $path.",\n";
|
||||||
}
|
}
|
||||||
|
@ -285,11 +287,19 @@ EOF;
|
||||||
$psr4 = $this->parseAutoloadsType($packageMap, 'psr-4', $mainPackage);
|
$psr4 = $this->parseAutoloadsType($packageMap, 'psr-4', $mainPackage);
|
||||||
$classmap = $this->parseAutoloadsType($sortedPackageMap, 'classmap', $mainPackage);
|
$classmap = $this->parseAutoloadsType($sortedPackageMap, 'classmap', $mainPackage);
|
||||||
$files = $this->parseAutoloadsType($sortedPackageMap, 'files', $mainPackage);
|
$files = $this->parseAutoloadsType($sortedPackageMap, 'files', $mainPackage);
|
||||||
|
$exclude = $this->parseAutoloadsType($sortedPackageMap, 'exclude-from-classmap', $mainPackage);
|
||||||
|
|
||||||
krsort($psr0);
|
krsort($psr0);
|
||||||
krsort($psr4);
|
krsort($psr4);
|
||||||
|
|
||||||
return array('psr-0' => $psr0, 'psr-4' => $psr4, 'classmap' => $classmap, 'files' => $files);
|
return
|
||||||
|
array(
|
||||||
|
'psr-0' => $psr0,
|
||||||
|
'psr-4' => $psr4,
|
||||||
|
'classmap' => $classmap,
|
||||||
|
'files' => $files,
|
||||||
|
'exclude-from-classmap' => $exclude
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -597,6 +607,23 @@ FOOTER;
|
||||||
$path = $package->getTargetDir() . '/' . $path;
|
$path = $package->getTargetDir() . '/' . $path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($type === 'exclude-from-classmap') {
|
||||||
|
// first escape user input
|
||||||
|
$path = sprintf(self::EXCLUDE_PATTERN, preg_quote($path));
|
||||||
|
|
||||||
|
if ($package === $mainPackage && $package->getTargetDir() && !is_readable($installPath.'/'.$path)) {
|
||||||
|
// remove target-dir from classmap entries of the root package
|
||||||
|
$targetDir = str_replace('\\<dirsep\\>', '[\\\\/]', preg_quote(str_replace(array('/', '\\'), '<dirsep>', $package->getTargetDir())));
|
||||||
|
$path = ltrim(preg_replace('{^'.$targetDir.'}', '', ltrim($path, '\\/')), '\\/');
|
||||||
|
}
|
||||||
|
elseif($package !== $mainPackage && $package->getTargetDir() && !is_readable($installPath.'/'.$path)) {
|
||||||
|
// add target-dir to exclude entries that don't have it
|
||||||
|
$path = preg_quote($package->getTargetDir()) . '/' . $path;
|
||||||
|
}
|
||||||
|
$autoloads[] = empty($installPath) ? $path : preg_quote($installPath) . '/' . $path;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (empty($installPath)) {
|
if (empty($installPath)) {
|
||||||
$autoloads[$namespace][] = empty($path) ? '.' : $path;
|
$autoloads[$namespace][] = empty($path) ? '.' : $path;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -42,13 +42,13 @@ class ClassMapGenerator
|
||||||
* Iterate over all files in the given directory searching for classes
|
* Iterate over all files in the given directory searching for classes
|
||||||
*
|
*
|
||||||
* @param Iterator|string $path The path to search in or an iterator
|
* @param Iterator|string $path The path to search in or an iterator
|
||||||
* @param string $whitelist Regex that matches against the file path
|
* @param string $blacklist Regex that matches against the file path that exclude from the classmap.
|
||||||
*
|
*
|
||||||
* @return array A class map array
|
* @return array A class map array
|
||||||
*
|
*
|
||||||
* @throws \RuntimeException When the path is neither an existing file nor directory
|
* @throws \RuntimeException When the path is neither an existing file nor directory
|
||||||
*/
|
*/
|
||||||
public static function createMap($path, $whitelist = null)
|
public static function createMap($path, $blacklist = '')
|
||||||
{
|
{
|
||||||
if (is_string($path)) {
|
if (is_string($path)) {
|
||||||
if (is_file($path)) {
|
if (is_file($path)) {
|
||||||
|
@ -72,7 +72,7 @@ class ClassMapGenerator
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($whitelist && !preg_match($whitelist, strtr($filePath, '\\', '/'))) {
|
if ($blacklist && preg_match($blacklist, strtr($filePath, '\\', '/'))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1016,6 +1016,36 @@ EOF;
|
||||||
$this->assertEquals($expectedPsr4, file_get_contents($this->vendorDir.'/composer/autoload_psr4.php'));
|
$this->assertEquals($expectedPsr4, file_get_contents($this->vendorDir.'/composer/autoload_psr4.php'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testExcludeFromClassmap()
|
||||||
|
{
|
||||||
|
$package = new Package('a', '1.0', '1.0');
|
||||||
|
$package->setAutoload(array(
|
||||||
|
'psr-0' => array(
|
||||||
|
'Main' => 'src/',
|
||||||
|
),
|
||||||
|
'classmap' => array('composersrc/'),
|
||||||
|
'exclude-from-classmap' => array('/tests/'),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->repository->expects($this->once())
|
||||||
|
->method('getCanonicalPackages')
|
||||||
|
->will($this->returnValue(array()));
|
||||||
|
|
||||||
|
$this->fs->ensureDirectoryExists($this->workingDir.'/composer');
|
||||||
|
$this->fs->ensureDirectoryExists($this->workingDir.'/src');
|
||||||
|
|
||||||
|
$this->fs->ensureDirectoryExists($this->workingDir.'/composersrc');
|
||||||
|
file_put_contents($this->workingDir.'/composersrc/foo.php', '<?php class ClassMapFoo {}');
|
||||||
|
|
||||||
|
$this->fs->ensureDirectoryExists($this->workingDir.'/composersrc/tests');
|
||||||
|
file_put_contents($this->workingDir.'/composersrc/tests/bar.php', '<?php class ClassExcludeMapFoo {}');
|
||||||
|
|
||||||
|
$this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', false, '_1');
|
||||||
|
|
||||||
|
// Assert that autoload_classmap.php was correctly generated.
|
||||||
|
$this->assertAutoloadFiles('classmap', $this->vendorDir.'/composer', 'classmap');
|
||||||
|
}
|
||||||
|
|
||||||
private function assertAutoloadFiles($name, $dir, $type = 'namespaces')
|
private function assertAutoloadFiles($name, $dir, $type = 'namespaces')
|
||||||
{
|
{
|
||||||
$a = __DIR__.'/Fixtures/autoload_'.$name.'.php';
|
$a = __DIR__.'/Fixtures/autoload_'.$name.'.php';
|
||||||
|
|
Loading…
Reference in New Issue