chore: complete update

This commit is contained in:
2025-07-17 16:24:20 +02:00
parent 899227b0a4
commit 64a7051137
1300 changed files with 85570 additions and 2756 deletions

View File

@@ -0,0 +1,127 @@
<?php
namespace App\Framework\DI;
use App\Framework\Reflection\ReflectionProvider;
use ReflectionMethod;
use ReflectionNamedType;
/**
* Führt Methoden auf beliebigen Klassen mit automatischer Dependency Injection aus
*/
final readonly class MethodInvoker
{
public function __construct(
private Container $container,
private ReflectionProvider $reflectionCache
) {}
/**
* Führt eine Methode auf einer Klasse aus und löst alle Parameter automatisch auf
*/
public function invoke(string $className, string $methodName, array $overrides = []): mixed
{
$instance = $this->container->get($className);
return $this->invokeOn($instance, $methodName, $overrides);
}
/**
* Führt eine Methode auf einer bereits existierenden Instanz aus
*/
public function invokeOn(object $instance, string $methodName, array $overrides = []): mixed
{
$reflection = $this->reflectionCache->getClass($instance::class);
if (!$reflection->hasMethod($methodName)) {
throw new \InvalidArgumentException(
"Method $methodName does not exist on class $instance::class"
);
}
$method = $this->reflectionCache->getMethod($instance::class, $methodName);
if (!$method->isPublic()) {
throw new \InvalidArgumentException(
"Method $methodName on class $instance::class is not public"
);
}
$parameters = $this->resolveMethodParameters($method, $overrides);
return $method->invokeArgs($instance, $parameters);
}
/**
* Führt eine statische Methode aus
*/
public function invokeStatic(string $className, string $methodName, array $overrides = []): mixed
{
$reflection = $this->reflectionCache->getClass($className);
if (!$reflection->hasMethod($methodName)) {
throw new \InvalidArgumentException(
"Method '{$methodName}' does not exist on class '{$className}'"
);
}
$method = $this->reflectionCache->getMethod($className, $methodName);
if (!$method->isStatic()) {
throw new \InvalidArgumentException(
"Method '{$methodName}' on class '{$className}' is not static"
);
}
$parameters = $this->resolveMethodParameters($method, $overrides);
return $method->invokeArgs(null, $parameters);
}
/**
* Löst alle Parameter einer Methode auf
*/
private function resolveMethodParameters(ReflectionMethod $method, array $overrides): array
{
$parameters = [];
foreach ($method->getParameters() as $param) {
$paramName = $param->getName();
// Override-Werte haben Priorität
if (array_key_exists($paramName, $overrides)) {
$parameters[] = $overrides[$paramName];
continue;
}
// Type-based injection
$type = $param->getType();
if ($type instanceof ReflectionNamedType && !$type->isBuiltin()) {
$typeName = $type->getName();
if ($this->container->has($typeName)) {
$parameters[] = $this->container->get($typeName);
continue;
}
}
// Default-Werte verwenden
if ($param->isDefaultValueAvailable()) {
$parameters[] = $param->getDefaultValue();
continue;
}
// Nullable Parameter
if ($type && $type->allowsNull()) {
$parameters[] = null;
continue;
}
throw new \InvalidArgumentException(
"Cannot resolve parameter '{$paramName}' for method '{$method->getName()}' on class '{$method->getDeclaringClass()->getName()}'"
);
}
return $parameters;
}
}