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        //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}