Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.12% covered (success)
95.12%
117 / 123
77.78% covered (warning)
77.78%
7 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
Calendar
95.12% covered (success)
95.12%
117 / 123
77.78% covered (warning)
77.78%
7 / 9
37
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
85.71% covered (warning)
85.71%
18 / 21
0.00% covered (danger)
0.00%
0 / 1
4.05
 readWeekDayListWithProcessList
91.67% covered (success)
91.67%
33 / 36
0.00% covered (danger)
0.00%
0 / 1
8.04
 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, $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, $slotType, $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\Zmsapi\Exception\Calendar\AppointmentsMissed') {
64                throw $exception;
65            }
66        }
67        return $calendar->getMonthList();
68    }
69
70    public function readAvailableSlotsFromDayAndScopeList(
71        ScopeList $scopeList,
72        $slotType = 'intern',
73        $slotsRequired = 0,
74        $forWeek = false
75    ) {
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        try {
89            $slots = \App::$http->readPostResult(
90                '/process/status/free/',
91                $this->calendar,
92                [
93                    'slotType' => $slotType,
94                    'slotsRequired' => $slotsRequired,
95                    'gql' => GraphDefaults::getFreeProcessList()
96                ]
97            )->getCollection();
98        } catch (\BO\Zmsclient\Exception $exception) {
99            if ($exception->template != 'BO\Zmsapi\Exception\Process\FreeProcessListEmpty') {
100                throw $exception;
101            }
102        }
103        return $slots;
104    }
105
106    public function readWeekDayListWithProcessList(
107        ?Cluster $cluster,
108        Workstation $workstation
109    ) {
110        $showAllInCluster = $cluster && 1 == $workstation->queue['clusterEnabled'];
111        $scopeList = $workstation->getScopeList($cluster);
112        $scope = $scopeList->getFirst();
113
114        $dayList = new DayList();
115
116        if ($showAllInCluster) {
117            $bookedProcessList = \App::$http
118                ->readGetResult('/cluster/' . $cluster->id . '/process/' . $this->dateTime->format('Y-m-d') . '/', ['showWeek' => 1])
119                ->getCollection();
120        } else {
121            $bookedProcessList = \App::$http
122                ->readGetResult('/scope/' . $scope->id . '/process/' . $this->dateTime->format('Y-m-d') . '/', ['showWeek' => 1])
123                ->getCollection();
124        }
125
126        /** @var ProcessList $bookedProcessList */
127        $processListByDate = $this->splitByDate($bookedProcessList);
128
129        $startDate = clone $this->dateTime->modify('Monday this week');
130        $endDate = clone $this->dateTime->modify('Sunday this week');
131        $currentDate = $startDate;
132
133        /** @var ProcessList $freeProcessList */
134        $freeProcessList = $this->readAvailableSlotsFromDayAndScopeList(
135            $scopeList,
136            'intern',
137            0,
138            true
139        );
140        $freeProcessListByDate = $freeProcessList ? $this->splitByDate($freeProcessList) : [];
141
142        while ($currentDate <= $endDate) {
143            $day = (new Day())->setDateTime($currentDate);
144            $day->status = Day::DETAIL;
145            $processList = new ProcessList();
146
147            $this->dateTime = $currentDate;
148            if ($currentDate->format('Y-m-d') >= \App::$now->format('Y-m-d')) {
149                if (isset($freeProcessListByDate[$currentDate->format('Y-m-d')])) {
150                    $processList->addList($freeProcessListByDate[$currentDate->format('Y-m-d')]);
151                }
152
153                if (isset($processListByDate[$currentDate->format('Y-m-d')])) {
154                    $processList->addList($processListByDate[$currentDate->format('Y-m-d')]);
155                }
156            }
157
158            $day['processList'] = $this->toProcessListByHour($processList);
159            $dayList->addEntity($day);
160            $currentDate = $currentDate->modify('+1 day');
161        }
162
163        return $this->toDayListByHour($dayList);
164    }
165
166    protected function getDateTimeFromWeekAndYear($week, $year)
167    {
168        $dateTime = new DateTimeImmutable();
169        return $dateTime->setISODate($year, $week);
170    }
171
172    public function toProcessListByHour(ProcessList $processList)
173    {
174        $list = array();
175        $oldList = $processList;
176        $oldList->sortByArrivalTime();
177        foreach ($oldList as $process) {
178            if (in_array($process->status, [ 'confirmed', 'free'])) {
179                $appointment = $process->getFirstAppointment();
180                $hour = (int)$appointment->toDateTime()->format('H');
181                if (!isset($list[$hour])) {
182                    $list[$hour] = array();
183                }
184                if (!isset($list[$hour][intval($appointment['date'])])) {
185                    $list[$hour][intval($appointment['date'])] = new ProcessList();
186                }
187                $list[$hour][intval($appointment['date'])]->addEntity($process);
188
189                unset($process);
190                ksort($list[$hour]);
191            }
192        }
193
194        ksort($list);
195        return $list;
196    }
197
198    public function toDayListByHour(DayList $dayList)
199    {
200        $list = array();
201        $hours = array();
202        $dayKeys = array();
203        foreach ($dayList as $day) {
204            $list['days'][] = $day;
205            $dayKey = $day->year . '-' . $day->month . '-' . $day->day;
206            $dayKeys[$dayKey] = $dayKey;
207            foreach ($day['processList'] as $hour => $processList) {
208                $list['hours'][$hour][$dayKey] = $processList;
209                $hours[$hour] = $hour;
210            }
211        }
212        foreach ($hours as $hour) {
213            foreach ($dayKeys as $dayKey) {
214                if (!isset($list['hours'][$hour][$dayKey])) {
215                    $list['hours'][$hour][$dayKey] = new ProcessList();
216                }
217            }
218            ksort($list['hours'][$hour]);
219        }
220
221        if (isset($list['hours']) && is_array($list['hours'])) {
222            ksort($list['hours']);
223        }
224
225        return $list;
226    }
227
228    private function splitByDate(ProcessList $processList)
229    {
230        $list = [];
231
232        foreach ($processList as $process) {
233            $dayKey = $process->getFirstAppointment()->toDateTime()->format("Y-m-d");
234            if (! isset($list[$dayKey])) {
235                $list[$dayKey] = new ProcessList();
236                ;
237            }
238
239            $list[$dayKey]->addEntity($process);
240        }
241
242        return $list;
243    }
244}