14 namespace Composer\Autoload;
17 use Composer\IO\IOInterface;
30 public static function dump($dirs, $file)
34 foreach ($dirs as $dir) {
35 $maps = array_merge($maps, static::createMap($dir));
38 file_put_contents($file, sprintf(
'<?php return %s;', var_export($maps,
true)));
53 public static function createMap($path, $whitelist = null, IOInterface $io = null, $namespace = null)
55 if (is_string($path)) {
57 $path = array(
new \SplFileInfo($path));
59 $path =
Finder::create()->files()->followLinks()->name(
'/\.(php|inc|hh)$/')->in($path);
61 throw new \RuntimeException(
62 'Could not scan for classes inside "' . $path .
63 '" which does not appear to be a file nor a folder'
70 foreach ($path as $file) {
71 $filePath = $file->getRealPath();
73 if (!in_array(pathinfo($filePath, PATHINFO_EXTENSION), array(
'php',
'inc',
'hh'))) {
77 if ($whitelist && !preg_match($whitelist, strtr($filePath,
'\\',
'/'))) {
81 $classes = self::findClasses($filePath);
83 foreach ($classes as $class) {
85 if (null !== $namespace && 0 !== strpos($class, $namespace)) {
89 if (!isset($map[$class])) {
90 $map[$class] = $filePath;
91 }
elseif ($io && $map[$class] !== $filePath && !preg_match(
'{/(test|fixture|example)s?/}i', strtr($map[$class] .
' ' . $filePath,
'\\',
'/'))) {
93 '<warning>Warning: Ambiguous class resolution, "' . $class .
'"' .
94 ' was found in both "' . $map[$class] .
'" and "' . $filePath .
'", the first will be used.</warning>'
112 $extraTypes = PHP_VERSION_ID < 50400 ?
'' :
'|trait';
113 if (defined(
'HHVM_VERSION') && version_compare(HHVM_VERSION,
'3.3',
'>=')) {
114 $extraTypes .=
'|enum';
118 $contents = @php_strip_whitespace($path);
120 if (!file_exists($path)) {
121 throw new \Exception(
'File does not exist');
123 if (!is_readable($path)) {
124 throw new \Exception(
'File is not readable');
127 }
catch (\Exception $e) {
128 throw new \RuntimeException(
'Could not scan for classes inside ' . $path .
": \n" . $e->getMessage(), 0, $e);
132 if (!preg_match(
'{\b(?:class|interface' . $extraTypes .
')\s}i', $contents)) {
137 $contents = preg_replace(
'{<<<\s*(\'?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)\\2(?=\r\n|\n|\r|;)}s',
'null', $contents);
139 $contents = preg_replace(
'{"[^"\\\\]*(\\\\.[^"\\\\]*)*"|\'[^\'\\\\]*(\\\\.[^\'\\\\]*)*\'}s',
'null', $contents);
141 if (substr($contents, 0, 2) !==
'<?') {
142 $contents = preg_replace(
'{^.+?<\?}s',
'<?', $contents, 1, $replacements);
143 if ($replacements === 0) {
148 $contents = preg_replace(
'{\?>.+<\?}s',
'?><?', $contents);
150 $pos = strrpos($contents,
'?>');
151 if (
false !== $pos &&
false === strpos(substr($contents, $pos),
'<?')) {
152 $contents = substr($contents, 0, $pos);
157 \b(?<![\$:>])(?P<type>class|interface' . $extraTypes .
') \s+ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*)
158 | \b(?<![\$:>])(?P<ns>namespace) (?P<nsname>\s+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\s*\\\\\s*[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*)? \s*[\{;]
160 }ix', $contents, $matches);
165 for ($i = 0, $len = count($matches[
'type']); $i < $len; $i++) {
166 if (!empty($matches[
'ns'][$i])) {
167 $namespace = str_replace(array(
' ',
"\t",
"\r",
"\n"),
'', $matches[
'nsname'][$i]) .
'\\';
169 $name = $matches[
'name'][$i];
170 if ($name[0] ===
':') {
172 $name =
'xhp' . substr(str_replace(array(
'-',
':'), array(
'_',
'__'), $name), 1);
173 }
elseif ($matches[
'type'][$i] ===
'enum') {
178 $name = rtrim($name,
':');
180 $classes[] = ltrim($namespace . $name,
'\\');