| 1 | <?php
|
| 2 | |
| 3 | * The content of this file is copied from composer's src/Composer/Autoload/ClassMapGenerator.php
|
| 4 | * the findClasses method was extracted, to prevent using any dependency.
|
| 5 | *
|
| 6 | * Composer (and thus this file) is distributed under the expat license, and
|
| 7 | * ClassMapGenerator.php also contains this notice:
|
| 8 | *
|
| 9 | * This file is part of Composer.
|
| 10 | *
|
| 11 | * (c) Nils Adermann <[email protected]>
|
| 12 | * Jordi Boggiano <[email protected]>
|
| 13 | *
|
| 14 | * For the full copyright and license information, please view the LICENSE
|
| 15 | * file that was distributed with this source code.
|
| 16 | *
|
| 17 | * This file is copied from the Symfony package.
|
| 18 | *
|
| 19 | * (c) Fabien Potencier <[email protected]>
|
| 20 | *
|
| 21 | * To the extent to wich it makes sense, as the author of the extract:
|
| 22 | * Copyright © 2020 Julien Lepiller <[email protected]>
|
| 23 |
|
| 24 |
|
| 25 | |
| 26 | * Extract the classes in the given file
|
| 27 | *
|
| 28 | * @param string $path The file to check
|
| 29 | * @throws \RuntimeException
|
| 30 | * @return array The found classes
|
| 31 |
|
| 32 | function findClasses($path)
|
| 33 | {
|
| 34 | $extraTypes = PHP_VERSION_ID < 50400 ? '' : '|trait';
|
| 35 | if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.3', '>=')) {
|
| 36 | $extraTypes .= '|enum';
|
| 37 | }
|
| 38 | |
| 39 | |
| 40 | $contents = @php_strip_whitespace($path);
|
| 41 | if (!$contents) {
|
| 42 | if (!file_exists($path)) {
|
| 43 | $message = 'File at "%s" does not exist, check your classmap definitions';
|
| 44 | } elseif (!is_readable($path)) {
|
| 45 | $message = 'File at "%s" is not readable, check its permissions';
|
| 46 | } elseif ('' === trim(file_get_contents($path))) {
|
| 47 | |
| 48 | return array();
|
| 49 | } else {
|
| 50 | $message = 'File at "%s" could not be parsed as PHP, it may be binary or corrupted';
|
| 51 | }
|
| 52 | $error = error_get_last();
|
| 53 | if (isset($error['message'])) {
|
| 54 | $message .= PHP_EOL . 'The following message may be helpful:' . PHP_EOL . $error['message'];
|
| 55 | }
|
| 56 | throw new \RuntimeException(sprintf($message, $path));
|
| 57 | }
|
| 58 | |
| 59 | if (!preg_match('{\b(?:class|interface'.$extraTypes.')\s}i', $contents)) {
|
| 60 | return array();
|
| 61 | }
|
| 62 | |
| 63 | $contents = preg_replace('{<<<[ \t]*([\'"]?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)(?:\s*)\\2(?=\s+|[;,.)])}s', 'null', $contents);
|
| 64 | |
| 65 | $contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents);
|
| 66 | |
| 67 | if (substr($contents, 0, 2) !== '<?') {
|
| 68 | $contents = preg_replace('{^.+?<\?}s', '<?', $contents, 1, $replacements);
|
| 69 | if ($replacements === 0) {
|
| 70 | return array();
|
| 71 | }
|
| 72 | }
|
| 73 | |
| 74 | $contents = preg_replace('{\?>(?:[^<]++|<(?!\?))*+<\?}s', '?><?', $contents);
|
| 75 | |
| 76 | $pos = strrpos($contents, '?>');
|
| 77 | if (false !== $pos && false === strpos(substr($contents, $pos), '<?')) {
|
| 78 | $contents = substr($contents, 0, $pos);
|
| 79 | }
|
| 80 | |
| 81 | if (preg_match('{(<\?)(?!(php|hh))}i', $contents)) {
|
| 82 | $contents = preg_replace('{//.* | /\*(?:[^*]++|\*(?!/))*\*/}x', '', $contents);
|
| 83 | }
|
| 84 | preg_match_all('{
|
| 85 | (?:
|
| 86 | \b(?<![\$:>])(?P<type>class|interface'.$extraTypes.') \s++ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+)
|
| 87 | | \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*+ [\{;]
|
| 88 | )
|
| 89 | }ix', $contents, $matches);
|
| 90 | $classes = array();
|
| 91 | $namespace = '';
|
| 92 | for ($i = 0, $len = count($matches['type']); $i < $len; $i++) {
|
| 93 | if (!empty($matches['ns'][$i])) {
|
| 94 | $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\';
|
| 95 | } else {
|
| 96 | $name = $matches['name'][$i];
|
| 97 | |
| 98 | if ($name === 'extends' || $name === 'implements') {
|
| 99 | continue;
|
| 100 | }
|
| 101 | if ($name[0] === ':') {
|
| 102 | |
| 103 | $name = 'xhp'.substr(str_replace(array('-', ':'), array('_', '__'), $name), 1);
|
| 104 | } elseif ($matches['type'][$i] === 'enum') {
|
| 105 | |
| 106 | |
| 107 | |
| 108 | |
| 109 | $name = rtrim($name, ':');
|
| 110 | }
|
| 111 | $classes[] = ltrim($namespace . $name, '\\');
|
| 112 | }
|
| 113 | }
|
| 114 | return $classes;
|
| 115 | }
|
| 116 |
|
| 117 | $options = getopt('i:f:', []);
|
| 118 | $file = $options["f"];
|
| 119 | $input = $options["i"];
|
| 120 |
|
| 121 | $classes = findClasses($file);
|
| 122 | foreach($classes as $class) {
|
| 123 | echo '$classmap[\''.$class.'\'] = \''.$input.'/'.$file.'\';';
|
| 124 | echo "\n";
|
| 125 | }
|