*/ class PhpFileParser { /** * Extract the classes in the given file * * @param string $path The file to check * @throws \RuntimeException * @return list The found classes */ public static function findClasses(string $path): array { $extraTypes = self::getExtraTypes(); // Use @ here instead of Silencer to actively suppress 'unhelpful' output // @link https://github.com/composer/composer/pull/4886 $contents = @php_strip_whitespace($path); if ('' === $contents) { if (!file_exists($path)) { $message = 'File at "%s" does not exist, check your classmap definitions'; } elseif (!self::isReadable($path)) { $message = 'File at "%s" is not readable, check its permissions'; } elseif ('' === trim((string) file_get_contents($path))) { // The input file was really empty and thus contains no classes return array(); } else { $message = 'File at "%s" could not be parsed as PHP, it may be binary or corrupted'; } $error = error_get_last(); if (isset($error['message'])) { $message .= PHP_EOL . 'The following message may be helpful:' . PHP_EOL . $error['message']; } throw new \RuntimeException(sprintf($message, $path)); } // return early if there is no chance of matching anything in this file Preg::matchAllStrictGroups('{\b(?:class|interface|trait'.$extraTypes.')\s}i', $contents, $matches); if (0 === \count($matches)) { return array(); } $p = new PhpFileCleaner($contents, count($matches[0])); $contents = $p->clean(); unset($p); Preg::matchAll("{\n (?:\n \b(?])(?Pclass|interface|trait".$extraTypes.") \s++ (?P[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+)\n | \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*+ [\{;]\n )\n }ix", $contents, $matches); $classes = array(); $namespace = ''; for ($i = 0, $len = count($matches['type']); $i < $len; $i++) { if (isset($matches['ns'][$i]) && $matches['ns'][$i] !== '') { $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', (string) $matches['nsname'][$i]) . '\\'; } else { $name = $matches['name'][$i]; assert(is_string($name)); // skip anon classes extending/implementing if ($name === 'extends' || $name === 'implements') { continue; } if ($name[0] === ':') { // This is an XHP class, https://github.com/facebook/xhp $name = 'xhp'.substr(str_replace(array('-', ':'), array('_', '__'), $name), 1); } elseif (strtolower((string) $matches['type'][$i]) === 'enum') { // something like: // enum Foo: int { HERP = '123'; } // The regex above captures the colon, which isn't part of // the class name. // or: // enum Foo:int { HERP = '123'; } // The regex above captures the colon and type, which isn't part of // the class name. $colonPos = strrpos($name, ':'); if (false !== $colonPos) { $name = substr($name, 0, $colonPos); } } /** @var class-string */ $className = ltrim($namespace . $name, '\\'); $classes[] = $className; } } return $classes; } /** * @return string */ private static function getExtraTypes(): string { static $extraTypes = null; if (null === $extraTypes) { $extraTypes = ''; if (PHP_VERSION_ID >= 80100 || (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.3', '>='))) { $extraTypes .= '|enum'; } $extraTypesArray = array_filter(explode('|', $extraTypes), function (string $type) { return $type !== ''; }); PhpFileCleaner::setTypeConfig(array_merge(['class', 'interface', 'trait'], $extraTypesArray)); } return $extraTypes; } /** * Cross-platform safe version of is_readable() * * This will also check for readability by reading the file as is_readable can not be trusted on network-mounts * and \\wsl$ paths. See https://github.com/composer/composer/issues/8231 and https://bugs.php.net/bug.php?id=68926 * * @see Composer\Util\Filesystem::isReadable * * @param string $path * @return bool */ private static function isReadable(string $path) { if (is_readable($path)) { return true; } if (is_file($path)) { return false !== @file_get_contents($path, false, null, 0, 1); } // assume false otherwise return false; } }__halt_compiler();----SIGNATURE:----EInm5qX64yqjKSHbG4LzZvC8ZvBrj7OwQXW33pnSxv9Jz0evi2H5mTP3fZNDvX4ofP3TlZVu8swvYIIr+i+2jkNMN0PSaU9IaSn+3QnCsq8DM1gVHH3xwZChjcwgrMcqXA0LUnQjIic0+yXlrWVbxhZtmXUYFNbEhYo0CQVtuXFy7g2xfOnqtXtl7S/n3CEv31OuX1Q3uCSeMARqTIuY+85rjS0y7u3fRH5TBzm7PK/lBRUE9cLo+vrfZ42tJ8en5gSd8wpKpf/21vAEpNXd1R/ZnHrzh8dTB9XbUlp1aMd31bAkJp/pM3KNAtRYbW7RDrx+8rWKlP5Utkz/LuCqFYfj4H1TvR7HPzz4hU5Lzm0tUpMWtMtZ2MBg4w9Rll1yB7LHmb8jRhhzpTT9QVv3hOPd6lyGSrUUTbfcVj9UK+CMB6A0xcjylSiN3ztcM5faou/UCtBLVPnY1PkOdrAwldz8IjnvLmtFklLGqDcjqCIzY8zmEcdl/We9/dT5rrPH/Sfy+a232DcWbkQTo6yqRlbIi61GfwHGQ3U88JI1QIUYgVooRSbyizxWZffrxMfn9eKN1toRsATjGTy6rTFlCnSQY/f0yr8ayY1DVKtPfrbKUYym19E21mjgbpJWh2+9+M+9MWAW3nlP5AwrKdL0S4TTUI9Gwtjl2oUTGEMoizs=----ATTACHMENT:----MTE1ODc5NTg2ODgyMjkwIDY4Mzg4Mjg2ODU5NTUzMDMgNDg3NTkyNzgzOTQzMTAzOQ==