Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
98.39% covered (success)
98.39%
183 / 186
89.47% covered (warning)
89.47%
17 / 19
CRAP
0.00% covered (danger)
0.00%
0 / 1
Cluster
98.39% covered (success)
98.39%
183 / 186
89.47% covered (warning)
89.47%
17 / 19
63
0.00% covered (danger)
0.00%
0 / 1
 readEntity
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
7
 readResolvedReferences
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 readEntityWithOpenedScopeStatus
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 readList
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
4
 readByScopeId
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
2
 readByDepartmentId
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
5
 readQueueList
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 readOpenedScopeList
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
5
 readEnabledScopeList
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 readScopeWithShortestWaitingTime
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
7
 readWithScopeWorkstationCount
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
4
 writeImageData
93.33% covered (success)
93.33%
14 / 15
0.00% covered (danger)
0.00%
0 / 1
4.00
 readImageData
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
2
 deleteImage
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 deleteEntity
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
2
 writeEntity
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
2
 updateEntity
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
2
 writeAssignedScopes
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
3
 removeCache
75.00% covered (warning)
75.00%
6 / 8
0.00% covered (danger)
0.00%
0 / 1
6.56
1<?php
2
3namespace BO\Zmsdb;
4
5use BO\Zmsdb\Application as App;
6use BO\Zmsentities\Cluster as Entity;
7use BO\Zmsentities\Collection\ClusterList as Collection;
8
9/**
10 *
11 * @SuppressWarnings(Public)
12 * @SuppressWarnings(Coupling)
13 * @SuppressWarnings(Complexity)
14 *
15 */
16class Cluster extends Base
17{
18    /**
19    * read entity
20    *
21    * @param
22    * itemId
23    * resolveReferences
24    *
25    * @return Resource Entity
26    */
27    public function readEntity($itemId, $resolveReferences = 0, $disableCache = false)
28    {
29        $cacheKey = "cluster-$itemId-$resolveReferences";
30
31        $cluster = null;
32        if (!$disableCache && App::$cache && App::$cache->has($cacheKey)) {
33            $cluster = App::$cache->get($cacheKey);
34        }
35
36        if (empty($cluster)) {
37            $query = new Query\Cluster(Query\Base::SELECT);
38            $query
39                ->addEntityMapping()
40                ->addResolvedReferences($resolveReferences)
41                ->addConditionClusterId($itemId);
42            $cluster = $this->fetchOne($query, new Entity());
43            if (! $cluster->hasId()) {
44                return null;
45            }
46        }
47
48        if (App::$cache) {
49            App::$cache->set($cacheKey, $cluster);
50        }
51
52        return $this->readResolvedReferences($cluster, $resolveReferences, $disableCache);
53    }
54
55    public function readResolvedReferences(
56        \BO\Zmsentities\Schema\Entity $entity,
57        $resolveReferences,
58        $disableCache = false
59    ) {
60        $entity['scopes'] = (new Scope())->readByClusterId($entity->id, $resolveReferences, $disableCache);
61
62        return $entity;
63    }
64
65    public function readEntityWithOpenedScopeStatus($itemId, \DateTimeInterface $now, $resolveReferences = 0)
66    {
67        $entity = $this->readEntity($itemId, $resolveReferences);
68        foreach ($entity->scopes as $scope) {
69            $scope->setStatusAvailability('isOpened', (new Scope())->readIsOpened($scope->getId(), $now));
70        }
71        return $entity;
72    }
73
74    /**
75    * read list of clusters
76    *
77    * @param
78    * resolveReferences
79    *
80    * @return Resource Collection
81    */
82    public function readList($resolveReferences = 0)
83    {
84        $clusterList = new Collection();
85        $query = new Query\Cluster(Query\Base::SELECT);
86        $query
87            ->addResolvedReferences($resolveReferences)
88            ->addEntityMapping();
89        $result = $this->fetchList($query, new Entity());
90        if (count($result)) {
91            foreach ($result as $entity) {
92                if ($entity instanceof Entity) {
93                    $entity = $this->readResolvedReferences($entity, $resolveReferences);
94                    $clusterList->addEntity($entity);
95                }
96            }
97        }
98        return $clusterList;
99    }
100
101    public function readByScopeId($scopeId, $resolveReferences = 0)
102    {
103        $query = new Query\Cluster(Query\Base::SELECT);
104        $query
105            ->addEntityMapping()
106            ->addResolvedReferences($resolveReferences)
107            ->addConditionScopeId($scopeId);
108        $entity = $this->fetchOne($query, new Entity());
109        if (! $entity->hasId()) {
110            return null;
111        }
112        $entity = $this->readResolvedReferences($entity, $resolveReferences);
113        return $entity;
114    }
115
116    public function readByDepartmentId($departmentId, $resolveReferences = 0, $disableCache = false)
117    {
118        $clusterList = new Collection();
119        $query = new Query\Cluster(Query\Base::SELECT);
120        $query
121            ->addEntityMapping()
122            ->addResolvedReferences($resolveReferences)
123            ->addConditionDepartmentId($departmentId);
124        $result = $this->fetchList($query, new Entity());
125        if (count($result)) {
126            foreach ($result as $entity) {
127                if ($entity instanceof Entity && !$clusterList->hasEntity($entity->id)) {
128                    $entity = $this->readResolvedReferences($entity, $resolveReferences, $disableCache);
129                    $clusterList->addEntity($entity);
130                }
131            }
132        }
133        return $clusterList;
134    }
135
136    /**
137     * get a queueList by cluster id and dateTime
138     *
139     ** @param
140     *            clusterId
141     *            now
142     *
143     * @return Bool
144     */
145    public function readQueueList(
146        $clusterId,
147        \DateTimeInterface $dateTime,
148        $resolveReferences = 0,
149        $withEntities = []
150    ) {
151        $cluster = $this->readEntity($clusterId, 1);
152
153        return (new Scope())
154            ->readScopesQueueListWithWaitingTime($cluster->scopes, $dateTime, $resolveReferences, $withEntities)
155            ->withSortedWaitingTime();
156    }
157
158    /**
159     * get a scopeList with opened scopes
160     *
161     ** @param
162     *            clusterId
163     *            now
164     *
165     * @return Bool
166     */
167    public function readOpenedScopeList($clusterId, \DateTimeInterface $dateTime)
168    {
169        $scopeList = new \BO\Zmsentities\Collection\ScopeList();
170        $cluster = $this->readEntity($clusterId, 1);
171        if ($cluster && $cluster->toProperty()->scopes->get()) {
172            foreach ($cluster->scopes as $scope) {
173                $availabilityList = (new Availability())->readOpeningHoursListByDate($scope['id'], $dateTime, 2);
174                if ($availabilityList->isOpened($dateTime)) {
175                    $scope->setStatusAvailability('isOpened', true);
176                    $scopeList->addEntity($scope);
177                }
178            }
179        }
180        return $scopeList;
181    }
182
183    public function readEnabledScopeList($clusterId, \DateTimeInterface $dateTime)
184    {
185        $scopeList = new \BO\Zmsentities\Collection\ScopeList();
186        foreach ($this->readOpenedScopeList($clusterId, $dateTime) as $scope) {
187            if ((new Scope())->readIsGivenNumberInContingent($scope['id'])) {
188                $scopeList->addEntity($scope);
189            }
190        }
191        return $scopeList;
192    }
193
194    /**
195     * get the scope with shortest estimated waitingtime
196     *
197     ** @param
198     *            clusterId
199     *            now
200     *
201     * @return Bool
202     */
203    public function readScopeWithShortestWaitingTime($clusterId, \DateTimeInterface $dateTime)
204    {
205        $scopeList = $this->readOpenedScopeList($clusterId, $dateTime)->getArrayCopy();
206        $nextScope = array_shift($scopeList);
207        $preferedScope = null;
208        $preferedWaitingTime = 0;
209        while ($nextScope) {
210            $scope = (new Scope())->readWithWorkstationCount($nextScope->id, $dateTime);
211            $queueList = (new Scope())->readQueueListWithWaitingTime($scope, $dateTime);
212            $data = $scope->getWaitingTimeFromQueueList($queueList, $dateTime);
213            if (
214                $scope->getCalculatedWorkstationCount() > 0 &&
215                $data &&
216                ($data['waitingTimeEstimate'] <= $preferedWaitingTime || 0 == $preferedWaitingTime)
217            ) {
218                $preferedWaitingTime = $data['waitingTimeEstimate'];
219                $preferedScope = $scope;
220            }
221            $nextScope = array_shift($scopeList);
222        }
223        if (! $preferedScope) {
224            throw new Exception\Cluster\ScopesWithoutWorkstationCount();
225        }
226        return $preferedScope;
227    }
228
229    /**
230     * get cluster with scopes workstation count
231     *
232     * * @param
233     * scopeId
234     * now
235     *
236     * @return number
237     */
238    public function readWithScopeWorkstationCount($clusterId, $dateTime, $resolveReferences = 0)
239    {
240        $scopeQuery = new Scope();
241        $scopeList = new \BO\Zmsentities\Collection\ScopeList();
242        $cluster = $this->readEntity($clusterId, $resolveReferences);
243        if ($cluster->toProperty()->scopes->get()) {
244            foreach ($cluster->scopes as $scope) {
245                $entity = $scopeQuery->readWithWorkstationCount($scope->id, $dateTime, $resolveReferences = 0);
246                if ($entity) {
247                    $scopeList->addEntity($entity);
248                }
249            }
250        }
251        $cluster->scopes = $scopeList;
252        return $cluster;
253    }
254
255    /**
256     * update image data for call display image
257     *
258     * @param
259     *         clusterId
260     *         Mimepart entity
261     *
262     * @return Mimepart entity
263     */
264    public function writeImageData($clusterId, \BO\Zmsentities\Mimepart $entity)
265    {
266        if ($entity->mime && $entity->content) {
267            $this->deleteImage($clusterId);
268            $extension = $entity->getExtension();
269            if ($extension == 'jpeg') {
270                $extension = 'jpg'; //compatibility ZMS1
271            }
272            $imageName = 'c_' . $clusterId . '_bild.' . $extension;
273            $this->perform(
274                (new Query\Scope(Query\Base::REPLACE))->getQueryWriteImageData(),
275                array(
276                'imagename' => $imageName,
277                'imagedata' => $entity->content
278                )
279            );
280        }
281        $entity->id = $clusterId;
282        return $entity;
283    }
284
285    /**
286     * read image data
287     *
288     * @param
289     *         clusterId
290     *
291     * @return Mimepart entity
292     */
293    public function readImageData($clusterId)
294    {
295        $imageName = 'c_' . $clusterId . '_bild';
296        $imageData = new \BO\Zmsentities\Mimepart();
297        $fileData = $this->getReader()->fetchAll(
298            (new Query\Scope(Query\Base::SELECT))->getQueryReadImageData(),
299            ['imagename' => "$imageName%"]
300        );
301        if ($fileData) {
302            $imageData->content = $fileData[0]['imagecontent'];
303            $imageData->mime = pathinfo($fileData[0]['imagename'])['extension'];
304        }
305        return $imageData;
306    }
307
308    /**
309     * delete image data for calldisplay image
310     *
311     * @param
312     *         clusterId
313     *
314     * @return Status
315     */
316    public function deleteImage($clusterId)
317    {
318        $imageName = 'c_' . $clusterId . '_bild';
319        $result = $this->perform(
320            (new Query\Scope(Query\Base::DELETE))->getQueryDeleteImage(),
321            array(
322            'imagename' => "$imageName%"
323            )
324        );
325        return $result;
326    }
327
328    /**
329    * remove an cluster
330    *
331    * @param
332    * itemId
333    *
334    * @return Resource Status
335    */
336    public function deleteEntity($itemId)
337    {
338        $result = false;
339        $cluster = $this->readEntity($itemId);
340        $query =  new Query\Cluster(Query\Base::DELETE);
341        $query->addConditionClusterId($itemId);
342        if ($this->deleteItem($query)) {
343            $result = $this->perform(
344                (new Query\Cluster(Query\Base::DELETE))->getQueryDeleteAssignedScopes(),
345                ['clusterId' => $itemId]
346            );
347        }
348
349        $this->removeCache($cluster);
350
351        return $result;
352    }
353
354    /**
355     * write an cluster
356     *
357     * @param
358     * entity
359     *
360     * @return Entity
361     */
362    public function writeEntity(\BO\Zmsentities\Cluster $entity)
363    {
364        $query = new Query\Cluster(Query\Base::INSERT);
365        $values = $query->reverseEntityMapping($entity);
366        $query->addValues($values);
367        $this->writeItem($query);
368        $lastInsertId = $this->getWriter()->lastInsertId();
369        if ($entity->toProperty()->scopes->isAvailable()) {
370            $this->writeAssignedScopes($lastInsertId, $entity->scopes);
371        }
372
373        $this->removeCache($entity);
374
375        return $this->readEntity($lastInsertId, 1, true);
376    }
377
378    /**
379     * update an cluster
380     *
381     * @param
382     * clusterId, entity
383     *
384     * @return Entity
385     */
386    public function updateEntity($clusterId, \BO\Zmsentities\Cluster $entity)
387    {
388        $query = new Query\Cluster(Query\Base::UPDATE);
389        $query->addConditionClusterId($clusterId);
390        $values = $query->reverseEntityMapping($entity);
391        $query->addValues($values);
392        $this->writeItem($query);
393        if ($entity->toProperty()->scopes->isAvailable()) {
394            $this->writeAssignedScopes($clusterId, $entity->scopes);
395        }
396
397        $this->removeCache($entity);
398
399        return $this->readEntity($clusterId, 1, true);
400    }
401
402    /**
403     * create links preferences of a department
404     *
405     * @param
406     *            departmentId,
407     *            links
408     *
409     * @return Boolean
410     */
411    protected function writeAssignedScopes($clusterId, $scopeList)
412    {
413        $cluster = $this->readEntity($clusterId);
414        $this->perform(
415            (new Query\Cluster(Query\Base::DELETE))->getQueryDeleteAssignedScopes(),
416            ['clusterId' => $clusterId]
417        );
418        foreach ($scopeList as $scope) {
419            if (0 < $scope['id']) {
420                $this->perform(
421                    (new Query\Cluster(Query\Base::REPLACE))->getQueryWriteAssignedScopes(),
422                    array(
423                    'clusterId' => $clusterId,
424                    'scopeId' => $scope['id']
425                    )
426                );
427            }
428        }
429
430        $this->removeCache($cluster);
431    }
432
433    public function removeCache($cluster)
434    {
435        if (!App::$cache || !isset($cluster->id)) {
436            return;
437        }
438
439        if (App::$cache->has("cluster-$cluster->id-0")) {
440            App::$cache->delete("cluster-$cluster->id-0");
441        }
442
443        if (App::$cache->has("cluster-$cluster->id-1")) {
444            App::$cache->delete("cluster-$cluster->id-1");
445        }
446
447        if (App::$cache->has("cluster-$cluster->id-2")) {
448            App::$cache->delete("cluster-$cluster->id-2");
449        }
450    }
451}