2013-08-28 11:04:02 +01:00
< ? 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\Debug ;
/**
* Autoloader checking if the class is really defined in the file found .
*
2014-02-04 10:33:08 +00:00
* The ClassLoader will wrap all registered autoloaders
* and will throw an exception if a file is found but does
2013-08-28 11:04:02 +01:00
* not declare the class .
*
* @ author Fabien Potencier < fabien @ symfony . com >
* @ author Christophe Coevoet < stof @ notk . org >
2014-02-04 10:33:08 +00:00
* @ author Nicolas Grekas < p @ tchwork . com >
2013-08-28 11:04:02 +01:00
*
* @ api
*/
class DebugClassLoader
{
2014-02-04 10:33:08 +00:00
private $classLoader ;
private $isFinder ;
private $wasFinder ;
2013-08-28 11:04:02 +01:00
/**
* Constructor .
*
2014-02-04 10:33:08 +00:00
* @ param callable | object $classLoader
2013-08-28 11:04:02 +01:00
*
* @ api
2014-02-04 10:33:08 +00:00
* @ deprecated since 2.5 , passing an object is deprecated and support for it will be removed in 3.0
2013-08-28 11:04:02 +01:00
*/
2014-02-04 10:33:08 +00:00
public function __construct ( $classLoader )
2013-08-28 11:04:02 +01:00
{
2014-02-04 10:33:08 +00:00
$this -> wasFinder = is_object ( $classLoader ) && method_exists ( $classLoader , 'findFile' );
if ( $this -> wasFinder ) {
$this -> classLoader = array ( $classLoader , 'loadClass' );
$this -> isFinder = true ;
} else {
$this -> classLoader = $classLoader ;
$this -> isFinder = is_array ( $classLoader ) && method_exists ( $classLoader [ 0 ], 'findFile' );
}
2013-08-28 11:04:02 +01:00
}
/**
* Gets the wrapped class loader .
*
2014-02-04 10:33:08 +00:00
* @ return callable | object a class loader
*
* @ deprecated since 2.5 , returning an object is deprecated and support for it will be removed in 3.0
2013-08-28 11:04:02 +01:00
*/
public function getClassLoader ()
{
2014-02-04 10:33:08 +00:00
if ( $this -> wasFinder ) {
return $this -> classLoader [ 0 ];
} else {
return $this -> classLoader ;
}
2013-08-28 11:04:02 +01:00
}
/**
2014-02-04 10:33:08 +00:00
* Wraps all autoloaders
2013-08-28 11:04:02 +01:00
*/
public static function enable ()
{
2014-02-04 10:33:08 +00:00
// Ensures we don't hit https://bugs.php.net/42098
class_exists ( __NAMESPACE__ . '\ErrorHandler' , true );
2013-08-28 11:04:02 +01:00
if ( ! is_array ( $functions = spl_autoload_functions ())) {
return ;
}
foreach ( $functions as $function ) {
spl_autoload_unregister ( $function );
}
foreach ( $functions as $function ) {
2014-02-04 10:33:08 +00:00
if ( ! is_array ( $function ) || ! $function [ 0 ] instanceof self ) {
$function = array ( new static ( $function ), 'loadClass' );
2013-08-28 11:04:02 +01:00
}
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 ) {
2014-02-04 10:33:08 +00:00
$function = $function [ 0 ] -> getClassLoader ();
2013-08-28 11:04:02 +01:00
}
spl_autoload_register ( $function );
}
}
/**
* Finds a file by class name
*
* @ param string $class A class name to resolve to file
*
* @ return string | null
2014-02-04 10:33:08 +00:00
*
* @ deprecated Deprecated since 2.5 , to be removed in 3.0 .
2013-08-28 11:04:02 +01:00
*/
public function findFile ( $class )
{
2014-02-04 10:33:08 +00:00
if ( $this -> wasFinder ) {
return $this -> classLoader [ 0 ] -> findFile ( $class );
}
2013-08-28 11:04:02 +01:00
}
/**
* Loads the given class or interface .
*
* @ param string $class The name of the class
*
2014-04-16 11:34:42 +01:00
* @ return bool | null True , if loaded
2013-08-28 11:04:02 +01:00
*
* @ throws \RuntimeException
*/
public function loadClass ( $class )
{
2014-02-04 10:33:08 +00:00
ErrorHandler :: stackErrors ();
try {
if ( $this -> isFinder ) {
if ( $file = $this -> classLoader [ 0 ] -> findFile ( $class )) {
require $file ;
}
} else {
call_user_func ( $this -> classLoader , $class );
$file = false ;
}
} catch ( \Exception $e ) {
ErrorHandler :: unstackErrors ();
throw $e ;
}
ErrorHandler :: unstackErrors ();
$exists = class_exists ( $class , false ) || interface_exists ( $class , false ) || ( function_exists ( 'trait_exists' ) && trait_exists ( $class , false ));
if ( $exists ) {
$name = new \ReflectionClass ( $class );
$name = $name -> getName ();
if ( $name !== $class ) {
throw new \RuntimeException ( sprintf ( 'Case mismatch between loaded and declared class names: %s vs %s' , $class , $name ));
}
}
if ( $file ) {
if ( '\\' == $class [ 0 ]) {
$class = substr ( $class , 1 );
}
2014-02-21 16:50:25 +00:00
$i = 0 ;
$tail = DIRECTORY_SEPARATOR . str_replace ( '\\' , DIRECTORY_SEPARATOR , $class ) . '.php' ;
2014-02-04 10:33:08 +00:00
$len = strlen ( $tail );
do {
2014-02-21 16:50:25 +00:00
$tail = substr ( $tail , $i );
$len -= $i ;
if ( 0 === substr_compare ( $file , $tail , - $len , $len , true )) {
if ( 0 !== substr_compare ( $file , $tail , - $len , $len , false )) {
if ( method_exists ( $this -> classLoader [ 0 ], 'getClassMap' )) {
$map = $this -> classLoader [ 0 ] -> getClassMap ();
} else {
$map = array ();
}
if ( ! isset ( $map [ $class ])) {
throw new \RuntimeException ( sprintf ( 'Case mismatch between class and source file names: %s vs %s' , $class , $file ));
}
}
break ;
2014-02-04 10:33:08 +00:00
}
2014-02-21 16:50:25 +00:00
} while ( false !== $i = strpos ( $tail , DIRECTORY_SEPARATOR , 1 ));
2013-08-28 11:04:02 +01:00
2014-02-04 10:33:08 +00:00
if ( ! $exists ) {
2013-08-28 11:04:02 +01:00
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 ;
}
}
}