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