Completed
Push — master ( 3b17e6...bbe84c )
by Joschi
02:12
created

Route::setSecure()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 5
ccs 0
cts 5
cp 0
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
crap 2
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
41
/**
42
 * Route
43
 *
44
 * @package Apparat\Server
45
 * @subpackage Apparat\Server\Ports
46
 */
47
class Route
48
{
49
    /**
50
     * Route name
51
     *
52
     * @var string
53
     */
54
    protected $name;
55
    /**
56
     * Route path
57
     *
58
     * @var string
59
     */
60
    protected $path;
61
    /**
62
     * Route action
63
     *
64
     * @var string
65
     */
66
    protected $action;
67
    /**
68
     * Route tokens
69
     *
70
     * @var array
71
     */
72
    protected $tokens = [];
73
    /**
74
     * Route default values
75
     *
76
     * @var array
77
     */
78
    protected $defaults = [];
79
    /**
80
     * Route wildcard name
81
     *
82
     * @var string|null
83
     */
84
    protected $wildcard = null;
85
    /**
86
     * Route host
87
     *
88
     * @var string|null
89
     */
90
    protected $host = null;
91
    /**
92
     * Allowed accept headers
93
     *
94
     * @var array
95
     */
96
    protected $accepts = [];
97
    /**
98
     * Allowed HTTP verbs
99
     *
100
     * @var array
101
     */
102
    protected $verbs = [];
103
    /**
104
     * Secure protocol behaviour
105
     *
106
     * @var boolean|null
107
     */
108
    protected $secure = false;
109
    /**
110
     * Authentication parameters
111
     *
112
     * @var mixed
113
     */
114
    protected $auth = null;
115
    /**
116
     * Custom extra parameters
117
     *
118
     * @var mixed
119
     */
120
    protected $extras = null;
121
    /**
122
     * Allowed HTTP verbs
123
     *
124
     * @var array
125
     */
126
    protected static $validVerbs = [
127
        self::GET => true,
128
        self::POST => true,
129
        self::PATCH => true,
130
        self::DELETE => true,
131
        self::OPTIONS => true,
132
        self::HEAD => true
133
    ];
134
    /**
135
     * GET request
136
     *
137
     * @var string
138
     */
139
    const GET = 'get';
140
    /**
141
     * POST request
142
     *
143
     * @var string
144
     */
145
    const POST = 'post';
146
    /**
147
     * PATCH request
148
     *
149
     * @var string
150
     */
151
    const PATCH = 'patch';
152
    /**
153
     * DELETE request
154
     *
155
     * @var string
156
     */
157
    const DELETE = 'delete';
158
    /**
159
     * OPTIONS request
160
     *
161
     * @var string
162
     */
163
    const OPTIONS = 'options';
164
    /**
165
     * HEAD request
166
     *
167
     * @var string
168
     */
169
    const HEAD = 'head';
170
171
    /**
172
     * Route constructor
173
     *
174
     * @param string|array $verbs Allowed HTTP verbs
175
     * @param string $name Route name
176
     * @param string $path Route path
177
     * @param string $action Route action
178
     */
179
    public function __construct($verbs, $name, $path, $action)
180
    {
181
        // Set and validate the allowed HTTP verbs
182
        $this->setAndValidateVerbs($verbs);
183
184
        // Set and validate the route name
185
        $this->setAndValidateName($name);
186
187
        // Set and validate the route path
188
        $this->setAndValidatePath($path);
189
        
190
        // Set and validate the route action
191
        $this->setAndValidateAction($action);
192
    }
193
194
    /**
195
     * Get the route name
196
     *
197
     * @return string Route name
198
     */
199
    public function getName()
200
    {
201
        return $this->name;
202
    }
203
204
    /**
205
     * Get the route path
206
     *
207
     * @return string
208
     */
209
    public function getPath()
210
    {
211
        return $this->path;
212
    }
213
214
    public function getAction()
215
    {
216
        return $this->action;
217
    }
218
219
    /**
220
     * Get the route tokens
221
     *
222
     * @return array Route tokens
223
     */
224
    public function getTokens()
225
    {
226
        return $this->tokens;
227
    }
228
229
    /**
230
     * Set the route tokens
231
     *
232
     * @param array $tokens Route tokens
233
     * @return Route Self reference
234
     */
235
    public function setTokens(array $tokens)
236
    {
237
        $this->tokens = $tokens;
238
        return $this;
239
    }
240
241
    /**
242
     * Get the route defaults
243
     *
244
     * @return array Route defaults
245
     */
246
    public function getDefaults()
247
    {
248
        return $this->defaults;
249
    }
250
251
    /**
252
     * Set the route defaults
253
     *
254
     * @param array $defaults Route defaults
255
     * @return Route Self reference
256
     */
257
    public function setDefaults(array $defaults)
258
    {
259
        $this->defaults = $defaults;
260
        return $this;
261
    }
262
263
    /**
264
     * Set the route wildcard name
265
     *
266
     * @return null|string
267
     */
268
    public function getWildcard()
269
    {
270
        return $this->wildcard;
271
    }
272
273
    /**
274
     * Get the route wildcard name
275
     *
276
     * @param null|string $wildcard Wildcard name
277
     * @return Route Self reference
278
     */
279
    public function setWildcard($wildcard)
280
    {
281
        $this->wildcard = $wildcard;
282
        return $this;
283
    }
284
285
    /**
286
     * Get the route host
287
     *
288
     * @return null|string Route host
289
     */
290
    public function getHost()
291
    {
292
        return $this->host;
293
    }
294
295
    /**
296
     * Set the route host
297
     *
298
     * @param null|string $host Route host
299
     * @return Route Self reference
300
     */
301
    public function setHost($host)
302
    {
303
        $this->host = $host;
304
        return $this;
305
    }
306
307
    /**
308
     * Get the allowed Accept headers
309
     *
310
     * @return array Allowed Accept headers
311
     */
312
    public function getAccepts()
313
    {
314
        return $this->accepts;
315
    }
316
317
    /**
318
     * Set the allowed Accept headers
319
     *
320
     * @param array $accepts Allowed Accept headers
321
     * @return Route Self reference
322
     */
323
    public function setAccepts(array $accepts)
324
    {
325
        $this->accepts = $accepts;
326
        return $this;
327
    }
328
329
    /**
330
     * Get the allowed HTTP verbs
331
     *
332
     * @return array Allowed HTTP verbs
333
     */
334
    public function getVerbs()
335
    {
336
        return $this->verbs;
337
    }
338
339
    /**
340
     * Set the allowed HTTP verbs
341
     *
342
     * @param array $verbs Allowed HTTP verbs
343
     * @return Route Self reference
344
     */
345
    public function setVerbs(array $verbs)
346
    {
347
        $this->verbs = $verbs;
348
        return $this;
349
    }
350
351
    /**
352
     * Get the secure protocol mode
353
     *
354
     * @return boolean|null Secure protocol mode
355
     */
356
    public function getSecure()
357
    {
358
        return $this->secure;
359
    }
360
361
    /**
362
     * Set the secure protocol mode
363
     *
364
     * @param boolean|null $secure Secure protocol mode
365
     * @return Route Self reference
366
     */
367
    public function setSecure($secure)
368
    {
369
        $this->secure = $secure;
370
        return $this;
371
    }
372
373
    /**
374
     * Get the authentication information
375
     *
376
     * @return mixed Authentication information
377
     */
378
    public function getAuth()
379
    {
380
        return $this->auth;
381
    }
382
383
    /**
384
     * Set the authentication information
385
     *
386
     * @param mixed $auth Authentication information
387
     * @return Route Self reference
388
     */
389
    public function setAuth($auth)
390
    {
391
        $this->auth = $auth;
392
        return $this;
393
    }
394
395
    /**
396
     * Get the custom extra information
397
     *
398
     * @return mixed Custom extra information
399
     */
400
    public function getExtras()
401
    {
402
        return $this->extras;
403
    }
404
405
    /**
406
     * Set the custom extra information
407
     *
408
     * @param mixed $extras Custom extra information
409
     * @return Route Self reference
410
     */
411
    public function setExtras($extras)
412
    {
413
        $this->extras = $extras;
414
        return $this;
415
    }
416
417
    /**
418
     * Validate the allowed HTTP verbs
419
     *
420
     * @param string|array $verbs Allowed HTTP verbs
421
     * @throws InvalidArgumentException If the HTTP verb list is empty
422
     * @throws InvalidArgumentException If the HTTP verb is invalid
423
     */
424
    protected function setAndValidateVerbs($verbs) {
425
        $this->verbs = array_map('strtolower', array_filter((array)$verbs));
426
427
        // If the HTTP verb list is empty
428
        if (!count($this->verbs)) {
429
            throw new InvalidArgumentException(
430
                'Empty route HTTP verbs',
431
                InvalidArgumentException::EMPTY_ROUTE_HTTP_VERBS
432
            );
433
        }
434
435
        // Run through all registered HTTP verbs
436
        foreach ($this->verbs as $verb) {
437
            // If the HTTP verb is invalid
438
            if (!array_key_exists($verb, self::$validVerbs)) {
439
                throw new InvalidArgumentException(
440
                    sprintf('Invalid route HTTP verb "%s"', $verb),
441
                    InvalidArgumentException::INVALID_ROUTE_HTTP_VERB
442
                );
443
            }
444
        }
445
    }
446
447
    /**
448
     * Set and validate the route name
449
     *
450
     * @param string $name Route name
451
     * @throws InvalidArgumentException If the route name is empty
452
     */
453
    protected function setAndValidateName($name) {
454
        $this->name = trim($name);
455
        // If the route name is empty
456
        if (!strlen($this->name)) {
457
            throw new InvalidArgumentException(
458
                'Route name must not be empty',
459
                InvalidArgumentException::EMPTY_ROUTE_NAME
460
            );
461
        }
462
    }
463
464
    /**
465
     * Set and validate the route path
466
     *
467
     * @param string $path Route path
468
     * @throws InvalidArgumentException If the route path is empty
469
     */
470
    protected function setAndValidatePath($path) {
471
        $this->path = trim($path);
472
        // If the route path is empty
473
        if (!strlen($this->path)) {
474
            throw new InvalidArgumentException(
475
                'Route path must not be empty',
476
                InvalidArgumentException::EMPTY_ROUTE_NAME
477
            );
478
        }
479
    }
480
481
    /**
482
     * Set and validate the route action
483
     * 
484
     * @param string $action Route action
485
     * @throws InvalidArgumentException If the route action is empty
486
     * @throws InvalidArgumentException If the route action is not a class name
487
     * @throws InvalidArgumentException If the route action is neither a callable nor an ActionInterface
488
     */
489
    protected function setAndValidateAction($action) {
490
        // If the action is given as string
491
        if (is_string($action)) {
492
            $this->action = trim($action);
493
494
            // If the route action is empty
495
            if (!strlen($this->action)) {
496
                throw new InvalidArgumentException(
497
                    'Route action must not be empty',
498
                    InvalidArgumentException::EMPTY_ROUTE_ACTION
499
                );
500
            }
501
502
            // If the route action is not a class name
503
            if (!class_exists($this->action)) {
504
                throw new InvalidArgumentException(
505
                    'Route action must be an existing class name',
506
                    InvalidArgumentException::ROUTE_ACTION_MUST_BE_CLASSNAME
507
                );
508
            }
509
510
            // If the route action doesn't implement the ActionInterface
511
            $actionReflection = new \ReflectionClass($this->action);
512
            if (!$actionReflection->implementsInterface(ActionInterface::class)) {
513
                throw new InvalidArgumentException(
514
                    'Route action must implement '.ActionInterface::class,
515
                    InvalidArgumentException::ROUTE_ACTION_MUST_IMPLEMENT_ACTION_INTERFACE
516
                );
517
            }
518
519
            return;
520
        }
521
522
        // If the action is given as callable
523
        if (is_callable($action)) {
524
            $this->action = $action;
525
            return;
526
        }
527
528
        // If the route action is neither a callable nor an ActionInterface
529
        throw new InvalidArgumentException(
530
            'Route action must be a callable or '.ActionInterface::class,
531
            InvalidArgumentException::ROUTE_ACTION_NOT_CALLABLE_OR_ACTION_INTERFACE
532
        );
533
    }
534
}
535