Passed
Push — master ( 13c68b...d6cf3f )
by Angel Fernando Quiroz
09:49 queued 19s
created

UsergroupRepository::getGroupsByUser()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 35
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 21
c 0
b 0
f 0
nc 6
nop 3
dl 0
loc 35
rs 9.584
1
<?php
2
3
declare(strict_types=1);
4
5
/* For licensing terms, see /license.txt */
6
7
namespace Chamilo\CoreBundle\Repository\Node;
8
9
use Chamilo\CoreBundle\Entity\AccessUrl;
10
use Chamilo\CoreBundle\Entity\Course;
11
use Chamilo\CoreBundle\Entity\Session;
12
use Chamilo\CoreBundle\Entity\User;
13
use Chamilo\CoreBundle\Entity\Usergroup;
14
use Chamilo\CoreBundle\Entity\UsergroupRelUser;
15
use Chamilo\CoreBundle\Helpers\AccessUrlHelper;
16
use Chamilo\CoreBundle\Repository\ResourceRepository;
17
use Doctrine\Persistence\ManagerRegistry;
18
use Exception;
19
20
class UsergroupRepository extends ResourceRepository
21
{
22
    public function __construct(
23
        ManagerRegistry $registry,
24
        private readonly IllustrationRepository $illustrationRepository,
25
        private readonly AccessUrlHelper $accessUrlHelper,
26
    ) {
27
        parent::__construct($registry, Usergroup::class);
28
    }
29
30
    public function findBySession(Session $session, bool $checkAccessUrl = false): array
31
    {
32
        $qb = $this->createQueryBuilder('ug')
33
            ->innerJoin('ug.sessions', 'ugs')
34
            ->where('ugs.session = :session')
35
            ->setParameter('session', $session)
36
        ;
37
38
        if ($checkAccessUrl && $this->accessUrlHelper->isMultiple()) {
39
            $accessUrl = $this->accessUrlHelper->getCurrent();
40
            $qb->innerJoin('ug.urls', 'url')
41
                ->andWhere('url.url = :urlId')
42
                ->setParameter('urlId', $accessUrl->getId())
43
            ;
44
        }
45
46
        return $qb->getQuery()->getResult();
47
    }
48
49
    public function findByCourse(Course $course, bool $checkAccessUrl = false): array
50
    {
51
        $qb = $this->createQueryBuilder('ug')
52
            ->innerJoin('ug.courses', 'ugc')
53
            ->where('ugc.course = :course')
54
            ->setParameter('course', $course)
55
        ;
56
57
        if ($checkAccessUrl && $this->accessUrlHelper->isMultiple()) {
58
            $accessUrl = $this->accessUrlHelper->getCurrent();
59
60
            $qb->innerJoin('ug.urls', 'url')
61
                ->andWhere('url.url = :urlId')
62
                ->setParameter('urlId', $accessUrl->getId())
63
            ;
64
        }
65
66
        return $qb->getQuery()->getResult();
67
    }
68
69
    /**
70
     * @param int|array $relationType
71
     */
72
    public function getGroupsByUser(int $userId, int $relationType = 0, bool $withImage = false): array
73
    {
74
        $qb = $this->createQueryBuilder('g')
75
            ->innerJoin('g.users', 'gu')
76
            ->where('gu.user = :userId')
77
            ->setParameter('userId', $userId)
78
            ->andWhere('g.groupType = :socialClass')
79
            ->setParameter('socialClass', Usergroup::SOCIAL_CLASS)
80
        ;
81
82
        if (0 !== $relationType) {
83
            if (\is_array($relationType)) {
84
                $qb->andWhere('gu.relationType IN (:relationType)')
85
                    ->setParameter('relationType', $relationType)
86
                ;
87
            } else {
88
                $qb->andWhere('gu.relationType = :relationType')
89
                    ->setParameter('relationType', $relationType)
90
                ;
91
            }
92
        }
93
94
        if ($this->accessUrlHelper->isMultiple()) {
95
            $accessUrl = $this->accessUrlHelper->getCurrent();
96
97
            $qb->innerJoin('g.urls', 'u')
98
                ->andWhere('u.url = :urlId')
99
                ->setParameter('urlId', $accessUrl->getId())
100
            ;
101
        }
102
103
        $qb->orderBy('g.createdAt', 'DESC');
104
        $query = $qb->getQuery();
105
106
        return $query->getResult();
107
    }
108
109
    public function countMembers(int $usergroupId): int
110
    {
111
        $qb = $this->createQueryBuilder('g')
112
            ->select('count(gu.id)')
113
            ->innerJoin('g.users', 'gu')
114
            ->where('g.id = :usergroupId')
115
            ->setParameter('usergroupId', $usergroupId)
116
        ;
117
118
        return (int) $qb->getQuery()->getSingleScalarResult();
119
    }
120
121
    public function getNewestGroups(int $limit = 30, string $query = ''): array
122
    {
123
        $qb = $this->createQueryBuilder('g')
124
            ->select('g, COUNT(gu) AS HIDDEN memberCount')
125
            ->innerJoin('g.users', 'gu')
126
            ->where('g.groupType = :socialClass')
127
            ->setParameter('socialClass', Usergroup::SOCIAL_CLASS)
128
            ->groupBy('g')
129
            ->orderBy('g.createdAt', 'DESC')
130
            ->setMaxResults($limit)
131
        ;
132
133
        if ($this->accessUrlHelper->isMultiple()) {
134
            $accessUrl = $this->accessUrlHelper->getCurrent();
135
136
            $qb->innerJoin('g.urls', 'u')
137
                ->andWhere('u.url = :urlId')
138
                ->setParameter('urlId', $accessUrl->getId())
139
            ;
140
        }
141
142
        if (!empty($query)) {
143
            $qb->andWhere('g.title LIKE :query OR g.description LIKE :query')
144
                ->setParameter('query', '%'.$query.'%')
145
            ;
146
        }
147
148
        return $qb->getQuery()->getResult();
149
    }
150
151
    public function getPopularGroups(int $limit = 30): array
152
    {
153
        $qb = $this->createQueryBuilder('g')
154
            ->select('g, COUNT(gu) as HIDDEN memberCount')
155
            ->innerJoin('g.users', 'gu')
156
            ->where('g.groupType = :socialClass')
157
            ->setParameter('socialClass', Usergroup::SOCIAL_CLASS)
158
            ->andWhere('gu.relationType IN (:relationTypes)')
159
            ->setParameter('relationTypes', [
160
                Usergroup::GROUP_USER_PERMISSION_ADMIN,
161
                Usergroup::GROUP_USER_PERMISSION_READER,
162
                Usergroup::GROUP_USER_PERMISSION_HRM,
163
            ])
164
            ->groupBy('g')
165
            ->orderBy('memberCount', 'DESC')
166
            ->setMaxResults($limit)
167
        ;
168
169
        if ($this->accessUrlHelper->isMultiple()) {
170
            $accessUrl = $this->accessUrlHelper->getCurrent();
171
172
            $qb->innerJoin('g.urls', 'u')
173
                ->andWhere('u.url = :urlId')
174
                ->setParameter('urlId', $accessUrl->getId())
175
            ;
176
        }
177
178
        return $qb->getQuery()->getResult();
179
    }
180
181
    public function findGroupById($id)
182
    {
183
        return $this->createQueryBuilder('ug')
184
            ->where('ug.id = :id')
185
            ->setParameter('id', $id)
186
            ->getQuery()
187
            ->getOneOrNullResult()
188
        ;
189
    }
190
191
    public function searchGroups(string $searchTerm): array
192
    {
193
        $queryBuilder = $this->createQueryBuilder('g');
194
        $queryBuilder->where('g.title LIKE :searchTerm')
195
            ->setParameter('searchTerm', '%'.$searchTerm.'%')
196
        ;
197
198
        return $queryBuilder->getQuery()->getResult();
199
    }
200
201
    public function getUsersByGroup(int $groupID, bool $includeNormalClass = false): array
202
    {
203
        $qb = $this->createQueryBuilder('g')
204
            ->innerJoin('g.users', 'gu')
205
            ->innerJoin('gu.user', 'u')
206
            ->where('g.id = :groupID')
207
            ->setParameter('groupID', $groupID)
208
        ;
209
210
        $relationTypes = [
211
            Usergroup::GROUP_USER_PERMISSION_ADMIN,
212
            Usergroup::GROUP_USER_PERMISSION_READER,
213
            Usergroup::GROUP_USER_PERMISSION_PENDING_INVITATION,
214
        ];
215
216
        if ($includeNormalClass) {
217
            $relationTypes[] = 0;
218
        }
219
220
        $qb->andWhere('gu.relationType IN (:relationTypes)')
221
            ->setParameter('relationTypes', $relationTypes)
222
            ->select('u.id, u.username, u.email, gu.relationType, u.pictureUri, u.firstname, u.lastname')
223
        ;
224
225
        $results = $qb->getQuery()->getResult();
226
227
        $userRepository = $this->_em->getRepository(User::class);
228
229
        foreach ($results as &$user) {
230
            $user['pictureUri'] = $userRepository->getUserPicture($user['id']);
231
        }
232
233
        return $results;
234
    }
235
236
    public function addUserToGroup(int $userId, int $groupId, int $relationType = Usergroup::GROUP_USER_PERMISSION_READER): void
237
    {
238
        $group = $this->find($groupId);
239
        $user = $this->_em->getRepository(User::class)->find($userId);
240
241
        if (!$group || !$user) {
242
            throw new Exception('Group or User not found');
243
        }
244
245
        if (Usergroup::GROUP_PERMISSION_CLOSED === (int) $group->getVisibility()) {
246
            $relationType = Usergroup::GROUP_USER_PERMISSION_PENDING_INVITATION;
247
        }
248
249
        $existingRelation = $this->_em->getRepository(UsergroupRelUser::class)->findOneBy([
250
            'usergroup' => $group,
251
            'user' => $user,
252
        ]);
253
254
        if (!$existingRelation) {
255
            $existingRelation = new UsergroupRelUser();
256
            $existingRelation->setUsergroup($group);
257
            $existingRelation->setUser($user);
258
        }
259
260
        $existingRelation->setRelationType($relationType);
261
262
        $this->_em->persist($existingRelation);
263
        $this->_em->flush();
264
    }
265
266
    public function updateUserRole($userId, $groupId, $relationType = Usergroup::GROUP_USER_PERMISSION_READER): void
267
    {
268
        $qb = $this->createQueryBuilder('g');
269
        $qb->delete(UsergroupRelUser::class, 'gu')
270
            ->where('gu.usergroup = :groupId')
271
            ->andWhere('gu.user = :userId')
272
            ->setParameter('groupId', $groupId)
273
            ->setParameter('userId', $userId)
274
        ;
275
276
        $query = $qb->getQuery();
277
        $query->execute();
278
279
        $group = $this->find($groupId);
280
        $user = $this->_em->getRepository(User::class)->find($userId);
281
282
        if (!$group || !$user) {
283
            throw new Exception('Group or User not found');
284
        }
285
286
        $usergroupRelUser = new UsergroupRelUser();
287
        $usergroupRelUser->setUsergroup($group);
288
        $usergroupRelUser->setUser($user);
289
        $usergroupRelUser->setRelationType($relationType);
290
291
        $this->_em->persist($usergroupRelUser);
292
        $this->_em->flush();
293
    }
294
295
    public function removeUserFromGroup(int $userId, int $groupId, bool $checkLeaveRestriction = true): bool
296
    {
297
        /** @var Usergroup $group */
298
        $group = $this->find($groupId);
299
        $user = $this->_em->getRepository(User::class)->find($userId);
300
301
        if (!$group || !$user) {
0 ignored issues
show
introduced by
$group is of type Chamilo\CoreBundle\Entity\Usergroup, thus it always evaluated to true.
Loading history...
302
            throw new Exception('Group or User not found');
303
        }
304
305
        if ($checkLeaveRestriction && !$group->getAllowMembersToLeaveGroup()) {
306
            throw new Exception('Members are not allowed to leave this group');
307
        }
308
309
        $relation = $this->_em->getRepository(UsergroupRelUser::class)->findOneBy([
310
            'usergroup' => $group,
311
            'user' => $user,
312
        ]);
313
314
        if ($relation) {
315
            $this->_em->remove($relation);
316
            $this->_em->flush();
317
318
            return true;
319
        }
320
321
        return false;
322
    }
323
324
    public function getInvitedUsersByGroup(int $groupID)
325
    {
326
        $qb = $this->createQueryBuilder('g')
327
            ->innerJoin('g.users', 'gu')
328
            ->innerJoin('gu.user', 'u')
329
            ->where('g.id = :groupID')
330
            ->setParameter('groupID', $groupID)
331
            ->andWhere('gu.relationType = :relationType')
332
            ->setParameter('relationType', Usergroup::GROUP_USER_PERMISSION_PENDING_INVITATION)
333
            ->select('u.id, u.username, u.email, gu.relationType')
334
        ;
335
336
        return $qb->getQuery()->getResult();
337
    }
338
339
    public function getInvitedUsers(int $groupId): array
340
    {
341
        $qb = $this->createQueryBuilder('g')
342
            ->innerJoin('g.users', 'rel')
343
            ->innerJoin('rel.user', 'u')
344
            ->where('g.id = :groupId')
345
            ->andWhere('rel.relationType = :relationType')
346
            ->setParameter('groupId', $groupId)
347
            ->setParameter('relationType', Usergroup::GROUP_USER_PERMISSION_PENDING_INVITATION)
348
            ->select('u')
349
        ;
350
351
        return $qb->getQuery()->getResult();
352
    }
353
354
    public function searchGroupsByTags(string $tag, int $from = 0, int $number_of_items = 10, bool $getCount = false)
355
    {
356
        $qb = $this->createQueryBuilder('g');
357
358
        if ($getCount) {
359
            $qb->select('COUNT(g.id)');
360
        } else {
361
            $qb->select('g.id, g.title, g.description, g.url, g.picture');
362
        }
363
364
        if ($this->accessUrlHelper->isMultiple()) {
365
            $accessUrl = $this->accessUrlHelper->getCurrent();
366
367
            $qb->innerJoin('g.accessUrls', 'a', 'WITH', 'g.id = a.usergroup')
368
                ->andWhere('a.url = :urlId')
369
                ->setParameter('urlId', $accessUrl->getId())
370
            ;
371
        }
372
373
        $qb->where(
374
            $qb->expr()->orX(
375
                $qb->expr()->like('g.title', ':tag'),
376
                $qb->expr()->like('g.description', ':tag'),
377
                $qb->expr()->like('g.url', ':tag')
378
            )
379
        )
380
            ->setParameter('tag', '%'.$tag.'%')
381
        ;
382
383
        if (!$getCount) {
384
            $qb->orderBy('g.title', 'ASC')
385
                ->setFirstResult($from)
386
                ->setMaxResults($number_of_items)
387
            ;
388
        }
389
390
        return $getCount ? $qb->getQuery()->getSingleScalarResult() : $qb->getQuery()->getResult();
391
    }
392
393
    public function getUsergroupPicture($userGroupId): string
394
    {
395
        $usergroup = $this->find($userGroupId);
396
        if (!$usergroup) {
397
            return '/img/icons/64/group_na.png';
398
        }
399
400
        $url = $this->illustrationRepository->getIllustrationUrl($usergroup);
401
        $params['w'] = 64;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$params was never initialized. Although not strictly required by PHP, it is generally a good practice to add $params = array(); before regardless.
Loading history...
402
        $params['rand'] = uniqid('u_', true);
403
        $paramsToString = '?'.http_build_query($params);
404
405
        return $url.$paramsToString;
406
    }
407
408
    public function isGroupMember(int $groupId, User $user): bool
409
    {
410
        if ($user->isSuperAdmin()) {
411
            return true;
412
        }
413
414
        $userRole = $this->getUserGroupRole($groupId, $user->getId());
415
416
        $allowedRoles = [
417
            Usergroup::GROUP_USER_PERMISSION_ADMIN,
418
            Usergroup::GROUP_USER_PERMISSION_MODERATOR,
419
            Usergroup::GROUP_USER_PERMISSION_READER,
420
            Usergroup::GROUP_USER_PERMISSION_HRM,
421
        ];
422
423
        return \in_array($userRole, $allowedRoles, true);
424
    }
425
426
    public function getUserGroupRole(int $groupId, int $userId): ?int
427
    {
428
        $qb = $this->createQueryBuilder('g');
429
        $qb->innerJoin('g.users', 'gu')
430
            ->where('g.id = :groupId AND gu.user = :userId')
431
            ->setParameter('groupId', $groupId)
432
            ->setParameter('userId', $userId)
433
            ->orderBy('gu.id', 'DESC')
434
            ->select('gu.relationType')
435
            ->setMaxResults(1)
436
        ;
437
438
        $result = $qb->getQuery()->getOneOrNullResult();
439
440
        return $result ? $result['relationType'] : null;
441
    }
442
443
    public function isGroupModerator(int $groupId, int $userId): bool
444
    {
445
        $relationType = $this->getUserGroupRole($groupId, $userId);
446
447
        return \in_array($relationType, [
448
            Usergroup::GROUP_USER_PERMISSION_ADMIN,
449
            Usergroup::GROUP_USER_PERMISSION_MODERATOR,
450
        ]);
451
    }
452
453
    /**
454
     * Determines whether to use the multi-URL feature.
455
     *
456
     * @return bool true if multi-URLs should be used, false otherwise
457
     */
458
    public function getUseMultipleUrl(): bool
459
    {
460
        // TODO: Implement the actual logic to determine if multi-URLs should be used.
461
        // For now, returning false as a default value.
462
        return false;
463
    }
464
465
    /**
466
     * Gets the current access URL ID.
467
     *
468
     * @return int the ID of the current access URL
469
     */
470
    public function getCurrentAccessUrlId(): int
471
    {
472
        // TODO: Implement the actual logic to obtain the current access URL ID.
473
        // For now, returning 1 as a default value.
474
        return 1;
475
    }
476
477
    public function getOneByTitleInUrl(string $title, AccessUrl $url): ?Usergroup
478
    {
479
        $qb = $this->getOrCreateQueryBuilder(null, 'g');
480
481
        return $qb
482
            ->innerJoin('g.urls', 'u')
483
            ->where($qb->expr()->eq('g.title', ':title'))
484
            ->andWhere($qb->expr()->eq('u.url', ':url'))
485
            ->setMaxResults(1)
486
            ->setParameters([
487
                'title' => $title,
488
                'url' => $url->getId()
489
            ])
490
            ->setParameter('title', $title)
491
            ->getQuery()
492
            ->getOneOrNullResult()
493
        ;
494
    }
495
}
496