Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
93.50% covered (success)
93.50%
187 / 200
66.67% covered (warning)
66.67%
10 / 15
CRAP
0.00% covered (danger)
0.00%
0 / 1
Department
93.50% covered (success)
93.50%
187 / 200
66.67% covered (warning)
66.67%
10 / 15
67.20
0.00% covered (danger)
0.00%
0 / 1
 readEntity
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
9
 readResolvedReferences
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
2
 readList
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
4
 readEntitiesByIds
92.86% covered (success)
92.86%
13 / 14
0.00% covered (danger)
0.00%
0 / 1
5.01
 readByScopeId
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 readByOrganisationId
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
4
 deleteEntity
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
7
 writeEntity
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
1 / 1
4
 updateEntity
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
1 / 1
4
 writeDepartmentDayoffs
94.12% covered (success)
94.12%
16 / 17
0.00% covered (danger)
0.00%
0 / 1
5.01
 writeDepartmentLinks
90.91% covered (success)
90.91%
10 / 11
0.00% covered (danger)
0.00%
0 / 1
5.02
 writeDepartmentMail
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 updateDepartmentMail
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 readQueueList
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
12
 removeCache
94.44% covered (success)
94.44%
17 / 18
0.00% covered (danger)
0.00%
0 / 1
9.01
1<?php
2
3namespace BO\Zmsdb;
4
5use BO\Zmsentities\Department as Entity;
6use BO\Zmsentities\Collection\DepartmentList as Collection;
7
8/**
9 * @SuppressWarnings(Coupling)
10 * @SuppressWarnings(Complexity)
11 *
12 */
13class Department extends Base
14{
15    public static $departmentCache = array();
16
17    public function readEntity($departmentId, $resolveReferences = 0, $disableCache = false)
18    {
19        $cacheKey = "department-$departmentId-$resolveReferences";
20
21        if (!$disableCache && \App::$cache && \App::$cache->has($cacheKey)) {
22            $department = \App::$cache->get($cacheKey);
23        }
24
25        if (empty($department)) {
26            $query = new Query\Department(Query\Base::SELECT);
27            $query->addEntityMapping()
28                ->addResolvedReferences($resolveReferences)
29                ->addConditionDepartmentId($departmentId);
30            $department = $this->fetchOne($query, new Entity());
31
32            if (\App::$cache) {
33                \App::$cache->set($cacheKey, $department);
34                if (\App::$log) {
35                    \App::$log->info('Department cache set', ['cache_key' => $cacheKey]);
36                }
37            }
38        }
39
40        if (isset($department['id']) && $department['id']) {
41            $department = $this->readResolvedReferences($department, $resolveReferences, $disableCache);
42            return $department->withOutClusterDuplicates();
43        }
44
45        return null;
46    }
47
48    public function readResolvedReferences(
49        \BO\Zmsentities\Schema\Entity $entity,
50        $resolveReferences,
51        $disableCache = false
52    ) {
53        $entity['links'] = (new Link())->readByDepartmentId($entity->id, $disableCache);
54        $entity['scopes'] = (new Scope())
55            ->readByDepartmentId($entity->id, $resolveReferences - 1, $disableCache)
56            ->sortByContactName();
57        if (0 < $resolveReferences) {
58            $entity['clusters'] = (new Cluster())->readByDepartmentId(
59                $entity->id,
60                $resolveReferences - 1,
61                $disableCache
62            );
63            $entity['dayoff'] = (new DayOff())->readOnlyByDepartmentId($entity->id, $disableCache);
64        }
65        return $entity;
66    }
67
68    public function readList($resolveReferences = 0)
69    {
70        $departmentList = new Collection();
71        $query = new Query\Department(Query\Base::SELECT);
72        $query->addEntityMapping();
73        $query->addResolvedReferences($resolveReferences);
74        $result = $this->fetchList($query, new Entity());
75        if (count($result)) {
76            foreach ($result as $department) {
77                $department = $this->readResolvedReferences($department, $resolveReferences);
78                if ($department instanceof Entity) {
79                    $departmentList->addEntity($department->withOutClusterDuplicates());
80                }
81            }
82        }
83        return $departmentList;
84    }
85
86    public function readEntitiesByIds(array $departmentIds, $resolveReferences = 0)
87    {
88        if (empty($departmentIds)) {
89            return [];
90        }
91
92        $query = new Query\Department(Query\Base::SELECT);
93        $query->addEntityMapping()
94            ->addResolvedReferences($resolveReferences)
95            ->addConditionDepartmentIds($departmentIds);
96
97        $departments = [];
98        $result = $this->fetchList($query, new Entity());
99
100        foreach ($result as $department) {
101            if ($department instanceof Entity) {
102                $department = $this->readResolvedReferences($department, $resolveReferences);
103                if ($department instanceof Entity) {
104                    $departments[$department->id] = $department->withOutClusterDuplicates();
105                }
106            }
107        }
108
109        return $departments;
110    }
111
112    public function readByScopeId($scopeId, $resolveReferences = 0)
113    {
114        $query = new Query\Department(Query\Base::SELECT);
115        $query->addEntityMapping()
116            ->addResolvedReferences($resolveReferences)
117            ->addConditionScopeId($scopeId);
118        $department = $this->fetchOne($query, new Entity());
119        $department = $this->readResolvedReferences($department, $resolveReferences);
120        return (isset($department['id']) && $department['id']) ? $department->withOutClusterDuplicates() : null;
121    }
122
123    public function readByOrganisationId($organisationId, $resolveReferences = 0)
124    {
125        $departmentList = new Collection();
126        $query = new Query\Department(Query\Base::SELECT);
127        $query
128            ->addEntityMapping()
129            ->addResolvedReferences($resolveReferences)
130            ->addConditionOrganisationId($organisationId);
131        $result = $this->fetchList($query, new Entity());
132        if (count($result)) {
133            foreach ($result as $department) {
134                if ($department instanceof Entity) {
135                    $department = $this->readResolvedReferences($department, $resolveReferences);
136                    $departmentList->addEntity($department->withOutClusterDuplicates());
137                }
138            }
139        }
140        return $departmentList;
141    }
142
143    public function deleteEntity($departmentId)
144    {
145        $entity = $this->readEntity($departmentId, 1);
146        if ($entity) {
147            if (
148                0 < $entity->toProperty()->scopes->get()->count()
149                || 0 < $entity->toProperty()->clusters->get()->count()
150            ) {
151                throw new Exception\Department\ScopeListNotEmpty();
152            }
153
154            self::$departmentCache = [];
155            $query = new Query\Department(Query\Base::DELETE);
156            $query->addConditionDepartmentId($departmentId);
157            $entityDelete = $this->deleteItem($query);
158            $emailDelete = $this->perform(Query\Department::QUERY_MAIL_DELETE, array(
159                $departmentId
160            ));
161        }
162
163        $this->removeCache($entity);
164
165        return ($entity && $entityDelete && $emailDelete) ? $entity : null;
166    }
167
168    public function writeEntity(\BO\Zmsentities\Department $entity, $parentId)
169    {
170        self::$departmentCache = [];
171        $query = new Query\Department(Query\Base::INSERT);
172        $values = $query->reverseEntityMapping($entity, $parentId);
173        // get owner by organisation
174        $owner = (new Owner())->readByOrganisationId($parentId);
175        $values['KundenID'] = $owner->id;
176        $query->addValues($values);
177        $this->writeItem($query);
178        $lastInsertId = $this->getWriter()
179            ->lastInsertId();
180        if ($entity->toProperty()->links->isAvailable()) {
181            $this->writeDepartmentLinks($lastInsertId, $entity->links);
182        }
183        if ($entity->toProperty()->dayoff->isAvailable()) {
184            $this->writeDepartmentDayoffs($lastInsertId, $entity->dayoff);
185        }
186        if ($entity->toProperty()->email->isAvailable()) {
187            $this->writeDepartmentMail(
188                $lastInsertId,
189                $entity->email,
190                $entity->sendEmailReminderEnabled,
191                $entity->sendEmailReminderMinutesBefore
192            );
193        }
194
195        $this->removeCache($entity);
196
197        return $this->readEntity($lastInsertId);
198    }
199
200    public function updateEntity($departmentId, \BO\Zmsentities\Department $entity)
201    {
202        self::$departmentCache = [];
203        $query = new Query\Department(Query\Base::UPDATE);
204        $query->addConditionDepartmentId($departmentId);
205        $values = $query->reverseEntityMapping($entity);
206        $query->addValues($values);
207        $this->writeItem($query);
208        if ($entity->toProperty()->links->isAvailable()) {
209            $this->writeDepartmentLinks($departmentId, $entity->links);
210        }
211        if ($entity->toProperty()->dayoff->isAvailable()) {
212            $this->writeDepartmentDayoffs($departmentId, $entity->dayoff);
213        }
214        if ($entity->toProperty()->email->isAvailable()) {
215            $this->updateDepartmentMail(
216                $departmentId,
217                $entity->email,
218                $entity->sendEmailReminderEnabled,
219                $entity->sendEmailReminderMinutesBefore
220            );
221        }
222        $this->removeCache($entity);
223        return $this->readEntity($departmentId, 0, true);
224    }
225
226    protected function writeDepartmentDayoffs($departmentId, $dayoffList)
227    {
228        if (!$departmentId) {
229            throw new Exception\Department\InvalidId();
230        }
231        $existingDayoffs = (new DayOff())->readOnlyByDepartmentId($departmentId);
232        if ($existingDayoffs->count()) {
233            foreach ($existingDayoffs as $item) {
234                $query = new DayOff();
235                $query->deleteEntity($item->getId());
236            }
237        }
238
239        foreach ($dayoffList as $dayoff) {
240            $query = new Query\DayOff(Query\Base::INSERT);
241            $query->addValues(
242                [
243                    'behoerdenid' => $departmentId,
244                    'Feiertag' => $dayoff['name'],
245                    'Datum' => (new \DateTimeImmutable('@' . $dayoff['date']))->format('Y-m-d')
246                ]
247            );
248            $this->writeItem($query);
249        }
250    }
251
252    protected function writeDepartmentLinks($departmentId, $links)
253    {
254        if (!$departmentId) {
255            throw new Exception\Department\InvalidId();
256        }
257        $existingLinks = (new Link())->readByDepartmentId($departmentId);
258        if ($existingLinks->count()) {
259            foreach ($existingLinks as $item) {
260                $query = new Link();
261                $query->deleteEntity($item->getId());
262            }
263        }
264
265        foreach ($links as $link) {
266            $link = new \BO\Zmsentities\Link($link);
267            $query = new Link();
268            $query->writeEntity($link, $departmentId);
269        }
270    }
271
272    protected function writeDepartmentMail(
273        $departmentId,
274        $email,
275        $sendEmailReminderEnabled,
276        $sendEmailReminderMinutesBefore
277    ) {
278        self::$departmentCache = [];
279        $result = $this->perform(Query\Department::QUERY_MAIL_INSERT, array(
280            $departmentId,
281            $email,
282            $sendEmailReminderEnabled,
283            $sendEmailReminderMinutesBefore
284        ));
285        return $result;
286    }
287
288    protected function updateDepartmentMail(
289        $departmentId,
290        $email,
291        $sendEmailReminderEnabled,
292        $sendEmailReminderMinutesBefore
293    ) {
294        self::$departmentCache = [];
295        $query = Query\Department::QUERY_MAIL_UPDATE;
296        return $this->fetchAffected($query, array(
297            'email' => $email,
298            'departmentId' => $departmentId,
299            'sendEmailReminderEnabled' => $sendEmailReminderEnabled,
300            'sendEmailReminderMinutesBefore' => $sendEmailReminderMinutesBefore
301        ));
302    }
303
304    public function readQueueList(
305        $departmentId,
306        \DateTimeInterface $dateTime,
307        $resolveReferences = 0
308    ) {
309        $queueList = new \BO\Zmsentities\Collection\QueueList();
310        $department = $this->readEntity($departmentId, 2);
311
312        foreach ($department->getScopeList() as $scope) {
313            $scope = (new Scope())->readWithWorkstationCount($scope->id, $dateTime);
314            $scopeQueueList = (new Scope())
315                ->readQueueListWithWaitingTime($scope, $dateTime, $resolveReferences);
316            if (0 < $scopeQueueList->count()) {
317                $queueList->addList($scopeQueueList);
318            }
319        }
320        return $queueList;
321    }
322
323    public function removeCache($department)
324    {
325        if (!\App::$cache || !isset($department->id)) {
326            return;
327        }
328
329        $invalidatedKeys = [];
330
331        // Invalidate department entity cache for all resolveReferences levels (0, 1, 2)
332        for ($resolveReferences = 0; $resolveReferences <= 2; $resolveReferences++) {
333            $key = "department-{$department->id}-{$resolveReferences}";
334            if (\App::$cache->has($key)) {
335                \App::$cache->delete($key);
336                $invalidatedKeys[] = $key;
337            }
338        }
339
340        // Invalidate scopeReadByDepartmentId cache for all resolveReferences levels (0, 1, 2)
341        for ($resolveReferences = 0; $resolveReferences <= 2; $resolveReferences++) {
342            $key = "scopeReadByDepartmentId-{$department->id}-{$resolveReferences}";
343            if (\App::$cache->has($key)) {
344                \App::$cache->delete($key);
345                $invalidatedKeys[] = $key;
346            }
347        }
348
349        if (!empty($invalidatedKeys) && \App::$log) {
350            \App::$log->info('Department cache invalidated', [
351                'department_id' => $department->id,
352                'invalidated_keys' => $invalidatedKeys
353            ]);
354        }
355    }
356}