Files
server/core/lib/Http/Middleware/MiddlewarePipeline.php
2026-02-10 18:46:11 -05:00

113 lines
3.6 KiB
PHP

<?php
namespace KTXC\Http\Middleware;
use KTXC\Http\Request\Request;
use KTXC\Http\Response\Response;
use Psr\Container\ContainerInterface;
/**
* Middleware pipeline - processes request through a stack of middleware
*/
class MiddlewarePipeline implements RequestHandlerInterface
{
/** @var array<string|MiddlewareInterface> */
private array $middleware = [];
private ?ContainerInterface $container = null;
public function __construct(?ContainerInterface $container = null)
{
$this->container = $container;
}
/**
* Add middleware to the pipeline
*
* @param string|MiddlewareInterface $middleware Middleware class name or instance
* @return self
*/
public function pipe(string|MiddlewareInterface $middleware): self
{
$this->middleware[] = $middleware;
return $this;
}
/**
* Handle the request through the middleware pipeline
*
* @param Request $request
* @return Response
*/
public function handle(Request $request): Response
{
// Create a handler for the pipeline
$handler = $this->createHandler(0);
return $handler->handle($request);
}
/**
* Create a handler for a specific position in the pipeline
*
* @param int $index Current position in the middleware stack
* @return RequestHandlerInterface
*/
public function createHandler(int $index): RequestHandlerInterface
{
// If we've reached the end of the pipeline, return a default handler
if (!isset($this->middleware[$index])) {
return new class implements RequestHandlerInterface {
public function handle(Request $request): Response {
return new Response(Response::$statusTexts[Response::HTTP_NOT_FOUND], Response::HTTP_NOT_FOUND);
}
};
}
return new class($this->middleware[$index], $this, $index, $this->container) implements RequestHandlerInterface {
private string|MiddlewareInterface $middleware;
private MiddlewarePipeline $pipeline;
private int $index;
private ?ContainerInterface $container;
public function __construct(
string|MiddlewareInterface $middleware,
MiddlewarePipeline $pipeline,
int $index,
?ContainerInterface $container
) {
$this->middleware = $middleware;
$this->pipeline = $pipeline;
$this->index = $index;
$this->container = $container;
}
public function handle(Request $request): Response
{
// Resolve middleware instance if it's a class name
$middleware = $this->middleware;
if (is_string($middleware)) {
if ($this->container && $this->container->has($middleware)) {
$middleware = $this->container->get($middleware);
} else {
$middleware = new $middleware();
}
}
if (!$middleware instanceof MiddlewareInterface) {
throw new \RuntimeException(
sprintf('Middleware must implement %s', MiddlewareInterface::class)
);
}
// Create the next handler in the chain
$next = $this->pipeline->createHandler($this->index + 1);
// Process this middleware
return $middleware->process($request, $next);
}
};
}
}