Passed
Push — master ( 20f36e...862b31 )
by Marcel
10:03
created

StudentAbsenceRepository::persist()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 1
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
    /**
39
     * @inheritDoc
40
     */
41
    public function findByStudents(array $students, ?StudentAbsenceType $type = null, ?DateTime $date = null, ?int $lesson = null): array {
42
        $ids = array_map(fn(Student $student) => $student->getId(), $students);
43
44
        $qb = $this->em->createQueryBuilder()
45
            ->select('sn', 's')
46
            ->from(StudentAbsence::class, 'sn')
47
            ->leftJoin('sn.student', 's');
48
49
        $qb->where($qb->expr()->in('s.id', ':students'))
50
            ->setParameter('students', $ids);
51
52
        $this->applyTypeIfGiven($qb, $type);
53
54
        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...
55
            $qb->andWhere(
56
                // start
57
                $qb->expr()->orX(
58
                    'sn.from.date < :date',
59
                    $qb->expr()->andX(
60
                        'sn.from.date = :date',
61
                        'sn.from.lesson <= :lesson'
62
                    )
63
                )
64
            );
65
            $qb->andWhere(
66
                // end
67
                $qb->expr()->orX(
68
                    'sn.until.date > :date',
69
                    $qb->expr()->andX(
70
                        'sn.until.date = :date',
71
                        'sn.until.lesson >= :lesson'
72
                    )
73
                )
74
            );
75
            $qb->setParameter('date', $date);
76
            $qb->setParameter('lesson', $lesson);
77
        } if($date !== null) {
78
            $this->applyDate($qb, $date);
79
        }
80
81
        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...
82
    }
83
84
    /**
85
     * @inheritDoc
86
     */
87
    public function findAll(?DateTime $date = null): array {
88
        $qb = $this->em->createQueryBuilder()
89
            ->select('sn', 's')
90
            ->from(StudentAbsence::class, 'sn')
91
            ->leftJoin('sn.student', 's');
92
93
        if($date !== null) {
94
            $this->applyDate($qb, $date);
95
        }
96
97
        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...
98
    }
99
100
    public function findAllUuids(DateTime $start, DateTime $end): array {
101
        return
102
            array_map(
103
                fn($row) => $row['uuid'],
104
                $this->em->createQueryBuilder()
105
                ->select('a.uuid')
106
                ->from(StudentAbsence::class, 'a')
107
                ->where('a.from.date >= :start')
108
                ->andWhere('a.until.date <= :end')
109
                ->setParameter('start', $start)
110
                ->setParameter('end', $end)
111
                ->getQuery()
112
                ->getScalarResult()
113
            );
114
    }
115
116
    private function applyDate(QueryBuilder $qb, DateTime $date) {
117
        $qb->andWhere('sn.from.date <= :date');
118
        $qb->andWhere('sn.until.date >= :date');
119
        $qb->setParameter('date', $date);
120
    }
121
122
    private function createPaginatorForQueryBuilder(QueryBuilder $queryBuilder, int $itemsPerPage, int &$page): Paginator {
123
        if(!is_numeric($page) || $page < 1) {
0 ignored issues
show
introduced by
The condition is_numeric($page) is always true.
Loading history...
124
            $page = 1;
125
        }
126
127
        $offset = ($page - 1) * $itemsPerPage;
128
        $paginator = new Paginator($queryBuilder);
129
        $paginator->getQuery()
130
            ->setMaxResults($itemsPerPage)
131
            ->setFirstResult($offset);
132
133
        return $paginator;
134
    }
135
136
    private function applyTypeIfGiven(QueryBuilder $queryBuilder, ?StudentAbsenceType $type): void {
137
        if($type !== null) {
138
            $queryBuilder->leftJoin('sn.type', 't')
139
                ->andWhere('t.id = :type')
140
                ->setParameter('type', $type->getId());
141
        }
142
143
    }
144
145
    public function getPaginator(?StudentAbsenceType $type, int $itemsPerPage, int &$page): Paginator {
146
        $qb = $this->em->createQueryBuilder()
147
            ->select('sn', 's')
148
            ->from(StudentAbsence::class, 'sn')
149
            ->leftJoin('sn.student', 's')
150
            ->orderBy('sn.until.date', 'desc');
151
152
        $this->applyTypeIfGiven($qb, $type);
153
154
        return $this->createPaginatorForQueryBuilder($qb, $itemsPerPage, $page);
155
    }
156
157
    public function getStudentPaginator(Student $student, ?StudentAbsenceType $type, int $itemsPerPage, int &$page): Paginator {
158
        $qb = $this->em->createQueryBuilder()
159
            ->select('sn', 's')
160
            ->from(StudentAbsence::class, 'sn')
161
            ->leftJoin('sn.student', 's');
162
163
        $qb->where('s.id = :student')
164
            ->setParameter('student', $student->getId())
165
            ->orderBy('sn.until.date', 'desc');
166
167
        $this->applyTypeIfGiven($qb, $type);
168
169
        return $this->createPaginatorForQueryBuilder($qb, $itemsPerPage, $page);
170
    }
171
172
    public function getGradePaginator(Grade $grade, Section $section, ?StudentAbsenceType $type, int $itemsPerPage, int &$page): Paginator {
173
        $qb = $this->em->createQueryBuilder()
174
            ->select('sn', 's')
175
            ->from(StudentAbsence::class, 'sn')
176
            ->leftJoin('sn.student', 's')
177
            ->leftJoin('s.gradeMemberships', 'gm')
178
            ->leftJoin('gm.section', 'sec')
179
            ->leftJoin('gm.grade', 'g')
180
            ->where('g.id = :grade')
181
            ->andWhere('sec.id = :section')
182
            ->setParameter('grade', $grade->getId())
183
            ->setParameter('section', $section->getId())
184
            ->orderBy('sn.until.date', 'desc');
185
186
        $this->applyTypeIfGiven($qb, $type);
187
188
        return $this->createPaginatorForQueryBuilder($qb, $itemsPerPage, $page);
189
    }
190
191
    /**
192
     * @inheritDoc
193
     */
194
    public function getStudentsPaginator(array $students, DateTime $date, ?StudentAbsenceType $type, int $itemsPerPage, int &$page): Paginator {
195
        $ids = array_map(fn(Student $student) => $student->getId(), $students);
196
197
        $qb = $this->em->createQueryBuilder()
198
            ->select('sn', 's')
199
            ->from(StudentAbsence::class, 'sn')
200
            ->leftJoin('sn.student', 's');
201
202
        $qb->where($qb->expr()->in('s.id', ':students'))
203
            ->setParameter('students', $ids)
204
            ->andWhere('sn.from.date <= :date')
205
            ->andWhere('sn.until.date >= :date')
206
            ->orderBy('sn.until.date', 'desc');
207
208
        $this->applyTypeIfGiven($qb, $type);
209
210
        return $this->createPaginatorForQueryBuilder($qb, $itemsPerPage, $page);
211
    }
212
}