1*605f8e8dSAndreas Gohr<?php 2*605f8e8dSAndreas Gohr 3*605f8e8dSAndreas Gohr/* 4*605f8e8dSAndreas Gohr * This file is part of Composer. 5*605f8e8dSAndreas Gohr * 6*605f8e8dSAndreas Gohr * (c) Nils Adermann <naderman@naderman.de> 7*605f8e8dSAndreas Gohr * Jordi Boggiano <j.boggiano@seld.be> 8*605f8e8dSAndreas Gohr * 9*605f8e8dSAndreas Gohr * For the full copyright and license information, please view the LICENSE 10*605f8e8dSAndreas Gohr * file that was distributed with this source code. 11*605f8e8dSAndreas Gohr */ 12*605f8e8dSAndreas Gohr 13*605f8e8dSAndreas Gohrnamespace Composer\Autoload; 14*605f8e8dSAndreas Gohr 15*605f8e8dSAndreas Gohr/** 16*605f8e8dSAndreas Gohr * ClassLoader implements a PSR-0 class loader 17*605f8e8dSAndreas Gohr * 18*605f8e8dSAndreas Gohr * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md 19*605f8e8dSAndreas Gohr * 20*605f8e8dSAndreas Gohr * $loader = new \Composer\Autoload\ClassLoader(); 21*605f8e8dSAndreas Gohr * 22*605f8e8dSAndreas Gohr * // register classes with namespaces 23*605f8e8dSAndreas Gohr * $loader->add('Symfony\Component', __DIR__.'/component'); 24*605f8e8dSAndreas Gohr * $loader->add('Symfony', __DIR__.'/framework'); 25*605f8e8dSAndreas Gohr * 26*605f8e8dSAndreas Gohr * // activate the autoloader 27*605f8e8dSAndreas Gohr * $loader->register(); 28*605f8e8dSAndreas Gohr * 29*605f8e8dSAndreas Gohr * // to enable searching the include path (eg. for PEAR packages) 30*605f8e8dSAndreas Gohr * $loader->setUseIncludePath(true); 31*605f8e8dSAndreas Gohr * 32*605f8e8dSAndreas Gohr * In this example, if you try to use a class in the Symfony\Component 33*605f8e8dSAndreas Gohr * namespace or one of its children (Symfony\Component\Console for instance), 34*605f8e8dSAndreas Gohr * the autoloader will first look for the class under the component/ 35*605f8e8dSAndreas Gohr * directory, and it will then fallback to the framework/ directory if not 36*605f8e8dSAndreas Gohr * found before giving up. 37*605f8e8dSAndreas Gohr * 38*605f8e8dSAndreas Gohr * This class is loosely based on the Symfony UniversalClassLoader. 39*605f8e8dSAndreas Gohr * 40*605f8e8dSAndreas Gohr * @author Fabien Potencier <fabien@symfony.com> 41*605f8e8dSAndreas Gohr * @author Jordi Boggiano <j.boggiano@seld.be> 42*605f8e8dSAndreas Gohr */ 43*605f8e8dSAndreas Gohrclass ClassLoader 44*605f8e8dSAndreas Gohr{ 45*605f8e8dSAndreas Gohr // PSR-4 46*605f8e8dSAndreas Gohr private $prefixLengthsPsr4 = array(); 47*605f8e8dSAndreas Gohr private $prefixDirsPsr4 = array(); 48*605f8e8dSAndreas Gohr private $fallbackDirsPsr4 = array(); 49*605f8e8dSAndreas Gohr 50*605f8e8dSAndreas Gohr // PSR-0 51*605f8e8dSAndreas Gohr private $prefixesPsr0 = array(); 52*605f8e8dSAndreas Gohr private $fallbackDirsPsr0 = array(); 53*605f8e8dSAndreas Gohr 54*605f8e8dSAndreas Gohr private $useIncludePath = false; 55*605f8e8dSAndreas Gohr private $classMap = array(); 56*605f8e8dSAndreas Gohr 57*605f8e8dSAndreas Gohr private $classMapAuthoritative = false; 58*605f8e8dSAndreas Gohr 59*605f8e8dSAndreas Gohr public function getPrefixes() 60*605f8e8dSAndreas Gohr { 61*605f8e8dSAndreas Gohr if (!empty($this->prefixesPsr0)) { 62*605f8e8dSAndreas Gohr return call_user_func_array('array_merge', $this->prefixesPsr0); 63*605f8e8dSAndreas Gohr } 64*605f8e8dSAndreas Gohr 65*605f8e8dSAndreas Gohr return array(); 66*605f8e8dSAndreas Gohr } 67*605f8e8dSAndreas Gohr 68*605f8e8dSAndreas Gohr public function getPrefixesPsr4() 69*605f8e8dSAndreas Gohr { 70*605f8e8dSAndreas Gohr return $this->prefixDirsPsr4; 71*605f8e8dSAndreas Gohr } 72*605f8e8dSAndreas Gohr 73*605f8e8dSAndreas Gohr public function getFallbackDirs() 74*605f8e8dSAndreas Gohr { 75*605f8e8dSAndreas Gohr return $this->fallbackDirsPsr0; 76*605f8e8dSAndreas Gohr } 77*605f8e8dSAndreas Gohr 78*605f8e8dSAndreas Gohr public function getFallbackDirsPsr4() 79*605f8e8dSAndreas Gohr { 80*605f8e8dSAndreas Gohr return $this->fallbackDirsPsr4; 81*605f8e8dSAndreas Gohr } 82*605f8e8dSAndreas Gohr 83*605f8e8dSAndreas Gohr public function getClassMap() 84*605f8e8dSAndreas Gohr { 85*605f8e8dSAndreas Gohr return $this->classMap; 86*605f8e8dSAndreas Gohr } 87*605f8e8dSAndreas Gohr 88*605f8e8dSAndreas Gohr /** 89*605f8e8dSAndreas Gohr * @param array $classMap Class to filename map 90*605f8e8dSAndreas Gohr */ 91*605f8e8dSAndreas Gohr public function addClassMap(array $classMap) 92*605f8e8dSAndreas Gohr { 93*605f8e8dSAndreas Gohr if ($this->classMap) { 94*605f8e8dSAndreas Gohr $this->classMap = array_merge($this->classMap, $classMap); 95*605f8e8dSAndreas Gohr } else { 96*605f8e8dSAndreas Gohr $this->classMap = $classMap; 97*605f8e8dSAndreas Gohr } 98*605f8e8dSAndreas Gohr } 99*605f8e8dSAndreas Gohr 100*605f8e8dSAndreas Gohr /** 101*605f8e8dSAndreas Gohr * Registers a set of PSR-0 directories for a given prefix, either 102*605f8e8dSAndreas Gohr * appending or prepending to the ones previously set for this prefix. 103*605f8e8dSAndreas Gohr * 104*605f8e8dSAndreas Gohr * @param string $prefix The prefix 105*605f8e8dSAndreas Gohr * @param array|string $paths The PSR-0 root directories 106*605f8e8dSAndreas Gohr * @param bool $prepend Whether to prepend the directories 107*605f8e8dSAndreas Gohr */ 108*605f8e8dSAndreas Gohr public function add($prefix, $paths, $prepend = false) 109*605f8e8dSAndreas Gohr { 110*605f8e8dSAndreas Gohr if (!$prefix) { 111*605f8e8dSAndreas Gohr if ($prepend) { 112*605f8e8dSAndreas Gohr $this->fallbackDirsPsr0 = array_merge( 113*605f8e8dSAndreas Gohr (array) $paths, 114*605f8e8dSAndreas Gohr $this->fallbackDirsPsr0 115*605f8e8dSAndreas Gohr ); 116*605f8e8dSAndreas Gohr } else { 117*605f8e8dSAndreas Gohr $this->fallbackDirsPsr0 = array_merge( 118*605f8e8dSAndreas Gohr $this->fallbackDirsPsr0, 119*605f8e8dSAndreas Gohr (array) $paths 120*605f8e8dSAndreas Gohr ); 121*605f8e8dSAndreas Gohr } 122*605f8e8dSAndreas Gohr 123*605f8e8dSAndreas Gohr return; 124*605f8e8dSAndreas Gohr } 125*605f8e8dSAndreas Gohr 126*605f8e8dSAndreas Gohr $first = $prefix[0]; 127*605f8e8dSAndreas Gohr if (!isset($this->prefixesPsr0[$first][$prefix])) { 128*605f8e8dSAndreas Gohr $this->prefixesPsr0[$first][$prefix] = (array) $paths; 129*605f8e8dSAndreas Gohr 130*605f8e8dSAndreas Gohr return; 131*605f8e8dSAndreas Gohr } 132*605f8e8dSAndreas Gohr if ($prepend) { 133*605f8e8dSAndreas Gohr $this->prefixesPsr0[$first][$prefix] = array_merge( 134*605f8e8dSAndreas Gohr (array) $paths, 135*605f8e8dSAndreas Gohr $this->prefixesPsr0[$first][$prefix] 136*605f8e8dSAndreas Gohr ); 137*605f8e8dSAndreas Gohr } else { 138*605f8e8dSAndreas Gohr $this->prefixesPsr0[$first][$prefix] = array_merge( 139*605f8e8dSAndreas Gohr $this->prefixesPsr0[$first][$prefix], 140*605f8e8dSAndreas Gohr (array) $paths 141*605f8e8dSAndreas Gohr ); 142*605f8e8dSAndreas Gohr } 143*605f8e8dSAndreas Gohr } 144*605f8e8dSAndreas Gohr 145*605f8e8dSAndreas Gohr /** 146*605f8e8dSAndreas Gohr * Registers a set of PSR-4 directories for a given namespace, either 147*605f8e8dSAndreas Gohr * appending or prepending to the ones previously set for this namespace. 148*605f8e8dSAndreas Gohr * 149*605f8e8dSAndreas Gohr * @param string $prefix The prefix/namespace, with trailing '\\' 150*605f8e8dSAndreas Gohr * @param array|string $paths The PSR-0 base directories 151*605f8e8dSAndreas Gohr * @param bool $prepend Whether to prepend the directories 152*605f8e8dSAndreas Gohr * 153*605f8e8dSAndreas Gohr * @throws \InvalidArgumentException 154*605f8e8dSAndreas Gohr */ 155*605f8e8dSAndreas Gohr public function addPsr4($prefix, $paths, $prepend = false) 156*605f8e8dSAndreas Gohr { 157*605f8e8dSAndreas Gohr if (!$prefix) { 158*605f8e8dSAndreas Gohr // Register directories for the root namespace. 159*605f8e8dSAndreas Gohr if ($prepend) { 160*605f8e8dSAndreas Gohr $this->fallbackDirsPsr4 = array_merge( 161*605f8e8dSAndreas Gohr (array) $paths, 162*605f8e8dSAndreas Gohr $this->fallbackDirsPsr4 163*605f8e8dSAndreas Gohr ); 164*605f8e8dSAndreas Gohr } else { 165*605f8e8dSAndreas Gohr $this->fallbackDirsPsr4 = array_merge( 166*605f8e8dSAndreas Gohr $this->fallbackDirsPsr4, 167*605f8e8dSAndreas Gohr (array) $paths 168*605f8e8dSAndreas Gohr ); 169*605f8e8dSAndreas Gohr } 170*605f8e8dSAndreas Gohr } elseif (!isset($this->prefixDirsPsr4[$prefix])) { 171*605f8e8dSAndreas Gohr // Register directories for a new namespace. 172*605f8e8dSAndreas Gohr $length = strlen($prefix); 173*605f8e8dSAndreas Gohr if ('\\' !== $prefix[$length - 1]) { 174*605f8e8dSAndreas Gohr throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 175*605f8e8dSAndreas Gohr } 176*605f8e8dSAndreas Gohr $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 177*605f8e8dSAndreas Gohr $this->prefixDirsPsr4[$prefix] = (array) $paths; 178*605f8e8dSAndreas Gohr } elseif ($prepend) { 179*605f8e8dSAndreas Gohr // Prepend directories for an already registered namespace. 180*605f8e8dSAndreas Gohr $this->prefixDirsPsr4[$prefix] = array_merge( 181*605f8e8dSAndreas Gohr (array) $paths, 182*605f8e8dSAndreas Gohr $this->prefixDirsPsr4[$prefix] 183*605f8e8dSAndreas Gohr ); 184*605f8e8dSAndreas Gohr } else { 185*605f8e8dSAndreas Gohr // Append directories for an already registered namespace. 186*605f8e8dSAndreas Gohr $this->prefixDirsPsr4[$prefix] = array_merge( 187*605f8e8dSAndreas Gohr $this->prefixDirsPsr4[$prefix], 188*605f8e8dSAndreas Gohr (array) $paths 189*605f8e8dSAndreas Gohr ); 190*605f8e8dSAndreas Gohr } 191*605f8e8dSAndreas Gohr } 192*605f8e8dSAndreas Gohr 193*605f8e8dSAndreas Gohr /** 194*605f8e8dSAndreas Gohr * Registers a set of PSR-0 directories for a given prefix, 195*605f8e8dSAndreas Gohr * replacing any others previously set for this prefix. 196*605f8e8dSAndreas Gohr * 197*605f8e8dSAndreas Gohr * @param string $prefix The prefix 198*605f8e8dSAndreas Gohr * @param array|string $paths The PSR-0 base directories 199*605f8e8dSAndreas Gohr */ 200*605f8e8dSAndreas Gohr public function set($prefix, $paths) 201*605f8e8dSAndreas Gohr { 202*605f8e8dSAndreas Gohr if (!$prefix) { 203*605f8e8dSAndreas Gohr $this->fallbackDirsPsr0 = (array) $paths; 204*605f8e8dSAndreas Gohr } else { 205*605f8e8dSAndreas Gohr $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; 206*605f8e8dSAndreas Gohr } 207*605f8e8dSAndreas Gohr } 208*605f8e8dSAndreas Gohr 209*605f8e8dSAndreas Gohr /** 210*605f8e8dSAndreas Gohr * Registers a set of PSR-4 directories for a given namespace, 211*605f8e8dSAndreas Gohr * replacing any others previously set for this namespace. 212*605f8e8dSAndreas Gohr * 213*605f8e8dSAndreas Gohr * @param string $prefix The prefix/namespace, with trailing '\\' 214*605f8e8dSAndreas Gohr * @param array|string $paths The PSR-4 base directories 215*605f8e8dSAndreas Gohr * 216*605f8e8dSAndreas Gohr * @throws \InvalidArgumentException 217*605f8e8dSAndreas Gohr */ 218*605f8e8dSAndreas Gohr public function setPsr4($prefix, $paths) 219*605f8e8dSAndreas Gohr { 220*605f8e8dSAndreas Gohr if (!$prefix) { 221*605f8e8dSAndreas Gohr $this->fallbackDirsPsr4 = (array) $paths; 222*605f8e8dSAndreas Gohr } else { 223*605f8e8dSAndreas Gohr $length = strlen($prefix); 224*605f8e8dSAndreas Gohr if ('\\' !== $prefix[$length - 1]) { 225*605f8e8dSAndreas Gohr throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 226*605f8e8dSAndreas Gohr } 227*605f8e8dSAndreas Gohr $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 228*605f8e8dSAndreas Gohr $this->prefixDirsPsr4[$prefix] = (array) $paths; 229*605f8e8dSAndreas Gohr } 230*605f8e8dSAndreas Gohr } 231*605f8e8dSAndreas Gohr 232*605f8e8dSAndreas Gohr /** 233*605f8e8dSAndreas Gohr * Turns on searching the include path for class files. 234*605f8e8dSAndreas Gohr * 235*605f8e8dSAndreas Gohr * @param bool $useIncludePath 236*605f8e8dSAndreas Gohr */ 237*605f8e8dSAndreas Gohr public function setUseIncludePath($useIncludePath) 238*605f8e8dSAndreas Gohr { 239*605f8e8dSAndreas Gohr $this->useIncludePath = $useIncludePath; 240*605f8e8dSAndreas Gohr } 241*605f8e8dSAndreas Gohr 242*605f8e8dSAndreas Gohr /** 243*605f8e8dSAndreas Gohr * Can be used to check if the autoloader uses the include path to check 244*605f8e8dSAndreas Gohr * for classes. 245*605f8e8dSAndreas Gohr * 246*605f8e8dSAndreas Gohr * @return bool 247*605f8e8dSAndreas Gohr */ 248*605f8e8dSAndreas Gohr public function getUseIncludePath() 249*605f8e8dSAndreas Gohr { 250*605f8e8dSAndreas Gohr return $this->useIncludePath; 251*605f8e8dSAndreas Gohr } 252*605f8e8dSAndreas Gohr 253*605f8e8dSAndreas Gohr /** 254*605f8e8dSAndreas Gohr * Turns off searching the prefix and fallback directories for classes 255*605f8e8dSAndreas Gohr * that have not been registered with the class map. 256*605f8e8dSAndreas Gohr * 257*605f8e8dSAndreas Gohr * @param bool $classMapAuthoritative 258*605f8e8dSAndreas Gohr */ 259*605f8e8dSAndreas Gohr public function setClassMapAuthoritative($classMapAuthoritative) 260*605f8e8dSAndreas Gohr { 261*605f8e8dSAndreas Gohr $this->classMapAuthoritative = $classMapAuthoritative; 262*605f8e8dSAndreas Gohr } 263*605f8e8dSAndreas Gohr 264*605f8e8dSAndreas Gohr /** 265*605f8e8dSAndreas Gohr * Should class lookup fail if not found in the current class map? 266*605f8e8dSAndreas Gohr * 267*605f8e8dSAndreas Gohr * @return bool 268*605f8e8dSAndreas Gohr */ 269*605f8e8dSAndreas Gohr public function isClassMapAuthoritative() 270*605f8e8dSAndreas Gohr { 271*605f8e8dSAndreas Gohr return $this->classMapAuthoritative; 272*605f8e8dSAndreas Gohr } 273*605f8e8dSAndreas Gohr 274*605f8e8dSAndreas Gohr /** 275*605f8e8dSAndreas Gohr * Registers this instance as an autoloader. 276*605f8e8dSAndreas Gohr * 277*605f8e8dSAndreas Gohr * @param bool $prepend Whether to prepend the autoloader or not 278*605f8e8dSAndreas Gohr */ 279*605f8e8dSAndreas Gohr public function register($prepend = false) 280*605f8e8dSAndreas Gohr { 281*605f8e8dSAndreas Gohr spl_autoload_register(array($this, 'loadClass'), true, $prepend); 282*605f8e8dSAndreas Gohr } 283*605f8e8dSAndreas Gohr 284*605f8e8dSAndreas Gohr /** 285*605f8e8dSAndreas Gohr * Unregisters this instance as an autoloader. 286*605f8e8dSAndreas Gohr */ 287*605f8e8dSAndreas Gohr public function unregister() 288*605f8e8dSAndreas Gohr { 289*605f8e8dSAndreas Gohr spl_autoload_unregister(array($this, 'loadClass')); 290*605f8e8dSAndreas Gohr } 291*605f8e8dSAndreas Gohr 292*605f8e8dSAndreas Gohr /** 293*605f8e8dSAndreas Gohr * Loads the given class or interface. 294*605f8e8dSAndreas Gohr * 295*605f8e8dSAndreas Gohr * @param string $class The name of the class 296*605f8e8dSAndreas Gohr * @return bool|null True if loaded, null otherwise 297*605f8e8dSAndreas Gohr */ 298*605f8e8dSAndreas Gohr public function loadClass($class) 299*605f8e8dSAndreas Gohr { 300*605f8e8dSAndreas Gohr if ($file = $this->findFile($class)) { 301*605f8e8dSAndreas Gohr includeFile($file); 302*605f8e8dSAndreas Gohr 303*605f8e8dSAndreas Gohr return true; 304*605f8e8dSAndreas Gohr } 305*605f8e8dSAndreas Gohr } 306*605f8e8dSAndreas Gohr 307*605f8e8dSAndreas Gohr /** 308*605f8e8dSAndreas Gohr * Finds the path to the file where the class is defined. 309*605f8e8dSAndreas Gohr * 310*605f8e8dSAndreas Gohr * @param string $class The name of the class 311*605f8e8dSAndreas Gohr * 312*605f8e8dSAndreas Gohr * @return string|false The path if found, false otherwise 313*605f8e8dSAndreas Gohr */ 314*605f8e8dSAndreas Gohr public function findFile($class) 315*605f8e8dSAndreas Gohr { 316*605f8e8dSAndreas Gohr // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 317*605f8e8dSAndreas Gohr if ('\\' == $class[0]) { 318*605f8e8dSAndreas Gohr $class = substr($class, 1); 319*605f8e8dSAndreas Gohr } 320*605f8e8dSAndreas Gohr 321*605f8e8dSAndreas Gohr // class map lookup 322*605f8e8dSAndreas Gohr if (isset($this->classMap[$class])) { 323*605f8e8dSAndreas Gohr return $this->classMap[$class]; 324*605f8e8dSAndreas Gohr } 325*605f8e8dSAndreas Gohr if ($this->classMapAuthoritative) { 326*605f8e8dSAndreas Gohr return false; 327*605f8e8dSAndreas Gohr } 328*605f8e8dSAndreas Gohr 329*605f8e8dSAndreas Gohr $file = $this->findFileWithExtension($class, '.php'); 330*605f8e8dSAndreas Gohr 331*605f8e8dSAndreas Gohr // Search for Hack files if we are running on HHVM 332*605f8e8dSAndreas Gohr if ($file === null && defined('HHVM_VERSION')) { 333*605f8e8dSAndreas Gohr $file = $this->findFileWithExtension($class, '.hh'); 334*605f8e8dSAndreas Gohr } 335*605f8e8dSAndreas Gohr 336*605f8e8dSAndreas Gohr if ($file === null) { 337*605f8e8dSAndreas Gohr // Remember that this class does not exist. 338*605f8e8dSAndreas Gohr return $this->classMap[$class] = false; 339*605f8e8dSAndreas Gohr } 340*605f8e8dSAndreas Gohr 341*605f8e8dSAndreas Gohr return $file; 342*605f8e8dSAndreas Gohr } 343*605f8e8dSAndreas Gohr 344*605f8e8dSAndreas Gohr private function findFileWithExtension($class, $ext) 345*605f8e8dSAndreas Gohr { 346*605f8e8dSAndreas Gohr // PSR-4 lookup 347*605f8e8dSAndreas Gohr $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; 348*605f8e8dSAndreas Gohr 349*605f8e8dSAndreas Gohr $first = $class[0]; 350*605f8e8dSAndreas Gohr if (isset($this->prefixLengthsPsr4[$first])) { 351*605f8e8dSAndreas Gohr foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { 352*605f8e8dSAndreas Gohr if (0 === strpos($class, $prefix)) { 353*605f8e8dSAndreas Gohr foreach ($this->prefixDirsPsr4[$prefix] as $dir) { 354*605f8e8dSAndreas Gohr if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { 355*605f8e8dSAndreas Gohr return $file; 356*605f8e8dSAndreas Gohr } 357*605f8e8dSAndreas Gohr } 358*605f8e8dSAndreas Gohr } 359*605f8e8dSAndreas Gohr } 360*605f8e8dSAndreas Gohr } 361*605f8e8dSAndreas Gohr 362*605f8e8dSAndreas Gohr // PSR-4 fallback dirs 363*605f8e8dSAndreas Gohr foreach ($this->fallbackDirsPsr4 as $dir) { 364*605f8e8dSAndreas Gohr if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { 365*605f8e8dSAndreas Gohr return $file; 366*605f8e8dSAndreas Gohr } 367*605f8e8dSAndreas Gohr } 368*605f8e8dSAndreas Gohr 369*605f8e8dSAndreas Gohr // PSR-0 lookup 370*605f8e8dSAndreas Gohr if (false !== $pos = strrpos($class, '\\')) { 371*605f8e8dSAndreas Gohr // namespaced class name 372*605f8e8dSAndreas Gohr $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) 373*605f8e8dSAndreas Gohr . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); 374*605f8e8dSAndreas Gohr } else { 375*605f8e8dSAndreas Gohr // PEAR-like class name 376*605f8e8dSAndreas Gohr $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; 377*605f8e8dSAndreas Gohr } 378*605f8e8dSAndreas Gohr 379*605f8e8dSAndreas Gohr if (isset($this->prefixesPsr0[$first])) { 380*605f8e8dSAndreas Gohr foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { 381*605f8e8dSAndreas Gohr if (0 === strpos($class, $prefix)) { 382*605f8e8dSAndreas Gohr foreach ($dirs as $dir) { 383*605f8e8dSAndreas Gohr if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 384*605f8e8dSAndreas Gohr return $file; 385*605f8e8dSAndreas Gohr } 386*605f8e8dSAndreas Gohr } 387*605f8e8dSAndreas Gohr } 388*605f8e8dSAndreas Gohr } 389*605f8e8dSAndreas Gohr } 390*605f8e8dSAndreas Gohr 391*605f8e8dSAndreas Gohr // PSR-0 fallback dirs 392*605f8e8dSAndreas Gohr foreach ($this->fallbackDirsPsr0 as $dir) { 393*605f8e8dSAndreas Gohr if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 394*605f8e8dSAndreas Gohr return $file; 395*605f8e8dSAndreas Gohr } 396*605f8e8dSAndreas Gohr } 397*605f8e8dSAndreas Gohr 398*605f8e8dSAndreas Gohr // PSR-0 include paths. 399*605f8e8dSAndreas Gohr if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { 400*605f8e8dSAndreas Gohr return $file; 401*605f8e8dSAndreas Gohr } 402*605f8e8dSAndreas Gohr } 403*605f8e8dSAndreas Gohr} 404*605f8e8dSAndreas Gohr 405*605f8e8dSAndreas Gohr/** 406*605f8e8dSAndreas Gohr * Scope isolated include. 407*605f8e8dSAndreas Gohr * 408*605f8e8dSAndreas Gohr * Prevents access to $this/self from included files. 409*605f8e8dSAndreas Gohr */ 410*605f8e8dSAndreas Gohrfunction includeFile($file) 411*605f8e8dSAndreas Gohr{ 412*605f8e8dSAndreas Gohr include $file; 413*605f8e8dSAndreas Gohr} 414