[ Index ] |
PHP Cross Reference of phpBB-3.2.11-deutsch |
[Summary view] [Print] [Text view]
1 <?php 2 3 /* 4 * This file is part of the Symfony package. 5 * 6 * (c) Fabien Potencier <fabien@symfony.com> 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12 namespace Symfony\Component\Debug; 13 14 /** 15 * Autoloader checking if the class is really defined in the file found. 16 * 17 * The ClassLoader will wrap all registered autoloaders 18 * and will throw an exception if a file is found but does 19 * not declare the class. 20 * 21 * @author Fabien Potencier <fabien@symfony.com> 22 * @author Christophe Coevoet <stof@notk.org> 23 * @author Nicolas Grekas <p@tchwork.com> 24 */ 25 class DebugClassLoader 26 { 27 private $classLoader; 28 private $isFinder; 29 private $loaded = array(); 30 private $wasFinder; 31 private static $caseCheck; 32 private static $deprecated = array(); 33 private static $php7Reserved = array('int', 'float', 'bool', 'string', 'true', 'false', 'null'); 34 private static $darwinCache = array('/' => array('/', array())); 35 36 /** 37 * @param callable|object $classLoader Passing an object is @deprecated since version 2.5 and support for it will be removed in 3.0 38 */ 39 public function __construct($classLoader) 40 { 41 $this->wasFinder = \is_object($classLoader) && method_exists($classLoader, 'findFile'); 42 43 if ($this->wasFinder) { 44 @trigger_error('The '.__METHOD__.' method will no longer support receiving an object into its $classLoader argument in 3.0.', E_USER_DEPRECATED); 45 $this->classLoader = array($classLoader, 'loadClass'); 46 $this->isFinder = true; 47 } else { 48 $this->classLoader = $classLoader; 49 $this->isFinder = \is_array($classLoader) && method_exists($classLoader[0], 'findFile'); 50 } 51 52 if (!isset(self::$caseCheck)) { 53 $file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), \DIRECTORY_SEPARATOR); 54 $i = strrpos($file, \DIRECTORY_SEPARATOR); 55 $dir = substr($file, 0, 1 + $i); 56 $file = substr($file, 1 + $i); 57 $test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file); 58 $test = realpath($dir.$test); 59 60 if (false === $test || false === $i) { 61 // filesystem is case sensitive 62 self::$caseCheck = 0; 63 } elseif (substr($test, -\strlen($file)) === $file) { 64 // filesystem is case insensitive and realpath() normalizes the case of characters 65 self::$caseCheck = 1; 66 } elseif (false !== stripos(PHP_OS, 'darwin')) { 67 // on MacOSX, HFS+ is case insensitive but realpath() doesn't normalize the case of characters 68 self::$caseCheck = 2; 69 } else { 70 // filesystem case checks failed, fallback to disabling them 71 self::$caseCheck = 0; 72 } 73 } 74 } 75 76 /** 77 * Gets the wrapped class loader. 78 * 79 * @return callable|object A class loader. Since version 2.5, returning an object is @deprecated and support for it will be removed in 3.0 80 */ 81 public function getClassLoader() 82 { 83 return $this->wasFinder ? $this->classLoader[0] : $this->classLoader; 84 } 85 86 /** 87 * Wraps all autoloaders. 88 */ 89 public static function enable() 90 { 91 // Ensures we don't hit https://bugs.php.net/42098 92 class_exists('Symfony\Component\Debug\ErrorHandler'); 93 class_exists('Psr\Log\LogLevel'); 94 95 if (!\is_array($functions = spl_autoload_functions())) { 96 return; 97 } 98 99 foreach ($functions as $function) { 100 spl_autoload_unregister($function); 101 } 102 103 foreach ($functions as $function) { 104 if (!\is_array($function) || !$function[0] instanceof self) { 105 $function = array(new static($function), 'loadClass'); 106 } 107 108 spl_autoload_register($function); 109 } 110 } 111 112 /** 113 * Disables the wrapping. 114 */ 115 public static function disable() 116 { 117 if (!\is_array($functions = spl_autoload_functions())) { 118 return; 119 } 120 121 foreach ($functions as $function) { 122 spl_autoload_unregister($function); 123 } 124 125 foreach ($functions as $function) { 126 if (\is_array($function) && $function[0] instanceof self) { 127 $function = $function[0]->getClassLoader(); 128 } 129 130 spl_autoload_register($function); 131 } 132 } 133 134 /** 135 * Finds a file by class name. 136 * 137 * @param string $class A class name to resolve to file 138 * 139 * @return string|null 140 * 141 * @deprecated since version 2.5, to be removed in 3.0. 142 */ 143 public function findFile($class) 144 { 145 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED); 146 147 if ($this->wasFinder) { 148 return $this->classLoader[0]->findFile($class); 149 } 150 } 151 152 /** 153 * Loads the given class or interface. 154 * 155 * @param string $class The name of the class 156 * 157 * @return bool|null True, if loaded 158 * 159 * @throws \RuntimeException 160 */ 161 public function loadClass($class) 162 { 163 ErrorHandler::stackErrors(); 164 165 try { 166 if ($this->isFinder && !isset($this->loaded[$class])) { 167 $this->loaded[$class] = true; 168 if ($file = $this->classLoader[0]->findFile($class)) { 169 require $file; 170 } 171 } else { 172 \call_user_func($this->classLoader, $class); 173 $file = false; 174 } 175 } catch (\Exception $e) { 176 ErrorHandler::unstackErrors(); 177 178 throw $e; 179 } catch (\Throwable $e) { 180 ErrorHandler::unstackErrors(); 181 182 throw $e; 183 } 184 185 ErrorHandler::unstackErrors(); 186 187 $exists = class_exists($class, false) || interface_exists($class, false) || (\function_exists('trait_exists') && trait_exists($class, false)); 188 189 if ($class && '\\' === $class[0]) { 190 $class = substr($class, 1); 191 } 192 193 if ($exists) { 194 $refl = new \ReflectionClass($class); 195 $name = $refl->getName(); 196 197 if ($name !== $class && 0 === strcasecmp($name, $class)) { 198 throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: %s vs %s', $class, $name)); 199 } 200 201 if (\in_array(strtolower($refl->getShortName()), self::$php7Reserved)) { 202 @trigger_error(sprintf('%s uses a reserved class name (%s) that will break on PHP 7 and higher', $name, $refl->getShortName()), E_USER_DEPRECATED); 203 } elseif (preg_match('#\n \* @deprecated (.*?)\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) { 204 self::$deprecated[$name] = preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]); 205 } else { 206 if (2 > $len = 1 + (strpos($name, '\\') ?: strpos($name, '_'))) { 207 $len = 0; 208 $ns = ''; 209 } else { 210 $ns = substr($name, 0, $len); 211 } 212 $parent = get_parent_class($class); 213 214 if (!$parent || strncmp($ns, $parent, $len)) { 215 if ($parent && isset(self::$deprecated[$parent]) && strncmp($ns, $parent, $len)) { 216 @trigger_error(sprintf('The %s class extends %s that is deprecated %s', $name, $parent, self::$deprecated[$parent]), E_USER_DEPRECATED); 217 } 218 219 $parentInterfaces = array(); 220 $deprecatedInterfaces = array(); 221 if ($parent) { 222 foreach (class_implements($parent) as $interface) { 223 $parentInterfaces[$interface] = 1; 224 } 225 } 226 227 foreach ($refl->getInterfaceNames() as $interface) { 228 if (isset(self::$deprecated[$interface]) && strncmp($ns, $interface, $len)) { 229 $deprecatedInterfaces[] = $interface; 230 } 231 foreach (class_implements($interface) as $interface) { 232 $parentInterfaces[$interface] = 1; 233 } 234 } 235 236 foreach ($deprecatedInterfaces as $interface) { 237 if (!isset($parentInterfaces[$interface])) { 238 @trigger_error(sprintf('The %s %s %s that is deprecated %s', $name, $refl->isInterface() ? 'interface extends' : 'class implements', $interface, self::$deprecated[$interface]), E_USER_DEPRECATED); 239 } 240 } 241 } 242 } 243 } 244 245 if ($file) { 246 if (!$exists) { 247 if (false !== strpos($class, '/')) { 248 throw new \RuntimeException(sprintf('Trying to autoload a class with an invalid name "%s". Be careful that the namespace separator is "\" in PHP, not "/".', $class)); 249 } 250 251 throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file)); 252 } 253 if (self::$caseCheck) { 254 $real = explode('\\', $class.strrchr($file, '.')); 255 $tail = explode(\DIRECTORY_SEPARATOR, str_replace('/', \DIRECTORY_SEPARATOR, $file)); 256 257 $i = \count($tail) - 1; 258 $j = \count($real) - 1; 259 260 while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) { 261 --$i; 262 --$j; 263 } 264 265 array_splice($tail, 0, $i + 1); 266 } 267 if (self::$caseCheck && $tail) { 268 $tail = \DIRECTORY_SEPARATOR.implode(\DIRECTORY_SEPARATOR, $tail); 269 $tailLen = \strlen($tail); 270 $real = $refl->getFileName(); 271 272 if (2 === self::$caseCheck) { 273 // realpath() on MacOSX doesn't normalize the case of characters 274 275 $i = 1 + strrpos($real, '/'); 276 $file = substr($real, $i); 277 $real = substr($real, 0, $i); 278 279 if (isset(self::$darwinCache[$real])) { 280 $kDir = $real; 281 } else { 282 $kDir = strtolower($real); 283 284 if (isset(self::$darwinCache[$kDir])) { 285 $real = self::$darwinCache[$kDir][0]; 286 } else { 287 $dir = getcwd(); 288 chdir($real); 289 $real = getcwd().'/'; 290 chdir($dir); 291 292 $dir = $real; 293 $k = $kDir; 294 $i = \strlen($dir) - 1; 295 while (!isset(self::$darwinCache[$k])) { 296 self::$darwinCache[$k] = array($dir, array()); 297 self::$darwinCache[$dir] = &self::$darwinCache[$k]; 298 299 while ('/' !== $dir[--$i]) { 300 } 301 $k = substr($k, 0, ++$i); 302 $dir = substr($dir, 0, $i--); 303 } 304 } 305 } 306 307 $dirFiles = self::$darwinCache[$kDir][1]; 308 309 if (isset($dirFiles[$file])) { 310 $kFile = $file; 311 } else { 312 $kFile = strtolower($file); 313 314 if (!isset($dirFiles[$kFile])) { 315 foreach (scandir($real, 2) as $f) { 316 if ('.' !== $f[0]) { 317 $dirFiles[$f] = $f; 318 if ($f === $file) { 319 $kFile = $k = $file; 320 } elseif ($f !== $k = strtolower($f)) { 321 $dirFiles[$k] = $f; 322 } 323 } 324 } 325 self::$darwinCache[$kDir][1] = $dirFiles; 326 } 327 } 328 329 $real .= $dirFiles[$kFile]; 330 } 331 332 if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true) 333 && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false) 334 ) { 335 throw new \RuntimeException(sprintf('Case mismatch between class and real file names: %s vs %s in %s', substr($tail, -$tailLen + 1), substr($real, -$tailLen + 1), substr($real, 0, -$tailLen + 1))); 336 } 337 } 338 339 return true; 340 } 341 } 342 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Nov 11 20:33:01 2020 | Cross-referenced by PHPXref 0.7.1 |