582 Zeilen
		
	
	
	
		
			16 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			582 Zeilen
		
	
	
	
		
			16 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
/**
 | 
						|
 * Zend Framework
 | 
						|
 *
 | 
						|
 * LICENSE
 | 
						|
 *
 | 
						|
 * This source file is subject to the new BSD license that is bundled
 | 
						|
 * with this package in the file LICENSE.txt.
 | 
						|
 * It is also available through the world-wide-web at this URL:
 | 
						|
 * http://framework.zend.com/license/new-bsd
 | 
						|
 * If you did not receive a copy of the license and are unable to
 | 
						|
 * obtain it through the world-wide-web, please send an email
 | 
						|
 * to license@zend.com so we can send you a copy immediately.
 | 
						|
 *
 | 
						|
 * @category   Zend
 | 
						|
 * @package    Zend_Loader
 | 
						|
 * @subpackage Autoloader
 | 
						|
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 | 
						|
 * @version    $Id$
 | 
						|
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 | 
						|
 */
 | 
						|
 | 
						|
/** Zend_Loader */
 | 
						|
require_once 'Zend/Loader.php';
 | 
						|
 | 
						|
/**
 | 
						|
 * Autoloader stack and namespace autoloader
 | 
						|
 *
 | 
						|
 * @uses       Zend_Loader_Autoloader
 | 
						|
 * @package    Zend_Loader
 | 
						|
 * @subpackage Autoloader
 | 
						|
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 | 
						|
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 | 
						|
 */
 | 
						|
