Route   B
last analyzed

Complexity

Total Complexity 50

Size/Duplication

Total Lines 588
Duplicated Lines 0 %

Coupling/Cohesion

Components 4
Dependencies 0

Importance

Changes 0
Metric Value
wmc 50
lcom 4
cbo 0
dl 0
loc 588
rs 8.6206
c 0
b 0
f 0

41 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A setName() 0 5 1
A getName() 0 4 1
A setPath() 0 5 1
A getPath() 0 4 1
A getPathRegex() 0 4 1
A setAction() 0 5 1
A getAction() 0 4 1
A setSchemes() 0 5 1
A hasScheme() 0 4 1
A getSchemes() 0 4 1
A setMethods() 0 5 1
A hasMethod() 0 4 1
A getMethods() 0 4 1
A setHost() 0 5 1
A getHost() 0 4 1
A getHostRegex() 0 4 1
A setRequirements() 0 5 1
A setRequirement() 0 5 1
A addRequirements() 0 5 1
A getRequirements() 0 4 1
A hasRequirement() 0 4 1
A getRequirement() 0 4 2
A getDefaults() 0 4 1
A setDefault() 0 5 1
A setDefaults() 0 5 1
A addDefaults() 0 5 1
A getDefault() 0 4 2
A hasDefault() 0 4 1
A setParameter() 0 5 1
A getParameter() 0 4 2
A hasParameter() 0 4 1
A setParameters() 0 5 1
A addParameters() 0 5 1
A getParameters() 0 4 1
A setComputedParameters() 0 4 1
A getComputedParameters() 0 4 1
A isCompiled() 0 4 1
A compile() 0 12 4
A getVariables() 0 4 1
A parsePattern() 0 21 4

How to fix   Complexity   

Complex Class

Complex classes like Route often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Route, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * slince routing library
4
 * @author Tao <[email protected]>
5
 */
