Remove `file_exists()` check from production autoloader
authorTim Düsterhus <duesterhus@woltlab.com>
Wed, 3 May 2023 13:05:35 +0000 (15:05 +0200)
committerTim Düsterhus <duesterhus@woltlab.com>
Wed, 3 May 2023 14:06:38 +0000 (16:06 +0200)
Resolves #5002

wcfsetup/install/files/lib/system/WCF.class.php

index 58d9d4f5675b463993bb6c24fe3bd216af1d0d70..8ec1490d73ecd400def04706c3a4f64b9d001f59 100644 (file)
@@ -821,31 +821,41 @@ class WCF
 
                 // PHP will implicitly check if the file exists when including it, which means that we can save a
                 // redundant syscall/fs access by not checking for existence ourselves. Do not use require_once()!
-
-                // TODO: Changed for #4684. Revert for release.
-                if (\file_exists($classPath)) {
-                    include_once($classPath);
-                }
+                @include_once($classPath);
             }
         }
     }
 
     /**
-     * Checks the class name casing after autoloading.
+     * Checks the class name casing after autoloading and does not suppress
+     * errors during loading.
      */
     final public static function autoloadDebug(string $className): void
     {
-        self::autoload($className);
+        $originalClassName = $className;
 
-        if (\class_exists($className)) {
-            $reflection = new \ReflectionClass($className);
+        // This is copy and pasted from self::autoload(). The $classPath calculation
+        // logic cannot be moved into a shared function, because it
+        // measurably reduced autoloader performance.
+        $className = \strtr($className, '\\', '/');
+        if (($slashPos = \strpos($className, '/')) !== null) {
+            $applicationPrefix = \substr($className, 0, $slashPos);
+            if (isset(self::$autoloadDirectories[$applicationPrefix])) {
+                $classPath = self::$autoloadDirectories[$applicationPrefix] . \substr($className, $slashPos + 1) . '.class.php';
+
+                if (\file_exists($classPath)) {
+                    require_once($classPath);
 
-            if ($className !== $reflection->getName()) {
-                throw new \Exception(\sprintf(
-                    "Loaded class '%s' with mismatching case '%s'. This will cause issues on case-sensitive file systems.",
-                    $reflection->getName(),
-                    $className,
-                ));
+                    $reflection = new \ReflectionClass($originalClassName);
+
+                    if ($originalClassName !== $reflection->getName()) {
+                        throw new \Exception(\sprintf(
+                            "Loaded class '%s' with mismatching case '%s'. This will cause issues on case-sensitive file systems.",
+                            $reflection->getName(),
+                            $originalClassName,
+                        ));
+                    }
+                }
             }
         }
     }