Completed
Push — master ( 495169...b31514 )
by Changwan
10:11
created

RouteCollection::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 3
dl 0
loc 8
ccs 6
cts 6
cp 1
crap 1
rs 9.4285
c 0
b 0
f 0
1
<?php
2
namespace Wandu\Router;
3
4
use FastRoute\DataGenerator\GroupCountBased as GCBGenerator;
5
use IteratorAggregate;
6
use Psr\Http\Message\ServerRequestInterface;
7
use Wandu\Router\Contracts\Dispatchable;
8
use Wandu\Router\Contracts\LoaderInterface;
9
use Wandu\Router\Contracts\ResponsifierInterface;
10
use Wandu\Router\Contracts\Routable;
11
use Wandu\Router\Contracts\RouteFluent;
12
use Wandu\Router\Path\Pattern;
13
14
class RouteCollection implements Routable, IteratorAggregate, Dispatchable
15
{
16
    /** @var \Wandu\Router\RouteCollection[] */
17
    protected $routers = [];
18
19
    /** @var \Wandu\Router\Route[] */
20
    protected $routes = [];
21
22
    /** @var array */
23
    protected $status;
24
25
    /**
26
     * @param string $prefix
27
     * @param array $middlewares
28
     * @param array $domains
29
     */
30 18
    public function __construct($prefix = '', $middlewares = [], $domains = [])
31
    {
32 18
        $this->status = [
33 18
            'prefix' => $prefix,
34 18
            'middlewares' => $middlewares,
35 18
            'domains' => $domains,
36
        ];
37 18
    }
38
39
    /**
40
     * @return array
41
     */
42 4
    public function toArray()
43
    {
44 4
        return iterator_to_array($this->getIterator());
45
    }
46
    
47
    /**
48
     * {@inheritdoc}
49
     */
50 1
    public function prefix(string $prefix, callable $handler)
51
    {
52 1
        $this->group(['prefix' => $prefix, ], $handler);
53 1
    }
54
55
    /**
56
     * {@inheritdoc}
57
     */
58 1
    public function domain($domain, callable $handler)
59
    {
60 1
        $this->group(['domain' => $domain, ], $handler);
61 1
    }
62
63
    /**
64
     * {@inheritdoc}
65
     */
66 1
    public function middleware($middleware, callable $handler)
67
    {
68 1
        $this->group(['middleware' => $middleware, ], $handler);
69 1
    }
70
71
    /**
72
     * {@inheritdoc}
73
     */
74 4
    public function group(array $attributes, callable $handler)
75
    {
76 4
        $prefix = '';
77 4
        if (isset($attributes['prefix'])) {
78 2
            $prefix = "{$this->status['prefix']}/" . $attributes['prefix'];
79
        }
80 4
        $middlewares = $this->status['middlewares'];
81 4
        if (isset($attributes['middleware'])) {
82 2
            $middlewares = array_merge($middlewares, array_filter((array)$attributes['middleware']));
83
        }
84 4
        if (isset($attributes['middlewares'])) {
85
            $middlewares = array_merge($middlewares, array_filter((array)$attributes['middlewares']));
86
        }
87 4
        $domains = [];
88 4
        if (isset($attributes['domain'])) {
89 2
            $domains = (array) $attributes['domain'];
90
        }
91 4
        if (isset($attributes['domains'])) {
92
            $domains = (array) $attributes['domains'];
93
        }
94 4
        $router = new RouteCollection($prefix, $middlewares, $domains);
95 4
        call_user_func($handler, $router);
96 4
        $this->routers[] = $router;
97 4
    }
98
99
    /**
100
     * {@inheritdoc}
101
     */
102
    public function append(callable $handler)
103
    {
104
        call_user_func($handler, $this);
105
    }
106
107
    public function resource($className, $except = [], $only = [])
0 ignored issues
show
Unused Code introduced by
The parameter $except is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $only is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
108
    {
109
        $this->get('', $className, 'index');
110
        $this->post('', $className, 'store');
111
        $this->get(':id', $className, 'show');
112
        $this->put(':id', $className, 'update');
113
        $this->patch(':id', $className, 'patch');
114
        $this->delete(':id', $className, 'destroy');
115
        // $this->options();
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
116
    }
117
118
    /**
119
     * {@inheritdoc}
120
     */
121 11
    public function get(string $path, string $className, string $methodName = 'index'): RouteFluent
122
    {
123 11
        return $this->createRoute(['GET', 'HEAD'], $path, $className, $methodName);
124
    }
125
126
    /**
127
     * {@inheritdoc}
128
     */
129 6
    public function post(string $path, string $className, string $methodName = 'index'): RouteFluent
130
    {
131 6
        return $this->createRoute(['POST'], $path, $className, $methodName);
132
    }
133
134
    /**
135
     * {@inheritdoc}
136
     */
137 1
    public function put(string $path, string $className, string $methodName = 'index'): RouteFluent
138
    {
139 1
        return $this->createRoute(['PUT'], $path, $className, $methodName);
140
    }
141
142
    /**
143
     * {@inheritdoc}
144
     */
145 1
    public function delete(string $path, string $className, string $methodName = 'index'): RouteFluent
146
    {
147 1
        return $this->createRoute(['DELETE'], $path, $className, $methodName);
148
    }
149
150
    /**
151
     * {@inheritdoc}
152
     */
153 1
    public function options(string $path, string $className, string $methodName = 'index'): RouteFluent
154
    {
155 1
        return $this->createRoute(['OPTIONS'], $path, $className, $methodName);
156
    }
157
158
    /**
159
     * {@inheritdoc}
160
     */
161 1
    public function patch(string $path, string $className, string $methodName = 'index'): RouteFluent
162
    {
163 1
        return $this->createRoute(['PATCH'], $path, $className, $methodName);
164
    }
165
166
    /**
167
     * {@inheritdoc}
168
     */
169 1
    public function any(string $path, string $className, string $methodName = 'index'): RouteFluent
170
    {
171 1
        return $this->createRoute([
172 1
            'GET',
173
            'HEAD',
174
            'POST',
175
            'PUT',
176
            'DELETE',
177
            'OPTIONS',
178
            'PATCH'
179 1
        ], $path, $className, $methodName);
180
    }
181
182
    /**
183
     * {@inheritdoc}
184
     */
185 18
    public function createRoute(array $methods, string $path, string $className, string $methodName = 'index'): RouteFluent
186
    {
187 18
        $path = trim("{$this->status['prefix']}/{$path}", '/');
188 18
        while(strpos($path, '//') !== false) {
189 1
            $path = str_replace('//', '/', $path);
190
        }
191 18
        $path = '/' . $path;
192 18
        $route = new Route($className, $methodName, $this->status['middlewares'], $this->status['domains']);
193 18
        $this->routes[] = [$methods, $path, $route];
194 18
        return $route;
195
    }
196
197
    /**
198
     * {@inheritdoc}
199
     */
200 18
    public function getIterator()
201
    {
202 18
        foreach ($this->routes as $route) {
203 18
            yield $route;
204
        }
205 18
        foreach ($this->routers as $router) {
206 4
            foreach ($router as $route) {
207 4
                yield $route;
208
            }
209
        }
210 18
    }
211
212
    /**
213
     * {@inheritdoc}
214
     */
215 14
    public function dispatch(LoaderInterface $loader, ResponsifierInterface $responsifier, ServerRequestInterface $request)
216
    {
217 14
        return $this->compile()->dispatch($loader, $responsifier, $request);
218
    }
219
220
    /**
221
     * @return \Wandu\Router\CompiledRouteCollection
222
     */
223 14
    public function compile(): CompiledRouteCollection
224
    {
225 14
        $routeMap = [];
226
227
        /** @var \FastRoute\DataGenerator\GroupCountBased[] $generators */
228 14
        $generators = [];
229
230
        /**
231
         * @var array|string[] $methods
232
         * @var string $path
233
         * @var \Wandu\Router\Route $route
234
         */
235 14
        foreach ($this->getIterator() as list($methods, $path, $route)) {
236 14
            $pathPattern = new Pattern($path);
237
238 14
            $handleId = uniqid('HANDLER');
239 14
            $routeMap[$handleId] = $route;
240
241 14
            foreach ($pathPattern->parse() as $parsedPath) {
242 14
                foreach ($methods as $method) {
243 14
                    $domains = $route->getDomains();
244 14
                    if (count($domains)) {
245 1
                        foreach ($domains as $domain) {
246 1
                            if (!isset($generators[$domain])) {
247 1
                                $generators[$domain] = new GCBGenerator();
248
                            }
249 1
                            $generators[$domain]->addRoute($method, $parsedPath, $handleId);
250
                        }
251
                    } else {
252 14
                        if (!isset($generators['@'])) {
253 14
                            $generators['@'] = new GCBGenerator();
254
                        }
255 14
                        $generators['@']->addRoute($method, $parsedPath, $handleId);
256
                    }
257
                }
258
            }
259
        }
260
261 14
        $compiledRoutes = array_map(function (GCBGenerator $generator) {
262 14
            return $generator->getData();
263 14
        }, $generators);
264 14
        return new CompiledRouteCollection($compiledRoutes, $routeMap);
265
    }
266
}
267