Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
85 / 85
100.00% covered (success)
100.00%
6 / 6
CRAP
100.00% covered (success)
100.00%
1 / 1
UserWorklogController
100.00% covered (success)
100.00%
85 / 85
100.00% covered (success)
100.00%
6 / 6
17
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
 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 deleteWorklog(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        $worklog->delete();
123
124        $this->log->info(
125            'Deleted worklog ({wl_id}) for {name} ({id}) at {time} spanning {hours}h{night_shift}: {text}',
126            [
127                'wl_id' => $worklog->id,
128                'name' => $worklog->user->name,
129                'id' => $worklog->user->id,
130                'time' => $worklog->worked_at,
131                'hours' => $worklog->hours,
132                'text' => $worklog->description,
133                'night_shift' => $worklog->night_shift ? ' at night' : '',
134            ]
135        );
136        $this->addNotification('worklog.delete.success');
137
138        return $this->redirect->to('/users?action=view&user_id=' . $user->id);
139        // TODO Once User_view.php gets removed, change this to withView + getNotifications
140    }
141
142    private function showEditWorklog(
143        User $user,
144        Carbon $work_date,
145        float $work_hours = 0,
146        string $description = '',
147        bool $night_shift = false,
148        bool $is_edit = false
149    ): Response {
150        return $this->response->withView(
151            'admin/user/edit-worklog.twig',
152            [
153                'userdata' => $user,
154                'work_date' => $work_date,
155                'work_hours' => $work_hours,
156                'description' => $description,
157                'night_shift' => $night_shift,
158                'is_edit' => $is_edit,
159            ]
160        );
161    }
162
163    private function needsUser(Request $request): User
164    {
165        $userId = (int) $request->getAttribute('user_id');
166        if (!config('enable_self_worklog') && ($userId === $this->auth->user()->id)) {
167            throw new HttpForbidden();
168        }
169        return $this->user->findOrFail($userId);
170    }
171}