Passed
Push — master ( 2daeaa...eba4a8 )
by Marcel
16:01
created

DashboardViewHelper::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 0
c 0
b 0
f 0
nc 1
nop 28
dl 0
loc 9
rs 10
ccs 0
cts 0
cp 0
crap 2

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace App\Dashboard;
4
5
use App\Dashboard\Absence\AbsenceResolver;
6
use App\Dashboard\Absence\ExamStudentsResolver;
7
use App\Entity\Appointment;
8
use App\Entity\Exam;
9
use App\Entity\ExamSupervision;
10
use App\Entity\FreeTimespan;
11
use App\Entity\Grade;
12
use App\Entity\GradeTeacher;
13
use App\Entity\Message;
14
use App\Entity\MessageScope;
15
use App\Entity\ResourceReservation;
16
use App\Entity\Room;
17
use App\Entity\Student;
18
use App\Entity\StudyGroup;
19
use App\Entity\StudyGroupMembership;
20
use App\Entity\Substitution;
21
use App\Entity\Teacher;
22
use App\Entity\TimetableLesson;
23
use App\Entity\TimetableSupervision;
24
use App\Entity\Tuition;
25
use App\Entity\User;
26
use App\Entity\UserType;
27
use App\Grouping\AbsentStudentGroup;
28
use App\Grouping\AbsentStudentStrategy as AbstentStudentGroupStrategy;
29
use App\Grouping\Grouper;
30
use App\Repository\AbsenceRepositoryInterface;
31
use App\Repository\AppointmentRepositoryInterface;
32
use App\Repository\ExamRepositoryInterface;
33
use App\Repository\FreeTimespanRepositoryInterface;
34
use App\Repository\InfotextRepositoryInterface;
35
use App\Repository\LessonEntryRepositoryInterface;
36
use App\Repository\MessageRepositoryInterface;
37
use App\Repository\ResourceReservationRepositoryInterface;
38
use App\Repository\StudentRepositoryInterface;
39
use App\Repository\StudyGroupRepositoryInterface;
40
use App\Repository\SubstitutionRepositoryInterface;
41
use App\Repository\TeacherAbsenceLessonRepositoryInterface;
42
use App\Repository\TeacherRepositoryInterface;
43
use App\Repository\TimetableLessonRepositoryInterface;
44
use App\Repository\TimetableSupervisionRepositoryInterface;
45
use App\Repository\TuitionRepositoryInterface;
46
use App\Section\SectionResolverInterface;
47
use App\Security\Voter\AbsenceVoter;
48
use App\Security\Voter\AppointmentVoter;
49
use App\Security\Voter\ExamVoter;
50
use App\Security\Voter\MessageVoter;
51
use App\Security\Voter\ResourceReservationVoter;
52
use App\Security\Voter\SubstitutionVoter;
53
use App\Settings\BookSettings;
54
use App\Settings\DashboardSettings;
55
use App\Settings\TimetableSettings;
56
use App\Sorting\AbsentStudentStrategy;
57
use App\Sorting\AbsentStudyGroupStrategy;
58
use App\Sorting\AbsentTeacherStrategy;
59
use App\Sorting\MessageStrategy;
60
use App\Sorting\Sorter;
61
use App\Timetable\TimetableTimeHelper;
62
use App\Utils\ArrayUtils;
63
use App\Utils\StudyGroupHelper;
64
use DateTime;
65
use SchulIT\CommonBundle\Helper\DateHelper;
66
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
67
use Symfony\Component\Validator\Validator\ValidatorInterface;
68
69
class DashboardViewHelper {
70
71
    public function __construct(private SubstitutionRepositoryInterface $substitutionRepository, private ExamRepositoryInterface $examRepository, private TimetableLessonRepositoryInterface $timetableRepository,
72
                                private TimetableSupervisionRepositoryInterface $supervisionRepository, private MessageRepositoryInterface $messageRepository, private InfotextRepositoryInterface $infotextRepository,
73
                                private AbsenceRepositoryInterface $absenceRepository, private StudyGroupRepositoryInterface $studyGroupRepository, private AppointmentRepositoryInterface $appointmentRepository,
74
                                private ResourceReservationRepositoryInterface $roomReservationRepository, private FreeTimespanRepositoryInterface $freeTimespanRepository, private StudyGroupHelper $studyGroupHelper,
75
                                private TimetableTimeHelper $timetableTimeHelper, private Sorter $sorter, private Grouper $grouper, private TimetableSettings $timetableSettings, private DashboardSettings $dashboardSettings,
76
                                private AuthorizationCheckerInterface $authorizationChecker, private ValidatorInterface $validator, private DateHelper $dateHelper, private AbsenceResolver $absenceResolver,
77
                                private SectionResolverInterface $sectionResolver, private readonly TuitionRepositoryInterface $tuitionRepository, private readonly TeacherAbsenceLessonRepositoryInterface $absenceLessonRepository,
78
                                private readonly BookSettings $bookSettings, private readonly LessonEntryRepositoryInterface $lessonEntryRepository, private readonly TeacherRepositoryInterface $teacherRepository, private readonly StudentRepositoryInterface $studentRepository)
79
    {
80
    }
81
82
    public function createViewForRoom(Room $room, DateTime $dateTime): DashboardView {
83
        $view = new DashboardView($dateTime);
84
85
        $this->addTimetableLessons($this->timetableRepository->findAllByRoom($dateTime, $dateTime, $room), $dateTime, $view, true);
86
        $this->addEmptyTimetableLessons($view, $this->timetableSettings->getMaxLessons());
87
88
        $this->addSubstitutions($this->substitutionRepository->findAllForRooms([ $room ], $dateTime), $view, true);
89
        $this->addExams($exams = $this->examRepository->findAllByRoomAndDate($room, $dateTime), $view, null, true);
90
        $this->addRoomReservations($this->roomReservationRepository->findAllByResourceAndDate($room, $dateTime), $view);
91
        $this->addFreeTimespans($this->freeTimespanRepository->findAllByDate($dateTime), $view);
92
        $this->setCurrentLesson($view);
93
94
        return $view;
95
    }
96
97
    public function createViewForTeacher(Teacher $teacher, DateTime $dateTime, bool $includeGradeMessages = false): DashboardView {
98
        $view = new DashboardView($dateTime);
99
100
        $start = $this->timetableSettings->getStartDate(UserType::Teacher);
101
        $end = $this->timetableSettings->getEndDate(UserType::Teacher);
102
103
        if($start !== null && $end !== null && $this->dateHelper->isBetween($dateTime, $start, $end)) {
104
            $this->addTimetableLessons($this->timetableRepository->findAllByTeacher($dateTime, $dateTime, $teacher), $dateTime, $view, true);
105
            $this->addSupervisions($this->supervisionRepository->findAllByTeacher($dateTime, $dateTime, $teacher), $view);
106
            $this->addEmptyTimetableLessons($view, $this->timetableSettings->getMaxLessons());
107
        }
108
109
        $messages = [ ];
110
111
        $section = $this->sectionResolver->getSectionForDate($dateTime);
112
113
        if($includeGradeMessages === true && $section !== null) {
114
            /** @var GradeTeacher $gradeTeacher */
115
            foreach($teacher->getGrades() as $gradeTeacher) {
116
                $studyGroups = $this->studyGroupRepository->findAllByGrades($gradeTeacher->getGrade(), $section);
117
                $messages = array_merge($messages, $this->messageRepository->findBy(MessageScope::Messages, UserType::Student, $dateTime, $studyGroups));
118
            }
119
        }
120
121
        $messages = array_merge($messages, $this->messageRepository->findBy(MessageScope::Messages, UserType::Teacher, $dateTime));
122
123
        $messages = ArrayUtils::createArrayWithKeys($messages, fn(Message $message) => $message->getId());
124
125
        $this->addMessages($messages, $view);
126
127
        $this->addSubstitutions($this->substitutionRepository->findAllForTeacher($teacher, $dateTime), $view, true);
128
        $this->addExams($this->examRepository->findAllByTeacher($teacher, $dateTime, true), $view, $teacher, true);
129
        $this->addInfotexts($dateTime, $view);
130
        $this->addAbsentStudyGroup($this->absenceRepository->findAllStudyGroups($dateTime), $view);
131
        $this->addAbsentTeachers($this->absenceRepository->findAllTeachers($dateTime), $view);
132
        $this->addAppointments($this->appointmentRepository->findAllForTeacher($teacher, $dateTime), $view);
133
        $this->addRoomReservations($this->roomReservationRepository->findAllByTeacherAndDate($teacher, $dateTime), $view);
134
        $this->addFreeTimespans($this->freeTimespanRepository->findAllByDate($dateTime), $view);
135
        $this->setCurrentLesson($view);
136
        $this->addBirthdays($view, $dateTime);
137
138
        return $view;
139
    }
140
141
    public function createViewForStudentOrParent(Student $student, DateTime $dateTime, UserType $userType): DashboardView {
142
        $view = new DashboardView($dateTime);
143
144
        $studyGroups = $this->studyGroupHelper->getStudyGroups([$student])->toArray();
145
146
        $start = $this->timetableSettings->getStartDate($userType);
147
        $end = $this->timetableSettings->getEndDate($userType);
148
149
        if($start !== null && $end !== null && $this->dateHelper->isBetween($dateTime, $start, $end)) {
150
            $this->addTimetableLessons($this->timetableRepository->findAllByStudent($dateTime, $dateTime, $student), $dateTime, $view, false);
151
            $this->addEmptyTimetableLessons($view, $this->timetableSettings->getMaxLessons());
152
        }
153
154
        $section = $this->sectionResolver->getSectionForDate($dateTime);
155
156
        $this->addMessages($this->messageRepository->findBy(MessageScope::Messages, $userType, $dateTime, $studyGroups), $view);
157
        $this->addSubstitutions($this->filterSubstitutionsByGrade($this->substitutionRepository->findAllForStudyGroups($studyGroups, $dateTime), $student->getGrade($section)), $view, false);
158
        $this->addExams($this->examRepository->findAllByStudents([$student], $dateTime, true), $view, null, false);
159
        $this->addInfotexts($dateTime, $view);
160
        $this->addAbsentStudyGroup($this->absenceRepository->findAllStudyGroups($dateTime), $view);
161
        $this->addAbsentTeachers($this->absenceRepository->findAllTeachers($dateTime), $view);
162
        $this->addAppointments($this->appointmentRepository->findAllForStudents([$student], $dateTime), $view);
163
        $this->addFreeTimespans($this->freeTimespanRepository->findAllByDate($dateTime), $view);
164
        $this->setCurrentLesson($view);
165
166
        $this->addExercises($view, $student, $dateTime);
167
168
        return $view;
169
    }
170
171
    public function createViewForUser(User $user, DateTime $dateTime): DashboardView {
172
        $view = new DashboardView($dateTime);
173
174
        $this->addMessages($this->messageRepository->findBy(MessageScope::Messages, $user->getUserType(), $dateTime), $view);
175
        $this->setCurrentLesson($view);
176
        $this->addBirthdays($view, $dateTime);
177
178
        return $view;
179
    }
180
181
    private function addBirthdays(DashboardView $view, DateTime $dateTime): DashboardView {
182
        foreach($this->teacherRepository->findAllByBirthday($dateTime) as $birthdayTeacher) {
183
            if($this->authorizationChecker->isGranted('ROLE_SHOW_BIRTHDAY', $birthdayTeacher)) {
184
                $view->addTeacherBirthday($birthdayTeacher);
185
            }
186
        }
187
188
        foreach($this->studentRepository->findAllByBirthday($dateTime) as $birthdayStudent) {
189
            if($this->authorizationChecker->isGranted('ROLE_SHOW_BIRTHDAY', $birthdayStudent)) {
190
                $view->addStudentBirthday($birthdayStudent);
191
            }
192
        }
193
194
        return $view;
195
    }
196
197
    private function setCurrentLesson(DashboardView $dashboardView): void {
198
        foreach($dashboardView->getLessons() as $lesson) {
199
            $startTime = $this->timetableTimeHelper->getLessonStartDateTime($dashboardView->getDateTime(), $lesson->getLessonNumber());
200
            $endTime = $this->timetableTimeHelper->getLessonEndDateTime($dashboardView->getDateTime(), $lesson->getLessonNumber());
201
            $now = $this->dateHelper->getNow();
202
203
            if($startTime <= $now && $now <= $endTime) {
204
                $lesson->setIsCurrent(true);
205
            }
206
        }
207
    }
208
209
    private function addExercises(DashboardView $view, Student $student, DateTime $date) {
210
        $start = (clone $date)->modify(sprintf('-%d days', $this->bookSettings->getExercisesDays()));
211
        $end = clone $date;
212
        $section = $this->sectionResolver->getSectionForDate($date);
213
        $grade = $student->getGrade($section);
214
215
        if($grade === null) {
216
            return;
217
        }
218
219
        $exerciseView = new ExercisesView($start, $end, $grade);
220
        $exerciseView->setEntriesWithExercises($this->lessonEntryRepository->findAllByStudentWithExercises($student, $start, $end));
221
        $view->setExercises($exerciseView);
222
    }
223
224
    /**
225
     * @param TimetableLesson[] $lessons
226
     */
227
    private function addTimetableLessons(iterable $lessons, DateTime $dateTime, DashboardView $dashboardView, bool $computeAbsences): void {
228
        foreach($lessons as $lesson) {
229
            $lessonStudents = [ ];
230
231
            if($lesson->getTuition() !== null) {
232
                $lessonStudents = $lesson
233
                    ->getTuition()
234
                    ->getStudyGroup()
235
                    ->getMemberships()
236
                    ->map(fn(StudyGroupMembership $membership) => $membership->getStudent())
237
                    ->toArray();
238
            }
239
240
            for($lessonNumber = $lesson->getLessonStart(); $lessonNumber <= $lesson->getLessonEnd(); $lessonNumber++) {
241
                $absentStudents = $computeAbsences ? $this->computeAbsentStudents($lessonStudents, $lessonNumber, $dateTime) : [ ];
242
                $absenceLesson = $this->absenceLessonRepository->findOneForLesson($lesson);
243
                $dashboardView->addItem($lessonNumber, new TimetableLessonViewItem($lesson, $absentStudents, $absenceLesson));
244
            }
245
        }
246
    }
247
248
    private function addEmptyTimetableLessons(DashboardView $view, int $numberOfLessons) {
249
        $lessons = $view->getLessonNumbers();
250
251
        for($i = 1; $i <= $numberOfLessons; $i++) {
252
            if(!in_array($i, $lessons)) {
253
                $view->addItem($i, new TimetableLessonViewItem(null, [], null));
254
            }
255
        }
256
257
        foreach($lessons as $lessonNumber) {
258
            $hasLessonEntry = false;
259
            $lesson = $view->getLesson($lessonNumber);
260
261
            if($lesson !== null) {
262
                foreach ($lesson->getItems() as $item) {
263
                    if ($item instanceof TimetableLessonViewItem) {
264
                        $hasLessonEntry = true;
265
                        break;
266
                    }
267
                }
268
            } else {
269
                $hasLessonEntry = false;
270
            }
271
272
            if($hasLessonEntry === false) {
273
                $view->addItem($lessonNumber, new TimetableLessonViewItem(null, [], null));
274
            }
275
        }
276
    }
277
278
    /**
279
     * @param TimetableSupervision[] $supervisions
280
     */
281
    private function addSupervisions(iterable $supervisions, DashboardView $dashboardView): void {
282
        foreach($supervisions as $supervision) {
283
            if ($supervision->isBefore()) {
284
                $dashboardView->addItemBefore($supervision->getLesson(), new SupervisionViewItem($supervision));
285
            } else {
286
                $dashboardView->addItem($supervision->getLesson(), new SupervisionViewItem($supervision));
287
            }
288
        }
289
    }
290
291
    /**
292
     * @param Substitution[] $substitutions
293
     */
294
    private function addSubstitutions(iterable $substitutions, DashboardView $dashboardView, bool $computeAbsences): void {
295
        $freeTypes = $this->dashboardSettings->getFreeLessonSubstitutionTypes();
296
297
        foreach($substitutions as $substitution) {
298
            if($this->authorizationChecker->isGranted(SubstitutionVoter::View, $substitution) !== true) {
299
                continue;
300
            }
301
302
            $isFreeLesson = in_array($substitution->getType(), $freeTypes);
303
304
            if($substitution->startsBefore()) {
305
                $dashboardView->addItemBefore($substitution->getLessonStart(), new SubstitutionViewItem($substitution, $isFreeLesson, [ ], [ ], null, null));
306
307
                if($substitution->getLessonEnd() - $substitution->getLessonStart() === 0) {
308
                    // Do not expand more lessons when the end is the same lesson as the beginning
309
                    continue;
310
                }
311
            }
312
            $studyGroups = $substitution->getReplacementStudyGroups()->count() > 0 ? $substitution->getReplacementStudyGroups() : $substitution->getStudyGroups();
313
            $students = $this->getStudents($studyGroups);
314
315
            for ($lesson = $substitution->getLessonStart(); $lesson <= $substitution->getLessonEnd(); $lesson++) {
316
                $absentStudents = $computeAbsences ? $this->computeAbsentStudents($students, $lesson, $substitution->getDate()) : [ ];
317
                $timetableLesson = $this->findTimetableLesson($substitution, $lesson);
318
                $absenceLesson = null;
319
320
                if($timetableLesson !== null) {
321
                    $absenceLesson = $this->absenceLessonRepository->findOneForLesson($timetableLesson);
322
                }
323
324
                $dashboardView->addItem($lesson, new SubstitutionViewItem($substitution, $isFreeLesson, $students, $absentStudents, $timetableLesson, $absenceLesson));
325
            }
326
        }
327
    }
328
329
    private function findTimetableLesson(Substitution $substitution, int $lesson): ?TimetableLesson {
330
        $tuition = $this->tuitionRepository->findOneBySubstitution($substitution, $this->sectionResolver->getSectionForDate($substitution->getDate()));
0 ignored issues
show
Bug introduced by
It seems like $this->sectionResolver->...ubstitution->getDate()) can also be of type null; however, parameter $section of App\Repository\TuitionRe...findOneBySubstitution() 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

330
        $tuition = $this->tuitionRepository->findOneBySubstitution($substitution, /** @scrutinizer ignore-type */ $this->sectionResolver->getSectionForDate($substitution->getDate()));
Loading history...
Bug introduced by
It seems like $substitution->getDate() can also be of type null; however, parameter $dateTime of App\Section\SectionResol...ce::getSectionForDate() does only seem to accept DateTime, 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

330
        $tuition = $this->tuitionRepository->findOneBySubstitution($substitution, $this->sectionResolver->getSectionForDate(/** @scrutinizer ignore-type */ $substitution->getDate()));
Loading history...
331
332
        if($tuition === null) {
333
            return null;
334
        }
335
336
        $lessons = $this->timetableRepository->findAllByTuitions($substitution->getDate(), $substitution->getDate(), [ $tuition ]);
0 ignored issues
show
Bug introduced by
It seems like $substitution->getDate() can also be of type null; however, parameter $end of App\Repository\Timetable...ce::findAllByTuitions() does only seem to accept DateTime, 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

336
        $lessons = $this->timetableRepository->findAllByTuitions($substitution->getDate(), /** @scrutinizer ignore-type */ $substitution->getDate(), [ $tuition ]);
Loading history...
Bug introduced by
It seems like $substitution->getDate() can also be of type null; however, parameter $start of App\Repository\Timetable...ce::findAllByTuitions() does only seem to accept DateTime, 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

336
        $lessons = $this->timetableRepository->findAllByTuitions(/** @scrutinizer ignore-type */ $substitution->getDate(), $substitution->getDate(), [ $tuition ]);
Loading history...
337
338
        foreach($lessons as $timetableLesson) {
339
            if($timetableLesson->getLessonStart() <= $lesson && $lesson <= $timetableLesson->getLessonEnd()) {
340
                return $timetableLesson;
341
            }
342
        }
343
344
        return null;
345
    }
