Passed
Push — master ( 65d552...4599b6 )
by Angel Fernando Quiroz
10:41
created

UsergroupRepository::getInvitedUsersByGroup()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

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