Completed
Push — master ( 3bd5ae...8ad167 )
by Бабичев
02:10
created

Rule   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 288
Duplicated Lines 0 %

Test Coverage

Coverage 65.56%

Importance

Changes 0
Metric Value
wmc 33
eloc 72
dl 0
loc 288
ccs 59
cts 90
cp 0.6556
rs 9.76
c 0
b 0
f 0

21 Methods

Rating   Name   Duplication   Size   Complexity  
A beforePrepare() 0 3 2
A getProtocol() 0 3 1
A hinge() 0 8 3
A getDefaultRegex() 0 3 2
A pathInit() 0 7 2
A getHost() 0 3 1
A jsonSerialize() 0 8 2
A arrayMerge() 0 5 1
A __construct() 0 10 3
A getName() 0 3 1
A afterPrepare() 0 9 1
A serialize() 0 7 2
A getDefaults() 0 3 1
A __sleep() 0 3 1
A pathExtract() 0 11 2
A serializeArray() 0 9 2
A getMethods() 0 3 1
A unserialize() 0 9 2
A getPath() 0 3 1
A prepare() 0 4 1
A getExtends() 0 3 1
1
<?php
2
3
namespace Bavix\Router;
4
5
abstract class Rule implements \Serializable, \JsonSerializable
6
{
7
8
    use Attachable;
9
10
    public const DEFAULT_REGEX = '[\w-]+';
11
12
    /**
13
     * @var string
14
     */
15
    protected $_protocol;
16
17
    /**
18
     * @var string
19
     */
20
    protected $_host;
21
22
    /**
23
     * @var null|string
24
     */
25
    protected $type;
26
27
    /**
28
     * @var null|Path
29
     */
30
    protected $path;
31
32
    /**
33
     * @var null|array
34
     */
35
    protected $methods;
36
37
    /**
38
     * @var array
39
     */
40
    protected $defaults;
41
42
    /**
43
     * @var array
44
     */
45
    protected $extends;
46
47
    /**
48
     * @var string
49
     */
50
    protected $defaultRegex;
51
52
    /**
53
     * Rule constructor.
54
     *
55
     * @param string $key
56
     * @param iterable $storage
57
     * @param null|self $parent
58
     */
59 7
    public function __construct(string $key, $storage, ?self $parent = null)
60
    {
61 7
        $this->prepare();
62 7
        $this->initializer($key, $storage);
0 ignored issues
show
Bug introduced by
$storage of type iterable is incompatible with the type array expected by parameter $storage of Bavix\Router\Rule::initializer(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

62
        $this->initializer($key, /** @scrutinizer ignore-type */ $storage);
Loading history...
63 7
        if ($parent) {
64 3
            $this->beforePrepare($parent);
65
        }
66 7
        $this->pathInit();
67 7
        if ($parent) {
68 3
            $this->afterPrepare($parent);
69
        }
70 7
    }
71
72
    /**
73
     * @return string
74
     */
75 1
    public function getName(): string
76
    {
77 1
        return $this->_name;
78
    }
79
80
    /**
81
     * @return string
82
     */
83 5
    public function getProtocol(): string
84
    {
85 5
        return $this->_protocol;
86
    }
87
88
    /**
89
     * @return string
90
     */
91 5
    public function getHost(): string
92
    {
93 5
        return $this->_host;
94
    }
95
96
    /**
97
     * @return Path
98
     */
99 5
    public function getPath(): Path
100
    {
101 5
        return $this->path;
102
    }
103
104
    /**
105
     * @return null|array
106
     */
107 6
    public function getMethods(): ?array
108
    {
109 6
        return $this->methods;
110
    }
111
112
    /**
113
     * @return array
114
     */
115
    public function getExtends(): array
116
    {
117
        return (array)$this->extends;
118
    }
119
120
    /**
121
     * @return array
122
     */
123 6
    public function getDefaults(): array
124
    {
125 6
        return (array)$this->defaults;
126
    }
127
128
    /**
129
     * @return string
130
     */
131 6
    public function getDefaultRegex(): string
132
    {
133 6
        return $this->defaultRegex ?: self::DEFAULT_REGEX;
134
    }
135
136
    /**
137
     * @param Path|null $path
138
     */
139 3
    protected function hinge(?Path $path): void
140
    {
141 3
        if ($this->path && $path) {
142 3
            $this->path->hinge($path);
143 3
            return;
144
        }
145
146
        $this->path = $path ?? $this->path;
147
    }
148
149
    /**
150
     * @param string $name
151
     * @param self   $parent
152
     */
153 3
    protected function arrayMerge(string $name, self $parent): void
154
    {
155 3
        $this->$name = \array_merge(
156 3
            (array)$parent->$name,
157 3
            (array)$this->$name
158
        );
159 3
    }
160
161
    /**
162
     * @param self $parent
163
     * @return void
164
     */
165 3
    protected function beforePrepare(self $parent): void
166
    {
167 3
        $this->defaultRegex = $this->defaultRegex ?: $parent->defaultRegex;
168 3
    }
169
170
    /**
171
     * @param self $parent
172
     * @return void
173
     */
174 3
    protected function afterPrepare(self $parent): void
175
    {
176 3
        $this->hinge($parent->path);
177 3
        $this->_protocol = $parent->protocol ?? $parent->_protocol ?? $this->_protocol;
178 3
        $this->_host = $parent->host ?? $parent->_host ?? $this->_host;
179 3
        $this->_name = $parent->_name . '.' . $this->_name;
180 3
        $this->methods = $this->methods ?? $parent->methods;
181 3
        $this->arrayMerge('defaults', $parent);
182 3
        $this->arrayMerge('extends', $parent);
183 3
    }
184
185
    /**
186
     * Returns an array of two elements.
187
     *
188
     * The first parameter is path,
189
     *  the second is an array of regular expressions.
190
     *
191
     * @return array
192
     */
193 7
    protected function pathExtract(): array
194
    {
195 7
        $regExp = [];
196 7
        $path = $this->path;
197
198 7
        if (\is_array($this->path)) {
0 ignored issues
show
introduced by
The condition is_array($this->path) is always false.
Loading history...
199
            $regExp = \array_pop($this->path);
200
            $path = \array_pop($this->path);
201
        }
202
203 7
        return [$path, $regExp];
204
    }
205
206
    /**
207
     * if this.path === string then new Path(string, [])
208
     * else this.path === array then new Path(...this.path)
209
     */
210 7
    protected function pathInit(): void
211
    {
212 7
        [$path, $regExp] = $this->pathExtract();
213 7
        $this->path = null;
214
215 7
        if ($path) {
216 6
            $this->path = new Path($this->getDefaultRegex(), $path, $regExp);
0 ignored issues
show
Bug introduced by
$path of type Bavix\Router\Path is incompatible with the type string expected by parameter $value of Bavix\Router\Path::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

216
            $this->path = new Path($this->getDefaultRegex(), /** @scrutinizer ignore-type */ $path, $regExp);
Loading history...
217
        }
218 7
    }
219
220
    /**
221
     * @return void
222
     */
223 7
    protected function prepare(): void
224
    {
225 7
        $this->_protocol = '\w+';
226 7
        $this->_host = '[^\/]+';
227 7
    }
228
229
    /**
230
     * @return array
231
     * @throws \ReflectionException
232
     */
233
    protected function serializeArray(): array
234
    {
235
        $properties = [];
236
        $reflation = new \ReflectionClass($this);
237
        $protected = $reflation->getProperties(\ReflectionProperty::IS_PROTECTED);
238
        foreach ($protected as $property) {
239
            $properties[] = $property->name;
240
        }
241
        return $properties;
242
    }
243
244
    /**
245
     * @return array
246
     * @throws \ReflectionException
247
     */
248
    public function __sleep(): array
249
    {
250
        return \array_keys($this->serializeArray());
251
    }
252
253
    /**
254
     * @inheritdoc
255
     * @throws \ReflectionException
256
     */
257
    public function serialize(): string
258
    {
259
        $data = [];
260
        foreach ($this->serializeArray() as $key => $value) {
261
            $data[$value] = $this->$value;
262
        }
263
        return \serialize($data);
264
    }
265
266
    /**
267
     * @inheritdoc
268
     */
269
    public function unserialize($serialized): void
270
    {
271
        /**
272
         * @var string $serialized
273
         * @var array $data
274
         */
275
        $data = \unserialize($serialized, (array)null);
276
        foreach ($data as $key => $value) {
277
            $this->{$key} = $value;
278
        }
279
    }
280
281
    /**
282
     * @inheritdoc
283
     * @throws \ReflectionException
284
     */
285
    public function jsonSerialize(): array
286
    {
287
        $data = [];
288
        foreach ($this->serializeArray() as $key => $value) {
289
            $key = \ltrim($value, '_');
290
            $data[$key] = $this->$value;
291
        }
292
        return $data;
293
    }
294
295
}
296