<?php
require_once 'Zend/Loader.php';
class Zend_Loader_Autoloader
{
protected static $_instance;
protected $_autoloaders = array();
protected $_defaultAutoloader = array('Zend_Loader', 'loadClass');
protected $_fallbackAutoloader = false;
protected $_internalAutoloader;
protected $_namespaces = array(
'Zend_' => true,
'ZendX_' => true,
);
protected $_namespaceAutoloaders = array();
protected $_suppressNotFoundWarnings = false;
protected $_zfPath;
public static function getInstance()
{
if (null === self::$_instance) {
self::$_instance = new self();
}
return self::$_instance;
}
public static function resetInstance()
{
self::$_instance = null;
}
public static function autoload($class)
{
$self = self::getInstance();
foreach ($self->getClassAutoloaders($class) as $autoloader) {
if ($autoloader instanceof Zend_Loader_Autoloader_Interface) {
if ($autoloader->autoload($class)) {
return true;
}
} elseif (is_string($autoloader)) {
if ($autoloader($class)) {
return true;
}
} elseif (is_array($autoloader)) {
$object = array_shift($autoloader);
$method = array_shift($autoloader);
if (call_user_func(array($object, $method), $class)) {
return true;
}
}
}
return false;
}
public function setDefaultAutoloader($callback)
{
if (!is_callable($callback)) {
throw new Zend_Loader_Exception('Invalid callback specified for default autoloader');
}
$this->_defaultAutoloader = $callback;
return $this;
}
public function getDefaultAutoloader()
{
return $this->_defaultAutoloader;
}
public function setAutoloaders(array $autoloaders)
{
$this->_autoloaders = $autoloaders;
return $this;
}
public function getAutoloaders()
{
return $this->_autoloaders;
}
public function getNamespaceAutoloaders($namespace)
{
$namespace = (string) $namespace;
if (!array_key_exists($namespace, $this->_namespaceAutoloaders)) {
return array();
}
return $this->_namespaceAutoloaders[$namespace];
}
public function registerNamespace($namespace)
{
if (is_string($namespace)) {
$namespace = (array) $namespace;
} elseif (!is_array($namespace)) {
throw new Zend_Loader_Exception('Invalid namespace provided');
}
foreach ($namespace as $ns) {
if (!isset($this->_namespaces[$ns])) {
$this->_namespaces[$ns] = true;
}
}
return $this;
}
public function unregisterNamespace($namespace)
{
if (is_string($namespace)) {
$namespace = (array) $namespace;
} elseif (!is_array($namespace)) {
throw new Zend_Loader_Exception('Invalid namespace provided');
}
foreach ($namespace as $ns) {
if (isset($this->_namespaces[$ns])) {
unset($this->_namespaces[$ns]);
}
}
return $this;
}
public function getRegisteredNamespaces()
{
return array_keys($this->_namespaces);
}
public function setZfPath($spec, $version = 'latest')
{
$path = $spec;
if (is_array($spec)) {
if (!isset($spec['path'])) {
throw new Zend_Loader_Exception('No path specified for ZF');
}
$path = $spec['path'];
if (isset($spec['version'])) {
$version = $spec['version'];
}
}
$this->_zfPath = $this->_getVersionPath($path, $version);
set_include_path(implode(PATH_SEPARATOR, array(
$this->_zfPath,
get_include_path(),
)));
return $this;
}
public function getZfPath()
{
return $this->_zfPath;
}
public function suppressNotFoundWarnings($flag = null)
{
if (null === $flag) {
return $this->_suppressNotFoundWarnings;
}
$this->_suppressNotFoundWarnings = (bool) $flag;
return $this;
}
public function setFallbackAutoloader($flag)
{
$this->_fallbackAutoloader = (bool) $flag;
return $this;
}
public function isFallbackAutoloader()
{
return $this->_fallbackAutoloader;
}
public function getClassAutoloaders($class)
{
$namespace = false;
$autoloaders = array();
foreach (array_keys($this->_namespaceAutoloaders) as $ns) {
if ('' == $ns) {
continue;
}
if (0 === strpos($class, $ns)) {
$namespace = $ns;
$autoloaders = $autoloaders + $this->getNamespaceAutoloaders($ns);
break;
}
}
foreach ($this->getRegisteredNamespaces() as $ns) {
if (0 === strpos($class, $ns)) {
$namespace = $ns;
$autoloaders[] = $this->_internalAutoloader;
break;
}
}
$autoloaders = $autoloaders + $this->getNamespaceAutoloaders('');
if (!$namespace && $this->isFallbackAutoloader()) {
$autoloaders[] = $this->_internalAutoloader;
}
return $autoloaders;
}
public function unshiftAutoloader($callback, $namespace = '')
{
$autoloaders = $this->getAutoloaders();
array_unshift($autoloaders, $callback);
$this->setAutoloaders($autoloaders);
$namespace = (array) $namespace;
foreach ($namespace as $ns) {
$autoloaders = $this->getNamespaceAutoloaders($ns);
array_unshift($autoloaders, $callback);
$this->_setNamespaceAutoloaders($autoloaders, $ns);
}
return $this;
}
public function pushAutoloader($callback, $namespace = '')
{
$autoloaders = $this->getAutoloaders();
array_push($autoloaders, $callback);
$this->setAutoloaders($autoloaders);
$namespace = (array) $namespace;
foreach ($namespace as $ns) {
$autoloaders = $this->getNamespaceAutoloaders($ns);
array_push($autoloaders, $callback);
$this->_setNamespaceAutoloaders($autoloaders, $ns);
}
return $this;
}
public function removeAutoloader($callback, $namespace = null)
{
if (null === $namespace) {
$autoloaders = $this->getAutoloaders();
if (false !== ($index = array_search($callback, $autoloaders, true))) {
unset($autoloaders[$index]);
$this->setAutoloaders($autoloaders);
}
foreach ($this->_namespaceAutoloaders as $ns => $autoloaders) {
if (false !== ($index = array_search($callback, $autoloaders, true))) {
unset($autoloaders[$index]);
$this->_setNamespaceAutoloaders($autoloaders, $ns);
}
}
} else {
$namespace = (array) $namespace;
foreach ($namespace as $ns) {
$autoloaders = $this->getNamespaceAutoloaders($ns);
if (false !== ($index = array_search($callback, $autoloaders, true))) {
unset($autoloaders[$index]);
$this->_setNamespaceAutoloaders($autoloaders, $ns);
}
}
}
return $this;
}
protected function __construct()
{
spl_autoload_register(array(__CLASS__, 'autoload'));
$this->_internalAutoloader = array($this, '_autoload');
}
protected function _autoload($class)
{
$callback = $this->getDefaultAutoloader();
try {
if ($this->suppressNotFoundWarnings()) {
@call_user_func($callback, $class);
} else {
call_user_func($callback, $class);
}
return $class;
} catch (Zend_Exception $e) {
return false;
}
}
protected function _setNamespaceAutoloaders(array $autoloaders, $namespace = '')
{
$namespace = (string) $namespace;
$this->_namespaceAutoloaders[$namespace] = $autoloaders;
return $this;
}
protected function _getVersionPath($path, $version)
{
$type = $this->_getVersionType($version);
if ($type == 'latest') {
$version = 'latest';
}
$availableVersions = $this->_getAvailableVersions($path, $version);
if (empty($availableVersions)) {
throw new Zend_Loader_Exception('No valid ZF installations discovered');
}
$matchedVersion = array_pop($availableVersions);
return $matchedVersion;
}
protected function _getVersionType($version)
{
if (strtolower($version) == 'latest') {
return 'latest';
}
$parts = explode('.', $version);
$count = count($parts);
if (1 == $count) {
return 'major';
}
if (2 == $count) {
return 'minor';
}
if (3 < $count) {
throw new Zend_Loader_Exception('Invalid version string provided');
}
return 'specific';
}
protected function _getAvailableVersions($path, $version)
{
if (!is_dir($path)) {
throw new Zend_Loader_Exception('Invalid ZF path provided');
}
$path = rtrim($path, '/');
$path = rtrim($path, '\\');
$versionLen = strlen($version);
$versions = array();
$dirs = glob("$path/*", GLOB_ONLYDIR);
foreach ($dirs as $dir) {
$dirName = substr($dir, strlen($path) + 1);
if (!preg_match('/^(?:ZendFramework-)?(\d+\.\d+\.\d+((a|b|pl|pr|p|rc)\d+)?)(?:-minimal)?$/i', $dirName, $matches)) {
continue;
}
$matchedVersion = $matches[1];
if (('latest' == $version)
|| ((strlen($matchedVersion) >= $versionLen)
&& (0 === strpos($matchedVersion, $version)))
) {
$versions[$matchedVersion] = $dir . '/library';
}
}
uksort($versions, 'version_compare');
return $versions;
}
}