Passed
Push — master ( 79866c...d57250 )
by Marcel
09:45
created

StudentAbsenceRepository::removeRange()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 8
nc 1
nop 2
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace App\Repository;
4
5
use App\Entity\Grade;
6
use App\Entity\Section;
7
use App\Entity\StudentAbsence;
8
use App\Entity\Student;
9
use App\Entity\StudentAbsenceType;
10
use DateTime;
11
use Doctrine\ORM\QueryBuilder;
12
use Doctrine\ORM\Tools\Pagination\Paginator;
13
14
class StudentAbsenceRepository extends AbstractRepository implements StudentAbsenceRepositoryInterface {
15
16
    public function persist(StudentAbsence $note): void {
17
        $this->em->persist($note);
18
        $this->em->flush();
19
    }
20
21
    public function remove(StudentAbsence $note): void {
22
        $this->em->remove($note);
23
        $this->em->flush();
24
    }
25
26
    /**
27
     * @inheritDoc
28
     */
29
    public function removeExpired(DateTime $threshold): int {
30
        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...
31
            ->delete(StudentAbsence::class, 's')
32
            ->where('s.until.date < :threshold')
33
            ->setParameter('threshold', $threshold)
34
            ->getQuery()
35
            ->execute();
36
    }
37
38
    public function removeRange(DateTime $start, DateTime $end): int {
39
        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...
40
            ->delete(StudentAbsence::class, 's')
41
            ->where('s.until.date >= :start')
42
            ->andWhere('s.until.date <= :end')
43
            ->setParameter('start', $start)
44
            ->setParameter('end', $end)
45
            ->getQuery()
46
            ->execute();
47
    }
48
49
    /**
50
     * @inheritDoc
51
     */
52
    public function findByStudents(array $students, ?StudentAbsenceType $type = null, ?DateTime $date = null, ?int $lesson = null): array {
53
        $ids = array_map(fn(Student $student) => $student->getId(), $students);
54
55
        $qb = $this->em->createQueryBuilder()
56
            ->select('sn', 's')
57
            ->from(StudentAbsence::class, 'sn')
58
            ->leftJoin('sn.student', 's');
59
60
        $qb->where($qb->expr()->in('s.id', ':students'))
61
            ->setParameter('students', $ids);
62
63
        $this->applyTypeIfGiven($qb, $type);
64
65
        if($date != null && $lesson != null) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $lesson of type integer|null against null; this is ambiguous if the integer can be zero. Consider using a strict comparison !== instead.
Loading history...
66
            $qb->andWhere(
67
                // start
68
                $qb->expr()->orX(
69
                    'sn.from.date < :date',
70
                    $qb->expr()->andX(
71
                        'sn.from.date = :date',
72
                        'sn.from.lesson <= :lesson'
73
                    )
74
                )
75
            );
76
            $qb->andWhere(
77
                // end
78
                $qb->expr()->orX(
79
                    'sn.until.date > :date',
80
                    $qb->expr()->andX(
81
                        'sn.until.date = :date',
82
                        'sn.until.lesson >= :lesson'
83
                    )
84
                )
85
            );
86
            $qb->setParameter('date', $date);
87
            $qb->setParameter('lesson', $lesson);
88
        } if($date !== null) {
89
            $this->applyDate($qb, $date);
90
        }
91
92
        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...
93
    }
94
95
    /**
96
     * @inheritDoc
97
     */
98
    public function findAll(?DateTime $date = null): array {
99
        $qb = $this->em->createQueryBuilder()
100
            ->select('sn', 's')
101
            ->from(StudentAbsence::class, 'sn')
102
            ->leftJoin('sn.student', 's');
103
104
        if($date !== null) {
105
            $this->applyDate($qb, $date);
106
        }
107
108
        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...
109
    }
110
111
    public function findAllUuids(DateTime $start, DateTime $end): array {
112
        return
113
            array_map(
114
                fn($row) => $row['uuid'],
115
                $this->em->createQueryBuilder()
116
                ->select('a.uuid')
117
                ->from(StudentAbsence::class, 'a')
118
                ->where('a.from.date >= :start')
119
                ->andWhere('a.until.date <= :end')
120
                ->setParameter('start', $start)
121
                ->setParameter('end', $end)
122
                ->getQuery()
123
                ->getScalarResult()
124
            );
125
    }
