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.
16
* @package Zend_Loader
17
* @subpackage Autoloader
18
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
* @version $Id: Autoloader.php 15508 2009-05-11 03:29:01Z matthew $
20
* @license http://framework.zend.com/license/new-bsd New BSD License
24
require_once 'Zend/Loader.php';
27
* Autoloader stack and namespace autoloader
29
* @uses Zend_Loader_Autoloader
30
* @package Zend_Loader
31
* @subpackage Autoloader
32
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
33
* @license New BSD {@link http://framework.zend.com/license/new-bsd}
35
class Zend_Loader_Autoloader
38
* @var Zend_Loader_Autoloader Singleton instance
40
protected static $_instance;
43
* @var array Concrete autoloader callback implementations
45
protected $_autoloaders = array();
48
* @var array Default autoloader callback
50
protected $_defaultAutoloader = array('Zend_Loader', 'loadClass');
53
* @var bool Whether or not to act as a fallback autoloader
55
protected $_fallbackAutoloader = false;
58
* @var array Callback for internal autoloader implementation
60
protected $_internalAutoloader;
63
* @var array Supported namespaces 'Zend' and 'ZendX' by default.
65
protected $_namespaces = array(
71
* @var array Namespace-specific autoloaders
73
protected $_namespaceAutoloaders = array();
76
* @var bool Whether or not to suppress file not found warnings
78
protected $_suppressNotFoundWarnings = false;
81
* Retrieve singleton instance
83
* @return Zend_Loader_Autoloader
85
public static function getInstance()
87
if (null === self::$_instance) {
88
self::$_instance = new self();
90
return self::$_instance;
94
* Reset the singleton instance
98
public static function resetInstance()
100
self::$_instance = null;
106
* @param string $class
109
public static function autoload($class)
111
$self = self::getInstance();
113
foreach ($self->getClassAutoloaders($class) as $autoloader) {
114
if ($autoloader instanceof Zend_Loader_Autoloader_Interface) {
115
if ($autoloader->autoload($class)) {
118
} elseif (is_string($autoloader)) {
119
if ($autoloader($class)) {
122
} elseif (is_array($autoloader)) {
123
$object = array_shift($autoloader);
124
$method = array_shift($autoloader);
125
if (call_user_func(array($object, $method), $class)) {
135
* Set the default autoloader implementation
137
* @param string|array $callback PHP callback
140
public function setDefaultAutoloader($callback)
142
if (!is_callable($callback)) {
143
throw new Zend_Loader_Exception('Invalid callback specified for default autoloader');
146
$this->_defaultAutoloader = $callback;
151
* Retrieve the default autoloader callback
153
* @return string|array PHP Callback
155
public function getDefaultAutoloader()
157
return $this->_defaultAutoloader;
161
* Set several autoloader callbacks at once
163
* @param array $autoloaders Array of PHP callbacks (or Zend_Loader_Autoloader_Interface implementations) to act as autoloaders
164
* @return Zend_Loader_Autoloader
166
public function setAutoloaders(array $autoloaders)
168
$this->_autoloaders = $autoloaders;
173
* Get attached autoloader implementations
177
public function getAutoloaders()
179
return $this->_autoloaders;
183
* Return all autoloaders for a given namespace
185
* @param string $namespace
188
public function getNamespaceAutoloaders($namespace)
190
$namespace = (string) $namespace;
191
if (!array_key_exists($namespace, $this->_namespaceAutoloaders)) {
194
return $this->_namespaceAutoloaders[$namespace];
198
* Register a namespace to autoload
200
* @param string $namespace
201
* @return Zend_Loader_Autoloader
203
public function registerNamespace($namespace)
205
if (is_string($namespace)) {
206
$namespace = (array) $namespace;
207
} elseif (!is_array($namespace)) {
208
throw new Zend_Loader_Exception('Invalid namespace provided');
211
foreach ($namespace as $ns) {
212
if (!isset($this->_namespaces[$ns])) {
213
$this->_namespaces[$ns] = true;
220
* Unload a registered autoload namespace
222
* @param string $namespace
223
* @return Zend_Loader_Autoloader
225
public function unregisterNamespace($namespace)
227
if (is_string($namespace)) {
228
$namespace = (array) $namespace;
229
} elseif (!is_array($namespace)) {
230
throw new Zend_Loader_Exception('Invalid namespace provided');
233
foreach ($namespace as $ns) {
234
if (isset($this->_namespaces[$ns])) {
235
unset($this->_namespaces[$ns]);
242
* Get a list of registered autoload namespaces
246
public function getRegisteredNamespaces()
248
return array_keys($this->_namespaces);
252
* Get or set the value of the "suppress not found warnings" flag
254
* @param null|bool $flag
255
* @return bool|Zend_Loader_Autoloader Returns boolean if no argument is passed, object instance otherwise
257
public function suppressNotFoundWarnings($flag = null)
259
if (null === $flag) {
260
return $this->_suppressNotFoundWarnings;
262
$this->_suppressNotFoundWarnings = (bool) $flag;
267
* Indicate whether or not this autoloader should be a fallback autoloader
270
* @return Zend_Loader_Autoloader
272
public function setFallbackAutoloader($flag)
274
$this->_fallbackAutoloader = (bool) $flag;
279
* Is this instance acting as a fallback autoloader?
283
public function isFallbackAutoloader()
285
return $this->_fallbackAutoloader;
289
* Get autoloaders to use when matching class
291
* Determines if the class matches a registered namespace, and, if so,
292
* returns only the autoloaders for that namespace. Otherwise, it returns
293
* all non-namespaced autoloaders.
295
* @param string $class
296
* @return array Array of autoloaders to use
298
public function getClassAutoloaders($class)
301
$autoloaders = array();
303
// Add concrete namespaced autoloaders
304
foreach (array_keys($this->_namespaceAutoloaders) as $ns) {
308
if (0 === strpos($class, $ns)) {
310
$autoloaders = $autoloaders + $this->getNamespaceAutoloaders($ns);
315
// Add internal namespaced autoloader
316
foreach ($this->getRegisteredNamespaces() as $ns) {
317
if (0 === strpos($class, $ns)) {
319
$autoloaders[] = $this->_internalAutoloader;
324
// Add non-namespaced autoloaders
325
$autoloaders = $autoloaders + $this->getNamespaceAutoloaders('');
327
// Add fallback autoloader
328
if (!$namespace && $this->isFallbackAutoloader()) {
329
$autoloaders[] = $this->_internalAutoloader;
336
* Add an autoloader to the beginning of the stack
338
* @param object|array|string $callback PHP callback or Zend_Loader_Autoloader_Interface implementation
339
* @param string|array $namespace Specific namespace(s) under which to register callback
340
* @return Zend_Loader_Autoloader
342
public function unshiftAutoloader($callback, $namespace = '')
344
$autoloaders = $this->getAutoloaders();
345
array_unshift($autoloaders, $callback);
346
$this->setAutoloaders($autoloaders);
348
$namespace = (array) $namespace;
349
foreach ($namespace as $ns) {
350
$autoloaders = $this->getNamespaceAutoloaders($ns);
351
array_unshift($autoloaders, $callback);
352
$this->_setNamespaceAutoloaders($autoloaders, $ns);
359
* Append an autoloader to the autoloader stack
361
* @param object|array|string $callback PHP callback or Zend_Loader_Autoloader_Interface implementation
362
* @param string|array $namespace Specific namespace(s) under which to register callback
363
* @return Zend_Loader_Autoloader
365
public function pushAutoloader($callback, $namespace = '')
367
$autoloaders = $this->getAutoloaders();
368
array_push($autoloaders, $callback);
369
$this->setAutoloaders($autoloaders);
371
$namespace = (array) $namespace;
372
foreach ($namespace as $ns) {
373
$autoloaders = $this->getNamespaceAutoloaders($ns);
374
array_push($autoloaders, $callback);
375
$this->_setNamespaceAutoloaders($autoloaders, $ns);
382
* Remove an autoloader from the autoloader stack
384
* @param object|array|string $callback PHP callback or Zend_Loader_Autoloader_Interface implementation
385
* @param null|string|array $namespace Specific namespace(s) from which to remove autoloader
386
* @return Zend_Loader_Autoloader
388
public function removeAutoloader($callback, $namespace = null)
390
if (null === $namespace) {
391
$autoloaders = $this->getAutoloaders();
392
if (false !== ($index = array_search($callback, $autoloaders, true))) {
393
unset($autoloaders[$index]);
394
$this->setAutoloaders($autoloaders);
397
foreach ($this->_namespaceAutoloaders as $ns => $autoloaders) {
398
if (false !== ($index = array_search($callback, $autoloaders, true))) {
399
unset($autoloaders[$index]);
400
$this->_setNamespaceAutoloaders($autoloaders, $ns);
404
$namespace = (array) $namespace;
405
foreach ($namespace as $ns) {
406
$autoloaders = $this->getNamespaceAutoloaders($ns);
407
if (false !== ($index = array_search($callback, $autoloaders, true))) {
408
unset($autoloaders[$index]);
409
$this->_setNamespaceAutoloaders($autoloaders, $ns);
420
* Registers instance with spl_autoload stack
424
protected function __construct()
426
spl_autoload_register(array(__CLASS__, 'autoload'));
427
$this->_internalAutoloader = array($this, '_autoload');
431
* Internal autoloader implementation
433
* @param string $class
436
protected function _autoload($class)
438
$callback = $this->getDefaultAutoloader();
440
if ($this->suppressNotFoundWarnings()) {
441
@call_user_func($callback, $class);
443
call_user_func($callback, $class);
446
} catch (Zend_Exception $e) {
452
* Set autoloaders for a specific namespace
454
* @param array $autoloaders
455
* @param string $namespace
456
* @return Zend_Loader_Autoloader
458
protected function _setNamespaceAutoloaders(array $autoloaders, $namespace = '')
460
$namespace = (string) $namespace;
461
$this->_namespaceAutoloaders[$namespace] = $autoloaders;