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

UsergroupRepository::searchGroups()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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