SuggestionResolver::resolve()   F
last analyzed

Complexity

Conditions 23
Paths 13824

Size

Total Lines 107
Code Lines 62

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 23
eloc 62
c 2
b 0
f 0
nc 13824
nop 3
dl 0
loc 107
rs 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace App\Book\AbsenceSuggestion;
4
5
use App\Dashboard\Absence\AbsenceResolver;
6
use App\Dashboard\AbsentExamStudent;
7
use App\Dashboard\AbsentStudent;
8
use App\Dashboard\AbsentStudentWithAbsenceNote;
9
use App\Entity\LessonAttendanceExcuseStatus;
10
use App\Entity\Student as StudentEntity;
11
use App\Entity\StudyGroupMembership;
12
use App\Entity\Tuition;
13
use App\Repository\ExcuseNoteRepositoryInterface;
14
use App\Repository\LessonAttendanceRepositoryInterface;
15
use App\Response\Book\AbsenceSuggestion;
16
use App\Response\Book\Student;
17
use DateTime;
18
19
class SuggestionResolver {
20
    public function __construct(private readonly AbsenceResolver $absenceResolver, private readonly LessonAttendanceRepositoryInterface $attendanceRepository,
21
                                private readonly ExcuseNoteRepositoryInterface $excuseNoteRepository) {
22
23
    }
24
25
    /**
26
     * @param Tuition $tuition
27
     * @param DateTime $date
28
     * @param int $lesson
29
     * @return AbsenceSuggestion[]
30
     */
31
    public function resolve(Tuition $tuition, DateTime $date, int $lesson): array {
32
        $students = $tuition->getStudyGroup()->getMemberships()->map(fn(StudyGroupMembership $membership) => $membership->getStudent())->toArray();
33
34
        $suggestions = [ ];
35
36
        $absences = $this->absenceResolver->resolve($date, $lesson, $students);
37
38
        foreach($this->filterAbsencesWithAreExcused($absences) as $absentStudent) {
39
            if(array_key_exists($absentStudent->getStudent()->getId(), $suggestions)) {
40
                continue; // prevent duplicates
41
            }
42
43
            $excuseStatus = ($absentStudent instanceof AbsentStudentWithAbsenceNote && $absentStudent->getAbsence()->getType()->isAlwaysExcused()) ? LessonAttendanceExcuseStatus::Excused : LessonAttendanceExcuseStatus::NotSet;
44
45
            $suggestions[$absentStudent->getStudent()->getId()] = new AbsenceSuggestion(
46
                $this->getStudent($absentStudent->getStudent()),
47
                $absentStudent->getReason()->value,
48
                $absentStudent->getAbsence()->getType()->getName(),
49
                $absentStudent->getAbsence()->getType()->isTypeWithZeroAbsenceLessons(),
50
                $excuseStatus
51
            );
52
        }
53
54
        foreach($this->filterAbsencesWithoutZeroAbsenceLessons($absences) as $absentStudent) {
55
            if(array_key_exists($absentStudent->getStudent()->getId(), $suggestions)) {
56
                continue; // prevent duplicates
57
            }
58
59
            $excuseStatus = ($absentStudent instanceof AbsentStudentWithAbsenceNote && $absentStudent->getAbsence()->getType()->isAlwaysExcused()) ? LessonAttendanceExcuseStatus::Excused : LessonAttendanceExcuseStatus::NotSet;
60
61
            $suggestions[$absentStudent->getStudent()->getId()] = new AbsenceSuggestion(
62
                $this->getStudent($absentStudent->getStudent()),
63
                $absentStudent->getReason()->value,
64
                $absentStudent->getAbsence()->getType()->getName(),
65
                false,
66
                $excuseStatus
67
            );
68
        }
69
70
        // Absence in previous lesson
71
        foreach($this->attendanceRepository->findAbsentByStudentsAndDate($students, $date) as $attendance) {
72
            if(array_key_exists($attendance->getStudent()->getId(), $suggestions)) {
73
                continue; // prevent duplicates
74
            }
75
76
            if($attendance->getEntry()->getLessonEnd() === $lesson - 1) {
77
                $suggestions[$attendance->getStudent()->getId()] = new AbsenceSuggestion(
78
                    $this->getStudent($attendance->getStudent()),
0 ignored issues
show
Bug introduced by
It seems like $attendance->getStudent() can also be of type null; however, parameter $entity of App\Book\AbsenceSuggesti...nResolver::getStudent() does only seem to accept App\Entity\Student, 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

78
                    $this->getStudent(/** @scrutinizer ignore-type */ $attendance->getStudent()),
Loading history...
79
                    'absent_before'
80
                );
81
            }
82
        }
83
84
        // Exam
85
        foreach($this->filterAbsencesWithExam($absences) as $absentExamStudent) {
86
            if(array_key_exists($absentExamStudent->getStudent()->getId(), $suggestions)) {
87
                continue; // prevent duplicates
88
            }
89
90
            if($absentExamStudent->getExam()->getTuitions()->count() === 1 && $absentExamStudent->getExam()->getTuitions()->first() === $tuition) {
91
                continue; // do not show exam of current tuition
92
            }
93
94
            $suggestions[$absentExamStudent->getStudent()->getId()] = new AbsenceSuggestion(
95
                $this->getStudent($absentExamStudent->getStudent()),
96
                $absentExamStudent->getReason()->value,
97
                null,
98
                true,
99
                LessonAttendanceExcuseStatus::Excused
100
            );
101
        }
102
103
        // Absences with zero absent lessons
104
        foreach($this->filterAbsencesWithZeroAbsenceLessons($absences) as $absentStudent) {
105
            if(array_key_exists($absentStudent->getStudent()->getId(), $suggestions)) {
106
                continue; // prevent duplicates
107
            }
108
109
            $excuseStatus = ($absentStudent instanceof AbsentStudentWithAbsenceNote && $absentStudent->getAbsence()->getType()->isAlwaysExcused()) ? LessonAttendanceExcuseStatus::Excused : LessonAttendanceExcuseStatus::NotSet;
110
111
            $suggestions[$absentStudent->getStudent()->getId()] = new AbsenceSuggestion(
112
                $this->getStudent($absentStudent->getStudent()),
113
                $absentStudent->getReason()->value,
114
                $absentStudent->getAbsence()->getType()->getName(),
115
                true,
116
                $excuseStatus
117
            );
118
        }
119
120
        // Excuse
121
        foreach($this->excuseNoteRepository->findByStudentsAndDate($students, $date) as $note) {
122
            if(array_key_exists($note->getStudent()->getId(), $suggestions)) {
123
                continue; // prevent duplicates
124
            }
125
126
            if($note->appliesToLesson($date, $lesson)) {
127
                $suggestions[$note->getStudent()->getId()] = new AbsenceSuggestion(
128
                    $this->getStudent($note->getStudent()),
129
                    'excuse',
130
                    null,
131
                    false,
132
                    LessonAttendanceExcuseStatus::Excused
133
                );
134
            }
135
        }
136
137
        return array_values($suggestions);
138
    }
139
140
    /**
141
     * @param AbsentStudent[] $students
142
     * @return AbsentStudentWithAbsenceNote[]
143
     */
144
    private function filterAbsencesWithoutZeroAbsenceLessons(array $students): array {
145
        return array_filter($students, fn(AbsentStudent $absentStudent) => ($absentStudent instanceof AbsentStudentWithAbsenceNote && !$absentStudent->getAbsence()->getType()->isTypeWithZeroAbsenceLessons()));
146
    }
147
148
    /**
149
     * @param AbsentStudent[] $students
150
     * @return AbsentExamStudent[]
151
     */
152
    private function filterAbsencesWithExam(array $students): array {
153
        return array_filter($students, fn(AbsentStudent $absentStudent) => $absentStudent instanceof AbsentExamStudent);
154
    }
155
156
    /**
157
     * @param AbsentStudent[] $students
158
     * @return AbsentStudentWithAbsenceNote[]
159
     */
160
    private function filterAbsencesWithZeroAbsenceLessons(array $students): array {
161
        return array_filter($students, fn(AbsentStudent $absentStudent) => ($absentStudent instanceof AbsentStudentWithAbsenceNote && $absentStudent->getAbsence()->getType()->isTypeWithZeroAbsenceLessons()));
162
    }
163
164
    private function filterAbsencesWithAreExcused(array $students): array {
165
        return array_filter($students, fn(AbsentStudent $absentStudent) => $absentStudent instanceof AbsentStudentWithAbsenceNote && $absentStudent->getAbsence()->getType()->isAlwaysExcused());
166
    }
167
168
    private function getStudent(StudentEntity $entity): Student {
169
        return new Student($entity->getUuid()->toString(), $entity->getFirstname(), $entity->getLastname());
0 ignored issues
show
Bug introduced by
It seems like $entity->getLastname() can also be of type null; however, parameter $lastname of App\Response\Book\Student::__construct() does only seem to accept string, 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

169
        return new Student($entity->getUuid()->toString(), $entity->getFirstname(), /** @scrutinizer ignore-type */ $entity->getLastname());
Loading history...
Bug introduced by
It seems like $entity->getFirstname() can also be of type null; however, parameter $firstname of App\Response\Book\Student::__construct() does only seem to accept string, 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

169
        return new Student($entity->getUuid()->toString(), /** @scrutinizer ignore-type */ $entity->getFirstname(), $entity->getLastname());
Loading history...
170
    }
171
}