Completed
Push — develop ( 599906...c694a4 )
by Neomerx
03:50 queued 02:08
created

Validator::getAttributeRules()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php namespace Limoncello\Flute\Validation;
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\Container\Traits\HasContainerTrait;
20
use Limoncello\Contracts\L10n\FormatterFactoryInterface;
21
use Limoncello\Contracts\L10n\FormatterInterface;
22
use Limoncello\Flute\Contracts\Validation\ErrorCodes;
23
use Limoncello\Flute\Contracts\Validation\JsonApiValidatorInterface;
24
use Limoncello\Flute\Http\JsonApiResponse;
25
use Limoncello\Flute\Validation\Execution\ContextStorage;
26
use Limoncello\Flute\Validation\Execution\JsonApiErrorCollection;
27
use Limoncello\Flute\Validation\Execution\JsonApiRuleSerializer;
28
use Limoncello\Flute\Validation\Rules\RelationshipsTrait;
29
use Limoncello\Validation\Contracts\Errors\ErrorInterface;
30
use Limoncello\Validation\Contracts\Execution\ContextStorageInterface;
31
use Limoncello\Validation\Execution\BlockInterpreter;
32
use Limoncello\Validation\Validator\BaseValidator;
33
use Neomerx\JsonApi\Contracts\Document\DocumentInterface as DI;
34
use Neomerx\JsonApi\Exceptions\JsonApiException;
35
use Psr\Container\ContainerInterface;
36
37
/**
38
 * @package Limoncello\Flute
39
 *
40
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
41
 * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
42
 */