346
347
    /**
348
     * @param Message[] $messages
349
     */
350
    private function addMessages(iterable $messages, DashboardView $dashboardView): void {
351
        $this->sorter->sort($messages, MessageStrategy::class);
0 ignored issues
show
Bug introduced by
$messages of type iterable is incompatible with the type array expected by parameter $array of App\Sorting\Sorter::sort(). ( Ignorable by Annotation )

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

351
        $this->sorter->sort(/** @scrutinizer ignore-type */ $messages, MessageStrategy::class);
Loading history...
352
353
        foreach($messages as $message) {
354
            if($this->authorizationChecker->isGranted(MessageVoter::View, $message) !== true) {
355
                continue;
356
            }
357
358
            $dashboardView->addMessage($message);
359
        }
360
    }
361
362
    /**
363
     * @param Exam[] $exams
364
     */
365
    private function addExams(iterable $exams, DashboardView $dashboardView, ?Teacher $teacher, bool $computeAbsences): void {
366
        foreach($exams as $exam) {
367
            if($this->authorizationChecker->isGranted(ExamVoter::Show, $exam) !== true) {
368
                continue;
369
            }
370
371
            /** @var int[] $tuitionTeacherIds */
372
            $tuitionTeacherIds = [ ];
373
374
            /** @var Tuition $tuition */
375
            foreach($exam->getTuitions() as $tuition) {
376
                $tuitionTeacherIds = array_merge($tuitionTeacherIds, array_map(fn(Teacher $teacher) => $teacher->getId(), $tuition->getTeachers()->toArray()));
377
            }
378
379
            $supervisions = [ ];
380
381
            if($teacher !== null) {
382
                /** @var ExamSupervision $supervision */
383
                foreach($exam->getSupervisions() as $supervision) {
384
                    $supervisions[$supervision->getLesson()] = $supervision->getTeacher()->getId();
385
                }
386
            }
387
388
            for($lesson = $exam->getLessonStart(); $lesson <= $exam->getLessonEnd(); $lesson++) {
389
                $absentStudents = $computeAbsences ? $this->computeAbsentStudents($exam->getStudents()->toArray(), $lesson, $exam->getDate(), [ ExamStudentsResolver::class ]) : [ ];
390
391
                if($teacher !== null) {
392
                    if(in_array($teacher->getId(), $tuitionTeacherIds)) {
393
                        $dashboardView->addItem($lesson, new ExamViewItem($exam, $absentStudents));
394
                    }
395
396
                    if(isset($supervisions[$lesson]) && $supervisions[$lesson] === $teacher->getId()) {
397
                        $dashboardView->addItem($lesson, new ExamSupervisionViewItem($exam, $absentStudents));
398
                    }
399
                } else {
400
                    $dashboardView->addItem($lesson, new ExamViewItem($exam, $absentStudents));
401
                }
402
            }
403
        }
404
    }
