Completed
Push — develop ( 019067...35e51d )
by Neomerx
03:05
created

BaseGroup::put()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
nc 1
cc 1
eloc 2
nop 3
crap 1
1
<?php namespace Limoncello\Core\Routing;
2
3
/**
4
 * Copyright 2015-2018 [email protected]
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
use Closure;
20
use Limoncello\Contracts\Routing\GroupInterface;
21
use Limoncello\Contracts\Routing\RouteInterface;
22
use Limoncello\Core\Reflection\CheckCallableTrait;
23
use Limoncello\Core\Routing\Traits\CallableTrait;
24
use Limoncello\Core\Routing\Traits\HasConfiguratorsTrait;
25
use Limoncello\Core\Routing\Traits\HasMiddlewareTrait;
26
use Limoncello\Core\Routing\Traits\HasRequestFactoryTrait;
27
use Limoncello\Core\Routing\Traits\UriTrait;
28
use ReflectionException;
29
30
/**
31
 * @package Limoncello\Core
32
 *
33
 * @SuppressWarnings(PHPMD.TooManyPublicMethods)
34
 */
35
abstract class BaseGroup implements GroupInterface
36
{
37
    use CallableTrait, UriTrait, HasRequestFactoryTrait, CheckCallableTrait;
38
39
    use HasMiddlewareTrait {
40
        addMiddleware as private addMiddlewareImpl;
41
    }
42
43
    use HasConfiguratorsTrait {
44
        addConfigurators as private addConfiguratorsImpl;
45
    }
46
47
    /** Default value if routes should use request factory from its group */
48
    const USE_FACTORY_FROM_GROUP_DEFAULT = true;
49
50
    /**
51
     * @var null|GroupInterface
52
     */
53
    private $parent;
54
55
    /**
56
     * @var string
57
     */
58
    private $uriPrefix = '';
59
60
    /**
61
     * @var string|null
62
     */
63
    private $name = null;
64
65
    /**
66
     * @var array
67
     */
68
    private $items = [];
69
70
    /**
71
     * @var bool
72
     */
73
    private $trailSlashes = false;
74
75
    /**
76
     * @return self
0 ignored issues
show
Documentation introduced by
Should the return type not be \self?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
77
     */
78
    abstract protected function createGroup(): self;
79
80
    /**
81
     * @param GroupInterface $parent
82
     *
83
     * @return $this
84
     */
85 17
    public function setParentGroup(GroupInterface $parent)
86
    {
87 17
        $this->parent = $parent;
88
89 17
        return $this;
90
    }
91
92
    /**
93
     * @param string $uriPrefix
94
     *
95
     * @return self
96
     */
97 17
    public function setUriPrefix(string $uriPrefix): self
98
    {
99 17
        $this->uriPrefix = $uriPrefix;
100
101 17
        return $this;
102
    }
103
104
    /**
105
     * @param string $name
106
     *
107
     * @return self
108
     */
109 1
    public function setName(string $name): self
110
    {
111 1
        $this->name = $name;
112
113 1
        return $this;
114
    }
115
116
    /**
117
     * @return self
118
     */
119 17
    public function clearName(): self
120
    {
121 17
        $this->name = null;
122
123 17
        return $this;
124
    }
125
126
    /**
127
     * @param bool $trailSlashes
128
     *
129
     * @return self
130
     */
131 17
    public function setHasTrailSlash(bool $trailSlashes): self
132
    {
133 17
        $this->trailSlashes = $trailSlashes;
134
135 17
        return $this;
136
    }
137
138
    /**
139
     * @inheritdoc
140
     */
141 18
    public function parentGroup(): ?GroupInterface
142
    {
143 18
        return $this->parent;
144
    }
145
146
    /**
147
     * @inheritdoc
148
     */
149 18
    public function getUriPrefix(): string
150
    {
151 18
        $parentPrefix = $this->getParentUriPrefix();
152 18
        if ($parentPrefix !== null) {
153 17
            return $this->normalizeUri($this->concatUri($parentPrefix, $this->uriPrefix), $this->hasTrailSlash());
154
        }
155
156 18
        return $this->normalizeUri($this->uriPrefix, $this->hasTrailSlash());
157
    }
158
159
    /**
160
     * @inheritdoc
161
     */
162 8
    public function getName(): ?string
163
    {
164 8
        return $this->name;
165
    }
166
167
    /**
168
     * @inheritdoc
169
     */
170 17
    public function getMiddleware(): array
171
    {
172 17
        $result = array_merge($this->getParentMiddleware(), $this->middleware);
173
174 17
        return $result;
175
    }
176
177
    /**
178
     * @inheritdoc
179
     */
180 1
    public function addMiddleware(array $middleware): GroupInterface
181
    {
182 1
        return $this->addMiddlewareImpl($middleware);
183
    }
184
185
    /**
186
     * @inheritdoc
187
     */
188 17
    public function getContainerConfigurators(): array
189
    {
190 17
        $result = array_merge($this->getParentConfigurators(), $this->configurators);
191
192 17
        return $result;
193
    }
194
195
    /**
196
     * @inheritdoc
197
     */
198 1
    public function addContainerConfigurators(array $configurators): GroupInterface
199
    {
200 1
        return $this->addConfiguratorsImpl($configurators);
201
    }
202
203
    /**
204
     * @inheritdoc
205
     */
206 17
    public function getRequestFactory(): ?callable
207
    {
208 17
        if ($this->isRequestFactorySet() === true) {
209 9
            return $this->requestFactory;
210
        }
211
212 15
        $parent = $this->parentGroup();
213 15
        $result = $parent === null ? $this->getDefaultRequestFactory() : $parent->getRequestFactory();
214
215 15
        return $result;
216
    }
217
218
    /**
219
     * @inheritdoc
220
     */
221 18
    public function getRoutes(): iterable
222
    {
223 18
        foreach ($this->items as $routeOrGroup) {
224 18
            if ($routeOrGroup instanceof RouteInterface) {
225
                /** @var RouteInterface $routeOrGroup */
226 18
                yield $routeOrGroup;
227 18
                continue;
228
            }
229
230
            /** @var GroupInterface $routeOrGroup */
231 17
            foreach ($routeOrGroup->getRoutes() as $route) {
232 17
                yield $route;
233
            }
234
        }
235
    }
236
237
    /**
238
     * @inheritdoc
239
     */
240 17
    public function group(string $prefix, Closure $closure, array $parameters = []): GroupInterface
241
    {
242
        list($middleware, $configurators, $factoryWasGiven, $requestFactory, $name) =
243 17
            $this->normalizeGroupParameters($parameters);
244
245 17
        $group = $this->createGroup()
246 17
            ->setUriPrefix($prefix)
247 17
            ->setMiddleware($middleware)
248 17
            ->setConfigurators($configurators);
249 17
        $name === null ? $group->clearName() : $group->setName($name);
250
251 17
        $factoryWasGiven === false ?: $group->setRequestFactory($requestFactory);
252
253 17
        return $this->addGroup($closure, $group);
254
    }
255
256
    /**
257
     * @inheritdoc
258
     */
259 17
    public function addGroup(Closure $closure, GroupInterface $group): GroupInterface
260
    {
261 17
        $closure($group);
262
263 17
        $this->items[] = $group;
264
265 17
        return $this;
266
    }
267
268
    /**
269
     * @inheritdoc
270
     */
271 18
    public function addRoute(RouteInterface $route): GroupInterface
272
    {
273 18
        $this->items[] = $route;
274
275 18
        return $this;
276
    }
277
278
    /**
279
     * @inheritdoc
280
     *
281
     * @throws ReflectionException
282
     */
283 22
    public function method(string $method, string $uriPath, callable $handler, array $parameters = []): GroupInterface
284
    {
285
        list($middleware, $configurators, $requestFactory, $useGroupFactory, $name) =
286 22
            $this->normalizeRouteParameters($parameters);
287
288 22
        $uriPath = $this->normalizeUri($uriPath, $this->hasTrailSlash());
289
290 22
        $route = $this->createRoute($this, $method, $uriPath, $handler)
291 21
            ->setUseGroupRequestFactory($useGroupFactory)
292 21
            ->setRequestFactory($requestFactory)
293 20
            ->setConfigurators($configurators)
294 19
            ->setMiddleware($middleware)
295 18
            ->setName($name);
296
297 18
        return $this->addRoute($route);
298
    }
299
300
    /**
301
     * @inheritdoc
302
     *
303
     * @throws ReflectionException
304
     */
305 22
    public function get(string $uriPath, callable $handler, array $parameters = []): GroupInterface
306
    {
307 22
        return $this->method('GET', $uriPath, $handler, $parameters);
308
    }
309
310
    /**
311
     * @inheritdoc
312
     *
313
     * @throws ReflectionException
314
     */
315 16
    public function post(string $uriPath, callable $handler, array $parameters = []): GroupInterface
316
    {
317 16
        return $this->method('POST', $uriPath, $handler, $parameters);
318
    }
319
320
    /**
321
     * @inheritdoc
322
     *
323
     * @throws ReflectionException
324
     */
325 1
    public function put(string $uriPath, callable $handler, array $parameters = []): GroupInterface
326
    {
327 1
        return $this->method('PUT', $uriPath, $handler, $parameters);
328
    }
329
330
    /**
331
     * @inheritdoc
332
     *
333
     * @throws ReflectionException
334
     */
335 2
    public function patch(string $uriPath, callable $handler, array $parameters = []): GroupInterface
336
    {
337 2
        return $this->method('PATCH', $uriPath, $handler, $parameters);
338
    }
339
340
    /**
341
     * @inheritdoc
342
     *
343
     * @throws ReflectionException
344
     */
345 10
    public function delete(string $uriPath, callable $handler, array $parameters = []): GroupInterface
346
    {
347 10
        return $this->method('DELETE', $uriPath, $handler, $parameters);
348
    }
349
350
    /**
351
     * @inheritdoc
352
     */
353 22
    public function hasTrailSlash(): bool
354
    {
355 22
        return $this->trailSlashes;
356
    }
357
358
    /**
359
     * @param GroupInterface $group
360
     * @param string         $method
361
     * @param string         $uriPath
362
     * @param callable       $handler
363
     *
364
     * @return Route
365
     *
366
     * @throws ReflectionException
367
     */
368 22
    protected function createRoute(GroupInterface $group, string $method, string $uriPath, callable $handler): Route
369
    {
370 22
        $route = (new Route($group, $method, $uriPath, $handler));
371
372 21
        return $route;
373
    }
374
375
    /**
376
     * @param array $parameters
377
     *
378
     * @return array
379
     */
380 22
    protected function normalizeRouteParameters(array $parameters): array
381
    {
382 22
        $factoryWasGiven = array_key_exists(RouteInterface::PARAM_REQUEST_FACTORY, $parameters);
383
        $useGroupFactory =
384 22
            $parameters[RouteInterface::PARAM_FACTORY_FROM_GROUP] ?? self::USE_FACTORY_FROM_GROUP_DEFAULT;
385
386
        return [
387 22
            $parameters[RouteInterface::PARAM_MIDDLEWARE_LIST] ?? [],
388 22
            $parameters[RouteInterface::PARAM_CONTAINER_CONFIGURATORS] ?? [],
389 22
            $parameters[RouteInterface::PARAM_REQUEST_FACTORY] ?? null,
390 22
            $factoryWasGiven === true ? false : $useGroupFactory,
391 22
            $parameters[RouteInterface::PARAM_NAME] ?? null,
392
        ];
393
    }
394
395
    /**
396
     * @param array $parameters
397
     *
398
     * @return array
399
     */
400 25
    protected function normalizeGroupParameters(array $parameters): array
401
    {
402 25
        $factoryWasGiven = array_key_exists(GroupInterface::PARAM_REQUEST_FACTORY, $parameters);
403
404
        return [
405 25
            $parameters[GroupInterface::PARAM_MIDDLEWARE_LIST] ?? [],
406 25
            $parameters[GroupInterface::PARAM_CONTAINER_CONFIGURATORS] ?? [],
407 25
            $factoryWasGiven,
408 25
            $parameters[GroupInterface::PARAM_REQUEST_FACTORY] ?? null,
409 25
            $parameters[GroupInterface::PARAM_NAME_PREFIX] ?? null,
410
        ];
411
    }
412
413
    /**
414
     * @return null|string
415
     */
416 18
    private function getParentUriPrefix(): ?string
417
    {
418 18
        $parent = $this->parentGroup();
419 18
        $result = $parent === null ? null : $parent->getUriPrefix();
420
421 18
        return $result;
422
    }
423
424
    /**
425
     * @return array
426
     */
427 17
    private function getParentMiddleware(): array
428
    {
429 17
        $parent = $this->parentGroup();
430 17
        $result = $parent === null ? [] : $parent->getMiddleware();
431
432 17
        return $result;
433
    }
434
435
    /**
436
     * @return array
437
     */
438 17
    private function getParentConfigurators(): array
439
    {
440 17
        $parent = $this->parentGroup();
441 17
        $result = $parent === null ? [] : $parent->getContainerConfigurators();
442
443 17
        return $result;
444
    }
445
}
446