Completed
Push — master ( 81d0e7...438276 )
by Aurimas
03:48
created

Router::buildRoutes()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 25
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 5
Metric Value
dl 0
loc 25
ccs 14
cts 14
cp 1
rs 8.439
cc 5
eloc 14
nc 6
nop 0
crap 5
1
<?php
2
3
namespace Thruster\Component\HttpRouter;
4
5
use FastRoute\BadRouteException;
6
use FastRoute\Dispatcher;
7
use FastRoute\RouteParser;
8
use FastRoute\DataGenerator;
9
use FastRoute\RouteCollector;
10
use Psr\Http\Message\ResponseInterface;
11
use Psr\Http\Message\ServerRequestInterface;
12
use Thruster\Component\HttpRouter\Exception\InvalidRouteOptionsException;
13
use Thruster\Component\HttpRouter\Exception\RouteNotFoundException;
14
use Thruster\Component\HttpRouter\Exception\RouteMethodNotAllowedException;
15
16
/**
17
 * Class Router
18
 *
19
 * @package Thruster\Component\HttpRouter
20
 * @author  Aurimas Niekis <[email protected]>
21
 */
22
class Router
23
{
24
    /**
25
     * @var array
26
     */
27
    protected $options;
28
29
    /**
30
     * @var array
31
     */
32
    protected $routes;
33
34
    /**
35
     * @var RouteableInterface
36
     */
37
    protected $handler;
38
39
    /**
40
     * @var RouteCollector
41
     */
42
    protected $routeCollector;
43
44
    /**
45
     * @var Dispatcher
46
     */
47
    protected $dispatcher;
48
49 8
    public function __construct(RouteableInterface $handler, array $options = [])
50
    {
51
        $options += [
52 8
            'route_parser' => 'FastRoute\\RouteParser\\Std',
53
            'data_generator' => 'FastRoute\\DataGenerator\\GroupCountBased',
54
            'dispatcher' => 'FastRoute\\Dispatcher\\GroupCountBased',
55
            'route_collector' => 'FastRoute\\RouteCollector',
56
        ];
57
58 8
        $this->routes = [];
59 8
        $this->handler = $handler;
60 8
        $this->options = $options;
61 8
    }
62
63 6
    public function buildRoutes()
64
    {
65 6
        $routeCollection = $this->getRouteCollector();
66
67 6
        foreach ($this->handler->getRoutes() as $name => $options) {
68 4
            if (count($options) < 3) {
69 1
                throw new InvalidRouteOptionsException($name);
70
            }
71
72 3
            $handler = array_pop($options);
73 3
            if (is_string($handler)) {
74 3
                $handler = [$this->handler, $handler];
75
            }
76
77 3
            $this->routes[$name] = $handler;
78
79 3
            $route = array_pop($options);
80
81
            try {
82 3
                $routeCollection->addRoute($options, $route, $name);
83 1
            } catch (BadRouteException $e) {
84 3
                throw new InvalidRouteOptionsException($name, $e);
85
            }
86
        }
87 4
    }
88
89
    /**
90
     * @param ServerRequestInterface $request
91
     *
92
     * @return ResponseInterface
93
     * @throws RouteMethodNotAllowedException
94
     * @throws RouteNotFoundException
95
     */
96 4
    public function handleRequest(ServerRequestInterface $request) : ResponseInterface
97
    {
98 4
        $dispatcher = $this->getDispatcher();
99 4
        $uri = $request->getUri();
100
101 4
        $route = $dispatcher->dispatch($request->getMethod(), $uri->getPath());
102
103 4
        switch ($route[0]) {
104 4
            case Dispatcher::NOT_FOUND:
105 1
                throw new RouteNotFoundException($request);
106 3
            case Dispatcher::METHOD_NOT_ALLOWED:
107 1
                throw new RouteMethodNotAllowedException($request, $route[1]);
108 2
            case Dispatcher::FOUND:
109
                $request = $request
110 1
                    ->withAttribute('route_name', $route[1])
111 1
                    ->withAttribute('route_params', $route[2]);
112
113 1
                return call_user_func($this->routes[$route[1]], $request);
114
        }
115
116 1
        throw new \LogicException('Should not reach this point');
117
    }
118
119
    /**
120
     * @return Dispatcher
121
     */
122 5
    public function getDispatcher() : Dispatcher
123
    {
124 5
        if ($this->dispatcher) {
125 4
            return $this->dispatcher;
126
        }
127
128 1
        $this->dispatcher = new $this->options['dispatcher'](
129 1
            $this->getRouteData()
130
        );
131
132 1
        return $this->dispatcher;
133
    }
134
135
    /**
136
     * @param Dispatcher $dispatcher
137
     *
138
     * @return $this
139
     */
140 4
    public function setDispatcher(Dispatcher $dispatcher) : self
141
    {
142 4
        $this->dispatcher = $dispatcher;
143
144 4
        return $this;
145
    }
146
147
    /**
148
     * @return RouteCollector
149
     */
150 6
    public function getRouteCollector() : RouteCollector
151
    {
152 6
        if ($this->routeCollector) {
153 2
            return $this->routeCollector;
154
        }
155
156 5
        $this->routeCollector = new $this->options['route_collector'](
157 5
            new $this->options['route_parser'](), new $this->options['data_generator']()
158
        );
159
160 5
        return $this->routeCollector;
161
    }
162
163
    /**
164
     * @param RouteCollector $routeCollector
165
     *
166
     * @return $this
167
     */
168 1
    public function setRouteCollector(RouteCollector $routeCollector) : self
169
    {
170 1
        $this->routeCollector = $routeCollector;
171
172 1
        return $this;
173
    }
174
175
    /**
176
     * @return array
177
     */
178 1
    public function getRouteData() : array
179
    {
180 1
        $this->buildRoutes();
181
182 1
        return $this->getRouteCollector()->getData();
183
    }
184
}
185