405
406
    private function addInfotexts(DateTime $dateTime, DashboardView $view): void {
407
        $infotexts = $this->infotextRepository->findAllByDate($dateTime);
408
409
        foreach($infotexts as $infotext) {
410
            $view->addInfotext($infotext);
411
        }
412
    }
413
414
    private function addAbsentTeachers(array $absences, DashboardView $view): void {
415
        $this->sorter->sort($absences, AbsentTeacherStrategy::class);
416
        foreach($absences as $absence) {
417
            if($this->authorizationChecker->isGranted(AbsenceVoter::View, $absence)) {
418
                $view->addAbsence($absence);
419
            }
420
        }
421
    }
422
423
    private function addAbsentStudyGroup(array $absences, DashboardView $view): void {
424
        $this->sorter->sort($absences, AbsentStudyGroupStrategy::class);
425
        foreach($absences as $absence) {
426
            if($this->authorizationChecker->isGranted(AbsenceVoter::View, $absence)) {
427
                $view->addAbsence($absence);
428
            }
429
        }
430
    }
431
432
    /**
433
     * @param Appointment[] $appointments
434
     */
435
    private function addAppointments(array $appointments, DashboardView $view): void {
436
        $freeCategories = $this->timetableSettings->getCategoryIds();
437
438
        foreach($appointments as $appointment) {
439
            if($this->authorizationChecker->isGranted(AppointmentVoter::View, $appointment)) {
440
                if(in_array($appointment->getCategory()->getId(), $freeCategories)) {
441
                    $view->removeLessons();;
442
                }
443
444
                $view->addAppointment($appointment);
445
            }
446
        }
447
    }
