Passed
Push — master ( 093d25...9ddd4f )
by Mr
01:54
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 Daikon\Boot\Middleware\Action\ActionInterface;
18
use Fig\Http\Message\StatusCodeInterface;
19
use Middlewares\Utils\Factory;
20
use Psr\Container\ContainerInterface;
21
use Psr\Http\Message\ResponseInterface;
22
use Psr\Http\Message\ServerRequestInterface;
23
use Psr\Http\Server\MiddlewareInterface;
24
use Psr\Http\Server\RequestHandlerInterface;
25
26
final class RoutingHandler implements MiddlewareInterface, StatusCodeInterface
27
{
28
    public const ATTR_REQUEST_HANDLER = '_request_handler';
29
30
    private RouterContainer $router;
31
32
    private ContainerInterface $container;
33
34
    public function __construct(RouterContainer $router, ContainerInterface $container)
35
    {
36
        $this->router = $router;
37
        $this->container = $container;
38
    }
39
40
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
41
    {
42
        $matcher = $this->router->getMatcher();
43
        if (!$route = $matcher->match($request)) {
44
            return $this->errorResponse($matcher->getFailedRoute());
45
        }
46
47
        foreach ($route->attributes as $name => $value) {
48
            $request = $request->withAttribute($name, $value);
49
        }
50
51
        return $handler->handle(
52
            $request->withAttribute(self::ATTR_REQUEST_HANDLER, $this->initializeHandler($route->handler))
53
        );
54
    }
55
56
    private function errorResponse(Route $failedRoute = null): ResponseInterface
57
    {
58
        if (!$failedRoute) {
59
            return Factory::createResponse(self::STATUS_INTERNAL_SERVER_ERROR);
60
        }
61
62
        switch ($failedRoute->failedRule) {
63
            case Accepts::class:
64
                return Factory::createResponse(self::STATUS_NOT_ACCEPTABLE);
65
            case Allows::class:
66
                $allowed = implode(', ', $failedRoute->allows);
67
                return Factory::createResponse(self::STATUS_METHOD_NOT_ALLOWED)->withHeader('Allow', $allowed);
68
            case Host::class:
69
            case Path::class:
70
                return Factory::createResponse(self::STATUS_NOT_FOUND);
71
            default:
72
                return Factory::createResponse(self::STATUS_INTERNAL_SERVER_ERROR);
73
        }
74
    }
75
76
    /** @param callable|ActionInterface $requestHandler */
77
    private function initializeHandler($requestHandler): callable
78
    {
79
        if (is_string($requestHandler)) {
80
            $requestHandler = $this->container->get($requestHandler);
81
        }
82
        return $requestHandler;
83
    }
84
}
85