. */ declare(strict_types=1); namespace Fisharebest\Webtrees\Http; use Fisharebest\Webtrees\Http\RequestHandlers\NotFound; use Fisharebest\Webtrees\Registry; use LogicException; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; use function array_reduce; use function array_reverse; use function is_string; readonly class Dispatcher { /** * @param list $middleware */ public static function dispatch(array $middleware, ServerRequestInterface $request): ResponseInterface { $pipeline = array_reduce( array: array_reverse(array: $middleware), callback: self::reduceMiddleware(...), initial: new NotFound(), ); return $pipeline->handle(request: $request); } /** * @param class-string|MiddlewareInterface $item */ private static function reduceMiddleware( RequestHandlerInterface $carry, string|MiddlewareInterface $item, ): RequestHandlerInterface { return new readonly class (carry: $carry, item: $item) implements RequestHandlerInterface { /** * @param class-string|MiddlewareInterface $item */ public function __construct( private RequestHandlerInterface $carry, private string|MiddlewareInterface $item, ) { } public function handle(ServerRequestInterface $request): ResponseInterface { $item = $this->item; if (is_string(value: $item)) { $item = Registry::container()->get(id: $item); } if ($item instanceof MiddlewareInterface) { return $item->process(request: $request, handler: $this->carry); } throw new LogicException(message: 'Invalid or undefined middleware'); } }; } }