AutoloaderFactory.php 8.0 KB

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