Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
RouteDispatcher
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
2 / 2
7
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 process
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
1 / 1
6
1<?php
2
3declare(strict_types=1);
4
5namespace Engelsystem\Middleware;
6
7use Engelsystem\Http\Request;
8use FastRoute\Dispatcher as FastRouteDispatcher;
9use Nyholm\Psr7\Uri;
10use Psr\Http\Message\ResponseInterface;
11use Psr\Http\Message\ServerRequestInterface;
12use Psr\Http\Server\MiddlewareInterface;
13use Psr\Http\Server\RequestHandlerInterface;
14
15class RouteDispatcher implements MiddlewareInterface
16{
17    /**
18     * @param ResponseInterface $response Default response
19     * @param MiddlewareInterface|null $notFound Handles any requests if the route can't be found
20     */
21    public function __construct(
22        protected FastRouteDispatcher $dispatcher,
23        protected ResponseInterface $response,
24        protected ?MiddlewareInterface $notFound = null
25    ) {
26    }
27
28    /**
29     * Process an incoming server request and return a response, optionally delegating
30     * response creation to a handler.
31     */
32    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
33    {
34        $path = (new Uri((string) $request->getUri()))->getPath();
35        if ($request instanceof Request) {
36            $path = $request->getPathInfo();
37        }
38
39        $path = urldecode($path);
40        $route = $this->dispatcher->dispatch($request->getMethod(), $path);
41
42        $status = $route[0];
43        if ($status == FastRouteDispatcher::NOT_FOUND) {
44            if ($this->notFound instanceof MiddlewareInterface) {
45                return $this->notFound->process($request, $handler);
46            }
47
48            return $this->response->withStatus(404);
49        }
50
51        if ($status == FastRouteDispatcher::METHOD_NOT_ALLOWED) {
52            $methods = $route[1];
53            return $this->response
54                ->withStatus(405)
55                ->withHeader('Allow', implode(', ', $methods));
56        }
57
58        $routeHandler = $route[1];
59        $request = $request->withAttribute('route-request-handler', $routeHandler);
60        $request = $request->withAttribute('route-request-path', $path);
61
62        $vars = $route[2];
63        foreach ($vars as $name => $value) {
64            $request = $request->withAttribute($name, $value);
65        }
66
67        return $handler->handle($request);
68    }
69}