Passed
Pull Request — master (#5576)
by Angel Fernando Quiroz
07:46
created

getUpcomingSessionsWithDatesForUser()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

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