Files
michaelschiemer/src/Framework/Core/InterfaceImplementationLocator.php
Michael Schiemer 55a330b223 Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug
- Add DISCOVERY_SHOW_PROGRESS=true
- Temporary changes for debugging InitializerProcessor fixes on production
2025-08-11 20:13:26 +02:00

81 lines
2.9 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Framework\Core;
use App\Framework\Core\ValueObjects\ClassName;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use ReflectionClass;
use Throwable;
class InterfaceImplementationLocator
{
/**
* Findet alle Klassen, die ein bestimmtes Interface implementieren
*
* @param string $directory Das Basisverzeichnis, in dem gesucht werden soll
* @param string $interfaceName Der vollständige Name des Interfaces (mit Namespace)
* @param bool $instantiate Gibt an, ob die gefundenen Klassen instanziiert werden sollen
* @return array<int, object|string> Array von Instanzen oder Klassennamen
*/
public function locate(string $directory, string $interfaceName, bool $instantiate = true): array
{
$implementations = [];
$rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory));
foreach ($rii as $file) {
if (! $file->isFile() || $file->getExtension() !== 'php') {
continue;
}
try {
$className = $this->getClassNameFromFile($file->getPathname());
if (! $className || ! ClassName::create($className)->exists()) {
continue;
}
$refClass = new ReflectionClass($className);
// Überprüfen, ob die Klasse das gewünschte Interface implementiert
if ($refClass->implementsInterface($interfaceName) &&
! $refClass->isAbstract() &&
! $refClass->isInterface()) {
if ($instantiate) {
// Prüfen, ob der Konstruktor Parameter hat
$constructor = $refClass->getConstructor();
if ($constructor === null || $constructor->getNumberOfRequiredParameters() === 0) {
$implementations[] = $refClass->newInstance();
} else {
// Bei Konstruktoren mit Pflichtparametern nur den Klassennamen zurückgeben
$implementations[] = $className;
}
} else {
$implementations[] = $className;
}
}
} catch (Throwable $e) {
#error_log("InterfaceImplementationLocator Warnung: Fehler in Datei {$file->getPathname()}: " . $e->getMessage());
}
}
return $implementations;
}
private function getClassNameFromFile(string $file): ?string
{
$contents = file_get_contents($file);
if (
preg_match('#namespace\s+([^;]+);#', $contents, $nsMatch)
&& preg_match('/class\s+(\w+)/', $contents, $classMatch)
) {
return trim($nsMatch[1]) . '\\' . trim($classMatch[1]);
}
return null;
}
}