Passed
Pull Request — master (#5576)
by Angel Fernando Quiroz
17:43 queued 10:32
created

SessionRepository::getSessionsByUser()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 10
nc 1
nop 2
dl 0
loc 15
rs 9.9332
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/* For licensing terms, see /license.txt */
6
7
namespace Chamilo\CoreBundle\Repository;
8
9
use Chamilo\CoreBundle\Entity\AccessUrl;
10
use Chamilo\CoreBundle\Entity\Course;
11
use Chamilo\CoreBundle\Entity\Session;
12
use Chamilo\CoreBundle\Entity\SessionRelCourse;
13
use Chamilo\CoreBundle\Entity\SessionRelCourseRelUser;
14
use Chamilo\CoreBundle\Entity\SessionRelUser;
15
use Chamilo\CoreBundle\Entity\User;
16
use Chamilo\CoreBundle\Settings\SettingsManager;
17
use DateTime;
18
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
19
use Doctrine\ORM\Query\Expr\Join;
20
use Doctrine\ORM\QueryBuilder;
21
use Doctrine\Persistence\ManagerRegistry;
22
use Exception;
23
24
/**
25
 * @author Julio Montoya <[email protected]>
26
 */
27
class SessionRepository extends ServiceEntityRepository
28
{
29
    public function __construct(
30
        ManagerRegistry $registry,
31
        private readonly SettingsManager $settingsManager,
32
    ) {
33
        parent::__construct($registry, Session::class);
34
    }
35
36
    public function create(): ?Session
37
    {
38
        return new Session();
39
    }
40
41
    public function update(Session $session): void
42
    {
43
        $this->getEntityManager()->persist($session);
44
        $this->getEntityManager()->flush();
45
    }
46
47
    /**
48
     * @return array<SessionRelUser>
49
     */
50
    public function getUsersByAccessUrl(Session $session, AccessUrl $url, array $relationTypeList = []): array
51
    {
52
        if (0 === $session->getUsers()->count()) {
53
            return [];
54
        }
55
56
        $qb = $this->addSessionRelUserFilterByUrl($session, $url);
57
        $qb->orderBy('sru.relationType');
58
59
        if ($relationTypeList) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $relationTypeList of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

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.

Loading history...
60
            $qb->andWhere(
61
                $qb->expr()->in('sru.relationType', $relationTypeList)
62
            );
63
        }
64
65
        return $qb->getQuery()->getResult();
66
    }
67
68
    public function getSessionsByUser(User $user, AccessUrl $url): QueryBuilder
69
    {
70
        $qb = $this->createQueryBuilder('s');
71
        $qb
72
            ->innerJoin('s.users', 'sru')
73
            ->leftJoin('s.urls', 'urls')
74
            ->where($qb->expr()->eq('sru.user', ':user'))
75
            ->andWhere($qb->expr()->eq('urls.url', ':url'))
76
            ->setParameters([
77
                'user' => $user,
78
                'url' => $url,
79
            ])
80
        ;
81
82
        return $qb;
83
    }
84
85
    /**
86
     * @return array<int, Session>
87
     *
88
     * @throws Exception
89
     */
90
    public function getPastSessionsOfUserInUrl(User $user, AccessUrl $url): array
91
    {
92
        $sessions = $this->getSubscribedSessionsOfUserInUrl($user, $url);
93
94
        $filterPastSessions = function (Session $session) use ($user) {
95
            $now = new DateTime();
96
            // Determine if the user is a coach
97
            $userIsCoach = $session->hasCoach($user);
98
99
            // Check if the session has a duration
100
            if ($session->getDuration() > 0) {
101
                $daysLeft = $session->getDaysLeftByUser($user);
102
                $session->setTitle($session->getTitle().'<-'.$daysLeft);
103
104
                return $daysLeft < 0 && !$userIsCoach;
105
            }
106
107
            // Get the appropriate end date based on whether the user is a coach
108
            $sessionEndDate = $userIsCoach && $session->getCoachAccessEndDate()
109
                ? $session->getCoachAccessEndDate()
110
                : $session->getAccessEndDate();
111
112
            // If there's no end date, the session is not considered past
113
            if (!$sessionEndDate) {
114
                return false;
115
            }
116
117
            // Check if the current date is after the end date
118
            return $now > $sessionEndDate;
119
        };
120
121
        return array_filter($sessions, $filterPastSessions);
122
    }
123
124
    /**
125
     * @return array<int, Session>
126
     *
127
     * @throws Exception
128
     */
129
    public function getCurrentSessionsOfUserInUrl(User $user, AccessUrl $url): array
130
    {
131
        $sessions = $this->getSubscribedSessionsOfUserInUrl($user, $url);
132
133
        $filterCurrentSessions = function (Session $session) use ($user) {
134
            // Determine if the user is a coach
135
            $userIsCoach = $session->hasCoach($user);
136
137
            // Check if session has a duration
138
            if ($session->getDuration() > 0) {
139
                $daysLeft = $session->getDaysLeftByUser($user);
140
141
                return $daysLeft >= 0 || $userIsCoach;
142
            }
143
144
            // Determine the start date based on whether the user is a coach
145
            $sessionStartDate = $userIsCoach && $session->getCoachAccessStartDate()
146
                ? $session->getCoachAccessStartDate()
147
                : $session->getAccessStartDate();
148
149
            // If there is no start date, consider the session current
150
            if (!$sessionStartDate) {
151
                return true;
152
            }
153
154
            // Get the current date and time
155
            $now = new DateTime();
156
157
            // Determine the end date based on whether the user is a coach
158
            $sessionEndDate = $userIsCoach && $session->getCoachAccessEndDate()
159
                ? $session->getCoachAccessEndDate()
160
                : $session->getAccessEndDate();
161
162
            // Check if the current date is within the start and end dates
163
            return $now >= $sessionStartDate && (!$sessionEndDate || $now <= $sessionEndDate);
164
        };
165
166
        return array_filter($sessions, $filterCurrentSessions);
167
    }
168
169
    /**
170
     * @return array<int, Session>
171
     *
172
     * @throws Exception
173
     */
174
    public function getUpcomingSessionsOfUserInUrl(User $user, AccessUrl $url): array
175
    {
176
        $sessions = $this->getSubscribedSessionsOfUserInUrl($user, $url);
177
178
        $filterUpcomingSessions = function (Session $session) use ($user) {
179
            $now = new DateTime();
180
181
            // All session with access by duration call be either current or past
182
            if ($session->getDuration() > 0) {
183
                return false;
184
            }
185
186
            // Determine if the user is a coach
187
            $userIsCoach = $session->hasCoach($user);
188
189
            // Get the appropriate start date based on whether the user is a coach
190
            $sessionStartDate = $userIsCoach && $session->getCoachAccessStartDate()
191
                ? $session->getCoachAccessStartDate()
192
                : $session->getAccessStartDate();
193
194
            // If there's no start date, the session is not considered future
195
            if (!$sessionStartDate) {
196
                return false;
197
            }
198
199
            // Check if the current date is before the start date
200
            return $now < $sessionStartDate;
201
        };
202
203
        return array_filter($sessions, $filterUpcomingSessions);
204
    }
205
206
    public function addUserInCourse(int $relationType, User $user, Course $course, Session $session): void
207
    {
208
        if (!$user->isActive()) {
209
            throw new Exception('User not active');
210
        }
211
212
        if (!$session->hasCourse($course)) {
213
            $msg = sprintf('Course %s is not subscribed to the session %s', $course->getTitle(), $session->getTitle());
214
215
            throw new Exception($msg);
216
        }
217
218
        if (!\in_array($relationType, Session::getRelationTypeList(), true)) {
219
            throw new Exception(sprintf('Cannot handle relationType %s', $relationType));
220
        }
221
222
        switch ($relationType) {
223
            case Session::DRH:
224
                if ($user->hasRole('ROLE_RRHH')) {
225
                    $session->addUserInSession(Session::DRH, $user);
226
                }
227
228
                break;
229
230
            case Session::STUDENT:
231
                $session
232
                    ->addUserInSession(Session::STUDENT, $user)
233
                    ->addUserInCourse(Session::STUDENT, $user, $course)
234
                ;
235
236
                break;
237
238
            case Session::COURSE_COACH:
239
                if ($user->hasRole('ROLE_TEACHER')) {
240
                    $session
241
                        ->addUserInSession(Session::COURSE_COACH, $user)
242
                        ->addUserInCourse(
243
                            Session::COURSE_COACH,
244
                            $user,
245
                            $course
246
                        )
247
                    ;
248
                }
249
250
                break;
251
        }
252
    }
253
254
    /**
255
     * @return array<SessionRelCourse>
256
     */
257
    public function getSessionCoursesByStatusInUserSubscription(User $user, Session $session, int $relationType, ?AccessUrl $url = null): array
258
    {
259
        $qb = $this->getEntityManager()->createQueryBuilder();
260
261
        $qb->select('src')
262
            ->from(SessionRelCourse::class, 'src')
263
            ->innerJoin(
264
                SessionRelUser::class,
265
                'sru',
266
                Join::WITH,
267
                'src.session = sru.session'
268
            )
269
            ->innerJoin('src.session', 'session')
270
            ->where(
271
                $qb->expr()->eq('session', ':session')
272
            )
273
            ->andWhere(
274
                $qb->expr()->eq('sru.user', ':user')
275
            )
276
            ->andWhere(
277
                $qb->expr()->eq('sru.relationType', ':relation_type')
278
            )
279
        ;
280
281
        $parameters = [
282
            'session' => $session,
283
            'user' => $user,
284
            'relation_type' => $relationType,
285
        ];
286
287
        if ($url) {
288
            $qb->innerJoin('session.urls', 'urls')
289
                ->andWhere(
290
                    $qb->expr()->eq('urls.url', ':url')
291
                )
292
            ;
293
294
            $parameters['url'] = $url;
295
        }
296
297
        $qb->setParameters($parameters);
298
299
        return $qb->getQuery()->getResult();
300
    }
301
302
    /**
303
     * @return array<SessionRelCourse>
304
     */
305
    public function getSessionCoursesByStatusInCourseSubscription(User $user, Session $session, int $status, ?AccessUrl $url = null): array
306
    {
307
        $qb = $this->getEntityManager()->createQueryBuilder();
308
309
        $qb->select('src')
310
            ->from(SessionRelCourse::class, 'src')
311
            ->innerJoin(
312
                SessionRelCourseRelUser::class,
313
                'srcru',
314
                Join::WITH,
315
                'src.session = srcru.session AND src.course = srcru.course'
316
            )
317
            ->innerJoin('srcru.session', 'session')
318
            ->where(
319
                $qb->expr()->eq('session', ':session')
320
            )
321
            ->andWhere(
322
                $qb->expr()->eq('srcru.user', ':user')
323
            )
324
            ->andWhere(
325
                $qb->expr()->eq('srcru.status', ':status')
326
            )
327
        ;
328
329
        $parameters = [
330
            'session' => $session,
331
            'user' => $user,
332
            'status' => $status,
333
        ];
334
335
        if ($url) {
336
            $qb->innerJoin('session.urls', 'urls')
337
                ->andWhere(
338
                    $qb->expr()->eq('urls.url', ':url')
339
                )
340
            ;
341
342
            $parameters['url'] = $url;
343
        }
344
345
        $qb->setParameters($parameters);
346
347
        return $qb->getQuery()->getResult();
348
    }
349
350
    private function addSessionRelUserFilterByUrl(Session $session, AccessUrl $url): QueryBuilder
351
    {
352
        $qb = $this->getEntityManager()->createQueryBuilder();
353
        $qb
354
            ->select('sru')
355
            ->from(SessionRelUser::class, 'sru')
356
            ->innerJoin('sru.user', 'u')
357
            ->innerJoin('u.portals', 'p')
358
            ->andWhere('sru.session = :session AND p.url = :url')
359
            ->setParameters([
360
                'session' => $session,
361
                'url' => $url,
362
            ])
363
        ;
364
365
        return $qb;
366
    }
367
368
    public function getUserFollowedSessionsInAccessUrl(User $user, AccessUrl $url): QueryBuilder
369
    {
370
        $callback = fn (Session $session) => $session->getId();
371
372
        if ($user->isHRM()) {
373
            $idList = array_map($callback, $user->getDRHSessions());
374
        } elseif ($user->isTeacher() || COURSEMANAGER === $user->getStatus()) {
375
            $idListAsCoach = $user
376
                ->getSessionsByStatusInCourseSubscription(Session::COURSE_COACH)
377
                ->map($callback)
378
                ->getValues()
379
            ;
380
            $idListAsGeneralCoach = array_map($callback, $user->getSessionsAsGeneralCoach());
381
            $idList = array_merge($idListAsCoach, $idListAsGeneralCoach);
382
        } elseif ($user->isSessionAdmin()) {
383
            $idList = array_map($callback, $user->getSessionsAsAdmin());
384
        } else {
385
            $idList = array_map($callback, $user->getSessionsAsStudent());
386
        }
387
388
        $qb = $this->createQueryBuilder('s');
389
        $qb
390
            ->innerJoin('s.urls', 'u')
391
            ->where($qb->expr()->eq('u.url', $url->getId()))
392
            ->andWhere($qb->expr()->in('s.id', ':id_list'))
393
            ->setParameter('id_list', $idList)
394
        ;
395
396
        return $qb;
397
    }
398
399
    /**
400
     * @return array<int, Session>
401
     *
402
     * @throws Exception
403
     */
404
    public function getSubscribedSessionsOfUserInUrl(
405
        User $user,
406
        AccessUrl $url,
407
        bool $ignoreVisibilityForAdmins = false,
408
    ): array {
409
        $sessions = $this->getSessionsByUser($user, $url)->getQuery()->getResult();
410
411
        $filterSessions = function (Session $session) use ($user, $ignoreVisibilityForAdmins) {
412
            $visibility = $session->setAccessVisibilityByUser($user, $ignoreVisibilityForAdmins);
413
414
            if (Session::VISIBLE !== $visibility) {
415
                $closedOrHiddenCourses = $session->getClosedOrHiddenCourses();
416
417
                if ($closedOrHiddenCourses->count() === $session->getCourses()->count()) {
418
                    $visibility = Session::INVISIBLE;
419
                }
420
            }
421
422
            switch ($visibility) {
423
                case Session::READ_ONLY:
424
                case Session::VISIBLE:
425
                case Session::AVAILABLE:
426
                    break;
427
428
                case Session::INVISIBLE:
429
                    if (!$ignoreVisibilityForAdmins) {
430
                        return false;
431
                    }
432
            }
433
434
            return true;
435
        };
436
437
        return array_filter($sessions, $filterSessions);
438
    }
439
}
440