Passed
Push — master ( d57a01...9aa081 )
by Marcel
08:19
created

LessonAttendanceRepository::applyTuition()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 15
c 0
b 0
f 0
dl 0
loc 23
rs 9.7666
cc 2
nc 2
nop 2
1
<?php
2
3
namespace App\Repository;
4
5
use App\Entity\LessonAttendance;
6
use App\Entity\LessonAttendanceType;
7
use App\Entity\LessonEntry;
8
use App\Entity\Student;
9
use App\Entity\Tuition;
10
use DateTime;
11
use Doctrine\ORM\QueryBuilder;
12
13
class LessonAttendanceRepository extends AbstractRepository implements LessonAttendanceRepositoryInterface {
14
15
    public function findAbsentByStudentsAndDate(array $students, DateTime $dateTime): array {
16
        $studentIds = array_map(fn(Student $student) => $student->getId(), $students);
17
18
        $qb = $this->em->createQueryBuilder();
19
20
        $qb->select(['a', 's', 'e', 'l'])
21
            ->from(LessonAttendance::class, 'a')
22
            ->leftJoin('a.student', 's')
23
            ->leftJoin('a.entry', 'e')
24
            ->leftJoin('e.lesson', 'l')
25
            ->where($qb->expr()->in('s.id', ':students'))
26
            ->andWhere('l.date = :date')
27
            ->andWhere('a.type = :type')
28
            ->setParameter('students', $studentIds)
29
            ->setParameter('date', $dateTime)
30
            ->setParameter('type', LessonAttendanceType::Absent);
31
32
        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...
33
    }
34
35
    public function persist(LessonAttendance $attendance): void {
36
        $this->em->persist($attendance);
37
        $this->em->flush();
38
    }
39
40
    public function remove(LessonAttendance $attendance): void {
41
        $this->em->remove($attendance);
42
        $this->em->flush();
43
    }
44
45
46
    private function countAttendance(LessonEntry $entry, int $type): int {
47
        return $this->em
48
            ->createQueryBuilder()
49
            ->select('COUNT(a.id)')
50
            ->from(LessonAttendance::class, 'a')
51
            ->leftJoin('a.entry', 'e')
52
            ->where('e.id = :entry')
53
            ->andWhere('a.type = :type')
54
            ->setParameter('entry', $entry->getId())
55
            ->setParameter('type', $type)
56
            ->getQuery()
57
            ->getSingleScalarResult();
58
    }
59
60
    public function countAbsent(LessonEntry $entry): int {
61
        return $this->countAttendance($entry, LessonAttendanceType::Absent);
62
    }
63
64
    public function countPresent(LessonEntry $entry): int {
65
        return $this->countAttendance($entry, LessonAttendanceType::Present);
66
    }
67
68
    public function countLate(LessonEntry $entry): int {
69
        return $this->countAttendance($entry, LessonAttendanceType::Late);
70
    }
71
72
    private function getDefaultQueryBuilder(): QueryBuilder {
73
        return $this->em->createQueryBuilder()
74
            ->select(['a', 'e', 'l'])
75
            ->from(LessonAttendance::class, 'a')
76
            ->leftJoin('a.entry', 'e')
77
            ->leftJoin('a.student', 's')
78
            ->leftJoin('e.lesson', 'l');
79
    }
80
81
    private function applyTuition(QueryBuilder $queryBuilder, array $tuitions): QueryBuilder {
82
        if(count($tuitions) === 0) {
83
            return $queryBuilder;
84
        }
85
86
        $qbInner = $this->em->createQueryBuilder()
87
            ->select(['aInner.id'])
88
            ->from(LessonAttendance::class, 'aInner')
89
            ->leftJoin('aInner.entry', 'eInner')
90
            ->leftJoin('eInner.tuition', 'tInner')
91
            ->where('tInner.id IN(:tuitions)');
92
93
        $ids = array_map(fn(Tuition $tuition) => $tuition->getId(), $tuitions);
94
95
        $queryBuilder
96
            ->andWhere(
97
                $queryBuilder->expr()->in(
98
                    'a.id', $qbInner->getDQL()
99
                )
100
            )
101
            ->setParameter('tuitions', $ids);
102
103
        return $queryBuilder;
104
    }
105
106
    public function findByStudent(Student $student, array $tuitions): array {
107
        $qb = $this->getDefaultQueryBuilder()
108
            ->where('s.id = :student')
109
            ->setParameter('student', $student->getId());
110
        $this->applyTuition($qb, $tuitions);
111
112
        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...
113
    }
114
115
    public function findLateByStudent(Student $student, array $tuitions): array {
116
        $qb = $this->getDefaultQueryBuilder()
117
            ->where('s.id = :student')
118
            ->andWhere('a.type = :type')
119
            ->setParameter('student', $student->getId())
120
            ->setParameter('type', LessonAttendanceType::Late);
121
        $this->applyTuition($qb, $tuitions);
122
123
        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...
124
    }
125
126
    public function findAbsentByStudent(Student $student, array $tuitions): array {
127
        $qb = $this->getDefaultQueryBuilder()
128
            ->where('s.id = :student')
129
            ->andWhere('a.type = :type')
130
            ->setParameter('student', $student)
131
            ->setParameter('type', LessonAttendanceType::Absent);
132
        $this->applyTuition($qb, $tuitions);
133
134
        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...
135
    }
136
137
    public function findAbsentByStudents(array $students, array $tuitions): array {
138
        $studentIds = array_map(fn(Student $student) => $student->getId(), $students);
139
140
        $qb = $this->getDefaultQueryBuilder();
141
142
        $qb
143
            ->where($qb->expr()->in('s.id', ':students'))
144
            ->andWhere('a.type = :type')
145
            ->setParameter('students', $studentIds)
146
            ->setParameter('type', LessonAttendanceType::Absent);
147
        $this->applyTuition($qb, $tuitions);
148
149
        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...
150
    }
151
}