Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
112 / 112 |
|
100.00% |
6 / 6 |
CRAP | |
100.00% |
1 / 1 |
ShiftsController | |
100.00% |
112 / 112 |
|
100.00% |
6 / 6 |
17 | |
100.00% |
1 / 1 |
entriesByAngeltype | |
100.00% |
19 / 19 |
|
100.00% |
1 / 1 |
1 | |||
entriesByLocation | |
100.00% |
15 / 15 |
|
100.00% |
1 / 1 |
1 | |||
entriesByShiftType | |
100.00% |
15 / 15 |
|
100.00% |
1 / 1 |
1 | |||
entriesByUser | |
100.00% |
19 / 19 |
|
100.00% |
1 / 1 |
1 | |||
shiftEntriesResponse | |
100.00% |
23 / 23 |
|
100.00% |
1 / 1 |
6 | |||
getNeededAngelTypes | |
100.00% |
21 / 21 |
|
100.00% |
1 / 1 |
7 |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Engelsystem\Controllers\Api; |
6 | |
7 | use Engelsystem\Controllers\Api\Resources\AngelTypeResource; |
8 | use Engelsystem\Controllers\Api\Resources\LocationResource; |
9 | use Engelsystem\Controllers\Api\Resources\ShiftWithEntriesResource; |
10 | use Engelsystem\Controllers\Api\Resources\UserResource; |
11 | use Engelsystem\Http\Request; |
12 | use Engelsystem\Http\Response; |
13 | use Engelsystem\Models\AngelType; |
14 | use Engelsystem\Models\Location; |
15 | use Engelsystem\Models\Shifts\NeededAngelType; |
16 | use Engelsystem\Models\Shifts\Shift; |
17 | use Engelsystem\Models\Shifts\ShiftEntry; |
18 | use Engelsystem\Models\Shifts\ShiftType; |
19 | use Illuminate\Database\Eloquent\Collection; |
20 | |
21 | class ShiftsController extends ApiController |
22 | { |
23 | use UsesAuth; |
24 | |
25 | public function entriesByAngeltype(Request $request): Response |
26 | { |
27 | $id = (int) $request->getAttribute('angeltype_id'); |
28 | /** @var AngelType $angeltype */ |
29 | $angeltype = AngelType::findOrFail($id); |
30 | /** @var ShiftEntry[]|Collection $shifts */ |
31 | $shiftEntries = $angeltype->shiftEntries() |
32 | ->with([ |
33 | 'shift.neededAngelTypes.angelType', |
34 | 'shift.location.neededAngelTypes.angelType', |
35 | 'shift.shiftEntries.angelType', |
36 | 'shift.shiftEntries.user.contact', |
37 | 'shift.shiftEntries.user.personalData', |
38 | 'shift.shiftType', |
39 | 'shift.schedule.shiftType.neededAngelTypes.angelType', |
40 | ]) |
41 | ->get(); |
42 | |
43 | /** @var Shift[]|Collection $shifts */ |
44 | $shifts = Collection::make( |
45 | $shiftEntries |
46 | ->pluck('shift') |
47 | ->sortBy('start') |
48 | ); |
49 | |
50 | return $this->shiftEntriesResponse($shifts); |
51 | } |
52 | |
53 | public function entriesByLocation(Request $request): Response |
54 | { |
55 | $locationId = (int) $request->getAttribute('location_id'); |
56 | /** @var Location $location */ |
57 | $location = Location::findOrFail($locationId); |
58 | /** @var Shift[]|Collection $shifts */ |
59 | $shifts = $location->shifts() |
60 | ->with([ |
61 | 'neededAngelTypes.angelType', |
62 | 'location.neededAngelTypes.angelType', |
63 | 'shiftEntries.angelType', |
64 | 'shiftEntries.user.contact', |
65 | 'shiftEntries.user.personalData', |
66 | 'shiftType', |
67 | 'schedule.shiftType.neededAngelTypes.angelType', |
68 | ]) |
69 | ->orderBy('start') |
70 | ->get(); |
71 | |
72 | return $this->shiftEntriesResponse($shifts); |
73 | } |
74 | |
75 | public function entriesByShiftType(Request $request): Response |
76 | { |
77 | $shiftTypeId = (int) $request->getAttribute('shifttype_id'); |
78 | /** @var ShiftType $shiftType */ |
79 | $shiftType = ShiftType::findOrFail($shiftTypeId); |
80 | /** @var Shift[]|Collection $shifts */ |
81 | $shifts = $shiftType->shifts() |
82 | ->with([ |
83 | 'neededAngelTypes.angelType', |
84 | 'location.neededAngelTypes.angelType', |
85 | 'shiftEntries.angelType', |
86 | 'shiftEntries.user.contact', |
87 | 'shiftEntries.user.personalData', |
88 | 'shiftType', |
89 | 'schedule.shiftType.neededAngelTypes.angelType', |
90 | ]) |
91 | ->orderBy('start') |
92 | ->get(); |
93 | |
94 | return $this->shiftEntriesResponse($shifts); |
95 | } |
96 | |
97 | public function entriesByUser(Request $request): Response |
98 | { |
99 | $id = $request->getAttribute('user_id'); |
100 | $user = $this->getUser($id); |
101 | |
102 | /** @var ShiftEntry[]|Collection $shifts */ |
103 | $shiftEntries = $user->shiftEntries() |
104 | ->with([ |
105 | 'shift.neededAngelTypes.angelType', |
106 | 'shift.location.neededAngelTypes.angelType', |
107 | 'shift.shiftEntries.angelType', |
108 | 'shift.shiftEntries.user.contact', |
109 | 'shift.shiftEntries.user.personalData', |
110 | 'shift.shiftType', |
111 | 'shift.schedule.shiftType.neededAngelTypes.angelType', |
112 | ]) |
113 | ->get(); |
114 | |
115 | /** @var Shift[]|Collection $shifts */ |
116 | $shifts = Collection::make( |
117 | $shiftEntries |
118 | ->pluck('shift') |
119 | ->sortBy('start') |
120 | ); |
121 | |
122 | return $this->shiftEntriesResponse($shifts); |
123 | } |
124 | |
125 | protected function shiftEntriesResponse(Collection $shifts): Response |
126 | { |
127 | /** @var Collection|Shift[] $shifts */ |
128 | $shiftEntries = []; |
129 | // Blob of not-optimized mediocre pseudo-serialization |
130 | foreach ($shifts as $shift) { |
131 | // Get all needed/used angel types |
132 | /** @var Collection|NeededAngelType[] $neededAngelTypes */ |
133 | $neededAngelTypes = $this->getNeededAngelTypes($shift); |
134 | |
135 | $angelTypes = new Collection(); |
136 | foreach ($neededAngelTypes as $neededAngelType) { |
137 | $entries = $neededAngelType->entries ?: new Collection(); |
138 | |
139 | // Skip empty entries |
140 | if ($neededAngelType->count <= 0 && $entries->isEmpty()) { |
141 | continue; |
142 | } |
143 | |
144 | $entries = $entries->map(fn(ShiftEntry $entry) => [ |
145 | 'user' => UserResource::toIdentifierArray($entry->user), |
146 | 'freeloaded' => $entry->freeloaded, |
147 | ]); |
148 | $angelTypeData = AngelTypeResource::toIdentifierArray($neededAngelType->angelType); |
149 | $angelTypes[] = new Collection([ |
150 | 'angel_type' => $angelTypeData, |
151 | 'needs' => $neededAngelType->count, |
152 | 'entries' => $entries, |
153 | ]); |
154 | } |
155 | |
156 | $locationData = new LocationResource($shift->location); |
157 | $shiftEntries[] = (new ShiftWithEntriesResource($shift))->toArray($locationData, $angelTypes); |
158 | } |
159 | |
160 | $data = ['data' => $shiftEntries]; |
161 | return $this->response |
162 | ->withContent(json_encode($data)); |
163 | } |
164 | |
165 | /** |
166 | * Collect all needed angel types |
167 | */ |
168 | protected function getNeededAngelTypes(Shift $shift): Collection |
169 | { |
170 | $neededAngelTypes = new Collection(); |
171 | if (!$shift->schedule) { |
172 | // Get from shift |
173 | $neededAngelTypes = $shift->neededAngelTypes; |
174 | } elseif ($shift->schedule->needed_from_shift_type) { |
175 | // Load instead from shift type |
176 | $neededAngelTypes = $shift->schedule->shiftType->neededAngelTypes; |
177 | } elseif (!$shift->schedule->needed_from_shift_type) { |
178 | // Load instead from location |
179 | $neededAngelTypes = $shift->location->neededAngelTypes; |
180 | } |
181 | |
182 | // Add needed angel types from additionally added users |
183 | foreach ($shift->shiftEntries as $entry) { |
184 | $neededAngelType = $neededAngelTypes->where('angel_type_id', $entry->angelType->id)->first(); |
185 | if (!$neededAngelType) { |
186 | $neededAngelType = new NeededAngelType([ |
187 | 'shift_id' => $shift->id, |
188 | 'angel_type_id' => $entry->angelType->id, |
189 | 'count' => 0, |
190 | ]); |
191 | $neededAngelTypes[] = $neededAngelType; |
192 | } |
193 | |
194 | // Add entries to needed angel type |
195 | $neededAngelType->entries = isset($neededAngelType->entries) |
196 | ? $neededAngelType->entries |
197 | : new Collection(); |
198 | $neededAngelType->entries[] = $entry; |
199 | } |
200 | |
201 | return $neededAngelTypes; |
202 | } |
203 | } |