Skip to content

Commit

Permalink
check included files for defined classes before include
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ktomk committed Jun 2, 2021
1 parent d2574b9 commit bd25485
Showing 1 changed file with 43 additions and 1 deletion.
44 changes: 43 additions & 1 deletion autoload.php
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,37 @@ 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.
Expand Down Expand Up @@ -166,6 +197,12 @@ public static function loadFile($path)
'traits' => get_declared_traits(),
];

$className = self::determinePathClass($classesBeforeLoad, $path);

if ($className !== null) {
goto determined_className;
}

include $path;

$classesAfterLoad = [
Expand All @@ -174,7 +211,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;
Expand Down

0 comments on commit bd25485

Please sign in to comment.