StudentAbsenceController   C
last analyzed

Complexity

Total Complexity 56

Size/Duplication

Total Lines 406
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 230
dl 0
loc 406
rs 5.5199
c 1
b 0
f 0
wmc 56

10 Methods

Rating   Name   Duplication   Size   Complexity  
B show() 0 47 6
B addBulk() 0 57 6
A edit() 0 21 4
A add() 0 30 4
D index() 0 118 23
A downloadAttachment() 0 19 3
A deny() 0 16 2
A remove() 0 20 3
A approve() 0 16 2
A createExcuseNote() 0 25 3

How to fix   Complexity   

Complex Class

Complex classes like StudentAbsenceController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use StudentAbsenceController, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace App\Controller;
4
5
use App\Converter\StudyGroupStringConverter;
6
use App\Entity\DateLesson;
7
use App\Entity\Exam;
8
use App\Entity\ExcuseNote;
9
use App\Entity\Student;
10
use App\Entity\StudentAbsence;
11
use App\Entity\StudentAbsenceAttachment;
12
use App\Entity\StudentAbsenceMessage;
13
use App\Entity\StudyGroupMembership;
14
use App\Entity\User;
15
use App\Form\Model\BulkStudentAbsence;
16
use App\Form\StudentAbsenceBulkType;
17
use App\Form\StudentAbsenceMessageType;
18
use App\Form\StudentAbsenceType;
19
use App\Grouping\StudentAbsenceGenericGroup;
20
use App\Grouping\StudentAbsenceGradeGroup;
21
use App\Grouping\StudentAbsenceStudentGroup;
22
use App\Grouping\StudentAbsenceTuitionGroup;
23
use App\Http\FlysystemFileResponse;
24
use App\Repository\AppointmentRepositoryInterface;
25
use App\Repository\ExamRepositoryInterface;
26
use App\Repository\ExcuseNoteRepositoryInterface;
27
use App\Repository\StudentAbsenceRepositoryInterface;
28
use App\Repository\StudentRepositoryInterface;
29
use App\Repository\StudyGroupRepositoryInterface;
30
use App\Repository\TuitionRepositoryInterface;
31
use App\Section\SectionResolverInterface;
32
use App\Security\Voter\ExcuseNoteVoter;
33
use App\Security\Voter\StudentAbsenceVoter;
34
use App\Settings\StudentAbsenceSettings;
35
use App\Settings\TimetableSettings;
36
use App\Sorting\AppointmentStrategy;
37
use App\Sorting\ExamDateLessonStrategy;
38
use App\Sorting\Sorter;
39
use App\Sorting\StudentAbsenceTuitionGroupStrategy;
40
use App\Sorting\StudyGroupStrategy;
41
use App\StudentAbsence\ApprovalHelper;
42
use App\Timetable\TimetableTimeHelper;
43
use App\View\Filter\GradeFilter;
44
use App\View\Filter\GradeFilterView;
45
use App\View\Filter\SectionFilter;
46
use App\View\Filter\StudentAbsenceTypeFilter;
47
use App\View\Filter\StudentFilter;
48
use App\View\Filter\TeacherFilter;
49
use League\Flysystem\FilesystemOperator;
50
use Mimey\MimeTypes;
51
use SchulIT\CommonBundle\Form\ConfirmType;
52
use SchulIT\CommonBundle\Helper\DateHelper;
53
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
54
use Symfony\Component\HttpFoundation\Request;
55
use Symfony\Component\HttpFoundation\Response;
56
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
57
use Symfony\Component\Routing\Annotation\Route;
58
59
#[Route(path: '/absence/students')]
60
#[Security("is_granted('ROLE_STUDENT_ABSENCE_CREATOR') or is_granted('ROLE_STUDENT_ABSENCE_VIEWER') or is_granted('new-absence')")]
61
class StudentAbsenceController extends AbstractController {
62
63
    public const ITEMS_PER_PAGE = 25;
64
65
    private const CSRF_TOKEN_ID = 'student_absence_approval';
66
67
    use DateTimeHelperTrait;
68
69
    #[Route(path: '/add', name: 'add_student_absence')]
70
    public function add(Request $request, StudentAbsenceSettings $settings,
71
                        StudentAbsenceRepositoryInterface $repository, StudentRepositoryInterface $studentRepository,
72
                        TimetableTimeHelper $timeHelper, TimetableSettings $timetableSettings, DateHelper $dateHelper): Response {
73
        $this->denyAccessUnlessGranted(StudentAbsenceVoter::New);
74
75
        if($settings->isEnabled() !== true) {
76
            throw new NotFoundHttpException();
77
        }
78
79
        $students = [ ];
0 ignored issues
show
Unused Code introduced by
The assignment to $students is dead and can be removed.
Loading history...
80
81
        $note = new StudentAbsence();
82
        $note->setFrom($timeHelper->getLessonDateForDateTime($this->getTodayOrNextDay($dateHelper, $settings->getNextDayThresholdTime())));
83
        $note->setUntil(new DateLesson());
84
        $note->getUntil()->setLesson($timetableSettings->getMaxLessons());
85
86
        $form = $this->createForm(StudentAbsenceType::class, $note);
87
        $form->handleRequest($request);
88
89
        if($form->isSubmitted() && $form->isValid()) {
90
            $repository->persist($note);
91
92
            $this->addFlash('success', 'absences.students.add.success');
93
            return $this->redirectToRoute('student_absences');
94
        }
95
96
        return $this->render('absences/students/add.html.twig', [
97
            'form' => $form->createView(),
98
            'settings' => $settings
99
        ]);
100
    }
101
102
    #[Route(path: '/add_bulk', name: 'add_student_absence_bulk')]
103
    public function addBulk(Request $request, StudentAbsenceSettings $settings, SectionResolverInterface $sectionResolver,
104
                            StudentAbsenceRepositoryInterface $repository, StudyGroupRepositoryInterface $studyGroupRepository,
105
                            TimetableTimeHelper $timeHelper, TimetableSettings $timetableSettings, DateHelper $dateHelper,
106
                            Sorter $sorter, StudyGroupStringConverter $studyGroupStringConverter): Response {
107
        $this->denyAccessUnlessGranted(StudentAbsenceVoter::Bulk);
108
109
        if($settings->isEnabled() !== true) {
110
            throw new NotFoundHttpException();
111
        }
112
113
        $students = [ ];
0 ignored issues
show
Unused Code introduced by
The assignment to $students is dead and can be removed.
Loading history...
114
115
        $note = new BulkStudentAbsence();
116
        $note->setFrom($timeHelper->getLessonDateForDateTime($this->getTodayOrNextDay($dateHelper, $settings->getNextDayThresholdTime())));
117
        $note->setUntil(new DateLesson());
118
        $note->getUntil()->setLesson($timetableSettings->getMaxLessons());
119
120
        $form = $this->createForm(StudentAbsenceBulkType::class, $note);
121
        $form->handleRequest($request);
122
123
        if($form->isSubmitted() && $form->isValid()) {
124
            // Create absence for each student
125
            /** @var Student $student */
126
            foreach($note->getStudents() as $student) {
127
                $studentAbsence = (new StudentAbsence())
128
                    ->setStudent($student)
129
                    ->setFrom($note->getFrom())
130
                    ->setUntil($note->getUntil())
131
                    ->setType($note->getType())
132
                    ->setMessage($note->getMessage())
133
                    ->setEmail($note->getEmail())
134
                    ->setPhone($note->getPhone());
135
136
                $repository->persist($studentAbsence);
137
            }
138
139
            $this->addFlash('success', 'absences.students.bulk.success');
140
            return $this->redirectToRoute('student_absences');
141
        }
142
143
        $studyGroupsData = [ ];
144
145
        $studyGroups = $studyGroupRepository->findAllBySection($sectionResolver->getCurrentSection());
0 ignored issues
show
Bug introduced by
It seems like $sectionResolver->getCurrentSection() can also be of type null; however, parameter $section of App\Repository\StudyGrou...ace::findAllBySection() does only seem to accept App\Entity\Section, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

145
        $studyGroups = $studyGroupRepository->findAllBySection(/** @scrutinizer ignore-type */ $sectionResolver->getCurrentSection());
Loading history...
146
        $sorter->sort($studyGroups, StudyGroupStrategy::class);
147
148
        foreach($studyGroups as $studyGroup) {
149
            $studyGroupsData[] = [
150
                'label' => $studyGroupStringConverter->convert($studyGroup, false, true),
151
                'students' => $studyGroup->getMemberships()->map(fn(StudyGroupMembership $m) => $m->getStudent()->getId())->toArray()
152
            ];
153
        }
154
155
        return $this->render('absences/students/add_bulk.html.twig', [
156
            'form' => $form->createView(),
157
            'settings' => $settings,
158
            'studyGroupsData' => $studyGroupsData
159
        ]);
160
    }
161
162
    #[Route(path: '/{uuid}/edit', name: 'edit_student_absence')]
163
    public function edit(StudentAbsence $absence, Request $request, StudentAbsenceSettings $settings, StudentAbsenceRepositoryInterface $repository): Response {
164
        $this->denyAccessUnlessGranted(StudentAbsenceVoter::New);
165
166
        if($settings->isEnabled() !== true) {
167
            throw new NotFoundHttpException();
168
        }
169
170
        $form = $this->createForm(StudentAbsenceType::class, $absence);
171
        $form->handleRequest($request);
172
173
        if($form->isSubmitted() && $form->isValid()) {
174
            $repository->persist($absence);
175
176
            $this->addFlash('success', 'absences.students.edit.success');
177
            return $this->redirectToRoute('student_absences');
178
        }
179
180
        return $this->render('absences/students/edit.html.twig', [
181
            'form' => $form->createView(),
182
            'settings' => $settings
183
        ]);
184
    }
185
186
    #[Route(path: '', name: 'student_absences')]
187
    public function index(SectionFilter $sectionFilter, GradeFilter $gradeFilter, TeacherFilter $teacherFilter, StudentFilter $studentFilter,
188
                          StudentAbsenceTypeFilter $typeFilter, Request $request,
189
                          StudentAbsenceRepositoryInterface $absenceRepository, TuitionRepositoryInterface $tuitionRepository,
190
                          SectionResolverInterface $sectionResolver, DateHelper $dateHelper, Sorter $sorter, StudentAbsenceSettings $settings): Response {
191
        $this->denyAccessUnlessGranted(StudentAbsenceVoter::CanViewAny);
192
193
        if($settings->isEnabled() !== true) {
194
            throw new NotFoundHttpException();
195
        }
196
197
        /** @var User $user */
198
        $user = $this->getUser();
199
200
        $sectionFilterView = $sectionFilter->handle($request->query->get('section'));
201
        $gradeFilterView = $gradeFilter->handle($request->query->get('grade', null), $sectionFilterView->getCurrentSection(), $user);
202
203
        if($user->isStudentOrParent()) {
204
            $gradeFilterView = new GradeFilterView([], null);
205
        }
206
207
        $studentFilterView = $studentFilter->handle($request->query->get('student', null), $sectionFilterView->getCurrentSection(), $user);
208
        $teacherFilterView = $teacherFilter->handle($request->query->get('teacher', null), $sectionFilterView->getCurrentSection(), $user, $request->query->get('teacher') !== '✗' && $gradeFilterView->getCurrentGrade() === null && $studentFilterView->getCurrentStudent() === null);
209
        $typeFilterView = $typeFilter->handle($request->query->get('type'));
210
211
        $groups = [ ];
212
213
        $page = $request->query->getInt('page', 1);
214
215
        $paginator = null;
216
217
        if($teacherFilterView->getCurrentTeacher() !== null && $sectionFilterView->getCurrentSection() !== null) {
218
            $tuitions = $tuitionRepository->findAllByTeacher($teacherFilterView->getCurrentTeacher(), $sectionFilterView->getCurrentSection());
219
220
            foreach($tuitions as $tuition) {
221
                $students = $tuition->getStudyGroup()->getMemberships()->map(fn(StudyGroupMembership $membership) => $membership->getStudent())->toArray();
222
223
                $absences = $absenceRepository->findByStudents($students, $typeFilterView->getCurrentType(), $dateHelper->getToday());
224
225
                if(count($absences) > 0) {
226
                    $group = new StudentAbsenceTuitionGroup($tuition);
227
228
                    foreach($absences as $note) {
229
                        if($this->isGranted(StudentAbsenceVoter::View, $note)) {
230
                            $group->addItem($note);
231
                        }
232
                    }
233
234
                    $groups[] = $group;
235
                }
236
            }
237
238
            $sorter->sort($groups, StudentAbsenceTuitionGroupStrategy::class);
239
240
        } else if($gradeFilterView->getCurrentGrade() !== null) {
241
            $paginator = $absenceRepository->getGradePaginator($gradeFilterView->getCurrentGrade(), $sectionFilterView->getCurrentSection(), $typeFilterView->getCurrentType(), self::ITEMS_PER_PAGE, $page);
0 ignored issues
show
Bug introduced by
It seems like $sectionFilterView->getCurrentSection() can also be of type null; however, parameter $section of App\Repository\StudentAb...ce::getGradePaginator() does only seem to accept App\Entity\Section, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

241
            $paginator = $absenceRepository->getGradePaginator($gradeFilterView->getCurrentGrade(), /** @scrutinizer ignore-type */ $sectionFilterView->getCurrentSection(), $typeFilterView->getCurrentType(), self::ITEMS_PER_PAGE, $page);
Loading history...
242
243
            if($paginator->count() > 0) {
244
                $group = new StudentAbsenceGradeGroup($gradeFilterView->getCurrentGrade());
245
246
                /** @var StudentAbsence $note */
247
                foreach ($paginator as $note) {
248
                    if($this->isGranted(StudentAbsenceVoter::View, $note)) {
249
                        $group->addItem($note);
250
                    }
251
                }
252
253
                $groups[] = $group;
254
            }
255
        } else if($studentFilterView->getCurrentStudent() !== null) {
256
            $paginator = $absenceRepository->getStudentPaginator($studentFilterView->getCurrentStudent(), $typeFilterView->getCurrentType(), self::ITEMS_PER_PAGE, $page);
257
258
            if($paginator->count() > 0) {
259
                $group = new StudentAbsenceStudentGroup($studentFilterView->getCurrentStudent());
260
261
                /** @var StudentAbsence $note */
262
                foreach ($paginator as $note) {
263
                    if($this->isGranted(StudentAbsenceVoter::View, $note)) {
264
                        $group->addItem($note);
265
                    }
266
                }
267
268
                $groups[] = $group;
269
            }
270
        } else {
271
            $paginator = $absenceRepository->getPaginator($typeFilterView->getCurrentType(), self::ITEMS_PER_PAGE, $page);
272
273
            if($paginator->count() > 0) {
274
                $group = new StudentAbsenceGenericGroup();
275
276
                /** @var StudentAbsence $note */
277
                foreach ($paginator as $note) {
278
                    if($this->isGranted(StudentAbsenceVoter::View, $note)) {
279
                        $group->addItem($note);
280
                    }
281
                }
282
283
                $groups[] = $group;
284
            }
285
        }
286
287
        $pages = 0;
288
        if($paginator !== null) {
289
            $pages = ceil((double)$paginator->count() / self::ITEMS_PER_PAGE);
290
        }
291
292
        return $this->render('absences/students/index.html.twig', [
293
            'groups' => $groups,
294
            'sectionFilter' => $sectionFilterView,
295
            'gradeFilter' => $gradeFilterView,
296
            'teacherFilter' => $teacherFilterView,
297
            'studentFilter' => $studentFilterView,
298
            'typeFilter' => $typeFilterView,
299
            'today' => $dateHelper->getToday(),
300
            'section' => $sectionResolver->getCurrentSection(),
301
            'pages' => $pages,
302
            'page' => $page,
303
            'isTeacherX' => $request->query->get('teacher') === '✗'
304
        ]);
305
    }
306
307
    #[Route(path: '/{uuid}', name: 'show_student_absence')]
308
    public function show(StudentAbsence $absence, StudentAbsenceSettings $settings, Request $request, StudentAbsenceRepositoryInterface $repository, ExamRepositoryInterface $examRepository,
309
                         AppointmentRepositoryInterface $appointmentRepository, Sorter $sorter): Response {
310
        $this->denyAccessUnlessGranted(StudentAbsenceVoter::View, $absence);
311
312
        if($settings->isEnabled() !== true) {
313
            throw new NotFoundHttpException();
314
        }
315
316
        $message = new StudentAbsenceMessage();
317
        $message->setAbsence($absence);
0 ignored issues
show
Bug introduced by
It seems like $absence can also be of type null; however, parameter $absence of App\Entity\StudentAbsenceMessage::setAbsence() does only seem to accept App\Entity\StudentAbsence, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

317
        $message->setAbsence(/** @scrutinizer ignore-type */ $absence);
Loading history...
318
        $form = $this->createForm(StudentAbsenceMessageType::class, $message);
319
        $form->handleRequest($request);
320
321
        if($form->isSubmitted() && $form->isValid()) {
322
            $absence->addMessage($message);
0 ignored issues
show
Bug introduced by
The method addMessage() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

322
            $absence->/** @scrutinizer ignore-call */ 
323
                      addMessage($message);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
323
            $repository->persist($absence);
0 ignored issues
show
Bug introduced by
It seems like $absence can also be of type null; however, parameter $note of App\Repository\StudentAb...oryInterface::persist() does only seem to accept App\Entity\StudentAbsence, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

323
            $repository->persist(/** @scrutinizer ignore-type */ $absence);
Loading history...
324
325
            $this->addFlash('success', 'absences.students.comment.success');
326
            return $this->redirectToRoute('show_student_absence', [
327
                'uuid' => $absence->getUuid()
328
            ]);
329
        }
330
331
        $exams = array_filter(
332
            $examRepository->findAllByStudents([$absence->getStudent()]),
333
            function(Exam $exam) use ($absence) {
334
                for($lessonNumber = $exam->getLessonStart(); $lessonNumber <= $exam->getLessonEnd(); $lessonNumber++) {
335
                    if((new DateLesson())->setDate(clone $exam->getDate())->setLesson($lessonNumber)->isBetween($absence->getFrom(), $absence->getUntil())) {
336
                        return true;
337
                    }
338
                }
339
340
                return false;
341
            }
342
        );
343
        $sorter->sort($exams, ExamDateLessonStrategy::class);
344
345
        $appointments = $appointmentRepository->findAllForStudentsAndTime([$absence->getStudent()], $absence->getFrom()->getDate(), $absence->getUntil()->getDate());
346
        $sorter->sort($appointments, AppointmentStrategy::class);
347
348
        return $this->render('absences/students/show.html.twig', [
349
            'absence' => $absence,
350
            'token_id' => self::CSRF_TOKEN_ID,
351
            'form' => $form->createView(),
352
            'exams' => $exams,
353
            'appointments' => $appointments
354
        ]);
355
    }
356
357
    #[Route(path: '/{uuid}/excuse_note', name: 'add_excuse_note_from_absence')]
358
    public function createExcuseNote(StudentAbsence $absence, Request $request, ExcuseNoteRepositoryInterface $excuseNoteRepository) {
359
        $this->denyAccessUnlessGranted(ExcuseNoteVoter::New);
360
361
        /** @var User $user */
362
        $user = $this->getUser();
363
364
        if($this->isCsrfTokenValid('excuse_note', $request->request->get('_csrf_token')) !== true) {
365
            $this->addFlash('error', 'CSRF token invalid.');
366
        } else if($absence->getType()->isAlwaysExcused()) {
367
            $this->addFlash('success', 'absences.students.show.create_excuse_note.not_necessary');
368
        } else {
369
            $excuseNote = (new ExcuseNote())
370
                ->setStudent($absence->getStudent())
371
                ->setFrom($absence->getFrom())
372
                ->setUntil($absence->getUntil())
373
                ->setExcusedBy($user->getTeacher())
374
                ->setComment('student_absence:' . $absence->getUuid()->toString());
375
376
            $excuseNoteRepository->persist($excuseNote);
377
            $this->addFlash('success', 'book.excuse_note.add.success');
378
        }
379
380
        return $this->redirectToRoute('show_student_absence', [
381
            'uuid' => $absence->getUuid()
382
        ]);
383
    }
384
385
    #[Route(path: '/{uuid}/approve', name: 'approve_student_absence')]
386
    public function approve(StudentAbsence $absence, Request $request, ApprovalHelper $approvalHelper): Response {
387
        $this->denyAccessUnlessGranted(StudentAbsenceVoter::Approve, $absence);
388
389
        /** @var User $user */
390
        $user = $this->getUser();
391
392
        if(!$this->isCsrfTokenValid(self::CSRF_TOKEN_ID, $request->query->get('_csrf_token'))) {
393
            $this->addFlash('error', 'CSRF token invalid.');
394
        } else {
395
            $approvalHelper->setApprovalStatus($absence, true, $user);
0 ignored issues
show
Bug introduced by
It seems like $absence can also be of type null; however, parameter $absence of App\StudentAbsence\Appro...er::setApprovalStatus() does only seem to accept App\Entity\StudentAbsence, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

395
            $approvalHelper->setApprovalStatus(/** @scrutinizer ignore-type */ $absence, true, $user);
Loading history...
396
            $this->addFlash('success', 'absences.students.approval.success');
397
        }
398
399
        return $this->redirectToRoute('show_student_absence', [
400
            'uuid' => $absence->getUuid()
401
        ]);
402
    }
403
404
    #[Route(path: '/{uuid}/deny', name: 'deny_student_absence')]
405
    public function deny(StudentAbsence $absence, Request $request, ApprovalHelper $approvalHelper): Response {
406
        $this->denyAccessUnlessGranted(StudentAbsenceVoter::Deny, $absence);
407
408
        /** @var User $user */
409
        $user = $this->getUser();
410
411
        if(!$this->isCsrfTokenValid(self::CSRF_TOKEN_ID, $request->query->get('_csrf_token'))) {
412
            $this->addFlash('error', 'CSRF token invalid.');
413
        } else {
414
            $approvalHelper->setApprovalStatus($absence, false, $user);
0 ignored issues
show
Bug introduced by
It seems like $absence can also be of type null; however, parameter $absence of App\StudentAbsence\Appro...er::setApprovalStatus() does only seem to accept App\Entity\StudentAbsence, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

414
            $approvalHelper->setApprovalStatus(/** @scrutinizer ignore-type */ $absence, false, $user);
Loading history...
415
            $this->addFlash('success', 'absences.students.approval.success');
416
        }
417
418
        return $this->redirectToRoute('show_student_absence', [
419
            'uuid' => $absence->getUuid()
420
        ]);
421
    }
422
423
    #[Route(path: '/attachments/{uuid}', name: 'download_student_absence_attachment', priority: 10)]
424
    public function downloadAttachment(StudentAbsenceAttachment $attachment, FilesystemOperator $studentAbsencesFilesystem, MimeTypes $mimeTypes, StudentAbsenceSettings $settings): Response {
425
        $this->denyAccessUnlessGranted(StudentAbsenceVoter::View, $attachment->getAbsence());
426
427
        if($settings->isEnabled() !== true) {
428
            throw new NotFoundHttpException();
429
        }
430
431
        if($studentAbsencesFilesystem->fileExists($attachment->getPath()) !== true) {
432
            throw new NotFoundHttpException();
433
        }
434
435
        $extension = pathinfo($attachment->getFilename(), PATHINFO_EXTENSION);
436
437
        return new FlysystemFileResponse(
438
            $studentAbsencesFilesystem,
439
            $attachment->getPath(),
440
            $attachment->getFilename(),
441
            $mimeTypes->getMimeType($extension)
442
        );
443
    }
444
445
    #[Route('/{uuid}/remove', name: 'remove_student_absence')]
446
    public function remove(StudentAbsence $absence, Request $request, StudentAbsenceRepositoryInterface $repository): Response {
447
        $this->denyAccessUnlessGranted(StudentAbsenceVoter::Remove, $absence);
448
449
        $form = $this->createForm(ConfirmType::class, null, [
450
            'message' => 'absences.students.remove.confirm'
451
        ]);
452
        $form->handleRequest($request);
453
454
        if($form->isSubmitted() && $form->isValid()) {
455
            $repository->remove($absence);
0 ignored issues
show
Bug introduced by
It seems like $absence can also be of type null; however, parameter $note of App\Repository\StudentAb...toryInterface::remove() does only seem to accept App\Entity\StudentAbsence, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

455
            $repository->remove(/** @scrutinizer ignore-type */ $absence);
Loading history...
456
457
            $this->addFlash('success', 'absences.students.remove.success');
458
459
            return $this->redirectToRoute('student_absences');
460
        }
461
462
        return $this->render('absences/students/remove.html.twig', [
463
            'form' => $form->createView(),
464
            'absence' => $absence
465
        ]);
466
    }
467
}