xref: /plugin/dw2pdf/vendor/composer/ClassLoader.php (revision dc4d9dc689082c963d5c1d9ee679553326788c6e)
10119ca25SAndreas Gohr<?php
20119ca25SAndreas Gohr
30119ca25SAndreas Gohr/*
40119ca25SAndreas Gohr * This file is part of Composer.
50119ca25SAndreas Gohr *
60119ca25SAndreas Gohr * (c) Nils Adermann <naderman@naderman.de>
70119ca25SAndreas Gohr *     Jordi Boggiano <j.boggiano@seld.be>
80119ca25SAndreas Gohr *
90119ca25SAndreas Gohr * For the full copyright and license information, please view the LICENSE
100119ca25SAndreas Gohr * file that was distributed with this source code.
110119ca25SAndreas Gohr */
120119ca25SAndreas Gohr
130119ca25SAndreas Gohrnamespace Composer\Autoload;
140119ca25SAndreas Gohr
150119ca25SAndreas Gohr/**
160119ca25SAndreas Gohr * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
170119ca25SAndreas Gohr *
180119ca25SAndreas Gohr *     $loader = new \Composer\Autoload\ClassLoader();
190119ca25SAndreas Gohr *
200119ca25SAndreas Gohr *     // register classes with namespaces
210119ca25SAndreas Gohr *     $loader->add('Symfony\Component', __DIR__.'/component');
220119ca25SAndreas Gohr *     $loader->add('Symfony',           __DIR__.'/framework');
230119ca25SAndreas Gohr *
240119ca25SAndreas Gohr *     // activate the autoloader
250119ca25SAndreas Gohr *     $loader->register();
260119ca25SAndreas Gohr *
270119ca25SAndreas Gohr *     // to enable searching the include path (eg. for PEAR packages)
280119ca25SAndreas Gohr *     $loader->setUseIncludePath(true);
290119ca25SAndreas Gohr *
300119ca25SAndreas Gohr * In this example, if you try to use a class in the Symfony\Component
310119ca25SAndreas Gohr * namespace or one of its children (Symfony\Component\Console for instance),
320119ca25SAndreas Gohr * the autoloader will first look for the class under the component/
330119ca25SAndreas Gohr * directory, and it will then fallback to the framework/ directory if not
340119ca25SAndreas Gohr * found before giving up.
350119ca25SAndreas Gohr *
360119ca25SAndreas Gohr * This class is loosely based on the Symfony UniversalClassLoader.
370119ca25SAndreas Gohr *
380119ca25SAndreas Gohr * @author Fabien Potencier <fabien@symfony.com>
390119ca25SAndreas Gohr * @author Jordi Boggiano <j.boggiano@seld.be>
400119ca25SAndreas Gohr * @see    http://www.php-fig.org/psr/psr-0/
410119ca25SAndreas Gohr * @see    http://www.php-fig.org/psr/psr-4/
420119ca25SAndreas Gohr */
430119ca25SAndreas Gohrclass ClassLoader
440119ca25SAndreas Gohr{
450119ca25SAndreas Gohr    // PSR-4
460119ca25SAndreas Gohr    private $prefixLengthsPsr4 = array();
470119ca25SAndreas Gohr    private $prefixDirsPsr4 = array();
480119ca25SAndreas Gohr    private $fallbackDirsPsr4 = array();
490119ca25SAndreas Gohr
500119ca25SAndreas Gohr    // PSR-0
510119ca25SAndreas Gohr    private $prefixesPsr0 = array();
520119ca25SAndreas Gohr    private $fallbackDirsPsr0 = array();
530119ca25SAndreas Gohr
540119ca25SAndreas Gohr    private $useIncludePath = false;
550119ca25SAndreas Gohr    private $classMap = array();
560119ca25SAndreas Gohr    private $classMapAuthoritative = false;
570119ca25SAndreas Gohr    private $missingClasses = array();
580119ca25SAndreas Gohr    private $apcuPrefix;
590119ca25SAndreas Gohr
600119ca25SAndreas Gohr    public function getPrefixes()
610119ca25SAndreas Gohr    {
620119ca25SAndreas Gohr        if (!empty($this->prefixesPsr0)) {
630119ca25SAndreas Gohr            return call_user_func_array('array_merge', $this->prefixesPsr0);
640119ca25SAndreas Gohr        }
650119ca25SAndreas Gohr
660119ca25SAndreas Gohr        return array();
670119ca25SAndreas Gohr    }
680119ca25SAndreas Gohr
690119ca25SAndreas Gohr    public function getPrefixesPsr4()
700119ca25SAndreas Gohr    {
710119ca25SAndreas Gohr        return $this->prefixDirsPsr4;
720119ca25SAndreas Gohr    }
730119ca25SAndreas Gohr
740119ca25SAndreas Gohr    public function getFallbackDirs()
750119ca25SAndreas Gohr    {
760119ca25SAndreas Gohr        return $this->fallbackDirsPsr0;
770119ca25SAndreas Gohr    }
780119ca25SAndreas Gohr
790119ca25SAndreas Gohr    public function getFallbackDirsPsr4()
800119ca25SAndreas Gohr    {
810119ca25SAndreas Gohr        return $this->fallbackDirsPsr4;
820119ca25SAndreas Gohr    }
830119ca25SAndreas Gohr
840119ca25SAndreas Gohr    public function getClassMap()
850119ca25SAndreas Gohr    {
860119ca25SAndreas Gohr        return $this->classMap;
870119ca25SAndreas Gohr    }
880119ca25SAndreas Gohr
890119ca25SAndreas Gohr    /**
900119ca25SAndreas Gohr     * @param array $classMap Class to filename map
910119ca25SAndreas Gohr     */
920119ca25SAndreas Gohr    public function addClassMap(array $classMap)
930119ca25SAndreas Gohr    {
940119ca25SAndreas Gohr        if ($this->classMap) {
950119ca25SAndreas Gohr            $this->classMap = array_merge($this->classMap, $classMap);
960119ca25SAndreas Gohr        } else {
970119ca25SAndreas Gohr            $this->classMap = $classMap;
980119ca25SAndreas Gohr        }
990119ca25SAndreas Gohr    }
1000119ca25SAndreas Gohr
1010119ca25SAndreas Gohr    /**
1020119ca25SAndreas Gohr     * Registers a set of PSR-0 directories for a given prefix, either
1030119ca25SAndreas Gohr     * appending or prepending to the ones previously set for this prefix.
1040119ca25SAndreas Gohr     *
1050119ca25SAndreas Gohr     * @param string       $prefix  The prefix
1060119ca25SAndreas Gohr     * @param array|string $paths   The PSR-0 root directories
1070119ca25SAndreas Gohr     * @param bool         $prepend Whether to prepend the directories
1080119ca25SAndreas Gohr     */
1090119ca25SAndreas Gohr    public function add($prefix, $paths, $prepend = false)
1100119ca25SAndreas Gohr    {
1110119ca25SAndreas Gohr        if (!$prefix) {
1120119ca25SAndreas Gohr            if ($prepend) {
1130119ca25SAndreas Gohr                $this->fallbackDirsPsr0 = array_merge(
1140119ca25SAndreas Gohr                    (array) $paths,
1150119ca25SAndreas Gohr                    $this->fallbackDirsPsr0
1160119ca25SAndreas Gohr                );
1170119ca25SAndreas Gohr            } else {
1180119ca25SAndreas Gohr                $this->fallbackDirsPsr0 = array_merge(
1190119ca25SAndreas Gohr                    $this->fallbackDirsPsr0,
1200119ca25SAndreas Gohr                    (array) $paths
1210119ca25SAndreas Gohr                );
1220119ca25SAndreas Gohr            }
1230119ca25SAndreas Gohr
1240119ca25SAndreas Gohr            return;
1250119ca25SAndreas Gohr        }
1260119ca25SAndreas Gohr
1270119ca25SAndreas Gohr        $first = $prefix[0];
1280119ca25SAndreas Gohr        if (!isset($this->prefixesPsr0[$first][$prefix])) {
1290119ca25SAndreas Gohr            $this->prefixesPsr0[$first][$prefix] = (array) $paths;
1300119ca25SAndreas Gohr
1310119ca25SAndreas Gohr            return;
1320119ca25SAndreas Gohr        }
1330119ca25SAndreas Gohr        if ($prepend) {
1340119ca25SAndreas Gohr            $this->prefixesPsr0[$first][$prefix] = array_merge(
1350119ca25SAndreas Gohr                (array) $paths,
1360119ca25SAndreas Gohr                $this->prefixesPsr0[$first][$prefix]
1370119ca25SAndreas Gohr            );
1380119ca25SAndreas Gohr        } else {
1390119ca25SAndreas Gohr            $this->prefixesPsr0[$first][$prefix] = array_merge(
1400119ca25SAndreas Gohr                $this->prefixesPsr0[$first][$prefix],
1410119ca25SAndreas Gohr                (array) $paths
1420119ca25SAndreas Gohr            );
1430119ca25SAndreas Gohr        }
1440119ca25SAndreas Gohr    }
1450119ca25SAndreas Gohr
1460119ca25SAndreas Gohr    /**
1470119ca25SAndreas Gohr     * Registers a set of PSR-4 directories for a given namespace, either
1480119ca25SAndreas Gohr     * appending or prepending to the ones previously set for this namespace.
1490119ca25SAndreas Gohr     *
1500119ca25SAndreas Gohr     * @param string       $prefix  The prefix/namespace, with trailing '\\'
1510119ca25SAndreas Gohr     * @param array|string $paths   The PSR-4 base directories
1520119ca25SAndreas Gohr     * @param bool         $prepend Whether to prepend the directories
1530119ca25SAndreas Gohr     *
1540119ca25SAndreas Gohr     * @throws \InvalidArgumentException
1550119ca25SAndreas Gohr     */
1560119ca25SAndreas Gohr    public function addPsr4($prefix, $paths, $prepend = false)
1570119ca25SAndreas Gohr    {
1580119ca25SAndreas Gohr        if (!$prefix) {
1590119ca25SAndreas Gohr            // Register directories for the root namespace.
1600119ca25SAndreas Gohr            if ($prepend) {
1610119ca25SAndreas Gohr                $this->fallbackDirsPsr4 = array_merge(
1620119ca25SAndreas Gohr                    (array) $paths,
1630119ca25SAndreas Gohr                    $this->fallbackDirsPsr4
1640119ca25SAndreas Gohr                );
1650119ca25SAndreas Gohr            } else {
1660119ca25SAndreas Gohr                $this->fallbackDirsPsr4 = array_merge(
1670119ca25SAndreas Gohr                    $this->fallbackDirsPsr4,
1680119ca25SAndreas Gohr                    (array) $paths
1690119ca25SAndreas Gohr                );
1700119ca25SAndreas Gohr            }
1710119ca25SAndreas Gohr        } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
1720119ca25SAndreas Gohr            // Register directories for a new namespace.
1730119ca25SAndreas Gohr            $length = strlen($prefix);
1740119ca25SAndreas Gohr            if ('\\' !== $prefix[$length - 1]) {
1750119ca25SAndreas Gohr                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
1760119ca25SAndreas Gohr            }
1770119ca25SAndreas Gohr            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
1780119ca25SAndreas Gohr            $this->prefixDirsPsr4[$prefix] = (array) $paths;
1790119ca25SAndreas Gohr        } elseif ($prepend) {
1800119ca25SAndreas Gohr            // Prepend directories for an already registered namespace.
1810119ca25SAndreas Gohr            $this->prefixDirsPsr4[$prefix] = array_merge(
1820119ca25SAndreas Gohr                (array) $paths,
1830119ca25SAndreas Gohr                $this->prefixDirsPsr4[$prefix]
1840119ca25SAndreas Gohr            );
1850119ca25SAndreas Gohr        } else {
1860119ca25SAndreas Gohr            // Append directories for an already registered namespace.
1870119ca25SAndreas Gohr            $this->prefixDirsPsr4[$prefix] = array_merge(
1880119ca25SAndreas Gohr                $this->prefixDirsPsr4[$prefix],
1890119ca25SAndreas Gohr                (array) $paths
1900119ca25SAndreas Gohr            );
1910119ca25SAndreas Gohr        }
1920119ca25SAndreas Gohr    }
1930119ca25SAndreas Gohr
1940119ca25SAndreas Gohr    /**
1950119ca25SAndreas Gohr     * Registers a set of PSR-0 directories for a given prefix,
1960119ca25SAndreas Gohr     * replacing any others previously set for this prefix.
1970119ca25SAndreas Gohr     *
1980119ca25SAndreas Gohr     * @param string       $prefix The prefix
1990119ca25SAndreas Gohr     * @param array|string $paths  The PSR-0 base directories
2000119ca25SAndreas Gohr     */
2010119ca25SAndreas Gohr    public function set($prefix, $paths)
2020119ca25SAndreas Gohr    {
2030119ca25SAndreas Gohr        if (!$prefix) {
2040119ca25SAndreas Gohr            $this->fallbackDirsPsr0 = (array) $paths;
2050119ca25SAndreas Gohr        } else {
2060119ca25SAndreas Gohr            $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
2070119ca25SAndreas Gohr        }
2080119ca25SAndreas Gohr    }
2090119ca25SAndreas Gohr
2100119ca25SAndreas Gohr    /**
2110119ca25SAndreas Gohr     * Registers a set of PSR-4 directories for a given namespace,
2120119ca25SAndreas Gohr     * replacing any others previously set for this namespace.
2130119ca25SAndreas Gohr     *
2140119ca25SAndreas Gohr     * @param string       $prefix The prefix/namespace, with trailing '\\'
2150119ca25SAndreas Gohr     * @param array|string $paths  The PSR-4 base directories
2160119ca25SAndreas Gohr     *
2170119ca25SAndreas Gohr     * @throws \InvalidArgumentException
2180119ca25SAndreas Gohr     */
2190119ca25SAndreas Gohr    public function setPsr4($prefix, $paths)
2200119ca25SAndreas Gohr    {
2210119ca25SAndreas Gohr        if (!$prefix) {
2220119ca25SAndreas Gohr            $this->fallbackDirsPsr4 = (array) $paths;
2230119ca25SAndreas Gohr        } else {
2240119ca25SAndreas Gohr            $length = strlen($prefix);
2250119ca25SAndreas Gohr            if ('\\' !== $prefix[$length - 1]) {
2260119ca25SAndreas Gohr                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
2270119ca25SAndreas Gohr            }
2280119ca25SAndreas Gohr            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
2290119ca25SAndreas Gohr            $this->prefixDirsPsr4[$prefix] = (array) $paths;
2300119ca25SAndreas Gohr        }
2310119ca25SAndreas Gohr    }
2320119ca25SAndreas Gohr
2330119ca25SAndreas Gohr    /**
2340119ca25SAndreas Gohr     * Turns on searching the include path for class files.
2350119ca25SAndreas Gohr     *
2360119ca25SAndreas Gohr     * @param bool $useIncludePath
2370119ca25SAndreas Gohr     */
2380119ca25SAndreas Gohr    public function setUseIncludePath($useIncludePath)
2390119ca25SAndreas Gohr    {
2400119ca25SAndreas Gohr        $this->useIncludePath = $useIncludePath;
2410119ca25SAndreas Gohr    }
2420119ca25SAndreas Gohr
2430119ca25SAndreas Gohr    /**
2440119ca25SAndreas Gohr     * Can be used to check if the autoloader uses the include path to check
2450119ca25SAndreas Gohr     * for classes.
2460119ca25SAndreas Gohr     *
2470119ca25SAndreas Gohr     * @return bool
2480119ca25SAndreas Gohr     */
2490119ca25SAndreas Gohr    public function getUseIncludePath()
2500119ca25SAndreas Gohr    {
2510119ca25SAndreas Gohr        return $this->useIncludePath;
2520119ca25SAndreas Gohr    }
2530119ca25SAndreas Gohr
2540119ca25SAndreas Gohr    /**
2550119ca25SAndreas Gohr     * Turns off searching the prefix and fallback directories for classes
2560119ca25SAndreas Gohr     * that have not been registered with the class map.
2570119ca25SAndreas Gohr     *
2580119ca25SAndreas Gohr     * @param bool $classMapAuthoritative
2590119ca25SAndreas Gohr     */
2600119ca25SAndreas Gohr    public function setClassMapAuthoritative($classMapAuthoritative)
2610119ca25SAndreas Gohr    {
2620119ca25SAndreas Gohr        $this->classMapAuthoritative = $classMapAuthoritative;
2630119ca25SAndreas Gohr    }
2640119ca25SAndreas Gohr
2650119ca25SAndreas Gohr    /**
2660119ca25SAndreas Gohr     * Should class lookup fail if not found in the current class map?
2670119ca25SAndreas Gohr     *
2680119ca25SAndreas Gohr     * @return bool
2690119ca25SAndreas Gohr     */
2700119ca25SAndreas Gohr    public function isClassMapAuthoritative()
2710119ca25SAndreas Gohr    {
2720119ca25SAndreas Gohr        return $this->classMapAuthoritative;
2730119ca25SAndreas Gohr    }
2740119ca25SAndreas Gohr
2750119ca25SAndreas Gohr    /**
2760119ca25SAndreas Gohr     * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
2770119ca25SAndreas Gohr     *
2780119ca25SAndreas Gohr     * @param string|null $apcuPrefix
2790119ca25SAndreas Gohr     */
2800119ca25SAndreas Gohr    public function setApcuPrefix($apcuPrefix)
2810119ca25SAndreas Gohr    {
282*dc4d9dc6SAnna Dabrowska        $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
2830119ca25SAndreas Gohr    }
2840119ca25SAndreas Gohr
2850119ca25SAndreas Gohr    /**
2860119ca25SAndreas Gohr     * The APCu prefix in use, or null if APCu caching is not enabled.
2870119ca25SAndreas Gohr     *
2880119ca25SAndreas Gohr     * @return string|null
2890119ca25SAndreas Gohr     */
2900119ca25SAndreas Gohr    public function getApcuPrefix()
2910119ca25SAndreas Gohr    {
2920119ca25SAndreas Gohr        return $this->apcuPrefix;
2930119ca25SAndreas Gohr    }
2940119ca25SAndreas Gohr
2950119ca25SAndreas Gohr    /**
2960119ca25SAndreas Gohr     * Registers this instance as an autoloader.
2970119ca25SAndreas Gohr     *
2980119ca25SAndreas Gohr     * @param bool $prepend Whether to prepend the autoloader or not
2990119ca25SAndreas Gohr     */
3000119ca25SAndreas Gohr    public function register($prepend = false)
3010119ca25SAndreas Gohr    {
3020119ca25SAndreas Gohr        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
3030119ca25SAndreas Gohr    }
3040119ca25SAndreas Gohr
3050119ca25SAndreas Gohr    /**
3060119ca25SAndreas Gohr     * Unregisters this instance as an autoloader.
3070119ca25SAndreas Gohr     */
3080119ca25SAndreas Gohr    public function unregister()
3090119ca25SAndreas Gohr    {
3100119ca25SAndreas Gohr        spl_autoload_unregister(array($this, 'loadClass'));
3110119ca25SAndreas Gohr    }
3120119ca25SAndreas Gohr
3130119ca25SAndreas Gohr    /**
3140119ca25SAndreas Gohr     * Loads the given class or interface.
3150119ca25SAndreas Gohr     *
3160119ca25SAndreas Gohr     * @param  string    $class The name of the class
3170119ca25SAndreas Gohr     * @return bool|null True if loaded, null otherwise
3180119ca25SAndreas Gohr     */
3190119ca25SAndreas Gohr    public function loadClass($class)
3200119ca25SAndreas Gohr    {
3210119ca25SAndreas Gohr        if ($file = $this->findFile($class)) {
3220119ca25SAndreas Gohr            includeFile($file);
3230119ca25SAndreas Gohr
3240119ca25SAndreas Gohr            return true;
3250119ca25SAndreas Gohr        }
3260119ca25SAndreas Gohr    }
3270119ca25SAndreas Gohr
3280119ca25SAndreas Gohr    /**
3290119ca25SAndreas Gohr     * Finds the path to the file where the class is defined.
3300119ca25SAndreas Gohr     *
3310119ca25SAndreas Gohr     * @param string $class The name of the class
3320119ca25SAndreas Gohr     *
3330119ca25SAndreas Gohr     * @return string|false The path if found, false otherwise
3340119ca25SAndreas Gohr     */
3350119ca25SAndreas Gohr    public function findFile($class)
3360119ca25SAndreas Gohr    {
3370119ca25SAndreas Gohr        // class map lookup
3380119ca25SAndreas Gohr        if (isset($this->classMap[$class])) {
3390119ca25SAndreas Gohr            return $this->classMap[$class];
3400119ca25SAndreas Gohr        }
3410119ca25SAndreas Gohr        if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
3420119ca25SAndreas Gohr            return false;
3430119ca25SAndreas Gohr        }
3440119ca25SAndreas Gohr        if (null !== $this->apcuPrefix) {
3450119ca25SAndreas Gohr            $file = apcu_fetch($this->apcuPrefix.$class, $hit);
3460119ca25SAndreas Gohr            if ($hit) {
3470119ca25SAndreas Gohr                return $file;
3480119ca25SAndreas Gohr            }
3490119ca25SAndreas Gohr        }
3500119ca25SAndreas Gohr
3510119ca25SAndreas Gohr        $file = $this->findFileWithExtension($class, '.php');
3520119ca25SAndreas Gohr
3530119ca25SAndreas Gohr        // Search for Hack files if we are running on HHVM
3540119ca25SAndreas Gohr        if (false === $file && defined('HHVM_VERSION')) {
3550119ca25SAndreas Gohr            $file = $this->findFileWithExtension($class, '.hh');
3560119ca25SAndreas Gohr        }
3570119ca25SAndreas Gohr
3580119ca25SAndreas Gohr        if (null !== $this->apcuPrefix) {
3590119ca25SAndreas Gohr            apcu_add($this->apcuPrefix.$class, $file);
3600119ca25SAndreas Gohr        }
3610119ca25SAndreas Gohr
3620119ca25SAndreas Gohr        if (false === $file) {
3630119ca25SAndreas Gohr            // Remember that this class does not exist.
3640119ca25SAndreas Gohr            $this->missingClasses[$class] = true;
3650119ca25SAndreas Gohr        }
3660119ca25SAndreas Gohr
3670119ca25SAndreas Gohr        return $file;
3680119ca25SAndreas Gohr    }
3690119ca25SAndreas Gohr
3700119ca25SAndreas Gohr    private function findFileWithExtension($class, $ext)
3710119ca25SAndreas Gohr    {
3720119ca25SAndreas Gohr        // PSR-4 lookup
3730119ca25SAndreas Gohr        $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
3740119ca25SAndreas Gohr
3750119ca25SAndreas Gohr        $first = $class[0];
3760119ca25SAndreas Gohr        if (isset($this->prefixLengthsPsr4[$first])) {
3777f027680SAndreas Gohr            $subPath = $class;
3787f027680SAndreas Gohr            while (false !== $lastPos = strrpos($subPath, '\\')) {
3797f027680SAndreas Gohr                $subPath = substr($subPath, 0, $lastPos);
3807f027680SAndreas Gohr                $search = $subPath . '\\';
3817f027680SAndreas Gohr                if (isset($this->prefixDirsPsr4[$search])) {
382e56751dfSMichael Große                    $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
3837f027680SAndreas Gohr                    foreach ($this->prefixDirsPsr4[$search] as $dir) {
384e56751dfSMichael Große                        if (file_exists($file = $dir . $pathEnd)) {
3850119ca25SAndreas Gohr                            return $file;
3860119ca25SAndreas Gohr                        }
3870119ca25SAndreas Gohr                    }
3880119ca25SAndreas Gohr                }
3890119ca25SAndreas Gohr            }
3900119ca25SAndreas Gohr        }
3910119ca25SAndreas Gohr
3920119ca25SAndreas Gohr        // PSR-4 fallback dirs
3930119ca25SAndreas Gohr        foreach ($this->fallbackDirsPsr4 as $dir) {
3940119ca25SAndreas Gohr            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
3950119ca25SAndreas Gohr                return $file;
3960119ca25SAndreas Gohr            }
3970119ca25SAndreas Gohr        }
3980119ca25SAndreas Gohr
3990119ca25SAndreas Gohr        // PSR-0 lookup
4000119ca25SAndreas Gohr        if (false !== $pos = strrpos($class, '\\')) {
4010119ca25SAndreas Gohr            // namespaced class name
4020119ca25SAndreas Gohr            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
4030119ca25SAndreas Gohr                . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
4040119ca25SAndreas Gohr        } else {
4050119ca25SAndreas Gohr            // PEAR-like class name
4060119ca25SAndreas Gohr            $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
4070119ca25SAndreas Gohr        }
4080119ca25SAndreas Gohr
4090119ca25SAndreas Gohr        if (isset($this->prefixesPsr0[$first])) {
4100119ca25SAndreas Gohr            foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
4110119ca25SAndreas Gohr                if (0 === strpos($class, $prefix)) {
4120119ca25SAndreas Gohr                    foreach ($dirs as $dir) {
4130119ca25SAndreas Gohr                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
4140119ca25SAndreas Gohr                            return $file;
4150119ca25SAndreas Gohr                        }
4160119ca25SAndreas Gohr                    }
4170119ca25SAndreas Gohr                }
4180119ca25SAndreas Gohr            }
4190119ca25SAndreas Gohr        }
4200119ca25SAndreas Gohr
4210119ca25SAndreas Gohr        // PSR-0 fallback dirs
4220119ca25SAndreas Gohr        foreach ($this->fallbackDirsPsr0 as $dir) {
4230119ca25SAndreas Gohr            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
4240119ca25SAndreas Gohr                return $file;
4250119ca25SAndreas Gohr            }
4260119ca25SAndreas Gohr        }
4270119ca25SAndreas Gohr
4280119ca25SAndreas Gohr        // PSR-0 include paths.
4290119ca25SAndreas Gohr        if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
4300119ca25SAndreas Gohr            return $file;
4310119ca25SAndreas Gohr        }
4320119ca25SAndreas Gohr
4330119ca25SAndreas Gohr        return false;
4340119ca25SAndreas Gohr    }
4350119ca25SAndreas Gohr}
4360119ca25SAndreas Gohr
4370119ca25SAndreas Gohr/**
4380119ca25SAndreas Gohr * Scope isolated include.
4390119ca25SAndreas Gohr *
4400119ca25SAndreas Gohr * Prevents access to $this/self from included files.
4410119ca25SAndreas Gohr */
4420119ca25SAndreas Gohrfunction includeFile($file)
4430119ca25SAndreas Gohr{
4440119ca25SAndreas Gohr    include $file;
4450119ca25SAndreas Gohr}
446