Passed
Push — 6.x ( 9e1e65 )
by Phil
28:52 queued 04:40
created

Dispatcher::isExtraConditionMatch()   B

Complexity

Conditions 7
Paths 4

Size

Total Lines 21
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 8.323

Importance

Changes 0
Metric Value
eloc 10
c 0
b 0
f 0
dl 0
loc 21
ccs 7
cts 10
cp 0.7
rs 8.8333
cc 7
nc 4
nop 2
crap 8.323
1
<?php
2
3
declare(strict_types=1);
4
5
namespace League\Route;
6
7
use FastRoute\Dispatcher as FastRoute;
8
use FastRoute\Dispatcher\GroupCountBased as GroupCountBasedDispatcher;
9
use League\Route\Http\Exception\{MethodNotAllowedException, NotFoundException};
10
use League\Route\Middleware\{MiddlewareAwareInterface, MiddlewareAwareTrait};
11
use League\Route\Strategy\{StrategyAwareInterface, StrategyAwareTrait, StrategyInterface};
12
use Psr\Http\Message\{ResponseInterface, ServerRequestInterface};
13
use Psr\Http\Server\RequestHandlerInterface;
14
use RuntimeException;
15
16
class Dispatcher extends GroupCountBasedDispatcher implements
17
    MiddlewareAwareInterface,
18
    RequestHandlerInterface,
19
    StrategyAwareInterface
20
{
21
    use MiddlewareAwareTrait;
22
    use StrategyAwareTrait;
23
24
    public function dispatchRequest(ServerRequestInterface $request): ResponseInterface
25
    {
26 54
        $method = $request->getMethod();
27
        $uri    = $request->getUri()->getPath();
28 54
        $match  = $this->dispatch($method, $uri);
29 54
30 54
        switch ($match[0]) {
31
            case FastRoute::NOT_FOUND:
32 54
                $this->setNotFoundDecoratorMiddleware();
33 54
                break;
34 18
            case FastRoute::METHOD_NOT_ALLOWED:
35 18
                $allowed = (array) $match[1];
36 36
                $this->setMethodNotAllowedDecoratorMiddleware($allowed);
37 6
                break;
38 6
            case FastRoute::FOUND:
39 6
                $route = $this->ensureHandlerIsRoute($match[1], $method, $uri)->setVars($match[2]);
40 30
41 30
                if ($this->isExtraConditionMatch($route, $request)) {
42
                    $this->setFoundMiddleware($route);
43 30
                    $request = $this->requestWithRouteAttributes($request, $route);
44 30
                    break;
45 30
                }
46 30
47
                $this->setNotFoundDecoratorMiddleware();
48
                break;
49
        }
50
51
        return $this->handle($request);
52
    }
53 54
54
    public function handle(ServerRequestInterface $request): ResponseInterface
55
    {
56 54
        $middleware = $this->shiftMiddleware();
57
        return $middleware->process($request, $this);
58 54
    }
59 54
60
    protected function ensureHandlerIsRoute($matchingHandler, $httpMethod, $uri): Route
61
    {
62 30
        if ($matchingHandler instanceof Route) {
63
            return $matchingHandler;
64 30
        }
65 30
66
        return new Route($httpMethod, $uri, $matchingHandler);
67
    }
68
69
    protected function isExtraConditionMatch(Route $route, ServerRequestInterface $request): bool
70
    {
71 30
        // check for scheme condition
72
        $scheme = $route->getScheme();
73 30
        if ($scheme !== null && $scheme !== $request->getUri()->getScheme()) {
74
            return false;
75 30
        }
76 9
77
        // check for domain condition
78
        $host = $route->getHost();
79 30
        if ($host !== null && $host !== $request->getUri()->getHost()) {
80
            return false;
81
        }
82 30
83
        // check for port condition
84 30
        $port = $route->getPort();
85
        if ($port !== null && $port !== $request->getUri()->getPort()) {
86
            return false;
87
        }
88
89
        return true;
90
    }
91
92
    protected function requestWithRouteAttributes(ServerRequestInterface $request, Route $route): ServerRequestInterface
93
    {
94 30
        $routerParams = $route->getVars();
95 30
96
        foreach ($routerParams as $key => $value) {
97 30
            $request = $request->withAttribute($key, $value);
98 3
        }
99
100
        return $request;
101
    }
102 30
103
    protected function setFoundMiddleware(Route $route): void
104
    {
105 30
        if ($route->getStrategy() === null) {
106 6
            $strategy = $this->getStrategy();
107 3
108
            if (!($strategy instanceof StrategyInterface)) {
109
                throw new RuntimeException('Cannot determine strategy to use for dispatch of found route');
110
            }
111 30
112 3
            $route->setStrategy($strategy);
113
        }
114
115
        $strategy  = $route->getStrategy();
116 30
        $container = $strategy instanceof ContainerAwareInterface ? $strategy->getContainer() : null;
117 30
118
        foreach ($this->getMiddlewareStack() as $key => $middleware) {
119 6
            $this->middleware[$key] = $this->resolveMiddleware($middleware, $container);
120
        }
121 6
122
        // wrap entire dispatch process in exception handler
123 6
        $this->prependMiddleware($strategy->getThrowableHandler());
124
125
        // add group and route specific middleware
126
        if ($group = $route->getParentGroup()) {
127 6
            foreach ($group->getMiddlewareStack() as $middleware) {
128 6
                $this->middleware($this->resolveMiddleware($middleware, $container));
129 6
            }
130
        }
131 18
132
        foreach ($route->getMiddlewareStack() as $middleware) {
133 18
            $this->middleware($this->resolveMiddleware($middleware, $container));
134
        }
135 18
136
        // add actual route to end of stack
137
        $this->middleware($route);
138
    }
139 18
140 18
    protected function setMethodNotAllowedDecoratorMiddleware(array $allowed): void
141 18
    {
142
        $strategy = $this->getStrategy();
143
144
        if (!($strategy instanceof StrategyInterface)) {
145
            throw new RuntimeException('Cannot determine strategy to use for dispatch of method not allowed route');
146
        }
147
148
        $middleware = $strategy->getMethodNotAllowedDecorator(new MethodNotAllowedException($allowed));
149
        $this->prependMiddleware($middleware);
150
    }
151
152
    protected function setNotFoundDecoratorMiddleware(): void
153
    {
154
        $strategy = $this->getStrategy();
155
156
        if (!($strategy instanceof StrategyInterface)) {
157
            throw new RuntimeException('Cannot determine strategy to use for dispatch of not found route');
158
        }
159
160
        $middleware = $strategy->getNotFoundDecorator(new NotFoundException());
161
        $this->prependMiddleware($middleware);
162
    }
163
}
164