Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
79 / 79
100.00% covered (success)
100.00%
6 / 6
CRAP
100.00% covered (success)
100.00%
1 / 1
ShiftTypesController
100.00% covered (success)
100.00%
79 / 79
100.00% covered (success)
100.00%
6 / 6
12
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 index
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 edit
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
1
 view
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 save
100.00% covered (success)
100.00%
42 / 42
100.00% covered (success)
100.00%
1 / 1
6
 delete
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4
5namespace Engelsystem\Controllers\Admin;
6
7use Engelsystem\Controllers\BaseController;
8use Engelsystem\Controllers\HasUserNotifications;
9use Engelsystem\Http\Exceptions\ValidationException;
10use Engelsystem\Http\Redirector;
11use Engelsystem\Http\Request;
12use Engelsystem\Http\Response;
13use Engelsystem\Http\Validation\Validator;
14use Engelsystem\Models\AngelType;
15use Engelsystem\Models\Shifts\NeededAngelType;
16use Engelsystem\Models\Shifts\ShiftType;
17use Illuminate\Database\Eloquent\Collection;
18use Psr\Log\LoggerInterface;
19
20class 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}