448
449
    /**
450
     * @param ResourceReservation[] $reservations
451
     */
452
    private function addRoomReservations(array $reservations, DashboardView $view): void {
453
        foreach($reservations as $reservation) {
454
            if($this->authorizationChecker->isGranted(ResourceReservationVoter::View)) {
455
                $violations = $this->validator->validate($reservation, null, ['collision']);
456
457
                for($lessonNumber = $reservation->getLessonStart(); $lessonNumber <= $reservation->getLessonEnd(); $lessonNumber++) {
458
                    $view->addItem($lessonNumber, new RoomReservationViewItem($reservation, $violations));
459
                }
460
            }
461
        }
462
    }
463
464
    /**
465
     * @param FreeTimespan[] $timespans
466
     */
467
    private function addFreeTimespans(array $timespans, DashboardView $view): void {
468
         foreach($timespans as $timespan) {
469
            for($lessonNumber = $timespan->getStart(); $lessonNumber <= $timespan->getEnd(); $lessonNumber++) {
470
                $view->addItem($lessonNumber, new FreeLessonView());
471
            }
472
        }
473
    }
474
475
    /**
476
     * @param Student[] $students
477
     * @param string[] $excludedResolvers FQCN of excluded strategies
478
     * @return AbsentStudentGroup[]
479
     */
