Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
42.47% covered (danger)
42.47%
31 / 73
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
OverallCalendarRead
42.47% covered (danger)
42.47%
31 / 73
50.00% covered (danger)
50.00%
1 / 2
39.42
0.00% covered (danger)
0.00%
0 / 1
 buildCalendar
10.64% covered (danger)
10.64%
5 / 47
0.00% covered (danger)
0.00%
0 / 1
97.35
 readResponse
100.00% covered (success)
100.00%
26 / 26
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace BO\Zmsapi;
4
5use BO\Slim\Render;
6use BO\Mellon\Validator;
7use BO\Zmsdb\OverallCalendar as CalendarQuery;
8use DateTimeImmutable;
9use DateTimeInterface;
10
11class OverallCalendarRead extends BaseController
12{
13    private function buildCalendar(array $rows, int $defaultSeats = 1): array
14    {
15        $calendar = [];
16        $lastSlotInfo = [];
17
18        foreach ($rows as $row) {
19            $dateKey  = (new DateTimeImmutable($row['time']))->format('Y-m-d');
20            $timeKey  = (new DateTimeImmutable($row['time']))->format('H:i');
21            $scopeKey = (int)$row['scope_id'];
22            $seatNo   = (int)$row['seat'];
23
24            $day   =& $calendar[$dateKey];
25            $scope =& $day['scopes'][$scopeKey];
26            $time  =& $scope['times'][$timeKey]['seats'];
27
28            $day['date']            = (new DateTimeImmutable($dateKey))->getTimestamp();
29            $scope['id']            = $scopeKey;
30            $scope['name']          = '';
31            $scope['maxSeats']      = max($scope['maxSeats'] ?? 0, $seatNo, $defaultSeats);
32            $time[$seatNo]['init']  = true;
33
34            if ($row['status'] === 'termin') {
35                if ($row['slots'] === null) {
36                    $time[$seatNo] = ['status' => 'skip'];
37                } else {
38                    $time[$seatNo] = [
39                        'status'    => 'termin',
40                        'processId' => (int)$row['process_id'],
41                        'slots'     => (int)$row['slots'],
42                    ];
43                    $lastSlotInfo["$scopeKey|$seatNo"] = [
44                        'processId' => (int)$row['process_id'],
45                        'openSlots' => (int)$row['slots'] - 1,
46                    ];
47                }
48            } else {
49                $info = $lastSlotInfo["$scopeKey|$seatNo"] ?? null;
50                if ($info && $info['openSlots'] > 0) {
51                    $time[$seatNo] = ['status' => 'skip'];
52                    $lastSlotInfo["$scopeKey|$seatNo"]['openSlots']--;
53                } else {
54                    $time[$seatNo] = ['status' => 'open'];
55                    unset($lastSlotInfo["$scopeKey|$seatNo"]);
56                }
57            }
58        }
59
60        foreach ($calendar as &$day) {
61            foreach ($day['scopes'] as &$scope) {
62                foreach ($scope['times'] as $timeKey => $slotInfo) {
63                    for ($seatNumber = 1; $seatNumber <= $scope['maxSeats']; $seatNumber++) {
64                        if (!isset($slotInfo['seats'][$seatNumber])) {
65                            $slotInfo['seats'][$seatNumber] = ['status' => 'open'];
66                        }
67                    }
68                    ksort($slotInfo['seats']);
69
70                    $scope['times'][$timeKey] = [
71                        'name'  => $timeKey,
72                        'seats' => array_values($slotInfo['seats']),
73                    ];
74                }
75                $scope['times'] = array_values($scope['times']);
76            }
77            $day['scopes'] = array_values($day['scopes']);
78        }
79
80        return ['days' => array_values($calendar)];
81    }
82
83    public function readResponse(
84        \Psr\Http\Message\RequestInterface $request,
85        \Psr\Http\Message\ResponseInterface $response,
86        array $args
87    ) {
88        $scopeIdCsv = Validator::param('scopeIds')
89            ->isString()->isMatchOf('/^\d+(,\d+)*$/')->assertValid()->getValue();
90        $scopeIds   = array_map('intval', explode(',', $scopeIdCsv));
91
92        $dateFrom   = Validator::param('dateFrom')->isDate('Y-m-d')->assertValid()->getValue();
93        $dateUntil  = Validator::param('dateUntil')->isDate('Y-m-d')->assertValid()->getValue();
94        $updateAfter = Validator::param('updateAfter')->isDatetime()->setDefault(null)->getValue();
95
96        $flatRows = (new CalendarQuery())->readSlots(
97            $scopeIds,
98            $dateFrom,
99            $dateUntil,
100            $updateAfter
101        );
102
103        $structured = $this->buildCalendar($flatRows);
104
105        $msg           = Response\Message::create($request);
106        $msg->data     = $structured;
107        $msg->meta->rows = count($flatRows);
108
109        $response = Render::withLastModified(
110            $response,
111            (new DateTimeImmutable())->getTimestamp(),
112            '0'
113        );
114        return Render::withJson(
115            $response,
116            $msg->setUpdatedMetaData(),
117            $msg->getStatuscode()
118        );
119    }
120}