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

src/Router/Rule.php (1 issue)

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 6
    public function __construct(string $key, $storage, ?self $parent = null)
60
    {
61 6
        $this->prepare();
62 6
        $this->initializer($key, $storage);
0 ignored issues
show
$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 6
        $this->pathInit();
64 6
        if ($parent) {
65 2
            $this->afterPrepare($parent);
66
        }
67 6
    }
68
69
    /**
70
     * @return string
71
     */
72 1
    public function getName(): string
73
    {
74 1
        return $this->_name;
75
    }
76
77
    /**
78
     * @return string
79
     */
80 4
    public function getProtocol(): string
81
    {
82 4
        return $this->_protocol;
83
    }
84
85
    /**
86
     * @return string
87
     */
88 4
    public function getHost(): string
89
    {
90 4
        return $this->_host;
91
    }
92
93
    /**
94
     * @return Path
95
     */
96 4
    public function getPath(): Path
97
    {
98 4
        return $this->path;
99
    }
100
101
    /**
102
     * @return null|array
103
     */
104 5
    public function getMethods(): ?array
105
    {
106 5
        return $this->methods;
107
    }
108
109
    /**
110
     * @return array
111
     */
112
    public function getExtends(): array
113
    {
114
        return (array)$this->extends;
115
    }
116
117
    /**
118
     * @return array
119
     */
120 5
    public function getDefaults(): array
121
    {
122 5
        return (array)$this->defaults;
123
    }
124
125
    /**
126
     * @return string
127
     */
128 5
    public function getDefaultRegex(): string
129
    {
130 5
        return $this->defaultRegex ?: self::DEFAULT_REGEX;
131
    }
132
133
    /**
134
     * @param Path|null $path
135
     */
136 2
    protected function hinge(?Path $path): void
137
    {
138 2
        if ($this->path && $path) {
139 2
            $this->path->hinge($path);
140 2
            return;
141
        }
142
143
        $this->path = $path ?? $this->path;
144
    }
145
146
    /**
147
     * @param string $name
148
     * @param self   $parent
149
     */
150 2
    protected function arrayMerge(string $name, self $parent): void
151
    {
152 2
        $this->$name = \array_merge(
153 2
            (array)$parent->$name,
154 2
            (array)$this->$name
155
        );
156 2
    }
157
158
    /**
159
     * @param self $parent
160
     * @return void
161
     */
162 2
    protected function afterPrepare(self $parent): void
163
    {
164 2
        $this->hinge($parent->path);
165 2
        $this->_protocol = $parent->protocol ?? $parent->_protocol ?? $this->_protocol;
166 2
        $this->_host = $parent->host ?? $parent->_host ?? $this->_host;
167 2
        $this->_name = $parent->_name . '.' . $this->_name;
168 2
        $this->methods = $this->methods ?? $parent->methods;
169 2
        $this->arrayMerge('defaults', $parent);
170 2
        $this->arrayMerge('extends', $parent);
171 2
    }
172
173
    /**
174
     * Returns an array of two elements.
175
     *
176
     * The first parameter is path,
177
     *  the second is an array of regular expressions.
178
     *
179
     * @return array
180
     */
181 6
    protected function pathExtract(): array
182
    {
183 6
        $regExp = [];
184 6
        $path = $this->path;
185
186 6
        if (\is_array($this->path)) {
187
            $regExp = \array_pop($this->path);
188
            $path = \array_pop($this->path);
189
        }
190
191 6
        return [$path, $regExp];
192
    }
193
194
    /**
195
     * if this.path === string then new Path(string, [])
196
     * else this.path === array then new Path(...this.path)
197
     */
198 6
    protected function pathInit(): void
199
    {
200 6
        [$path, $regExp] = $this->pathExtract();
201 6
        $this->path = null;
202
203 6
        if ($path) {
204 5
            $this->path = new Path($this->getDefaultRegex(), $path, $regExp);
205
        }
206 6
    }
207
208
    /**
209
     * @return void
210
     */
211 6
    protected function prepare(): void
212
    {
213 6
        $this->_protocol = '\w+';
214 6
        $this->_host = '[^\/]+';
215 6
    }
216
217
    /**
218
     * @return array
219
     * @throws \ReflectionException
220
     */
221
    protected function serializeArray(): array
222
    {
223
        $properties = [];
224
        $reflation = new \ReflectionClass($this);
225
        $protected = $reflation->getProperties(\ReflectionProperty::IS_PROTECTED);
226
        foreach ($protected as $property) {
227
            $properties[] = $property->name;
228
        }
229
        return $properties;
230
    }
231
232
    /**
233
     * @return array
234
     * @throws \ReflectionException
235
     */
236
    public function __sleep(): array
237
    {
238
        return \array_keys($this->serializeArray());
239
    }
240
241
    /**
242
     * @inheritdoc
243
     * @throws \ReflectionException
244
     */
245
    public function serialize(): string
246
    {
247
        $data = [];
248
        foreach ($this->serializeArray() as $key => $value) {
249
            $data[$value] = $this->$value;
250
        }
251
        return \serialize($data);
252
    }
253
254
    /**
255
     * @inheritdoc
256
     */
257
    public function unserialize($serialized): void
258
    {
259
        /**
260
         * @var string $serialized
261
         * @var array $data
262
         */
263
        $data = \unserialize($serialized, (array)null);
264
        foreach ($data as $key => $value) {
265
            $this->{$key} = $value;
266
        }
267
    }
268
269
    /**
270
     * @inheritdoc
271
     * @throws \ReflectionException
272
     */
273
    public function jsonSerialize(): array
274
    {
275
        $data = [];
276
        foreach ($this->serializeArray() as $key => $value) {
277
            $key = \ltrim($value, '_');
278
            $data[$key] = $this->$value;
279
        }
280
        return $data;
281
    }
282
283
}
284