Passed
Push — master ( 65b336...1323cd )
by Бабичев
44s
created

Path   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 182
Duplicated Lines 0 %

Test Coverage

Coverage 66.67%

Importance

Changes 0
Metric Value
wmc 16
dl 0
loc 182
ccs 42
cts 63
cp 0.6667
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A serialize() 0 3 1
A getPattern() 0 14 2
A hinge() 0 7 1
A unserialize() 0 4 2
A getRegex() 0 3 1
A getValue() 0 3 1
A regexAttribute() 0 3 1
A __sleep() 0 3 1
A quote() 0 11 1
A processing() 0 22 3
A jsonSerialize() 0 7 1
1
<?php
2
3
namespace Bavix\Router;
4
5
use Bavix\Exceptions\Runtime;
6
7
class Path implements \Serializable, \JsonSerializable
8
{
9
10
    /**
11
     * @var string
12
     */
13
    protected $defaultRegex;
14
15
    /**
16
     * @var string
17
     */
18
    protected $pattern;
19
20
    /**
21
     * @var string
22
     */
23
    protected $value;
24
25
    /**
26
     * @var array
27
     */
28
    protected $regex;
29
30
    /**
31
     * Path constructor.
32
     *
33
     * @param string $defaultRegex
34
     * @param string $value
35
     * @param array  $regex
36
     */
37 5
    public function __construct(string $defaultRegex, string $value, array $regex = [])
38
    {
39 5
        $this->defaultRegex = $defaultRegex;
40 5
        $this->value = $value;
41 5
        $this->regex = $regex;
42 5
        $this->processing();
43 5
    }
44
45
    /**
46
     * @param string $value
47
     *
48
     * @return string
49
     */
50 4
    protected function quote(string $value): string
51
    {
52 4
        $path = \preg_quote($value, '()');
53 4
        $path = \strtr($path, [
54 4
            '\\(' => '(',
55
            '\\)' => ')',
56
            '\\<' => '<',
57
            '\\>' => '>',
58
        ]);
59
60 4
        return \str_replace(')', ')?', $path);
61
    }
62
63
    /**
64
     * @param string $name
65
     *
66
     * @return string
67
     */
68 4
    protected function regexAttribute(string $name): string
69
    {
70 4
        return $this->regex[$name] ?? $this->defaultRegex;
71
    }
72
73
    /**
74
     * @return string
75
     */
76 4
    public function getPattern(): string
77
    {
78 4
        if (!$this->pattern) {
79 4
            $this->pattern = \preg_replace_callback(
80 4
                '~\<(?<key>' . $this->defaultRegex . '+)\>~',
81 4
                function ($matches) {
82 4
                    return '(?<' . $matches['key'] . '>' .
83 4
                        $this->regexAttribute($matches['key']) .
84 4
                        ')';
85 4
                },
86 4
                $this->quote($this->value)
87
            );
88
        }
89 4
        return $this->pattern;
90
    }
91
92
    /**
93
     * @return string
94
     */
95
    public function getValue(): string
96
    {
97
        return $this->value;
98
    }
99
100
    /**
101
     * @return array
102
     */
103
    public function getRegex(): array
104
    {
105
        return $this->regex;
106
    }
107
108
    /**
109
     * @param self $parent
110
     */
111 2
    public function hinge(self $parent): void
112
    {
113 2
        $this->pattern = null;
114 2
        $this->value   = $parent->value . $this->value;
115 2
        $this->regex   = \array_merge(
116 2
            $parent->regex,
117 2
            $this->regex
118
        );
119 2
    }
120
121
    /**
122
     * processing:
123
     *  path: '/(<lang:\w+>)' -> '/(<lang>)'
124
     *  re: [] -> ['lang' => '\w+']
125
     *
126
     *  if attr exists -> throws
127
     */
128 5
    protected function processing(): void
129
    {
130 5
        $this->value = \preg_replace_callback(
131 5
            '~\<(?<key>' . $this->defaultRegex . '+):(?<value>.+?)>~',
132 5
            function (array $matches) {
133
134 3
                if (!empty($this->regex[$matches['key']])) {
135
                    throw new Runtime(\sprintf(
136
                        'duplicate in registry key `%s` for path `%s`',
137
                        $matches['key'],
138
                        $this->value
139
                    ));
140
                }
141
142 3
                if (!empty($matches['value']))
143
                {
144 3
                    $this->regex[$matches['key']] = $matches['value'];
145
                }
146
147 3
                return '<' . $matches['key'] . '>';
148 5
            },
149 5
            $this->value
150
        );
151 5
    }
152
153
    /**
154
     * @return array
155
     */
156
    public function __sleep(): array
157
    {
158
        return \array_keys($this->jsonSerialize());
159
    }
160
161
    /**
162
     * @inheritdoc
163
     */
164
    public function serialize(): string
165
    {
166
        return \serialize($this->jsonSerialize());
167
    }
168
169
    /**
170
     * @inheritdoc
171
     */
172
    public function unserialize($serialized): void
173
    {
174
        foreach (\unserialize($serialized, (array)null) as $key => $value) {
175
            $this->$key = $value;
176
        }
177
    }
178
179
    /**
180
     * @inheritdoc
181
     */
182
    public function jsonSerialize(): array
183
    {
184
        return [
185
            'defaultRegex' => $this->defaultRegex,
186
            'pattern' => $this->pattern,
187
            'regex' => $this->regex,
188
            'value' => $this->value,
189
        ];
190
    }
191
192
}
193