Chris@0: .
Chris@0: */
Chris@0:
Chris@0: namespace Doctrine\Common;
Chris@0:
Chris@0: /**
Chris@0: * A ClassLoader is an autoloader for class files that can be
Chris@0: * installed on the SPL autoload stack. It is a class loader that either loads only classes
Chris@0: * of a specific namespace or all namespaces and it is suitable for working together
Chris@0: * with other autoloaders in the SPL autoload stack.
Chris@0: *
Chris@0: * If no include path is configured through the constructor or {@link setIncludePath}, a ClassLoader
Chris@0: * relies on the PHP include_path
.
Chris@0: *
Chris@0: * @author Roman Borschel
Chris@0: * @since 2.0
Chris@0: *
Chris@0: * @deprecated the ClassLoader is deprecated and will be removed in version 3.0 of doctrine/common.
Chris@0: */
Chris@0: class ClassLoader
Chris@0: {
Chris@0: /**
Chris@0: * PHP file extension.
Chris@0: *
Chris@0: * @var string
Chris@0: */
Chris@0: protected $fileExtension = '.php';
Chris@0:
Chris@0: /**
Chris@0: * Current namespace.
Chris@0: *
Chris@0: * @var string|null
Chris@0: */
Chris@0: protected $namespace;
Chris@0:
Chris@0: /**
Chris@0: * Current include path.
Chris@0: *
Chris@0: * @var string|null
Chris@0: */
Chris@0: protected $includePath;
Chris@0:
Chris@0: /**
Chris@0: * PHP namespace separator.
Chris@0: *
Chris@0: * @var string
Chris@0: */
Chris@0: protected $namespaceSeparator = '\\';
Chris@0:
Chris@0: /**
Chris@0: * Creates a new ClassLoader that loads classes of the
Chris@0: * specified namespace from the specified include path.
Chris@0: *
Chris@0: * If no include path is given, the ClassLoader relies on the PHP include_path.
Chris@0: * If neither a namespace nor an include path is given, the ClassLoader will
Chris@0: * be responsible for loading all classes, thereby relying on the PHP include_path.
Chris@0: *
Chris@0: * @param string|null $ns The namespace of the classes to load.
Chris@0: * @param string|null $includePath The base include path to use.
Chris@0: */
Chris@0: public function __construct($ns = null, $includePath = null)
Chris@0: {
Chris@0: $this->namespace = $ns;
Chris@0: $this->includePath = $includePath;
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Sets the namespace separator used by classes in the namespace of this ClassLoader.
Chris@0: *
Chris@0: * @param string $sep The separator to use.
Chris@0: *
Chris@0: * @return void
Chris@0: */
Chris@0: public function setNamespaceSeparator($sep)
Chris@0: {
Chris@0: $this->namespaceSeparator = $sep;
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Gets the namespace separator used by classes in the namespace of this ClassLoader.
Chris@0: *
Chris@0: * @return string
Chris@0: */
Chris@0: public function getNamespaceSeparator()
Chris@0: {
Chris@0: return $this->namespaceSeparator;
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Sets the base include path for all class files in the namespace of this ClassLoader.
Chris@0: *
Chris@0: * @param string|null $includePath
Chris@0: *
Chris@0: * @return void
Chris@0: */
Chris@0: public function setIncludePath($includePath)
Chris@0: {
Chris@0: $this->includePath = $includePath;
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Gets the base include path for all class files in the namespace of this ClassLoader.
Chris@0: *
Chris@0: * @return string|null
Chris@0: */
Chris@0: public function getIncludePath()
Chris@0: {
Chris@0: return $this->includePath;
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Sets the file extension of class files in the namespace of this ClassLoader.
Chris@0: *
Chris@0: * @param string $fileExtension
Chris@0: *
Chris@0: * @return void
Chris@0: */
Chris@0: public function setFileExtension($fileExtension)
Chris@0: {
Chris@0: $this->fileExtension = $fileExtension;
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Gets the file extension of class files in the namespace of this ClassLoader.
Chris@0: *
Chris@0: * @return string
Chris@0: */
Chris@0: public function getFileExtension()
Chris@0: {
Chris@0: return $this->fileExtension;
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Registers this ClassLoader on the SPL autoload stack.
Chris@0: *
Chris@0: * @return void
Chris@0: */
Chris@0: public function register()
Chris@0: {
Chris@0: spl_autoload_register([$this, 'loadClass']);
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Removes this ClassLoader from the SPL autoload stack.
Chris@0: *
Chris@0: * @return void
Chris@0: */
Chris@0: public function unregister()
Chris@0: {
Chris@0: spl_autoload_unregister([$this, 'loadClass']);
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Loads the given class or interface.
Chris@0: *
Chris@0: * @param string $className The name of the class to load.
Chris@0: *
Chris@0: * @return boolean TRUE if the class has been successfully loaded, FALSE otherwise.
Chris@0: */
Chris@0: public function loadClass($className)
Chris@0: {
Chris@0: if (self::typeExists($className)) {
Chris@0: return true;
Chris@0: }
Chris@0:
Chris@0: if (! $this->canLoadClass($className)) {
Chris@0: return false;
Chris@0: }
Chris@0:
Chris@0: require ($this->includePath !== null ? $this->includePath . DIRECTORY_SEPARATOR : '')
Chris@0: . str_replace($this->namespaceSeparator, DIRECTORY_SEPARATOR, $className)
Chris@0: . $this->fileExtension;
Chris@0:
Chris@0: return self::typeExists($className);
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Asks this ClassLoader whether it can potentially load the class (file) with
Chris@0: * the given name.
Chris@0: *
Chris@0: * @param string $className The fully-qualified name of the class.
Chris@0: *
Chris@0: * @return boolean TRUE if this ClassLoader can load the class, FALSE otherwise.
Chris@0: */
Chris@0: public function canLoadClass($className)
Chris@0: {
Chris@0: if ($this->namespace !== null && strpos($className, $this->namespace.$this->namespaceSeparator) !== 0) {
Chris@0: return false;
Chris@0: }
Chris@0:
Chris@0: $file = str_replace($this->namespaceSeparator, DIRECTORY_SEPARATOR, $className) . $this->fileExtension;
Chris@0:
Chris@0: if ($this->includePath !== null) {
Chris@0: return is_file($this->includePath . DIRECTORY_SEPARATOR . $file);
Chris@0: }
Chris@0:
Chris@0: return (false !== stream_resolve_include_path($file));
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Checks whether a class with a given name exists. A class "exists" if it is either
Chris@0: * already defined in the current request or if there is an autoloader on the SPL
Chris@0: * autoload stack that is a) responsible for the class in question and b) is able to
Chris@0: * load a class file in which the class definition resides.
Chris@0: *
Chris@0: * If the class is not already defined, each autoloader in the SPL autoload stack
Chris@0: * is asked whether it is able to tell if the class exists. If the autoloader is
Chris@0: * a ClassLoader, {@link canLoadClass} is used, otherwise the autoload
Chris@0: * function of the autoloader is invoked and expected to return a value that
Chris@0: * evaluates to TRUE if the class (file) exists. As soon as one autoloader reports
Chris@0: * that the class exists, TRUE is returned.
Chris@0: *
Chris@0: * Note that, depending on what kinds of autoloaders are installed on the SPL
Chris@0: * autoload stack, the class (file) might already be loaded as a result of checking
Chris@0: * for its existence. This is not the case with a ClassLoader, who separates
Chris@0: * these responsibilities.
Chris@0: *
Chris@0: * @param string $className The fully-qualified name of the class.
Chris@0: *
Chris@0: * @return boolean TRUE if the class exists as per the definition given above, FALSE otherwise.
Chris@0: */
Chris@0: public static function classExists($className)
Chris@0: {
Chris@0: return self::typeExists($className, true);
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Gets the ClassLoader from the SPL autoload stack that is responsible
Chris@0: * for (and is able to load) the class with the given name.
Chris@0: *
Chris@0: * @param string $className The name of the class.
Chris@0: *
Chris@0: * @return ClassLoader The ClassLoader for the class or NULL if no such ClassLoader exists.
Chris@0: */
Chris@0: public static function getClassLoader($className)
Chris@0: {
Chris@0: foreach (spl_autoload_functions() as $loader) {
Chris@0: if (is_array($loader)
Chris@0: && ($classLoader = reset($loader))
Chris@0: && $classLoader instanceof ClassLoader
Chris@0: && $classLoader->canLoadClass($className)
Chris@0: ) {
Chris@0: return $classLoader;
Chris@0: }
Chris@0: }
Chris@0:
Chris@0: return null;
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * Checks whether a given type exists
Chris@0: *
Chris@0: * @param string $type
Chris@0: * @param bool $autoload
Chris@0: *
Chris@0: * @return bool
Chris@0: */
Chris@0: private static function typeExists($type, $autoload = false)
Chris@0: {
Chris@0: return class_exists($type, $autoload)
Chris@0: || interface_exists($type, $autoload)
Chris@0: || trait_exists($type, $autoload);
Chris@0: }
Chris@0: }