annotate vendor/squizlabs/php_codesniffer/autoload.php @ 4:a9cd425dd02b

Update, including to Drupal core 8.6.10
author Chris Cannam
date Thu, 28 Feb 2019 13:11:55 +0000
parents
children 12f9dff5fda9
rev   line source
Chris@4 1 <?php
Chris@4 2 /**
Chris@4 3 * Autoloads files for PHP_CodeSniffer and tracks what has been loaded.
Chris@4 4 *
Chris@4 5 * Due to different namespaces being used for custom coding standards,
Chris@4 6 * the autoloader keeps track of what class is loaded after a file is included,
Chris@4 7 * even if the file is ultimately included by another autoloader (such as composer).
Chris@4 8 *
Chris@4 9 * This allows PHP_CodeSniffer to request the class name after loading a class
Chris@4 10 * when it only knows the filename, without having to parse the file to find it.
Chris@4 11 *
Chris@4 12 * @author Greg Sherwood <gsherwood@squiz.net>
Chris@4 13 * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
Chris@4 14 * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
Chris@4 15 */
Chris@4 16
Chris@4 17 namespace PHP_CodeSniffer;
Chris@4 18
Chris@4 19 if (class_exists('PHP_CodeSniffer\Autoload', false) === false) {
Chris@4 20 class Autoload
Chris@4 21 {
Chris@4 22
Chris@4 23 /**
Chris@4 24 * The composer autoloader.
Chris@4 25 *
Chris@4 26 * @var Composer\Autoload\ClassLoader
Chris@4 27 */
Chris@4 28 private static $composerAutoloader = null;
Chris@4 29
Chris@4 30 /**
Chris@4 31 * A mapping of file names to class names.
Chris@4 32 *
Chris@4 33 * @var array<string, string>
Chris@4 34 */
Chris@4 35 private static $loadedClasses = [];
Chris@4 36
Chris@4 37 /**
Chris@4 38 * A mapping of class names to file names.
Chris@4 39 *
Chris@4 40 * @var array<string, string>
Chris@4 41 */
Chris@4 42 private static $loadedFiles = [];
Chris@4 43
Chris@4 44 /**
Chris@4 45 * A list of additional directories to search during autoloading.
Chris@4 46 *
Chris@4 47 * This is typically a list of coding standard directories.
Chris@4 48 *
Chris@4 49 * @var string[]
Chris@4 50 */
Chris@4 51 private static $searchPaths = [];
Chris@4 52
Chris@4 53
Chris@4 54 /**
Chris@4 55 * Loads a class.
Chris@4 56 *
Chris@4 57 * This method only loads classes that exist in the PHP_CodeSniffer namespace.
Chris@4 58 * All other classes are ignored and loaded by subsequent autoloaders.
Chris@4 59 *
Chris@4 60 * @param string $class The name of the class to load.
Chris@4 61 *
Chris@4 62 * @return bool
Chris@4 63 */
Chris@4 64 public static function load($class)
Chris@4 65 {
Chris@4 66 // Include the composer autoloader if there is one, but re-register it
Chris@4 67 // so this autoloader runs before the composer one as we need to include
Chris@4 68 // all files so we can figure out what the class/interface/trait name is.
Chris@4 69 if (self::$composerAutoloader === null) {
Chris@4 70 // Make sure we don't try to load any of Composer's classes
Chris@4 71 // while the autoloader is being setup.
Chris@4 72 if (strpos($class, 'Composer\\') === 0) {
Chris@4 73 return;
Chris@4 74 }
Chris@4 75
Chris@4 76 if (strpos(__DIR__, 'phar://') !== 0
Chris@4 77 && file_exists(__DIR__.'/../../autoload.php') === true
Chris@4 78 ) {
Chris@4 79 self::$composerAutoloader = include __DIR__.'/../../autoload.php';
Chris@4 80 if (self::$composerAutoloader instanceof \Composer\Autoload\ClassLoader) {
Chris@4 81 self::$composerAutoloader->unregister();
Chris@4 82 self::$composerAutoloader->register();
Chris@4 83 } else {
Chris@4 84 // Something went wrong, so keep going without the autoloader
Chris@4 85 // although namespaced sniffs might error.
Chris@4 86 self::$composerAutoloader = false;
Chris@4 87 }
Chris@4 88 } else {
Chris@4 89 self::$composerAutoloader = false;
Chris@4 90 }
Chris@4 91 }//end if
Chris@4 92
Chris@4 93 $ds = DIRECTORY_SEPARATOR;
Chris@4 94 $path = false;
Chris@4 95
Chris@4 96 if (substr($class, 0, 16) === 'PHP_CodeSniffer\\') {
Chris@4 97 if (substr($class, 0, 22) === 'PHP_CodeSniffer\Tests\\') {
Chris@4 98 $isInstalled = !is_dir(__DIR__.$ds.'tests');
Chris@4 99 if ($isInstalled === false) {
Chris@4 100 $path = __DIR__.$ds.'tests';
Chris@4 101 } else {
Chris@4 102 $path = '@test_dir@'.$ds.'PHP_CodeSniffer'.$ds.'CodeSniffer';
Chris@4 103 }
Chris@4 104
Chris@4 105 $path .= $ds.substr(str_replace('\\', $ds, $class), 22).'.php';
Chris@4 106 } else {
Chris@4 107 $path = __DIR__.$ds.'src'.$ds.substr(str_replace('\\', $ds, $class), 16).'.php';
Chris@4 108 }
Chris@4 109 }
Chris@4 110
Chris@4 111 // See if the composer autoloader knows where the class is.
Chris@4 112 if ($path === false && self::$composerAutoloader !== false) {
Chris@4 113 $path = self::$composerAutoloader->findFile($class);
Chris@4 114 }
Chris@4 115
Chris@4 116 // See if the class is inside one of our alternate search paths.
Chris@4 117 if ($path === false) {
Chris@4 118 foreach (self::$searchPaths as $searchPath => $nsPrefix) {
Chris@4 119 $className = $class;
Chris@4 120 if ($nsPrefix !== '' && substr($class, 0, strlen($nsPrefix)) === $nsPrefix) {
Chris@4 121 $className = substr($class, (strlen($nsPrefix) + 1));
Chris@4 122 }
Chris@4 123
Chris@4 124 $path = $searchPath.$ds.str_replace('\\', $ds, $className).'.php';
Chris@4 125 if (is_file($path) === true) {
Chris@4 126 break;
Chris@4 127 }
Chris@4 128
Chris@4 129 $path = false;
Chris@4 130 }
Chris@4 131 }
Chris@4 132
Chris@4 133 if ($path !== false && is_file($path) === true) {
Chris@4 134 self::loadFile($path);
Chris@4 135 return true;
Chris@4 136 }
Chris@4 137
Chris@4 138 return false;
Chris@4 139
Chris@4 140 }//end load()
Chris@4 141
Chris@4 142
Chris@4 143 /**
Chris@4 144 * Includes a file and tracks what class or interface was loaded as a result.
Chris@4 145 *
Chris@4 146 * @param string $path The path of the file to load.
Chris@4 147 *
Chris@4 148 * @return string The fully qualified name of the class in the loaded file.
Chris@4 149 */
Chris@4 150 public static function loadFile($path)
Chris@4 151 {
Chris@4 152 if (strpos(__DIR__, 'phar://') !== 0) {
Chris@4 153 $path = realpath($path);
Chris@4 154 if ($path === false) {
Chris@4 155 return false;
Chris@4 156 }
Chris@4 157 }
Chris@4 158
Chris@4 159 if (isset(self::$loadedClasses[$path]) === true) {
Chris@4 160 return self::$loadedClasses[$path];
Chris@4 161 }
Chris@4 162
Chris@4 163 $classes = get_declared_classes();
Chris@4 164 $interfaces = get_declared_interfaces();
Chris@4 165 $traits = get_declared_traits();
Chris@4 166
Chris@4 167 include $path;
Chris@4 168
Chris@4 169 $className = null;
Chris@4 170 $newClasses = array_reverse(array_diff(get_declared_classes(), $classes));
Chris@4 171 foreach ($newClasses as $name) {
Chris@4 172 if (isset(self::$loadedFiles[$name]) === false) {
Chris@4 173 $className = $name;
Chris@4 174 break;
Chris@4 175 }
Chris@4 176 }
Chris@4 177
Chris@4 178 if ($className === null) {
Chris@4 179 $newClasses = array_reverse(array_diff(get_declared_interfaces(), $interfaces));
Chris@4 180 foreach ($newClasses as $name) {
Chris@4 181 if (isset(self::$loadedFiles[$name]) === false) {
Chris@4 182 $className = $name;
Chris@4 183 break;
Chris@4 184 }
Chris@4 185 }
Chris@4 186 }
Chris@4 187
Chris@4 188 if ($className === null) {
Chris@4 189 $newClasses = array_reverse(array_diff(get_declared_traits(), $traits));
Chris@4 190 foreach ($newClasses as $name) {
Chris@4 191 if (isset(self::$loadedFiles[$name]) === false) {
Chris@4 192 $className = $name;
Chris@4 193 break;
Chris@4 194 }
Chris@4 195 }
Chris@4 196 }
Chris@4 197
Chris@4 198 self::$loadedClasses[$path] = $className;
Chris@4 199 self::$loadedFiles[$className] = $path;
Chris@4 200 return self::$loadedClasses[$path];
Chris@4 201
Chris@4 202 }//end loadFile()
Chris@4 203
Chris@4 204
Chris@4 205 /**
Chris@4 206 * Adds a directory to search during autoloading.
Chris@4 207 *
Chris@4 208 * @param string $path The path to the directory to search.
Chris@4 209 * @param string $nsPrefix The namespace prefix used by files under this path.
Chris@4 210 *
Chris@4 211 * @return void
Chris@4 212 */
Chris@4 213 public static function addSearchPath($path, $nsPrefix='')
Chris@4 214 {
Chris@4 215 self::$searchPaths[$path] = rtrim(trim((string) $nsPrefix), '\\');
Chris@4 216
Chris@4 217 }//end addSearchPath()
Chris@4 218
Chris@4 219
Chris@4 220 /**
Chris@4 221 * Retrieve the namespaces and paths registered by external standards.
Chris@4 222 *
Chris@4 223 * @return array
Chris@4 224 */
Chris@4 225 public static function getSearchPaths()
Chris@4 226 {
Chris@4 227 return self::$searchPaths;
Chris@4 228
Chris@4 229 }//end getSearchPaths()
Chris@4 230
Chris@4 231
Chris@4 232 /**
Chris@4 233 * Gets the class name for the given file path.
Chris@4 234 *
Chris@4 235 * @param string $path The name of the file.
Chris@4 236 *
Chris@4 237 * @throws \Exception If the file path has not been loaded.
Chris@4 238 * @return string
Chris@4 239 */
Chris@4 240 public static function getLoadedClassName($path)
Chris@4 241 {
Chris@4 242 if (isset(self::$loadedClasses[$path]) === false) {
Chris@4 243 throw new \Exception("Cannot get class name for $path; file has not been included");
Chris@4 244 }
Chris@4 245
Chris@4 246 return self::$loadedClasses[$path];
Chris@4 247
Chris@4 248 }//end getLoadedClassName()
Chris@4 249
Chris@4 250
Chris@4 251 /**
Chris@4 252 * Gets the file path for the given class name.
Chris@4 253 *
Chris@4 254 * @param string $class The name of the class.
Chris@4 255 *
Chris@4 256 * @throws \Exception If the class name has not been loaded
Chris@4 257 * @return string
Chris@4 258 */
Chris@4 259 public static function getLoadedFileName($class)
Chris@4 260 {
Chris@4 261 if (isset(self::$loadedFiles[$class]) === false) {
Chris@4 262 throw new \Exception("Cannot get file name for $class; class has not been included");
Chris@4 263 }
Chris@4 264
Chris@4 265 return self::$loadedFiles[$class];
Chris@4 266
Chris@4 267 }//end getLoadedFileName()
Chris@4 268
Chris@4 269
Chris@4 270 /**
Chris@4 271 * Gets the mapping of file names to class names.
Chris@4 272 *
Chris@4 273 * @return array<string, string>
Chris@4 274 */
Chris@4 275 public static function getLoadedClasses()
Chris@4 276 {
Chris@4 277 return self::$loadedClasses;
Chris@4 278
Chris@4 279 }//end getLoadedClasses()
Chris@4 280
Chris@4 281
Chris@4 282 /**
Chris@4 283 * Gets the mapping of class names to file names.
Chris@4 284 *
Chris@4 285 * @return array<string, string>
Chris@4 286 */
Chris@4 287 public static function getLoadedFiles()
Chris@4 288 {
Chris@4 289 return self::$loadedFiles;
Chris@4 290
Chris@4 291 }//end getLoadedFiles()
Chris@4 292
Chris@4 293
Chris@4 294 }//end class
Chris@4 295
Chris@4 296 // Register the autoloader before any existing autoloaders to ensure
Chris@4 297 // it gets a chance to hear about every autoload request, and record
Chris@4 298 // the file and class name for it.
Chris@4 299 spl_autoload_register(__NAMESPACE__.'\Autoload::load', true, true);
Chris@4 300 }//end if