480
    private function computeAbsentStudents(array $students, int $lesson, DateTime $dateTime, array $excludedResolvers = [ ]): array {
481
        $absentStudents = $this->absenceResolver->resolve($dateTime, $lesson, $students, $excludedResolvers);
482
483
        /** @var AbsentStudentGroup[] $groups */
484
        $groups = $this->grouper->group($absentStudents, AbstentStudentGroupStrategy::class);
485
        $this->sorter->sortGroupItems($groups, AbsentStudentStrategy::class);
486
487
        return $groups;
488
    }
489
490
    /**
491
     * @param iterable|StudyGroup[] $studyGroups
492
     * @return Student[]
493
     */
494
    private function getStudents(iterable $studyGroups): array {
495
        $students = [ ];
496
497
        foreach($studyGroups as $group) {
498
            /** @var StudyGroupMembership $membership */
499
            foreach($group->getMemberships() as $membership) {
500
                $students[] = $membership->getStudent();
501
            }
502
        }
503
504
        return $students;
505
    }
506
507
    /**
508
     * Filters the given substitutions for only those which are applied to the given grade.
509
     *
510
     * @param Substitution[] $substitutions
511
     * @return Substitution[]
512
     */
513
    private function filterSubstitutionsByGrade(array $substitutions, ?Grade $grade) {
514
        $result = [ ];
515
516
        foreach($substitutions as $substitution) {
517
            if($substitution->getReplacementGrades()->count() === 0 || $substitution->getReplacementGrades()->contains($grade)) {
518
                $result[] = $substitution;
519
            }
520
        }
521
522
        return $result;
523
    }
524
}