TimetableImporter::getSubjectOverrideMap()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 4
c 1
b 0
f 0
dl 0
loc 8
rs 10
cc 2
nc 2
nop 0
1
<?php
2
3
namespace App\Untis\Html\Timetable;
4
5
use App\Grouping\Grouper;
6
use App\Import\Importer;
7
use App\Import\ImportException;
8
use App\Import\ImportResult;
9
use App\Import\TimetableLessonsImportStrategy;
10
use App\Repository\TimetableWeekRepositoryInterface;
11
use App\Request\Data\TimetableLessonData;
12
use App\Request\Data\TimetableLessonsData;
13
use App\Settings\UntisSettings;
14
use App\Untis\Html\HtmlParseException;
15
use DateTime;
16
use Symfony\Component\Stopwatch\Stopwatch;
17
18
class TimetableImporter {
19
    public function __construct(private Importer $importer, private TimetableLessonsImportStrategy $strategy, private TimetableReader $reader, private TimetableWeekRepositoryInterface $weekRepository, private TimetableLessonCombiner $lessonCombiner, private Grouper $grouper, private UntisSettings $settings)
20
    {
21
    }
22
23
    /**
24
     * @param string[] $gradeLessonsHtml
25
     * @param string[] $subjectLessonsHtml
26
     * @throws HtmlParseException
27
     * @throws ImportException
28
     */
29
    public function import(array $gradeLessonsHtml, array $subjectLessonsHtml, DateTime $start, DateTime $end): ImportResult {
30
        $lessons = [ ];
31
32
        foreach($gradeLessonsHtml as $html) {
33
            $result = $this->reader->readHtml($html, TimetableType::Grade);
34
            $lessons = array_merge(
35
                $lessons,
36
                $this->lessonCombiner->combine($result->getLessons())
37
            );
38
        }
39
40
        foreach($subjectLessonsHtml as $html) {
41
            $result = $this->reader->readHtml($html, TimetableType::Subject);
42
            $lessons = array_merge($lessons,
43
                $this->lessonCombiner->combine($result->getLessons())
44
            );
45
        }
46
47
        $groups = $this->grouper->group($lessons, LessonStrategy::class);
48
49
        $lessonsToImport = [ ];
50
51
        /**
52
         * This week map can be used to convert from calendar weeks to Untis weeks. It looks something like this:
53
         *
54
         * [ 1 => 'A', 2 => 'B', 3 => 'A', 4 => 'B', ...] (in case there are A/B-weeks)
55
         */
56
        $weeksMap = [ ];
57
        foreach($this->weekRepository->findAll() as $week) {
58
            foreach($week->getWeeksAsIntArray() as $weekNumber) {
59
                $weeksMap[$weekNumber] = $week->getKey();
60
            }
61
        }
62
63
        /**
64
         * This matrix is used to get a list of dates for a given week and day. It looks something like this:
65
         *
66
         * [
67
         *      'A' => [
68
         *          1 => [ '2022-01-03', '2022-01-17', ... ]
69
         *          2 => [ '2022-01-04', '2022-01-18', ... ]
70
         *      ],
71
         *      'B' => ...
72
         * ]
73
         */
74
        $weekMatrix = [ ];
75
        $current = clone $start;
76
        while($current <= $end) {
77
            $current->setTime(0, 0);
78
79
            $week = $weeksMap[(int)$current->format('W')];
80
            $day = (int)$current->format('w');
81
82
            if(!array_key_exists($week, $weekMatrix)) {
83
                $weekMatrix[$week] = [ ];
84
            }
85
86
            if(!array_key_exists($day, $weekMatrix[$week])) {
87
                $weekMatrix[$week][$day] = [ ];
88
            }
89
90
            $weekMatrix[$week][$day][] = $current;
91
92
            $current = (clone $current)->modify('+1 day');
93
        }
94
95
        $subjectOverrides = $this->getSubjectOverrideMap();
96
97
        /** @var LessonGroup $group */
98
        foreach($groups as $group) {
99
            if(count($group->getLessons()) === 0) {
0 ignored issues
show
Bug introduced by
The method getLessons() does not exist on App\Grouping\GroupInterface. It seems like you code against a sub-type of App\Grouping\GroupInterface such as App\Grouping\LessonDayGroup or App\Untis\Html\Timetable\LessonGroup. ( Ignorable by Annotation )

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

99
            if(count($group->/** @scrutinizer ignore-call */ getLessons()) === 0) {
Loading history...
100
                // just in case...
101
                continue;
102
            }
103
104
            $teachers = [ ];
105
            $grades = [ ];
106
107
            foreach($group->getLessons() as $lesson) {
108
                if(!in_array($lesson->getTeacher(), $teachers)) {
109
                    $teachers[] = $lesson->getTeacher();
110
                }
111
112
                if(!in_array($lesson->getGrade(), $grades)) {
113
                    $grades[] = $lesson->getGrade();
114
                }
115
            }
116
117
            $lesson = $group->getLessons()[0];
118
119
            // Iterate over weeks
120
            foreach($lesson->getWeeks() as $week) {
121
                if(!isset($weekMatrix[$week][$lesson->getDay()])) {
122
                    continue;
123
                }
124
125
                foreach($weekMatrix[$week][$lesson->getDay()] as $date) {
126
                    $lessonsToImport[] = (new TimetableLessonData())
127
                        ->setId($group->getKey() . '-' . $date->format('Y-m-d'))
128
                        ->setDate($date)
129
                        ->setGrades($grades)
130
                        ->setTeachers($teachers)
131
                        ->setRoom($lesson->getRoom())
132
                        ->setSubject($subjectOverrides[$lesson->getSubject()] ?? $lesson->getSubject())
133
                        ->setLessonStart($lesson->getLessonStart())
134
                        ->setLessonEnd($lesson->getLessonEnd());
135
                }
136
            }
137
        }
138
139
        $data = new TimetableLessonsData();
140
        $data->setStartDate($start);
141
        $data->setEndDate($end);
142
        $data->setLessons($lessonsToImport);
143
144
        return $this->importer->replaceImport($data, $this->strategy);
145
    }
146
147
    private function getSubjectOverrideMap(): array {
148
        $map = [ ];
149
150
        foreach($this->settings->getSubjectOverrides() as $override) {
151
            $map[$override['untis']] = $override['override'];
152
        }
153
154
        return $map;
155
    }
156
}