126
127
    private function applyDate(QueryBuilder $qb, DateTime $date) {
128
        $qb->andWhere('sn.from.date <= :date');
129
        $qb->andWhere('sn.until.date >= :date');
130
        $qb->setParameter('date', $date);
131
    }
132
133
    private function createPaginatorForQueryBuilder(QueryBuilder $queryBuilder, int $itemsPerPage, int &$page): Paginator {
134
        if(!is_numeric($page) || $page < 1) {
0 ignored issues
show
introduced by
The condition is_numeric($page) is always true.
Loading history...
135
            $page = 1;
136
        }
137
138
        $offset = ($page - 1) * $itemsPerPage;
139
        $paginator = new Paginator($queryBuilder);
140
        $paginator->getQuery()
141
            ->setMaxResults($itemsPerPage)
142
            ->setFirstResult($offset);
143
144
        return $paginator;
145
    }
146
147
    private function applyTypeIfGiven(QueryBuilder $queryBuilder, ?StudentAbsenceType $type): void {
148
        if($type !== null) {
149
            $queryBuilder->leftJoin('sn.type', 't')
150
                ->andWhere('t.id = :type')
151
                ->setParameter('type', $type->getId());
152
        }
153
154
    }
155
156
    public function getPaginator(?StudentAbsenceType $type, int $itemsPerPage, int &$page): Paginator {
157
        $qb = $this->em->createQueryBuilder()
158
            ->select('sn', 's')
159
            ->from(StudentAbsence::class, 'sn')
160
            ->leftJoin('sn.student', 's')
161
            ->orderBy('sn.until.date', 'desc');
162
163
        $this->applyTypeIfGiven($qb, $type);
164
165
        return $this->createPaginatorForQueryBuilder($qb, $itemsPerPage, $page);
166
    }
167
168
    public function getStudentPaginator(Student $student, ?StudentAbsenceType $type, int $itemsPerPage, int &$page): Paginator {
169
        $qb = $this->em->createQueryBuilder()
170
            ->select('sn', 's')
171
            ->from(StudentAbsence::class, 'sn')
172
            ->leftJoin('sn.student', 's');
173
174
        $qb->where('s.id = :student')
175
            ->setParameter('student', $student->getId())
176
            ->orderBy('sn.until.date', 'desc');
177
178
        $this->applyTypeIfGiven($qb, $type);
179
180
        return $this->createPaginatorForQueryBuilder($qb, $itemsPerPage, $page);
181
    }
182
183
    public function getGradePaginator(Grade $grade, Section $section, ?StudentAbsenceType $type, int $itemsPerPage, int &$page): Paginator {
184
        $qb = $this->em->createQueryBuilder()
185
            ->select('sn', 's')
186
            ->from(StudentAbsence::class, 'sn')
187
            ->leftJoin('sn.student', 's')
188
            ->leftJoin('s.gradeMemberships', 'gm')
189
            ->leftJoin('gm.section', 'sec')
190
            ->leftJoin('gm.grade', 'g')
191
            ->where('g.id = :grade')
192
            ->andWhere('sec.id = :section')
193
            ->setParameter('grade', $grade->getId())
194
            ->setParameter('section', $section->getId())
195
            ->orderBy('sn.until.date', 'desc');
196
197
        $this->applyTypeIfGiven($qb, $type);
198
199
        return $this->createPaginatorForQueryBuilder($qb, $itemsPerPage, $page);
200
    }
201
202
    /**
203
     * @inheritDoc
204
     */
205
    public function getStudentsPaginator(array $students, DateTime $date, ?StudentAbsenceType $type, int $itemsPerPage, int &$page): Paginator {
206
        $ids = array_map(fn(Student $student) => $student->getId(), $students);
207
208
        $qb = $this->em->createQueryBuilder()
209
            ->select('sn', 's')
210
            ->from(StudentAbsence::class, 'sn')
211
            ->leftJoin('sn.student', 's');
212
213
        $qb->where($qb->expr()->in('s.id', ':students'))
214
            ->setParameter('students', $ids)
215
            ->andWhere('sn.from.date <= :date')
216
            ->andWhere('sn.until.date >= :date')
217
            ->orderBy('sn.until.date', 'desc');
218
219
        $this->applyTypeIfGiven($qb, $type);
220
221
        return $this->createPaginatorForQueryBuilder($qb, $itemsPerPage, $page);
222
    }
223
}