6
namespace Slince\Routing;
7
8
class Route
9
{
10
    /**
11
     * head
12
     * @var string
13
     */
14
    const HEAD = 'HEAD';
15
16
    /**
17
     * get
18
     * @var string
19
     */
20
    const GET = 'GET';
21
22
    /**
23
     * post
24
     * @var string
25
     */
26
    const POST = 'POST';
27
28
    /**
29
     * put
30
     * @var string
31
     */
32
    const PUT = 'PUT';
33
34
    /**
35
     * patch
36
     * @var string
37
     */
38
    const PATCH = 'PATCH';
39
40
    /**
41
     * delete
42
     * @var string
43
     */
44
    const DELETE = 'DELETE';
45
46
    /**
47
     * purge
48
     * @var string
49
     */
50
    const PURGE = 'PURGE';
51
52
    /**
53
     * options
54
     * @var string
55
     */
56
    const OPTIONS = 'OPTIONS';
57
58
    /**
59
     * trace
60
     * @var string
61
     */
62
    const TRACE = 'TRACE';
63
64
    /**
65
     * connect
66
     * @var string
67
     */
68
    const CONNECT = 'CONNECT';
69
70
    /**
71
     * The route name
72
     * @var string
73
     */
74
    protected $name;
75
76
    /**
77
     * Path
78
     * @var string
79
     */
80
    protected $path;
81
82
    /**
83
     * Action
84
     * @var mixed
85
     */
86
    protected $action;
87
88
    /**
89
     * Schemes
90
     * @var array
91
     */
92
    protected $schemes = [];
93
94
    /**
95
     * Host
96
     * @var string
97
     */
98
    protected $host;
99
100
    /**
101
     * Methods
102
     * @var array
103
     */
104
    protected $methods = [];
105
106
    /**
107
     * Requirements
108
     * @var array
109
     */
110
    protected $requirements = [];
111
112
    /**
113
     * Defaults
114
     * @var array
115
     */
116
    protected $defaults= [];
117
118
    /**
119
     * Parameters
120
     * @var array
121
     */
122
    protected $parameters = [];
123
124
    /**
125
     * The computed parameters
126
     * @var array
127
     */
128
    protected $computedParameters = [];
129
130
    /**
131
     * whether the route has been compiled
132
     * @var bool
133
     */
134
    protected $isCompiled = false;
135
136
    /**
137
     * the host regex
138
     * @var string
139
     */
140
    protected $hostRegex;
141
142
    /**
143
     * the path regex
144
     * @var string
145
     */
146
    protected $pathRegex;
147
148
    /**
149
     * Array of host variables
150
     * @var array
151
     */
152
    protected $hostVariables = [];
153
154
    /**
155
     * Array of path variables
156
     * @var array
157
     */
158
    protected $pathVariables = [];
159
160
    /**
161
     * Array of variables
162
     * @var array
163
     */
164
    protected $variables = [];
165
166
    public function __construct($path, $action) {
167
        $this->setPath($path);
168
        $this->setAction($action);
169
    }
170
171
    /**
172
     * Sets route name
173
     * @param string $name
174
     * @return Route
175
     */
176
    public function setName($name)
177
    {
178
        $this->name = $name;
179
        return $this;
180
    }
181
182
    /**
183
     * @return string
184
     */
185
    public function getName()
186
    {
187
        return $this->name;
188
    }
189
190
    /**
191
     * Sets the route path
192
     * @param string $path
193
     * @return Route
194
     */
195
    public function setPath($path)
196
    {
197
        $this->path = '/' . trim($path, '/');
198
        return $this;
199
    }
200
201
    /**
202
     * Gets the route path
203
     * @return string path
204
     */
205
    public function getPath()
206
    {
207
        return $this->path;
208
    }
209
210
    /**
211
     * Gets the path regex
212
     * @return string
213
     */
214
    public function getPathRegex()
215
    {
216
        return $this->pathRegex;
217
    }
218
219
    /**
220
     * Sets the action for the route
221
     * @param mixed $action
222
     * @return Route
223
     */
224
    public function setAction($action)
225
    {
226
        $this->action = $action;
227
        return $this;
228
    }
229
230
    /**
231
     * Gets the action
232
     * @return mixed
233
     */
234
    public function getAction()
235
    {
236
        return $this->action;
237
    }
238
239
    /**
240
     * Sets the route schemes
241
     * @param string|array $schemes
242
     * @return Route
243
     */
244
    public function setSchemes($schemes)
245
    {
246
        $this->schemes = array_map('strtolower', (array)$schemes);
247
        return $this;
248
    }
249
250
    /**
251
     * Checks whether the route has the scheme
252
     * @param string $scheme
253
     * @return bool
254
     */
255
    public function hasScheme($scheme)
256
    {
257
        return in_array(strtolower($scheme), $this->schemes);
258
    }
259
260
    /**
261
     * Gets all schemes
262
     * @return array
263
     */
264
    public function getSchemes()
265
    {
266
        return $this->schemes;
267
    }
268
269
    /**
270
     * Sets the route request methods
271
     * @param string|array $methods
272
     * @return Route
273
     */
274
    public function setMethods($methods)
275
    {
276
        $this->methods = array_map('strtoupper', (array)$methods);
277
        return $this;
278
    }
279
280
    /**
281
     * Checks whether the route has the request method
282
     * @param string $method
283
     * @return bool
284
     */
285
    public function hasMethod($method)
286
    {
287
        return in_array(strtoupper($method), $this->methods);
288
    }
289
290
    /**
291
     * Gets all request methods that the route supports
292
     * @return array
293
     */
294
    public function getMethods()
295
    {
296
        return $this->methods;
297
    }
298
299
    /**
300
     * Set the route host
301
     * @param string $host
302
     * @return Route
303
     */
304
    public function setHost($host)
305
    {
306
        $this->host = $host;
307
        return $this;
308
    }
309
310
    /**
311
     * Gets the host
312
     * @return string
313
     */
314
    public function getHost()
315
    {
316
        return $this->host;
317
    }
318
319
    /**
320
     * Gets the route host regex
321
     * @return string
322
     */
323
    public function getHostRegex()
324
    {
325
        return $this->hostRegex;
326
    }
327
328
    /**
329
     * Sets the requirements of the route
330
     * @param array $requirements
331
     * @return Route
332
     */
333
    public function setRequirements(array $requirements)
334
    {
335
        $this->requirements = $requirements;
336
        return $this;
337
    }
338
339
    /**
340
     * Sets a requirement by specified name and value
341
     * @param string $name
342
     * @param string $requirement
343
     * @return Route
344
     */
345
    public function setRequirement($name, $requirement)
346
    {
347
        $this->requirements[$name] = $requirement;
348
        return $this;
349
    }
350
351
    /**
352
     * Add the requirements of the route (not replace)
353
     * @param array $requirements
354
     * @return Route
355
     */
356
    public function addRequirements(array $requirements)
357
    {
358
        $this->requirements += $requirements;
359
        return $this;
360
    }
361
362
    /**
363
     * Gets all requirements
364
     * @return array
365
     */
366
    public function getRequirements()
367
    {
368
        return $this->requirements;
369
    }
370
371
    /**
372
     * Checks whether the route has the requirement
373
     * @param string $name
374
     * @return bool
375
     */
376
    public function hasRequirement($name)
377
    {
378
        return isset($this->requirements[$name]);
379
    }
380
381
    /**
382
     * Gets a requirement by its name
383
     * @param string $name
384
     * @param string $default
385
     * @return string|null
386
     */
387
    public function getRequirement($name, $default = null)
388
    {
389
        return isset($this->requirements[$name]) ? $this->requirements[$name] : $default;
390
    }
391
392
    /**
393
     *  Gets the defaults
394
     */
395
    public function getDefaults()
396
    {
397
        return $this->defaults;
398
    }
399
400
    /**
401
     * Sets a default item
402
     * @param string $name
403
     * @param string $value
404
     * @return Route
405
     */
406
    public function setDefault($name, $value)
407
    {
408
        $this->defaults[$name] = $value;
409
        return $this;
410
    }
411
412
    /**
413
     * Sets the defaults
414
     * @param array $defaults
415
     * @return Route
416
     */
417
    public function setDefaults(array $defaults)
418
    {
419
        $this->defaults = $defaults;
420
        return $this;
421
    }
422
423
    /**
424
     * Add the defaults of the route (not replace)
425
     * @param array $defaults
426
     * @return Route
427
     */
428
    public function addDefaults(array $defaults)
429
    {
430
        $this->defaults += $defaults;
431
        return $this;
432
    }
433
434
    /**
435
     * Gets the default option value by its name
436
     * @param string $name
437
     * @return mixed|null
438
     */
439
    public function getDefault($name)
440
    {
441
        return isset($this->defaults[$name]) ? $this->defaults[$name] : null;
442
    }
443
444
    /**
445
     * Checks whether the route has the default option
446
     * @param string $name
447
     * @return bool
448
     */
449
    public function hasDefault($name)
450
    {
451
        return array_key_exists($name, $this->defaults);
452
    }
453
454
    /**
455
     * Sets the route parameters
456
     * @param string $name
457
     * @param mixed $parameter
458
     * @return Route
459
     */
460
    public function setParameter($name, $parameter)
461
    {
462
        $this->parameters[$name] = $parameter;
463
        return $this;
464
    }
465
466
    /**
467
     * Gets the route parameters
468
     * @param string $name
469
     * @return mixed
470
     */
471
    public function getParameter($name)
472
    {
473
        return isset($this->parameters[$name]) ? $this->parameters[$name] : null;
474
    }
475
476
    /**
477
     * Checks whether the parameter exists
478
     * @param string $name
479
     * @return mixed
480
     */
481
    public function hasParameter($name)
482
    {
483
        return array_key_exists($name, $this->parameters);
484
    }
485
486
    /**
487
     * Sets all parameters
488
     * @param array $parameters
489
     * @return Route
490
     */
491
    public function setParameters(array $parameters)
492
    {
493
        $this->parameters = $parameters;
494
        return $this;
495
    }
496
497
    /**
498
     * Add the parameters of the route (not replace)
499
     * @param array $parameters
500
     * @return Route
501
     */
502
    public function addParameters(array $parameters)
503
    {
504
        $this->parameters += $parameters;
505
        return $this;
506
    }
507
508
    /**
509
     * Gets all parameters
510
     * @return array
511
     */
512
    public function getParameters()
513
    {
514
        return $this->parameters;
515
    }
516
517
    /**
518
     * @param array $computedParameters
519
     */
520
    public function setComputedParameters($computedParameters)
521
    {
522
        $this->computedParameters = $computedParameters;
523
    }
524
525
    /**
526
     * @return array
527
     */
528
    public function getComputedParameters()
529
    {
530
        return $this->computedParameters;
531
    }
532
533
    /**
534
     * {@inheritdoc}
535
     */
536
    public function isCompiled()
537
    {
538
        return $this->isCompiled;
539
    }
540
541
    /**
542
     * Complies the route
543
     * @param boolean $reCompile
544
     * @return Route
545
     */
546
    public function compile($reCompile = false)
547
    {
548
        if (!$this->isCompiled || $reCompile) {
549
            if ($this->getHost()) {
550
                $this->hostRegex = $this->parsePattern($this->getHost(), true);
551
            }
552
            $this->pathRegex = $this->parsePattern($this->getPath(), false);
553
            $this->variables = array_merge($this->hostVariables, $this->pathVariables);
554
            $this->isCompiled = true;
555
        }
556
        return $this;
557
    }
558
559
    /**
560
     * Gets all variables that been compiled
561
     * @return array
562
     */
563
    public function getVariables()
564
    {
565
        return $this->variables;
566
    }
567
568
    /**
569
     * Parses the path to regex
570
     * @param string $path
571
     * @param boolean $isHost
572
     * @return string
573
     */
574
    protected function parsePattern($path, $isHost)
575
    {
576
        $variables = [];
577
        $regex = preg_replace_callback('#[/\.]?\{([a-zA-Z0-9_,]*)\}#i', function ($match) use(&$variables){
578
            $variables[] = $match[1];
579
            $subRegex = "(?P<{$match[1]}>" . (isset($this->requirements[$match[1]]) ? $this->requirements[$match[1]] : '[^/\.]+') . ')';
580
            $regex = str_replace('\{' . $match[1] . '\}', $subRegex, preg_quote($match[0], '#'));
581
            if ($this->hasDefault($match[1])) {
582
                $regex = "(?:{$regex})?";
583
            }
584
            return $regex;
585
        }, $path);
586
        $regex = "#^{$regex}$#";
587
        if ($isHost) {
588
            $regex .= 'i';
589
            $this->hostVariables = $variables;
590
        } else {
591
            $this->pathVariables = $variables;
592
        }
593
        return $regex;
594
    }
595
}