Skip to content

Commit

Permalink
[Debug] enhance perf of DebugClassLoader
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolas-grekas committed May 8, 2014
1 parent 896a351 commit 485e047
Showing 1 changed file with 31 additions and 25 deletions.
56 changes: 31 additions & 25 deletions src/Symfony/Component/Debug/DebugClassLoader.php
Expand Up @@ -29,6 +29,7 @@ class DebugClassLoader
private $classLoader;
private $isFinder;
private $wasFinder;
private static $caseCheck;

/**
* Constructor.
Expand All @@ -49,6 +50,10 @@ public function __construct($classLoader)
$this->classLoader = $classLoader;
$this->isFinder = is_array($classLoader) && method_exists($classLoader[0], 'findFile');
}

if (!isset(self::$caseCheck)) {
self::$caseCheck = false !== stripos(PHP_OS, 'win') ? (false !== stripos(PHP_OS, 'darwin') ? 2 : 1) : 0;
}
}

/**
Expand Down Expand Up @@ -162,40 +167,49 @@ public function loadClass($class)

$exists = class_exists($class, false) || interface_exists($class, false) || (function_exists('trait_exists') && trait_exists($class, false));

if ('\\' === $class[0]) {
$class = substr($class, 1);
}

if ($exists) {
$name = new \ReflectionClass($class);
$name = $name->getName();
$refl = new \ReflectionClass($class);
$name = $refl->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);
}
if (!$exists) {
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));
}

if (preg_match('#([/\\\\][a-zA-Z_\x7F-\xFF][a-zA-Z0-9_\x7F-\xFF]*)+\.(php|hh)$#', $file, $tail)) {
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));
}
if (self::$caseCheck && preg_match('#([/\\\\][a-zA-Z_\x7F-\xFF][a-zA-Z0-9_\x7F-\xFF]*)+\.(php|hh)$#D', $file, $tail)) {
$tail = $tail[0];
$real = realpath($file);
$real = $refl->getFilename();

if (false !== stripos(PHP_OS, 'darwin')) {
// realpath() on MacOSX doesn't normalize the case of characters,
// let's do it ourselves. This is tricky.
if (2 === self::$caseCheck) {
// realpath() on MacOSX doesn't normalize the case of characters
$cwd = getcwd();
$basename = strrpos($real, '/');
chdir(substr($real, 0, $basename));
$basename = substr($real, $basename + 1);
$real = getcwd().'/';
$h = opendir('.');
while (false !== $f = readdir($h)) {
if (0 === strcasecmp($f, $basename)) {
$real .= $f;
break;
// glob() patterns are case-sensitive even if the underlying fs is not
if (!in_array($basename, glob($basename.'*', GLOB_NOSORT), true)) {
$real = getcwd().'/';
$h = opendir('.');
while (false !== $f = readdir($h)) {
if (0 === strcasecmp($f, $basename)) {
$real .= $f;
break;
}
}
closedir($h);
}
closedir($h);
chdir($cwd);
}

Expand All @@ -206,14 +220,6 @@ public function loadClass($class)
}
}

if (!$exists) {
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;
}
}
Expand Down

0 comments on commit 485e047

Please sign in to comment.