Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
93.85% |
61 / 65 |
|
85.71% |
12 / 14 |
CRAP | |
0.00% |
0 / 1 |
Schema | |
93.85% |
61 / 65 |
|
85.71% |
12 / 14 |
39.35 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
withResolvedReferences | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
2 | |||
resolveKey | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
4 | |||
resolveReferences | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
3 | |||
toJsonObject | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 | |||
setJsonObject | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setDefaults | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setJsonCompressLevel | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
toSanitizedArray | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
toSanitizedValue | |
100.00% |
13 / 13 |
|
100.00% |
1 / 1 |
7 | |||
toSanitizedList | |
66.67% |
6 / 9 |
|
0.00% |
0 / 1 |
8.81 | |||
isItemEmpty | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
3 | |||
withoutRefs | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getWithoutRefs | |
83.33% |
5 / 6 |
|
0.00% |
0 / 1 |
4.07 |
1 | <?php |
2 | |
3 | namespace BO\Zmsentities\Schema; |
4 | |
5 | class Schema extends \ArrayObject |
6 | { |
7 | protected $input = null; |
8 | |
9 | protected $asObject = null; |
10 | |
11 | protected $defaults = []; |
12 | |
13 | /** |
14 | * @var Int $jsonCompressLevel |
15 | */ |
16 | protected $jsonCompressLevel = 0; |
17 | |
18 | /** |
19 | * Read the json schema and let array act like an object |
20 | */ |
21 | public function __construct($input = [], $flags = \ArrayObject::ARRAY_AS_PROPS, $iterator_class = "ArrayIterator") |
22 | { |
23 | $this->input = $input; |
24 | parent::__construct($input, $flags, $iterator_class); |
25 | } |
26 | |
27 | public function withResolvedReferences($resolveLevel) |
28 | { |
29 | if ($resolveLevel > 0) { |
30 | $schema = clone $this; |
31 | $schema = $this->resolveReferences($schema, $resolveLevel); |
32 | $schema->setJsonObject(json_decode(json_encode($schema->toSanitizedArray(true)))); |
33 | return $schema; |
34 | } |
35 | return $this; |
36 | } |
37 | |
38 | protected function resolveKey($key, $value, $resolveLevel) |
39 | { |
40 | //error_log("Resolve($resolveLevel) Key = " . $key . " -> " . gettype($value)); |
41 | if (is_array($value)) { |
42 | $value = $this->resolveReferences($value, $resolveLevel); |
43 | } elseif ($key === '$ref' && $value[0] != '#') { |
44 | //error_log("Load $value"); |
45 | $value = Loader::asArray($value)->withResolvedReferences($resolveLevel - 1); |
46 | } |
47 | return $value; |
48 | } |
49 | |
50 | protected function resolveReferences($hash, $resolveLevel) |
51 | { |
52 | foreach ($hash as $key => $value) { |
53 | $hash[$key] = $this->resolveKey($key, $value, $resolveLevel); |
54 | if ($hash[$key] instanceof self) { |
55 | // Schema from Loader::asArray() is returned, we guess $key is '$ref' and should be replaced |
56 | return $hash[$key]->getArrayCopy(); |
57 | } |
58 | } |
59 | return $hash; |
60 | } |
61 | |
62 | public function toJsonObject($keepEmpty = false) |
63 | { |
64 | if (null !== $this->asObject) { |
65 | $data = $this->asObject; |
66 | } elseif (! $keepEmpty) { |
67 | $data = json_decode(json_encode($this->toSanitizedArray($keepEmpty))); |
68 | } else { |
69 | $data = json_decode(json_encode($this->toSanitizedArray($keepEmpty))); |
70 | } |
71 | return $data; |
72 | } |
73 | |
74 | public function setJsonObject(\stdClass $asObject) |
75 | { |
76 | $this->asObject = $asObject; |
77 | return $this; |
78 | } |
79 | |
80 | public function setDefaults($defaults) |
81 | { |
82 | $this->defaults = $defaults; |
83 | } |
84 | |
85 | public function setJsonCompressLevel($jsonCompressLevel) |
86 | { |
87 | $this->jsonCompressLevel = $jsonCompressLevel; |
88 | return $this; |
89 | } |
90 | |
91 | public function toSanitizedArray($keepEmpty = false) |
92 | { |
93 | $data = $this->getArrayCopy(); |
94 | $data = $this->toSanitizedValue($data, $keepEmpty, $this->defaults); |
95 | return $data; |
96 | } |
97 | |
98 | /** |
99 | * Sanitize value for valid export as JSON |
100 | * |
101 | */ |
102 | protected function toSanitizedValue($value, $keepEmpty = false, $defaults = []) |
103 | { |
104 | if ($value instanceof \BO\Zmsentities\Helper\NoSanitize) { |
105 | return $value; |
106 | } |
107 | if ($value instanceof \BO\Zmsentities\Collection\JsonUnindexed) { |
108 | $value = array_values($value->getArrayCopy()); |
109 | } elseif ($value instanceof \ArrayObject) { |
110 | if (method_exists($value, 'getDefaults')) { |
111 | $defaults = $value->getDefaults(); |
112 | } |
113 | $value = $value->getArrayCopy(); |
114 | } |
115 | if (is_array($value)) { |
116 | $value = $this->toSanitizedList($value, $keepEmpty, $defaults); |
117 | } |
118 | if ($value instanceof \JsonSerializable) { |
119 | $value = $value->jsonSerialize(); |
120 | } |
121 | return $value; |
122 | } |
123 | |
124 | protected function toSanitizedList($value, $keepEmpty, $defaults = []) |
125 | { |
126 | foreach ($value as $key => $item) { |
127 | if ($this->jsonCompressLevel > 0 && isset($defaults[$key])) { |
128 | $value[$key] = $this->toSanitizedValue($item, $keepEmpty, $defaults[$key]); |
129 | if ($defaults[$key] === $value[$key]) { |
130 | $value[$key] = null; |
131 | } |
132 | } else { |
133 | $value[$key] = $this->toSanitizedValue($item, $keepEmpty); |
134 | } |
135 | if (! $keepEmpty && $this->isItemEmpty($value[$key])) { |
136 | unset($value[$key]); |
137 | } |
138 | } |
139 | return $value; |
140 | } |
141 | |
142 | protected static function isItemEmpty($item) |
143 | { |
144 | return ( |
145 | null === $item |
146 | || (is_array($item) && count($item) == 0) |
147 | ); |
148 | } |
149 | |
150 | /* |
151 | * Uses a path like '/changePassword/0' to fetch property settings |
152 | * |
153 | public function toProperty() |
154 | { |
155 | return new \BO\Zmsentities\Helper\Property($this); |
156 | } |
157 | |
158 | |
159 | public function getPropertyByPath($path) |
160 | { |
161 | $pointerList = explode('/', trim($path, '/ ')); |
162 | $property = $this->toProperty(); |
163 | $property = $pointerList[0] == 'properties' ? $property : $property->properties; |
164 | foreach ($pointerList as $pointer) { |
165 | if ($property->type->get() == 'array') { |
166 | $property = $property['items']; |
167 | } elseif ($property->type->get() == 'object' && $pointer !== 'properties') { |
168 | $property = $property->properties[$pointer]; |
169 | } elseif (is_numeric($pointer)) { |
170 | // ignore array items |
171 | } else { |
172 | $property = $property[$pointer]; |
173 | } |
174 | } |
175 | return $property->get([]); |
176 | } |
177 | */ |
178 | |
179 | public function withoutRefs() |
180 | { |
181 | return $this->getWithoutRefs(clone $this); |
182 | } |
183 | |
184 | protected function getWithoutRefs($data) |
185 | { |
186 | foreach ($data as $key => $value) { |
187 | if (is_array($value)) { |
188 | $data[$key] = $this->getWithoutRefs($value); |
189 | } |
190 | if ($key === '$ref') { |
191 | unset($data[$key]); |
192 | } |
193 | } |
194 | return $data; |
195 | } |
196 | } |