Skip to content

Commit bd25485

Browse files
committed
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.
1 parent d2574b9 commit bd25485

File tree

1 file changed

+43
-1
lines changed

1 file changed

+43
-1
lines changed

autoload.php

+43-1
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,37 @@ public static function load($class)
139139

140140
}//end load()
141141

142+
/**
143+
* Determine which class was loaded from path
144+
*
145+
* @param array $classesBeforeLoad The classes/interfaces/traits before the file was included.
146+
* @param string $path The path that already has been included.
147+
*
148+
* @return string The fully qualified name of the class in the loaded file.
149+
*/
150+
private static function determinePathClass(
151+
array $classesBeforeLoad, $path
152+
) {
153+
$alreadyIncluded = in_array($path, get_included_files(), true);
154+
if ($alreadyIncluded === false) {
155+
return null;
156+
}
157+
158+
$name = pathinfo($path, PATHINFO_FILENAME);
159+
$declared = preg_grep(
160+
'(\\\\'.preg_quote($name).'$)',
161+
$classesBeforeLoad['classes']
162+
);
163+
foreach ($declared as $className) {
164+
$reflection = new \ReflectionClass($className);
165+
$classFileName = $reflection->getFileName();
166+
if ($classFileName === $path) {
167+
return $className;
168+
}
169+
}
170+
171+
}//end determinePathClass()
172+
142173

143174
/**
144175
* Includes a file and tracks what class or interface was loaded as a result.
@@ -166,6 +197,12 @@ public static function loadFile($path)
166197
'traits' => get_declared_traits(),
167198
];
168199

200+
$className = self::determinePathClass($classesBeforeLoad, $path);
201+
202+
if ($className !== null) {
203+
goto determined_className;
204+
}
205+
169206
include $path;
170207

171208
$classesAfterLoad = [
@@ -174,7 +211,12 @@ public static function loadFile($path)
174211
'traits' => get_declared_traits(),
175212
];
176213

177-
$className = self::determineLoadedClass($classesBeforeLoad, $classesAfterLoad);
214+
$className = self::determineLoadedClass(
215+
$classesBeforeLoad,
216+
$classesAfterLoad
217+
);
218+
219+
determined_className:
178220

179221
self::$loadedClasses[$path] = $className;
180222
self::$loadedFiles[$className] = $path;

0 commit comments

Comments
 (0)