Skip to content

Commit

Permalink
[Foundation] updated the autoloader, added a new one
Browse files Browse the repository at this point in the history
  • Loading branch information
fabpot committed Jan 13, 2010
1 parent a0551d5 commit a1d2230
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 57 deletions.
75 changes: 18 additions & 57 deletions src/Symfony/Foundation/ClassLoader.php
Expand Up @@ -15,7 +15,7 @@
* ClassLoader implementation that implements the technical interoperability
* standards for PHP 5.3 namespaces and class names.
*
* Based on http://groups.google.com/group/php-standards/web/final-proposal
* Based on http://groups.google.com/group/php-standards/web/psr-0-final-proposal
*
* Example usage:
*
Expand All @@ -42,19 +42,7 @@ class ClassLoader
*/
public function registerNamespace($namespace, $includePath = null)
{
if (!isset($this->namespaces[$namespace]))
{
$this->namespaces[$namespace] = $includePath;
}
else
{
if (!is_array($this->namespaces[$namespace]))
{
$this->namespaces[$namespace] = array($this->namespaces[$namespace]);
}

$this->namespaces[$namespace][] = $includePath;
}
$this->namespaces[$namespace] = $includePath;
}

/**
Expand All @@ -65,14 +53,6 @@ public function register()
spl_autoload_register(array($this, 'loadClass'));
}

/**
* Uninstalls this class loader from the SPL autoloader stack.
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
}

/**
* Loads the given class or interface.
*
Expand All @@ -81,43 +61,24 @@ public function unregister()
public function loadClass($className)
{
$vendor = substr($className, 0, stripos($className, '\\'));
if ($vendor || isset($this->namespaces['']))
if (!isset($this->namespaces[$vendor]))
{
$fileName = '';
$namespace = '';
if (false !== ($lastNsPos = strripos($className, '\\')))
{
$namespace = substr($className, 0, $lastNsPos);
$className = substr($className, $lastNsPos + 1);
$fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR;
}
$fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className).'.php';

if (null !== $this->namespaces[$vendor])
{
if (is_array($this->namespaces[$vendor]))
{
foreach ($this->namespaces[$vendor] as $dir)
{
if (!file_exists($dir.DIRECTORY_SEPARATOR.$fileName))
{
continue;
}

require $dir.DIRECTORY_SEPARATOR.$fileName;
return;
}

break;
}
}
else
{
require $this->namespaces[$vendor].DIRECTORY_SEPARATOR.$fileName;
}
}
else
{
require $fileName;
}
if (false !== ($lastNsPos = strripos($className, '\\')))
{
$namespace = substr($className, 0, $lastNsPos);
$className = substr($className, $lastNsPos + 1);
$fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR;
}
else
{
$namespace = '';
$fileName = '';
}
$fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className).'.php';

require $this->namespaces[$vendor].DIRECTORY_SEPARATOR.$fileName;
}
}
147 changes: 147 additions & 0 deletions src/Symfony/Foundation/UniversalClassLoader.php
@@ -0,0 +1,147 @@
<?php

namespace Symfony\Foundation;

/*
* This file is part of the symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

/**
* UniversalClassLoader implements a "universal" autoloder for PHP 5.3.
*
* It is able to load classes that use either:
*
* * The technical interoperability standards for PHP 5.3 namespaces and
* class names (http://groups.google.com/group/php-standards/web/final-proposal);
*
* * The PEAR naming convention for classes (http://pear.php.net/).
*
* Classes from a sub-namespace or a sub-hierarchy of PEAR classes can be
* looked for in a list of locations to ease the vendoring of a sub-set of
* classes for large projects.
*
* Example usage:
*
* $loader = new ClassLoader();
*
* // register classes with namespaces
* $loader->registerNamespaces(array(
* 'Symfony\Components' => __DIR__.'/components',
* 'Symfony' => __DIR__.'/framework',
* ));
*
* // register a library using the PEAR naming convention
* $loader->registerClasses(array(
* 'Swift_' => __DIR__.'/Swift',
* ));
*
* // activate the autoloader
* $loader->register();
*
* In this example, if you try to use a class in the Symfony\Components
* namespace or one of its children (Symfony\Components\Console for instance),
* the autoloader will first look for the class under the components/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* @package symfony
* @subpackage foundation
* @author Fabien Potencier <fabien.potencier@symfony-project.org>
*/
class UniversalClassLoader
{
protected $namespaces = array();
protected $prefixes = array();

/**
* Registers an array of namespaces
*
* @param array $namespaces An array of namespaces (namespaces as keys and locations as values)
*/
public function registerNamespaces(array $namespaces)
{
$this->namespaces = array_merge($this->namespaces, $namespaces);
}

/**
* Registers a namespace.
*
* @param string $namespace The namespace
* @param string $path The location of the namespace
*/
public function registerNamespace($namespace, $path)
{
$this->namespaces[$namespace] = $path;
}

/**
* Registers an array of classes using the PEAR naming convention.
*
* @param array $classes An array of classes (prefixes as keys and locations as values)
*/
public function registerPrefixes(array $classes)
{
$this->prefixes = array_merge($this->prefixes, $classes);
}

/**
* Registers a set of classes using the PEAR naming convention.
*
* @param string $prefix The classes prefix
* @param string $path The location of the classes
*/
public function registerPrefix($prefix, $path)
{
$this->prefixes[$prefix] = $path;
}

/**
* Registers this instance as an autoloader.
*/
public function register()
{
spl_autoload_register(array($this, 'loadClass'));
}

/**
* Loads the given class or interface.
*
* @param string $class The name of the class
*/
public function loadClass($class)
{
if (false !== ($pos = strripos($class, '\\')))
{
// namespaced class name
$namespace = substr($class, 0, $pos);
foreach ($this->namespaces as $ns => $dir)
{
if (0 === strpos($namespace, $ns))
{
$class = substr($class, $pos + 1);
require $dir.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';

return;
}
}
}
else
{
// PEAR-like class name
foreach ($this->prefixes as $prefix => $dir)
{
if (0 === strpos($class, $prefix))
{
require $dir.DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';

return;
}
}
}
}
}

0 comments on commit a1d2230

Please sign in to comment.