Skip to content
This repository has been archived by the owner on Jan 30, 2020. It is now read-only.

Commit

Permalink
Merge branch 'master' of git://git.zendframework.com/zf
Browse files Browse the repository at this point in the history
  • Loading branch information
Shahar Evron committed Oct 6, 2011
Show file tree
Hide file tree
Showing 25 changed files with 683 additions and 42 deletions.
89 changes: 65 additions & 24 deletions src/AutoloaderFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
* @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 AutoloaderFactory
abstract class AutoloaderFactory
{
/**
* @var array All autoloaders registered using the factory
Expand All @@ -42,15 +42,6 @@ class AutoloaderFactory
*/
protected static $standardAutoloader;

/**
* Not meant to be instantiable
*
* @return void
*/
private function __construct()
{
}

/**
* Factory for autoloaders
*
Expand Down Expand Up @@ -84,21 +75,23 @@ public static function factory($options)
throw new Exception\InvalidArgumentException('Options provided must be an array or Traversable');
}

foreach ($options as $class => $opts) {
if (!class_exists($class)) {
$autoloader = self::getStandardAutoloader();
foreach ($options as $class => $options) {
if (!isset(static::$loaders[$class])) {
$autoloader = static::getStandardAutoloader();
if (!class_exists($class) && !$autoloader->autoload($class)) {
require_once 'Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException(sprintf('Autoloader class "%s" not loaded', $class));
}
if ($class === 'Zend\Loader\StandardAutoloader') {
$autoloader->setOptions($options);
} else {
$autoloader = new $class($options);
}
$autoloader->register();
static::$loaders[$class] = $autoloader;
} else {
static::$loaders[$class]->setOptions($options);
}
$loader = new $class($opts);
if (!$loader instanceof SplAutoloader) {
require_once 'Exception/DomainException.php';
throw new Exception\DomainException(sprintf('Autoloader class "%s" does not implement Zend\Loader\SplAutoloader', $class));
}
$loader->register();
self::$loaders[] = new $loader;
}
}

Expand All @@ -114,6 +107,54 @@ public static function getRegisteredAutoloaders()
return static::$loaders;
}

/**
* Retrieves an autoloader by class name
*
* @param string $class
* @return SplAutoloader
* @throws Exception\InvalidArgumentException for non-registered class
*/
public static function getRegisteredAutoloader($class)
{
if (!isset(static::$loaders[$class])) {
require_once 'Exception/InvalidArgumentException.php';
throw new Exception\InvalidArgumentException(sprintf('Autoloader class "%s" not loaded', $class));
}
return static::$loaders[$class];
}

/**
* Unregisters all autoloaders that have been registered via the factory.
* This will NOT unregister autoloaders registered outside of the fctory.
*
* @return void
*/
public static function unregisterAutoloaders()
{
foreach (static::getRegisteredAutoloaders() as $class => $autoloader) {
spl_autoload_unregister(array($autoloader, 'autoload'));
unset(static::$loaders[$class]);
}
}

/**
* Unregister a single autoloader by class name
*
* @param string $autoloaderClass
* @return bool
*/
public static function unregisterAutoloader($autoloaderClass)
{
if (!isset(static::$loaders[$autoloaderClass])) {
return false;
}

$autoloader = static::$loaders[$autoloaderClass];
spl_autoload_unregister(array($autoloader, 'autoload'));
unset(static::$loaders[$autoloaderClass]);
return true;
}

/**
* Get an instance of the standard autoloader
*
Expand All @@ -125,14 +166,14 @@ public static function getRegisteredAutoloaders()
*/
protected static function getStandardAutoloader()
{
if (null !== self::$standardAutoloader) {
return self::$standardAutoloader;
if (null !== static::$standardAutoloader) {
return static::$standardAutoloader;
}

require_once __DIR__ . '/StandardAutoloader.php';
$loader = new StandardAutoloader();
$loader->setFallbackAutoloader(true);
self::$standardAutoloader = $loader;
return self::$standardAutoloader;
static::$standardAutoloader = $loader;
return static::$standardAutoloader;
}
}
2 changes: 1 addition & 1 deletion src/ClassMapAutoloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ public function getAutoloadMap()
public function autoload($class)
{
if (isset($this->map[$class])) {
include $this->map[$class];
require_once $this->map[$class];
}
}

Expand Down
188 changes: 188 additions & 0 deletions src/ModuleAutoloader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
<?php

namespace Zend\Loader;

use SplFileInfo,
Traversable;

class ModuleAutoloader implements SplAutoloader
{
/**
* @var array An array of module paths to scan
*/
protected $paths = array();

/**
* Constructor
*
* Allow configuration of the autoloader via the constructor.
*
* @param null|array|Traversable $options
* @return void
*/
public function __construct($options = null)
{
if (null !== $options) {
$this->setOptions($options);
}
}

/**
* Configure the autoloader
*
* In most cases, $options should be either an associative array or
* Traversable object.
*
* @param array|Traversable $options
* @return SplAutoloader
*/
public function setOptions($options)
{
$this->registerPaths($options);
return $this;
}

/**
* Autoload a class
*
* @param $class
* @return mixed
* False [if unable to load $class]
* get_class($class) [if $class is successfully loaded]
*/
public function autoload($class)
{
// Limit scope of this autoloader
if (substr($class, -7) !== '\Module') {
return false;
}
$moduleClassPath = str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';

foreach ($this->paths as $path) {
$file = new SplFileInfo($path . $moduleClassPath);
if ($file->isReadable()) {
// Found directory with Module.php in it
require_once $file->getRealPath();
return $class;
}
// No directory with Module.php, searching for phars
$moduleName = substr($class, 0, strpos($class, '\\'));

// Find executable phars
$matches = glob($path . $moduleName . '.{phar,phar.gz,phar.bz2,phar.tar,phar.tar.gz,phar.tar.bz2,phar.zip}', GLOB_BRACE);
$executable = true;
if (count($matches) == 0) {
$matches = glob($path . $moduleName . '.{tar,tar.gz,tar.bz2,zip}', GLOB_BRACE);
$executable = false;
}
foreach ($matches as $phar) {
$file = new SplFileInfo($phar);
if ($file->isReadable() && $file->isFile()) {
if ($executable) {
// First see if the stub makes the Module class available
require_once $file->getRealPath();
if (class_exists($class)) {
return $class;
}
}
// No stub, or stub did not provide Module class; try Module.php directly
$moduleClassFile = 'phar://' . $file->getRealPath() . '/Module.php';
$file = new SplFileInfo($moduleClassFile);
if ($file->isReadable() && $file->isFile()) {
require_once $moduleClassFile;
if (class_exists($class)) {
return $class;
}
}
}
}
}
return false;
}

/**
* Register the autoloader with spl_autoload registry
*
* @return void
*/
public function register()
{
spl_autoload_register(array($this, 'autoload'));
}

/**
* Unregister the autoloader with spl_autoload registry
*
* @return void
*/
public function unregister()
{
$test = spl_autoload_unregister(array($this, 'autoload'));
}

/**
* registerPaths
*
* @param array|Traversable $paths
* @return ModuleLoader
*/
public function registerPaths($paths)
{
if (is_array($paths) || $paths instanceof Traversable) {
foreach ($paths as $path) {
$this->registerPath($path);
}
} else {
throw new \InvalidArgumentException(
'Parameter to \\Zend\\Loader\\ModuleAutoloader\'s '
. 'registerPaths method must be an array or '
. 'implement the \\Traversable interface'
);
}
return $this;
}

/**
* registerPath
*
* @param string $path
* @return ModuleLoader
*/
public function registerPath($path)
{
if (!is_string($path)) {
throw new \InvalidArgumentException(sprintf(
'Invalid path provided; must be a string, received %s',
gettype($path)
));
}
$this->paths[] = static::normalizePath($path);
return $this;
}

/**
* getPaths
*
* This is primarily for unit testing, but could have other uses.
*
* @return array
*/
public function getPaths()
{
return $this->paths;
}

/**
* Normalize a path for insertion in the stack
*
* @param string $path
* @return string
*/
public static function normalizePath($path)
{
$path = rtrim($path, '/');
$path = rtrim($path, '\\');
$path .= DIRECTORY_SEPARATOR;
return $path;
}
}
Loading

0 comments on commit fab8e06

Please sign in to comment.