CoolFace
Apppublic

ReacherCD/Batcave

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