Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
94 / 94
100.00% covered (success)
100.00%
7 / 7
CRAP
100.00% covered (success)
100.00%
1 / 1
UserWorklogController
100.00% covered (success)
100.00%
94 / 94
100.00% covered (success)
100.00%
7 / 7
19
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
 editWorklog
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
3
 saveWorklog
100.00% covered (success)
100.00%
34 / 34
100.00% covered (success)
100.00%
1 / 1
6
 showDeleteWorklog
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
2
 deleteWorklog
100.00% covered (success)
100.00%
20 / 20
100.00% covered (success)
100.00%
1 / 1
3
 showEditWorklog
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
1
 needsUser
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3declare(strict_types=1);
4
5namespace Engelsystem\Controllers\Admin;
6
7use Carbon\Carbon;
8use Engelsystem\Config\Config;
9use Engelsystem\Controllers\BaseController;
10use Engelsystem\Controllers\HasUserNotifications;
11use Engelsystem\Helpers\Authenticator;
12use Engelsystem\Http\Exceptions\HttpForbidden;
13use Engelsystem\Http\Exceptions\HttpNotFound;
14use Engelsystem\Http\Redirector;
15use Engelsystem\Http\Request;
16use Engelsystem\Http\Response;
17use Engelsystem\Models\User\User;
18use Engelsystem\Models\Worklog;
19use Psr\Log\LoggerInterface;
20
21class UserWorklogController extends BaseController
22{
23    use HasUserNotifications;
24
25    /** @var array<string> */
26    protected array $permissions = [
27        'admin_user_worklog',
28    ];
29
30    public function __construct(
31        protected Authenticator $auth,
32        protected Config $config,
33        protected LoggerInterface $log,
34        protected Worklog $worklog,
35        protected Redirector $redirect,
36        protected Response $response,
37        protected User $user
38    ) {
39    }
40
41    public function editWorklog(Request $request): Response
42    {
43        $user = $this->needsUser($request);
44        $worklogId = $request->getAttribute('worklog_id'); // optional
45
46        if (isset($worklogId)) {
47            $worklog = $this->worklog->findOrFail((int) $worklogId);
48
49            if ($worklog->user->id != $user->id) {
50                throw new HttpNotFound();
51            }
52            return $this->showEditWorklog(
53                $user,
54                $worklog->worked_at,
55                $worklog->hours,
56                $worklog->description,
57                $worklog->night_shift,
58                true
59            );
60        } else {
61            return $this->showEditWorklog($user, Carbon::today());
62        }
63    }
64
65    public function saveWorklog(Request $request): Response
66    {
67        $user = $this->needsUser($request);
68        $worklogId = $request->getAttribute('worklog_id'); // optional
69
70        $data = $this->validate($request, [
71            'work_date' => 'required|date:Y-m-d',
72            'work_hours' => 'float|min:0',
73            'description' => 'required|max:200',
74            'night_shift' => 'optional|checked',
75        ]);
76
77        // Search / create worklog
78        if (isset($worklogId)) {
79            $worklog = $this->worklog->findOrFail((int) $worklogId);
80
81            if ($worklog->user->id != $user->id) {
82                throw new HttpNotFound();
83            }
84        } else {
85            $worklog = new Worklog();
86            $worklog->user()->associate($user);
87            $worklog->creator()->associate($this->auth->user());
88        }
89        $worklog->worked_at = $data['work_date'];
90        $worklog->hours = $data['work_hours'];
91        $worklog->description = $data['description'];
92        $worklog->night_shift = $data['night_shift'] ?: false;
93        $worklog->save();
94
95        $this->log->info(
96            'Saved worklog ({wl_id}) for {name} ({id}) at {time} spanning {hours}h{night_shift}: {text}',
97            [
98                'wl_id' => $worklog->id,
99                'name' => $user->name,
100                'id' => $user->id,
101                'time' => $worklog->worked_at,
102                'hours' => $worklog->hours,
103                'text' => $worklog->description,
104                'night_shift' => $worklog->night_shift ? ' at night' : '',
105            ]
106        );
107        $this->addNotification(isset($worklogId) ? 'worklog.edit.success' : 'worklog.add.success');
108
109        return $this->redirect->to('/users?action=view&user_id=' . $user->id);
110        // TODO Once User_view.php gets removed, change this to withView + getNotifications
111    }
112
113    public function showDeleteWorklog(Request $request): Response
114    {
115        $user = $this->needsUser($request);
116        $worklogId = $request->getAttribute('worklog_id');
117        $worklog = $this->worklog->findOrFail($worklogId);
118
119        if ($worklog->user->id != $user->id) {
120            throw new HttpNotFound();
121        }
122
123        return $this->response->withView(
124            'admin/user/delete-worklog.twig',
125            ['userdata' => $user]
126        );
127    }
128
129    public function deleteWorklog(Request $request): Response
130    {
131        $user = $this->needsUser($request);
132        $worklogId = $request->getAttribute('worklog_id');
133        $worklog = $this->worklog->findOrFail($worklogId);
134
135        if ($worklog->user->id != $user->id) {
136            throw new HttpNotFound();
137        }
138        $worklog->delete();
139
140        $this->log->info(
141            'Deleted worklog ({wl_id}) for {name} ({id}) at {time} spanning {hours}h{night_shift}: {text}',
142            [
143                'wl_id' => $worklog->id,
144                'name' => $worklog->user->name,
145                'id' => $worklog->user->id,
146                'time' => $worklog->worked_at,
147                'hours' => $worklog->hours,
148                'text' => $worklog->description,
149                'night_shift' => $worklog->night_shift ? ' at night' : '',
150            ]
151        );
152        $this->addNotification('worklog.delete.success');
153
154        return $this->redirect->to('/users?action=view&user_id=' . $user->id);
155        // TODO Once User_view.php gets removed, change this to withView + getNotifications
156    }
157
158    private function showEditWorklog(
159        User $user,
160        Carbon $work_date,
161        float $work_hours = 0,
162        string $description = '',
163        bool $night_shift = false,
164        bool $is_edit = false
165    ): Response {
166        return $this->response->withView(
167            'admin/user/edit-worklog.twig',
168            [
169                'userdata' => $user,
170                'work_date' => $work_date,
171                'work_hours' => $work_hours,
172                'description' => $description,
173                'night_shift' => $night_shift,
174                'is_edit' => $is_edit,
175            ]
176        );
177    }
178
179    private function needsUser(Request $request): User
180    {
181        $userId = (int) $request->getAttribute('user_id');
182        if (!config('enable_self_worklog') && ($userId === $this->auth->user()->id)) {
183            throw new HttpForbidden();
184        }
185        return $this->user->findOrFail($userId);
186    }
187}