43
class Validator extends BaseValidator implements JsonApiValidatorInterface
44
{
45
    use RelationshipsTrait, HasContainerTrait;
46
47
    /**
48
     * Namespace for string resources.
49
     */
50
    const RESOURCES_NAMESPACE = 'Limoncello.Flute.Validation';
51
52
    /** Rule description index */
53
    const RULE_INDEX = 0;
54
55
    /** Rule description index */
56
    const RULE_ATTRIBUTES = self::RULE_INDEX + 1;
57
58
    /** Rule description index */
59
    const RULE_TO_ONE = self::RULE_ATTRIBUTES + 1;
60
61
    /** Rule description index */
62
    const RULE_TO_MANY = self::RULE_TO_ONE + 1;
63
64
    /** Rule description index */
65
    const RULE_UNLISTED_ATTRIBUTE = self::RULE_TO_MANY + 1;
66
67
    /** Rule description index */
68
    const RULE_UNLISTED_RELATIONSHIP = self::RULE_UNLISTED_ATTRIBUTE + 1;
69
70
    /**
71
     * @var int
72
     */
73
    private $errorStatus;
74
75
    /**
76
     * @var ContextStorageInterface
77
     */
78
    private $contextStorage;
79
80
    /**
81
     * @var JsonApiErrorCollection
82
     */
83
    private $jsonApiErrors;
84
85
    /**
86
     * @var array
87
     */
88
    private $blocks;
89
90
    /**
91
     * @var array
92
     */
93
    private $idRule;
94
95
    /**
96
     * @var array
97
     */
98
    private $typeRule;
99
100
    /**
101
     * @var int[]
102
     */
103
    private $attributeRules;
104
105
    /**
106
     * @var int[]
107
     */
108
    private $toOneRules;
109
110
    /**
111
     * @var int[]
112
     */
113
    private $toManyRules;
114
115
    /**
116
     * @var bool
117
     */
118
    private $isIgnoreUnknowns;
119
120
    /**
121
     * @var FormatterInterface|null
122
     */
123
    private $messageFormatter;
124
125
    /**
126
     * @param string             $name
127
     * @param array              $data
128
     * @param ContainerInterface $container
129
     * @param int                $errorStatus
130
     *
131
     * @SuppressWarnings(PHPMD.StaticAccess)
132
     */
133 21
    public function __construct(
134
        string $name,
135
        array $data,
136
        ContainerInterface $container,
137
        int $errorStatus = JsonApiResponse::HTTP_UNPROCESSABLE_ENTITY
138
    ) {
139 21
        $this->setContainer($container);
140
141 21
        $ruleSet           = JsonApiRuleSerializer::extractRuleSet($name, $data);
142 21
        $this->blocks      = JsonApiRuleSerializer::extractBlocks($data);
143 21
        $this->idRule      = JsonApiRuleSerializer::getIdRule($ruleSet);
144 21
        $this->typeRule    = JsonApiRuleSerializer::getTypeRule($ruleSet);
145 21
        $this->errorStatus = $errorStatus;
146
147
        $this
148 21
            ->setAttributeRules(JsonApiRuleSerializer::getAttributeRules($ruleSet))
149 21
            ->setToOneIndexes(JsonApiRuleSerializer::getToOneRules($ruleSet))
150 21
            ->setToManyIndexes(JsonApiRuleSerializer::getToManyRules($ruleSet))
151 21
            ->disableIgnoreUnknowns();
152
153 21
        parent::__construct();
154
    }
155
156
    /**
157
     * @inheritdoc
158
     */
159 12
    public function assert($jsonData): JsonApiValidatorInterface
160
    {
161 12
        if ($this->validate($jsonData) === false) {
162 6
            throw new JsonApiException($this->getJsonApiErrorCollection(), $this->getErrorStatus());
163
        }
164
165 6
        return $this;
166
    }
167
168
    /**
169
     * @inheritdoc
170
     *
171
     * @SuppressWarnings(PHPMD.ElseExpression)
172
     */
173 18
    public function validate($input): bool
174
    {
175 18
        $this->reInitAggregatorsIfNeeded();
176
177 18
        if (is_array($input) === true) {
178
            $this
179 17
                ->validateType($input)
180 17
                ->validateId($input)
181 17
                ->validateAttributes($input)
182 17
                ->validateRelationships($input);
183
        } else {
184 1
            $title   = $this->formatMessage(ErrorCodes::INVALID_VALUE);
185 1
            $details = $this->formatMessage(ErrorCodes::INVALID_VALUE);
186 1
            $this->getJsonApiErrorCollection()->addDataError($title, $details, $this->getErrorStatus());
187
        }
188
189 18
        $hasNoErrors = $this->getJsonApiErrorCollection()->count() <= 0;
190
191 18
        return $hasNoErrors;
192
    }
193
194
    /**
195
     * @inheritdoc
196
     */
197 6
    public function getJsonApiErrors(): array
198
    {
199 6
        return $this->getJsonApiErrorCollection()->getArrayCopy();
200
    }
201
202
    /**
203
     * @inheritdoc
204
     */
205 11
    public function getJsonApiCaptures(): array
206
    {
207 11
        return $this->getCaptures()->get();
208
    }
209
210
    /**
211
     * @return BaseValidator
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use Validator.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
212
     */
213 21
    protected function resetAggregators(): BaseValidator
214
    {
215 21
        $self = parent::resetAggregators();
216
217 21
        $this->jsonApiErrors  = $this->createJsonApiErrors();
218 21
        $this->contextStorage = $this->createContextStorage();
219
220 21
        return $self;
221
    }
222
223
    /**
224
     * @param array $jsonData
225
     *
226
     * @return self
227
     *
228
     * @SuppressWarnings(PHPMD.StaticAccess)
229
     * @SuppressWarnings(PHPMD.ElseExpression)
230
     */
231 17
    private function validateType(array $jsonData): self
232
    {
233
        // execute start(s)
234 17
        $starts = JsonApiRuleSerializer::getRuleStartIndexes($this->getTypeRule());
235 17
        $this->executeStarts($starts);
236
237 17
        if (array_key_exists(DI::KEYWORD_DATA, $jsonData) === true &&
238 17
            array_key_exists(DI::KEYWORD_TYPE, $data = $jsonData[DI::KEYWORD_DATA]) === true
239
        ) {
240
            // execute main validation block(s)
241 16
            $index = JsonApiRuleSerializer::getRuleIndex($this->getTypeRule());
242 16
            $this->executeBlock($data[DI::KEYWORD_TYPE], $index);
243
        } else {
244 1
            $title   = $this->formatMessage(ErrorCodes::INVALID_VALUE);
245 1
            $details = $this->formatMessage(ErrorCodes::TYPE_MISSING);
246 1
            $this->getJsonApiErrorCollection()->addDataTypeError($title, $details, $this->getErrorStatus());
247
        }
248
249
        // execute end(s)
250 17
        $ends = JsonApiRuleSerializer::getRuleEndIndexes($this->getTypeRule());
251 17
        $this->executeEnds($ends);
252
253 17 View Code Duplication
        if (count($this->getErrors()) > 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
254 1
            $title = $this->formatMessage(ErrorCodes::INVALID_VALUE);
255 1
            foreach ($this->getErrors()->get() as $error) {
256 1
                $this->getJsonApiErrorCollection()
257 1
                    ->addDataTypeError($title, $this->getMessage($error), $this->getErrorStatus());
258
            }
259 1
            $this->getErrors()->clear();
260
        }
261
262 17
        return $this;
263
    }
264
265
    /**
266
     * @param array $jsonData
267
     *
268
     * @return self
269
     *
270
     * @SuppressWarnings(PHPMD.StaticAccess)
271
     */
272 17
    private function validateId(array $jsonData): self
273
    {
274
        // execute start(s)
275 17
        $starts = JsonApiRuleSerializer::getRuleStartIndexes($this->getIdRule());
276 17
        $this->executeStarts($starts);
277
278
        // execute main validation block(s)
279 17
        if (array_key_exists(DI::KEYWORD_DATA, $jsonData) === true &&
280 17
            array_key_exists(DI::KEYWORD_ID, $data = $jsonData[DI::KEYWORD_DATA]) === true
281
        ) {
282 15
            $index = JsonApiRuleSerializer::getRuleIndex($this->getIdRule());
283 15
            $this->executeBlock($data[DI::KEYWORD_ID], $index);
284
        }
285
286
        // execute end(s)
287 17
        $ends = JsonApiRuleSerializer::getRuleEndIndexes($this->getIdRule());
288 17
        $this->executeEnds($ends);
289
290 17 View Code Duplication
        if (count($this->getErrors()) > 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
291 3
            $title = $this->formatMessage(ErrorCodes::INVALID_VALUE);
292 3
            foreach ($this->getErrors()->get() as $error) {
293 3
                $this->getJsonApiErrorCollection()
294 3
                    ->addDataIdError($title, $this->getMessage($error), $this->getErrorStatus());
295
            }
296 3
            $this->getErrors()->clear();
297
        }
298
299 17
        return $this;
300
    }
301
302
    /**
303
     * @param array $jsonData
304
     *
305
     * @return self
306
     *
307
     * @SuppressWarnings(PHPMD.StaticAccess)
308
     * @SuppressWarnings(PHPMD.ElseExpression)
309
     */
310 17
    private function validateAttributes(array $jsonData): self
311
    {
312
        // execute start(s)
313 17
        $starts = JsonApiRuleSerializer::getRulesStartIndexes($this->getAttributeRules());
314 17
        $this->executeStarts($starts);
315
316 17
        if (array_key_exists(DI::KEYWORD_DATA, $jsonData) === true &&
317 17
            array_key_exists(DI::KEYWORD_ATTRIBUTES, $data = $jsonData[DI::KEYWORD_DATA]) === true
318
        ) {
319 16
            if (is_array($attributes = $data[DI::KEYWORD_ATTRIBUTES]) === false) {
320 2
                $title   = $this->formatMessage(ErrorCodes::INVALID_VALUE);
321 2
                $details = $this->formatMessage(ErrorCodes::INVALID_ATTRIBUTES);
322 2
                $this->getJsonApiErrorCollection()->addAttributesError($title, $details, $this->getErrorStatus());
323
            } else {
324
                // execute main validation block(s)
325 14
                foreach ($attributes as $name => $value) {
326 11
                    if ($this->hasAttributeIndex($name) === true) {
327 10
                        $this->executeBlock($value, $this->getAttributeIndex($name));
328 1 View Code Duplication
                    } elseif ($this->isIgnoreUnknowns() === false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
329 1
                        $title   = $this->formatMessage(ErrorCodes::INVALID_VALUE);
330 1
                        $details = $this->formatMessage(ErrorCodes::UNKNOWN_ATTRIBUTE);
331 1
                        $status  = $this->getErrorStatus();
332 11
                        $this->getJsonApiErrorCollection()->addDataAttributeError($name, $title, $details, $status);
333
                    }
334
                }
335
            }
336
        }
337
338
        // execute end(s)
339 17
        $ends = JsonApiRuleSerializer::getRulesEndIndexes($this->getAttributeRules());
340 17
        $this->executeEnds($ends);
341
342 17
        if (count($this->getErrors()) > 0) {
343 2
            foreach ($this->getErrors()->get() as $error) {
344 2
                $this->getJsonApiErrorCollection()->addValidationAttributeError($error);
345
            }
346 2
            $this->getErrors()->clear();
347
        }
348
349 17
        return $this;
350
    }
351
352
    /**
353
     * @param array $jsonData
354
     *
355
     * @return self
356
     *
357
     * @SuppressWarnings(PHPMD.StaticAccess)
358
     * @SuppressWarnings(PHPMD.ElseExpression)
359
     */
360 17
    private function validateRelationships(array $jsonData): self
361
    {
362
        // execute start(s)
363 17
        $starts = array_merge(
364 17
            JsonApiRuleSerializer::getRulesStartIndexes($this->getToOneRules()),
365 17
            JsonApiRuleSerializer::getRulesStartIndexes($this->getToManyRules())
366
        );
367 17
        $this->executeStarts($starts);
368
369 17
        if (array_key_exists(DI::KEYWORD_DATA, $jsonData) === true &&
370 17
            array_key_exists(DI::KEYWORD_RELATIONSHIPS, $data = $jsonData[DI::KEYWORD_DATA]) === true
371
        ) {
372 10
            if (is_array($relationships = $data[DI::KEYWORD_RELATIONSHIPS]) === false) {
373 1
                $title   = $this->formatMessage(ErrorCodes::INVALID_VALUE);
374 1
                $details = $this->formatMessage(ErrorCodes::INVALID_RELATIONSHIP_TYPE);
375 1
                $this->getJsonApiErrorCollection()->addRelationshipsError($title, $details, $this->getErrorStatus());
376
            } else {
377
                // ok we got to something that could be null or a valid relationship
378 9
                $toOneIndexes  = JsonApiRuleSerializer::getRulesIndexes($this->getToOneRules());
379 9
                $toManyIndexes = JsonApiRuleSerializer::getRulesIndexes($this->getToManyRules());
380
381 9
                foreach ($relationships as $name => $relationship) {
382 9
                    if (array_key_exists($name, $toOneIndexes) === true) {
383
                        // it might be to1 relationship
384 8
                        $this->validateAsToOneRelationship($toOneIndexes[$name], $name, $relationship);
385 9
                    } elseif (array_key_exists($name, $toManyIndexes) === true) {
386
                        // it might be toMany relationship
387 8
                        $this->validateAsToManyRelationship($toManyIndexes[$name], $name, $relationship);
388 View Code Duplication
                    } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
389
                        // unknown relationship
390 1
                        $title   = $this->formatMessage(ErrorCodes::INVALID_VALUE);
391 1
                        $details = $this->formatMessage(ErrorCodes::UNKNOWN_RELATIONSHIP);
392 1
                        $status  = $this->getErrorStatus();
393 9
                        $this->getJsonApiErrorCollection()->addRelationshipError($name, $title, $details, $status);
394
                    }
395
                }
396
            }
397
        }
398
399
        // execute end(s)
400 17
        $ends = array_merge(
401 17
            JsonApiRuleSerializer::getRulesEndIndexes($this->getToOneRules()),
402 17
            JsonApiRuleSerializer::getRulesEndIndexes($this->getToManyRules())
403
        );
404 17
        $this->executeEnds($ends);
405
406 17
        if (count($this->getErrors()) > 0) {
407 3
            foreach ($this->getErrors()->get() as $error) {
408 3
                $this->getJsonApiErrorCollection()->addValidationRelationshipError($error);
409
            }
410 3
            $this->getErrors()->clear();
411
        }
412
413 17
        return $this;
414
    }
