Passed
Push — master ( 168c03...b525a2 )
by Marcel
14:55
created

ExamRepository::findAllExternalWithRange()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1.0156

Importance

Changes 0
Metric Value
eloc 8
c 0
b 0
f 0
dl 0
loc 10
rs 10
ccs 3
cts 4
cp 0.75
cc 1
nc 1
nop 2
crap 1.0156
1
<?php
2
3
namespace App\Repository;
4
5
use App\Entity\Exam;
6
use App\Entity\Grade;
7
use App\Entity\Room;
8
use App\Entity\Section;
9
use App\Entity\Student;
10
use App\Entity\StudyGroup;
11
use App\Entity\Teacher;
12
use DateTime;
13
use Doctrine\ORM\QueryBuilder;
14
use Doctrine\ORM\Tools\Pagination\Paginator;
15
16
class ExamRepository extends AbstractTransactionalRepository implements ExamRepositoryInterface {
17 2
18 2
    private function getDefaultQueryBuilder(DateTime $today = null, bool $onlyToday = false, bool $onlyPlanned = true): QueryBuilder {
19
        $qb = $this->em->createQueryBuilder();
20
21 2
        $qb
22 2
            ->select(['e', 's', 't', 'sg', 'g', 'tt', 'st'])
23 2
            ->from(Exam::class, 'e')
24 2
            ->leftJoin('e.supervisions', 's')
25 2
            ->leftJoin('s.teacher', 'st')
26 2
            ->leftJoin('e.tuitions', 't')
27 2
            ->leftJoin('t.teachers', 'tt')
28 2
            ->leftJoin('t.studyGroup', 'sg')
29 2
            ->leftJoin('sg.grades', 'g');
30
31 2
        if($today !== null) {
32
            $qb->setParameter('today', $today);
33
34
            if($onlyToday === true) {
35
                $qb->where('e.date = :today');
36
            } else {
37
                $qb->where('e.date >= :today');
38
            }
39
        }
40
41 2
        if($onlyPlanned === true) {
42 2
            $qb->andWhere(
43 2
                $qb->expr()->andX(
44 2
                    $qb->expr()->isNotNull('e.date'),
45 2
                    $qb->expr()->isNotNull('e.lessonStart'),
46 2
                    $qb->expr()->isNotNull('e.lessonEnd')
47
                )
48
            );
49
        }
50
51 2
        return $qb;
52
    }
53
54
    public function findOneById(int $id): ?Exam {
55
        return $this->getDefaultQueryBuilder()
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getDefault...)->getOneOrNullResult() could return the type integer which is incompatible with the type-hinted return App\Entity\Exam|null. Consider adding an additional type-check to rule them out.
Loading history...
56
            ->andWhere('e.id = :id')
57
            ->setParameter('id', $id)
58
            ->getQuery()
59
            ->getOneOrNullResult();
60
    }
61
62
    public function findOneByExternalId(string $externalId): ?Exam {
63
        return $this->getDefaultQueryBuilder()
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getDefault...)->getOneOrNullResult() could return the type integer which is incompatible with the type-hinted return App\Entity\Exam|null. Consider adding an additional type-check to rule them out.
Loading history...
64
            ->andWhere('e.externalId = :externalId')
65
            ->setParameter('externalId', $externalId)
66
            ->getQuery()
67
            ->getOneOrNullResult();
68
    }
69
70
    /**
71
     * @inheritDoc
72
     */
73
    public function findAllByIds(array $ids): array {
74
        return $this->getDefaultQueryBuilder()
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getDefault...getQuery()->getResult() could return the type integer which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
75
            ->andWhere('e.id IN (:ids)')
76
            ->setParameter('ids', $ids)
77
            ->getQuery()
78
            ->getResult();
79
    }
80
81
    /**
82
     * @inheritDoc
83
     */
84
    public function findAllByTuitions(array $tuitions, ?DateTime $today = null, bool $onlyPlanned = true) {
85
        $qb = $this->getDefaultQueryBuilder($today, false, $onlyPlanned);
86
87
        $qbInner = $this->em->createQueryBuilder()
88
            ->select('eInner.id')
89
            ->from(Exam::class, 'eInner')
90
            ->leftJoin('eInner.tuitions', 'tInner')
91
            ->where($qb->expr()->in('tInner.id', ':tuitions'));
92
93
        $qb
94
            ->andWhere($qb->expr()->in('e.id', $qbInner->getDQL()))
95
            ->setParameter('tuitions', $tuitions);
96
97
        return $qb->getQuery()->getResult();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $qb->getQuery()->getResult() also could return the type integer which is incompatible with the return type mandated by App\Repository\ExamRepos...ce::findAllByTuitions() of App\Entity\Exam[].
Loading history...
98
    }
