diff --git a/src/Symfony/Component/ClassLoader/CHANGELOG.md b/src/Symfony/Component/ClassLoader/CHANGELOG.md index 54ffb642e6..b770166735 100644 --- a/src/Symfony/Component/ClassLoader/CHANGELOG.md +++ b/src/Symfony/Component/ClassLoader/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +2.4.0 +----- + + * deprecated the DebugClassLoader as it has been moved to the Debug component instead + 2.3.0 ----- diff --git a/src/Symfony/Component/ClassLoader/DebugClassLoader.php b/src/Symfony/Component/ClassLoader/DebugClassLoader.php index 9a6069fe68..8edd4c1999 100644 --- a/src/Symfony/Component/ClassLoader/DebugClassLoader.php +++ b/src/Symfony/Component/ClassLoader/DebugClassLoader.php @@ -22,6 +22,8 @@ namespace Symfony\Component\ClassLoader; * @author Christophe Coevoet * * @api + * + * @deprecated Deprecated since version 2.4, to be removed in 3.0. Use the DebugClassLoader provided by the Debug component instead. */ class DebugClassLoader { diff --git a/src/Symfony/Component/Debug/CHANGELOG.md b/src/Symfony/Component/Debug/CHANGELOG.md index a8321da551..84335a10b2 100644 --- a/src/Symfony/Component/Debug/CHANGELOG.md +++ b/src/Symfony/Component/Debug/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 2.4.0 ----- + * added a DebugClassLoader able to wrap any autoloader providing a findFile method * improved error messages for not found classes and functions 2.3.0 diff --git a/src/Symfony/Component/Debug/Debug.php b/src/Symfony/Component/Debug/Debug.php index 2e36805ca3..00098154d7 100644 --- a/src/Symfony/Component/Debug/Debug.php +++ b/src/Symfony/Component/Debug/Debug.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Debug; -use Symfony\Component\ClassLoader\DebugClassLoader; +use Symfony\Component\Debug\DebugClassLoader; /** * Registers all the debug tools. @@ -51,8 +51,6 @@ class Debug ini_set('display_errors', 1); } - if (class_exists('Symfony\Component\ClassLoader\DebugClassLoader')) { - DebugClassLoader::enable(); - } + DebugClassLoader::enable(); } } diff --git a/src/Symfony/Component/Debug/DebugClassLoader.php b/src/Symfony/Component/Debug/DebugClassLoader.php new file mode 100644 index 0000000000..a0c6c5a4f9 --- /dev/null +++ b/src/Symfony/Component/Debug/DebugClassLoader.php @@ -0,0 +1,133 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug; + +/** + * Autoloader checking if the class is really defined in the file found. + * + * The ClassLoader will wrap all registered autoloaders providing a + * findFile method and will throw an exception if a file is found but does + * not declare the class. + * + * @author Fabien Potencier + * @author Christophe Coevoet + * + * @api + */ +class DebugClassLoader +{ + private $classFinder; + + /** + * Constructor. + * + * @param object $classFinder + * + * @api + */ + public function __construct($classFinder) + { + $this->classFinder = $classFinder; + } + + /** + * Gets the wrapped class loader. + * + * @return object a class loader instance + */ + public function getClassLoader() + { + return $this->classFinder; + } + + /** + * Replaces all autoloaders implementing a findFile method by a DebugClassLoader wrapper. + */ + public static function enable() + { + if (!is_array($functions = spl_autoload_functions())) { + return; + } + + foreach ($functions as $function) { + spl_autoload_unregister($function); + } + + foreach ($functions as $function) { + if (is_array($function) && !$function[0] instanceof self && method_exists($function[0], 'findFile')) { + $function = array(new static($function[0]), 'loadClass'); + } + + spl_autoload_register($function); + } + } + + /** + * Disables the wrapping. + */ + public static function disable() + { + if (!is_array($functions = spl_autoload_functions())) { + return; + } + + foreach ($functions as $function) { + spl_autoload_unregister($function); + } + + foreach ($functions as $function) { + if (is_array($function) && $function[0] instanceof self) { + $function[0] = $function[0]->getClassLoader(); + } + + spl_autoload_register($function); + } + } + + /** + * Finds a file by class name + * + * @param string $class A class name to resolve to file + * + * @return string|null + */ + public function findFile($class) + { + return $this->classFinder->findFile($class); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * + * @return Boolean|null True, if loaded + * + * @throws \RuntimeException + */ + public function loadClass($class) + { + if ($file = $this->classFinder->findFile($class)) { + require $file; + + if (!class_exists($class, false) && !interface_exists($class, false) && (!function_exists('trait_exists') || !trait_exists($class, false))) { + if (false !== strpos($class, '/')) { + throw new \RuntimeException(sprintf('Trying to autoload a class with an invalid name "%s". Be careful that the namespace separator is "\" in PHP, not "/".', $class)); + } + + throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file)); + } + + return true; + } + } +} diff --git a/src/Symfony/Component/ClassLoader/Tests/DebugClassLoaderTest.php b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php similarity index 70% rename from src/Symfony/Component/ClassLoader/Tests/DebugClassLoaderTest.php rename to src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php index 873515c336..a18e5811cc 100644 --- a/src/Symfony/Component/ClassLoader/Tests/DebugClassLoaderTest.php +++ b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php @@ -9,10 +9,9 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\ClassLoader\Tests; +namespace Symfony\Component\Debug\Tests; -use Symfony\Component\ClassLoader\ClassLoader; -use Symfony\Component\ClassLoader\DebugClassLoader; +use Symfony\Component\Debug\DebugClassLoader; class DebugClassLoaderTest extends \PHPUnit_Framework_TestCase { @@ -41,12 +40,27 @@ class DebugClassLoaderTest extends \PHPUnit_Framework_TestCase $reflProp = $reflClass->getProperty('classFinder'); $reflProp->setAccessible(true); - $this->assertNotInstanceOf('Symfony\Component\ClassLoader\DebugClassLoader', $reflProp->getValue($function[0])); + $this->assertNotInstanceOf('Symfony\Component\Debug\DebugClassLoader', $reflProp->getValue($function[0])); + + DebugClassLoader::disable(); return; } } - throw new \Exception('DebugClassLoader did not register'); + DebugClassLoader::disable(); + + $this->fail('DebugClassLoader did not register'); + } +} + +class ClassLoader +{ + public function loadClass($class) + { + } + + public function findFile($class) + { } } diff --git a/src/Symfony/Component/Debug/composer.json b/src/Symfony/Component/Debug/composer.json index 413b71a035..17dcb3e288 100644 --- a/src/Symfony/Component/Debug/composer.json +++ b/src/Symfony/Component/Debug/composer.json @@ -24,8 +24,7 @@ }, "suggest": { "symfony/http-foundation": "", - "symfony/http-kernel": "", - "symfony/class-loader": "" + "symfony/http-kernel": "" }, "autoload": { "psr-0": { "Symfony\\Component\\Debug\\": "" }