Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
118 / 118
100.00% covered (success)
100.00%
10 / 10
CRAP
100.00% covered (success)
100.00%
1 / 1
UserSettingsController
100.00% covered (success)
100.00%
118 / 118
100.00% covered (success)
100.00%
10 / 10
42
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
 certificate
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
6
 saveIfsgCertificate
100.00% covered (success)
100.00%
28 / 28
100.00% covered (success)
100.00%
1 / 1
9
 saveDrivingLicense
100.00% covered (success)
100.00%
37 / 37
100.00% covered (success)
100.00%
1 / 1
13
 settingsMenu
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
6
 checkPermission
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
3
 view
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 getUser
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 isIfsgSupporter
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 isDriverLicenseSupporter
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace Engelsystem\Controllers\Admin;
6
7use Engelsystem\Config\Config;
8use Engelsystem\Controllers\BaseController;
9use Engelsystem\Controllers\HasUserNotifications;
10use Engelsystem\Helpers\Authenticator;
11use Engelsystem\Http\Exceptions\HttpForbidden;
12use Engelsystem\Http\Exceptions\HttpNotFound;
13use Engelsystem\Http\Redirector;
14use Engelsystem\Http\Request;
15use Engelsystem\Http\Response;
16use Engelsystem\Models\AngelType;
17use Engelsystem\Models\User\User;
18use Psr\Log\LoggerInterface;
19
20class UserSettingsController extends BaseController
21{
22    use HasUserNotifications;
23
24    public function __construct(
25        protected Authenticator $auth,
26        protected Config $config,
27        protected LoggerInterface $log,
28        protected Redirector $redirect,
29        protected Response $response
30    ) {
31    }
32
33    public function certificate(Request $request): Response
34    {
35        if (!config('ifsg_enabled') && !config('driving_license_enabled')) {
36            throw new HttpNotFound();
37        }
38
39        if (
40            !(
41                $this->auth->canAny(['user.ifsg.edit', 'user.drive.edit'])
42                || $this->isDriverLicenseSupporter()
43                || $this->isIfsgSupporter()
44            )
45        ) {
46            throw new HttpForbidden();
47        }
48
49        $user = $this->getUser($request);
50
51        return $this->view(
52            $user,
53            'pages/settings/certificates-admin',
54            [
55                'certificates' => $user->license,
56            ]
57        );
58    }
59
60    public function saveIfsgCertificate(Request $request): Response
61    {
62        if (!config('ifsg_enabled')) {
63            throw new HttpNotFound();
64        }
65
66        $this->checkPermission('user.ifsg.edit', $this->isIfsgSupporter());
67        $user = $this->getUser($request);
68
69        $data = $this->validate($request, [
70            'ifsg_certificate_light' => 'optional|checked',
71            'ifsg_certificate' => 'optional|checked',
72            'ifsg_confirmed' => 'optional|checked',
73        ]);
74
75        if (config('ifsg_light_enabled')) {
76            $user->license->ifsg_certificate_light = !$data['ifsg_certificate'] && $data['ifsg_certificate_light'];
77        }
78        $user->license->ifsg_certificate = (bool) $data['ifsg_certificate'];
79        $user->license->ifsg_confirmed = $data['ifsg_confirmed']
80            && ($user->license->ifsg_certificate || $user->license->ifsg_certificate_light);
81
82        $user->license->save();
83        $this->addNotification('settings.certificates.success');
84        $this->log->info('Certificate "{certificate}" of user {user} ({id}) is {confirmation}.', [
85            'certificate' => $user->license->ifsg_certificate_light
86                ? 'IfSG light'
87                : ($user->license->ifsg_certificate
88                    ? 'IfSG'
89                    : 'no IfSG'
90                ),
91            'user' => $user->name,
92            'id' => $user->id,
93            'confirmation' => $user->license->ifsg_confirmed ? 'confirmed' : 'unconfirmed',
94        ]);
95
96        return $this->redirect->to('/users/' . $user->id . '/certificates');
97    }
98
99    public function saveDrivingLicense(Request $request): Response
100    {
101        if (!config('driving_license_enabled')) {
102            throw new HttpNotFound();
103        }
104
105        $this->checkPermission('user.drive.edit', $this->isDriverLicenseSupporter());
106        $user = $this->getUser($request);
107
108        $data = $this->validate($request, [
109            'drive_car' => 'optional|checked',
110            'drive_3_5t' => 'optional|checked',
111            'drive_7_5t' => 'optional|checked',
112            'drive_12t' => 'optional|checked',
113            'drive_forklift' => 'optional|checked',
114            'drive_confirmed' => 'optional|checked',
115        ]);
116
117        $user->license->drive_car = (bool) $data['drive_car'];
118        $user->license->drive_3_5t = (bool) $data['drive_3_5t'];
119        $user->license->drive_7_5t = (bool) $data['drive_7_5t'];
120        $user->license->drive_12t = (bool) $data['drive_12t'];
121        $user->license->drive_forklift = (bool) $data['drive_forklift'];
122        $user->license->drive_confirmed = $data['drive_confirmed'] && (
123            $user->license->drive_car
124            || $user->license->drive_3_5t
125            || $user->license->drive_7_5t
126            || $user->license->drive_12t
127            || $user->license->drive_forklift
128        );
129
130        $user->license->save();
131        $this->addNotification('settings.certificates.success');
132
133        $this->log->info('Certificate "{certificate}" of user {user} ({id}) is {confirmation}.', [
134            'certificate' => ($user->license->drive_car ? 'car' : '')
135                . ($user->license->drive_3_5t ? ', 3.5t' : '')
136                . ($user->license->drive_7_5t ? ', 7.5t' : '')
137                . ($user->license->drive_12t ? ', 12t' : '')
138                . ($user->license->drive_forklift ? ', forklift' : ''),
139            'user' => $user->name,
140            'id' => $user->id,
141            'confirmation' => $user->license->drive_confirmed ? 'confirmed' : 'unconfirmed',
142        ]);
143
144        return $this->redirect->to('/users/' . $user->id . '/certificates');
145    }
146
147    public function settingsMenu(User $user): array
148    {
149        $menu = [
150            url('/users', ['action' => 'view', 'user_id' => $user->id]) => [
151                'title' => 'general.back', 'icon' => 'chevron-left',
152            ],
153        ];
154
155        if (config('ifsg_enabled') || config('driving_license_enabled')) {
156            $menu[url('/users/' . $user->id . '/certificates')] = [
157                'title' => 'settings.certificates',
158                'icon' => 'card-checklist',
159                'permission' => (
160                    $this->auth->canAny(['user.ifsg.edit', 'user.drive.edit'])
161                    || $this->isIfsgSupporter()
162                    || $this->isDriverLicenseSupporter()
163                ) ? null : '_',
164            ];
165        }
166
167        return $menu;
168    }
169
170    protected function checkPermission(string | array $abilities, bool $overwrite = false): void
171    {
172        if (!$overwrite && !$this->auth->can($abilities)) {
173            throw new HttpForbidden();
174        }
175    }
176
177    protected function view(User $user, string $view, array $data = []): Response
178    {
179        return $this->response->withView(
180            $view,
181            array_merge([
182                'settings_menu' => $this->settingsMenu($user),
183                'is_admin' => true,
184                'admin_user' => $user,
185            ], $data)
186        );
187    }
188
189    protected function getUser(Request $request): User
190    {
191        $userId = $request->getAttribute('user_id');
192        return User::findOrFail($userId);
193    }
194
195    public function isIfsgSupporter(): bool
196    {
197        return (bool) AngelType::whereRequiresIfsgCertificate(true)
198            ->leftJoin('user_angel_type', 'user_angel_type.angel_type_id', 'angel_types.id')
199            ->where('user_angel_type.user_id', $this->auth->user()?->id)
200            ->where('user_angel_type.supporter', true)
201            ->count();
202    }
203
204    public function isDriverLicenseSupporter(): bool
205    {
206        return (bool) AngelType::whereRequiresDriverLicense(true)
207            ->leftJoin('user_angel_type', 'user_angel_type.angel_type_id', 'angel_types.id')
208            ->where('user_angel_type.user_id', $this->auth->user()?->id)
209            ->where('user_angel_type.supporter', true)
210            ->count();
211    }
212}