* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * * @license MIT */ namespace Composer\Autoload; /** * ClassMapGenerator * * @author Gyula Sallai */ class ClassMapGenerator { /** * Generate a class map file * * @param Traversable $dirs Directories or a single path to search in * @param string $file The name of the class map file */ public static function dump($dirs, $file) { $maps = array(); foreach ($dirs as $dir) { $maps = array_merge($maps, static::createMap($dir)); } file_put_contents($file, sprintf('isFile()) { continue; } $filePath = $file->getRealPath(); if (!in_array(pathinfo($filePath, PATHINFO_EXTENSION), array('php', 'inc'))) { continue; } if ($whitelist && !preg_match($whitelist, strtr($filePath, '\\', '/'))) { continue; } $classes = self::findClasses($filePath); foreach ($classes as $class) { $map[$class] = $filePath; } } return $map; } /** * Extract the classes in the given file * * @param string $path The file to check * * @return array The found classes */ private static function findClasses($path) { $traits = version_compare(PHP_VERSION, '5.4', '<') ? '' : '|trait'; try { $contents = php_strip_whitespace($path); } catch (\Exception $e) { throw new \RuntimeException('Could not scan for classes inside '.$path.": \n".$e->getMessage(), 0, $e); } // return early if there is no chance of matching anything in this file if (!preg_match('{\b(?:class|interface'.$traits.')\b}i', $contents)) { return array(); } // strip heredocs/nowdocs $contents = preg_replace('{<<<\'?(\w+)\'?(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)\\1(?=\r\n|\n|\r|;)}s', 'null', $contents); // strip strings $contents = preg_replace('{"[^"\\\\]*(\\\\.[^"\\\\]*)*"|\'[^\'\\\\]*(\\\\.[^\'\\\\]*)*\'}', 'null', $contents); // strip leading non-php code if needed if (substr($contents, 0, 2) !== '.+<\?}s', '?>'); if (false !== $pos && false === strpos(substr($contents, $pos), '])(?Pclass|interface'.$traits.') \s+ (?P[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*) | \b(?])(?Pnamespace) (?P\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*[\{;] ) }ix', $contents, $matches); $classes = array(); $namespace = ''; for ($i = 0, $len = count($matches['type']); $i < $len; $i++) { if (!empty($matches['ns'][$i])) { $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\'; } else { $classes[] = ltrim($namespace . $matches['name'][$i], '\\'); } } return $classes; } }