Completed
Push — master ( bbe84c...cc1044 )
by Joschi
02:10
created

Route::getDefaults()   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 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
/**
4
 * apparat-server
5
 *
6
 * @category    Apparat
7
 * @package     Apparat\Server
8
 * @subpackage  Apparat\Server\Ports
9
 * @author      Joschi Kuphal <[email protected]> / @jkphl
10
 * @copyright   Copyright © 2016 Joschi Kuphal <[email protected]> / @jkphl
11
 * @license     http://opensource.org/licenses/MIT The MIT License (MIT)
12
 */
13
14
/***********************************************************************************
15
 *  The MIT License (MIT)
16
 *
17
 *  Copyright © 2016 Joschi Kuphal <[email protected]> / @jkphl
18
 *
19
 *  Permission is hereby granted, free of charge, to any person obtaining a copy of
20
 *  this software and associated documentation files (the "Software"), to deal in
21
 *  the Software without restriction, including without limitation the rights to
22
 *  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
23
 *  the Software, and to permit persons to whom the Software is furnished to do so,
24
 *  subject to the following conditions:
25
 *
26
 *  The above copyright notice and this permission notice shall be included in all
27
 *  copies or substantial portions of the Software.
28
 *
29
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
31
 *  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
32
 *  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
33
 *  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34
 *  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35
 ***********************************************************************************/
36
37
namespace Apparat\Server\Ports;
38
39
use Apparat\Server\Ports\Contract\ActionInterface;
40
use Apparat\Server\Ports\Contract\RouteInterface;
41
42
/**
43
 * Route
44
 *
45
 * @package Apparat\Server
46
 * @subpackage Apparat\Server\Ports
47
 */
