mirror of
https://github.com/symfony/class-loader.git
synced 2026-03-24 09:12:18 +01:00
Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
39a9bc391d | ||
|
|
d3b0938fa2 | ||
|
|
3acea26b17 | ||
|
|
732b31a9fe | ||
|
|
afb83252cb | ||
|
|
b321e4830b | ||
|
|
343414e2a5 | ||
|
|
e971e40b45 | ||
|
|
dd8c297b91 | ||
|
|
26de2f175f | ||
|
|
142de518bf | ||
|
|
8a70d1963f | ||
|
|
18d1b5e575 | ||
|
|
181f15a84f | ||
|
|
0a5217edb6 | ||
|
|
e5f3ef7ebd | ||
|
|
77f69969b1 | ||
|
|
8478872572 | ||
|
|
622d370a07 | ||
|
|
827c54ee98 | ||
|
|
7ffb15eeff | ||
|
|
fa3394c6fd | ||
|
|
5e53d66ce8 | ||
|
|
db283a5469 | ||
|
|
dcee47cd55 | ||
|
|
d1e0a27c9c | ||
|
|
aeef488005 | ||
|
|
44c1b7bb7c | ||
|
|
8bff32cf48 | ||
|
|
1c37a180ab | ||
|
|
1fe171b104 | ||
|
|
40585c3fec | ||
|
|
a474c6ead0 | ||
|
|
dc06308090 | ||
|
|
58cfa84f7d | ||
|
|
a61d4e81cd | ||
|
|
e69dbce5e1 | ||
|
|
d482b15c7a | ||
|
|
bcf4926ca7 | ||
|
|
f7c749435b | ||
|
|
66599a59d7 | ||
|
|
50b9d9501e | ||
|
|
e9e73907ef | ||
|
|
f75698ef2a | ||
|
|
5f9dc90230 | ||
|
|
0730d0f8f9 | ||
|
|
18fab536be | ||
|
|
c6d6082c7c | ||
|
|
329e3c07fd | ||
|
|
439c25836a | ||
|
|
cddda216d0 | ||
|
|
107c3efbd8 | ||
|
|
171fa40ebb | ||
|
|
5a119c3862 | ||
|
|
2d1cdaebc9 | ||
|
|
8a43fc467a | ||
|
|
1d40164f58 | ||
|
|
438613c948 | ||
|
|
969e077c5a | ||
|
|
f291c7b0a9 | ||
|
|
cd3c46b051 | ||
|
|
6d7411ecce | ||
|
|
10a8db6444 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
vendor/
|
||||
composer.lock
|
||||
phpunit.xml
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Symfony\Component\ClassLoader;
|
||||
* ApcClassLoader implements a wrapping autoloader cached in APC for PHP 5.3.
|
||||
*
|
||||
* It expects an object implementing a findFile method to find the file. This
|
||||
* allow using it as a wrapper around the other loaders of the component (the
|
||||
* allows using it as a wrapper around the other loaders of the component (the
|
||||
* ClassLoader and the UniversalClassLoader for instance) but also around any
|
||||
* other autoloader following this convention (the Composer one for instance)
|
||||
*
|
||||
@@ -42,34 +42,44 @@ namespace Symfony\Component\ClassLoader;
|
||||
class ApcClassLoader
|
||||
{
|
||||
private $prefix;
|
||||
private $classFinder;
|
||||
|
||||
/**
|
||||
* The class loader object being decorated.
|
||||
*
|
||||
* @var object
|
||||
* A class loader object that implements the findFile() method.
|
||||
*/
|
||||
protected $decorated;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $prefix A prefix to create a namespace in APC
|
||||
* @param object $classFinder An object that implements findFile() method.
|
||||
* @param string $prefix The APC namespace prefix to use.
|
||||
* @param object $decorated A class loader object that implements the findFile() method.
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function __construct($prefix, $classFinder)
|
||||
public function __construct($prefix, $decorated)
|
||||
{
|
||||
if (!extension_loaded('apc')) {
|
||||
throw new \RuntimeException('Unable to use ApcClassLoader as APC is not enabled.');
|
||||
}
|
||||
|
||||
if (!method_exists($classFinder, 'findFile')) {
|
||||
if (!method_exists($decorated, 'findFile')) {
|
||||
throw new \InvalidArgumentException('The class finder must implement a "findFile" method.');
|
||||
}
|
||||
|
||||
$this->prefix = $prefix;
|
||||
$this->classFinder = $classFinder;
|
||||
$this->decorated = $decorated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param Boolean $prepend Whether to prepend the autoloader or not
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
@@ -89,7 +99,7 @@ class ApcClassLoader
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return Boolean|null True, if loaded
|
||||
* @return bool|null True, if loaded
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
@@ -110,9 +120,17 @@ class ApcClassLoader
|
||||
public function findFile($class)
|
||||
{
|
||||
if (false === $file = apc_fetch($this->prefix.$class)) {
|
||||
apc_store($this->prefix.$class, $file = $this->classFinder->findFile($class));
|
||||
apc_store($this->prefix.$class, $file = $this->decorated->findFile($class));
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Passes through all unknown calls onto the decorated object.
|
||||
*/
|
||||
public function __call($method, $args)
|
||||
{
|
||||
return call_user_func_array(array($this->decorated, $method), $args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,8 @@ class ApcUniversalClassLoader extends UniversalClassLoader
|
||||
*
|
||||
* @param string $prefix A prefix to create a namespace in APC
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function __construct($prefix)
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
2.3.0
|
||||
-----
|
||||
|
||||
* added a WinCacheClassLoader for WinCache
|
||||
|
||||
2.1.0
|
||||
-----
|
||||
|
||||
|
||||
@@ -28,8 +28,8 @@ class ClassCollectionLoader
|
||||
* @param array $classes An array of classes to load
|
||||
* @param string $cacheDir A cache directory
|
||||
* @param string $name The cache name prefix
|
||||
* @param Boolean $autoReload Whether to flush the cache when the cache is stale or not
|
||||
* @param Boolean $adaptive Whether to remove already declared classes or not
|
||||
* @param bool $autoReload Whether to flush the cache when the cache is stale or not
|
||||
* @param bool $adaptive Whether to remove already declared classes or not
|
||||
* @param string $extension File extension of the resulting file
|
||||
*
|
||||
* @throws \InvalidArgumentException When class can't be loaded
|
||||
@@ -63,7 +63,7 @@ class ClassCollectionLoader
|
||||
// auto-reload
|
||||
$reload = false;
|
||||
if ($autoReload) {
|
||||
$metadata = $cacheDir.'/'.$name.$extension.'.meta';
|
||||
$metadata = $cache.'.meta';
|
||||
if (!is_file($metadata) || !is_file($cache)) {
|
||||
$reload = true;
|
||||
} else {
|
||||
@@ -104,14 +104,14 @@ class ClassCollectionLoader
|
||||
|
||||
$c = preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', file_get_contents($class->getFileName()));
|
||||
|
||||
// add namespace declaration for global code
|
||||
// fakes namespace declaration for global code
|
||||
if (!$class->inNamespace()) {
|
||||
$c = "\nnamespace\n{\n".self::stripComments($c)."\n}\n";
|
||||
} else {
|
||||
$c = self::fixNamespaceDeclarations('<?php '.$c);
|
||||
$c = preg_replace('/^\s*<\?php/', '', $c);
|
||||
$c = "\nnamespace\n{\n".$c."\n}\n";
|
||||
}
|
||||
|
||||
$c = self::fixNamespaceDeclarations('<?php '.$c);
|
||||
$c = preg_replace('/^\s*<\?php/', '', $c);
|
||||
|
||||
$content .= $c;
|
||||
}
|
||||
|
||||
@@ -144,45 +144,79 @@ class ClassCollectionLoader
|
||||
return $source;
|
||||
}
|
||||
|
||||
$rawChunk = '';
|
||||
$output = '';
|
||||
$inNamespace = false;
|
||||
$tokens = token_get_all($source);
|
||||
|
||||
for ($i = 0, $max = count($tokens); $i < $max; $i++) {
|
||||
$token = $tokens[$i];
|
||||
for (reset($tokens); false !== $token = current($tokens); next($tokens)) {
|
||||
if (is_string($token)) {
|
||||
$output .= $token;
|
||||
$rawChunk .= $token;
|
||||
} elseif (in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) {
|
||||
// strip comments
|
||||
continue;
|
||||
} elseif (T_NAMESPACE === $token[0]) {
|
||||
if ($inNamespace) {
|
||||
$output .= "}\n";
|
||||
$rawChunk .= "}\n";
|
||||
}
|
||||
$output .= $token[1];
|
||||
$rawChunk .= $token[1];
|
||||
|
||||
// namespace name and whitespaces
|
||||
while (($t = $tokens[++$i]) && is_array($t) && in_array($t[0], array(T_WHITESPACE, T_NS_SEPARATOR, T_STRING))) {
|
||||
$output .= $t[1];
|
||||
while (($t = next($tokens)) && is_array($t) && in_array($t[0], array(T_WHITESPACE, T_NS_SEPARATOR, T_STRING))) {
|
||||
$rawChunk .= $t[1];
|
||||
}
|
||||
if (is_string($t) && '{' === $t) {
|
||||
if ('{' === $t) {
|
||||
$inNamespace = false;
|
||||
--$i;
|
||||
prev($tokens);
|
||||
} else {
|
||||
$output = rtrim($output);
|
||||
$output .= "\n{";
|
||||
$rawChunk = rtrim($rawChunk)."\n{";
|
||||
$inNamespace = true;
|
||||
}
|
||||
} elseif (T_START_HEREDOC === $token[0]) {
|
||||
$output .= self::compressCode($rawChunk).$token[1];
|
||||
do {
|
||||
$token = next($tokens);
|
||||
$output .= is_string($token) ? $token : $token[1];
|
||||
} while ($token[0] !== T_END_HEREDOC);
|
||||
$output .= "\n";
|
||||
$rawChunk = '';
|
||||
} elseif (T_CONSTANT_ENCAPSED_STRING === $token[0]) {
|
||||
$output .= self::compressCode($rawChunk).$token[1];
|
||||
$rawChunk = '';
|
||||
} else {
|
||||
$output .= $token[1];
|
||||
$rawChunk .= $token[1];
|
||||
}
|
||||
}
|
||||
|
||||
if ($inNamespace) {
|
||||
$output .= "}\n";
|
||||
$rawChunk .= "}\n";
|
||||
}
|
||||
|
||||
return $output;
|
||||
return $output.self::compressCode($rawChunk);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is only useful for testing.
|
||||
*/
|
||||
public static function enableTokenizer($bool)
|
||||
{
|
||||
self::$useTokenizer = (bool) $bool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips leading & trailing ws, multiple EOL, multiple ws.
|
||||
*
|
||||
* @param string $code Original PHP code
|
||||
*
|
||||
* @return string compressed code
|
||||
*/
|
||||
private static function compressCode($code)
|
||||
{
|
||||
return preg_replace(
|
||||
array('/^\s+/m', '/\s+$/m', '/([\n\r]+ *[\n\r]+)+/', '/[ \t]+/'),
|
||||
array('', '', "\n", ' '),
|
||||
$code
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -205,43 +239,12 @@ class ClassCollectionLoader
|
||||
throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $file));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes comments from a PHP source string.
|
||||
*
|
||||
* We don't use the PHP php_strip_whitespace() function
|
||||
* as we want the content to be readable and well-formatted.
|
||||
*
|
||||
* @param string $source A PHP string
|
||||
*
|
||||
* @return string The PHP string with the comments removed
|
||||
*/
|
||||
private static function stripComments($source)
|
||||
{
|
||||
if (!function_exists('token_get_all')) {
|
||||
return $source;
|
||||
}
|
||||
|
||||
$output = '';
|
||||
foreach (token_get_all($source) as $token) {
|
||||
if (is_string($token)) {
|
||||
$output .= $token;
|
||||
} elseif (!in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) {
|
||||
$output .= $token[1];
|
||||
}
|
||||
}
|
||||
|
||||
// replace multiple new lines with a single newline
|
||||
$output = preg_replace(array('/\s+$/Sm', '/\n+/S'), "\n", $output);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an ordered array of passed classes including all their dependencies.
|
||||
*
|
||||
* @param array $classes
|
||||
*
|
||||
* @return array An array of sorted \ReflectionClass instances (dependencies added if needed)
|
||||
* @return \ReflectionClass[] An array of sorted \ReflectionClass instances (dependencies added if needed)
|
||||
*
|
||||
* @throws \InvalidArgumentException When a class can't be loaded
|
||||
*/
|
||||
@@ -278,17 +281,19 @@ class ClassCollectionLoader
|
||||
array_unshift($classes, $parent);
|
||||
}
|
||||
|
||||
$traits = array();
|
||||
|
||||
if (function_exists('get_declared_traits')) {
|
||||
foreach ($classes as $c) {
|
||||
foreach (self::getTraits($c) as $trait) {
|
||||
self::$seen[$trait->getName()] = true;
|
||||
|
||||
array_unshift($classes, $trait);
|
||||
foreach (self::resolveDependencies(self::computeTraitDeps($c), $c) as $trait) {
|
||||
if ($trait !== $c) {
|
||||
$traits[] = $trait;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array_merge(self::getInterfaces($class), $classes);
|
||||
return array_merge(self::getInterfaces($class), $traits, $classes);
|
||||
}
|
||||
|
||||
private static function getInterfaces(\ReflectionClass $class)
|
||||
@@ -308,26 +313,55 @@ class ClassCollectionLoader
|
||||
return $classes;
|
||||
}
|
||||
|
||||
private static function getTraits(\ReflectionClass $class)
|
||||
private static function computeTraitDeps(\ReflectionClass $class)
|
||||
{
|
||||
$traits = $class->getTraits();
|
||||
$classes = array();
|
||||
$deps = array($class->getName() => $traits);
|
||||
while ($trait = array_pop($traits)) {
|
||||
if ($trait->isUserDefined() && !isset(self::$seen[$trait->getName()])) {
|
||||
$classes[] = $trait;
|
||||
|
||||
$traits = array_merge($traits, $trait->getTraits());
|
||||
self::$seen[$trait->getName()] = true;
|
||||
$traitDeps = $trait->getTraits();
|
||||
$deps[$trait->getName()] = $traitDeps;
|
||||
$traits = array_merge($traits, $traitDeps);
|
||||
}
|
||||
}
|
||||
|
||||
return $classes;
|
||||
return $deps;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is only useful for testing.
|
||||
* Dependencies resolution.
|
||||
*
|
||||
* This function does not check for circular dependencies as it should never
|
||||
* occur with PHP traits.
|
||||
*
|
||||
* @param array $tree The dependency tree
|
||||
* @param \ReflectionClass $node The node
|
||||
* @param \ArrayObject $resolved An array of already resolved dependencies
|
||||
* @param \ArrayObject $unresolved An array of dependencies to be resolved
|
||||
*
|
||||
* @return \ArrayObject The dependencies for the given node
|
||||
*
|
||||
* @throws \RuntimeException if a circular dependency is detected
|
||||
*/
|
||||
public static function enableTokenizer($bool)
|
||||
private static function resolveDependencies(array $tree, $node, \ArrayObject $resolved = null, \ArrayObject $unresolved = null)
|
||||
{
|
||||
self::$useTokenizer = (Boolean) $bool;
|
||||
if (null === $resolved) {
|
||||
$resolved = new \ArrayObject();
|
||||
}
|
||||
if (null === $unresolved) {
|
||||
$unresolved = new \ArrayObject();
|
||||
}
|
||||
$nodeName = $node->getName();
|
||||
$unresolved[$nodeName] = $node;
|
||||
foreach ($tree[$nodeName] as $dependency) {
|
||||
if (!$resolved->offsetExists($dependency->getName())) {
|
||||
self::resolveDependencies($tree, $dependency, $resolved, $unresolved);
|
||||
}
|
||||
}
|
||||
$resolved[$nodeName] = $node;
|
||||
unset($unresolved[$nodeName]);
|
||||
|
||||
return $resolved;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ class ClassLoader
|
||||
/**
|
||||
* Turns on searching the include for class files.
|
||||
*
|
||||
* @param Boolean $useIncludePath
|
||||
* @param bool $useIncludePath
|
||||
*/
|
||||
public function setUseIncludePath($useIncludePath)
|
||||
{
|
||||
@@ -114,7 +114,7 @@ class ClassLoader
|
||||
* Can be used to check if the autoloader uses the include path to check
|
||||
* for classes.
|
||||
*
|
||||
* @return Boolean
|
||||
* @return bool
|
||||
*/
|
||||
public function getUseIncludePath()
|
||||
{
|
||||
@@ -124,7 +124,7 @@ class ClassLoader
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param Boolean $prepend Whether to prepend the autoloader or not
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
@@ -144,7 +144,7 @@ class ClassLoader
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return Boolean|null True, if loaded
|
||||
* @return bool|null True, if loaded
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
@@ -164,13 +164,9 @@ class ClassLoader
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
if ('\\' == $class[0]) {
|
||||
$class = substr($class, 1);
|
||||
}
|
||||
|
||||
if (false !== $pos = strrpos($class, '\\')) {
|
||||
// namespaced class name
|
||||
$classPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $pos)) . DIRECTORY_SEPARATOR;
|
||||
$classPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $pos)).DIRECTORY_SEPARATOR;
|
||||
$className = substr($class, $pos + 1);
|
||||
} else {
|
||||
// PEAR-like class name
|
||||
@@ -178,21 +174,21 @@ class ClassLoader
|
||||
$className = $class;
|
||||
}
|
||||
|
||||
$classPath .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
|
||||
$classPath .= str_replace('_', DIRECTORY_SEPARATOR, $className).'.php';
|
||||
|
||||
foreach ($this->prefixes as $prefix => $dirs) {
|
||||
if (0 === strpos($class, $prefix)) {
|
||||
if ($class === strstr($class, $prefix)) {
|
||||
foreach ($dirs as $dir) {
|
||||
if (file_exists($dir . DIRECTORY_SEPARATOR . $classPath)) {
|
||||
return $dir . DIRECTORY_SEPARATOR . $classPath;
|
||||
if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) {
|
||||
return $dir.DIRECTORY_SEPARATOR.$classPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->fallbackDirs as $dir) {
|
||||
if (file_exists($dir . DIRECTORY_SEPARATOR . $classPath)) {
|
||||
return $dir . DIRECTORY_SEPARATOR . $classPath;
|
||||
if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) {
|
||||
return $dir.DIRECTORY_SEPARATOR.$classPath;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
|
||||
namespace Symfony\Component\ClassLoader;
|
||||
|
||||
if (!defined('T_TRAIT')) {
|
||||
define('T_TRAIT', 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* ClassMapGenerator
|
||||
*
|
||||
@@ -39,7 +43,7 @@ class ClassMapGenerator
|
||||
/**
|
||||
* Iterate over all files in the given directory searching for classes
|
||||
*
|
||||
* @param Iterator|string $dir The directory to search in or an iterator
|
||||
* @param \Iterator|string $dir The directory to search in or an iterator
|
||||
*
|
||||
* @return array A class map array
|
||||
*/
|
||||
@@ -67,7 +71,6 @@ class ClassMapGenerator
|
||||
foreach ($classes as $class) {
|
||||
$map[$class] = $path;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $map;
|
||||
@@ -84,7 +87,6 @@ class ClassMapGenerator
|
||||
{
|
||||
$contents = file_get_contents($path);
|
||||
$tokens = token_get_all($contents);
|
||||
$T_TRAIT = version_compare(PHP_VERSION, '5.4', '<') ? -1 : T_TRAIT;
|
||||
|
||||
$classes = array();
|
||||
|
||||
@@ -111,7 +113,7 @@ class ClassMapGenerator
|
||||
break;
|
||||
case T_CLASS:
|
||||
case T_INTERFACE:
|
||||
case $T_TRAIT:
|
||||
case T_TRAIT:
|
||||
// Find the classname
|
||||
while (($t = $tokens[++$i]) && is_array($t)) {
|
||||
if (T_STRING === $t[0]) {
|
||||
@@ -121,7 +123,7 @@ class ClassMapGenerator
|
||||
}
|
||||
}
|
||||
|
||||
$classes[] = ltrim($namespace . $class, '\\');
|
||||
$classes[] = ltrim($namespace.$class, '\\');
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -86,7 +86,9 @@ class DebugClassLoader
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return Boolean|null True, if loaded
|
||||
* @return bool|null True, if loaded
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
|
||||
@@ -48,7 +48,7 @@ class DebugUniversalClassLoader extends UniversalClassLoader
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2004-2013 Fabien Potencier
|
||||
Copyright (c) 2004-2014 Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -33,7 +33,7 @@ class MapClassLoader
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param Boolean $prepend Whether to prepend the autoloader or not
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
@@ -47,10 +47,6 @@ class MapClassLoader
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ('\\' === $class[0]) {
|
||||
$class = substr($class, 1);
|
||||
}
|
||||
|
||||
if (isset($this->map[$class])) {
|
||||
require $this->map[$class];
|
||||
}
|
||||
@@ -65,10 +61,6 @@ class MapClassLoader
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
if ('\\' === $class[0]) {
|
||||
$class = substr($class, 1);
|
||||
}
|
||||
|
||||
if (isset($this->map[$class])) {
|
||||
return $this->map[$class];
|
||||
}
|
||||
|
||||
@@ -64,9 +64,6 @@ Resources
|
||||
|
||||
You can run the unit tests with the following command:
|
||||
|
||||
phpunit
|
||||
|
||||
If you also want to run the unit tests that depend on other Symfony
|
||||
Components, install dev dependencies before running PHPUnit:
|
||||
|
||||
php composer.phar install --dev
|
||||
$ cd path/to/Symfony/Component/ClassLoader/
|
||||
$ composer.phar install
|
||||
$ phpunit
|
||||
|
||||
@@ -55,15 +55,13 @@ class ApcUniversalClassLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertTrue(class_exists($className), $message);
|
||||
}
|
||||
|
||||
public function getLoadClassTests()
|
||||
{
|
||||
return array(
|
||||
array('\\Apc\\Namespaced\\Foo', '\\Apc\\Namespaced\\Foo', '->loadClass() loads Apc\Namespaced\Foo class'),
|
||||
public function getLoadClassTests()
|
||||
{
|
||||
return array(
|
||||
array('\\Apc\\Namespaced\\Foo', 'Apc\\Namespaced\\Foo', '->loadClass() loads Apc\Namespaced\Foo class'),
|
||||
array('Apc_Pearlike_Foo', 'Apc_Pearlike_Foo', '->loadClass() loads Apc_Pearlike_Foo class'),
|
||||
array('\\Apc\\Namespaced\\Bar', '\\Apc\\Namespaced\\Bar', '->loadClass() loads Apc\Namespaced\Bar class with a leading slash'),
|
||||
array('Apc_Pearlike_Bar', '\\Apc_Pearlike_Bar', '->loadClass() loads Apc_Pearlike_Bar class with a leading slash'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getLoadClassFromFallbackTests
|
||||
@@ -79,15 +77,15 @@ class ApcUniversalClassLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertTrue(class_exists($className), $message);
|
||||
}
|
||||
|
||||
public function getLoadClassFromFallbackTests()
|
||||
{
|
||||
return array(
|
||||
array('\\Apc\\Namespaced\\Baz', '\\Apc\\Namespaced\\Baz', '->loadClass() loads Apc\Namespaced\Baz class'),
|
||||
public function getLoadClassFromFallbackTests()
|
||||
{
|
||||
return array(
|
||||
array('\\Apc\\Namespaced\\Baz', 'Apc\\Namespaced\\Baz', '->loadClass() loads Apc\Namespaced\Baz class'),
|
||||
array('Apc_Pearlike_Baz', 'Apc_Pearlike_Baz', '->loadClass() loads Apc_Pearlike_Baz class'),
|
||||
array('\\Apc\\Namespaced\\FooBar', '\\Apc\\Namespaced\\FooBar', '->loadClass() loads Apc\Namespaced\Baz class from fallback dir'),
|
||||
array('\\Apc\\Namespaced\\FooBar', 'Apc\\Namespaced\\FooBar', '->loadClass() loads Apc\Namespaced\Baz class from fallback dir'),
|
||||
array('Apc_Pearlike_FooBar', 'Apc_Pearlike_FooBar', '->loadClass() loads Apc_Pearlike_Baz class from fallback dir'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getLoadClassNamespaceCollisionTests
|
||||
@@ -102,15 +100,15 @@ class ApcUniversalClassLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertTrue(class_exists($className), $message);
|
||||
}
|
||||
|
||||
public function getLoadClassNamespaceCollisionTests()
|
||||
{
|
||||
return array(
|
||||
public function getLoadClassNamespaceCollisionTests()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
array(
|
||||
'Apc\\NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha',
|
||||
'Apc\\NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta',
|
||||
),
|
||||
'\Apc\NamespaceCollision\A\Foo',
|
||||
'Apc\NamespaceCollision\A\Foo',
|
||||
'->loadClass() loads NamespaceCollision\A\Foo from alpha.',
|
||||
),
|
||||
array(
|
||||
@@ -118,7 +116,7 @@ class ApcUniversalClassLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
'Apc\\NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta',
|
||||
'Apc\\NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha',
|
||||
),
|
||||
'\Apc\NamespaceCollision\A\Bar',
|
||||
'Apc\NamespaceCollision\A\Bar',
|
||||
'->loadClass() loads NamespaceCollision\A\Bar from alpha.',
|
||||
),
|
||||
array(
|
||||
@@ -126,7 +124,7 @@ class ApcUniversalClassLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
'Apc\\NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha',
|
||||
'Apc\\NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta',
|
||||
),
|
||||
'\Apc\NamespaceCollision\A\B\Foo',
|
||||
'Apc\NamespaceCollision\A\B\Foo',
|
||||
'->loadClass() loads NamespaceCollision\A\B\Foo from beta.',
|
||||
),
|
||||
array(
|
||||
@@ -134,11 +132,11 @@ class ApcUniversalClassLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
'Apc\\NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta',
|
||||
'Apc\\NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha',
|
||||
),
|
||||
'\Apc\NamespaceCollision\A\B\Bar',
|
||||
'Apc\NamespaceCollision\A\B\Bar',
|
||||
'->loadClass() loads NamespaceCollision\A\B\Bar from beta.',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getLoadClassPrefixCollisionTests
|
||||
@@ -152,9 +150,9 @@ class ApcUniversalClassLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertTrue(class_exists($className), $message);
|
||||
}
|
||||
|
||||
public function getLoadClassPrefixCollisionTests()
|
||||
{
|
||||
return array(
|
||||
public function getLoadClassPrefixCollisionTests()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
array(
|
||||
'ApcPrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha/Apc',
|
||||
@@ -188,5 +186,5 @@ class ApcUniversalClassLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
'->loadClass() loads ApcPrefixCollision_A_B_Bar from beta.',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,35 @@ require_once __DIR__.'/Fixtures/ClassesWithParents/A.php';
|
||||
|
||||
class ClassCollectionLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testTraitDependencies()
|
||||
{
|
||||
if (version_compare(phpversion(), '5.4', '<')) {
|
||||
$this->markTestSkipped('Requires PHP > 5.4');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
require_once __DIR__.'/Fixtures/deps/traits.php';
|
||||
|
||||
$r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader');
|
||||
$m = $r->getMethod('getOrderedClasses');
|
||||
$m->setAccessible(true);
|
||||
|
||||
$ordered = $m->invoke('Symfony\Component\ClassLoader\ClassCollectionLoader', array('CTFoo'));
|
||||
|
||||
$this->assertEquals(
|
||||
array('TD', 'TC', 'TB', 'TA', 'TZ', 'CTFoo'),
|
||||
array_map(function ($class) { return $class->getName(); }, $ordered)
|
||||
);
|
||||
|
||||
$ordered = $m->invoke('Symfony\Component\ClassLoader\ClassCollectionLoader', array('CTBar'));
|
||||
|
||||
$this->assertEquals(
|
||||
array('TD', 'TZ', 'TC', 'TB', 'TA', 'CTBar'),
|
||||
array_map(function ($class) { return $class->getName(); }, $ordered)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getDifferentOrders
|
||||
*/
|
||||
@@ -71,8 +100,8 @@ class ClassCollectionLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testClassWithTraitsReordering(array $classes)
|
||||
{
|
||||
if (version_compare(phpversion(), '5.4.0', '<')) {
|
||||
$this->markTestSkipped('Requires PHP > 5.4.0.');
|
||||
if (version_compare(phpversion(), '5.4', '<')) {
|
||||
$this->markTestSkipped('Requires PHP > 5.4');
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -86,9 +115,9 @@ class ClassCollectionLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
$expected = array(
|
||||
'ClassesWithParents\\GInterface',
|
||||
'ClassesWithParents\\CInterface',
|
||||
'ClassesWithParents\\CTrait',
|
||||
'ClassesWithParents\\ATrait',
|
||||
'ClassesWithParents\\BTrait',
|
||||
'ClassesWithParents\\CTrait',
|
||||
'ClassesWithParents\\B',
|
||||
'ClassesWithParents\\A',
|
||||
'ClassesWithParents\\D',
|
||||
@@ -125,8 +154,20 @@ class ClassCollectionLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('<?php '.$expected, ClassCollectionLoader::fixNamespaceDeclarations('<?php '.$source));
|
||||
}
|
||||
|
||||
public function getFixNamespaceDeclarationsData()
|
||||
{
|
||||
return array(
|
||||
array("namespace;\nclass Foo {}\n", "namespace\n{\nclass Foo {}\n}"),
|
||||
array("namespace Foo;\nclass Foo {}\n", "namespace Foo\n{\nclass Foo {}\n}"),
|
||||
array("namespace Bar ;\nclass Foo {}\n", "namespace Bar\n{\nclass Foo {}\n}"),
|
||||
array("namespace Foo\Bar;\nclass Foo {}\n", "namespace Foo\Bar\n{\nclass Foo {}\n}"),
|
||||
array("namespace Foo\Bar\Bar\n{\nclass Foo {}\n}\n", "namespace Foo\Bar\Bar\n{\nclass Foo {}\n}"),
|
||||
array("namespace\n{\nclass Foo {}\n}\n", "namespace\n{\nclass Foo {}\n}"),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getFixNamespaceDeclarationsData
|
||||
* @dataProvider getFixNamespaceDeclarationsDataWithoutTokenizer
|
||||
*/
|
||||
public function testFixNamespaceDeclarationsWithoutTokenizer($source, $expected)
|
||||
{
|
||||
@@ -135,7 +176,7 @@ class ClassCollectionLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
ClassCollectionLoader::enableTokenizer(true);
|
||||
}
|
||||
|
||||
public function getFixNamespaceDeclarationsData()
|
||||
public function getFixNamespaceDeclarationsDataWithoutTokenizer()
|
||||
{
|
||||
return array(
|
||||
array("namespace;\nclass Foo {}\n", "namespace\n{\nclass Foo {}\n}\n"),
|
||||
@@ -148,16 +189,72 @@ class ClassCollectionLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testUnableToLoadClassException()
|
||||
{
|
||||
ClassCollectionLoader::load(array('SomeNotExistingClass'), '', 'foo', false);
|
||||
if (is_file($file = sys_get_temp_dir().'/foo.php')) {
|
||||
unlink($file);
|
||||
}
|
||||
|
||||
ClassCollectionLoader::load(array('SomeNotExistingClass'), sys_get_temp_dir(), 'foo', false);
|
||||
}
|
||||
|
||||
public function testLoadTwiceClass()
|
||||
public function testCommentStripping()
|
||||
{
|
||||
ClassCollectionLoader::load(array('Foo'), '', 'foo', false);
|
||||
ClassCollectionLoader::load(array('Foo'), '', 'foo', false);
|
||||
if (is_file($file = sys_get_temp_dir().'/bar.php')) {
|
||||
unlink($file);
|
||||
}
|
||||
spl_autoload_register($r = function ($class) {
|
||||
if (0 === strpos($class, 'Namespaced') || 0 === strpos($class, 'Pearlike_')) {
|
||||
require_once __DIR__.'/Fixtures/'.str_replace(array('\\', '_'), '/', $class).'.php';
|
||||
}
|
||||
});
|
||||
|
||||
ClassCollectionLoader::load(
|
||||
array('Namespaced\\WithComments', 'Pearlike_WithComments'),
|
||||
sys_get_temp_dir(),
|
||||
'bar',
|
||||
false
|
||||
);
|
||||
|
||||
spl_autoload_unregister($r);
|
||||
|
||||
$this->assertEquals(<<<EOF
|
||||
namespace Namespaced
|
||||
{
|
||||
class WithComments
|
||||
{
|
||||
public static \$loaded = true;
|
||||
}
|
||||
\$string ='string shoult not be modified {\$string}';
|
||||
\$heredoc = (<<<HD
|
||||
|
||||
|
||||
Heredoc should not be modified {\$string}
|
||||
|
||||
|
||||
HD
|
||||
);
|
||||
\$nowdoc =<<<'ND'
|
||||
|
||||
|
||||
Nowdoc should not be modified {\$string}
|
||||
|
||||
|
||||
ND
|
||||
;
|
||||
}
|
||||
namespace
|
||||
{
|
||||
class Pearlike_WithComments
|
||||
{
|
||||
public static \$loaded = true;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
, str_replace("<?php \n", '', file_get_contents($file)));
|
||||
|
||||
unlink($file);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,8 +54,6 @@ class ClassLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
return array(
|
||||
array('\\Namespaced2\\Foo', 'Namespaced2\\Foo', '->loadClass() loads Namespaced2\Foo class'),
|
||||
array('\\Pearlike2_Foo', 'Pearlike2_Foo', '->loadClass() loads Pearlike2_Foo class'),
|
||||
array('\\Namespaced2\\Bar', '\\Namespaced2\\Bar', '->loadClass() loads Namespaced2\Bar class with a leading slash'),
|
||||
array('\\Pearlike2_Bar', '\\Pearlike2_Bar', '->loadClass() loads Pearlike2_Bar class with a leading slash'),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -100,7 +98,7 @@ class ClassLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
$loader->setUseIncludePath(true);
|
||||
$this->assertTrue($loader->getUseIncludePath());
|
||||
|
||||
set_include_path(__DIR__.'/Fixtures/includepath' . PATH_SEPARATOR . $includePath);
|
||||
set_include_path(__DIR__.'/Fixtures/includepath'.PATH_SEPARATOR.$includePath);
|
||||
|
||||
$this->assertEquals(__DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.'includepath'.DIRECTORY_SEPARATOR.'Foo.php', $loader->findFile('Foo'));
|
||||
|
||||
|
||||
@@ -72,10 +72,11 @@ class ClassMapGeneratorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
$data = array(
|
||||
array(__DIR__.'/Fixtures/Namespaced', array(
|
||||
'Namespaced\\Bar' => realpath(__DIR__).'/Fixtures/Namespaced/Bar.php',
|
||||
'Namespaced\\Foo' => realpath(__DIR__).'/Fixtures/Namespaced/Foo.php',
|
||||
'Namespaced\\Baz' => realpath(__DIR__).'/Fixtures/Namespaced/Baz.php',
|
||||
)
|
||||
'Namespaced\\Bar' => realpath(__DIR__).'/Fixtures/Namespaced/Bar.php',
|
||||
'Namespaced\\Foo' => realpath(__DIR__).'/Fixtures/Namespaced/Foo.php',
|
||||
'Namespaced\\Baz' => realpath(__DIR__).'/Fixtures/Namespaced/Baz.php',
|
||||
'Namespaced\\WithComments' => realpath(__DIR__).'/Fixtures/Namespaced/WithComments.php',
|
||||
),
|
||||
),
|
||||
array(__DIR__.'/Fixtures/beta/NamespaceCollision', array(
|
||||
'NamespaceCollision\\A\\B\\Bar' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/A/B/Bar.php',
|
||||
@@ -84,9 +85,10 @@ class ClassMapGeneratorTest extends \PHPUnit_Framework_TestCase
|
||||
'NamespaceCollision\\C\\B\\Foo' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/C/B/Foo.php',
|
||||
)),
|
||||
array(__DIR__.'/Fixtures/Pearlike', array(
|
||||
'Pearlike_Foo' => realpath(__DIR__).'/Fixtures/Pearlike/Foo.php',
|
||||
'Pearlike_Bar' => realpath(__DIR__).'/Fixtures/Pearlike/Bar.php',
|
||||
'Pearlike_Baz' => realpath(__DIR__).'/Fixtures/Pearlike/Baz.php',
|
||||
'Pearlike_Foo' => realpath(__DIR__).'/Fixtures/Pearlike/Foo.php',
|
||||
'Pearlike_Bar' => realpath(__DIR__).'/Fixtures/Pearlike/Bar.php',
|
||||
'Pearlike_Baz' => realpath(__DIR__).'/Fixtures/Pearlike/Baz.php',
|
||||
'Pearlike_WithComments' => realpath(__DIR__).'/Fixtures/Pearlike/WithComments.php',
|
||||
)),
|
||||
array(__DIR__.'/Fixtures/classmap', array(
|
||||
'Foo\\Bar\\A' => realpath(__DIR__).'/Fixtures/classmap/sameNsMultipleClasses.php',
|
||||
@@ -123,7 +125,7 @@ class ClassMapGeneratorTest extends \PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
$finder = new \Symfony\Component\Finder\Finder();
|
||||
$finder->files()->in(__DIR__ . '/Fixtures/beta/NamespaceCollision');
|
||||
$finder->files()->in(__DIR__.'/Fixtures/beta/NamespaceCollision');
|
||||
|
||||
$this->assertEqualsNormalized(array(
|
||||
'NamespaceCollision\\A\\B\\Bar' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/A/B/Bar.php',
|
||||
|
||||
@@ -2,4 +2,6 @@
|
||||
|
||||
namespace ClassesWithParents;
|
||||
|
||||
class A extends B {}
|
||||
class A extends B
|
||||
{
|
||||
}
|
||||
|
||||
@@ -2,4 +2,6 @@
|
||||
|
||||
namespace ClassesWithParents;
|
||||
|
||||
class B implements CInterface {}
|
||||
class B implements CInterface
|
||||
{
|
||||
}
|
||||
|
||||
37
Tests/Fixtures/Namespaced/WithComments.php
Normal file
37
Tests/Fixtures/Namespaced/WithComments.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Namespaced;
|
||||
|
||||
class WithComments
|
||||
{
|
||||
/** @Boolean */
|
||||
public static $loaded = true;
|
||||
}
|
||||
|
||||
$string = 'string shoult not be modified {$string}';
|
||||
|
||||
$heredoc = (<<<HD
|
||||
|
||||
|
||||
Heredoc should not be modified {$string}
|
||||
|
||||
|
||||
HD
|
||||
);
|
||||
|
||||
$nowdoc = <<<'ND'
|
||||
|
||||
|
||||
Nowdoc should not be modified {$string}
|
||||
|
||||
|
||||
ND;
|
||||
16
Tests/Fixtures/Pearlike/WithComments.php
Normal file
16
Tests/Fixtures/Pearlike/WithComments.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
class Pearlike_WithComments
|
||||
{
|
||||
/** @Boolean */
|
||||
public static $loaded = true;
|
||||
}
|
||||
@@ -13,5 +13,4 @@ namespace ClassMap;
|
||||
|
||||
class SomeClass extends SomeParent implements SomeInterface
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -13,5 +13,4 @@ namespace ClassMap;
|
||||
|
||||
interface SomeInterface
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -13,5 +13,4 @@ namespace ClassMap;
|
||||
|
||||
abstract class SomeParent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -1,14 +1,24 @@
|
||||
<?php
|
||||
namespace {
|
||||
class A {}
|
||||
class A
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
namespace Alpha {
|
||||
class A {}
|
||||
class B {}
|
||||
class A
|
||||
{
|
||||
}
|
||||
class B
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
namespace Beta {
|
||||
class A {}
|
||||
class B {}
|
||||
class A
|
||||
{
|
||||
}
|
||||
class B
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,5 +11,9 @@
|
||||
|
||||
namespace Foo\Bar;
|
||||
|
||||
class A {}
|
||||
class B {}
|
||||
class A
|
||||
{
|
||||
}
|
||||
class B
|
||||
{
|
||||
}
|
||||
|
||||
37
Tests/Fixtures/deps/traits.php
Normal file
37
Tests/Fixtures/deps/traits.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
trait TD
|
||||
{
|
||||
}
|
||||
|
||||
trait TZ
|
||||
{
|
||||
use TD;
|
||||
}
|
||||
|
||||
trait TC
|
||||
{
|
||||
use TD;
|
||||
}
|
||||
|
||||
trait TB
|
||||
{
|
||||
use TC;
|
||||
}
|
||||
|
||||
trait TA
|
||||
{
|
||||
use TB;
|
||||
}
|
||||
|
||||
class CTFoo
|
||||
{
|
||||
use TA;
|
||||
use TZ;
|
||||
}
|
||||
|
||||
class CTBar
|
||||
{
|
||||
use TZ;
|
||||
use TA;
|
||||
}
|
||||
@@ -25,6 +25,7 @@ namespace Foo {
|
||||
|
||||
class CBar implements IBar
|
||||
{
|
||||
use TBar, TFooBar;
|
||||
use TBar;
|
||||
use TFooBar;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ class UniversalClassLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
$loader = new UniversalClassLoader();
|
||||
$loader->registerNamespace('Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
|
||||
$loader->registerPrefix('Pearlike_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
|
||||
$loader->loadClass($testClassName);
|
||||
$this->assertTrue($loader->loadClass($testClassName));
|
||||
$this->assertTrue(class_exists($className), $message);
|
||||
}
|
||||
|
||||
@@ -32,8 +32,6 @@ class UniversalClassLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
return array(
|
||||
array('\\Namespaced\\Foo', 'Namespaced\\Foo', '->loadClass() loads Namespaced\Foo class'),
|
||||
array('\\Pearlike_Foo', 'Pearlike_Foo', '->loadClass() loads Pearlike_Foo class'),
|
||||
array('\\Namespaced\\Bar', '\\Namespaced\\Bar', '->loadClass() loads Namespaced\Bar class with a leading slash'),
|
||||
array('\\Pearlike_Bar', '\\Pearlike_Bar', '->loadClass() loads Pearlike_Bar class with a leading slash'),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -49,7 +47,7 @@ class UniversalClassLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
$loader->useIncludePath(true);
|
||||
$this->assertTrue($loader->getUseIncludePath());
|
||||
|
||||
set_include_path(__DIR__.'/Fixtures/includepath' . PATH_SEPARATOR . $includePath);
|
||||
set_include_path(__DIR__.'/Fixtures/includepath'.PATH_SEPARATOR.$includePath);
|
||||
|
||||
$this->assertEquals(__DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.'includepath'.DIRECTORY_SEPARATOR.'Foo.php', $loader->findFile('Foo'));
|
||||
|
||||
@@ -92,7 +90,7 @@ class UniversalClassLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
$loader->registerPrefix('Pearlike_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures');
|
||||
$loader->registerNamespaceFallbacks(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/fallback'));
|
||||
$loader->registerPrefixFallbacks(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/fallback'));
|
||||
$loader->loadClass($testClassName);
|
||||
$this->assertTrue($loader->loadClass($testClassName));
|
||||
$this->assertTrue(class_exists($className), $message);
|
||||
}
|
||||
|
||||
@@ -128,7 +126,7 @@ class UniversalClassLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
$loader = new UniversalClassLoader();
|
||||
$loader->registerNamespaces($namespaces);
|
||||
|
||||
$loader->loadClass($className);
|
||||
$this->assertTrue($loader->loadClass($className));
|
||||
$this->assertTrue(class_exists($className), $message);
|
||||
}
|
||||
|
||||
@@ -178,7 +176,7 @@ class UniversalClassLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
$loader = new UniversalClassLoader();
|
||||
$loader->registerPrefixes($prefixes);
|
||||
|
||||
$loader->loadClass($className);
|
||||
$this->assertTrue($loader->loadClass($className));
|
||||
$this->assertTrue(class_exists($className), $message);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
spl_autoload_register(function ($class) {
|
||||
if (0 === strpos(ltrim($class, '/'), 'Symfony\Component\ClassLoader')) {
|
||||
if (file_exists($file = __DIR__.'/../'.substr(str_replace('\\', '/', $class), strlen('Symfony\Component\ClassLoader')).'.php')) {
|
||||
require_once $file;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (file_exists($loader = __DIR__.'/../vendor/autoload.php')) {
|
||||
require_once $loader;
|
||||
}
|
||||
@@ -70,7 +70,7 @@ class UniversalClassLoader
|
||||
* Turns on searching the include for class files. Allows easy loading
|
||||
* of installed PEAR packages
|
||||
*
|
||||
* @param Boolean $useIncludePath
|
||||
* @param bool $useIncludePath
|
||||
*/
|
||||
public function useIncludePath($useIncludePath)
|
||||
{
|
||||
@@ -81,7 +81,7 @@ class UniversalClassLoader
|
||||
* Can be used to check if the autoloader uses the include path to check
|
||||
* for classes.
|
||||
*
|
||||
* @return Boolean
|
||||
* @return bool
|
||||
*/
|
||||
public function getUseIncludePath()
|
||||
{
|
||||
@@ -229,7 +229,7 @@ class UniversalClassLoader
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param Boolean $prepend Whether to prepend the autoloader or not
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
@@ -242,11 +242,15 @@ class UniversalClassLoader
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return bool|null True, if loaded
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
require $file;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,10 +263,6 @@ class UniversalClassLoader
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
if ('\\' == $class[0]) {
|
||||
$class = substr($class, 1);
|
||||
}
|
||||
|
||||
if (false !== $pos = strrpos($class, '\\')) {
|
||||
// namespaced class name
|
||||
$namespace = substr($class, 0, $pos);
|
||||
@@ -287,7 +287,6 @@ class UniversalClassLoader
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// PEAR-like class name
|
||||
$normalizedClass = str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';
|
||||
|
||||
133
WinCacheClassLoader.php
Normal file
133
WinCacheClassLoader.php
Normal file
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\ClassLoader;
|
||||
|
||||
/**
|
||||
* WinCacheClassLoader implements a wrapping autoloader cached in WinCache.
|
||||
*
|
||||
* It expects an object implementing a findFile method to find the file. This
|
||||
* allow using it as a wrapper around the other loaders of the component (the
|
||||
* ClassLoader and the UniversalClassLoader for instance) but also around any
|
||||
* other autoloader following this convention (the Composer one for instance)
|
||||
*
|
||||
* $loader = new ClassLoader();
|
||||
*
|
||||
* // register classes with namespaces
|
||||
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||
* $loader->add('Symfony', __DIR__.'/framework');
|
||||
*
|
||||
* $cachedLoader = new WinCacheClassLoader('my_prefix', $loader);
|
||||
*
|
||||
* // activate the cached autoloader
|
||||
* $cachedLoader->register();
|
||||
*
|
||||
* // eventually deactivate the non-cached loader if it was registered previously
|
||||
* // to be sure to use the cached one.
|
||||
* $loader->unregister();
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Kris Wallsmith <kris@symfony.com>
|
||||
* @author Artem Ryzhkov <artem@smart-core.org>
|
||||
*/
|
||||
class WinCacheClassLoader
|
||||
{
|
||||
private $prefix;
|
||||
|
||||
/**
|
||||
* The class loader object being decorated.
|
||||
*
|
||||
* @var \Symfony\Component\ClassLoader\ClassLoader
|
||||
* A class loader object that implements the findFile() method.
|
||||
*/
|
||||
protected $decorated;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $prefix The WinCache namespace prefix to use.
|
||||
* @param object $decorated A class loader object that implements the findFile() method.
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __construct($prefix, $decorated)
|
||||
{
|
||||
if (!extension_loaded('wincache')) {
|
||||
throw new \RuntimeException('Unable to use WinCacheClassLoader as WinCache is not enabled.');
|
||||
}
|
||||
|
||||
if (!method_exists($decorated, 'findFile')) {
|
||||
throw new \InvalidArgumentException('The class finder must implement a "findFile" method.');
|
||||
}
|
||||
|
||||
$this->prefix = $prefix;
|
||||
$this->decorated = $decorated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this instance as an autoloader.
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return bool|null True, if loaded
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
require $file;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a file by class name while caching lookups to WinCache.
|
||||
*
|
||||
* @param string $class A class name to resolve to file
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
if (false === $file = wincache_ucache_get($this->prefix.$class)) {
|
||||
wincache_ucache_set($this->prefix.$class, $file = $this->decorated->findFile($class), 0);
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Passes through all unknown calls onto the decorated object.
|
||||
*/
|
||||
public function __call($method, $args)
|
||||
{
|
||||
return call_user_func_array(array($this->decorated, $method), $args);
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@
|
||||
namespace Symfony\Component\ClassLoader;
|
||||
|
||||
/**
|
||||
* XcacheClassLoader implements a wrapping autoloader cached in Xcache for PHP 5.3.
|
||||
* XcacheClassLoader implements a wrapping autoloader cached in XCache for PHP 5.3.
|
||||
*
|
||||
* It expects an object implementing a findFile method to find the file. This
|
||||
* allows using it as a wrapper around the other loaders of the component (the
|
||||
@@ -43,34 +43,41 @@ namespace Symfony\Component\ClassLoader;
|
||||
class XcacheClassLoader
|
||||
{
|
||||
private $prefix;
|
||||
private $classFinder;
|
||||
|
||||
/**
|
||||
* @var object A class loader object that implements the findFile() method
|
||||
*/
|
||||
private $decorated;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $prefix A prefix to create a namespace in Xcache
|
||||
* @param object $classFinder An object that implements findFile() method.
|
||||
* @param string $prefix The XCache namespace prefix to use.
|
||||
* @param object $decorated A class loader object that implements the findFile() method.
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function __construct($prefix, $classFinder)
|
||||
public function __construct($prefix, $decorated)
|
||||
{
|
||||
if (!extension_loaded('Xcache')) {
|
||||
throw new \RuntimeException('Unable to use XcacheClassLoader as Xcache is not enabled.');
|
||||
if (!extension_loaded('xcache')) {
|
||||
throw new \RuntimeException('Unable to use XcacheClassLoader as XCache is not enabled.');
|
||||
}
|
||||
|
||||
if (!method_exists($classFinder, 'findFile')) {
|
||||
if (!method_exists($decorated, 'findFile')) {
|
||||
throw new \InvalidArgumentException('The class finder must implement a "findFile" method.');
|
||||
}
|
||||
|
||||
$this->prefix = $prefix;
|
||||
$this->classFinder = $classFinder;
|
||||
$this->decorated = $decorated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param Boolean $prepend Whether to prepend the autoloader or not
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
@@ -90,7 +97,7 @@ class XcacheClassLoader
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return Boolean|null True, if loaded
|
||||
* @return bool|null True, if loaded
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
@@ -113,9 +120,18 @@ class XcacheClassLoader
|
||||
if (xcache_isset($this->prefix.$class)) {
|
||||
$file = xcache_get($this->prefix.$class);
|
||||
} else {
|
||||
xcache_set($this->prefix.$class, $file = $this->classFinder->findFile($class));
|
||||
$file = $this->decorated->findFile($class);
|
||||
xcache_set($this->prefix.$class, $file);
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Passes through all unknown calls onto the decorated object.
|
||||
*/
|
||||
public function __call($method, $args)
|
||||
{
|
||||
return call_user_func_array(array($this->decorated, $method), $args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,15 @@
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/finder": "2.1.*"
|
||||
"symfony/finder": "~2.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": { "Symfony\\Component\\ClassLoader": "" }
|
||||
"psr-0": { "Symfony\\Component\\ClassLoader\\": "" }
|
||||
},
|
||||
"target-dir": "Symfony/Component/ClassLoader",
|
||||
"minimum-stability": "dev"
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.3-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
|
||||
backupGlobals="false"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false"
|
||||
syntaxCheck="false"
|
||||
bootstrap="Tests/bootstrap.php"
|
||||
bootstrap="vendor/autoload.php"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="Symfony ClassLoader Component Test Suite">
|
||||
|
||||
Reference in New Issue
Block a user