Completed
Pull Request — master (#76)
by Simone
08:31
created

Schema::validate()   C

Complexity

Conditions 11
Paths 27

Size

Total Lines 35
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 35
rs 5.2653
cc 11
eloc 18
nc 27
nop 1

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * This file is part of sensorario/resources repository
5
 *
6
 * (c) Simone Gentili <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Sensorario\Resources\Schema;
13
14
use RuntimeException;
15
16
final class Schema
17
{
18
    const PRIMITIVE_ARRAY   = 'array';
19
    const PRIMITIVE_BOOLEAN = 'boolean';
20
    const PRIMITIVE_DEFAULT = Schema::PRIMITIVE_NULL;
21
    const PRIMITIVE_INTEGER = 'integer';
22
    const PRIMITIVE_NULL    = 'null';
23
    const PRIMITIVE_NUMBER  = 'number';
24
    const PRIMITIVE_OBJECT  = 'object';
25
    const PRIMITIVE_STRING  = 'string';
26
27
    private $completeSchema;
28
29
    private $schemaNames = [];
30
31
    private $required = [];
32
33
    private $validTypes = [
34
        self::PRIMITIVE_ARRAY,
35
        self::PRIMITIVE_BOOLEAN,
36
        self::PRIMITIVE_DEFAULT,
37
        self::PRIMITIVE_INTEGER,
38
        self::PRIMITIVE_NULL,
39
        self::PRIMITIVE_NUMBER,
40
        self::PRIMITIVE_OBJECT,
41
        self::PRIMITIVE_STRING,
42
    ];
43
44
    private $subSchemaCounter = 0;
45
46
    private $properties = [];
47
48
    public function __construct(
49
        Parser $parser,
50
        $schema
51
    ) {
52
        $this->completeSchema = $schema;
53
        $this->schemaNames[] = 'root';
54
        $this->parser = $parser;
0 ignored issues
show
Bug introduced by
The property parser does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
55
        $this->parseSchema($this->completeSchema);
56
    }
57
58
    private function parseSchema($schema)
59
    {
60
        $this->parser->setSchema($schema);
61
        $this->parser->setValidTypes($this->validTypes);
62
        $this->parser->parseSchema();
63
64
        foreach ($schema['properties'] as $name => $def) {
65
            $this->properties[$name] = $def;
66
            if (!isset($def['type'])) {
67
                throw new Exceptions\NoPropertyTypeException();
68
            }
69
        }
70
71
        if (isset($schema['required'])) {
72
            $this->required = array_merge(
73
                $this->required,
74
                $schema['required']
75
            );
76
        }
77
78
        foreach ($schema as $key => $value) {
79
            if (!in_array($key, ['required', 'properties', 'title', 'type'])) {
80
                $this->schemaNames[] = $key;
81
                $this->subSchemaCounter++;
82
                $this->parseSchema($value);
83
            }
84
        }
85
    }
86
87
    public function countSubSchemas()
88
    {
89
        return $this->subSchemaCounter;
90
    }
91
92
    public function completeSchema()
93
    {
94
        return $this->completeSchema;
95
    }
96
97
    public function schemaNames()
98
    {
99
        return $this->schemaNames;
100
    }
101
102
    public function getTitle()
103
    {
104
        return $this->completeSchema['title'];
105
    }
106
107
    /** @todo move this inside an applipcation service */
108
    public function validate($json) 
109
    {
110
        $jsonAsArray = json_decode($json, true);
111
112
        foreach ($jsonAsArray as $name => $property) {
113
            if (!isset($this->properties()[$name])) {
114
                throw new Exceptions\NotAllowedPropertyException();
115
            }
116
        }
117
118
        foreach ($this->required as $requiredProperty) {
119
            if (!isset($jsonAsArray[$requiredProperty])) {
120
                throw new Exceptions\MissingPropertyException();
121
            }
122
        }
123
124
        foreach ($jsonAsArray as $name => $property) {
125
            $prop = $this->properties()[$name];
126
            if (gettype($jsonAsArray[$name]) != $prop['type']) {
127
                if ($prop['type'] == Schema::PRIMITIVE_INTEGER && is_numeric($jsonAsArray[$name])) {
128
                    continue;
129
                }
130
131
                if ($prop['type'] == Schema::PRIMITIVE_ARRAY) {
132
                    if (!isset($prop['items'])) {
133
                        throw new Exceptions\UndefinedArrayItemsTypeException();
134
                    }
135
                }
136
137
                throw new Exceptions\NotAllowedValueException();
138
            }
139
        }
140
141
        return json_decode($json);
142
    }
143
144
    public function properties()
145
    {
146
        return $this->properties;
147
    }
148
149
    public function required()
150
    {
151
        return $this->required;
152
    }
153
}
154