Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
79 / 79 |
|
100.00% |
6 / 6 |
CRAP | |
100.00% |
1 / 1 |
ShiftTypesController | |
100.00% |
79 / 79 |
|
100.00% |
6 / 6 |
12 | |
100.00% |
1 / 1 |
__construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
index | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
1 | |||
edit | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
1 | |||
view | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 | |||
save | |
100.00% |
42 / 42 |
|
100.00% |
1 / 1 |
6 | |||
delete | |
100.00% |
12 / 12 |
|
100.00% |
1 / 1 |
2 |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Engelsystem\Controllers\Admin; |
6 | |
7 | use Engelsystem\Controllers\BaseController; |
8 | use Engelsystem\Controllers\HasUserNotifications; |
9 | use Engelsystem\Http\Exceptions\ValidationException; |
10 | use Engelsystem\Http\Redirector; |
11 | use Engelsystem\Http\Request; |
12 | use Engelsystem\Http\Response; |
13 | use Engelsystem\Http\Validation\Validator; |
14 | use Engelsystem\Models\AngelType; |
15 | use Engelsystem\Models\Shifts\NeededAngelType; |
16 | use Engelsystem\Models\Shifts\ShiftType; |
17 | use Illuminate\Database\Eloquent\Collection; |
18 | use Psr\Log\LoggerInterface; |
19 | |
20 | class ShiftTypesController extends BaseController |
21 | { |
22 | use HasUserNotifications; |
23 | |
24 | /** @var array<string> */ |
25 | protected array $permissions = [ |
26 | 'shifttypes.view', |
27 | 'edit' => 'shifttypes.edit', |
28 | 'delete' => 'shifttypes.edit', |
29 | 'save' => 'shifttypes.edit', |
30 | ]; |
31 | |
32 | public function __construct( |
33 | protected LoggerInterface $log, |
34 | protected ShiftType $shiftType, |
35 | protected Redirector $redirect, |
36 | protected Response $response |
37 | ) { |
38 | } |
39 | |
40 | public function index(): Response |
41 | { |
42 | $shiftTypes = $this->shiftType |
43 | ->get() |
44 | ->sortBy('name', SORT_NATURAL | SORT_FLAG_CASE); |
45 | |
46 | return $this->response->withView( |
47 | 'admin/shifttypes/index', |
48 | ['shifttypes' => $shiftTypes, 'is_index' => true] |
49 | ); |
50 | } |
51 | |
52 | public function edit(Request $request): Response |
53 | { |
54 | $shiftTypeId = (int) $request->getAttribute('shift_type_id'); |
55 | |
56 | $shiftType = $this->shiftType->find($shiftTypeId); |
57 | $angeltypes = AngelType::all() |
58 | ->sortBy('name'); |
59 | |
60 | return $this->response->withView( |
61 | 'admin/shifttypes/edit', |
62 | [ |
63 | 'shifttype' => $shiftType, |
64 | 'angel_types' => $angeltypes, |
65 | ] |
66 | ); |
67 | } |
68 | |
69 | public function view(Request $request): Response |
70 | { |
71 | $shiftTypeId = (int) $request->getAttribute('shift_type_id'); |
72 | $shiftType = $this->shiftType->findOrFail($shiftTypeId); |
73 | |
74 | return $this->response->withView( |
75 | 'admin/shifttypes/view', |
76 | ['shifttype' => $shiftType, 'is_view' => true] |
77 | ); |
78 | } |
79 | |
80 | public function save(Request $request): Response |
81 | { |
82 | $shiftTypeId = (int) $request->getAttribute('shift_type_id'); |
83 | |
84 | /** @var ShiftType $shiftType */ |
85 | $shiftType = $this->shiftType->findOrNew($shiftTypeId); |
86 | |
87 | if ($request->request->has('delete')) { |
88 | return $this->delete($request); |
89 | } |
90 | |
91 | /** @var Collection|AngelType[] $angelTypes */ |
92 | $angelTypes = AngelType::all(); |
93 | $validation = []; |
94 | foreach ($angelTypes as $angelType) { |
95 | $validation['angel_type_' . $angelType->id] = 'optional|int'; |
96 | } |
97 | |
98 | $data = $this->validate( |
99 | $request, |
100 | [ |
101 | 'name' => 'required|max:255', |
102 | 'description' => 'optional', |
103 | ] + $validation |
104 | ); |
105 | |
106 | if (ShiftType::whereName($data['name'])->where('id', '!=', $shiftType->id)->exists()) { |
107 | throw new ValidationException((new Validator())->addErrors(['name' => ['validation.name.exists']])); |
108 | } |
109 | |
110 | $shiftType->name = $data['name']; |
111 | $shiftType->description = $data['description'] ?? ''; |
112 | |
113 | $shiftType->save(); |
114 | $shiftType->neededAngelTypes()->delete(); |
115 | |
116 | // Associate angel types with the shift type |
117 | $angelsInfo = ''; |
118 | foreach ($angelTypes as $angelType) { |
119 | $count = $data['angel_type_' . $angelType->id]; |
120 | if (!$count) { |
121 | continue; |
122 | } |
123 | |
124 | $neededAngelType = new NeededAngelType(); |
125 | |
126 | $neededAngelType->shiftType()->associate($shiftType); |
127 | $neededAngelType->angelType()->associate($angelType); |
128 | |
129 | $neededAngelType->count = $data['angel_type_' . $angelType->id]; |
130 | |
131 | $neededAngelType->save(); |
132 | |
133 | $angelsInfo .= sprintf(', %s: %s', $angelType->name, $count); |
134 | } |
135 | |
136 | $this->log->info( |
137 | 'Updated shift type "{name}": {description} {angels}', |
138 | [ |
139 | 'name' => $shiftType->name, |
140 | 'description' => $shiftType->description, |
141 | 'angels' => $angelsInfo, |
142 | ] |
143 | ); |
144 | |
145 | $this->addNotification('shifttype.edit.success'); |
146 | |
147 | return $this->redirect->to('/admin/shifttypes'); |
148 | } |
149 | |
150 | public function delete(Request $request): Response |
151 | { |
152 | $data = $this->validate($request, [ |
153 | 'id' => 'required|int', |
154 | 'delete' => 'checked', |
155 | ]); |
156 | |
157 | $shiftType = $this->shiftType->findOrFail($data['id']); |
158 | |
159 | $shifts = $shiftType->shifts; |
160 | foreach ($shifts as $shift) { |
161 | event('shift.deleting', ['shift' => $shift]); |
162 | } |
163 | $shiftType->delete(); |
164 | |
165 | $this->log->info('Deleted shift type {name}', ['name' => $shiftType->name]); |
166 | $this->addNotification('shifttype.delete.success'); |
167 | |
168 | return $this->redirect->to('/admin/shifttypes'); |
169 | } |
170 | } |