Passed
Push — master ( e53071...81298c )
by Csaba
46s
created

SchemaValidator::allowExtraneous()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
namespace Fathomminds\Rest\Schema;
3
4
use Fathomminds\Rest\Schema\TypeValidators\ValidatorFactory;
5
use Fathomminds\Rest\Exceptions\RestException;
6
7
class SchemaValidator
8
{
9
    protected $fields = [];
10
    protected $allowExtraneous = false;
11
12 10
    public function validate($resource)
13
    {
14 10
        $this->expectObject($resource);
15 10
        $extraneousCheck = [];
16 10
        if (!$this->allowExtraneous) {
17 9
            $extraneousCheck = $this->validateExtraneousFields($resource);
18
        }
19 10
        $errors = array_merge(
20 10
            $this->validateRequiredFields($resource),
21
            $extraneousCheck,
22 10
            $this->validateFieldTypes($resource)
23
        );
24 10
        if (!empty($errors)) {
25 6
            throw new RestException(
26 6
                'Invalid structure',
27
                [
28 6
                    'schema' => get_class($resource),
29 6
                    'errors' => $errors,
30
                ]
31
            );
32
        }
33 4
    }
34
35 31
    public function allowExtraneous($value)
36
    {
37 31
        $this->allowExtraneous = $value;
38 31
    }
39
40 11
    private function expectObject($resource)
41
    {
42 11
        if (gettype($resource) !== 'object') {
43 1
            throw new RestException(
44 1
                'Object expected',
45
                [
46 1
                    'schema' => static::class,
47 1
                    'type' => gettype($resource),
48
                ]
49
            );
50
        }
51 10
    }
52
53 10
    private function validateRequiredFields($resource)
54
    {
55 10
        $errors = [];
56 10
        $requiredFields = $this->getRequiredFields($resource);
57 10
        foreach ($requiredFields as $fieldName) {
58 10
            if (!property_exists($resource, $fieldName)) {
59 10
                $errors[$fieldName] = 'Missing required field';
60
            }
61
        }
62 10
        return $errors;
63
    }
64
65 9
    private function validateExtraneousFields($resource)
66
    {
67 9
        $errors = [];
68 9
        foreach (array_keys(get_object_vars($resource)) as $fieldName) {
69 7
            if (!isset($resource->schema()[$fieldName])) {
70 7
                $errors[$fieldName] = 'Extraneous field';
71
            }
72
        }
73 9
        return $errors;
74
    }
75
76 10
    private function validateFieldTypes($resource)
77
    {
78 10
        $validatorFactory = new ValidatorFactory;
79 10
        $errors = [];
80 10
        foreach ($resource->schema() as $fieldName => $rules) {
81 10
            if (property_exists($resource, $fieldName)) {
82
                try {
83 8
                    $validatorFactory->create($rules)->validate($resource->{$fieldName});
84 1
                } catch (RestException $ex) {
85 1
                    $errors[$fieldName]['error'] = $ex->getMessage();
86 10
                    $errors[$fieldName]['details'] = $ex->getDetails();
87
                }
88
            }
89
        }
90 10
        return $errors;
91
    }
92
93 17
    private function filterFields($resource, $paramKey, $paramValue)
94
    {
95 17
        $fields = [];
96 17
        foreach ($resource->schema() as $fieldName => $params) {
97 17
            if (isset($params[$paramKey]) && $params[$paramKey] == $paramValue) {
98 17
                $fields[] = $fieldName;
99
            }
100
        }
101 17
        return $fields;
102
    }
103
104 2
    public function getFields($resource)
105
    {
106 2
        return $resource->schema();
107
    }
108
109 10
    public function getRequiredFields($resource)
110
    {
111 10
        return $this->filterFields($resource, 'required', true);
112
    }
113
114 9
    public function getUniqueFields($resource)
115
    {
116 9
        return $this->filterFields($resource, 'unique', true);
117
    }
118
}
119