415
416
    /**
417
     * @param int    $index
418
     * @param string $name
419
     * @param mixed  $mightBeRelationship
420
     *
421
     * @return void
422
     *
423
     * @SuppressWarnings(PHPMD.ElseExpression)
424
     */
425 8
    private function validateAsToOneRelationship(int $index, string $name, $mightBeRelationship): void
426
    {
427 8
        if (is_array($mightBeRelationship) === true &&
428 8
            array_key_exists(DI::KEYWORD_DATA, $mightBeRelationship) === true &&
429 8
            ($parsed = $this->parseSingleRelationship($mightBeRelationship[DI::KEYWORD_DATA])) !== false
430
        ) {
431
            // All right we got something. Now pass it to a validation rule.
432 6
            $this->executeBlock($parsed, $index);
433
        } else {
434 2
            $title   = $this->formatMessage(ErrorCodes::INVALID_VALUE);
435 2
            $details = $this->formatMessage(ErrorCodes::INVALID_RELATIONSHIP);
436 2
            $this->getJsonApiErrorCollection()->addRelationshipError($name, $title, $details, $this->getErrorStatus());
437
        }
438
    }
439
440
    /**
441
     * @param int    $index
442
     * @param string $name
443
     * @param mixed  $mightBeRelationship
444
     *
445
     * @return void
446
     *
447
     * @SuppressWarnings(PHPMD.ElseExpression)
448
     */