99
100
    /**
101
     * @inheritDoc
102
     */
103
    public function findAllByStudyGroup(StudyGroup $studyGroup, ?DateTime $today = null, bool $onlyToday = false, bool $onlyPlanned = true) {
104
        $qb = $this->getDefaultQueryBuilder($today, $onlyToday, $onlyPlanned);
105
106
        $qbInner = $this->em->createQueryBuilder()
107
            ->select('eInner.id')
108
            ->from(Exam::class, 'eInner')
109
            ->leftJoin('eInner.tuitions', 'tInner')
110
            ->leftJoin('tInner.studyGroup', 'sInner')
111
            ->where('sInner.id = :studyGroup');
112
113
        $qb
114
            ->andWhere($qb->expr()->in('e.id', $qbInner->getDQL()))
115
            ->setParameter('studyGroup', $studyGroup->getId());
116
117
        return $qb->getQuery()->getResult();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $qb->getQuery()->getResult() also could return the type integer which is incompatible with the return type mandated by App\Repository\ExamRepos...::findAllByStudyGroup() of App\Entity\Exam[].
Loading history...
118
    }
119
120
    public function findAllDatesByStudyGroup(StudyGroup $studyGroup, ?DateTime $today = null, bool $onlyPlanned = true) {
121
        $qb = $this->getDefaultQueryBuilder($today, false, $onlyPlanned)
122
            ->select(['e.date', 'COUNT(DISTINCT e.id) AS count'])
123
            ->groupBy('e.date');
124
125
        $qbInner = $this->em->createQueryBuilder()
126
            ->select('eInner.id')
127
            ->from(Exam::class, 'eInner')
128
            ->leftJoin('eInner.tuitions', 'tInner')
129
            ->leftJoin('tInner.studyGroup', 'sInner')
130
            ->where('sInner.id = :studyGroup');
131
132
        $qb
133
            ->andWhere($qb->expr()->in('e.id', $qbInner->getDQL()))
134
            ->setParameter('studyGroup', $studyGroup->getId());
135
136
        return $qb->getQuery()->getScalarResult();
137
    }
138
139
    /**
140
     * @inheritDoc
141
     */
142
    public function findAllByTeacher(Teacher $teacher, ?DateTime $today = null, bool $onlyToday = false, bool $onlyPlanned = true) {
143
        $qb = $this->getDefaultQueryBuilder($today, $onlyToday, $onlyPlanned);
144
145
        $qbInner = $this->em->createQueryBuilder()
146
            ->select('eInner.id')
147
            ->from(Exam::class, 'eInner')
148
            ->leftJoin('eInner.supervisions', 'sInner')
149
            ->leftJoin('eInner.tuitions', 'tInner')
150
            ->leftJoin('tInner.teachers', 'teacherInner')
151
            ->andWhere(
152
                $qb->expr()->orX(
153
                    'teacherInner.id = :teacher',
154
                    'sInner.teacher = :teacher'
155
                )
156
            );
157
158
        $qb
159
            ->andWhere($qb->expr()->in('e.id', $qbInner->getDQL()))
160
            ->setParameter('teacher', $teacher->getId());
161
162
        return $qb->getQuery()->getResult();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $qb->getQuery()->getResult() also could return the type integer which is incompatible with the return type mandated by App\Repository\ExamRepos...ace::findAllByTeacher() of App\Entity\Exam[].
Loading history...
163
    }
164
165
    /**
166
     * @inheritDoc
167
     */
