Passed
Push — master ( 7c17ca...f3fb85 )
by Mr
02:18
created

RoutingHandler::initializeHandler()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 3
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 6
ccs 0
cts 6
cp 0
crap 6
rs 10
1
<?php declare(strict_types=1);
2
/**
3
 * This file is part of the daikon-cqrs/boot project.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
9
namespace Daikon\Boot\Middleware;
10
11
use Aura\Router\Route;
12
use Aura\Router\RouterContainer;
13
use Aura\Router\Rule\Accepts;
14
use Aura\Router\Rule\Allows;
15
use Aura\Router\Rule\Host;
16
use Aura\Router\Rule\Path;
17
use Fig\Http\Message\StatusCodeInterface;
18
use Middlewares\Utils\Factory;
19
use Psr\Container\ContainerInterface;
20
use Psr\Http\Message\ResponseInterface;
21
use Psr\Http\Message\ServerRequestInterface;
22
use Psr\Http\Server\MiddlewareInterface;
23
use Psr\Http\Server\RequestHandlerInterface;
24
25
final class RoutingHandler implements MiddlewareInterface, StatusCodeInterface
26
{
27
    public const ATTR_REQUEST_HANDLER = '_request_handler';
28
29
    private RouterContainer $router;
30
31
    private ContainerInterface $container;
32
33
    public function __construct(RouterContainer $router, ContainerInterface $container)
34
    {
35
        $this->router = $router;
36
        $this->container = $container;
37
    }
38
39
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
40
    {
41
        $matcher = $this->router->getMatcher();
42
        if (!$route = $matcher->match($request)) {
43
            return $this->errorResponse($matcher->getFailedRoute());
44
        }
45
46
        foreach ($route->attributes as $name => $value) {
47
            $request = $request->withAttribute($name, $value);
48
        }
49
50
        $requestHandler = is_string($route->handler)
51
            ? $this->container->get($route->handler)
52
            : $route->handler;
53
54
        return $handler->handle(
55
            $request->withAttribute(self::ATTR_REQUEST_HANDLER, $requestHandler)
56
        );
57
    }
58
59
    private function errorResponse(Route $failedRoute = null): ResponseInterface
60
    {
61
        if (!$failedRoute) {
62
            return Factory::createResponse(self::STATUS_INTERNAL_SERVER_ERROR);
63
        }
64
65
        switch ($failedRoute->failedRule) {
66
            case Accepts::class:
67
                return Factory::createResponse(self::STATUS_NOT_ACCEPTABLE);
68
            case Allows::class:
69
                $allowed = implode(', ', $failedRoute->allows);
70
                return Factory::createResponse(self::STATUS_METHOD_NOT_ALLOWED)->withHeader('Allow', $allowed);
71
            case Host::class:
72
            case Path::class:
73
                return Factory::createResponse(self::STATUS_NOT_FOUND);
74
            default:
75
                return Factory::createResponse(self::STATUS_INTERNAL_SERVER_ERROR);
76
        }
77
    }
78
}
79