48
class Route implements RouteInterface
49
{
50
    /**
51
     * GET request
52
     *
53
     * @var string
54
     */
55
    const GET = 'GET';
56
    /**
57
     * POST request
58
     *
59
     * @var string
60
     */
61
    const POST = 'POST';
62
    /**
63
     * PATCH request
64
     *
65
     * @var string
66
     */
67
    const PATCH = 'PATCH';
68
    /**
69
     * DELETE request
70
     *
71
     * @var string
72
     */
73
    const DELETE = 'DELETE';
74
    /**
75
     * OPTIONS request
76
     *
77
     * @var string
78
     */
79
    const OPTIONS = 'OPTIONS';
80
    /**
81
     * HEAD request
82
     *
83
     * @var string
84
     */
85
    const HEAD = 'HEAD';
86
    /**
87
     * Allowed HTTP verbs
88
     *
89
     * @var array
90
     */
91
    protected static $validVerbs = [
92
        self::GET => true,
93
        self::POST => true,
94
        self::PATCH => true,
95
        self::DELETE => true,
96
        self::OPTIONS => true,
97
        self::HEAD => true
98
    ];
99
    /**
100
     * Route name
101
     *
102
     * @var string
103
     */
104
    protected $name;
105
    /**
106
     * Route path
107
     *
108
     * @var string
109
     */
110
    protected $path;
111
    /**
112
     * Route action
113
     *
114
     * @var string|callable
115
     */
116
    protected $action;
117
    /**
118
     * Route tokens
119
     *
120
     * @var array
121
     */
122
    protected $tokens = [];
123
    /**
124
     * Route default values
125
     *
126
     * @var array
127
     */
128
    protected $defaults = [];
129
    /**
130
     * Route wildcard name
131
     *
132
     * @var string|null
133
     */
134
    protected $wildcard = null;
135
    /**
136
     * Route host
137
     *
138
     * @var string|null
139
     */
140
    protected $host = null;
141
    /**
142
     * Allowed accept headers
143
     *
144
     * @var array
145
     */
146
    protected $accepts = [];
147
    /**
148
     * Allowed HTTP verbs
149
     *
150
     * @var array
151
     */
152
    protected $verbs = [];
153
    /**
154
     * Secure protocol behaviour
155
     *
156
     * @var boolean|null
157
     */
158
    protected $secure = false;
159
    /**
160
     * Authentication parameters
161
     *
162
     * @var mixed
163
     */
164
    protected $auth = null;
165
    /**
166
     * Custom extra parameters
167
     *
168
     * @var array
169
     */
170
    protected $extras = [];
171
172
    /**
173
     * Route constructor
174
     *
175
     * @param string|array $verbs Allowed HTTP verbs
176
     * @param string $name Route name
177
     * @param string $path Route path
178
     * @param string $action Route action
179
     */
180 1
    public function __construct($verbs, $name, $path, $action)
181
    {
182
        // Set and validate the allowed HTTP verbs
183 1
        $this->setAndValidateVerbs($verbs);
184
185
        // Set and validate the route name
186 1
        $this->setAndValidateName($name);
187
188
        // Set and validate the route path
189 1
        $this->setAndValidatePath($path);
190
191
        // Set and validate the route action
192 1
        $this->setAndValidateAction($action);
193 1
    }
194
195
    /**
196
     * Validate the allowed HTTP verbs
197
     *
198
     * @param string|array $verbs Allowed HTTP verbs
199
     * @throws InvalidArgumentException If the HTTP verb list is empty
200
     * @throws InvalidArgumentException If the HTTP verb is invalid
201
     */
202 1
    protected function setAndValidateVerbs($verbs)
203
    {
204 1
        $this->verbs = array_map('strtoupper', array_filter((array)$verbs));
205
206
        // If the HTTP verb list is empty
207 1
        if (!count($this->verbs)) {
208
            throw new InvalidArgumentException(
209
                'Empty route HTTP verbs',
210
                InvalidArgumentException::EMPTY_ROUTE_HTTP_VERBS
211
            );
212
        }
213
214
        // Run through all registered HTTP verbs
215 1
        foreach ($this->verbs as $verb) {
216
            // If the HTTP verb is invalid
217 1
            if (!array_key_exists($verb, self::$validVerbs)) {
218
                throw new InvalidArgumentException(
219
                    sprintf('Invalid route HTTP verb "%s"', $verb),
220
                    InvalidArgumentException::INVALID_ROUTE_HTTP_VERB
221
                );
222
            }
223 1
        }
224 1
    }
225
226
    /**
227
     * Set and validate the route name
228
     *
229
     * @param string $name Route name
230
     * @throws InvalidArgumentException If the route name is empty
231
     */
232 1
    protected function setAndValidateName($name)
233
    {
234 1
        $this->name = trim($name);
235
        // If the route name is empty
236 1
        if (!strlen($this->name)) {
237
            throw new InvalidArgumentException(
238
                'Route name must not be empty',
239
                InvalidArgumentException::EMPTY_ROUTE_NAME
240
            );
241
        }
242 1
    }
243
244
    /**
245
     * Set and validate the route path
246
     *
247
     * @param string $path Route path
248
     * @throws InvalidArgumentException If the route path is empty
249
     */
250 1
    protected function setAndValidatePath($path)
251
    {
252 1
        $this->path = trim($path);
253
        // If the route path is empty
254 1
        if (!strlen($this->path)) {
255
            throw new InvalidArgumentException(
256
                'Route path must not be empty',
257
                InvalidArgumentException::EMPTY_ROUTE_NAME
258
            );
259
        }
260 1
    }
261
262
    /**
263
     * Set and validate the route action
264
     *
265
     * @param string $action Route action
266
     * @throws InvalidArgumentException If the route action is empty
267
     * @throws InvalidArgumentException If the route action is not a class name
268
     * @throws InvalidArgumentException If the route action is neither a callable nor an ActionInterface
269
     */
270 1
    protected function setAndValidateAction($action)
271
    {
272
        // If the action is given as string
273 1
        if (is_string($action)) {
274 1
            $this->action = trim($action);
275
276
            // If the route action is empty
277 1
            if (!strlen($this->action)) {
278
                throw new InvalidArgumentException(
279
                    'Route action must not be empty',
280
                    InvalidArgumentException::EMPTY_ROUTE_ACTION
281
                );
282
            }
283
284
            // If the route action is not a class name
285 1
            if (!class_exists($this->action)) {
286
                throw new InvalidArgumentException(
287
                    'Route action must be an existing class name',
288
                    InvalidArgumentException::ROUTE_ACTION_MUST_BE_CLASSNAME
289
                );
290
            }
291
292
            // If the route action doesn't implement the ActionInterface
293 1
            $actionReflection = new \ReflectionClass($this->action);
294 1
            if (!$actionReflection->implementsInterface(ActionInterface::class)) {
295
                throw new InvalidArgumentException(
296
                    'Route action must implement '.ActionInterface::class,
297
                    InvalidArgumentException::ROUTE_ACTION_MUST_IMPLEMENT_ACTION_INTERFACE
298
                );
299
            }
300
301 1
            return;
302
        }
303
304
        // If the action is given as callable
305
        if (is_callable($action)) {
306
            $this->action = $action;
307
            return;
308
        }
309
310
        // If the route action is neither a callable nor an ActionInterface
311
        throw new InvalidArgumentException(
312
            'Route action must be a callable or '.ActionInterface::class,
313
            InvalidArgumentException::ROUTE_ACTION_NOT_CALLABLE_OR_ACTION_INTERFACE
314
        );
315
    }
316
317
    /**
318
     * Get the route name
319
     *
320
     * @return string Route name
321
     */
322 1
    public function getName()
323
    {
324 1
        return $this->name;
325
    }
326
327
    /**
328
     * Get the route path
329
     *
330
     * @return string Route path
331
     */
332 1
    public function getPath()
333
    {
334 1
        return $this->path;
335
    }
336
337
    /**
338
     * Get the route action
339
     *
340
     * @return callable|string Route action
341
     */
342 1
    public function getAction()
343
    {
344 1
        return $this->action;
345
    }
346
347
    /**
348
     * Get the route tokens
349
     *
350
     * @return array Route tokens
351
     */
352 1
    public function getTokens()
353
    {
354 1
        return $this->tokens;
355
    }
356
357
    /**
358
     * Set the route tokens
359
     *
360
     * @param array $tokens Route tokens
361
     * @return Route Self reference
362
     */
363 1
    public function setTokens(array $tokens)
364
    {
365 1
        $this->tokens = $tokens;
366 1
        return $this;
367
    }
368
369
    /**
370
     * Get the route defaults
371
     *
372
     * @return array Route defaults
373
     */
374 1
    public function getDefaults()
375
    {
376 1
        return $this->defaults;
377
    }
378
379
    /**
380
     * Set the route defaults
381
     *
382
     * @param array $defaults Route defaults
383
     * @return Route Self reference
384
     */
385
    public function setDefaults(array $defaults)
386
    {
387
        $this->defaults = $defaults;
388
        return $this;
389
    }
390
391
    /**
392
     * Set the route wildcard name
393
     *
394
     * @return null|string
395
     */
396 1
    public function getWildcard()
397
    {
398 1
        return $this->wildcard;
399
    }
400
401
    /**
402
     * Get the route wildcard name
403
     *
404
     * @param null|string $wildcard Wildcard name
405
     * @return Route Self reference
406
     */
407
    public function setWildcard($wildcard)
408
    {
409
        $this->wildcard = $wildcard;
410
        return $this;
411
    }
412
413
    /**
414
     * Get the route host
415
     *
416
     * @return null|string Route host
417
     */
418 1
    public function getHost()
419
    {
420 1
        return $this->host;
421
    }
422
423
    /**
424
     * Set the route host
425
     *
426
     * @param null|string $host Route host
427
     * @return Route Self reference
428
     */
429
    public function setHost($host)
430
    {
431
        $this->host = $host;
432
        return $this;
433
    }
434
435
    /**
436
     * Get the allowed Accept headers
437
     *
438
     * @return array Allowed Accept headers
439
     */
440 1
    public function getAccepts()
441
    {
442 1
        return $this->accepts;
443
    }
444
445
    /**
446
     * Set the allowed Accept headers
447
     *
448
     * @param array $accepts Allowed Accept headers
449
     * @return Route Self reference
450
     */
451
    public function setAccepts(array $accepts)
452
    {
453
        $this->accepts = $accepts;
454
        return $this;
455
    }
456
457
    /**
458
     * Get the allowed HTTP verbs
459
     *
460
     * @return array Allowed HTTP verbs
461
     */
462 1
    public function getVerbs()
463
    {
464 1
        return $this->verbs;
465
    }
466
467
    /**
468
     * Set the allowed HTTP verbs
469
     *
470
     * @param array $verbs Allowed HTTP verbs
471
     * @return Route Self reference
472
     */
473
    public function setVerbs(array $verbs)
474
    {
475
        $this->verbs = $verbs;
476
        return $this;
477
    }
478
479
    /**
480
     * Get the secure protocol mode
481
     *
482
     * @return boolean|null Secure protocol mode
483
     */
484 1
    public function getSecure()
485
    {
486 1
        return $this->secure;
487
    }
488
489
    /**
490
     * Set the secure protocol mode
491
     *
492
     * @param boolean|null $secure Secure protocol mode
493
     * @return Route Self reference
494
     */
495
    public function setSecure($secure)
496
    {
497
        $this->secure = $secure;
498
        return $this;
499
    }
500
501
    /**
502
     * Get the authentication information
503
     *
504
     * @return mixed Authentication information
505
     */
506 1
    public function getAuth()
507
    {
508 1
        return $this->auth;
509
    }
510
511
    /**
512
     * Set the authentication information
513
     *
514
     * @param mixed $auth Authentication information
515
     * @return Route Self reference
516
     */
517
    public function setAuth($auth)
518
    {
519
        $this->auth = $auth;
520
        return $this;
521
    }
522
523
    /**
524
     * Get the custom extra information
525
     *
526
     * @return array Custom extra information
527
     */
528 1
    public function getExtras()
529
    {
530 1
        return $this->extras;
531
    }
532
533
    /**
534
     * Set the custom extra information
535
     *
536
     * @param array $extras Custom extra information
537
     * @return Route Self reference
538
     */
539
    public function setExtras(array $extras)
540
    {
541
        $this->extras = $extras;
542
        return $this;
543
    }
544
}
545