diff --git a/src/ZweistRouteService.php b/src/ZweistRouteService.php index c55e04e..7f97f1c 100644 --- a/src/ZweistRouteService.php +++ b/src/ZweistRouteService.php @@ -9,6 +9,10 @@ use Psr\Container\ContainerInterface; use Psr\Container\NotFoundExceptionInterface; use Psr\Http\Server\MiddlewareInterface; +use ReflectionClass; +use ReflectionException; +use ReflectionNamedType; +use ReflectionUnionType; use RuntimeException; use Slim\Routing\Route; use Slim\Routing\RouteCollectorProxy; @@ -38,6 +42,7 @@ public function __construct( * @throws JsonException * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface + * @throws ReflectionException */ public function applyRoutes(RouteCollectorProxy $routeCollectorProxy): void { @@ -67,14 +72,54 @@ public function applyRoutes(RouteCollectorProxy $routeCollectorProxy): void * @var array{class: class-string, context: mixed} $middlewareData */ foreach ($routeSettings['middleware'] as $middlewareData) { - /** @var MiddlewareInterface $middleware */ - $middleware = $this->container->get($middlewareData['class']); + + $reflectionClass = new ReflectionClass($middlewareData['class']); + $reflectionMethod = $reflectionClass->getConstructor(); + + $middleware = null; + + if ($reflectionMethod !== null) { + $parameterValues = []; + + foreach ($reflectionMethod->getParameters() as $parameter) { + $parameterType = $parameter->getType(); + $parameterValue = null; + + if ($parameterType instanceof ReflectionUnionType) { + foreach ($parameterType->getTypes() as $type) { + if (($type instanceof ReflectionNamedType) && $parameterValue === null) { + try { + $parameterValue = $this->container->get($type->getName()); + } catch (ContainerExceptionInterface) { // @codeCoverageIgnoreStart + /*noop*/ + } // @codeCoverageIgnoreEnd + } + } + } + + if (($parameterType instanceof ReflectionNamedType) && ($parameterValue === null)) { + try { + $parameterValue = $this->container->get($parameterType->getName()); + } catch (ContainerExceptionInterface) { // @codeCoverageIgnoreStart + /*noop*/ + } // @codeCoverageIgnoreEnd + } + + $parameterValues[$parameter->getName()] = $parameterValue; + } + + $middleware = new $middlewareData['class'](...$parameterValues); + } else { + $middleware = new $middlewareData['class'](); + } if ($middleware instanceof MiddlewareWithContextInterface) { $middleware->setContext($middlewareData['context']); } - $route->addMiddleware($middleware); + if ($middleware instanceof MiddlewareInterface) { + $route->addMiddleware($middleware); + } } } } diff --git a/tests/ExampleApplication/ExampleMiddleware.php b/tests/ExampleApplication/ExampleMiddleware.php index d92e3a8..5c81104 100644 --- a/tests/ExampleApplication/ExampleMiddleware.php +++ b/tests/ExampleApplication/ExampleMiddleware.php @@ -9,6 +9,8 @@ use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; use Zrnik\Zweist\Content\MiddlewareWithContextInterface; +use Zrnik\Zweist\Tests\ExampleSchema\NotASchemaClass; +use Zrnik\Zweist\Tests\ExampleSchema\SchemaClass; class ExampleMiddleware implements MiddlewareInterface, MiddlewareWithContextInterface { @@ -20,6 +22,11 @@ class ExampleMiddleware implements MiddlewareInterface, MiddlewareWithContextInt private mixed $context; + // @phpstan-ignore-next-line + public function __construct(NotASchemaClass $notASchemaClass, SchemaClass|NotASchemaClass $something) + { + } + public function setContext(mixed $context): void { $this->context = $context; @@ -30,14 +37,20 @@ public function process( RequestHandlerInterface $handler ): ResponseInterface { - return $handler - ->handle($request) - ->withHeader( - self::VALUE_HEADER_NAME, - self::VALUE_HEADER_VALUE - )->withHeader( + $response = $handler->handle($request); + + $response = $response->withHeader( + self::VALUE_HEADER_NAME, + self::VALUE_HEADER_VALUE + ); + + if ($this->context !== null) { + $response = $response->withHeader( self::CONTEXT_HEADER_NAME, $this->context, ); + } + + return $response; } }