Completed
Pull Request — master (#230)
by
unknown
02:24
created

Dispatcher::handle()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2.032

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 4
cts 5
cp 0.8
rs 9.9332
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2.032
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 OutOfBoundsException;
11
use Psr\Http\Message\{ResponseInterface, ServerRequestInterface};
12
use Psr\Http\Server\RequestHandlerInterface;
13
14
class Dispatcher extends GroupCountBasedDispatcher implements
15
    MiddlewareAwareInterface,
16
    RequestHandlerInterface,
17
    StrategyAwareInterface
18
{
19
    use MiddlewareAwareTrait;
20
    use StrategyAwareTrait;
21
22
    /**
23
     * Dispatch the current route
24
     *
25
     * @param \Psr\Http\Message\ServerRequestInterface $request
26
     *
27
     * @return \Psr\Http\Message\ResponseInterface
28
     */
29 32
    public function dispatchRequest(ServerRequestInterface $request) : ResponseInterface
30
    {
31 32
        $httpMethod = $request->getMethod();
32 32
        $uri = $request->getUri()->getPath();
33 32
        $match = $this->dispatch($httpMethod, $uri);
34
35 32
        switch ($match[0]) {
36 32
            case FastRoute::NOT_FOUND:
37 12
                $this->setNotFoundDecoratorMiddleware();
38 12
                break;
39 20
            case FastRoute::METHOD_NOT_ALLOWED:
40 4
                $allowed = (array) $match[1];
41 4
                $this->setMethodNotAllowedDecoratorMiddleware($allowed);
42 4
                break;
43 16
            case FastRoute::FOUND:
44 16
                $route = $this->ensureHandlerIsRoute($match[1], $httpMethod, $uri)->setVars($match[2]);
45 16
                $this->setFoundMiddleware($route);
46 16
                break;
47
        }
48
49 32
        return $this->handle($request);
50
    }
51
52
    /**
53
     * Ensure handler is a Route, honoring the contract of dispatchRequest.
54
     *
55
     * @param Route|mixed $matchingHandler
56
     * @param string $httpMethod
57
     * @param string $uri
58
     *
59
     * @return Route
60
     *
61
     */
62 16
    private function ensureHandlerIsRoute($matchingHandler, $httpMethod, $uri) : Route
63
    {
64 16
        if (is_a($matchingHandler, Route::class)) {
65 14
            return $matchingHandler;
66
        }
67 2
        return new Route($httpMethod, $uri, $matchingHandler);
68
    }
69
70
    /**
71
     * {@inheritdoc}
72
     */
73 32
    public function handle(ServerRequestInterface $request) : ResponseInterface
74
    {
75 32
        $middleware = $this->shiftMiddleware();
76
77 32
        if (is_null($middleware)) {
78
            throw new OutOfBoundsException('Reached end of middleware stack. Does your controller return a response?');
79
        }
80
81 32
        return $middleware->process($request, $this);
82
    }
83
84
    /**
85
     * Set up middleware for a found route
86
     *
87
     * @param \League\Route\Route $route
88
     *
89
     * @return void
90
     */
91 16
    protected function setFoundMiddleware(Route $route) : void
92
    {
93 16
        if (is_null($route->getStrategy())) {
94 2
            $route->setStrategy($this->getStrategy());
95
        }
96
97
        // wrap entire dispatch process in exception handler
98 16
        $this->prependMiddleware($route->getStrategy()->getExceptionHandler());
99
100
        // add group and route specific middleware
101 16
        if ($group = $route->getParentGroup()) {
102 4
            $this->middlewares($group->getMiddlewareStack());
103
        }
104
105 16
        $this->middlewares($route->getMiddlewareStack());
106
107
        // add actual route to end of stack
108 16
        $this->middleware($route);
109 16
    }
110
111
    /**
112
     * Set up middleware for a not found route
113
     *
114
     * @return void
115
     */
116 12
    protected function setNotFoundDecoratorMiddleware() : void
117
    {
118 12
        $middleware = $this->getStrategy()->getNotFoundDecorator(new NotFoundException);
119 12
        $this->prependMiddleware($middleware);
120 12
    }
121
122
    /**
123
     * Set up middleware for a not allowed route
124
     *
125
     * @param array $allowed
126
     *
127
     * @return void
128
     */
129 4
    protected function setMethodNotAllowedDecoratorMiddleware(array $allowed) : void
130
    {
131 4
        $middleware = $this->getStrategy()->getMethodNotAllowedDecorator(
132 4
            new MethodNotAllowedException($allowed)
133
        );
134
135 4
        $this->prependMiddleware($middleware);
136 4
    }
137
}
138