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