Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
80.51% covered (warning)
80.51%
95 / 118
81.48% covered (warning)
81.48%
22 / 27
CRAP
0.00% covered (danger)
0.00%
0 / 1
Base
80.51% covered (warning)
80.51%
95 / 118
81.48% covered (warning)
81.48%
22 / 27
81.06
0.00% covered (danger)
0.00%
0 / 1
 getFirst
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getLast
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 sortByName
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 sortByContactName
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 sortByCustomKey
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 sortByCustomStringKey
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 __clone
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 hasEntity
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
4
 getEntity
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
4
 addEntity
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 offsetSet
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 addData
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
4
 addList
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 getIds
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getIdsCsv
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCsvForProperty
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 getCsvForPropertyList
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
6
 withValueFor
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 withLessData
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 setJsonCompressLevel
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 getAsArray
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 jsonSerialize
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 __toString
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getResolveLevel
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setResolveLevel
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 withResolveLevel
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 chunk
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3/**
4 * @package Zmsdldb
5 * @copyright BerlinOnline Stadtportal GmbH & Co. KG
6 **/
7
8namespace BO\Zmsentities\Collection;
9
10use BO\Zmsentities\Helper\Sorter;
11use BO\Zmsentities\Schema\Entity;
12
13/**
14 * @SuppressWarnings(NumberOfChildren)
15 * @SuppressWarnings(Public)
16 * @SuppressWarnings(Complexity)
17 *
18 */
19class Base extends \ArrayObject implements \JsonSerializable
20{
21    public const ENTITY_CLASS = '';
22
23    /**
24     * @var Int $resolveLevel indicator on data integrity
25     */
26    protected $resolveLevel = null;
27
28    public function getFirst()
29    {
30        $item = $this->getIterator()->current();
31        return $item;
32    }
33
34    public function getLast()
35    {
36        $copy = $this->getArrayCopy();
37        $item = end($copy);
38        return $item;
39    }
40
41    public function sortByName()
42    {
43        $this->uasort(function ($a, $b) {
44            return strcmp(
45                Sorter::toSortableString(ucfirst($a->name ?? '')),
46                Sorter::toSortableString(ucfirst($b->name ?? ''))
47            );
48        });
49        return $this;
50    }
51
52    public function sortByContactName()
53    {
54        $this->uasort(function ($a, $b) {
55            return strcmp(
56                Sorter::toSortableString(ucfirst($a->contact['name'] ?? '')),
57                Sorter::toSortableString(ucfirst($b->contact['name'] ?? ''))
58            );
59        });
60        return $this;
61    }
62
63    public function sortByCustomKey($key)
64    {
65        $this->uasort(function ($a, $b) use ($key) {
66            return ($a[$key] - $b[$key]);
67        });
68        return $this;
69    }
70
71    public function sortByCustomStringKey($key)
72    {
73        $this->uasort(function ($a, $b) use ($key) {
74            return strcmp(
75                Sorter::toSortableString(ucfirst($a[$key] ?? '')),
76                Sorter::toSortableString(ucfirst($b[$key] ?? ''))
77            );
78        });
79        return $this;
80    }
81
82    public function __clone()
83    {
84        foreach ($this as $key => $property) {
85            $this[$key] = clone $property;
86        }
87    }
88
89    public function hasEntity($primary)
90    {
91        foreach ($this as $entity) {
92            if (isset($entity->{$entity::PRIMARY}) && $primary == $entity->{$entity::PRIMARY}) {
93                return true;
94            }
95        }
96        return false;
97    }
98
99    public function getEntity($primary)
100    {
101        foreach ($this as $entity) {
102            if (isset($entity->{$entity::PRIMARY}) && $primary == $entity->{$entity::PRIMARY}) {
103                return $entity;
104            }
105        }
106        return null;
107    }
108
109    public function addEntity(\BO\Zmsentities\Schema\Entity $entity)
110    {
111        $this->offsetSet(null, $entity);
112        return $this;
113    }
114
115    #[\Override]
116    public function offsetSet(mixed $index, mixed $value): void
117    {
118        $className = $this::ENTITY_CLASS;
119        if (is_a($value, $className)) {
120            parent::offsetSet($index, $value);
121        } elseif (is_array($value)) {
122            parent::offsetSet($index, new $className($value));
123        } else {
124            throw new \Exception('Invalid entity ' . get_class($value) . ' for collection ' . __CLASS__);
125        }
126    }
127
128    public function addData($mergeData)
129    {
130        foreach ($mergeData as $item) {
131            if ($item instanceof Entity) {
132                if (null === $item->getResolveLevel()) {
133                    $item->setResolveLevel($this->getResolveLevel());
134                }
135                $this->addEntity($item);
136            } else {
137                $className = $this::ENTITY_CLASS;
138                $entity = new $className($item);
139                $entity->setResolveLevel($this->getResolveLevel());
140                $this->addEntity($entity);
141            }
142        }
143        return $this;
144    }
145
146    public function addList(Base $list)
147    {
148        foreach ($list as $item) {
149            $this->addEntity($item);
150        }
151        return $this;
152    }
153
154    public function getIds()
155    {
156        $list = [];
157        foreach ($this as $entity) {
158            $list[] = $entity->id;
159        }
160        return $list;
161    }
162
163    public function getIdsCsv()
164    {
165        return implode(',', $this->getIds());
166    }
167
168    public function getCsvForProperty($propertyName, $csvSeperator = ',')
169    {
170        $list = [];
171        foreach ($this as $entry) {
172            if ($entry->hasProperty($propertyName)) {
173                $list[] = $entry->getProperty($propertyName);
174            }
175        }
176        return implode($csvSeperator, $list);
177    }
178
179    public function getCsvForPropertyList(array $propertyList, $propertySeperator = '', $csvSeperator = ',')
180    {
181        $list = [];
182        foreach ($this as $entry) {
183            $propertyConcat = '';
184            foreach ($propertyList as $propertyName) {
185                if ($entry->hasProperty($propertyName)) {
186                    if ($propertyConcat) {
187                        $propertyConcat .= $propertySeperator;
188                    }
189                    $propertyConcat .= $entry->getProperty($propertyName);
190                }
191            }
192            if ($propertyConcat) {
193                $list[] = $propertyConcat;
194            }
195        }
196        return implode($csvSeperator, $list);
197    }
198
199    /**
200     * Change a parameter on all entries
201     */
202    public function withValueFor($param, $newValue)
203    {
204        $list = new static();
205        foreach ($this as $entry) {
206            $list[] = $entry->withProperty($param, $newValue);
207        }
208        return $list;
209    }
210
211    /**
212     * Reduce items data of dereferenced entities to a required minimum
213     *
214     */
215    public function withLessData(array $keepArray = [])
216    {
217        $list = new static();
218        foreach ($this as $key => $item) {
219            $list[$key] = $item->withLessData($keepArray);
220        }
221        return $list;
222    }
223
224    public function setJsonCompressLevel($jsonCompressLevel)
225    {
226        foreach ($this as $item) {
227            $item->setJsonCompressLevel($jsonCompressLevel);
228        }
229    }
230
231    public function getAsArray()
232    {
233        $array = [];
234        foreach ($this as $item) {
235            $array[] = $item;
236        }
237
238        return $array;
239    }
240
241    #[\Override]
242    public function jsonSerialize(): mixed
243    {
244        return $this->getArrayCopy();
245    }
246
247    public function __toString()
248    {
249        $list = [];
250        foreach ($this as $item) {
251            $list[] = $item->__toString();
252        }
253        return "[" . implode(',', $list) . "]";
254    }
255
256    /**
257     * @return Int
258     */
259    public function getResolveLevel()
260    {
261        return $this->resolveLevel;
262    }
263
264    /**
265     * @param Int $resolveLevel
266     * @return self
267     */
268    public function setResolveLevel($resolveLevel)
269    {
270        $this->resolveLevel = $resolveLevel;
271        return $this;
272    }
273
274    /**
275     * @param Int $resolveLevel
276     * @return self
277     */
278    public function withResolveLevel($resolveLevel)
279    {
280        $collection = new static();
281        foreach ($this as $entity) {
282            $reduced = $entity->withResolveLevel($resolveLevel);
283            if (null !== $reduced) {
284                $collection[] = $reduced;
285            }
286        }
287        return $collection;
288    }
289
290    public function chunk($length)
291    {
292        $chunks = [new static()];
293        $id = 0;
294        foreach ($this as $entry) {
295            if (! isset($chunks[floor($id / $length)])) {
296                $chunks[floor($id / $length)] = new static();
297            }
298
299            $chunks[floor($id / $length)][] = $entry;
300
301            $id++;
302        }
303
304        return $chunks;
305    }
306}