Issues (16)

src/Rule.php (2 issues)

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 8
    public function __construct(string $key, array $storage, ?self $parent = null)
60
    {
61 8
        if ($parent) {
62 4
            $this->beforePrepare($parent);
63
        }
64 8
        $this->prepare();
65 8
        $this->initializer($key, $storage);
66 8
        $this->pathInit();
67 8
        if ($parent) {
68 4
            $this->afterPrepare($parent);
69
        }
70 8
    }
71
72
    /**
73
     * @param self $parent
74
     * @return void
75
     */
76 4
    protected function beforePrepare(self $parent): void
77
    {
78 4
        $this->defaultRegex = $this->defaultRegex ?: $parent->defaultRegex;
79 4
    }
80
81
    /**
82
     * @return void
83
     */
84 8
    protected function prepare(): void
85
    {
86 8
        $this->_protocol = '\w+';
87 8
        $this->_host = '[^\/]+';
88 8
    }
89
90
    /**
91
     * if this.path === string then new Path(string, [])
92
     * else this.path === array then new Path(...this.path)
93
     */
94 8
    protected function pathInit(): void
95
    {
96 8
        [$path, $regExp] = $this->pathExtract();
97 8
        $this->path = null;
98
99 8
        if ($path) {
100 7
            $this->path = new Path($this->getDefaultRegex(), $path, $regExp);
0 ignored issues
show
$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

100
            $this->path = new Path($this->getDefaultRegex(), /** @scrutinizer ignore-type */ $path, $regExp);
Loading history...
101
        }
102 8
    }
103
104
    /**
105
     * Returns an array of two elements.
106
     *
107
     * The first parameter is path,
108
     *  the second is an array of regular expressions.
109
     *
110
     * @return array
111
     */
112 8
    protected function pathExtract(): array
113
    {
114 8
        $regExp = [];
115 8
        $path = $this->path;
116
117 8
        if (\is_array($this->path)) {
0 ignored issues
show
The condition is_array($this->path) is always false.
Loading history...
118
            $regExp = \array_pop($this->path);
119
            $path = \array_pop($this->path);
120
        }
121
122 8
        return [$path, $regExp];
123
    }
124
125
    /**
126
     * @return string
127
     */
128 7
    public function getDefaultRegex(): string
129
    {
130 7
        return $this->defaultRegex ?: self::DEFAULT_REGEX;
131
    }
132
133
    /**
134
     * @param self $parent
135
     * @return void
136
     */
137 4
    protected function afterPrepare(self $parent): void
138
    {
139 4
        $this->hinge($parent->path);
140 4
        $this->_protocol = $parent->protocol ?? $parent->_protocol ?? $this->_protocol;
141 4
        $this->_host = $parent->host ?? $parent->_host ?? $this->_host;
142 4
        $this->_name = $parent->_name . '.' . $this->_name;
143 4
        $this->methods = $this->methods ?? $parent->methods;
144 4
        $this->arrayMerge('defaults', $parent);
145 4
        $this->arrayMerge('extends', $parent);
146 4
    }
147
148
    /**
149
     * @param Path|null $path
150
     */
151 4
    protected function hinge(?Path $path): void
152
    {
153 4
        if ($this->path && $path) {
154 4
            $this->path->hinge($path);
155 4
            return;
156
        }
157
158
        $this->path = $path ?? $this->path;
159
    }
160
161
    /**
162
     * @param string $name
163
     * @param self $parent
164
     */
165 4
    protected function arrayMerge(string $name, self $parent): void
166
    {
167 4
        $this->$name = \array_merge(
168 4
            (array)$parent->$name,
169 4
            (array)$this->$name
170
        );
171 4
    }
172
173
    /**
174
     * @return string
175
     */
176 1
    public function getName(): string
177
    {
178 1
        return $this->_name;
179
    }
180
181
    /**
182
     * @return string
183
     */
184 6
    public function getProtocol(): string
185
    {
186 6
        return $this->_protocol;
187
    }
188
189
    /**
190
     * @return string
191
     */
192 6
    public function getHost(): string
193
    {
194 6
        return $this->_host;
195
    }
196
197
    /**
198
     * @return Path
199
     */
200 6
    public function getPath(): Path
201
    {
202 6
        return $this->path;
203
    }
204
205
    /**
206
     * @return null|array
207
     */
208 7
    public function getMethods(): ?array
209
    {
210 7
        return $this->methods;
211
    }
212
213
    /**
214
     * @return array
215
     */
216
    public function getExtends(): array
217
    {
218
        return (array)$this->extends;
219
    }
220
221
    /**
222
     * @return array
223
     */
224 7
    public function getDefaults(): array
225
    {
226 7
        return (array)$this->defaults;
227
    }
228
229
    /**
230
     * @return array
231
     * @throws \ReflectionException
232
     */
233
    public function __sleep(): array
234
    {
235
        return \array_keys($this->serializeArray());
236
    }
237
238
    /**
239
     * @return array
240
     * @throws \ReflectionException
241
     */
242
    protected function serializeArray(): array
243
    {
244
        $properties = [];
245
        $reflation = new \ReflectionClass($this);
246
        $protected = $reflation->getProperties(\ReflectionProperty::IS_PROTECTED);
247
        foreach ($protected as $property) {
248
            $properties[] = $property->name;
249
        }
250
        return $properties;
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