Passed
Push — 5.x ( b66c10...1ca894 )
by Phil
01:52 queued 11s
created

Dispatcher::isExtraConditionMatch()   B

Complexity

Conditions 7
Paths 4

Size

Total Lines 21
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 7

Importance

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