449 8
    private function validateAsToManyRelationship(int $index, string $name, $mightBeRelationship): void
450
    {
451 8
        $isParsed       = true;
452 8
        $collectedPairs = [];
453 8
        if (is_array($mightBeRelationship) === true &&
454 8
            array_key_exists(DI::KEYWORD_DATA, $mightBeRelationship) === true &&
455 8
            is_array($data = $mightBeRelationship[DI::KEYWORD_DATA]) === true
456
        ) {
457 6
            foreach ($data as $mightTypeAndId) {
458
                // we accept only pairs of type and id (no `null`s are accepted).
459 5
                if (is_array($parsed = $this->parseSingleRelationship($mightTypeAndId)) === true) {
460 4
                    $collectedPairs[] = $parsed;
461
                } else {
462 1
                    $isParsed = false;
463 6
                    break;
464
                }
465
            }
466
        } else {
467 2
            $isParsed = false;
468
        }
469
470 8 View Code Duplication
        if ($isParsed === true) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
471
            // All right we got something. Now pass it to a validation rule.
472 5
            $this->executeBlock($collectedPairs, $index);
473
        } else {
474 3
            $title   = $this->formatMessage(ErrorCodes::INVALID_VALUE);
475 3
            $details = $this->formatMessage(ErrorCodes::INVALID_RELATIONSHIP);
476 3
            $this->getJsonApiErrorCollection()->addRelationshipError($name, $title, $details, $this->getErrorStatus());
477
        }
