| <?php |
| |
| /* |
| * This file is part of the Symfony package. |
| * |
| * (c) Fabien Potencier <fabien@symfony.com> |
| * |
| * For the full copyright and license information, please view the LICENSE |
| * file that was distributed with this source code. |
| */ |
| |
| namespace Symfony\Component\ClassLoader; |
| |
| /** |
| * UniversalClassLoader implements a "universal" autoloader for PHP 5.3. |
| * |
| * It is able to load classes that use either: |
| * |
| * * The technical interoperability standards for PHP 5.3 namespaces and |
| * class names (http://groups.google.com/group/php-standards/web/psr-0-final-proposal); |
| * |
| * * The PEAR naming convention for classes (http://pear.php.net/). |
| * |
| * Classes from a sub-namespace or a sub-hierarchy of PEAR classes can be |
| * looked for in a list of locations to ease the vendoring of a sub-set of |
| * classes for large projects. |
| * |
| * Example usage: |
| * |
| * $loader = new UniversalClassLoader(); |
| * |
| * // register classes with namespaces |
| * $loader->registerNamespaces(array( |
| * 'Symfony\Component' => __DIR__.'/component', |
| * 'Symfony' => __DIR__.'/framework', |
| * 'Sensio' => array(__DIR__.'/src', __DIR__.'/vendor'), |
| * )); |
| * |
| * // register a library using the PEAR naming convention |
| * $loader->registerPrefixes(array( |
| * 'Swift_' => __DIR__.'/Swift', |
| * )); |
| * |
| * |
| * // to enable searching the include path (eg. for PEAR packages) |
| * $loader->useIncludePath(true); |
| * |
| * // activate the autoloader |
| * $loader->register(); |
| * |
| * In this example, if you try to use a class in the Symfony\Component |
| * namespace or one of its children (Symfony\Component\Console for instance), |
| * the autoloader will first look for the class under the component/ |
| * directory, and it will then fallback to the framework/ directory if not |
| * found before giving up. |
| * |
| * @author Fabien Potencier <fabien@symfony.com> |
| * |
| * @api |
| */ |
| class UniversalClassLoader |
| { |
| private $namespaces = array(); |
| private $prefixes = array(); |
| private $namespaceFallbacks = array(); |
| private $prefixFallbacks = array(); |
| private $useIncludePath = false; |
| |
| /** |
| * Turns on searching the include for class files. Allows easy loading |
| * of installed PEAR packages |
| * |
| * @param Boolean $useIncludePath |
| */ |
| public function useIncludePath($useIncludePath) |
| { |
| $this->useIncludePath = $useIncludePath; |
| } |
| |
| /** |
| * Can be used to check if the autoloader uses the include path to check |
| * for classes. |
| * |
| * @return Boolean |
| */ |
| public function getUseIncludePath() |
| { |
| return $this->useIncludePath; |
| } |
| |
| /** |
| * Gets the configured namespaces. |
| * |
| * @return array A hash with namespaces as keys and directories as values |
| */ |
| public function getNamespaces() |
| { |
| return $this->namespaces; |
| } |
| |
| /** |
| * Gets the configured class prefixes. |
| * |
| * @return array A hash with class prefixes as keys and directories as values |
| */ |
| public function getPrefixes() |
| { |
| return $this->prefixes; |
| } |
| |
| /** |
| * Gets the directory(ies) to use as a fallback for namespaces. |
| * |
| * @return array An array of directories |
| */ |
| public function getNamespaceFallbacks() |
| { |
| return $this->namespaceFallbacks; |
| } |
| |
| /** |
| * Gets the directory(ies) to use as a fallback for class prefixes. |
| * |
| * @return array An array of directories |
| */ |
| public function getPrefixFallbacks() |
| { |
| return $this->prefixFallbacks; |
| } |
| |
| /** |
| * Registers the directory to use as a fallback for namespaces. |
| * |
| * @param array $dirs An array of directories |
| * |
| * @api |
| */ |
| public function registerNamespaceFallbacks(array $dirs) |
| { |
| $this->namespaceFallbacks = $dirs; |
| } |
| |
| /** |
| * Registers the directory to use as a fallback for class prefixes. |
| * |
| * @param array $dirs An array of directories |
| * |
| * @api |
| */ |
| public function registerPrefixFallbacks(array $dirs) |
| { |
| $this->prefixFallbacks = $dirs; |
| } |
| |
| /** |
| * Registers an array of namespaces |
| * |
| * @param array $namespaces An array of namespaces (namespaces as keys and locations as values) |
| * |
| * @api |
| */ |
| public function registerNamespaces(array $namespaces) |
| { |
| foreach ($namespaces as $namespace => $locations) { |
| $this->namespaces[$namespace] = (array) $locations; |
| } |
| } |
| |
| /** |
| * Registers a namespace. |
| * |
| * @param string $namespace The namespace |
| * @param array|string $paths The location(s) of the namespace |
| * |
| * @api |
| */ |
| public function registerNamespace($namespace, $paths) |
| { |
| $this->namespaces[$namespace] = (array) $paths; |
| } |
| |
| /** |
| * Registers an array of classes using the PEAR naming convention. |
| * |
| * @param array $classes An array of classes (prefixes as keys and locations as values) |
| * |
| * @api |
| */ |
| public function registerPrefixes(array $classes) |
| { |
| foreach ($classes as $prefix => $locations) { |
| $this->prefixes[$prefix] = (array) $locations; |
| } |
| } |
| |
| /** |
| * Registers a set of classes using the PEAR naming convention. |
| * |
| * @param string $prefix The classes prefix |
| * @param array|string $paths The location(s) of the classes |
| * |
| * @api |
| */ |
| public function registerPrefix($prefix, $paths) |
| { |
| $this->prefixes[$prefix] = (array) $paths; |
| } |
| |
| /** |
| * Registers this instance as an autoloader. |
| * |
| * @param Boolean $prepend Whether to prepend the autoloader or not |
| * |
| * @api |
| */ |
| public function register($prepend = false) |
| { |
| spl_autoload_register(array($this, 'loadClass'), true, $prepend); |
| } |
| |
| /** |
| * Loads the given class or interface. |
| * |
| * @param string $class The name of the class |
| */ |
| public function loadClass($class) |
| { |
| if ($file = $this->findFile($class)) { |
| require $file; |
| } |
| } |
| |
| /** |
| * Finds the path to the file where the class is defined. |
| * |
| * @param string $class The name of the class |
| * |
| * @return string|null The path, if found |
| */ |
| public function findFile($class) |
| { |
| if ('\\' == $class[0]) { |
| $class = substr($class, 1); |
| } |
| |
| if (false !== $pos = strrpos($class, '\\')) { |
| // namespaced class name |
| $namespace = substr($class, 0, $pos); |
| $className = substr($class, $pos + 1); |
| $normalizedClass = str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $className).'.php'; |
| foreach ($this->namespaces as $ns => $dirs) { |
| if (0 !== strpos($namespace, $ns)) { |
| continue; |
| } |
| |
| foreach ($dirs as $dir) { |
| $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass; |
| if (is_file($file)) { |
| return $file; |
| } |
| } |
| } |
| |
| foreach ($this->namespaceFallbacks as $dir) { |
| $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass; |
| if (is_file($file)) { |
| return $file; |
| } |
| } |
| |
| } else { |
| // PEAR-like class name |
| $normalizedClass = str_replace('_', DIRECTORY_SEPARATOR, $class).'.php'; |
| foreach ($this->prefixes as $prefix => $dirs) { |
| if (0 !== strpos($class, $prefix)) { |
| continue; |
| } |
| |
| foreach ($dirs as $dir) { |
| $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass; |
| if (is_file($file)) { |
| return $file; |
| } |
| } |
| } |
| |
| foreach ($this->prefixFallbacks as $dir) { |
| $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass; |
| if (is_file($file)) { |
| return $file; |
| } |
| } |
| } |
| |
| if ($this->useIncludePath && $file = stream_resolve_include_path($normalizedClass)) { |
| return $file; |
| } |
| } |
| } |