Passed
Pull Request — master (#6214)
by
unknown
08:18
created

UsergroupRepository::getPopularGroups()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 28
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

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