Route   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 135
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 37
c 2
b 0
f 0
dl 0
loc 135
rs 10
wmc 16

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
A getPattern() 0 3 1
A setPattern() 0 10 3
A getMethods() 0 3 1
A addMethods() 0 4 1
A extractDefaults() 0 14 3
A setMethods() 0 9 3
A validatePattern() 0 9 3
1
<?php
2
3
/**
4
 * Phoole (PHP7.2+)
5
 *
6
 * @category  Library
7
 * @package   Phoole\Route
8
 * @copyright Copyright (c) 2019 Hong Zhang
9
 */
10
declare(strict_types=1);
11
12
namespace Phoole\Route\Util;
13
14
/**
15
 * Route
16
 *
17
 * @package Phoole\Route
18
 */
19
class Route
20
{
21
    /**
22
     * @var string[]
23
     */
24
    protected $methods;
25
26
    /**
27
     * @var string
28
     */
29
    protected $pattern;
30
31
    /**
32
     * @param  string|string[] $method    HTTP method[s]
33
     * @param  string          $pattern   URI pattern to match
34
     * @param  mixed           $handler   request handler
35
     * @param  array           $defaults  default parameters
36
     * @throws \LogicException            if pattern not right
37
     */
38
    public function __construct(
39
        $method,
40
        string $pattern,
41
        $handler,
42
        array $defaults = []
43
    ) {
44
        $this
45
            ->setPattern($pattern, $defaults)
46
            ->setMethods($method, $handler, $defaults);
47
    }
48
49
    /**
50
     * @return string
51
     */
52
    public function getPattern(): string
53
    {
54
        return $this->pattern;
55
    }
56
57
    /**
58
     * Set route pattern
59
     *
60
     * @param  string  $pattern
61
     * @param  array  &$defaults
62
     * @return $this
63
     * @throws \LogicException  if pattern not right
64
     */
65
    public function setPattern(string $pattern, &$defaults)
66
    {
67
        if ($this->validatePattern($pattern)) {
68
            list($pattern, $params) = $this->extractDefaults($pattern);
69
            $this->pattern = $pattern;
70
            if (!empty($params)) {
71
                $defaults = array_merge($params, $defaults);
72
            }
73
        }
74
        return $this;
75
    }
76
77
    /**
78
     * Add new methods from another route
79
     *
80
     * @param  Route $route  another route
81
     * @return $this
82
     */
83
    public function addMethods(Route $route)
84
    {
85
        $this->methods = array_merge($this->methods, $route->getMethods());
86
        return $this;
87
    }
88
89
    /**
90
     * @return  array
91
     */
92
    public function getMethods(): array
93
    {
94
        return $this->methods;
95
    }
96
97
    /**
98
     * Set methods(with related handler/defaults)
99
     *
100
     * @param  string|string[] $method
101
     * @param  mixed           $handler
102
     * @param  array           $defaults
103
     * @return $this
104
     */
105
    public function setMethods($method, $handler, array $defaults)
106
    {
107
        $methods = is_string($method) ?
108
            preg_split('~[^A-Z]+~', strtoupper($method), -1, PREG_SPLIT_NO_EMPTY) :
109
            array_map('strtoupper', $method);
110
        foreach ($methods as $mth) {
111
            $this->methods[$mth] = [$handler, $defaults];
112
        }
113
        return $this;
114
    }
115
116
    /**
117
     * Validate the pattern
118
     *
119
     * @param  string $pattern
120
     * @return bool
121
     * @throws \LogicException  if not valid pattern
122
     */
123
    protected function validatePattern(string $pattern): bool
124
    {
125
        if (
126
            substr_count($pattern, '[') !== substr_count($pattern, ']') ||
127
            substr_count($pattern, '{') !== substr_count($pattern, '}')
128
        ) {
129
            throw new \LogicException("Invalid route pattern '$pattern'");
130
        }
131
        return TRUE;
132
    }
133
134
    /**
135
     * Extract default values from the pattern
136
     *
137
     * @param  string $pattern
138
     * @return array
139
     */
140
    protected function extractDefaults(string $pattern): array
141
    {
142
        $vals = [];
143
        $regex = '~\{([a-zA-Z][a-zA-Z0-9_]*+)[^\}]*(=[a-zA-Z0-9._]++)\}~';
144
        if (preg_match_all($regex, $pattern, $matches, \PREG_SET_ORDER)) {
145
            $srch = $repl = [];
146
            foreach ($matches as $m) {
147
                $srch[] = $m[0];
148
                $repl[] = str_replace($m[2], '', $m[0]);
149
                $vals[$m[1]] = substr($m[2], 1);
150
            }
151
            $pattern = str_replace($srch, $repl, $pattern);
152
        }
153
        return [$pattern, $vals];
154
    }
155
}