Total Complexity | 60 |
Total Lines | 525 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like SessionRepository often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use SessionRepository, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
28 | class SessionRepository extends ServiceEntityRepository |
||
29 | { |
||
30 | public function __construct( |
||
35 | } |
||
36 | |||
37 | public function create(): ?Session |
||
38 | { |
||
39 | return new Session(); |
||
40 | } |
||
41 | |||
42 | public function update(Session $session): void |
||
43 | { |
||
44 | $this->getEntityManager()->persist($session); |
||
45 | $this->getEntityManager()->flush(); |
||
46 | } |
||
47 | |||
48 | /** |
||
49 | * @return array<SessionRelUser> |
||
50 | */ |
||
51 | public function getUsersByAccessUrl(Session $session, AccessUrl $url, array $relationTypeList = []): array |
||
67 | } |
||
68 | |||
69 | public function getSessionsByUser(User $user, AccessUrl $url): QueryBuilder |
||
70 | { |
||
71 | $qb = $this->createQueryBuilder('s'); |
||
72 | $qb |
||
73 | ->innerJoin('s.users', 'sru') |
||
74 | ->leftJoin('s.urls', 'urls') |
||
75 | ->where($qb->expr()->eq('sru.user', ':user')) |
||
76 | ->andWhere($qb->expr()->eq('urls.url', ':url')) |
||
77 | ->setParameters([ |
||
78 | 'user' => $user, |
||
79 | 'url' => $url, |
||
80 | ]) |
||
81 | ->orderBy('s.displayStartDate', 'ASC') |
||
82 | ->addOrderBy('s.title', 'ASC') |
||
83 | ->addOrderBy('s.position', 'ASC') |
||
84 | ; |
||
85 | |||
86 | return $qb; |
||
87 | } |
||
88 | |||
89 | /** |
||
90 | * @return array<int, Session> |
||
91 | * |
||
92 | * @throws Exception |
||
93 | */ |
||
94 | public function getPastSessionsOfUserInUrl(User $user, AccessUrl $url): array |
||
126 | } |
||
127 | |||
128 | /** |
||
129 | * @return array<int, Session> |
||
130 | * |
||
131 | * @throws Exception |
||
132 | */ |
||
133 | public function getCurrentSessionsOfUserInUrl( |
||
134 | User $user, |
||
135 | AccessUrl $url, |
||
136 | int $currentPage = 1, |
||
137 | int $itemsPerPage = 10 |
||
138 | ): array { |
||
139 | $qb = $this->getSessionsByUser($user, $url); |
||
140 | |||
141 | return $qb |
||
142 | ->andWhere( |
||
143 | $qb->expr()->orX( |
||
144 | $qb->expr()->isNull('sru.accessStartDate'), |
||
145 | $qb->expr()->isNull('sru.accessEndDate'), |
||
146 | $qb->expr()->andX( |
||
147 | $qb->expr()->lte('sru.accessStartDate', ':now'), |
||
148 | $qb->expr()->gte('sru.accessEndDate', ':now'), |
||
149 | ), |
||
150 | ) |
||
151 | ) |
||
152 | ->setParameter('now', new DateTime()) |
||
153 | ->setFirstResult(($currentPage - 1) * $itemsPerPage) |
||
154 | ->setMaxResults($itemsPerPage) |
||
155 | ->getQuery() |
||
156 | ->getResult(); |
||
157 | ; |
||
158 | } |
||
159 | |||
160 | /** |
||
161 | * @return array<int, Session> |
||
162 | * |
||
163 | * @throws Exception |
||
164 | */ |
||
165 | public function getUpcomingSessionsOfUserInUrl( |
||
166 | User $user, |
||
167 | AccessUrl $url, |
||
168 | int $currentPage = 1, |
||
169 | int $itemsPerPage = 10 |
||
170 | ): array { |
||
171 | $qb = $this->getSessionsByUser($user, $url); |
||
172 | |||
173 | return $qb |
||
174 | ->andWhere( |
||
175 | $qb->expr()->gt('sru.accessStartDate', ':now'), |
||
176 | ) |
||
177 | ->setParameter('now', new DateTime()) |
||
178 | ->setFirstResult(($currentPage - 1) * $itemsPerPage) |
||
179 | ->setMaxResults($itemsPerPage) |
||
180 | ->getQuery() |
||
181 | ->getResult(); |
||
182 | ; |
||
183 | } |
||
184 | |||
185 | public function addUserInCourse(int $relationType, User $user, Course $course, Session $session): void |
||
186 | { |
||
187 | if (!$user->isActive()) { |
||
188 | throw new Exception('User not active'); |
||
189 | } |
||
190 | |||
191 | if (!$session->hasCourse($course)) { |
||
192 | $msg = \sprintf('Course %s is not subscribed to the session %s', $course->getTitle(), $session->getTitle()); |
||
193 | |||
194 | throw new Exception($msg); |
||
195 | } |
||
196 | |||
197 | if (!\in_array($relationType, Session::getRelationTypeList(), true)) { |
||
198 | throw new Exception(\sprintf('Cannot handle relationType %s', $relationType)); |
||
199 | } |
||
200 | |||
201 | $entityManager = $this->getEntityManager(); |
||
202 | $existingRecord = $entityManager->getRepository(SessionRelUser::class)->findOneBy([ |
||
203 | 'session' => $session, |
||
204 | 'user' => $user, |
||
205 | 'relationType' => $relationType, |
||
206 | ]); |
||
207 | |||
208 | if ($existingRecord) { |
||
209 | $entityManager->remove($existingRecord); |
||
210 | $entityManager->flush(); |
||
211 | } |
||
212 | |||
213 | switch ($relationType) { |
||
214 | case Session::DRH: |
||
215 | if ($user->hasRole('ROLE_HR')) { |
||
216 | $session->addUserInSession(Session::DRH, $user); |
||
217 | } |
||
218 | |||
219 | break; |
||
220 | |||
221 | case Session::STUDENT: |
||
222 | $session |
||
223 | ->addUserInSession(Session::STUDENT, $user) |
||
224 | ->addUserInCourse(Session::STUDENT, $user, $course) |
||
225 | ; |
||
226 | |||
227 | break; |
||
228 | |||
229 | case Session::COURSE_COACH: |
||
230 | if ($user->hasRole('ROLE_TEACHER')) { |
||
231 | $session |
||
232 | ->addUserInSession(Session::COURSE_COACH, $user) |
||
233 | ->addUserInCourse( |
||
234 | Session::COURSE_COACH, |
||
235 | $user, |
||
236 | $course |
||
237 | ) |
||
238 | ; |
||
239 | } |
||
240 | |||
241 | break; |
||
242 | } |
||
243 | |||
244 | $entityManager->persist($session); |
||
245 | $entityManager->flush(); |
||
246 | } |
||
247 | |||
248 | /** |
||
249 | * @return array<SessionRelCourse> |
||
250 | */ |
||
251 | public function getSessionCoursesByStatusInUserSubscription(User $user, Session $session, int $relationType, ?AccessUrl $url = null): array |
||
252 | { |
||
253 | $qb = $this->getEntityManager()->createQueryBuilder(); |
||
254 | |||
255 | $qb->select('src') |
||
256 | ->from(SessionRelCourse::class, 'src') |
||
257 | ->innerJoin( |
||
258 | SessionRelUser::class, |
||
259 | 'sru', |
||
260 | Join::WITH, |
||
261 | 'src.session = sru.session' |
||
262 | ) |
||
263 | ->innerJoin('src.session', 'session') |
||
264 | ->where( |
||
265 | $qb->expr()->eq('session', ':session') |
||
266 | ) |
||
267 | ->andWhere( |
||
268 | $qb->expr()->eq('sru.user', ':user') |
||
269 | ) |
||
270 | ->andWhere( |
||
271 | $qb->expr()->eq('sru.relationType', ':relation_type') |
||
272 | ) |
||
273 | ; |
||
274 | |||
275 | $parameters = [ |
||
276 | 'session' => $session, |
||
277 | 'user' => $user, |
||
278 | 'relation_type' => $relationType, |
||
279 | ]; |
||
280 | |||
281 | if ($url) { |
||
282 | $qb->innerJoin('session.urls', 'urls') |
||
283 | ->andWhere( |
||
284 | $qb->expr()->eq('urls.url', ':url') |
||
285 | ) |
||
286 | ; |
||
287 | |||
288 | $parameters['url'] = $url; |
||
289 | } |
||
290 | |||
291 | $qb->setParameters($parameters); |
||
292 | |||
293 | return $qb->getQuery()->getResult(); |
||
294 | } |
||
295 | |||
296 | /** |
||
297 | * @return array<SessionRelCourse> |
||
298 | */ |
||
299 | public function getSessionCoursesByStatusInCourseSubscription(User $user, Session $session, int $status, ?AccessUrl $url = null): array |
||
300 | { |
||
301 | $qb = $this->getEntityManager()->createQueryBuilder(); |
||
302 | |||
303 | $qb->select('src') |
||
304 | ->from(SessionRelCourse::class, 'src') |
||
305 | ->innerJoin( |
||
306 | SessionRelCourseRelUser::class, |
||
307 | 'srcru', |
||
308 | Join::WITH, |
||
309 | 'src.session = srcru.session AND src.course = srcru.course' |
||
310 | ) |
||
311 | ->innerJoin('srcru.session', 'session') |
||
312 | ->where( |
||
313 | $qb->expr()->eq('session', ':session') |
||
314 | ) |
||
315 | ->andWhere( |
||
316 | $qb->expr()->eq('srcru.user', ':user') |
||
317 | ) |
||
318 | ->andWhere( |
||
319 | $qb->expr()->eq('srcru.status', ':status') |
||
320 | ) |
||
321 | ; |
||
322 | |||
323 | $parameters = [ |
||
324 | 'session' => $session, |
||
325 | 'user' => $user, |
||
326 | 'status' => $status, |
||
327 | ]; |
||
328 | |||
329 | if ($url) { |
||
330 | $qb->innerJoin('session.urls', 'urls') |
||
331 | ->andWhere( |
||
332 | $qb->expr()->eq('urls.url', ':url') |
||
333 | ) |
||
334 | ; |
||
335 | |||
336 | $parameters['url'] = $url; |
||
337 | } |
||
338 | |||
339 | $qb->setParameters($parameters); |
||
340 | |||
341 | return $qb->getQuery()->getResult(); |
||
342 | } |
||
343 | |||
344 | private function addSessionRelUserFilterByUrl(Session $session, AccessUrl $url): QueryBuilder |
||
360 | } |
||
361 | |||
362 | public function getUserFollowedSessionsInAccessUrl(User $user, AccessUrl $url): QueryBuilder |
||
363 | { |
||
364 | $callback = fn (Session $session) => $session->getId(); |
||
365 | |||
366 | if ($user->isHRM()) { |
||
367 | $idList = array_map($callback, $user->getDRHSessions()); |
||
368 | } elseif ($user->isTeacher() || COURSEMANAGER === $user->getStatus()) { |
||
369 | $idListAsCoach = $user |
||
370 | ->getSessionsByStatusInCourseSubscription(Session::COURSE_COACH) |
||
371 | ->map($callback) |
||
372 | ->getValues() |
||
373 | ; |
||
374 | $idListAsGeneralCoach = array_map($callback, $user->getSessionsAsGeneralCoach()); |
||
375 | $idList = array_merge($idListAsCoach, $idListAsGeneralCoach); |
||
376 | } elseif ($user->isSessionAdmin()) { |
||
377 | $idList = array_map($callback, $user->getSessionsAsAdmin()); |
||
378 | } else { |
||
379 | $idList = array_map($callback, $user->getSessionsAsStudent()); |
||
380 | } |
||
381 | |||
382 | $qb = $this->createQueryBuilder('s'); |
||
383 | $qb |
||
384 | ->innerJoin('s.urls', 'u') |
||
385 | ->where($qb->expr()->eq('u.url', $url->getId())) |
||
386 | ->andWhere($qb->expr()->in('s.id', ':id_list')) |
||
387 | ->setParameter('id_list', $idList) |
||
388 | ; |
||
389 | |||
390 | return $qb; |
||
391 | } |
||
392 | |||
393 | /** |
||
394 | * @return array<int, Session> |
||
395 | * |
||
396 | * @throws Exception |
||
397 | */ |
||
398 | public function getSubscribedSessionsOfUserInUrl( |
||
399 | User $user, |
||
400 | AccessUrl $url, |
||
401 | bool $ignoreVisibilityForAdmins = false, |
||
402 | ): array { |
||
403 | $sessions = $this->getSessionsByUser($user, $url)->getQuery()->getResult(); |
||
404 | |||
405 | $filterSessions = function (Session $session) use ($user, $ignoreVisibilityForAdmins) { |
||
406 | $visibility = $session->setAccessVisibilityByUser($user, $ignoreVisibilityForAdmins); |
||
407 | |||
408 | if (Session::VISIBLE !== $visibility) { |
||
409 | $closedOrHiddenCourses = $session->getClosedOrHiddenCourses(); |
||
410 | |||
411 | if ($closedOrHiddenCourses->count() === $session->getCourses()->count()) { |
||
412 | $visibility = Session::INVISIBLE; |
||
413 | } |
||
414 | } |
||
415 | |||
416 | switch ($visibility) { |
||
417 | case Session::READ_ONLY: |
||
418 | case Session::VISIBLE: |
||
419 | case Session::AVAILABLE: |
||
420 | break; |
||
421 | |||
422 | case Session::INVISIBLE: |
||
423 | if (!$ignoreVisibilityForAdmins) { |
||
424 | return false; |
||
425 | } |
||
426 | } |
||
427 | |||
428 | return true; |
||
429 | }; |
||
430 | |||
431 | return array_filter($sessions, $filterSessions); |
||
432 | } |
||
433 | |||
434 | /** |
||
435 | * Finds a valid child session based on access dates and reinscription days. |
||
436 | */ |
||
437 | public function findValidChildSession(Session $session): ?Session |
||
438 | { |
||
439 | $childSessions = $this->findChildSessions($session); |
||
440 | $now = new DateTime(); |
||
441 | |||
442 | foreach ($childSessions as $childSession) { |
||
443 | $startDate = $childSession->getAccessStartDate(); |
||
444 | $endDate = $childSession->getAccessEndDate(); |
||
445 | $daysToReinscription = $childSession->getDaysToReinscription(); |
||
446 | |||
447 | if (empty($daysToReinscription) || $daysToReinscription <= 0) { |
||
448 | continue; |
||
449 | } |
||
450 | |||
451 | $adjustedEndDate = (clone $endDate)->modify('-'.$daysToReinscription.' days'); |
||
452 | |||
453 | if ($startDate <= $now && $adjustedEndDate >= $now) { |
||
454 | return $childSession; |
||
455 | } |
||
456 | } |
||
457 | |||
458 | return null; |
||
459 | } |
||
460 | |||
461 | /** |
||
462 | * Finds a valid parent session based on access dates and reinscription days. |
||
463 | */ |
||
464 | public function findValidParentSession(Session $session): ?Session |
||
488 | } |
||
489 | |||
490 | /** |
||
491 | * Finds child sessions based on the parent session. |
||
492 | */ |
||
493 | public function findChildSessions(Session $parentSession): array |
||
494 | { |
||
495 | return $this->createQueryBuilder('s') |
||
496 | ->where('s.parentId = :parentId') |
||
497 | ->setParameter('parentId', $parentSession->getId()) |
||
498 | ->getQuery() |
||
499 | ->getResult() |
||
500 | ; |
||
501 | } |
||
502 | |||
503 | /** |
||
504 | * Finds the parent session for a given session. |
||
505 | */ |
||
506 | public function findParentSession(Session $session): ?Session |
||
513 | } |
||
514 | |||
515 | /** |
||
516 | * Find sessions without child and ready for repetition. |
||
517 | * |
||
518 | * @return Session[] |
||
519 | */ |
||
520 | public function findSessionsWithoutChildAndReadyForRepetition() |
||
521 | { |
||
522 | $currentDate = new DateTime(); |
||
523 | |||
524 | $qb = $this->createQueryBuilder('s') |
||
525 | ->where('s.daysToNewRepetition IS NOT NULL') |
||
526 | ->andWhere('s.lastRepetition = :false') |
||
527 | ->andWhere(':currentDate BETWEEN DATE_SUB(s.accessEndDate, s.daysToNewRepetition, \'DAY\') AND s.accessEndDate') |
||
528 | ->andWhere('NOT EXISTS ( |
||
529 | SELECT 1 |
||
530 | FROM Chamilo\CoreBundle\Entity\Session child |
||
531 | WHERE child.parentId = s.id |
||
532 | AND child.accessEndDate >= :currentDate |
||
533 | )') |
||
534 | ->setParameter('false', false) |
||
535 | ->setParameter('currentDate', $currentDate) |
||
536 | ; |
||
537 | |||
538 | return $qb->getQuery()->getResult(); |
||
539 | } |
||
540 | |||
541 | public function countUsersBySession(int $sessionId, int $relationType = Session::STUDENT): int |
||
553 | } |
||
554 | } |
||
555 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.