PublicationSchemaValidator::__invoke()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Hyde\Publications\Actions;
6
7
use stdClass;
8
use Hyde\Facades\Filesystem;
9
use Illuminate\Contracts\Validation\Validator;
10
11
use function collect;
12
use function is_array;
13
use function validator;
14
use function json_decode;
15
16
/**
17
 * @see \Hyde\Publications\Testing\Feature\PublicationSchemaValidatorTest
18
 */
19
class PublicationSchemaValidator
20
{
21
    protected stdClass $schema;
22
23
    protected Validator $schemaValidator;
24
    protected array $fieldValidators = [];
25
26
    public static function call(string $publicationTypeName): static
27
    {
28
        return (new self($publicationTypeName))->__invoke();
29
    }
30
31
    public function __construct(string $publicationTypeName)
32
    {
33
        $this->schema = json_decode(Filesystem::getContents("$publicationTypeName/schema.json"));
34
    }
35
36
    /** @return $this */
37
    public function __invoke(): static
38
    {
39
        $this->makePropertyValidator();
40
        $this->makeFieldsValidators();
41
42
        return $this;
43
    }
44
45
    /** @throws \Illuminate\Validation\ValidationException */
46
    public function validate(): void
47
    {
48
        $this->schemaValidator->validate();
49
        $this->validateFields();
50
    }
51
52
    /** @return array<string, Validator|array */
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<string, Validator|array at position 6 could not be parsed: Expected '>' at position 6, but found 'array'.
Loading history...
53
    public function errors(): array
54
    {
55
        return [
56
            'schema' => $this->schemaValidator->errors()->all(),
57
            'fields' => $this->evaluateFieldValidators(),
58
        ];
59
    }
60
61
    protected function makePropertyValidator(): void
62
    {
63
        $rules = [
64
            'name' => 'required|string',
65
            'canonicalField' => 'nullable|string',
66
            'detailTemplate' => 'nullable|string',
67
            'listTemplate' => 'nullable|string',
68
            'sortField' => 'nullable|string',
69
            'sortAscending' => 'nullable|boolean',
70
            'pageSize' => 'nullable|integer',
71
            'fields' => 'nullable|array',
72
            'directory' => 'nullable|prohibited',
73
        ];
74
75
        $this->schemaValidator = $this->makeValidator($rules, $this->schema);
76
    }
77
78
    protected function makeFieldsValidators(): void
79
    {
80
        $rules = [
81
            'type' => 'required|string',
82
            'name' => 'required|string',
83
            'rules' => 'nullable|array',
84
        ];
85
86
        if (is_array($this->schema->fields)) {
87
            foreach ($this->schema->fields as $field) {
88
                $this->fieldValidators[] = $this->makeValidator($rules, $field);
89
            }
90
        }
91
    }
92
93
    /** @return array<array-key, array<array-key, string>> */
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<array-key, array<array-key, string>> at position 2 could not be parsed: Unknown type name 'array-key' at position 2 in array<array-key, array<array-key, string>>.
Loading history...
94
    protected function evaluateFieldValidators(): array
95
    {
96
        return collect($this->fieldValidators)->map(function (Validator $validator): array {
0 ignored issues
show
Bug introduced by
$this->fieldValidators of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect(). ( Ignorable by Annotation )

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

96
        return collect(/** @scrutinizer ignore-type */ $this->fieldValidators)->map(function (Validator $validator): array {
Loading history...
97
            return $validator->errors()->all();
98
        })->all();
99
    }
100
101
    protected function validateFields(): void
102
    {
103
        foreach ($this->fieldValidators as $validator) {
104
            $validator->validate();
105
        }
106
    }
107
108
    protected function makeValidator(array $rules, stdClass $input): Validator
109
    {
110
        return validator($this->mapRulesInput($rules, $input), $rules);
111
    }
112
113
    protected function mapRulesInput(array $rules, stdClass $input): array
114
    {
115
        return collect($rules)->mapWithKeys(function (string $rule, string $key) use ($input): array {
0 ignored issues
show
Bug introduced by
$rules of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect(). ( Ignorable by Annotation )

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

115
        return collect(/** @scrutinizer ignore-type */ $rules)->mapWithKeys(function (string $rule, string $key) use ($input): array {
Loading history...
116
            return [$key => $input->{$key} ?? null];
117
        })->all();
118
    }
119
}
120