168
    public function findAllDatesByTeacher(Teacher $teacher, ?DateTime $today = null, bool $onlyToday = false, bool $onlyPlanned = true) {
169
        $qb = $this->getDefaultQueryBuilder($today, $onlyToday, $onlyPlanned)
170
            ->select(['e.date', 'COUNT(DISTINCT e.id) AS count'])
171
            ->groupBy('e.date');
172
173
        $qbInner = $this->em->createQueryBuilder()
174
            ->select('eInner.id')
175
            ->from(Exam::class, 'eInner')
176
            ->leftJoin('eInner.supervisions', 'sInner')
177
            ->leftJoin('eInner.tuitions', 'tInner')
178
            ->leftJoin('tInner.teachers', 'teacherInner')
179
            ->andWhere(
180
                $qb->expr()->orX(
181
                    'teacherInner.id = :teacher',
182
                    'sInner.teacher = :teacher',
183
                )
184
            );
185
186
        $qb
187
            ->andWhere($qb->expr()->in('e.id', $qbInner->getDQL()))
188
            ->setParameter('teacher', $teacher->getId());
189
190
        return $qb->getQuery()->getScalarResult();
191
    }
192
193
    /**
194
     * @inheritDoc
195
     */
196
    public function findAllByStudents(array $students, ?DateTime $today = null, bool $onlyToday = false, bool $onlyPlanned = true) {
197
        $qb = $this->getDefaultQueryBuilder($today, $onlyToday, $onlyPlanned);
198
199
        $studentIds = array_map(fn(Student $student) => $student->getId(), $students);
200
201
        $qbInner = $this->em->createQueryBuilder()
202
            ->select('eInner.id')
203
            ->from(Exam::class, 'eInner')
204
            ->leftJoin('eInner.students', 'sInner')
205
            ->where(
206
                $qb->expr()->in('sInner.id', ':studentIds')
207
            );
208
209
        $qb
210
            ->andWhere($qb->expr()->in('e.id', $qbInner->getDQL()))
211
            ->setParameter('studentIds', $studentIds);
212
213
        return $qb->getQuery()->getResult();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $qb->getQuery()->getResult() also could return the type integer which is incompatible with the return type mandated by App\Repository\ExamRepos...ce::findAllByStudents() of App\Entity\Exam[].
Loading history...
214
    }
215
216
    /**
217
     * @inheritDoc
218
     */
219
    public function findAllDatesByStudents(array $students, ?DateTime $today = null, bool $onlyToday = false, bool $onlyPlanned = true) {
220
        $qb = $this->getDefaultQueryBuilder($today, $onlyToday, $onlyPlanned)
221
            ->select(['e.date', 'COUNT(DISTINCT e.id) AS count'])
222
            ->groupBy('e.date');
223
224
        $studentIds = array_map(fn(Student $student) => $student->getId(), $students);
225
226
        $qbInner = $this->em->createQueryBuilder()
227
            ->select('eInner.id')
228
            ->from(Exam::class, 'eInner')
229
            ->leftJoin('eInner.students', 'sInner')
230
            ->where(
231
                $qb->expr()->in('sInner.id', ':studentIds')
232
            );
233
234
        $qb
235
            ->andWhere($qb->expr()->in('e.id', $qbInner->getDQL()))
236
            ->setParameter('studentIds', $studentIds);
237
238
        return $qb->getQuery()->getScalarResult();
239
    }
240
241
    /**
242
     * @inheritDoc
243
     */
244
    public function findAllByGrade(Grade $grade, ?DateTime $today = null, bool $onlyToday = false, bool $onlyPlanned = true) {
245
        $qb = $this->getDefaultQueryBuilder($today, $onlyToday, $onlyPlanned);
246
247
        $qbInner = $this->em->createQueryBuilder()
248
            ->select('eInner.id')
249
            ->from(Exam::class, 'eInner')
250
            ->leftJoin('eInner.tuitions', 'tInner')
251
            ->leftJoin('tInner.studyGroup', 'sgInner')
252
            ->leftJoin('sgInner.grades', 'gInner')
253
            ->where('gInner.id = :grade');
254
255
        $qb
256
            ->andWhere($qb->expr()->in('e.id', $qbInner->getDQL()))
257
            ->setParameter('grade', $grade->getId());
258
259
        return $qb->getQuery()->getResult();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $qb->getQuery()->getResult() also could return the type integer which is incompatible with the return type mandated by App\Repository\ExamRepos...rface::findAllByGrade() of App\Entity\Exam[].
Loading history...
260
    }
261
262
    /**
263
     * @inheritDoc
264
     */
