BookExporter   D
last analyzed

Complexity

Total Complexity 58

Size/Duplication

Total Lines 352
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 197
dl 0
loc 352
rs 4.5599
c 2
b 0
f 0
wmc 58

17 Methods

Rating   Name   Duplication   Size   Complexity  
A castTuition() 0 7 2
F export() 0 153 28
A castStudent() 0 8 2
A exportGradeJson() 0 4 1
A castSection() 0 5 1
A castTeacher() 0 11 2
B castEntry() 0 48 9
A exportTuitionJson() 0 4 1
A castLesson() 0 11 2
A __construct() 0 4 1
A exportGrade() 0 8 1
A exportTuitionXml() 0 4 1
A castAttendanceType() 0 7 1
A exportGradeXml() 0 4 1
A castGrade() 0 12 3
A castComment() 0 8 1
A exportTuition() 0 9 1

How to fix   Complexity   

Complex Class

Complex classes like BookExporter 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 BookExporter, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace App\Book\Export;
4
5
use App\Book\EntryOverview;
6
use App\Book\EntryOverviewHelper;
7
use App\Book\Grade\GradeOverviewHelper;
8
use App\Book\Student\AbsenceExcuseResolver;
9
use App\Book\Student\LessonAttendance;
10
use App\Book\Student\StudentInfo;
11
use App\Book\Student\StudentInfoResolver;
12
use App\Entity\BookComment as CommentEntity;
13
use App\Entity\Grade as GradeEntity;
14
use App\Entity\GradeMembership;
15
use App\Entity\GradeTeacher;
16
use App\Entity\LessonAttendance as LessonAttendanceEntity;
17
use App\Entity\LessonAttendanceType;
18
use App\Entity\LessonEntry;
19
use App\Entity\LessonEntry as LessonEntryEntity;
20
use App\Entity\Section as SectionEntity;
21
use App\Entity\Student as StudentEntity;
22
use App\Entity\StudyGroupMembership;
23
use App\Entity\Teacher as TeacherEntity;
24
use App\Entity\TimetableLesson;
25
use App\Entity\Tuition as TuitionEntity;
26
use App\Repository\TuitionRepositoryInterface;
27
use App\Sorting\Sorter;
28
use App\Sorting\StudentStrategy;
29
use App\Utils\ArrayUtils;
30
use InvalidArgumentException;
31
use JMS\Serializer\SerializerInterface;
32
33
class BookExporter {
34
35
    public function __construct(private readonly EntryOverviewHelper $overviewHelper, private readonly StudentInfoResolver $studentInfoResolver,
36
                                private readonly Sorter $sorter, private readonly SerializerInterface $serializer,
37
                                private readonly GradeOverviewHelper $gradeOverviewHelper, private readonly TuitionRepositoryInterface $tuitionRepository)
38
    {
39
    }
40
41
    /**
42
     * @param StudentEntity[] $students
43
     */
44
    private function export(Book $book, array $students, ?TuitionEntity $tuition, ?GradeEntity $grade, SectionEntity $section, EntryOverview $overview): Book {
45
        $book
46
            ->setStart($section->getStart())
0 ignored issues
show
Bug introduced by
It seems like $section->getStart() can also be of type null; however, parameter $start of App\Book\Export\Book::setStart() 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

46
            ->setStart(/** @scrutinizer ignore-type */ $section->getStart())
Loading history...
47
            ->setEnd($section->getEnd())
0 ignored issues
show
Bug introduced by
It seems like $section->getEnd() can also be of type null; however, parameter $end of App\Book\Export\Book::setEnd() 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

47
            ->setEnd(/** @scrutinizer ignore-type */ $section->getEnd())
Loading history...
48
            ->setSection($this->castSection($section));
49
50
        if($book->getTuition() !== null && $tuition !== null) {
51
            /** @var TeacherEntity $teacher */
52
            foreach ($tuition->getTeachers() as $teacher) {
53
                $book->getTuition()->addTeacher(
54
                    (new Teacher())
55
                        ->setAcronym($teacher->getAcronym())
56
                        ->setId($teacher->getUuid()->toString())
57
                        ->setFirstname($teacher->getFirstname())
58
                        ->setLastname($teacher->getLastname())
59
                        ->setTitle($teacher->getTitle())
60
                );
61
            }
62
        }
63
64
        if($tuition !== null) {
65
            $grades = [];
66
67
            foreach ($tuition->getStudyGroup()->getGrades() as $tuitionGrade) {
68
                $exportGrade = (new Grade())
69
                    ->setName($tuitionGrade->getName());
70
71
                /** @var GradeTeacher $teacher */
72
                foreach ($tuitionGrade->getTeachers() as $teacher) {
73
                    $exportGrade->addTeacher(
74
                        (new Teacher())
75
                            ->setAcronym($teacher->getTeacher()->getAcronym())
76
                            ->setId($teacher->getTeacher()->getUuid()->toString())
77
                            ->setFirstname($teacher->getTeacher()->getFirstname())
78
                            ->setLastname($teacher->getTeacher()->getLastname())
79
                            ->setTitle($teacher->getTeacher()->getTitle())
80
                    );
81
                }
82
83
                $grades[] = $exportGrade;
84
            }
85
            $book->setGrades($grades);
86
        }
87
88
        $gradeOverview = null;
89
        $tuitions = [ ];
90
91
        if($tuition !== null) {
92
            $tuitions = [ $tuition ];
93
            $gradeOverview = $this->gradeOverviewHelper->computeOverviewForTuition($tuition);
94
        } else if($grade !== null) {
95
            $gradeOverview = $this->gradeOverviewHelper->computeForGrade($grade, $section);
96
            foreach($gradeOverview->getCategories() as $category) {
97
                $tuitions[$category->getTuition()->getId()] = $category->getTuition();
98
            }
99
        }
100
101
        if($gradeOverview !== null) {
102
            foreach($tuitions as $gradeTuition) {
103
                $studentGrades = new StudentGrades();
104
                $studentGrades->setTuition($this->castTuition($gradeTuition));
105
106
                foreach ($gradeOverview->getCategories() as $category) {
107
                    if($category->getTuition() !== $gradeTuition) {
108
                        continue;
109
                    }
110
111
                    if ($category->getCategory()->isExportable()) {
112
                        $studentGrades->addCategory(
113
                            (new TuitionGradeCategory())
114
                                ->setUuid($category->getCategory()->getUuid()->toString())
115
                                ->setDisplayName($category->getCategory()->getDisplayName())
116
                        );
117
                    }
118
                }
119
120
                foreach ($gradeOverview->getRows() as $row) {
121
                    foreach ($gradeOverview->getCategories() as $category) {
122
                        if($category->getTuition() !== $gradeTuition) {
123
                            continue;
124
                        }
125
126
                        if ($category->getCategory()->isExportable()) {
127
                            $studentGrades->addGrade((new TuitionGrade())
128
                                ->setStudent($row->getTuitionOrStudent()->getExternalId())
129
                                ->setGradeCategory($category->getCategory()->getUuid()->toString())
130
                                ->setEncryptedGrade($row->getGrade($category->getTuition(), $category->getCategory())?->getEncryptedGrade()));
131
                        }
132
                    }
133
                }
134
135
                $book->addStudentGrades($studentGrades);
136
            }
137
        }
138
139
        $this->sorter->sort($students, StudentStrategy::class);
140
141
        $studentInfo = [ ];
142
        $tuitionsToConsider = $tuition !== null ? [ $tuition ] : $this->tuitionRepository->findAllByGrades([$grade], $section);
143
144
        foreach($students as $student) {
145
            $info = $this->studentInfoResolver->resolveStudentInfo($student, $section, $tuitionsToConsider);
146
            $studentInfo[$student->getId()] = $info;
147
            $book->addStudentSummary(
148
                (new StudentSummary())
149
                    ->setStudent($this->castStudent($student, $section))
150
                    ->setLateMinutesCount($info->getLateMinutesCount())
151
                    ->setAbsentLessonsCount($info->getAbsentLessonsCount())
152
                    ->setExcuseStatusNotSetLessonCount($info->getNotExcusedOrNotSetLessonsCount())
153
                    ->setNotExcusedAbsentLessonCount($info->getNotExcusedAbsentLessonsCount())
154
            );
155
        }
156
157
        $weeks = [ ];
158
        foreach($overview->getDays() as $day) {
159
            $weekNumber = (int)$day->getDate()->format('W');
160
161
            if(!isset($weeks[$weekNumber])) {
162
                $weeks[$weekNumber] = (new Week())
163
                    ->setStart(clone $day->getDate())
164
                    ->setEnd((clone $day->getDate())->modify('+6 days'))
165
                    ->setWeekNumber($weekNumber);
166
            }
167
168
            $exportDay = (new Day())
169
                ->setDate(clone $day->getDate());
170
171
            foreach($overview->getComments($day->getDate()) as $comment) {
172
                $exportDay->addComment($this->castComment($comment, $section));
173
            }
174
175
            $lessons = [ ];
176
177
            foreach($day->getLessons() as $lesson) {
178
                if($lesson->getEntry() === null) {
179
                    $lessons[] = $this->castLesson($lesson->getLesson(), $lesson->getLessonNumber());
180
                } else {
181
                    $lessons[$lesson->getEntry()->getUuid()->toString()] = $this->castEntry($lesson->getEntry(), $section, $studentInfo);
182
                }
183
            }
184
185
            foreach($lessons as $lesson) {
186
                $exportDay->addLesson($lesson);
187
            }
188
189
            $weeks[$weekNumber]->addDay($exportDay);
190
        }
191
192
        foreach($weeks as $week) {
193
            $book->addWeek($week);
194
        }
195
196
        return $book;
197
    }
198
199
    public function exportGrade(GradeEntity $grade, SectionEntity $section): Book {
200
        $book = (new Book())
201
            ->setGrades([$this->castGrade($grade, $section)]);
202
203
        $students = $grade->getMemberships()->filter(fn(GradeMembership $membership) => $membership->getSection() === $section)->map(fn(GradeMembership $membership) => $membership->getStudent())->toArray();
204
        $overview = $this->overviewHelper->computeOverviewForGrade($grade, $section->getStart(), $section->getEnd());
0 ignored issues
show
Bug introduced by
It seems like $section->getStart() can also be of type null; however, parameter $start of App\Book\EntryOverviewHe...mputeOverviewForGrade() 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

204
        $overview = $this->overviewHelper->computeOverviewForGrade($grade, /** @scrutinizer ignore-type */ $section->getStart(), $section->getEnd());
Loading history...
Bug introduced by
It seems like $section->getEnd() can also be of type null; however, parameter $end of App\Book\EntryOverviewHe...mputeOverviewForGrade() 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

204
        $overview = $this->overviewHelper->computeOverviewForGrade($grade, $section->getStart(), /** @scrutinizer ignore-type */ $section->getEnd());
Loading history...
205
206
        return $this->export($book, $students, null, $grade, $section, $overview);
207
    }
208
209
    public function exportTuition(TuitionEntity $tuition, SectionEntity $section): Book {
210
        $book = (new Book())
211
            ->setTuition($this->castTuition($tuition));
212
213
        $students = $tuition->getStudyGroup()->getMemberships()->map(fn(StudyGroupMembership $membership) => $membership->getStudent())->toArray();
214
215
        $overview = $this->overviewHelper->computeOverviewForTuition($tuition, $section->getStart(), $section->getEnd());
0 ignored issues
show
Bug introduced by
It seems like $section->getStart() can also be of type null; however, parameter $start of App\Book\EntryOverviewHe...uteOverviewForTuition() 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

215
        $overview = $this->overviewHelper->computeOverviewForTuition($tuition, /** @scrutinizer ignore-type */ $section->getStart(), $section->getEnd());
Loading history...
Bug introduced by
It seems like $section->getEnd() can also be of type null; however, parameter $end of App\Book\EntryOverviewHe...uteOverviewForTuition() 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

215
        $overview = $this->overviewHelper->computeOverviewForTuition($tuition, $section->getStart(), /** @scrutinizer ignore-type */ $section->getEnd());
Loading history...
216
217
        return $this->export($book, $students, $tuition, null, $section, $overview);
218
    }
219
220
    public function exportGradeXml(GradeEntity $grade, SectionEntity $section): string {
221
        return $this->serializer->serialize(
222
            $this->exportGrade($grade, $section),
223
            'xml'
224
        );
225
    }
226
227
    public function exportGradeJson(GradeEntity $grade, SectionEntity $section): string {
228
        return $this->serializer->serialize(
229
            $this->exportGrade($grade, $section),
230
            'json'
231
        );
232
    }
233
234
    public function exportTuitionXml(TuitionEntity $tuition, SectionEntity $section): string {
235
        return $this->serializer->serialize(
236
            $this->exportTuition($tuition, $section),
237
            'xml'
238
        );
239
    }
240
241
    public function exportTuitionJson(TuitionEntity $tuition, SectionEntity $section): string {
242
        return $this->serializer->serialize(
243
            $this->exportTuition($tuition, $section),
244
            'json'
245
        );
246
    }
247
248
    private function castLesson(TimetableLesson $lessonEntity, int $lessonNumber): Lesson {
249
        $subject = $lessonEntity->getTuition()->getSubject();
250
251
        $lesson = (new Lesson())
252
            ->setIsMissing(true)
253
            ->setStart($lessonNumber)
254
            ->setEnd($lessonNumber)
255
            ->setSubject($subject !== null ? $subject->getAbbreviation() : null)
0 ignored issues
show
Bug introduced by
It seems like $subject !== null ? $sub...etAbbreviation() : null can also be of type null; however, parameter $subject of App\Book\Export\Lesson::setSubject() 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

255
            ->setSubject(/** @scrutinizer ignore-type */ $subject !== null ? $subject->getAbbreviation() : null)
Loading history...
256
            ->setTeacher($this->castTeacher($lessonEntity->getTuition()->getTeachers()->first()));
0 ignored issues
show
Bug introduced by
It seems like $this->castTeacher($less...getTeachers()->first()) can also be of type null; however, parameter $teacher of App\Book\Export\Lesson::setTeacher() does only seem to accept App\Book\Export\Teacher, 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

256
            ->setTeacher(/** @scrutinizer ignore-type */ $this->castTeacher($lessonEntity->getTuition()->getTeachers()->first()));
Loading history...
257
258
        return $lesson;
259
    }
260
261
    /**
262
     * @param StudentInfo[] $studentInfo
263
     */
264
    private function castEntry(LessonEntryEntity $entry, SectionEntity $section, array $studentInfo): Lesson {
265
        $subject = $entry->getTuition()->getSubject();
266
267
        $lesson = (new Lesson())
268
            ->setStart($entry->getLessonStart())
269
            ->setEnd($entry->getLessonEnd())
270
            ->setSubject($subject !== null ? $subject->getAbbreviation() : null)
0 ignored issues
show
Bug introduced by
It seems like $subject !== null ? $sub...etAbbreviation() : null can also be of type null; however, parameter $subject of App\Book\Export\Lesson::setSubject() 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

270
            ->setSubject(/** @scrutinizer ignore-type */ $subject !== null ? $subject->getAbbreviation() : null)
Loading history...
271
            ->setReplacementSubject($entry->getReplacementSubject())
272
            ->setTeacher($this->castTeacher($entry->getTeacher()))
0 ignored issues
show
Bug introduced by
It seems like $this->castTeacher($entry->getTeacher()) can also be of type null; however, parameter $teacher of App\Book\Export\Lesson::setTeacher() does only seem to accept App\Book\Export\Teacher, 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

272
            ->setTeacher(/** @scrutinizer ignore-type */ $this->castTeacher($entry->getTeacher()))
Loading history...
273
            ->setReplacementTeacher($this->castTeacher($entry->getReplacementTeacher()))
274
            ->setWasCancelled($entry->isCancelled())
275
            ->setTopic($entry->isCancelled() ? $entry->getCancelReason() : $entry->getTopic())
276
            ->setComment($entry->getComment())
277
            ->setExercises($entry->getExercises())
278
            ->setIsMissing(false);
279
280
        /** @var LessonAttendanceEntity $attendance */
281
        foreach($entry->getAttendances() as $attendance) {
282
            $exportAttendance = (new Attendance())
283
                ->setComment($attendance->getComment())
284
                ->setLateMinutesCount($attendance->getLateMinutes())
285
                ->setStudent($this->castStudent($attendance->getStudent(), $section))
286
                ->setType($this->castAttendanceType($attendance->getType()));
287
288
            // check if lesson is excused
289
            if($attendance->getType() === LessonAttendanceType::Absent) {
290
                $exportAttendance->setAbsentLessonCount(
291
                    ($entry->getLessonEnd() - $attendance->getAbsentLessons()) < $entry->getLessonStart() ? 1 : 0
292
                );
293
294
                // check info
295
                $info = $studentInfo[$attendance->getStudent()->getId()] ?? null;
296
297
                if($info !== null) {
298
                    /** @var LessonAttendance $possibleAttendance */
299
                    $possibleAttendance = ArrayUtils::first($info->getAbsentLessonAttendances(), fn(LessonAttendance $lessonAttendance) => $lessonAttendance->getAttendance()->getId() === $attendance->getId()
300
                        && $lessonAttendance->getAttendance()->getEntry() === $entry);
301
302
                    if($possibleAttendance !== null) {
303
                        $exportAttendance->setIsExcused($possibleAttendance->isExcused());
304
                    }
305
                }
306
            }
307
308
            $lesson->addAttendance($exportAttendance);
309
        }
310
311
        return $lesson;
312
    }
313
314
    private function castAttendanceType(int $type): string
315
    {
316
        return match ($type) {
317
            LessonAttendanceType::Absent => 'absent',
318
            LessonAttendanceType::Present => 'present',
319
            LessonAttendanceType::Late => 'late',
320
            default => throw new InvalidArgumentException(sprintf('$type must be either 0, 1 or 2, %d given', $type)),
321
        };
322
    }
323
324
    private function castSection(SectionEntity $section): Section {
325
        return (new Section())
326
            ->setName($section->getDisplayName())
0 ignored issues
show
Bug introduced by
It seems like $section->getDisplayName() can also be of type null; however, parameter $name of App\Book\Export\Section::setName() 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

326
            ->setName(/** @scrutinizer ignore-type */ $section->getDisplayName())
Loading history...
327
            ->setYear($section->getYear())
328
            ->setNumber($section->getNumber());
329
    }
330
331
    private function castGrade(GradeEntity $gradeEntity, SectionEntity $section): Grade {
332
        $grade = (new Grade())
333
            ->setName($gradeEntity->getName());
0 ignored issues
show
Bug introduced by
It seems like $gradeEntity->getName() can also be of type null; however, parameter $name of App\Book\Export\Grade::setName() 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

333
            ->setName(/** @scrutinizer ignore-type */ $gradeEntity->getName());
Loading history...
334
335
        /** @var GradeTeacher $gradeTeacher */
336
        foreach($gradeEntity->getTeachers() as $gradeTeacher) {
337
            if($gradeTeacher->getSection()->getId() === $section->getId()) {
338
                $grade->addTeacher($this->castTeacher($gradeTeacher->getTeacher()));
0 ignored issues
show
Bug introduced by
It seems like $this->castTeacher($gradeTeacher->getTeacher()) can also be of type null; however, parameter $teacher of App\Book\Export\Grade::addTeacher() does only seem to accept App\Book\Export\Teacher, 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

338
                $grade->addTeacher(/** @scrutinizer ignore-type */ $this->castTeacher($gradeTeacher->getTeacher()));
Loading history...
339
            }
340
        }
341
342
        return $grade;
343
    }
344
345
    private function castComment(CommentEntity $comment, SectionEntity $section): Comment {
346
        return (new Comment())
347
            ->setDate($comment->getDate())
0 ignored issues
show
Bug introduced by
It seems like $comment->getDate() can also be of type null; however, parameter $date of App\Book\Export\Comment::setDate() 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

347
            ->setDate(/** @scrutinizer ignore-type */ $comment->getDate())
Loading history...
348
            ->setTeacher($this->castTeacher($comment->getTeacher()))
0 ignored issues
show
Bug introduced by
It seems like $this->castTeacher($comment->getTeacher()) can also be of type null; however, parameter $teacher of App\Book\Export\Comment::setTeacher() does only seem to accept App\Book\Export\Teacher, 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

348
            ->setTeacher(/** @scrutinizer ignore-type */ $this->castTeacher($comment->getTeacher()))
Loading history...
349
            ->setStudents(
350
                $comment->getStudents()->map(fn(StudentEntity $student) => $this->castStudent($student, $section))->toArray()
351
            )
352
            ->setComment($comment->getText());
0 ignored issues
show
Bug introduced by
It seems like $comment->getText() can also be of type null; however, parameter $comment of App\Book\Export\Comment::setComment() 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

352
            ->setComment(/** @scrutinizer ignore-type */ $comment->getText());
Loading history...
353
    }
354
355
    private function castTuition(TuitionEntity $tuition): Tuition {
356
        $subject = $tuition->getSubject();
357
358
        return (new Tuition())
359
            ->setId($tuition->getExternalId())
0 ignored issues
show
Bug introduced by
It seems like $tuition->getExternalId() can also be of type null; however, parameter $id of App\Book\Export\Tuition::setId() 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

359
            ->setId(/** @scrutinizer ignore-type */ $tuition->getExternalId())
Loading history...
360
            ->setName($tuition->getName())
0 ignored issues
show
Bug introduced by
It seems like $tuition->getName() can also be of type null; however, parameter $name of App\Book\Export\Tuition::setName() 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

360
            ->setName(/** @scrutinizer ignore-type */ $tuition->getName())
Loading history...
361
            ->setSubject($subject !== null ? $subject->getAbbreviation() : null);
0 ignored issues
show
Bug introduced by
It seems like $subject !== null ? $sub...etAbbreviation() : null can also be of type null; however, parameter $subject of App\Book\Export\Tuition::setSubject() 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

361
            ->setSubject(/** @scrutinizer ignore-type */ $subject !== null ? $subject->getAbbreviation() : null);
Loading history...
362
    }
363
364
    private function castTeacher(?TeacherEntity $teacher): ?Teacher {
365
        if($teacher === null) {
366
            return null;
367
        }
368
369
        return (new Teacher())
370
            ->setId($teacher->getExternalId())
0 ignored issues
show
Bug introduced by
It seems like $teacher->getExternalId() can also be of type null; however, parameter $id of App\Book\Export\Teacher::setId() 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

370
            ->setId(/** @scrutinizer ignore-type */ $teacher->getExternalId())
Loading history...
371
            ->setAcronym($teacher->getAcronym())
0 ignored issues
show
Bug introduced by
It seems like $teacher->getAcronym() can also be of type null; however, parameter $acronym of App\Book\Export\Teacher::setAcronym() 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

371
            ->setAcronym(/** @scrutinizer ignore-type */ $teacher->getAcronym())
Loading history...
372
            ->setFirstname($teacher->getFirstname())
0 ignored issues
show
Bug introduced by
It seems like $teacher->getFirstname() can also be of type null; however, parameter $firstname of App\Book\Export\Teacher::setFirstname() 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

372
            ->setFirstname(/** @scrutinizer ignore-type */ $teacher->getFirstname())
Loading history...
373
            ->setLastname($teacher->getLastname())
0 ignored issues
show
Bug introduced by
It seems like $teacher->getLastname() can also be of type null; however, parameter $lastname of App\Book\Export\Teacher::setLastname() 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

373
            ->setLastname(/** @scrutinizer ignore-type */ $teacher->getLastname())
Loading history...
374
            ->setTitle($teacher->getTitle());
375
    }
376
377
    private function castStudent(StudentEntity $student, SectionEntity $section): Student {
378
        $grade = $student->getGrade($section);
379
380
        return (new Student())
381
            ->setId($student->getExternalId())
0 ignored issues
show
Bug introduced by
It seems like $student->getExternalId() can also be of type null; however, parameter $id of App\Book\Export\Student::setId() 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

381
            ->setId(/** @scrutinizer ignore-type */ $student->getExternalId())
Loading history...
382
            ->setFirstname($student->getFirstname())
383
            ->setLastname($student->getLastname())
384
            ->setGrade($grade !== null ? $grade->getName() : null);
385
    }
386
}