web/lib/Zend/Loader/AutoloaderFactory.php
changeset 808 6b6c2214f778
child 1230 68c69c656a2c
equal deleted inserted replaced
807:877f952ae2bd 808:6b6c2214f778
       
     1 <?php
       
     2 /**
       
     3  * Zend Framework
       
     4  *
       
     5  * LICENSE
       
     6  *
       
     7  * This source file is subject to the new BSD license that is bundled
       
     8  * with this package in the file LICENSE.txt.
       
     9  * It is also available through the world-wide-web at this URL:
       
    10  * http://framework.zend.com/license/new-bsd
       
    11  * If you did not receive a copy of the license and are unable to
       
    12  * obtain it through the world-wide-web, please send an email
       
    13  * to license@zend.com so we can send you a copy immediately.
       
    14  *
       
    15  * @category   Zend
       
    16  * @package    Zend_Loader
       
    17  * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
       
    18  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    19  */
       
    20 
       
    21 require_once dirname(__FILE__) . '/SplAutoloader.php';
       
    22 
       
    23 if (class_exists('Zend_Loader_AutoloaderFactory')) return;
       
    24 
       
    25 /**
       
    26  * @package    Zend_Loader
       
    27  * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
       
    28  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    29  */
       
    30 abstract class Zend_Loader_AutoloaderFactory
       
    31 {
       
    32     const STANDARD_AUTOLOADER = 'Zend_Loader_StandardAutoloader';
       
    33 
       
    34     /**
       
    35      * @var array All autoloaders registered using the factory
       
    36      */
       
    37     protected static $loaders = array();
       
    38 
       
    39     /**
       
    40      * @var Zend_Loader_StandardAutoloader StandardAutoloader instance for resolving 
       
    41      * autoloader classes via the include_path
       
    42      */
       
    43     protected static $standardAutoloader;
       
    44 
       
    45     /**
       
    46      * Factory for autoloaders
       
    47      *
       
    48      * Options should be an array or Traversable object of the following structure:
       
    49      * <code>
       
    50      * array(
       
    51      *     '<autoloader class name>' => $autoloaderOptions,
       
    52      * )
       
    53      * </code>
       
    54      *
       
    55      * The factory will then loop through and instantiate each autoloader with
       
    56      * the specified options, and register each with the spl_autoloader.
       
    57      *
       
    58      * You may retrieve the concrete autoloader instances later using
       
    59      * {@link getRegisteredAutoloaders()}.
       
    60      *
       
    61      * Note that the class names must be resolvable on the include_path or via
       
    62      * the Zend library, using PSR-0 rules (unless the class has already been
       
    63      * loaded).
       
    64      *
       
    65      * @param  array|Traversable $options (optional) options to use. Defaults to Zend_Loader_StandardAutoloader
       
    66      * @return void
       
    67      * @throws Zend_Loader_Exception_InvalidArgumentException for invalid options
       
    68      * @throws Zend_Loader_Exception_InvalidArgumentException for unloadable autoloader classes
       
    69      */
       
    70     public static function factory($options = null)
       
    71     {
       
    72         if (null === $options) {
       
    73             if (!isset(self::$loaders[self::STANDARD_AUTOLOADER])) {
       
    74                 $autoloader = self::getStandardAutoloader();
       
    75                 $autoloader->register();
       
    76                 self::$loaders[self::STANDARD_AUTOLOADER] = $autoloader;
       
    77             }
       
    78 
       
    79             // Return so we don't hit the next check's exception (we're done here anyway)
       
    80             return;
       
    81         }
       
    82 
       
    83         if (!is_array($options) && !($options instanceof Traversable)) {
       
    84             require_once 'Exception/InvalidArgumentException.php';
       
    85             throw new Zend_Loader_Exception_InvalidArgumentException(
       
    86                 'Options provided must be an array or Traversable'
       
    87             );
       
    88         }
       
    89 
       
    90         foreach ($options as $class => $options) {
       
    91             if (!isset(self::$loaders[$class])) {
       
    92                 $autoloader = self::getStandardAutoloader();
       
    93                 if (!class_exists($class) && !$autoloader->autoload($class)) {
       
    94                     require_once 'Exception/InvalidArgumentException.php';
       
    95                     throw new Zend_Loader_Exception_InvalidArgumentException(sprintf(
       
    96                         'Autoloader class "%s" not loaded', 
       
    97                         $class
       
    98                     ));
       
    99                 }
       
   100 
       
   101                 // unfortunately is_subclass_of is broken on some 5.3 versions
       
   102                 // additionally instanceof is also broken for this use case
       
   103                 if (version_compare(PHP_VERSION, '5.3.7', '>=')) {
       
   104                         if (!is_subclass_of($class, 'Zend_Loader_SplAutoloader')) {
       
   105                         require_once 'Exception/InvalidArgumentException.php';
       
   106                         throw new Zend_Loader_Exception_InvalidArgumentException(sprintf(
       
   107                             'Autoloader class %s must implement Zend\\Loader\\SplAutoloader', 
       
   108                             $class
       
   109                         ));
       
   110                     }
       
   111                 }
       
   112 
       
   113                 if ($class === self::STANDARD_AUTOLOADER) {
       
   114                     $autoloader->setOptions($options);
       
   115                 } else {
       
   116                     $autoloader = new $class($options);
       
   117                 }
       
   118                 $autoloader->register();
       
   119                 self::$loaders[$class] = $autoloader;
       
   120             } else {
       
   121                 self::$loaders[$class]->setOptions($options);
       
   122             }
       
   123         }
       
   124     }
       
   125 
       
   126     /**
       
   127      * Get an list of all autoloaders registered with the factory
       
   128      *
       
   129      * Returns an array of autoloader instances.
       
   130      *
       
   131      * @return array
       
   132      */
       
   133     public static function getRegisteredAutoloaders()
       
   134     {
       
   135         return self::$loaders;
       
   136     }
       
   137 
       
   138     /**
       
   139      * Retrieves an autoloader by class name
       
   140      *
       
   141      * @param string $class
       
   142      * @return Zend_Loader_SplAutoloader
       
   143      * @throws Zend_Loader_Exception_InvalidArgumentException for non-registered class
       
   144      */
       
   145     public static function getRegisteredAutoloader($class)
       
   146     {
       
   147         if (!isset(self::$loaders[$class])) {
       
   148             require_once 'Exception/InvalidArgumentException.php';
       
   149             throw new Zend_Loader_Exception_InvalidArgumentException(sprintf('Autoloader class "%s" not loaded', $class));
       
   150         }
       
   151         return self::$loaders[$class];
       
   152     }
       
   153 
       
   154     /**
       
   155      * Unregisters all autoloaders that have been registered via the factory.
       
   156      * This will NOT unregister autoloaders registered outside of the fctory.
       
   157      *
       
   158      * @return void
       
   159      */
       
   160     public static function unregisterAutoloaders()
       
   161     {
       
   162         foreach (self::getRegisteredAutoloaders() as $class => $autoloader) {
       
   163             spl_autoload_unregister(array($autoloader, 'autoload'));
       
   164             unset(self::$loaders[$class]);
       
   165         }
       
   166     }
       
   167 
       
   168     /**
       
   169      * Unregister a single autoloader by class name
       
   170      *
       
   171      * @param  string $autoloaderClass
       
   172      * @return bool
       
   173      */
       
   174     public static function unregisterAutoloader($autoloaderClass)
       
   175     {
       
   176         if (!isset(self::$loaders[$autoloaderClass])) {
       
   177             return false;
       
   178         }
       
   179 
       
   180         $autoloader = self::$loaders[$autoloaderClass];
       
   181         spl_autoload_unregister(array($autoloader, 'autoload'));
       
   182         unset(self::$loaders[$autoloaderClass]);
       
   183         return true;
       
   184     }
       
   185 
       
   186     /**
       
   187      * Get an instance of the standard autoloader
       
   188      *
       
   189      * Used to attempt to resolve autoloader classes, using the 
       
   190      * StandardAutoloader. The instance is marked as a fallback autoloader, to 
       
   191      * allow resolving autoloaders not under the "Zend" or "Zend" namespaces.
       
   192      * 
       
   193      * @return Zend_Loader_SplAutoloader
       
   194      */
       
   195     protected static function getStandardAutoloader()
       
   196     {
       
   197         if (null !== self::$standardAutoloader) {
       
   198             return self::$standardAutoloader;
       
   199         }
       
   200 
       
   201         // Extract the filename from the classname
       
   202         $stdAutoloader = substr(strrchr(self::STANDARD_AUTOLOADER, '_'), 1);
       
   203 
       
   204         if (!class_exists(self::STANDARD_AUTOLOADER)) {
       
   205             require_once dirname(__FILE__) . "/$stdAutoloader.php";
       
   206         }
       
   207         $loader = new Zend_Loader_StandardAutoloader();
       
   208         self::$standardAutoloader = $loader;
       
   209         return self::$standardAutoloader;
       
   210     }
       
   211 }