265
    public function findAllDatesByGrade(Grade $grade, ?DateTime $today = null, bool $onlyToday = false, bool $onlyPlanned = true) {
266
        $qb = $this->getDefaultQueryBuilder($today, $onlyToday, $onlyPlanned)
267
            ->select(['e.date', 'COUNT(DISTINCT e.id) AS count'])
268
            ->groupBy('e.date');
269
270
        $qbInner = $this->em->createQueryBuilder()
271
            ->select('eInner.id')
272
            ->from(Exam::class, 'eInner')
273
            ->leftJoin('eInner.tuitions', 'tInner')
274
            ->leftJoin('tInner.studyGroup', 'sgInner')
275
            ->leftJoin('sgInner.grades', 'gInner')
276
            ->where('gInner.id = :grade');
277
278
        $qb
279
            ->andWhere($qb->expr()->in('e.id', $qbInner->getDQL()))
280
            ->setParameter('grade', $grade->getId());
281
282
        return $qb->getQuery()->getScalarResult();
283
    }
284
285
    /**
286
     * @inheritDoc
287
     */
288
    public function findAllByDate(DateTime $today): array {
289
        $qb = $this->getDefaultQueryBuilder($today, true);
290
        return $qb->getQuery()->getResult();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $qb->getQuery()->getResult() could return the type integer which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
291
    }
292
293
    /**
294
     * @inheritDoc
295
     */
296
    public function findAllByDateAndLesson(DateTime $today, int $lesson): array {
297
        $qb = $this->getDefaultQueryBuilder($today, true);
298
299
        $qb
300
            ->andWhere('e.lessonStart <= :lesson AND e.lessonEnd >= :lesson')
301
            ->setParameter('lesson', $lesson);
302
303
        return $qb->getQuery()->getResult();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $qb->getQuery()->getResult() could return the type integer which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
304
    }
305
306
    /**
307
     * @inheritDoc
308
     */
309
    public function findAllByRoomAndDate(Room $room, DateTime $today): array {
310
        $qb = $this->getDefaultQueryBuilder($today, true);
311
312
        $qb
313
            ->andWhere('e.room = :room')
314
            ->setParameter('room', $room->getId());
315
316
        return $qb->getQuery()->getResult();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $qb->getQuery()->getResult() could return the type integer which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
317
    }
318
319
    /**
320
     * @inheritDoc
321
     */
322
    public function findAllByRoomAndDateAndLesson(Room $room, DateTime $today, int $lesson): array {
323
        $qb = $this->getDefaultQueryBuilder($today, true);
324
325
        $qb
326
            ->andWhere('e.lessonStart <= :lesson AND e.lessonEnd >= :lesson')
327
            ->setParameter('lesson', $lesson)
328
            ->andWhere('e.room = :room')
329
            ->setParameter('room', $room->getId());
330
331
        return $qb->getQuery()->getResult();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $qb->getQuery()->getResult() could return the type integer which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
332
    }
333
334
    /**
335
     * @inheritDoc
336
     */
337
    public function findAll(?DateTime $today = null, bool $onlyToday = false, bool $onlyPlanned = true) {
338
        return $this->getDefaultQueryBuilder($today, $onlyToday, $onlyPlanned)
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getDefault...getQuery()->getResult() also could return the type integer which is incompatible with the return type mandated by App\Repository\ExamRepositoryInterface::findAll() of App\Entity\Exam[].
Loading history...
339
            ->getQuery()
340
            ->getResult();
341
    }
342
343
    /**
344
     * @inheritDoc
345
     */
346
    public function findAllDates(?DateTime $today = null, bool $onlyPlanned = true) {
347
        return $this->getDefaultQueryBuilder($today, false, $onlyPlanned)
348
            ->select(['e.date', 'COUNT(DISTINCT e.id) AS count'])
349
            ->groupBy('e.date')
350
            ->getQuery()
351
            ->getScalarResult();
352
    }
353
354
    /**
355
     * @inheritDoc
356
     */
