Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
112 / 112
100.00% covered (success)
100.00%
6 / 6
CRAP
100.00% covered (success)
100.00%
1 / 1
ShiftsController
100.00% covered (success)
100.00%
112 / 112
100.00% covered (success)
100.00%
6 / 6
17
100.00% covered (success)
100.00%
1 / 1
 entriesByAngeltype
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
1 / 1
1
 entriesByLocation
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
1
 entriesByShiftType
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
1
 entriesByUser
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
1 / 1
1
 shiftEntriesResponse
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
1 / 1
6
 getNeededAngelTypes
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
1 / 1
7
1<?php
2
3declare(strict_types=1);
4
5namespace Engelsystem\Controllers\Api;
6
7use Engelsystem\Controllers\Api\Resources\AngelTypeResource;
8use Engelsystem\Controllers\Api\Resources\LocationResource;
9use Engelsystem\Controllers\Api\Resources\ShiftWithEntriesResource;
10use Engelsystem\Controllers\Api\Resources\UserResource;
11use Engelsystem\Http\Request;
12use Engelsystem\Http\Response;
13use Engelsystem\Models\AngelType;
14use Engelsystem\Models\Location;
15use Engelsystem\Models\Shifts\NeededAngelType;
16use Engelsystem\Models\Shifts\Shift;
17use Engelsystem\Models\Shifts\ShiftEntry;
18use Engelsystem\Models\Shifts\ShiftType;
19use Illuminate\Database\Eloquent\Collection;
20
21class 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}