|
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 } |