478
    }
479
480
    /**
481
     * @param mixed $data
482
     *
483
     * @return array|null|false Either `array` ($type => $id), or `null`, or `false` on error.
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<*,integer|double|string|boolean>|false|null.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
484
     *
485
     * @SuppressWarnings(PHPMD.ElseExpression)
486
     */
487 7
    private function parseSingleRelationship($data)
488
    {
489 7
        if ($data === null) {
490 2
            $result = null;
491 5
        } elseif (is_array($data) === true &&
492 5
            array_key_exists(DI::KEYWORD_TYPE, $data) === true &&
493 5
            array_key_exists(DI::KEYWORD_ID, $data) === true &&
494 5
            is_scalar($type = $data[DI::KEYWORD_TYPE]) === true &&
495 5
            is_scalar($index = $data[DI::KEYWORD_ID]) === true
496
        ) {
497 4
            $result = [$type => $index];
498
        } else {
499 1
            $result = false;
500
        }
501
502 7
        return $result;
503
    }
504
505
    /**
506
     * Re-initializes internal aggregators for captures, errors, etc.
507
     */
508 18
    private function reInitAggregatorsIfNeeded(): void
509
    {
510 18
        $this->areAggregatorsDirty() === false ?: $this->resetAggregators();
511
    }
512
513
    /**
514
     * @param mixed $input
515
     * @param int   $index
516
     *
517
     * @return void
518
     *
519
     * @SuppressWarnings(PHPMD.StaticAccess)
520
     */
