Passed
Push — master ( d17b70...413065 )
by Divine Niiquaye
03:12
created

Route::getPath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Flight Routing.
7
 *
8
 * PHP version 7.1 and above required
9
 *
10
 * @author    Divine Niiquaye Ibok <[email protected]>
11
 * @copyright 2019 Biurad Group (https://biurad.com/)
12
 * @license   https://opensource.org/licenses/BSD-3-Clause License
13
 *
14
 * For the full copyright and license information, please view the LICENSE
15
 * file that was distributed with this source code.
16
 */
17
18
namespace Flight\Routing\Annotation;
19
20
use Flight\Routing\Exceptions\InvalidAnnotationException;
21
22
/**
23
 * Annotation class for @Route().
24
 *
25
 * @Annotation
26
 *
27
 * ```php
28
 * <?php
29
 *  /**
30
 *   * @Route("/blog" name="blog", methods={"GET", "HEAD"}, defaults={"_locale" = "en"})
31
 *   * /
32
 *  class Blog
33
 *  {
34
 *     /**
35
 *      * @Route("/{_locale}", name="index", methods={"GET", "HEAD"})
36
 *      * /
37
 *     public function index()
38
 *     {
39
 *     }
40
 *     /**
41
 *      * @Route("/{_locale}/{id}", name="post", methods={"GET", "HEAD"}, patterns={"id" = "[0-9]+"})
42
 *      * /
43
 *     public function show($id)
44
 *     {
45
 *     }
46
 *  }
47
 * ```
48
 *
49
 * On PHP 8, the annotation class can be used as an attribute as well:
50
 * ```php
51
 *     #[Route('/Blog', methods: ['GET', 'POST'])]
52
 *     class Blog
53
 *     {
54
 *         #[Route('/', name: 'blog_index')]
55
 *         public function index()
56
 *         {
57
 *         }
58
 *         #[Route('/{id}', name: 'blog_post', patterns: ["id" => '\d+'])]
59
 *         public function show()
60
 *         {
61
 *         }
62
 *     }
63
 * ```
64
 *
65
 * @Target({"CLASS", "METHOD"})
66
 */
67
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD)]
68
final class Route
69
{
70
    /** @var string @Required */
71
    private $path;
72
73
    /** @var null|string @Required */
74
    private $name;
75
76
    /** @var string[] @Required */
77
    private $methods;
78
79
    /** @var null|string */
80
    private $domain;
81
82
    /** @var string[] */
83
    private $schemes;
84
85
    /** @var string[] */
86
    private $middlewares;
87
88
    /** @var array<string,string> */
89
    private $patterns;
90
91
    /** @var array<string,mixed> */
92
    private $defaults;
93
94
    /**
95
     * @param array<string,mixed> $params      data array managed by the Doctrine Annotations library or the path
96
     * @param null|string         $path
97
     * @param string              $name
98
     * @param string[]            $methods
99
     * @param string[]            $patterns
100
     * @param string[]            $defaults
101
     * @param string[]            $domain
102
     * @param string[]            $schemes
103
     * @param string[]            $middlewares
104
     */
105 121
    public function __construct(
106
        array $params = [],
107
        ?string $path = null,
108
        string $name = null,
109
        array $methods = [],
110
        array $patterns = [],
111
        array $defaults = [],
112
        string $domain = null,
113
        array $schemes = [],
114
        array $middlewares = []
115
    ) {
116 121
        if (isset($params['value'])) {
117 5
            $params['path'] = $params['value'];
118 5
            unset($params['value']);
119 120
        } elseif (\is_string($params)) {
120
            $params = ['path' => $params];
121
        }
122
123 121
        $params = \array_merge([
124 121
            'middlewares' => $middlewares,
125 121
            'patterns'    => $patterns,
126 121
            'defaults'    => $defaults,
127 121
            'schemes'     => $schemes,
128 121
            'methods'     => $methods,
129 121
            'domain'      => $domain,
130 121
            'name'        => $name,
131 121
            'path'        => $path,
132 121
        ], $params);
133
134 121
        $this->assertParamsContainValidName($params);
135 108
        $this->assertParamsContainValidPath($params);
136 94
        $this->assertParamsContainValidMethods($params);
137 73
        $this->assertParamsContainValidSchemes($params);
138 55
        $this->assertParamsContainValidMiddlewares($params);
139 35
        $this->assertParamsContainValidPatterns($params);
140 17
        $this->assertParamsContainValidDefaults($params);
141
142 7
        $this->name        = $params['name'];
143 7
        $this->path        = $params['path'];
144 7
        $this->methods     = $params['methods'];
145 7
        $this->domain      = $params['domain'];
146 7
        $this->middlewares = $params['middlewares'];
147 7
        $this->schemes     = $params['schemes'];
148 7
        $this->patterns    = $params['patterns'];
149 7
        $this->defaults    = $params['defaults'];
150 7
    }
151
152
    /**
153
     * @return string
154
     */
155 6
    public function getPath(): string
156
    {
157 6
        return $this->path;
158
    }
159
160
    /**
161
     * @return null|string
162
     */
163 6
    public function getDomain(): ?string
164
    {
165 6
        return $this->domain;
166
    }
167
168
    /**
169
     * @return null|string
170
     */
171 7
    public function getName(): ?string
172
    {
173 7
        return $this->name;
174
    }
175
176
    /**
177
     * @return array<string,string>
178
     */
179 6
    public function getPatterns(): array
180
    {
181 6
        return $this->patterns;
182
    }
183
184
    /**
185
     * @return string[]
186
     */
187 6
    public function getMethods(): array
188
    {
189 6
        return $this->methods;
190
    }
191
192
    /**
193
     * @return string[]
194
     */
195 6
    public function getMiddlewares(): array
196
    {
197 6
        return $this->middlewares;
198
    }
199
200
    /**
201
     * @return string[]
202
     */
203 6
    public function getSchemes(): array
204
    {
205 6
        return $this->schemes;
206
    }
207
208
    /**
209
     * @return array<string,mixed>
210
     */
211 6
    public function getDefaults(): array
212
    {
213 6
        return $this->defaults;
214
    }
215
216
    /**
217
     * @param array<string,mixed> $params
218
     *
219
     * @throws InvalidAnnotationException
220
     */
221 121
    private function assertParamsContainValidName(array $params): void
222
    {
223 121
        if (null === $params['name']) {
224 5
            return;
225
        }
226
227 120
        if (empty($params['name']) || !\is_string($params['name'])) {
228 13
            throw new InvalidAnnotationException(\sprintf(
229 13
                '@Route.name must %s.',
230 13
                empty($params['name']) ? 'be not an empty string' : 'contain only a string'
231
            ));
232
        }
233 107
    }
234
235
    /**
236
     * @param array<string,mixed> $params
237
     *
238
     * @throws InvalidAnnotationException
239
     */
240 108
    private function assertParamsContainValidPath(array $params): void
241
    {
242 108
        if (empty($params['path']) || !\is_string($params['path'])) {
243 14
            throw new InvalidAnnotationException('@Route.path must be not an empty string.');
244
        }
245 94
    }
246
247
    /**
248
     * @param array<string,mixed> $params
249
     *
250
     * @throws InvalidAnnotationException
251
     */
252 94
    private function assertParamsContainValidMethods(array $params): void
253
    {
254 94
        if (!\is_array($params['methods'])) {
255 11
            throw new InvalidAnnotationException('@Route.methods must contain only an array.');
256
        }
257
258 83
        foreach ($params['methods'] as $method) {
259 83
            if (!\is_string($method)) {
260 10
                throw new InvalidAnnotationException('@Route.methods must contain only strings.');
261
            }
262
        }
263 73
    }
264
265
    /**
266
     * @param array<string,mixed> $params
267
     *
268
     * @throws InvalidAnnotationException
269
     */
270 55
    private function assertParamsContainValidMiddlewares(array $params): void
271
    {
272 55
        if (!\is_array($params['middlewares'])) {
273 10
            throw new InvalidAnnotationException('@Route.middlewares must be an array.');
274
        }
275
276 45
        foreach ($params['middlewares'] as $middleware) {
277 15
            if (!\is_string($middleware)) {
278 10
                throw new InvalidAnnotationException('@Route.middlewares must contain only strings.');
279
            }
280
        }
281 35
    }
282
283
    /**
284
     * @param array<string,mixed> $params
285
     *
286
     * @throws InvalidAnnotationException
287
     */
288 35
    private function assertParamsContainValidPatterns(array $params): void
289
    {
290 35
        if (!\is_array($params['patterns'])) {
291 9
            throw new InvalidAnnotationException('@Route.patterns must be an array.');
292
        }
293
294 26
        foreach ($params['patterns'] as $pattern) {
295 14
            if (!\is_string($pattern)) {
296 9
                throw new InvalidAnnotationException('@Route.patterns must contain only strings.');
297
            }
298
        }
299 17
    }
300
301
    /**
302
     * @param array<string,mixed> $params
303
     *
304
     * @throws InvalidAnnotationException
305
     */
306 73
    private function assertParamsContainValidSchemes(array $params): void
307
    {
308 73
        if (!\is_array($params['schemes'])) {
309 9
            throw new InvalidAnnotationException('@Route.schemes must be an array.');
310
        }
311
312 64
        foreach ($params['schemes'] as $scheme) {
313 14
            if (!\is_string($scheme)) {
314 9
                throw new InvalidAnnotationException('@Route.schemes must contain only strings.');
315
            }
316
        }
317 55
    }
318
319
    /**
320
     * @param array<string,mixed> $params
321
     *
322
     * @throws InvalidAnnotationException
323
     */
324 17
    private function assertParamsContainValidDefaults(array $params): void
325
    {
326 17
        if (!\is_array($params['defaults'])) {
327 10
            throw new InvalidAnnotationException('@Route.defaults must be an array.');
328
        }
329 7
    }
330
}
331