File indexing completed on 2024-12-22 05:36:49

0001 <?php
0002 /**
0003  * Zend Framework
0004  *
0005  * LICENSE
0006  *
0007  * This source file is subject to the new BSD license that is bundled
0008  * with this package in the file LICENSE.txt.
0009  * It is also available through the world-wide-web at this URL:
0010  * http://framework.zend.com/license/new-bsd
0011  * If you did not receive a copy of the license and are unable to
0012  * obtain it through the world-wide-web, please send an email
0013  * to license@zend.com so we can send you a copy immediately.
0014  *
0015  * @category   Zend
0016  * @package    Zend_Loader
0017  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0018  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0019  */
0020 
0021 // require_once dirname(__FILE__) . '/SplAutoloader.php';
0022 
0023 if (class_exists('Zend_Loader_AutoloaderFactory')) return;
0024 
0025 /**
0026  * @package    Zend_Loader
0027  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0028  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0029  */
0030 abstract class Zend_Loader_AutoloaderFactory
0031 {
0032     const STANDARD_AUTOLOADER  = 'Zend_Loader_StandardAutoloader';
0033     const CLASS_MAP_AUTOLOADER = 'Zend_Loader_ClassMapAutoloader';
0034 
0035     /**
0036      * @var array All autoloaders registered using the factory
0037      */
0038     protected static $loaders = array();
0039 
0040     /**
0041      * @var Zend_Loader_StandardAutoloader StandardAutoloader instance for resolving 
0042      * autoloader classes via the include_path
0043      */
0044     protected static $standardAutoloader;
0045 
0046     /**
0047      * Factory for autoloaders
0048      *
0049      * Options should be an array or Traversable object of the following structure:
0050      * <code>
0051      * array(
0052      *     '<autoloader class name>' => $autoloaderOptions,
0053      * )
0054      * </code>
0055      *
0056      * The factory will then loop through and instantiate each autoloader with
0057      * the specified options, and register each with the spl_autoloader.
0058      *
0059      * You may retrieve the concrete autoloader instances later using
0060      * {@link getRegisteredAutoloaders()}.
0061      *
0062      * Note that the class names must be resolvable on the include_path or via
0063      * the Zend library, using PSR-0 rules (unless the class has already been
0064      * loaded).
0065      *
0066      * @param  array|Traversable $options (optional) options to use. Defaults to Zend_Loader_StandardAutoloader
0067      * @return void
0068      * @throws Zend_Loader_Exception_InvalidArgumentException for invalid options
0069      * @throws Zend_Loader_Exception_InvalidArgumentException for unloadable autoloader classes
0070      */
0071     public static function factory($options = null)
0072     {
0073         if (null === $options) {
0074             if (!isset(self::$loaders[self::STANDARD_AUTOLOADER])) {
0075                 $autoloader = self::getStandardAutoloader();
0076                 $autoloader->register();
0077                 self::$loaders[self::STANDARD_AUTOLOADER] = $autoloader;
0078             }
0079 
0080             // Return so we don't hit the next check's exception (we're done here anyway)
0081             return;
0082         }
0083 
0084         if (!is_array($options) && !($options instanceof Traversable)) {
0085             // require_once 'Exception/InvalidArgumentException.php';
0086             throw new Zend_Loader_Exception_InvalidArgumentException(
0087                 'Options provided must be an array or Traversable'
0088             );
0089         }
0090 
0091         foreach ($options as $class => $options) {
0092             if (!isset(self::$loaders[$class])) {
0093                 // Check class map autoloader
0094                 if ($class == self::CLASS_MAP_AUTOLOADER) {
0095                     if (!class_exists(self::CLASS_MAP_AUTOLOADER)) {
0096                         // Extract the filename from the classname
0097                         $classMapLoader = substr(
0098                             strrchr(self::CLASS_MAP_AUTOLOADER, '_'), 1
0099                         );
0100 
0101                         // require_once dirname(__FILE__) . "/$classMapLoader.php";
0102                     }
0103                 }
0104 
0105                 // Autoload with standard autoloader
0106                 $autoloader = self::getStandardAutoloader();
0107                 if (!class_exists($class) && !$autoloader->autoload($class)) {
0108                     // require_once 'Exception/InvalidArgumentException.php';
0109                     throw new Zend_Loader_Exception_InvalidArgumentException(sprintf(
0110                         'Autoloader class "%s" not loaded', 
0111                         $class
0112                     ));
0113                 }
0114 
0115                 // unfortunately is_subclass_of is broken on some 5.3 versions
0116                 // additionally instanceof is also broken for this use case
0117                 if (version_compare(PHP_VERSION, '5.3.7', '>=')) {
0118                         if (!is_subclass_of($class, 'Zend_Loader_SplAutoloader')) {
0119                         // require_once 'Exception/InvalidArgumentException.php';
0120                         throw new Zend_Loader_Exception_InvalidArgumentException(sprintf(
0121                             'Autoloader class %s must implement Zend\\Loader\\SplAutoloader', 
0122                             $class
0123                         ));
0124                     }
0125                 }
0126 
0127                 if ($class === self::STANDARD_AUTOLOADER) {
0128                     $autoloader->setOptions($options);
0129                 } else {
0130                     $autoloader = new $class($options);
0131                 }
0132                 $autoloader->register();
0133                 self::$loaders[$class] = $autoloader;
0134             } else {
0135                 self::$loaders[$class]->setOptions($options);
0136             }
0137         }
0138     }
0139 
0140     /**
0141      * Get an list of all autoloaders registered with the factory
0142      *
0143      * Returns an array of autoloader instances.
0144      *
0145      * @return array
0146      */
0147     public static function getRegisteredAutoloaders()
0148     {
0149         return self::$loaders;
0150     }
0151 
0152     /**
0153      * Retrieves an autoloader by class name
0154      *
0155      * @param string $class
0156      * @return Zend_Loader_SplAutoloader
0157      * @throws Zend_Loader_Exception_InvalidArgumentException for non-registered class
0158      */
0159     public static function getRegisteredAutoloader($class)
0160     {
0161         if (!isset(self::$loaders[$class])) {
0162             // require_once 'Exception/InvalidArgumentException.php';
0163             throw new Zend_Loader_Exception_InvalidArgumentException(sprintf('Autoloader class "%s" not loaded', $class));
0164         }
0165         return self::$loaders[$class];
0166     }
0167 
0168     /**
0169      * Unregisters all autoloaders that have been registered via the factory.
0170      * This will NOT unregister autoloaders registered outside of the fctory.
0171      *
0172      * @return void
0173      */
0174     public static function unregisterAutoloaders()
0175     {
0176         foreach (self::getRegisteredAutoloaders() as $class => $autoloader) {
0177             spl_autoload_unregister(array($autoloader, 'autoload'));
0178             unset(self::$loaders[$class]);
0179         }
0180     }
0181 
0182     /**
0183      * Unregister a single autoloader by class name
0184      *
0185      * @param  string $autoloaderClass
0186      * @return bool
0187      */
0188     public static function unregisterAutoloader($autoloaderClass)
0189     {
0190         if (!isset(self::$loaders[$autoloaderClass])) {
0191             return false;
0192         }
0193 
0194         $autoloader = self::$loaders[$autoloaderClass];
0195         spl_autoload_unregister(array($autoloader, 'autoload'));
0196         unset(self::$loaders[$autoloaderClass]);
0197         return true;
0198     }
0199 
0200     /**
0201      * Get an instance of the standard autoloader
0202      *
0203      * Used to attempt to resolve autoloader classes, using the 
0204      * StandardAutoloader. The instance is marked as a fallback autoloader, to 
0205      * allow resolving autoloaders not under the "Zend" or "Zend" namespaces.
0206      * 
0207      * @return Zend_Loader_SplAutoloader
0208      */
0209     protected static function getStandardAutoloader()
0210     {
0211         if (null !== self::$standardAutoloader) {
0212             return self::$standardAutoloader;
0213         }
0214 
0215         // Extract the filename from the classname
0216         $stdAutoloader = substr(strrchr(self::STANDARD_AUTOLOADER, '_'), 1);
0217 
0218         if (!class_exists(self::STANDARD_AUTOLOADER)) {
0219             // require_once dirname(__FILE__) . "/$stdAutoloader.php";
0220         }
0221         $loader = new Zend_Loader_StandardAutoloader();
0222         self::$standardAutoloader = $loader;
0223         return self::$standardAutoloader;
0224     }
0225 }