From 606a9d1b7785ea2ec8ca6769ece2b367aabacc34 Mon Sep 17 00:00:00 2001 From: Tom Klingenberg Date: Wed, 2 Jun 2021 02:22:35 +0200 Subject: [PATCH] check included files for defined classes before include including a file that re-redefines leads to a fatal error, making phpcs fail hard. including files from a rule-set while these files may have already been included (likely by auto-loading and could then be seen as a race- condition) now checks if it has been already included and if so, searches all loaded classes for the class-name and if found, verifies the class is from that file. this effectively prevents the fatal error and works for classes / files with a PSR-4 naming scheme. --- autoload.php | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/autoload.php b/autoload.php index 0dcf1b4c81..29baf003b4 100644 --- a/autoload.php +++ b/autoload.php @@ -140,6 +140,38 @@ public static function load($class) }//end load() + /** + * Determine which class was loaded from path + * + * @param array $classesBeforeLoad The classes/interfaces/traits before the file was included. + * @param string $path The path that already has been included. + * + * @return string The fully qualified name of the class in the loaded file. + */ + private static function determinePathClass( + array $classesBeforeLoad, $path + ) { + $alreadyIncluded = in_array($path, get_included_files(), true); + if ($alreadyIncluded === false) { + return null; + } + + $name = pathinfo($path, PATHINFO_FILENAME); + $declared = preg_grep( + '(\\\\'.preg_quote($name).'$)', + $classesBeforeLoad['classes'] + ); + foreach ($declared as $className) { + $reflection = new \ReflectionClass($className); + $classFileName = $reflection->getFileName(); + if ($classFileName === $path) { + return $className; + } + } + + }//end determinePathClass() + + /** * Includes a file and tracks what class or interface was loaded as a result. * @@ -166,6 +198,12 @@ public static function loadFile($path) 'traits' => get_declared_traits(), ]; + $className = self::determinePathClass($classesBeforeLoad, $path); + + if ($className !== null) { + goto determined_className; + } + include $path; $classesAfterLoad = [ @@ -174,7 +212,12 @@ public static function loadFile($path) 'traits' => get_declared_traits(), ]; - $className = self::determineLoadedClass($classesBeforeLoad, $classesAfterLoad); + $className = self::determineLoadedClass( + $classesBeforeLoad, + $classesAfterLoad + ); + + determined_className: self::$loadedClasses[$path] = $className; self::$loadedFiles[$className] = $path;