Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
40 / 40
100.00% covered (success)
100.00%
11 / 11
CRAP
100.00% covered (success)
100.00%
1 / 1
PublicationSchemaValidator
100.00% covered (success)
100.00%
40 / 40
100.00% covered (success)
100.00%
11 / 11
14
100.00% covered (success)
100.00%
1 / 1
 call
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 __invoke
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 validate
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 errors
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 makePropertyValidator
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
1
 makeFieldsValidators
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
 evaluateFieldValidators
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 validateFields
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 makeValidator
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 mapRulesInput
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace Hyde\Publications\Actions;
6
7use stdClass;
8use Hyde\Facades\Filesystem;
9use Illuminate\Contracts\Validation\Validator;
10
11use function collect;
12use function is_array;
13use function validator;
14use function json_decode;
15
16/**
17 * @see \Hyde\Publications\Testing\Feature\PublicationSchemaValidatorTest
18 */
19class 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 */
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>> */
94    protected function evaluateFieldValidators(): array
95    {
96        return collect($this->fieldValidators)->map(function (Validator $validator): array {
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 {
116            return [$key => $input->{$key} ?? null];
117        })->all();
118    }
119}