521 16
    private function executeBlock($input, int $index): void
522
    {
523 16
        BlockInterpreter::executeBlock(
524 16
            $input,
525 16
            $index,
526 16
            $this->getBlocks(),
527 16
            $this->getContextStorage(),
528 16
            $this->getCaptures(),
529 16
            $this->getErrors()
530
        );
531
    }
532
533
    /**
534
     * @param array $indexes
535
     *
536
     * @return void
537
     *
538
     * @SuppressWarnings(PHPMD.StaticAccess)
539
     */
540 17
    private function executeStarts(array $indexes): void
541
    {
542 17
        BlockInterpreter::executeStarts($indexes, $this->getBlocks(), $this->getContextStorage(), $this->getErrors());
543
    }
544
545
    /**
546
     * @param array $indexes
547
     *
548
     * @return void
549
     *
550
     * @SuppressWarnings(PHPMD.StaticAccess)
551
     */
552 17
    private function executeEnds(array $indexes): void
553
    {
554 17
        BlockInterpreter::executeEnds($indexes, $this->getBlocks(), $this->getContextStorage(), $this->getErrors());
555
    }
556
557
    /**
558
     * @param ErrorInterface $error
559
     *
560
     * @return string
561
     */
562 3 View Code Duplication
    private function getMessage(ErrorInterface $error): string
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...
563
    {
564 3
        $context = $error->getMessageContext();
565 3
        $args    = $context === null ? [] : $context;
566 3
        $message = $this->formatMessage($error->getMessageCode(), $args);
567
568 3
        return $message;
569
    }
570
571
    /**
572
     * @return array
573
     */
574 17
    protected function getIdRule(): array
575
    {
576 17
        return $this->idRule;
577
    }
578
579
    /**
580
     * @return array
581
     */
582 17
    protected function getTypeRule(): array
583
    {
584 17
        return $this->typeRule;
585
    }
586
587
    /**
588
     * @return ContextStorageInterface
589
     */
590 17
    protected function getContextStorage(): ContextStorageInterface
591
    {
592 17
        return $this->contextStorage;
593
    }
594
595
    /**
596
     * @return ContextStorageInterface
597
     */
598 21
    protected function createContextStorage(): ContextStorageInterface
599
    {
600 21
        return new ContextStorage($this->getContainer(), $this->getBlocks());
601
    }
602
603
    /**
604
     * @return JsonApiErrorCollection
605
     */
606 18
    protected function getJsonApiErrorCollection(): JsonApiErrorCollection
607
    {
608 18
        return $this->jsonApiErrors;
609
    }
610
611
    /**
612
     * @return JsonApiErrorCollection
613
     */
614 21
    protected function createJsonApiErrors(): JsonApiErrorCollection
615
    {
616 21
        return new JsonApiErrorCollection($this->getContainer(), $this->getErrorStatus());
617
    }
618
619
    /**
620
     * @return int
621
     */
622 21
    protected function getErrorStatus(): int
623
    {
624 21
        return $this->errorStatus;
625
    }
626
627
    /**
628
     * @return bool
629
     */
630 1
    protected function isIgnoreUnknowns(): bool
631
    {
632 1
        return $this->isIgnoreUnknowns;
633
    }
634
635
    /**
636
     * @return self
637
     */
638 1
    protected function enableIgnoreUnknowns(): self
639
    {
640 1
        $this->isIgnoreUnknowns = true;
641
642 1
        return $this;
643
    }
644
645
    /**
646
     * @return self
647
     */
648 21
    protected function disableIgnoreUnknowns(): self
649
    {
650 21
        $this->isIgnoreUnknowns = false;
651
652 21
        return $this;
653
    }
654
655
    /**
656
     * @param array $rules
657
     *
658
     * @return self
659
     */
660 21
    private function setAttributeRules(array $rules): self