class Zend_Loader_Autoloader
 | 
						|
{
 | 
						|
    /**
 | 
						|
     * @var Zend_Loader_Autoloader Singleton instance
 | 
						|
     */
 | 
						|
    protected static $_instance;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var array Concrete autoloader callback implementations
 | 
						|
     */
 | 
						|
    protected $_autoloaders = array();
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var array Default autoloader callback
 | 
						|
     */
 | 
						|
    protected $_defaultAutoloader = array('Zend_Loader', 'loadClass');
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var bool Whether or not to act as a fallback autoloader
 | 
						|
     */
 | 
						|
    protected $_fallbackAutoloader = false;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var array Callback for internal autoloader implementation
 | 
						|
     */
 | 
						|
    protected $_internalAutoloader;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var array Supported namespaces 'Zend' and 'ZendX' by default.
 | 
						|
     */
 | 
						|
    protected $_namespaces = array(
 | 
						|
        'Zend_'  => true,
 | 
						|
        'ZendX_' => true,
 | 
						|
    );
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var array Namespace-specific autoloaders
 | 
						|
     */
 | 
						|
    protected $_namespaceAutoloaders = array();
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var bool Whether or not to suppress file not found warnings
 | 
						|
     */
 | 
						|
    protected $_suppressNotFoundWarnings = false;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var null|string
 | 
						|
     */
 | 
						|
    protected $_zfPath;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Retrieve singleton instance
 | 
						|
     *
 | 
						|
     * @return Zend_Loader_Autoloader
 | 
						|
     */
 | 
						|
    public static function getInstance()
 | 
						|
    {
 | 
						|
        if (null === self::$_instance) {
 | 
						|
            self::$_instance = new self();
 | 
						|
        }
 | 
						|
        return self::$_instance;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Reset the singleton instance
 | 
						|
     *
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public static function resetInstance()
 | 
						|
    {
 | 
						|
        self::$_instance = null;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Autoload a class
 | 
						|
     *
 | 
						|
     * @param  string $class
 | 
						|
     * @return bool
 | 
						|
     */
 | 
						|
    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_array($autoloader)) {
 | 
						|
                if (call_user_func($autoloader, $class)) {
 | 
						|
                    return true;
 | 
						|
                }
 | 
						|
            } elseif (is_string($autoloader) || is_callable($autoloader)) {
 | 
						|
                if ($autoloader($class)) {
 | 
						|
                    return true;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Set the default autoloader implementation
 | 
						|
     *
 | 
						|
     * @param  string|array $callback PHP callback
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function setDefaultAutoloader($callback)
 | 
						|
    {
 | 
						|
        if (!is_callable($callback)) {
 | 
						|
            throw new Zend_Loader_Exception('Invalid callback specified for default autoloader');
 | 
						|
        }
 | 
						|
 | 
						|
        $this->_defaultAutoloader = $callback;
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Retrieve the default autoloader callback
 | 
						|
     *
 | 
						|
     * @return string|array PHP Callback
 | 
						|
     */
 | 
						|
    public function getDefaultAutoloader()
 | 
						|
    {
 | 
						|
        return $this->_defaultAutoloader;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Set several autoloader callbacks at once
 | 
						|
     *
 | 
						|
     * @param  array $autoloaders Array of PHP callbacks (or Zend_Loader_Autoloader_Interface implementations) to act as autoloaders
 | 
						|
     * @return Zend_Loader_Autoloader
 | 
						|
     */
 | 
						|
    public function setAutoloaders(array $autoloaders)
 | 
						|
    {
 | 
						|
        $this->_autoloaders = $autoloaders;
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get attached autoloader implementations
 | 
						|
     *
 | 
						|
     * @return array
 | 
						|
     */
 | 
						|
    public function getAutoloaders()
 | 
						|
    {
 | 
						|
        return $this->_autoloaders;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Return all autoloaders for a given namespace
 | 
						|
     *
 | 
						|
     * @param  string $namespace
 | 
						|
     * @return array
 | 
						|
     */
 | 
						|
    public function getNamespaceAutoloaders($namespace)
 | 
						|
    {
 | 
						|
        $namespace = (string) $namespace;
 | 
						|
        if (!array_key_exists($namespace, $this->_namespaceAutoloaders)) {
 | 
						|
            return array();
 | 
						|
        }
 | 
						|
        return $this->_namespaceAutoloaders[$namespace];
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Register a namespace to autoload
 | 
						|
     *
 | 
						|
     * @param  string|array $namespace
 | 
						|
     * @return Zend_Loader_Autoloader
 | 
						|
     */
 | 
						|
    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;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Unload a registered autoload namespace
 | 
						|
     *
 | 
						|
     * @param  string|array $namespace
 | 
						|
     * @return Zend_Loader_Autoloader
 | 
						|
     */
 | 
						|
    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;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get a list of registered autoload namespaces
 | 
						|
     *
 | 
						|
     * @return array
 | 
						|
     */
 | 
						|
    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;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get or set the value of the "suppress not found warnings" flag
 | 
						|
     *
 | 
						|
     * @param  null|bool $flag
 | 
						|
     * @return bool|Zend_Loader_Autoloader Returns boolean if no argument is passed, object instance otherwise
 | 
						|
     */
 | 
						|
    public function suppressNotFoundWarnings($flag = null)
 | 
						|
    {
 | 
						|
        if (null === $flag) {
 | 
						|
            return $this->_suppressNotFoundWarnings;
 | 
						|
        }
 | 
						|
        $this->_suppressNotFoundWarnings = (bool) $flag;
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Indicate whether or not this autoloader should be a fallback autoloader
 | 
						|
     *
 | 
						|
     * @param  bool $flag
 | 
						|
     * @return Zend_Loader_Autoloader
 | 
						|
     */
 | 
						|
    public function setFallbackAutoloader($flag)
 | 
						|
    {
 | 
						|
        $this->_fallbackAutoloader = (bool) $flag;
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Is this instance acting as a fallback autoloader?
 | 
						|
     *
 | 
						|
     * @return bool
 | 
						|
     */
 | 
						|
    public function isFallbackAutoloader()
 | 
						|
    {
 | 
						|
        return $this->_fallbackAutoloader;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get autoloaders to use when matching class
 | 
						|
     *
 | 
						|
     * Determines if the class matches a registered namespace, and, if so,
 | 
						|
     * returns only the autoloaders for that namespace. Otherwise, it returns
 | 
						|
     * all non-namespaced autoloaders.
 | 
						|
     *
 | 
						|
     * @param  string $class
 | 
						|
     * @return array Array of autoloaders to use
 | 
						|
     */
 | 
						|
    public function getClassAutoloaders($class)
 | 
						|
    {
 | 
						|
        $namespace   = false;
 | 
						|
        $autoloaders = array();
 | 
						|
 | 
						|
        // Add concrete namespaced autoloaders
 | 
						|
        foreach (array_keys($this->_namespaceAutoloaders) as $ns) {
 | 
						|
            if ('' == $ns) {
 | 
						|
                continue;
 | 
						|
            }
 | 
						|
            if (0 === strpos($class, $ns)) {
 | 
						|
                $namespace   = $ns;
 | 
						|
                $autoloaders = $autoloaders + $this->getNamespaceAutoloaders($ns);
 | 
						|
                break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        // Add internal namespaced autoloader
 | 
						|
        foreach ($this->getRegisteredNamespaces() as $ns) {
 | 
						|
            if (0 === strpos($class, $ns)) {
 | 
						|
                $namespace     = $ns;
 | 
						|
                $autoloaders[] = $this->_internalAutoloader;
 | 
						|
                break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        // Add non-namespaced autoloaders
 | 
						|
        $autoloaders = $autoloaders + $this->getNamespaceAutoloaders('');
 | 
						|
 | 
						|
        // Add fallback autoloader
 | 
						|
        if (!$namespace && $this->isFallbackAutoloader()) {
 | 
						|
            $autoloaders[] = $this->_internalAutoloader;
 | 
						|
        }
 | 
						|
 | 
						|
        return $autoloaders;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Add an autoloader to the beginning of the stack
 | 
						|
     *
 | 
						|
     * @param  object|array|string $callback PHP callback or Zend_Loader_Autoloader_Interface implementation
 | 
						|
     * @param  string|array $namespace Specific namespace(s) under which to register callback
 | 
						|
     * @return Zend_Loader_Autoloader
 | 
						|
     */
 | 
						|
    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;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Append an autoloader to the autoloader stack
 | 
						|
     *
 | 
						|
     * @param  object|array|string $callback PHP callback or Zend_Loader_Autoloader_Interface implementation
 | 
						|
     * @param  string|array $namespace Specific namespace(s) under which to register callback
 | 
						|
     * @return Zend_Loader_Autoloader
 | 
						|
     */
 | 
						|
    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;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Remove an autoloader from the autoloader stack
 | 
						|
     *
 | 
						|
     * @param  object|array|string $callback PHP callback or Zend_Loader_Autoloader_Interface implementation
 | 
						|
     * @param  null|string|array $namespace Specific namespace(s) from which to remove autoloader
 | 
						|
     * @return Zend_Loader_Autoloader
 | 
						|
     */
 | 
						|
    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;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Constructor
 | 
						|
     *
 | 
						|
     * Registers instance with spl_autoload stack
 | 
						|
     *
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    protected function __construct()
 | 
						|
    {
 | 
						|
        spl_autoload_register(array(__CLASS__, 'autoload'));
 | 
						|
        $this->_internalAutoloader = array($this, '_autoload');
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Internal autoloader implementation
 | 
						|
     *
 | 
						|
     * @param  string $class
 | 
						|
     * @return bool
 | 
						|
     */
 | 
						|
    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;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Set autoloaders for a specific namespace
 | 
						|
     *
 | 
						|
     * @param  array $autoloaders
 | 
						|
     * @param  string $namespace
 | 
						|
     * @return Zend_Loader_Autoloader
 | 
						|
     */
 | 
						|
    protected function _setNamespaceAutoloaders(array $autoloaders, $namespace = '')
 | 
						|
    {
 | 
						|
        $namespace = (string) $namespace;
 | 
						|
        $this->_namespaceAutoloaders[$namespace] = $autoloaders;
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Retrieve the filesystem path for the requested ZF version
 | 
						|
     *
 | 
						|
     * @param  string $path
 | 
						|
     * @param  string $version
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    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;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Retrieve the ZF version type
 | 
						|
     *
 | 
						|
     * @param  string $version
 | 
						|
     * @return string "latest", "major", "minor", or "specific"
 | 
						|
     * @throws Zend_Loader_Exception if version string contains too many dots
 | 
						|
     */
 | 
						|
    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';
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get available versions for the version type requested
 | 
						|
     *
 | 
						|
     * @param  string $path
 | 
						|
     * @param  string $version
 | 
						|
     * @return array
 | 
						|
     */
 | 
						|
    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 ((array) $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;
 | 
						|
    }
 | 
						|
}
 |