Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.28% covered (success)
95.28%
121 / 127
77.78% covered (warning)
77.78%
7 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
Calendar
95.28% covered (success)
95.28%
121 / 127
77.78% covered (warning)
77.78%
7 / 9
38
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
4
 getDateTime
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 readMonthListByScopeList
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
3
 readAvailableSlotsFromDayAndScopeList
86.96% covered (warning)
86.96%
20 / 23
0.00% covered (danger)
0.00%
0 / 1
5.06
 readWeekDayListWithProcessList
92.11% covered (success)
92.11%
35 / 38
0.00% covered (danger)
0.00%
0 / 1
8.03
 getDateTimeFromWeekAndYear
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 toProcessListByHour
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
5
 toDayListByHour
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
1 / 1
8
 splitByDate
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3/**
4 *
5 * @package Zmsadmin
6 * @copyright BerlinOnline Stadtportal GmbH & Co. KG
7 *
8 */
9
10namespace BO\Zmsadmin\Helper;
11
12use BO\Zmsentities\Calendar as Entity;
13use BO\Zmsentities\Cluster;
14use BO\Zmsentities\Day;
15use BO\Zmsentities\Collection\DayList;
16use BO\Zmsentities\Collection\ScopeList;
17use BO\Zmsentities\Collection\ProcessList;
18use BO\Zmsentities\Helper\DateTime;
19use BO\Zmsentities\Workstation;
20use DateTimeImmutable;
21
22class Calendar
23{
24    protected $calendar;
25
26    protected $dateTime;
27
28    public function __construct($selectedDate = null, $selectedWeek = null, ?int $selectedYear = null)
29    {
30        if ($selectedWeek && $selectedYear) {
31            $this->dateTime = $this->getDateTimeFromWeekAndYear($selectedWeek, $selectedYear);
32        } else {
33            $this->dateTime = ($selectedDate) ? new DateTime($selectedDate) : \App::$now;
34        }
35
36        $this->calendar = new Entity();
37        $this->calendar->firstDay = new Day();
38        $this->calendar->lastDay = new Day();
39    }
40
41    public function getDateTime()
42    {
43        return $this->dateTime;
44    }
45
46    public function readMonthListByScopeList(ScopeList $scopeList, string $slotType, int $slotsRequired)
47    {
48        // TODO Berechne die Tage im Kalendar
49        $this->calendar->scopes = $scopeList;
50        $this->calendar->firstDay->setDateTime($this->dateTime->modify('first day of this month'));
51        $this->calendar->lastDay->setDateTime($this->dateTime->modify('last day of next month'));
52        try {
53            $calendar = \App::$http->readPostResult(
54                '/calendar/',
55                $this->calendar,
56                [
57                    'fillWithEmptyDays' => 1,
58                    'slotType' => $slotType,
59                    'slotsRequired' => $slotsRequired
60                ]
61            )->getEntity();
62        } catch (\BO\Zmsclient\Exception $exception) {
63            if ($exception->template != 'BO\Zmsbackend\Calendar\Exception\AppointmentsMissed') {
64                throw $exception;
65            }
66        }
67        return $calendar->getMonthList();
68    }
69
70    public function readAvailableSlotsFromDayAndScopeList(
71        ScopeList $scopeList,
72        string $slotType = 'intern',
73        int $slotsRequired = 0,
74        bool $forWeek = false
75    ): ?ProcessList {
76        $this->calendar->scopes = $scopeList;
77
78        $this->calendar->firstDay->setDateTime($this->dateTime);
79        $this->calendar->lastDay->setDateTime($this->dateTime);
80
81        if ($forWeek) {
82            $startDate = clone $this->dateTime->modify('Monday this week');
83            $endDate = clone $this->dateTime->modify('Sunday this week');
84            $this->calendar->firstDay->setDateTime($startDate);
85            $this->calendar->lastDay->setDateTime($endDate);
86        }
87
88        $slots = null;
89        try {
90            $collection = \App::$http->readPostResult(
91                '/process/status/free/',
92                $this->calendar,
93                [
94                    'slotType' => $slotType,
95                    'slotsRequired' => $slotsRequired,
96                    'gql' => GraphDefaults::getFreeProcessList()
97                ]
98            )->getCollection();
99            $slots = $collection instanceof ProcessList ? $collection : null;
100        } catch (\BO\Zmsclient\Exception $exception) {
101            if ($exception->template != 'BO\Zmsbackend\Process\Exception\FreeProcessListEmpty') {
102                throw $exception;
103            }
104        }
105        return $slots;
106    }
107
108    public function readWeekDayListWithProcessList(
109        ?Cluster $cluster,
110        Workstation $workstation
111    ) {
112        $showAllInCluster = $cluster && 1 == $workstation->queue['clusterEnabled'];
113        $scopeList = $workstation->getScopeList($cluster);
114        $scope = $scopeList->getFirst();
115
116        $dayList = new DayList();
117
118        if ($showAllInCluster) {
119            $bookedProcessList = \App::$http
120                ->readGetResult('/cluster/' . $cluster->id . '/process/' . $this->dateTime->format('Y-m-d') . '/', ['showWeek' => 1])
121                ->getCollection();
122        } else {
123            $bookedProcessList = \App::$http
124                ->readGetResult('/scope/' . $scope->id . '/process/' . $this->dateTime->format('Y-m-d') . '/', ['showWeek' => 1])
125                ->getCollection();
126        }
127
128        /** @var ProcessList $bookedProcessList */
129        $processListByDate = $this->splitByDate($bookedProcessList);
130
131        $startDate = clone $this->dateTime->modify('Monday this week');
132        $endDate = clone $this->dateTime->modify('Sunday this week');
133        $currentDate = $startDate;
134
135        $freeProcessList = $this->readAvailableSlotsFromDayAndScopeList(
136            $scopeList,
137            'intern',
138            0,
139            true
140        );
141        $freeProcessListByDate = $freeProcessList instanceof ProcessList
142            ? $this->splitByDate($freeProcessList)
143            : [];
144
145        while ($currentDate <= $endDate) {
146            $day = (new Day())->setDateTime($currentDate);
147            $day->status = Day::DETAIL;
148            $processList = new ProcessList();
149
150            $this->dateTime = $currentDate;
151            if ($currentDate->format('Y-m-d') >= \App::$now->format('Y-m-d')) {
152                if (isset($freeProcessListByDate[$currentDate->format('Y-m-d')])) {
153                    $processList->addList($freeProcessListByDate[$currentDate->format('Y-m-d')]);
154                }
155
156                if (isset($processListByDate[$currentDate->format('Y-m-d')])) {
157                    $processList->addList($processListByDate[$currentDate->format('Y-m-d')]);
158                }
159            }
160
161            $day['processList'] = $this->toProcessListByHour($processList);
162            $dayList->addEntity($day);
163            $currentDate = $currentDate->modify('+1 day');
164        }
165
166        return $this->toDayListByHour($dayList);
167    }
168
169    protected function getDateTimeFromWeekAndYear($week, int $year): DateTimeImmutable
170    {
171        $dateTime = new DateTimeImmutable();
172        return $dateTime->setISODate($year, $week);
173    }
174
175    /**
176     * @return ProcessList[][]
177     *
178     */
179    public function toProcessListByHour(ProcessList $processList): array
180    {
181        $list = array();
182        $oldList = $processList;
183        $oldList->sortByArrivalTime();
184        foreach ($oldList as $process) {
185            if (in_array($process->status, [ 'confirmed', 'free'])) {
186                $appointment = $process->getFirstAppointment();
187                $hour = (int)$appointment->toDateTime()->format('H');
188                if (!isset($list[$hour])) {
189                    $list[$hour] = array();
190                }
191                if (!isset($list[$hour][intval($appointment['date'])])) {
192                    $list[$hour][intval($appointment['date'])] = new ProcessList();
193                }
194                $list[$hour][intval($appointment['date'])]->addEntity($process);
195
196                unset($process);
197                ksort($list[$hour]);
198            }
199        }
200
201        ksort($list);
202        return $list;
203    }
204
205    /**
206     * @return ((ProcessList|mixed)[]|Day)[][]
207     *
208     */
209    public function toDayListByHour(DayList $dayList): array
210    {
211        $list = array();
212        $hours = array();
213        $dayKeys = array();
214        foreach ($dayList as $day) {
215            $list['days'][] = $day;
216            $dayKey = $day->year . '-' . $day->month . '-' . $day->day;
217            $dayKeys[$dayKey] = $dayKey;
218            foreach ($day['processList'] as $hour => $processList) {
219                $list['hours'][$hour][$dayKey] = $processList;
220                $hours[$hour] = $hour;
221            }
222        }
223        foreach ($hours as $hour) {
224            foreach ($dayKeys as $dayKey) {
225                if (!isset($list['hours'][$hour][$dayKey])) {
226                    $list['hours'][$hour][$dayKey] = new ProcessList();
227                }
228            }
229            ksort($list['hours'][$hour]);
230        }
231
232        if (isset($list['hours']) && is_array($list['hours'])) {
233            ksort($list['hours']);
234        }
235
236        return $list;
237    }
238
239    /**
240     * @return ProcessList[]
241     *
242     */
243    private function splitByDate(ProcessList $processList): array
244    {
245        $list = [];
246
247        foreach ($processList as $process) {
248            $dayKey = $process->getFirstAppointment()->toDateTime()->format("Y-m-d");
249            if (! isset($list[$dayKey])) {
250                $list[$dayKey] = new ProcessList();
251                ;
252            }
253
254            $list[$dayKey]->addEntity($process);
255        }
256
257        return $list;
258    }
259}