661
    {
662 21
        assert($this->debugCheckIndexesExist($rules));
663
664 21
        $this->attributeRules = $rules;
665
666 21
        return $this;
667
    }
668
669
    /**
670
     * @param array $rules
671
     *
672
     * @return self
673
     */
674 21
    private function setToOneIndexes(array $rules): self
675
    {
676 21
        assert($this->debugCheckIndexesExist($rules));
677
678 21
        $this->toOneRules = $rules;
679
680 21
        return $this;
681
    }
682
683
    /**
684
     * @param array $rules
685
     *
686
     * @return self
687
     */
688 21
    private function setToManyIndexes(array $rules): self
689
    {
690 21
        assert($this->debugCheckIndexesExist($rules));
691
692 21
        $this->toManyRules = $rules;
693
694 21
        return $this;
695
    }
696
697
    /**
698
     * @return int[]
699
     */
700 17
    protected function getAttributeRules(): array
701
    {
702 17
        return $this->attributeRules;
703
    }
704
705
    /**
706
     * @return int[]
707
     */
708 17
    protected function getToOneRules(): array
709
    {
710 17
        return $this->toOneRules;
711
    }
712
713
    /**
714
     * @return int[]
715
     */
716 17
    protected function getToManyRules(): array
717
    {
718 17
        return $this->toManyRules;
719
    }
720
721
    /**
722
     * @return array
723
     */
724 21
    private function getBlocks(): array
725
    {
726 21
        return $this->blocks;
727
    }
728
729
    /**
730
     * @return FormatterInterface
731
     */
732 9
    protected function getMessageFormatter(): FormatterInterface
733
    {
734 9
        if ($this->messageFormatter === null) {
735
            /** @var FormatterFactoryInterface $factory */
736 9
            $factory                = $this->getContainer()->get(FormatterFactoryInterface::class);
737 9
            $this->messageFormatter = $factory->createFormatter(static::RESOURCES_NAMESPACE);
738
        }
739
740 9
        return $this->messageFormatter;
741
    }
742
743
    /**
744
     * @param string $name
745
     *
746
     * @return int
747
     *
748
     * @SuppressWarnings(PHPMD.StaticAccess)
749
     */
750 10
    private function getAttributeIndex(string $name): int
751
    {
752 10
        $indexes = JsonApiRuleSerializer::getRulesIndexes($this->getAttributeRules());
753 10
        $index   = $indexes[$name];
754
755 10
        return $index;
756
    }
757
758
    /**
759
     * @param string $name
760
     *
761
     * @return bool
762
     *
763
     * @SuppressWarnings(PHPMD.StaticAccess)
764
     */
765 11
    private function hasAttributeIndex(string $name): bool
766
    {
767 11
        $indexes      = JsonApiRuleSerializer::getRulesIndexes($this->getAttributeRules());
768 11
        $hasAttribute = array_key_exists($name, $indexes);
769
770 11
        return $hasAttribute;
771
    }
772
773
    /**
774
     * @param int   $messageId
775
     * @param array $args
776
     *
777
     * @return string
778
     */
779 9
    private function formatMessage(int $messageId, array $args = []): string
780
    {
781 9
        $message = $this->getMessageFormatter()->formatMessage($messageId, $args);
782
783 9
        return $message;
784
    }
785
786
    /**
787
     * @param array $rules
788
     *
789
     * @return bool
790
     *
791
     * @SuppressWarnings(PHPMD.StaticAccess)
792
     */
793 21
    private function debugCheckIndexesExist(array $rules): bool
794
    {
795 21
        $allOk = true;
796
797 21
        $indexes = array_merge(
798 21
            JsonApiRuleSerializer::getRulesIndexes($rules),
799 21
            JsonApiRuleSerializer::getRulesStartIndexes($rules),
800 21
            JsonApiRuleSerializer::getRulesEndIndexes($rules)
801
        );
802
803 21
        foreach ($indexes as $index) {
804 17
            $allOk = $allOk && is_int($index) && JsonApiRuleSerializer::isRuleExist($index, $this->getBlocks());
805
        }
806
807 21
        return $allOk;
808
    }
809
}
810