Completed
Push — master ( a15d3a...1145d3 )
by Phil
15s queued 13s
created

Dispatcher::requestWithRouteAttributes()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

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