Completed
Push — master ( 0ca994...bcdd07 )
by Neomerx
05:23
created

JsonApiRuleSerializer::getData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 0
1
<?php namespace Limoncello\Flute\Validation\Execution;
2
3
/**
4
 * Copyright 2015-2017 [email protected]
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
use Limoncello\Validation\Contracts\Execution\BlockSerializerInterface;
20
use Limoncello\Validation\Contracts\Rules\RuleInterface;
21
use Limoncello\Validation\Execution\BlockSerializer;
22
use Neomerx\JsonApi\Contracts\Document\DocumentInterface;
23
24
/**
25
 * @package Limoncello\Flute
26
 */
27
class JsonApiRuleSerializer
28
{
29
    /** Serialized indexes key */
30
    const SERIALIZED_RULE_SETS = 0;
31
32
    /** Serialized rules key */
33
    const SERIALIZED_BLOCKS = self::SERIALIZED_RULE_SETS + 1;
34
35
    /** Index key */
36
    const ID_SERIALIZED = 0;
37
38
    /** Index key */
39
    const TYPE_SERIALIZED = self::ID_SERIALIZED + 1;
40
41
    /** Index key */
42
    const ATTRIBUTES_SERIALIZED = self::TYPE_SERIALIZED + 1;
43
44
    /** Index key */
45
    const TO_ONE_SERIALIZED = self::ATTRIBUTES_SERIALIZED + 1;
46
47
    /** Index key */
48
    const TO_MANY_SERIALIZED = self::TO_ONE_SERIALIZED + 1;
49
50
    // Single rule serialization keys
51
52
    /** Index key */
53
    const SINGLE_RULE_INDEX = 0;
54
55
    /** Index key */
56
    const SINGLE_RULE_START_INDEXES = self::SINGLE_RULE_INDEX + 1;
57
58
    /** Index key */
59
    const SINGLE_RULE_END_INDEXES = self::SINGLE_RULE_START_INDEXES + 1;
60
61
    // Rules array serialization keys
62
63
    /** Index key */
64
    const RULES_ARRAY_INDEXES = 0;
65
66
    /** Index key */
67
    const RULES_ARRAY_START_INDEXES = self::RULES_ARRAY_INDEXES + 1;
68
69
    /** Index key */
70
    const RULES_ARRAY_END_INDEXES = self::RULES_ARRAY_START_INDEXES + 1;
71
72
    /**
73
     * @var BlockSerializerInterface
74
     */
75
    private $blockSerializer;
76
77
    /**
78
     * @var array
79
     */
80
    private $ruleSets;
81
82
    /**
83
     * Constructor.
84
     */
85
    public function __construct()
86
    {
87
        $this->blockSerializer = $this->createBlockSerializer();
88
        $this->ruleSets        = [];
89
    }
90
91
    /** @noinspection PhpTooManyParametersInspection
92
     * @param string          $name
93
     * @param RuleInterface   $idRule
94
     * @param RuleInterface   $typeRule
95
     * @param RuleInterface[] $attributeRules
96
     * @param RuleInterface[] $toOneRules
97
     * @param RuleInterface[] $toManyRules
98
     *
99
     * @return self
100
     */
101
    public function addResourceRules(
102
        string $name,
103
        RuleInterface $idRule,
104
        RuleInterface $typeRule,
105
        array $attributeRules,
106
        array $toOneRules,
107
        array $toManyRules
108
    ): self {
109
        assert(!empty($name));
110
        assert(!array_key_exists($name, $this->ruleSets));
111
112
        $idRule->setName(DocumentInterface::KEYWORD_ID)->enableCapture();
113
        $typeRule->setName(DocumentInterface::KEYWORD_TYPE)->enableCapture();
114
115
        $ruleSet = [
116
            static::ID_SERIALIZED         => $this->serializeRule($idRule),
117
            static::TYPE_SERIALIZED       => $this->serializeRule($typeRule),
118
            static::ATTRIBUTES_SERIALIZED => $this->serializeRulesArray($attributeRules),
119
            static::TO_ONE_SERIALIZED     => $this->serializeRulesArray($toOneRules),
120
            static::TO_MANY_SERIALIZED    => $this->serializeRulesArray($toManyRules),
121
        ];
122
123
        $this->ruleSets[$name] = $ruleSet;
124
125
        $this->getSerializer()->clearBlocksWithStart()->clearBlocksWithEnd();
126
127
        return $this;
128
    }
129
130
    /**
131
     * @return array
132
     *
133
     * @SuppressWarnings(PHPMD.StaticAccess)
134
     */
135
    public function getData(): array
136
    {
137
        return [
138
            static::SERIALIZED_RULE_SETS => $this->ruleSets,
139
            static::SERIALIZED_BLOCKS    => static::getBlocks($this->getSerializer()->get()),
140
        ];
141
    }
142
143
    /**
144
     * @param string $name
145
     * @param array  $data
146
     *
147
     * @return array
148
     */
149
    public static function extractRuleSet(string $name, array $data): array
150
    {
151
        assert($data[static::SERIALIZED_RULE_SETS] ?? false);
152
        $indexes = $data[static::SERIALIZED_RULE_SETS][$name];
153
        assert(is_array($indexes));
154
155
        return $indexes;
156
    }
157
158
    /**
159
     * @param array $data
160
     *
161
     * @return array
162
     */
163
    public static function extractBlocks(array $data): array
164
    {
165
        assert(array_key_exists(static::SERIALIZED_BLOCKS, $data));
166
        $serializedRules = $data[static::SERIALIZED_BLOCKS];
167
        assert(is_array($serializedRules));
168
169
        return $serializedRules;
170
    }
171
172
    /**
173
     * @param array $ruleSet
174
     *
175
     * @return array
176
     */
177 View Code Duplication
    public static function getIdRule(array $ruleSet): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
178
    {
179
        assert(array_key_exists(static::ID_SERIALIZED, $ruleSet));
180
        $rule = $ruleSet[static::ID_SERIALIZED];
181
        assert(is_array($rule));
182
183
        return $rule;
184
    }
185
186
    /**
187
     * @param array $ruleSet
188
     *
189
     * @return array
190
     */
191 View Code Duplication
    public static function getTypeRule(array $ruleSet): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
192
    {
193
        assert(array_key_exists(static::TYPE_SERIALIZED, $ruleSet));
194
        $rule = $ruleSet[static::TYPE_SERIALIZED];
195
        assert(is_array($rule));
196
197
        return $rule;
198
    }
199
200
    /**
201
     * @param array $ruleSet
202
     *
203
     * @return array
204
     */
205 View Code Duplication
    public static function getAttributeRules(array $ruleSet): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
206
    {
207
        assert(array_key_exists(static::ATTRIBUTES_SERIALIZED, $ruleSet));
208
        $rules = $ruleSet[static::ATTRIBUTES_SERIALIZED];
209
        assert(is_array($rules));
210
211
        return $rules;
212
    }
213
214
    /**
215
     * @param array $ruleSet
216
     *
217
     * @return array
218
     */
219 View Code Duplication
    public static function getToOneRules(array $ruleSet): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
220
    {
221
        assert(array_key_exists(static::TO_ONE_SERIALIZED, $ruleSet));
222
        $rules = $ruleSet[static::TO_ONE_SERIALIZED];
223
        assert(is_array($rules));
224
225
        return $rules;
226
    }
227
228
    /**
229
     * @param array $ruleSet
230
     *
231
     * @return array
232
     */
233 View Code Duplication
    public static function getToManyRules(array $ruleSet): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
234
    {
235
        assert(array_key_exists(static::TO_MANY_SERIALIZED, $ruleSet));
236
        $rules = $ruleSet[static::TO_MANY_SERIALIZED];
237
        assert(is_array($rules));
238
239
        return $rules;
240
    }
241
242
    /**
243
     * @param array $serializedRule
244
     *
245
     * @return int
246
     */
247 View Code Duplication
    public static function getRuleIndex(array $serializedRule): int
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
248
    {
249
        assert(array_key_exists(static::SINGLE_RULE_INDEX, $serializedRule));
250
        $result = $serializedRule[static::SINGLE_RULE_INDEX];
251
        assert(is_int($result));
252
253
        return $result;
254
    }
255
256
    /**
257
     * @param array $serializedRule
258
     *
259
     * @return array
260
     */
261 View Code Duplication
    public static function getRuleStartIndexes(array $serializedRule): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
262
    {
263
        assert(array_key_exists(static::SINGLE_RULE_START_INDEXES, $serializedRule));
264
        $result = $serializedRule[static::SINGLE_RULE_START_INDEXES];
265
        assert(is_array($result));
266
267
        return $result;
268
    }
269
270
    /**
271
     * @param array $serializedRule
272
     *
273
     * @return array
274
     */
275 View Code Duplication
    public static function getRuleEndIndexes(array $serializedRule): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
276
    {
277
        assert(array_key_exists(static::SINGLE_RULE_END_INDEXES, $serializedRule));
278
        $result = $serializedRule[static::SINGLE_RULE_END_INDEXES];
279
        assert(is_array($result));
280
281
        return $result;
282
    }
283
284
    /**
285
     * @param array $serializedRules
286
     *
287
     * @return array
288
     */
289
    public static function getRulesIndexes(array $serializedRules): array
290
    {
291
        assert(array_key_exists(static::RULES_ARRAY_INDEXES, $serializedRules));
292
        $result = $serializedRules[static::RULES_ARRAY_INDEXES];
293
        assert(is_array($result));
294
295
        return $result;
296
    }
297
298
    /**
299
     * @param array $serializedRules
300
     *
301
     * @return array
302
     */
303
    public static function getRulesStartIndexes(array $serializedRules): array
304
    {
305
        assert(array_key_exists(static::RULES_ARRAY_START_INDEXES, $serializedRules));
306
        $result = $serializedRules[static::RULES_ARRAY_START_INDEXES];
307
        assert(is_array($result));
308
309
        return $result;
310
    }
311
312
    /**
313
     * @param array $serializedRules
314
     *
315
     * @return array
316
     */
317
    public static function getRulesEndIndexes(array $serializedRules): array
318
    {
319
        assert(array_key_exists(static::RULES_ARRAY_END_INDEXES, $serializedRules));
320
        $result = $serializedRules[static::RULES_ARRAY_END_INDEXES];
321
        assert(is_array($result));
322
323
        return $result;
324
    }
325
326
    /**
327
     * @param int   $index
328
     * @param array $blocks
329
     *
330
     * @return bool
331
     */
332
    public static function isRuleExist(int $index, array $blocks): bool
333
    {
334
        $result = array_key_exists($index, $blocks);
335
336
        return $result;
337
    }
338
339
    /**
340
     * @param array $serializedRules
341
     *
342
     * @return array
343
     *
344
     * @SuppressWarnings(PHPMD.StaticAccess)
345
     */
346
    public static function getBlocks(array $serializedRules): array
347
    {
348
        $blocks = BlockSerializer::unserializeBlocks($serializedRules);
349
350
        return $blocks;
351
    }
352
353
    /**
354
     * @return BlockSerializerInterface
355
     */
356
    protected function getSerializer(): BlockSerializerInterface
357
    {
358
        return $this->blockSerializer;
359
    }
360
361
    /**
362
     * @return BlockSerializerInterface
363
     */
364
    protected function createBlockSerializer(): BlockSerializerInterface
365
    {
366
        return new BlockSerializer();
367
    }
368
369
    /**
370
     * @param RuleInterface $rule
371
     *
372
     * @return array
373
     */
374
    private function serializeRule(RuleInterface $rule): array
375
    {
376
        $this->getSerializer()->clearBlocksWithStart()->clearBlocksWithEnd();
377
378
        $result = [
379
            static::SINGLE_RULE_INDEX         => $this->getSerializer()->addBlock($rule->toBlock()),
380
            static::SINGLE_RULE_START_INDEXES => $this->getSerializer()->getBlocksWithStart(),
381
            static::SINGLE_RULE_END_INDEXES   => $this->getSerializer()->getBlocksWithEnd(),
382
        ];
383
384
        return $result;
385
    }
386
387
    /**
388
     * @param RuleInterface[] $rules
389
     *
390
     * @return array
391
     */
392
    private function serializeRulesArray(array $rules): array
393
    {
394
        $this->getSerializer()->clearBlocksWithStart()->clearBlocksWithEnd();
395
396
        $indexes = [];
397
        foreach ($rules as $name => $rule) {
398
            assert(is_string($name) === true && empty($name) === false);
399
            assert($rule instanceof RuleInterface);
400
401
            $block          = $rule->setName($name)->enableCapture()->toBlock();
402
            $indexes[$name] = $this->getSerializer()->addBlock($block);
403
        }
404
405
        return [
406
            static::RULES_ARRAY_INDEXES       => $indexes,
407
            static::RULES_ARRAY_START_INDEXES => $this->getSerializer()->getBlocksWithStart(),
408
            static::RULES_ARRAY_END_INDEXES   => $this->getSerializer()->getBlocksWithEnd(),
409
        ];
410
    }
411
}
412