357
    public function findAllExternal(DateTime $today = null) {
358
        $qb = $this->getDefaultQueryBuilder($today);
359
360
        return $qb->andWhere($qb->expr()->isNotNull('e.externalId'))
0 ignored issues
show
Bug Best Practice introduced by
The expression return $qb->andWhere($qb...getQuery()->getResult() also could return the type integer which is incompatible with the return type mandated by App\Repository\ExamRepos...face::findAllExternal() of App\Entity\Exam[].
Loading history...
361
            ->getQuery()
362
            ->getResult();
363
    }
364
365
    public function findAllExternalWithRange(DateTime $start, DateTime $end): array {
366
        $qb = $this->getDefaultQueryBuilder(null)
367
            ->andWhere('e.date >= :start')
368
            ->andWhere('e.date <= :end')
369
            ->setParameter('start', $start)
370
            ->setParameter('end', $end);
371 2
372 2
        return $qb->andWhere($qb->expr()->isNotNull('e.externalId'))
0 ignored issues
show
Bug Best Practice introduced by
The expression return $qb->andWhere($qb...getQuery()->getResult() could return the type integer which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
373
            ->getQuery()
374 2
            ->getResult();
375 2
    }
376 2
377
    public function persist(Exam $exam): void {
378
        $this->em->persist($exam);
379
        $this->flushIfNotInTransaction();
380
    }
381
382 2
    public function remove(Exam $exam): void {
383 2
        $this->em->remove($exam);
384 2
        $this->flushIfNotInTransaction();
385 2
    }
386
387
    public function removeBetween(DateTime $start, DateTime $end): int {
388
        return $this->em->createQueryBuilder()
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->em->create...->getQuery()->execute() could return the type array<mixed,mixed> which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
389
            ->delete(Exam::class, 'e')
390
            ->where('e.date >= :start')
391
            ->andWhere('e.date <= :end')
392
            ->setParameter('start', $start)
393
            ->setParameter('end', $end)
394
            ->getQuery()
395
            ->execute();
396
    }
397
398
    /**
399
     * @inheritDoc
400
     */
401
    public function getPaginator(int $itemsPerPage, int &$page, ?Grade $grade = null, ?Teacher $teacher = null, ?Student $student = null, ?StudyGroup $studyGroup = null, bool $onlyPlanned = true, ?DateTime $today = null, ?DateTime $end = null, ?Section $section = null): Paginator {
402
        $qb = $this->getDefaultQueryBuilder($today, false, $onlyPlanned);
403
404
        if($end !== null) {
405
            $qb->andWhere('e.date <= :end')
406
                ->setParameter('end', $end);
407
        }
408
409
        $qbInner = $this->em->createQueryBuilder()
410
            ->select('eInner.id')
411
            ->from(Exam::class, 'eInner')
412
            ->leftJoin('eInner.tuitions', 'tInner')
413
            ->leftJoin('tInner.studyGroup', 'sgInner')
414
            ->leftJoin('sgInner.grades', 'gInner');
415
416
        if($grade !== null) {
417
            $qbInner->where('gInner.id = :grade');
418
            $qb->setParameter('grade', $grade->getId());
419
        }
420
421
        if($teacher !== null) {
422
            $qbInner
423
                 ->leftJoin('eInner.supervisions', 'sInner')
424
                 ->leftJoin('tInner.teachers', 'ttInner')
425
                 ->andWhere(
426
                     $qbInner->expr()->orX(
427
                         'ttInner.id = :teacher',
428
                         'sInner.teacher = :teacher'
429
                     )
430
                 );
431
             $qb->setParameter('teacher', $teacher->getId());
432
        }
433
434
        if($student !== null) {
435
            $qbInner
436
                ->leftJoin('eInner.students', 'sInner')
437
                ->andWhere('sInner.id = :student');
438
            $qb->setParameter('student', $student->getId());
439
        }
440
441
        if($studyGroup !== null) {
442
            $qbInner
443
                ->andWhere('sgInner.id = :studygroup');
444
            $qb->setParameter('studygroup', $studyGroup->getId());
445
        }
446
447
        if($section !== null) {
448
            $qb->leftJoin('t.section', 'section')
449
                ->andWhere('section.id = :section')
450
                ->setParameter('section', $section->getId());
451
        }
452
453
        $qb
454
            ->andWhere($qb->expr()->in('e.id', $qbInner->getDQL()))
455
            ->orderBy('e.date', 'asc');
456
457
        if(!is_numeric($page) || $page < 1) {
0 ignored issues
show
introduced by
The condition is_numeric($page) is always true.
Loading history...
458
            $page = 1;
459
        }
460
461
        $offset = ($page - 1) * $itemsPerPage;
462
463
        $paginator = new Paginator($qb);
464
        $paginator->getQuery()
465
            ->setMaxResults($itemsPerPage)
466
            ->setFirstResult($offset);
467
468
        return $paginator;
469
    }
470
471
}