Passed
Pull Request — master (#6295)
by
unknown
09:51
created

GroupManager::update_category()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 66
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 43
nc 6
nop 15
dl 0
loc 66
rs 9.232
c 1
b 0
f 0

How to fix   Long Method    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\Course;
6
use Chamilo\CoreBundle\Entity\User;
7
use Chamilo\CoreBundle\Framework\Container;
8
use Chamilo\CourseBundle\Entity\CGroup;
9
use Chamilo\CourseBundle\Entity\CGroupCategory;
10
use Doctrine\Common\Collections\ArrayCollection;
11
use Doctrine\Common\Collections\Criteria;
12
use Chamilo\CoreBundle\Component\Utils\ActionIcon;
13
use Chamilo\CoreBundle\Component\Utils\ToolIcon;
14
use Chamilo\CourseBundle\Entity\CGroupRelUsergroup;
15
use Chamilo\CoreBundle\Entity\Usergroup;
16
use Chamilo\CoreBundle\Entity\Session;
17
18
/**
19
 * This library contains some functions for group-management.
20
 *
21
 * @author Bart Mollet
22
 *
23
 * @todo Add $course_code parameter to all functions. So this GroupManager can
24
 * be used outside a session.
25
 */
26
class GroupManager
27
{
28
    /* DEFAULT_GROUP_CATEGORY:
29
    When group categories aren't available (platform-setting),
30
    all groups are created in this 'dummy'-category*/
31
    public const DEFAULT_GROUP_CATEGORY = 2;
32
33
    /**
34
     * infinite.
35
     */
36
    public const INFINITE = 99999;
37
    /**
38
     * No limit on the number of users in a group.
39
     */
40
    public const MEMBER_PER_GROUP_NO_LIMIT = 0;
41
    /**
42
     * No limit on the number of groups per user.
43
     */
44
    public const GROUP_PER_MEMBER_NO_LIMIT = 0;
45
    /**
46
     * The tools of a group can have 3 states
47
     * - not available
48
     * - public
49
     * - private.
50
     */
51
    public const TOOL_NOT_AVAILABLE = 0;
52
    public const TOOL_PUBLIC = 1;
53
    public const TOOL_PRIVATE = 2;
54
    public const TOOL_PRIVATE_BETWEEN_USERS = 3;
55
56
    /**
57
     * Constants for the available group tools.
58
     */
59
    public const GROUP_TOOL_FORUM = 0;
60
    public const GROUP_TOOL_DOCUMENTS = 1;
61
    public const GROUP_TOOL_CALENDAR = 2;
62
    public const GROUP_TOOL_ANNOUNCEMENT = 3;
63
    public const GROUP_TOOL_WORK = 4;
64
    public const GROUP_TOOL_WIKI = 5;
65
    public const GROUP_TOOL_CHAT = 6;
66
67
    public const DOCUMENT_MODE_SHARE = 0; // By default
68
    public const DOCUMENT_MODE_READ_ONLY = 1;
69
    public const DOCUMENT_MODE_COLLABORATION = 2;
70
71
    public function __construct()
72
    {
73
    }
74
75
    /**
76
     * @param int $courseId
77
     *
78
     * @return CGroup[]
79
     */
80
    public static function get_groups($courseId = 0)
81
    {
82
        $repo = Container::getGroupRepository();
83
        $course = api_get_course_entity($courseId);
84
        if (null !== $course) {
85
            return [];
86
        }
87
88
        $qb = $repo->getResourcesByCourse($course);
89
90
        return $qb->getQuery()->getResult();
91
        /*$table_group = Database::get_course_table(TABLE_GROUP);
92
        $courseId = !empty($courseId) ? (int) $courseId : api_get_course_int_id();
93
94
        $sql = "SELECT * FROM $table_group WHERE c_id = $courseId  ";
95
        $result = Database::query($sql);
96
97
        return Database::store_result($result, 'ASSOC');*/
98
    }
99
100
    /**
101
     * Get list of groups for current course.
102
     *
103
     * @param int    $categoryId       The id of the category from which the groups are
104
     *                                 requested
105
     * @param Course $course           Default is current course
106
     * @param int    $status           group status
107
     * @param int    $sessionId
108
     * @param bool   $getCount
109
     * @param bool   $notInGroup       Get groups not in a category
110
     * @param bool   $returnEntityList
111
     *
112
     * @return array|CGroup[] an array with all information about the groups
113
     */
114
    public static function get_group_list(
115
        $categoryId = null,
116
        Course $course = null,
117
        $status = null,
118
        $sessionId = 0,
119
        $getCount = false,
120
        $filterByKeyword = null,
121
        $returnEntityList = false
122
    ) {
123
        $course = $course ?? api_get_course_entity();
124
125
        if (null === $course) {
126
            return [];
127
        }
128
129
        $sessionId = empty($sessionId) ? api_get_session_id() : (int) $sessionId;
130
        $repo = Container::getGroupRepository();
131
        $session = api_get_session_entity($sessionId);
132
        $qb = $repo->findAllByCourse($course, $session, $filterByKeyword, $status, $categoryId);
133
134
        if ($getCount) {
135
            return $repo->getCount($qb);
136
        }
137
138
        if ($returnEntityList) {
139
            return $qb->getQuery()->getResult();
140
        }
141
142
        return $qb->getQuery()->getArrayResult();
143
144
        /*$table_group = Database::get_course_table(TABLE_GROUP);
145
        $select = ' g.iid,
146
                    g.title,
147
                    g.description,
148
                    g.category_id,
149
                    g.max_student maximum_number_of_members,
150
                    g.secret_directory,
151
                    g.self_registration_allowed,
152
                    g.self_unregistration_allowed,
153
                    g.status
154
                    ';
155
        if ($getCount) {
156
            $select = ' DISTINCT count(g.iid) as count ';
157
        }
158
159
        $sql = "SELECT
160
                $select
161
                FROM $table_group g
162
                WHERE 1 = 1 ";
163
164
        if (!is_null($categoryId)) {
165
            $sql .= " AND g.category_id = '".intval($categoryId)."' ";
166
            $session_condition = api_get_session_condition($sessionId);
167
            if (!empty($session_condition)) {
168
                //$sql .= $session_condition;
169
            }
170
        } else {
171
            $session_condition = api_get_session_condition($sessionId, true);
172
        }
173
174
        $session_condition = '';
175
176
        if (!is_null($status)) {
177
            $sql .= " AND g.status = '".intval($status)."' ";
178
        }
179
180
        //$sql .= " AND g.c_id = $course_id ";
181
        if ($notInGroup) {
182
            $sql .= "  AND (g.category_id IS NULL OR g.category_id = 0) ";
183
        }
184
185
        if (!empty($session_condition)) {
186
            $sql .= $session_condition;
187
        }
188
        $sql .= ' ORDER BY UPPER(g.title)';
189
190
        $result = Database::query($sql);
191
192
        if ($getCount) {
193
            $row = Database::fetch_array($result);
194
195
            return $row['count'];
196
        }
197
198
        $groups = [];
199
        while ($thisGroup = Database::fetch_array($result)) {
200
            $thisGroup['number_of_members'] = count(self::get_subscribed_users($thisGroup));
201
            if (0 != $thisGroup['session_id']) {
202
                $sql = 'SELECT name FROM '.Database::get_main_table(TABLE_MAIN_SESSION).'
203
                        WHERE id='.$thisGroup['session_id'];
204
                $rs_session = Database::query($sql);
205
                if (Database::num_rows($rs_session) > 0) {
206
                    $thisGroup['session_name'] = Database::result($rs_session, 0, 0);
207
                }
208
            }
209
            $groups[] = $thisGroup;
210
        }
211
212
        return $groups;*/
213
    }
214
215
    /**
216
     * Create a group.
217
     *
218
     * @param string $name        The name for this group
219
     * @param int    $category_id
220
     * @param int    $tutor       The user-id of the group's tutor
221
     * @param int    $places      How many people can subscribe to the new group
222
     *
223
     * @return int
224
     */
225
    public static function create_group($name, $category_id, $tutor, $places)
226
    {
227
        $_course = api_get_course_info();
228
        $session_id = api_get_session_id();
229
        $course_id = $_course['real_id'];
230
        $category = self::get_category($category_id);
231
        $places = (int) $places;
232
233
        // Default values
234
        $docState = CGroup::TOOL_PRIVATE;
235
        $calendarState = CGroup::TOOL_PRIVATE;
236
        $workState = CGroup::TOOL_PRIVATE;
237
        $anonuncementState = CGroup::TOOL_PRIVATE;
238
        $forumState = CGroup::TOOL_PRIVATE;
239
        $wikiState = CGroup::TOOL_PRIVATE;
240
        $chatState = CGroup::TOOL_PRIVATE;
241
        $selfRegAllowed = 0;
242
        $selfUnregAllwoed = 0;
243
        $documentAccess = 0;
244
245
        if ($category) {
246
            if (0 == $places) {
247
                //if the amount of users per group is not filled in, use the setting from the category
248
                $places = $category['max_student'];
249
            } else {
250
                if ($places > $category['max_student'] && 0 != $category['max_student']) {
251
                    $places = $category['max_student'];
252
                }
253
            }
254
            $docState = $category['doc_state'];
255
            $calendarState = $category['calendar_state'];
256
            $workState = $category['work_state'];
257
            $anonuncementState = $category['announcements_state'];
258
            $forumState = $category['forum_state'];
259
            $wikiState = $category['wiki_state'];
260
            $chatState = $category['chat_state'];
261
            $selfRegAllowed = $category['self_reg_allowed'];
262
            $selfUnregAllwoed = $category['self_unreg_allowed'];
263
            $documentAccess = isset($category['document_access']) ? $category['document_access'] : 0;
264
        }
265
266
        $course = api_get_course_entity($course_id);
267
        $session = api_get_session_entity($session_id);
268
269
        $category = null;
270
        if (!empty($category_id)) {
271
            $category = Container::getGroupCategoryRepository()->find($category_id);
272
        }
273
274
        /** @var CGroup $group */
275
        $group = (new CGroup())
276
            ->setTitle($name)
277
            ->setCategory($category)
278
            ->setMaxStudent($places)
279
            ->setDocState($docState)
280
            ->setCalendarState($calendarState)
281
            ->setWorkState($workState)
282
            ->setForumState($forumState)
283
            ->setWikiState($wikiState)
284
            ->setAnnouncementsState($anonuncementState)
285
            ->setChatState($chatState)
286
            ->setSelfRegistrationAllowed(1 === (int) $selfRegAllowed)
287
            ->setSelfUnregistrationAllowed(1 === (int) $selfUnregAllwoed)
288
            ->setDocumentAccess((int) $documentAccess)
289
            ->setParent($course)
290
            ->addCourseLink($course, $session)
291
        ;
292
293
        $repo = Container::getGroupRepository();
294
        $repo->create($group);
295
        $lastId = $group->getIid();
296
297
        if ($lastId) {
298
            // create a forum if needed
299
            if ($forumState >= 0) {
300
                $forumName = get_lang('Group forums');
301
                $repo = Container::getForumCategoryRepository();
302
                $category = $repo->findCourseResourceByTitle($forumName, $course->getResourceNode(), $course);
303
                /*$criteria = ['cId' => $course_id, 'catTitle' => $forumName];
304
                $category = $repo->findOneBy($criteria);*/
305
306
                if (empty($category)) {
307
                    $categoryId = saveForumCategory(['forum_category_title' => $forumName]);
308
                } else {
309
                    $categoryId = $category->getIid();
310
                }
311
312
                $values = [];
313
                $values['forum_title'] = $name;
314
                $values['group_id'] = $lastId;
315
                $values['forum_category'] = $categoryId;
316
                $values['allow_anonymous_group']['allow_anonymous'] = 0;
317
                $values['students_can_edit_group']['students_can_edit'] = 0;
318
                $values['approval_direct_group']['approval_direct'] = 0;
319
                $values['allow_attachments_group']['allow_attachments'] = 1;
320
                $values['allow_new_threads_group']['allow_new_threads'] = 1;
321
                $values['default_view_type_group']['default_view_type'] = api_get_setting('default_forum_view');
322
                $values['group_forum'] = $lastId;
323
                if ('1' == $forumState) {
324
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'public';
325
                } elseif ('2' == $forumState) {
326
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'private';
327
                } elseif ('0' == $forumState) {
328
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'unavailable';
329
                }
330
                store_forum($values);
331
            }
332
        }
333
334
        return $lastId;
335
    }
336
337
    /**
338
     * Create subgroups.
339
     * This function creates new groups based on an existing group. It will
340
     * create the specified number of groups and fill those groups with users
341
     * from the base group.
342
     *
343
     * @param int $group_id         the group from which subgroups have to be created
344
     * @param int $number_of_groups The number of groups that have to be created
345
     */
346
    public static function create_subgroups($group_id, $number_of_groups)
347
    {
348
        $courseId = api_get_course_int_id();
349
        $table_group = Database::get_course_table(TABLE_GROUP);
350
        $category_id = self::create_category(
351
            get_lang('Subgroups'),
352
            '',
353
            self::TOOL_PRIVATE,
354
            self::TOOL_PRIVATE,
355
            0,
356
            0,
357
            1,
358
            1
359
        );
360
        $users = self::get_users($group_id);
361
        $group_ids = [];
362
363
        for ($group_nr = 1; $group_nr <= $number_of_groups; $group_nr++) {
364
            $group_ids[] = self::create_group(
365
                get_lang('Subgroup').' '.$group_nr,
366
                $category_id,
367
                0,
368
                0
369
            );
370
        }
371
372
        $members = [];
373
        foreach ($users as $index => $user_id) {
374
            $groupId = $group_ids[$index % $number_of_groups];
375
            self::subscribeUsers(
376
                $user_id,
377
                api_get_group_entity($groupId)
378
            );
379
            $members[$group_ids[$groupId]]++;
380
        }
381
382
        foreach ($members as $group_id => $places) {
383
            $sql = "UPDATE $table_group SET max_student = $places
384
                    WHERE c_id = $courseId  AND id = $group_id";
385
            Database::query($sql);
386
        }
387
    }
388
389
    /**
390
     * Create a group for every class subscribed to the current course.
391
     *
392
     * @author Esteban Ristich <[email protected]>
393
     *
394
     * @param int $categoryId The category in which the groups should be created
395
     * @param array $classIds  The ids of the classes to be created
396
     *
397
     * @return array
398
     */
399
    public static function create_class_groups(int $categoryId, array $classIds = []): array
400
    {
401
        $options['where'] = [' usergroup.course_id = ? ' => api_get_course_int_id()];
402
        $obj = new UserGroupModel();
403
        $classes = $obj->getUserGroupInCourse($options);
404
        $group_ids = [];
405
406
        foreach ($classes as $class) {
407
            if (in_array((int)$class['id'], $classIds)) {
408
                $userList = $obj->get_users_by_usergroup($class['id']);
409
                $groupId = self::create_group(
410
                    $class['title'],
411
                    $categoryId,
412
                    0,
413
                    null
414
                );
415
416
                if ($groupId) {
417
                    self::subscribeUsers($userList, api_get_group_entity($groupId));
418
                    $group_ids[] = $groupId;
419
                }
420
            }
421
        }
422
423
        return $group_ids;
424
    }
425
426
    /**
427
     * Create a group for every class subscribed to the current course
428
     *
429
     * @todo: move part of doctrine query in repository for future
430
     *
431
     * @author Esteban Ristich <[email protected]>
432
     *
433
     * @param int $category_id The category in which the groups should be created
434
     * @param array $classIds The ids of the classes to be created
435
     *
436
     * @return array
437
     * @throws \Doctrine\DBAL\DBALException
438
     */
439
    public static function create_usergroup_consistent_groups(int $category_id = 0, array $classIds = []): array
440
    {
441
        // check if group is not duplicated in same category
442
        /** @var \Chamilo\CourseBundle\Repository\CGroupRelUsergroupRepository $relRepository */
443
        $relRepository = Database::getManager()->getRepository(CGroupRelUsergroup::class);
444
        $filteredClassIds = $classIds;
445
446
        foreach ($classIds as $k => $classId) {
447
            // get count of duclicated groups in same category
448
            $qb = $relRepository->createQueryBuilder('gru');
449
            $qb = $qb->select('count(gru.id)');
450
            $qb = $qb->innerJoin('gru.group', 'g', \Doctrine\ORM\Query\Expr\Join::WITH, 'g.category = :categoryId');
451
            $qb->setParameter('categoryId', $category_id);
452
            $qb->where($qb->expr()->eq('gru.usergroup', ':usergroupId'));
453
            $qb->setParameter('usergroupId', $classId);
454
            // $rawSQL = $qb->getQuery()->getSql();
455
            $groupNb = $qb->getQuery()->getSingleScalarResult();
456
            $isDuplicate = $groupNb !== 0;
457
            if ($isDuplicate) {
458
                unset($filteredClassIds[$k]);
459
            }
460
        }
461
462
        // check if a category has been done, create one otherwise
463
        $categorieGroupe =  self::get_category($category_id);
464
        if (count($categorieGroupe) == 0) {
465
            $category_id = self::create_category(
466
                get_lang('DefaultGroupCategory'),
467
                '',
468
                1,
469
                1,
470
                1,
471
                1,
472
                1,
473
                1
474
            );
475
        }
476
477
        if ($category_id == 0) {
478
            return [];
479
        }
480
481
        // BEGIN TEST
482
        $courseId = api_get_course_int_id();
483
        $sessionId = api_get_session_id();
484
        $group_ids = [];
485
        $session = Database::getManager()->getRepository(Session::class)->find($sessionId);
486
        $course = Database::getManager()->getRepository(Course::class)->find($courseId);
487
488
        foreach ($filteredClassIds as $classId) {
489
            $usergroup = Database::getManager()->getRepository(Usergroup::class)->find($classId);
490
491
            $groupId = self::create_group(
492
                $usergroup->getTitle(), // name of class (usergroup)
493
                $category_id, // category_id
494
                0,
495
                null
496
            );
497
498
            $group = Database::getManager()->getRepository(CGroup::class)->find($groupId);
499
500
            // fill the group from usergroup
501
            $obj = new UserGroupModel();
502
            $userList = $obj->get_users_by_usergroup($classId);
503
            if ($groupId) {
504
                self::subscribeUsers($userList, api_get_group_entity($groupId));
505
            }
506
507
            $groupRelUsergroup = (new CGroupRelUsergroup())
508
                ->setGroup($group)
509
                ->setUsergroup($usergroup)
510
                ->setSession($session)
511
                ->setCourse($course)
512
                ->setReadyAutogroup(0)
513
            ;
514
515
            $em = Database::getManager();
516
            $em->persist($groupRelUsergroup);
517
            $em->flush();
518
519
            $group_ids[] = $groupRelUsergroup->getId();
520
        }
521
        return $group_ids;
522
    }
523
524
    /**
525
     * Get the usergroup (class) linked to the group if it exists.
526
     *
527
     * @author Esteban Ristich <[email protected]>
528
     *
529
     * @param CGroup $group
530
     *
531
     * @return Usergroup|null
532
     */
533
    public static function get_usergroup_link(CGroup $group): ?Usergroup
534
    {
535
        $em = Database::getManager();
536
        $repo = $em->getRepository(CGroupRelUsergroup::class);
537
        $criteria = [
538
            'group' => $group,
539
        ];
540
541
        $rel = $repo->findOneBy($criteria);
542
        if ($rel instanceof CGroupRelUsergroup) {
543
            return $rel->getUsergroup();
544
        } else {
545
            return null;
546
        }
547
    }
548
549
    /**
550
     * Check if a group has a consistent link to an usergroup.
551
     *
552
     * @author Esteban Ristich <[email protected]>
553
     *
554
     * @param CGroup $group
555
     *
556
     * @return bool
557
     */
558
    public static function is_group_linked_to_usergroup(CGroup $group): bool
559
    {
560
        $em = Database::getManager();
561
        $repo = $em->getRepository(CGroupRelUsergroup::class);
562
        $criteria = [
563
            'group' => $group,
564
        ];
565
566
        $rel = $repo->findOneBy($criteria);
567
        return $rel instanceof CGroupRelUsergroup;
568
    }
569
570
    /**
571
     * Remove the consistent link between usergroup and group.
572
     *
573
     * @author Esteban Ristich <[email protected]>
574
     *
575
     * @param CGroup $group
576
     *
577
     * @return bool
578
     */
579
    public static function remove_group_consistent_link(CGroup $group): bool
580
    {
581
        $em = Database::getManager();
582
        $repo = Database::getManager()->getRepository(CGroupRelUsergroup::class);
583
        $criteria = [
584
            'group' => $group,
585
        ];
586
587
        $rel = $repo->findOneBy($criteria);
588
        if ($rel instanceof CGroupRelUsergroup) {
589
            $em->remove($rel);
590
            $em->flush();
591
            return true;
592
        } else {
593
            return false;
594
        }
595
    }
596
597
    /**
598
     * Deletes groups and their data.
599
     *
600
     * @author Christophe Gesche <[email protected]>
601
     * @author Hugues Peeters <[email protected]>
602
     * @author Bart Mollet
603
     *
604
     * @param string $course_code Default is current course
605
     *
606
     * @return int - number of groups deleted
607
     */
608
    public static function deleteGroup(CGroup $group, $course_code = null)
609
    {
610
        if (empty($group)) {
611
            return false;
612
        }
613
        $course_info = api_get_course_info($course_code);
614
        if (empty($course_info)) {
615
            return false;
616
        }
617
618
        $em = Database::getManager();
619
        $groupIid = $group->getIid();
620
621
        // Unsubscribe all users
622
        self::unsubscribeAllUsers($groupIid);
623
        self::unsubscribe_all_tutors($groupIid);
624
625
        $em
626
            ->createQuery(
627
                'DELETE FROM ChamiloCourseBundle:CForum f WHERE f.forumOfGroup = :group'
628
            )
629
            ->execute(['group' => $groupIid]);
630
631
        // delete the groups
632
        $repo = Container::getGroupRepository();
633
        $em->remove($group);
634
        $em->flush();
635
636
        return true;
637
    }
638
639
    /**
640
     * @deprecated Should be deleted by the resources.
641
     *
642
     * Function needed only when deleting a course, in order to be sure that all group ids are deleted.
643
     *
644
     * @param int $courseId
645
     *
646
     * @return bool
647
     */
648
    public static function deleteAllGroupsFromCourse($courseId)
649
    {
650
        $courseId = (int) $courseId;
651
652
        if (empty($courseId)) {
653
            return false;
654
        }
655
656
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
657
        $sql = "SELECT iid FROM $table
658
                WHERE c_id = $courseId ";
659
        Database::query($sql);
660
661
        // Database table definitions
662
        $table = Database::get_course_table(TABLE_GROUP_USER);
663
        $sql = "DELETE FROM $table
664
                WHERE c_id = $courseId";
665
        Database::query($sql);
666
667
        $table = Database::get_course_table(TABLE_GROUP_TUTOR);
668
        $sql = "DELETE FROM $table
669
                WHERE c_id = $courseId";
670
        Database::query($sql);
671
672
        $groupTable = Database::get_course_table(TABLE_GROUP);
673
        $sql = "DELETE FROM $groupTable
674
                WHERE c_id = $courseId";
675
        Database::query($sql);
676
677
        return true;
678
    }
679
680
    /**
681
     * Get group properties.
682
     *
683
     * @param int $group_id the group from which properties are requested
684
     *
685
     * @return array All properties. Array-keys are:
686
     *               name, tutor_id, description, maximum_number_of_students,
687
     *               directory and visibility of tools
688
     */
689
    public static function get_group_properties($group_id)
690
    {
691
        $group_id = (int) $group_id;
692
693
        if (empty($group_id)) {
694
            return null;
695
        }
696
697
        $table_group = Database::get_course_table(TABLE_GROUP);
698
699
        $sql = "SELECT * FROM $table_group
700
                WHERE iid = ".$group_id;
701
702
        $db_result = Database::query($sql);
703
        $db_object = Database::fetch_object($db_result);
704
705
        $result = [];
706
        if ($db_object) {
707
            $result['id'] = $db_object->iid;
708
            $result['iid'] = $db_object->iid;
709
            $result['name'] = $db_object->title; // for temporary compatibility with title - should be removed in the long run
710
            $result['title'] = $db_object->title;
711
            $result['status'] = $db_object->status;
712
            $result['description'] = $db_object->description;
713
            $result['maximum_number_of_students'] = $db_object->max_student;
714
            $result['max_student'] = $db_object->max_student;
715
            $result['doc_state'] = $db_object->doc_state;
716
            $result['work_state'] = $db_object->work_state;
717
            $result['calendar_state'] = $db_object->calendar_state;
718
            $result['announcements_state'] = $db_object->announcements_state;
719
            $result['forum_state'] = $db_object->forum_state;
720
            $result['wiki_state'] = $db_object->wiki_state;
721
            $result['chat_state'] = $db_object->chat_state;
722
            $result['self_registration_allowed'] = $db_object->self_registration_allowed;
723
            $result['self_unregistration_allowed'] = $db_object->self_unregistration_allowed;
724
            $result['count_users'] = 0;
725
            /*$result['count_users'] = count(
726
                self::get_subscribed_users($result)
727
            );*/
728
            /*$result['count_tutor'] = count(
729
                self::get_subscribed_tutors($result)
730
            );*/
731
            //$result['count_all'] = $result['count_users'] + $result['count_tutor'];
732
            $result['count_all'] = null;
733
            $result['document_access'] = isset($db_object->document_access) ? $db_object->document_access : self::DOCUMENT_MODE_SHARE;
734
        }
735
736
        return $result;
737
    }
738
739
    /**
740
     * @param string $name
741
     * @param string $courseCode
742
     * @param int    $sessionId
743
     *
744
     * @return array
745
     */
746
    public static function getGroupByName($name, $courseCode = null, $sessionId = 0)
747
    {
748
        $name = trim($name);
749
750
        if (empty($name)) {
751
            return [];
752
        }
753
754
        $course_info = api_get_course_info($courseCode);
755
        $course_id = $course_info['real_id'];
756
        $name = Database::escape_string($name);
757
        $sessionId = empty($sessionId) ? api_get_session_id() : (int) $sessionId;
758
        $sessionCondition = api_get_session_condition($sessionId);
759
760
        $table = Database::get_course_table(TABLE_GROUP);
761
        $sql = "SELECT * FROM $table
762
                WHERE
763
                  c_id = $course_id AND
764
                  name = '$name'
765
                  $sessionCondition
766
                LIMIT 1";
767
        $res = Database::query($sql);
768
        $group = [];
769
        if (Database::num_rows($res)) {
770
            $group = Database::fetch_assoc($res);
771
        }
772
773
        return $group;
774
    }
775
776
    /**
777
     * Set group properties
778
     * Changes the group's properties.
779
     *
780
     * @param int       Group Id
781
     * @param string    Group name
782
     * @param string    Group description
783
     * @param int       Max number of students in group
784
     * @param int       Document tool's visibility (0=none,1=private,2=public)
785
     * @param int       Work tool's visibility (0=none,1=private,2=public)
786
     * @param int       Calendar tool's visibility (0=none,1=private,2=public)
787
     * @param int       Announcement tool's visibility (0=none,1=private,2=public)
788
     * @param int       Forum tool's visibility (0=none,1=private,2=public)
789
     * @param int       Wiki tool's visibility (0=none,1=private,2=public)
790
     * @param int       Chat tool's visibility (0=none,1=private,2=public)
791
     * @param bool Whether self registration is allowed or not
792
     * @param bool Whether self unregistration is allowed or not
793
     * @param int $categoryId
794
     * @param int $documentAccess
795
     *
796
     * @return bool TRUE if properties are successfully changed, false otherwise
797
     */
798
    public static function set_group_properties(
799
        $group_id,
800
        $name,
801
        $description,
802
        $maxStudent,
803
        $docState,
804
        $workState,
805
        $calendarState,
806
        $anonuncementState,
807
        $forumState,
808
        $wikiState,
809
        $chatState,
810
        $selfRegistrationAllowed,
811
        $selfUnRegistrationAllowed,
812
        $categoryId = null,
813
        $documentAccess = 0
814
    ) {
815
        $table_forum = Database::get_course_table(TABLE_FORUM);
816
        $categoryId = (int) $categoryId;
817
        $group_id = (int) $group_id;
818
        $forumState = (int) $forumState;
819
        $repo = Container::getGroupRepository();
820
821
        /** @var CGroup $group */
822
        $group = $repo->find($group_id);
823
824
        $category = null;
825
        if (!empty($categoryId)) {
826
            $category = Container::getGroupCategoryRepository()->find($categoryId);
827
        }
828
829
        $group
830
            ->setTitle($name)
831
            ->setCategory($category)
832
            ->setMaxStudent($maxStudent)
833
            ->setDocState($docState)
834
            ->setCalendarState($calendarState)
835
            ->setWorkState($workState)
836
            ->setForumState($forumState)
837
            ->setWikiState($wikiState)
838
            ->setAnnouncementsState($anonuncementState)
839
            ->setChatState($chatState)
840
            ->setSelfRegistrationAllowed($selfRegistrationAllowed)
841
            ->setSelfUnregistrationAllowed($selfUnRegistrationAllowed)
842
            ->setDocumentAccess($documentAccess)
843
        ;
844
845
        $repo->update($group);
846
847
        /* Here we are updating a field in the table forum_forum that perhaps
848
        duplicates the table group_info.forum_state cvargas*/
849
        $sql2 = "UPDATE $table_forum SET ";
850
        if (1 === $forumState) {
851
            $sql2 .= " forum_group_public_private='public' ";
852
        } elseif (2 === $forumState) {
853
            $sql2 .= " forum_group_public_private='private' ";
854
        } elseif (0 === $forumState) {
855
            $sql2 .= " forum_group_public_private='unavailable' ";
856
        }
857
        $sql2 .= ' WHERE forum_of_group='.$group_id;
858
        Database::query($sql2);
859
860
        return true;
861
    }
862
863
    /**
864
     * Get the total number of groups for the current course.
865
     *
866
     * @return int the number of groups for the current course
867
     */
868
    public static function get_number_of_groups()
869
    {
870
        $repo = Container::getGroupRepository();
871
872
        $course = api_get_course_entity(api_get_course_int_id());
873
        if (null === $course) {
874
            return 0;
875
        }
876
877
        $session = api_get_session_entity(api_get_session_id());
878
        $group = api_get_group_entity(api_get_group_id());
879
        $qb = $repo->getResourcesByCourse($course, $session, $group);
880
        $qb->select('count(resource)');
881
882
        return $qb->getQuery()->getSingleScalarResult();
883
        /*$courseId = api_get_course_int_id();
884
        $table = Database::get_course_table(TABLE_GROUP);
885
        $sql = "SELECT COUNT(id) AS number_of_groups
886
                FROM $table
887
                WHERE c_id = $courseId ";
888
        $res = Database::query($sql);
889
        $obj = Database::fetch_object($res);
890
891
        return $obj->number_of_groups;*/
892
    }
893
894
    /**
895
     * Get all categories.
896
     */
897
    public static function get_categories(Course $course = null): array
898
    {
899
        $repo = Container::getGroupCategoryRepository();
900
901
        if (null === $course) {
902
            $course = api_get_course_entity(api_get_course_int_id());
903
        }
904
905
        $session = api_get_session_entity(api_get_session_id());
906
        $group = null;
907
908
        $qb = $repo->getResourcesByCourse($course, $session, $group, null, true, true);
909
910
        return $qb->getQuery()->getArrayResult();
911
    }
912
913
    /**
914
     * Get a group category.
915
     *
916
     * @param int    $id          The category id
917
     * @param string $course_code The course (default = current course)
918
     *
919
     * @return array
920
     */
921
    public static function get_category($id, $course_code = null)
922
    {
923
        if (empty($id)) {
924
            return [];
925
        }
926
927
        $courseInfo = api_get_course_info($course_code);
928
        $courseId = $courseInfo['real_id'];
929
        $id = (int) $id;
930
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
931
        $sql = "SELECT * FROM $table
932
                WHERE  iid = $id
933
                LIMIT 1";
934
        $res = Database::query($sql);
935
936
        return Database::fetch_array($res);
937
    }
938
939
    /**
940
     * Get a group category.
941
     *
942
     * @param string $title
943
     * @param string $course_code The course (default = current course)
944
     *
945
     * @return array
946
     */
947
    public static function getCategoryByTitle($title, $course_code = null)
948
    {
949
        $title = trim($title);
950
951
        if (empty($title)) {
952
            return [];
953
        }
954
955
        $course_info = api_get_course_info($course_code);
956
        $courseId = $course_info['real_id'];
957
        $title = Database::escape_string($title);
958
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
959
        $sql = "SELECT * FROM $table
960
                WHERE c_id = $courseId AND title = '$title'
961
                LIMIT 1";
962
        $res = Database::query($sql);
963
        $category = [];
964
        if (Database::num_rows($res)) {
965
            $category = Database::fetch_assoc($res);
966
        }
967
968
        return $category;
969
    }
970
971
    /**
972
     * Get the unique category of a given group.
973
     *
974
     * @param int    $group_id    The iid of the group
975
     * @param string $course_code The course in which the group is (default =
976
     *                            current course)
977
     *
978
     * @return array The category
979
     */
980
    public static function get_category_from_group($group_id, $course_code = '')
981
    {
982
        $table_group = Database::get_course_table(TABLE_GROUP);
983
        $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
984
985
        $group_id = (int) $group_id;
986
987
        if (empty($group_id)) {
988
            return [];
989
        }
990
991
        $course_info = api_get_course_info($course_code);
992
993
        if (empty($course_info)) {
994
            return false;
995
        }
996
997
        $sql = "SELECT gc.* FROM $table_group_cat gc
998
                INNER JOIN $table_group g
999
                ON (gc.iid = g.category_id)
1000
                WHERE
1001
                    g.iid = $group_id
1002
                LIMIT 1";
1003
        $res = Database::query($sql);
1004
        $cat = [];
1005
        if (Database::num_rows($res)) {
1006
            $cat = Database::fetch_array($res);
1007
        }
1008
1009
        return $cat;
1010
    }
1011
1012
    /**
1013
     * Delete a group category.
1014
     *
1015
     * @param int    $cat_id      The id of the category to delete
1016
     * @param string $course_code The code in which the category should be
1017
     *                            deleted (default = current course)
1018
     *
1019
     * @return bool
1020
     */
1021
    public static function delete_category($cat_id, $course_code = '')
1022
    {
1023
        $course_info = api_get_course_info($course_code);
1024
        if (empty($course_info)) {
1025
            return false;
1026
        }
1027
1028
        $table_group = Database::get_course_table(TABLE_GROUP);
1029
        $cat_id = (int) $cat_id;
1030
        $sql = "SELECT iid FROM $table_group
1031
                WHERE category_id='".$cat_id."'";
1032
        $res = Database::query($sql);
1033
        if (Database::num_rows($res) > 0) {
1034
            while ($group = Database::fetch_object($res)) {
1035
                // Delete all groups in category
1036
                /*$groupInfo = self::get_group_properties($group->iid, true);
1037
                self::deleteGroup($groupInfo, $course_code);
1038
                */
1039
                // Set the category to NULL to avoid losing groups in sessions.
1040
                $sql = "UPDATE $table_group SET category_id = NULL WHERE iid = ".$group->iid;
1041
                Database::query($sql);
1042
            }
1043
        }
1044
1045
        $category = Database::getManager()->getRepository(CGroupCategory::class)->find($cat_id);
1046
        if ($category) {
1047
            Database::getManager()->remove($category);
1048
            Database::getManager()->flush();
1049
        }
1050
1051
        /*$sql = "DELETE FROM $table_group_cat
1052
                WHERE iid='".$cat_id."'";
1053
        Database::query($sql);*/
1054
1055
        return true;
1056
    }
1057
1058
    /**
1059
     * Create group category.
1060
     *
1061
     * @param string $title                     The title of the new category
1062
     * @param string $description               The description of the new category
1063
     * @param int    $selfRegistrationAllowed   allow users to self register
1064
     * @param int    $selfUnRegistrationAllowed allow user to self unregister
1065
     * @param int    $documentAccess            document access
1066
     *
1067
     * @return mixed
1068
     */
1069
    public static function create_category(
1070
        $title,
1071
        $description = '',
1072
        $docState = 1,
1073
        $workState = 1,
1074
        $calendarState = 1,
1075
        $anonuncementState = 1,
1076
        $forumState = 1,
1077
        $wikiState = 1,
1078
        $chatState = 1,
1079
        $selfRegistrationAllowed = 0,
1080
        $selfUnRegistrationAllowed = 0,
1081
        $maxStudent = 8,
1082
        $groupsPerUser = 0,
1083
        $documentAccess = 0
1084
    ) {
1085
        if (empty($title)) {
1086
            return false;
1087
        }
1088
1089
        $course = api_get_course_entity(api_get_course_int_id());
1090
        $session = api_get_session_entity(api_get_session_id());
1091
1092
        $category = new CGroupCategory();
1093
        $category
1094
            ->setTitle($title)
1095
            ->setDescription($description)
1096
            ->setMaxStudent($maxStudent)
1097
            ->setDocState($docState)
1098
            ->setCalendarState($calendarState)
1099
            ->setWorkState($workState)
1100
            ->setForumState($forumState)
1101
            ->setWikiState($wikiState)
1102
            ->setAnnouncementsState($anonuncementState)
1103
            ->setChatState($chatState)
1104
            ->setSelfRegAllowed($selfRegistrationAllowed)
1105
            ->setSelfUnregAllowed($selfUnRegistrationAllowed)
1106
            ->setDocumentAccess($documentAccess)
1107
            ->setGroupsPerUser($groupsPerUser)
1108
            ->setParent($course)
1109
            ->addCourseLink($course, $session)
1110
        ;
1111
1112
        $repo = Container::getGroupCategoryRepository();
1113
        $repo->create($category);
1114
1115
        return $category->getIid();
1116
    }
1117
1118
    /**
1119
     * Update group category.
1120
     *
1121
     * @param int    $id
1122
     * @param string $title
1123
     * @param string $description
1124
     * @param $doc_state
1125
     * @param $work_state
1126
     * @param $calendar_state
1127
     * @param $announcements_state
1128
     * @param $forum_state
1129
     * @param $wiki_state
1130
     * @param $chat_state
1131
     * @param $selfRegistrationAllowed
1132
     * @param $selfUnRegistrationAllowed
1133
     * @param $maximum_number_of_students
1134
     * @param $groups_per_user
1135
     * @param $documentAccess
1136
     */
1137
    public static function update_category(
1138
        $id,
1139
        $title,
1140
        $description,
1141
        $doc_state,
1142
        $work_state,
1143
        $calendar_state,
1144
        $announcements_state,
1145
        $forum_state,
1146
        $wiki_state,
1147
        $chat_state,
1148
        $selfRegistrationAllowed,
1149
        $selfUnRegistrationAllowed,
1150
        $maximum_number_of_students,
1151
        $groups_per_user,
1152
        $documentAccess
1153
    ) {
1154
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
1155
        $id = (int) $id;
1156
1157
        $allowDocumentAccess = ('true' === api_get_setting('document.group_category_document_access'));
1158
        $documentCondition = '';
1159
        if ($allowDocumentAccess) {
1160
            $documentAccess = (int) $documentAccess;
1161
            $documentCondition = " document_access = $documentAccess, ";
1162
        }
1163
1164
        $sql = 'UPDATE '.$table." SET
1165
                    title='".Database::escape_string($title)."',
1166
                    description='".Database::escape_string($description)."',
1167
                    doc_state = '".Database::escape_string($doc_state)."',
1168
                    work_state = '".Database::escape_string($work_state)."',
1169
                    calendar_state = '".Database::escape_string($calendar_state)."',
1170
                    announcements_state = '".Database::escape_string($announcements_state)."',
1171
                    forum_state = '".Database::escape_string($forum_state)."',
1172
                    wiki_state = '".Database::escape_string($wiki_state)."',
1173
                    chat_state = '".Database::escape_string($chat_state)."',
1174
                    groups_per_user   = '".Database::escape_string($groups_per_user)."',
1175
                    self_reg_allowed = '".Database::escape_string($selfRegistrationAllowed)."',
1176
                    self_unreg_allowed = '".Database::escape_string($selfUnRegistrationAllowed)."',
1177
                    $documentCondition
1178
                    max_student = ".intval($maximum_number_of_students)."
1179
                WHERE iid = $id";
1180
        Database::query($sql);
1181
1182
        // Updating all groups inside this category
1183
        $groups = self::get_group_list($id);
1184
1185
        if (!empty($groups)) {
1186
            foreach ($groups as $group) {
1187
                self::set_group_properties(
1188
                    $group['iid'],
1189
                    $group['title'],
1190
                    $group['description'],
1191
                    $maximum_number_of_students,
1192
                    $doc_state,
1193
                    $work_state,
1194
                    $calendar_state,
1195
                    $announcements_state,
1196
                    $forum_state,
1197
                    $wiki_state,
1198
                    $chat_state,
1199
                    $selfRegistrationAllowed,
1200
                    $selfUnRegistrationAllowed,
1201
                    $id,
1202
                    $documentAccess
1203
                );
1204
            }
1205
        }
1206
    }
1207
1208
    /**
1209
     * Returns the number of groups of the user with the greatest number of
1210
     * subscriptions in the given category.
1211
     */
1212
    public static function get_current_max_groups_per_user($category_id = null, $course_code = null)
1213
    {
1214
        $course_info = api_get_course_info($course_code);
1215
        $group_table = Database::get_course_table(TABLE_GROUP);
1216
1217
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1218
        $sql = "SELECT COUNT(gu.group_id) AS current_max
1219
                FROM $group_user_table gu
1220
                INNER JOIN $group_table g
1221
                ON (gu.group_id = g.iid)
1222
                WHERE 1= 1 ";
1223
        if (null != $category_id) {
1224
            $category_id = intval($category_id);
1225
            $sql .= ' AND g.category_id = '.$category_id;
1226
        }
1227
        $sql .= ' GROUP BY gu.user_id
1228
                  ORDER BY current_max DESC LIMIT 1';
1229
1230
        $res = Database::query($sql);
1231
        $obj = Database::fetch_object($res);
1232
1233
        if ($obj) {
1234
            return $obj->current_max;
1235
        }
1236
1237
        return 0;
1238
    }
1239
1240
    /**
1241
     * Swaps the display-order of two categories.
1242
     *
1243
     * @param int $id1 The id of the first category
1244
     * @param int $id2 The id of the second category
1245
     */
1246
    public static function swap_category_order($id1, $id2)
1247
    {
1248
        $em = Database::getManager();
1249
1250
        $course = api_get_course_entity();
1251
        $session = api_get_session_entity();
1252
1253
        $groupCategoryRepo = $em->getRepository(CGroupCategory::class);
1254
        $cat1 = $groupCategoryRepo->find($id1);
1255
        $cat2 = $groupCategoryRepo->find($id2);
1256
1257
        if ($cat1 && $cat2) {
1258
            $node1 = $cat1->getResourceNode();
1259
            $node2 = $cat2->getResourceNode();
1260
1261
            if ($node1 && $node2) {
1262
                $link1 = $node1->getResourceLinkByContext($course, $session);
1263
                $link2 = $node2->getResourceLinkByContext($course, $session);
1264
1265
                if ($link1 && $link2) {
1266
                    $order1 = $link1->getDisplayOrder();
1267
                    $order2 = $link2->getDisplayOrder();
1268
1269
                    $link1->setDisplayOrder($order2);
1270
                    $link2->setDisplayOrder($order1);
1271
                }
1272
1273
                $em->flush();
1274
            }
1275
        }
1276
    }
1277
1278
    /**
1279
     * Get all users from a given group.
1280
     *
1281
     * @param int  $group_id        The group
1282
     * @param bool $load_extra_info
1283
     * @param int  $start
1284
     * @param int  $limit
1285
     * @param bool $getCount
1286
     * @param int  $courseId
1287
     * @param $column
1288
     * @param $direction
1289
     *
1290
     * @return array list of user id
1291
     */
1292
    public static function get_users(
1293
        $group_id,
1294
        $load_extra_info = false,
1295
        $start = null,
1296
        $limit = null,
1297
        $getCount = false,
1298
        $courseId = null,
1299
        $column = null,
1300
        $direction = null
1301
    ) {
1302
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1303
        $groupTable = Database::get_course_table(TABLE_GROUP);
1304
        $user_table = Database::get_main_table(TABLE_MAIN_USER);
1305
        $group_id = (int) $group_id;
1306
1307
        if (empty($courseId)) {
1308
            $courseId = api_get_course_int_id();
1309
        } else {
1310
            $courseId = (int) $courseId;
1311
        }
1312
1313
        $select = ' SELECT u.id, firstname, lastname ';
1314
        if ($getCount) {
1315
            $select = ' SELECT count(u.id) count';
1316
        }
1317
        $sql = "$select
1318
                FROM $group_user_table gu
1319
                INNER JOIN $groupTable g
1320
                ON (gu.group_id = g.iid)
1321
                INNER JOIN $user_table u
1322
                ON (u.id = gu.user_id)
1323
                WHERE u.active <> ".USER_SOFT_DELETED." AND
1324
                    g.iid = $group_id";
1325
1326
        if (!empty($column) && !empty($direction)) {
1327
            $column = Database::escape_string($column);
1328
            $direction = ('ASC' === $direction ? 'ASC' : 'DESC');
1329
            $sql .= " ORDER BY `$column` $direction";
1330
        }
1331
1332
        if (!empty($start) && !empty($limit)) {
1333
            $start = (int) $start;
1334
            $limit = (int) $limit;
1335
            $sql .= " LIMIT $start, $limit";
1336
        }
1337
        $res = Database::query($sql);
1338
        $users = [];
1339
        while ($obj = Database::fetch_object($res)) {
1340
            if ($getCount) {
1341
                return $obj->count;
1342
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
1343
            }
1344
            if ($load_extra_info) {
1345
                $users[] = api_get_user_info($obj->id);
1346
            } else {
1347
                $users[] = $obj->id;
1348
            }
1349
        }
1350
1351
        return $users;
1352
    }
1353
1354
    /**
1355
     * @param int $group_id id
1356
     *
1357
     * @return array
1358
     */
1359
    public static function getStudentsAndTutors($group_id)
1360
    {
1361
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1362
        $tutor_user_table = Database::get_course_table(TABLE_GROUP_TUTOR);
1363
        $groupTable = Database::get_course_table(TABLE_GROUP);
1364
1365
        $course_id = api_get_course_int_id();
1366
        $group_id = (int) $group_id;
1367
1368
        $sql = "SELECT user_id
1369
                FROM $group_user_table gu
1370
                INNER JOIN $groupTable g
1371
                ON (gu.group_id = g.iid)
1372
                WHERE g.iid = $group_id";
1373
        $res = Database::query($sql);
1374
        $users = [];
1375
1376
        while ($obj = Database::fetch_object($res)) {
1377
            $users[] = api_get_user_info($obj->user_id);
1378
        }
1379
1380
        $sql = "SELECT user_id
1381
                FROM $tutor_user_table gu
1382
                INNER JOIN $groupTable g
1383
                ON (gu.group_id = g.iid)
1384
                WHERE g.iid = $group_id";
1385
        $res = Database::query($sql);
1386
        while ($obj = Database::fetch_object($res)) {
1387
            $users[] = api_get_user_info($obj->user_id);
1388
        }
1389
1390
        return $users;
1391
    }
1392
1393
    /**
1394
     * Get only tutors from a group.
1395
     *
1396
     * @param array $groupInfo
1397
     *
1398
     * @return array
1399
     */
1400
    public static function getTutors($groupInfo)
1401
    {
1402
        $groupTable = Database::get_course_table(TABLE_GROUP);
1403
        $tutor_user_table = Database::get_course_table(TABLE_GROUP_TUTOR);
1404
        $course_id = api_get_course_int_id();
1405
        $group_id = (int) $groupInfo['iid'];
1406
1407
        $sql = "SELECT user_id
1408
                FROM $tutor_user_table gu
1409
                INNER JOIN $groupTable g
1410
                ON (gu.group_id = g.iid)
1411
                WHERE g.iid = $group_id";
1412
        $res = Database::query($sql);
1413
1414
        $users = [];
1415
        while ($obj = Database::fetch_object($res)) {
1416
            $users[] = api_get_user_info($obj->user_id);
1417
        }
1418
1419
        return $users;
1420
    }
1421
1422
    /**
1423
     * Get only students from a group (not tutors).
1424
     *
1425
     * @param bool $filterOnlyActive
1426
     *
1427
     * @return array
1428
     */
1429
    public static function getStudents($groupId, $filterOnlyActive = false)
1430
    {
1431
        $groupId = (int) $groupId;
1432
        $activeCondition = $filterOnlyActive ? 'AND u.active = 1' : '';
1433
1434
        $em = Database::getManager();
1435
        $subscriptions = $em
1436
            ->createQuery("
1437
                SELECT u.id FROM ChamiloCoreBundle:User u
1438
                INNER JOIN ChamiloCourseBundle:CGroupRelUser gu
1439
                WITH u.id = gu.user
1440
                INNER JOIN ChamiloCourseBundle:CGroup g
1441
                WITH gu.group = g.iid
1442
                WHERE g.iid = :group
1443
                    $activeCondition
1444
            ")
1445
            ->setParameters([
1446
                'group' => $groupId,
1447
            ])
1448
            ->getResult();
1449
1450
        $users = [];
1451
        if (!empty($subscriptions)) {
1452
            foreach ($subscriptions as $subscription) {
1453
                $users[] = api_get_user_info($subscription['id']);
1454
            }
1455
        }
1456
1457
        return $users;
1458
    }
1459
1460
    public static function getStudentsCount($groupId, $filterOnlyActive = false)
1461
    {
1462
        $groupId = (int) $groupId;
1463
        $activeCondition = $filterOnlyActive ? 'AND u.active = 1' : '';
1464
1465
        $em = Database::getManager();
1466
1467
        return $em
1468
            ->createQuery("
1469
                SELECT COUNT(u.id) FROM ChamiloCoreBundle:User u
1470
                INNER JOIN ChamiloCourseBundle:CGroupRelUser gu
1471
                WITH u.id = gu.user
1472
                INNER JOIN ChamiloCourseBundle:CGroup g
1473
                WITH gu.group = g.iid
1474
                WHERE g.iid = :group
1475
                    $activeCondition
1476
            ")
1477
            ->setParameters([
1478
                'group' => $groupId,
1479
            ])
1480
            ->getSingleScalarResult();
1481
    }
1482
1483
    /**
1484
     * Returns users belonging to any of the group.
1485
     *
1486
     * @param array $groups list of group ids
1487
     *
1488
     * @return array list of user ids
1489
     */
1490
    public static function get_groups_users($groups = [])
1491
    {
1492
        $result = [];
1493
        $table = Database::get_course_table(TABLE_GROUP_USER);
1494
        $groups = array_map('intval', $groups);
1495
        // protect individual elements with surrounding quotes
1496
        $groups = implode(', ', $groups);
1497
        $sql = "SELECT DISTINCT user_id
1498
                FROM $table gu
1499
                WHERE gu.group_id IN ($groups)";
1500
        $rs = Database::query($sql);
1501
        while ($row = Database::fetch_array($rs)) {
1502
            $result[] = $row['user_id'];
1503
        }
1504
1505
        return $result;
1506
    }
1507
1508
    /**
1509
     * Fill the groups with students.
1510
     * The algorithm takes care to first fill the groups with the least # of users.
1511
     * Analysis
1512
     * There was a problem with the "ALL" setting.
1513
     * When max # of groups is set to all, the value is sometimes NULL and sometimes ALL
1514
     * and in both cased the query does not work as expected.
1515
     * Stupid solution (currently implemented: set ALL to a big number (INFINITE) and things are solved :)
1516
     * Better solution: that's up to you.
1517
     *
1518
     * Note
1519
     * Throughout Dokeos there is some confusion about "course id" and "course code"
1520
     * The code is e.g. TEST101, but sometimes a variable that is called courseID also contains a course code string.
1521
     * However, there is also a integer course_id that uniquely identifies the course.
1522
     * ywarnier:> Now the course_id has been removed (25/1/2005)
1523
     * The databases are als very inconsistent in this.
1524
     *
1525
     * @author Chrisptophe Gesche <[email protected]>,
1526
     *         Hugues Peeters     <[email protected]> - original version
1527
     * @author Roan Embrechts - virtual course support, code cleaning
1528
     * @author Bart Mollet - code cleaning, use other GroupManager-functions
1529
     *
1530
     * @return bool
1531
     */
1532
    public static function fillGroupWithUsers(CGroup $group)
1533
    {
1534
        $_course = api_get_course_info();
1535
        if (empty($_course) || empty($group)) {
1536
            return false;
1537
        }
1538
        $session_id = api_get_session_id();
1539
        $complete_user_list = CourseManager::get_user_list_from_course_code(
1540
            $_course['code'],
1541
            $session_id
1542
        );
1543
        $groupIid = $group->getIid();
1544
        $category = self::get_category_from_group($groupIid);
1545
1546
        // Getting max numbers of user from group
1547
        $maxNumberStudents = empty($group->getMaxStudent()) ? self::INFINITE : $group->getMaxStudent();
1548
        $groupsPerUser = self::INFINITE;
1549
        $categoryId = 0;
1550
        if ($category) {
1551
            $groupsPerUser = empty($category['groups_per_user']) ? self::INFINITE : $category['groups_per_user'];
1552
            $maxNumberStudentsCategory = empty($category['max_student']) ? self::INFINITE : $category['max_student'];
1553
            $categoryId = $category['iid'];
1554
            if ($maxNumberStudentsCategory < $maxNumberStudents) {
1555
                $maxNumberStudents = $maxNumberStudentsCategory;
1556
            }
1557
        }
1558
1559
        $usersToAdd = [];
1560
        foreach ($complete_user_list as $userInfo) {
1561
            $isSubscribed = self::is_subscribed($userInfo['user_id'], $group);
1562
            if ($isSubscribed) {
1563
                continue;
1564
            }
1565
            $numberOfGroups = self::user_in_number_of_groups(
1566
                $userInfo['user_id'],
1567
                $categoryId
1568
            );
1569
            if ($groupsPerUser > $numberOfGroups) {
1570
                $usersToAdd[] = $userInfo['user_id'];
1571
            }
1572
            if (count($usersToAdd) == $maxNumberStudents) {
1573
                break;
1574
            }
1575
        }
1576
1577
        foreach ($usersToAdd as $userId) {
1578
            self::subscribeUsers($userId, $group);
1579
        }
1580
    }
1581
1582
    /**
1583
     * Get the number of students in a group.
1584
     *
1585
     * @param int $group_id id
1586
     *
1587
     * @return int number of students in the given group
1588
     */
1589
    public static function number_of_students($group_id, $course_id = null)
1590
    {
1591
        $table = Database::get_course_table(TABLE_GROUP_USER);
1592
        $group_id = (int) $group_id;
1593
        $course_id = (int) $course_id;
1594
1595
        if (empty($course_id)) {
1596
            $course_id = api_get_course_int_id();
1597
        }
1598
        $sql = "SELECT COUNT(*) AS number_of_students
1599
                FROM $table
1600
                WHERE c_id = $course_id AND group_id = $group_id";
1601
        $result = Database::query($sql);
1602
        $db_object = Database::fetch_object($result);
1603
1604
        return $db_object->number_of_students;
1605
    }
1606
1607
    /**
1608
     * Maximum number of students in a group.
1609
     *
1610
     * @param int $group_id iid
1611
     *
1612
     * @return int maximum number of students in the given group
1613
     */
1614
    public static function maximum_number_of_students($group_id)
1615
    {
1616
        $table = Database::get_course_table(TABLE_GROUP);
1617
        $group_id = (int) $group_id;
1618
        $course_id = api_get_course_int_id();
1619
        $sql = "SELECT max_student FROM $table
1620
                WHERE iid = $group_id";
1621
        $db_result = Database::query($sql);
1622
        $db_object = Database::fetch_object($db_result);
1623
        if (0 == $db_object->max_student) {
1624
            return self::INFINITE;
1625
        }
1626
1627
        return $db_object->max_student;
1628
    }
1629
1630
    /**
1631
     * Number of groups of a user.
1632
     *
1633
     * @param int $user_id
1634
     * @param int $cat_id
1635
     *
1636
     * @return int the number of groups the user is subscribed in
1637
     */
1638
    public static function user_in_number_of_groups($user_id, $cat_id = 0)
1639
    {
1640
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1641
        $table_group = Database::get_course_table(TABLE_GROUP);
1642
        $user_id = (int) $user_id;
1643
        $cat_id = (int) $cat_id;
1644
1645
        $course_id = api_get_course_int_id();
1646
        $cat_condition = '';
1647
        if (!empty($cat_id)) {
1648
            $cat_condition = " AND g.category_id =  $cat_id ";
1649
        }
1650
1651
        $sql = "SELECT COUNT(*) AS number_of_groups
1652
                FROM $table_group_user gu
1653
                INNER JOIN $table_group g
1654
                ON (g.iid = gu.group_id)
1655
                WHERE
1656
                    gu.user_id = $user_id
1657
                    $cat_condition";
1658
1659
        $result = Database::query($sql);
1660
        $db_object = Database::fetch_object($result);
1661
1662
        return $db_object->number_of_groups;
1663
    }
1664
1665
    /**
1666
     * Is sef-registration allowed?
1667
     *
1668
     * @param int $user_id
1669
     *
1670
     * @return bool TRUE if self-registration is allowed in the given group
1671
     */
1672
    public static function is_self_registration_allowed($user_id, CGroup $group)
1673
    {
1674
        if (empty($user_id)) {
1675
            return false;
1676
        }
1677
1678
        if ($group) {
1679
            if (0 == $group->getStatus() || 1 != $group->getSelfRegistrationAllowed()) {
1680
                return false;
1681
            }
1682
1683
            return self::canUserSubscribe($user_id, $group);
1684
        }
1685
1686
        return false;
1687
    }
1688
1689
    /**
1690
     * Is sef-unregistration allowed?
1691
     *
1692
     * @param int $user_id
1693
     *
1694
     * @return bool TRUE if self-unregistration is allowed in the given group
1695
     */
1696
    public static function is_self_unregistration_allowed($user_id, CGroup $group)
1697
    {
1698
        if (empty($user_id) || empty($group)) {
1699
            return false;
1700
        }
1701
        if (0 == $group->getStatus() || 1 != $group->getSelfUnregistrationAllowed()) {
1702
            return false;
1703
        }
1704
1705
        return self::is_subscribed($user_id, $group);
1706
    }
1707
1708
    /**
1709
     * Is user subscribed in group?
1710
     *
1711
     * @param int $user_id
1712
     *
1713
     * @return bool TRUE if given user is subscribed in given group
1714
     */
1715
    public static function is_subscribed($user_id, CGroup $group)
1716
    {
1717
        $course_id = api_get_course_int_id();
1718
        if (empty($user_id) || empty($group) || empty($course_id)) {
1719
            return false;
1720
        }
1721
        $table = Database::get_course_table(TABLE_GROUP_USER);
1722
        $group_id = $group->getIid();
1723
        $user_id = (int) $user_id;
1724
1725
        $sql = "SELECT 1 FROM $table
1726
                WHERE
1727
                    group_id = $group_id AND
1728
                    user_id = $user_id
1729
                ";
1730
        $result = Database::query($sql);
1731
1732
        return Database::num_rows($result) > 0;
1733
    }
1734
1735
    /**
1736
     * Can a user subscribe to a specified group in a course.
1737
     *
1738
     * @param int  $user_id
1739
     * @param bool $checkMaxNumberStudents
1740
     *
1741
     * @return bool true if success
1742
     */
1743
    public static function canUserSubscribe(
1744
        $user_id,
1745
        CGroup $group,
1746
        $checkMaxNumberStudents = true
1747
    ) {
1748
        $groupIid = $group->getIid();
1749
        if ($checkMaxNumberStudents) {
1750
            $category = self::get_category_from_group($group->getIid());
1751
            if ($category) {
1752
                if (self::GROUP_PER_MEMBER_NO_LIMIT == $category['groups_per_user']) {
1753
                    $category['groups_per_user'] = self::INFINITE;
1754
                }
1755
                $result = self::user_in_number_of_groups($user_id, $category['iid']) < $category['groups_per_user'];
1756
                if (false == $result) {
1757
                    return false;
1758
                }
1759
            }
1760
1761
            $result = self::number_of_students($groupIid) < self::maximum_number_of_students($groupIid);
1762
1763
            if (false == $result) {
1764
                return false;
1765
            }
1766
        }
1767
1768
        $result = self::isTutorOfGroup($user_id, $group);
1769
1770
        if ($result) {
1771
            return false;
1772
        }
1773
1774
        $result = self::is_subscribed($user_id, $group);
1775
1776
        if ($result) {
1777
            return false;
1778
        }
1779
1780
        return true;
1781
    }
1782
1783
    /**
1784
     * Get all subscribed users (members) from a group.
1785
     *
1786
     * @return array An array with information of all users from the given group.
1787
     *               (user_id, firstname, lastname, email)
1788
     */
1789
    public static function get_subscribed_users(CGroup $group)
1790
    {
1791
        //$order = api_sort_by_first_name() ? ' ORDER BY u.firstname, u.lastname' : ' ORDER BY u.lastname, u.firstname';
1792
        $order = ['lastname' => Criteria::DESC, 'firstname' => Criteria::ASC];
1793
        if (api_sort_by_first_name()) {
1794
            $order = ['firstname' => Criteria::ASC, 'lastname' => Criteria::ASC];
1795
        }
1796
        $orderListByOfficialCode = api_get_setting('order_user_list_by_official_code');
1797
        if ('true' === $orderListByOfficialCode) {
1798
            //$order = ' ORDER BY u.official_code, u.firstname, u.lastname';
1799
            $order = ['officialCode' => Criteria::ASC, 'firstname' => Criteria::ASC, 'lastname' => Criteria::ASC];
1800
        }
1801
1802
        $users = $group->getMembers();
1803
        $userList = [];
1804
        foreach ($users as $groupRelUser) {
1805
            $userList[] = $groupRelUser->getUser();
1806
        }
1807
1808
        $criteria = Criteria::create();
1809
        $criteria->orderBy($order);
1810
        $users = new ArrayCollection($userList);
1811
        $users = $users->matching($criteria);
1812
1813
        $list = [];
1814
        foreach ($users as $user) {
1815
            $list[$user->getId()] = [
1816
                'user_id' => $user->getId(),
1817
                'firstname' => $user->getFirstname(),
1818
                'lastname' => $user->getLastname(),
1819
                'email' => $user->getEmail(),
1820
                'username' => $user->getUsername(),
1821
            ];
1822
        }
1823
1824
        return $list;
1825
    }
1826
1827
    /**
1828
     * Subscribe user(s) to a specified group in current course (as a student).
1829
     *
1830
     * @param mixed  $userList  Can be an array with user-id's or a single user-id
1831
     * @param CGroup $group
1832
     * @param int    $course_id
1833
     *
1834
     * @return bool
1835
     */
1836
    public static function subscribeUsers($userList, CGroup $group = null, $course_id = null)
1837
    {
1838
        if (empty($group)) {
1839
            return false;
1840
        }
1841
        $userList = is_array($userList) ? $userList : [$userList];
1842
        $course_id = empty($course_id) ? api_get_course_int_id() : (int) $course_id;
1843
        $group_id = $group->getIid();
1844
1845
        if (!empty($userList)) {
1846
            $table = Database::get_course_table(TABLE_GROUP_USER);
1847
            foreach ($userList as $user_id) {
1848
                if (self::canUserSubscribe($user_id, $group)) {
1849
                    $user_id = (int) $user_id;
1850
                    $sql = "INSERT INTO $table (c_id, user_id, group_id, status, role)
1851
                            VALUES ('$course_id', '".$user_id."', '".$group_id."', 0, '')";
1852
                    Database::query($sql);
1853
                }
1854
            }
1855
        }
1856
1857
        return true;
1858
    }
1859
1860
    /**
1861
     * Subscribe tutor(s) to a specified group in current course.
1862
     *
1863
     * @param mixed $userList  Can be an array with user-id's or a single user-id
1864
     * @param CGroup $group
1865
     * @param int   $course_id
1866
     */
1867
    public static function subscribeTutors($userList, CGroup $group = null, $course_id = 0)
1868
    {
1869
        if (empty($group)) {
1870
            return false;
1871
        }
1872
        $userList = is_array($userList) ? $userList : [$userList];
1873
        $result = true;
1874
        $course_id = !empty($course_id) ? intval($course_id) : api_get_course_int_id();
1875
        $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1876
        $groupId = (int) $group->getIid();
1877
1878
        foreach ($userList as $user_id) {
1879
            $user_id = intval($user_id);
1880
            if (self::canUserSubscribe($user_id, $group, false)) {
1881
                $sql = 'INSERT INTO '.$table_group_tutor." (c_id, user_id, group_id)
1882
                        VALUES ('$course_id', '".$user_id."', '".$groupId."')";
1883
                $result = Database::query($sql);
1884
            }
1885
        }
1886
1887
        return $result;
1888
    }
1889
1890
    /**
1891
     * Unsubscribe user(s) from a specified group in current course.
1892
     *
1893
     * @param mixed $userList Can be an array with user-id's or a single user-id
1894
     *
1895
     * @return bool
1896
     */
1897
    public static function unsubscribeUsers($userList, CGroup $group = null)
1898
    {
1899
        if (empty($group)) {
1900
            return false;
1901
        }
1902
        $userList = is_array($userList) ? $userList : [$userList];
1903
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1904
        $group_id = $group->getIid();
1905
        $course_id = api_get_course_int_id();
1906
        $sql = 'DELETE FROM '.$table_group_user.'
1907
                WHERE
1908
                    group_id = '.$group_id.' AND
1909
                    user_id IN ('.implode(',', $userList).')
1910
                ';
1911
        Database::query($sql);
1912
    }
1913
1914
    /**
1915
     * Unsubscribe all users from one or more groups.
1916
     *
1917
     * @param int $groupId
1918
     *
1919
     * @return bool
1920
     */
1921
    public static function unsubscribeAllUsers($groupId)
1922
    {
1923
        $groupId = (int) $groupId;
1924
        if (empty($groupId)) {
1925
            return false;
1926
        }
1927
1928
        $table = Database::get_course_table(TABLE_GROUP_USER);
1929
        $sql = "DELETE FROM $table
1930
                WHERE
1931
                    group_id = $groupId ";
1932
1933
        return Database::query($sql);
1934
    }
1935
1936
    /**
1937
     * Unsubscribe all tutors from one or more groups.
1938
     *
1939
     * @param int $groupId iid
1940
     *
1941
     * @see unsubscribe_all_users. This function is almost an exact copy of that function.
1942
     *
1943
     * @return bool TRUE if successful
1944
     *
1945
     * @author Patrick Cool <[email protected]>, Ghent University
1946
     */
1947
    public static function unsubscribe_all_tutors($groupId)
1948
    {
1949
        $courseId = api_get_course_int_id();
1950
        $groupId = (int) $groupId;
1951
1952
        if (empty($courseId) || empty($groupId)) {
1953
            return false;
1954
        }
1955
1956
        if (!empty($groupId)) {
1957
            $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1958
            $sql = "DELETE FROM $table_group_tutor
1959
                    WHERE group_id = $groupId ";
1960
            Database::query($sql);
1961
        }
1962
1963
        return true;
1964
    }
1965
1966
    /**
1967
     * Is the user a tutor of this group?
1968
     *
1969
     * @todo replace this function with $group->isUserTutor
1970
     */
1971
    public static function isTutorOfGroup($userId, CGroup $group = null)
1972
    {
1973
        if (empty($group)) {
1974
            return false;
1975
        }
1976
1977
        $userId = (int) $userId;
1978
        $group_id = (int) $group->getIid();
1979
1980
        $table = Database::get_course_table(TABLE_GROUP_TUTOR);
1981
1982
        $sql = "SELECT * FROM $table
1983
                WHERE
1984
                    user_id = $userId AND
1985
                    group_id = $group_id";
1986
        $result = Database::query($sql);
1987
1988
        return Database::num_rows($result) > 0;
1989
    }
1990
1991
    /**
1992
     * Is the user part of this group? This can be a tutor or a normal member
1993
     * you should use this function if the access to a tool or functionality is
1994
     * restricted to the people who are actually in the group
1995
     * before you had to check if the user was
1996
     * 1. a member of the group OR
1997
     * 2. a tutor of the group. This function combines both.
1998
     */
1999
    public static function isUserInGroup($user_id, CGroup $group)
2000
    {
2001
        $member = self::is_subscribed($user_id, $group);
2002
        if ($member) {
2003
            return true;
2004
        }
2005
2006
        $tutor = self::isTutorOfGroup($user_id, $group);
2007
        if ($tutor) {
2008
            return true;
2009
        }
2010
2011
        return false;
2012
    }
2013
2014
    /**
2015
     * Get all group's from a given course in which a given user is unsubscribed.
2016
     *
2017
     * @author  Patrick Cool
2018
     *
2019
     * @param int $course_id retrieve the groups for
2020
     * @param int $user_id   the ID of the user you want to know all its group memberships
2021
     *
2022
     * @return array
2023
     */
2024
    public static function get_group_ids($course_id, $user_id)
2025
    {
2026
        $groups = [];
2027
        $tbl_group = Database::get_course_table(TABLE_GROUP_USER);
2028
        $tbl_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
2029
        $user_id = intval($user_id);
2030
        $course_id = intval($course_id);
2031
2032
        $sql = "SELECT group_id FROM $tbl_group
2033
                WHERE user_id = '$user_id'";
2034
        $result = Database::query($sql);
2035
2036
        if ($result) {
2037
            while ($row = Database::fetch_array($result)) {
2038
                $groups[] = $row['group_id'];
2039
            }
2040
        }
2041
2042
        //Also loading if i'm the tutor
2043
        $sql = "SELECT group_id FROM $tbl_group_tutor
2044
                WHERE user_id = '$user_id'";
2045
        $result = Database::query($sql);
2046
        if ($result) {
2047
            while ($row = Database::fetch_array($result)) {
2048
                $groups[] = $row['group_id'];
2049
            }
2050
        }
2051
        if (!empty($groups)) {
2052
            array_filter($groups);
2053
        }
2054
2055
        return $groups;
2056
    }
2057
2058
    /**
2059
     * Check if a user has access to a certain group tool.
2060
     *
2061
     * @param int    $user_id The user id
2062
     * @param CGroup $group
2063
     * @param string $tool    The tool to check the access rights. This should be
2064
     *                        one of constants: GROUP_TOOL_DOCUMENTS
2065
     *
2066
     * @return bool true if the given user has access to the given tool in the
2067
     *              given course
2068
     */
2069
    public static function userHasAccess($user_id, CGroup $group = null, $tool)
2070
    {
2071
        if (null === $group) {
2072
            return false;
2073
        }
2074
2075
        // Admin have access everywhere
2076
        if (api_is_platform_admin()) {
2077
            return true;
2078
        }
2079
2080
        // Course admin also have access to everything
2081
        if (api_is_allowed_to_edit(false, true, true)) {
2082
            return true;
2083
        }
2084
2085
        if (0 == $group->getStatus()) {
2086
            return false;
2087
        }
2088
2089
        switch ($tool) {
2090
            case self::GROUP_TOOL_FORUM:
2091
                $toolStatus = $group->getForumState();
2092
                break;
2093
            case self::GROUP_TOOL_DOCUMENTS:
2094
                $toolStatus = $group->getDocState();
2095
                break;
2096
            case self::GROUP_TOOL_CALENDAR:
2097
                $toolStatus = $group->getCalendarState();
2098
                break;
2099
            case self::GROUP_TOOL_ANNOUNCEMENT:
2100
                $toolStatus = $group->getAnnouncementsState();
2101
                break;
2102
            case self::GROUP_TOOL_WORK:
2103
                $toolStatus = $group->getWorkState();
2104
                break;
2105
            case self::GROUP_TOOL_WIKI:
2106
                $toolStatus = $group->getWikiState();
2107
                break;
2108
            case self::GROUP_TOOL_CHAT:
2109
                $toolStatus = $group->getChatState();
2110
                break;
2111
            default:
2112
                return false;
2113
        }
2114
2115
        switch ($toolStatus) {
2116
            case self::TOOL_NOT_AVAILABLE:
2117
                return false;
2118
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
2119
            case self::TOOL_PUBLIC:
2120
                return true;
2121
                break;
2122
            case self::TOOL_PRIVATE:
2123
                $userIsInGroup = self::isUserInGroup($user_id, $group);
2124
                if ($userIsInGroup) {
2125
                    return true;
2126
                }
2127
                break;
2128
            case self::TOOL_PRIVATE_BETWEEN_USERS:
2129
                // Only works for announcements for now
2130
                $userIsInGroup = self::isUserInGroup($user_id, $group);
2131
                if ($userIsInGroup && self::GROUP_TOOL_ANNOUNCEMENT == $tool) {
2132
                    return true;
2133
                }
2134
                break;
2135
        }
2136
2137
        return false;
2138
    }
2139
2140
    /**
2141
     * @param int $userId
2142
     * @param int $sessionId
2143
     *
2144
     * @return bool
2145
     */
2146
    public static function userHasAccessToBrowse($userId, CGroup $group = null, $sessionId = 0)
2147
    {
2148
        if (null === $group) {
2149
            return false;
2150
        }
2151
2152
        if (api_is_platform_admin()) {
2153
            return true;
2154
        }
2155
2156
        if (api_is_allowed_to_edit(false, true, true)) {
2157
            return true;
2158
        }
2159
2160
        if (!empty($sessionId)) {
2161
            if (api_is_coach($sessionId, api_get_course_int_id())) {
2162
                return true;
2163
            }
2164
2165
            if (api_is_drh()) {
2166
                if (SessionManager::isUserSubscribedAsHRM($sessionId, $userId)) {
2167
                    return true;
2168
                }
2169
            }
2170
        }
2171
2172
        if (self::isTutorOfGroup($userId, $group)) {
2173
            return true;
2174
        }
2175
2176
        if (0 == $group->getStatus()) {
2177
            return false;
2178
        }
2179
2180
        if (self::userHasAccess($userId, $group, self::GROUP_TOOL_FORUM) ||
2181
            self::userHasAccess($userId, $group, self::GROUP_TOOL_DOCUMENTS) ||
2182
            self::userHasAccess($userId, $group, self::GROUP_TOOL_CALENDAR) ||
2183
            self::userHasAccess($userId, $group, self::GROUP_TOOL_ANNOUNCEMENT) ||
2184
            self::userHasAccess($userId, $group, self::GROUP_TOOL_WORK) ||
2185
            self::userHasAccess($userId, $group, self::GROUP_TOOL_WIKI) ||
2186
            self::userHasAccess($userId, $group, self::GROUP_TOOL_CHAT)
2187
        ) {
2188
            return true;
2189
        }
2190
        //@todo check group session id
2191
        $groupSessionId = null;
2192
2193
        if (api_is_session_general_coach() && $groupSessionId == $sessionId) {
2194
            return true;
2195
        }
2196
2197
        return false;
2198
    }
2199
2200
    /**
2201
     * Get all groups where a specific user is subscribed.
2202
     *
2203
     * @param int $user_id
2204
     *
2205
     * @return array
2206
     */
2207
    public static function get_user_group_name($user_id)
2208
    {
2209
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
2210
        $table_group = Database::get_course_table(TABLE_GROUP);
2211
        $user_id = intval($user_id);
2212
        $course_id = api_get_course_int_id();
2213
        $sql = "SELECT title
2214
                FROM $table_group g
2215
                INNER JOIN $table_group_user gu
2216
                ON (gu.group_id = g.iid)
2217
                WHERE
2218
                  gu.user_id = $user_id";
2219
        $res = Database::query($sql);
2220
        $groups = [];
2221
        while ($group = Database::fetch_array($res)) {
2222
            $groups[] .= $group['title'];
2223
        }
2224
2225
        return $groups;
2226
    }
2227
2228
    /**
2229
     * Get all groups where a specific user is subscribed.
2230
     *
2231
     * @param int      $user_id
2232
     * @param int      $courseId
2233
     * @param int|null $sessionId
2234
     *
2235
     * @return array
2236
     */
2237
    public static function getAllGroupPerUserSubscription($user_id, $courseId = 0, $sessionId = null)
2238
    {
2239
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
2240
        $table_tutor_user = Database::get_course_table(TABLE_GROUP_TUTOR);
2241
        $table_group = Database::get_course_table(TABLE_GROUP);
2242
        $user_id = (int) $user_id;
2243
        $courseId = empty($courseId) ? api_get_course_int_id() : (int) $courseId;
2244
2245
        $sql = "SELECT DISTINCT g.*
2246
               FROM $table_group g
2247
               LEFT JOIN $table_group_user gu
2248
               ON (gu.group_id = g.iid)
2249
               LEFT JOIN $table_tutor_user tu
2250
               ON (tu.group_id = g.iid)
2251
               WHERE
2252
                  (gu.user_id = $user_id OR tu.user_id = $user_id) ";
2253
2254
        /*if (null !== $sessionId) {
2255
            $sessionId = (int) $sessionId;
2256
            $sql .= " AND g.session_id = $sessionId ";
2257
        }*/
2258
2259
        $res = Database::query($sql);
2260
        $groups = [];
2261
        while ($group = Database::fetch_assoc($res)) {
2262
            $groups[] = $group;
2263
        }
2264
2265
        return $groups;
2266
    }
2267
2268
    /**
2269
     * @param CGroup[] $groupList
2270
     * @param int      $category_id
2271
     *
2272
     * @return string
2273
     */
2274
    public static function processGroups($groupList, $category_id = 0)
2275
    {
2276
        $charset = 'UTF-8';
2277
        $category_id = (int) $category_id;
2278
        $totalRegistered = 0;
2279
        $group_data = [];
2280
        $user_info = api_get_user_info();
2281
        $session_id = api_get_session_id();
2282
        $user_id = $user_info['user_id'];
2283
        $hideGroup = api_get_setting('hide_course_group_if_no_tools_available');
2284
        $extraField = new ExtraField('survey');
2285
        $surveyGroupExists = $extraField->get_handler_field_info_by_field_variable('group_id') ? true : false;
2286
        $url = api_get_path(WEB_CODE_PATH).'group/';
2287
2288
        $confirmMessage = addslashes(
2289
            api_htmlentities(get_lang('Please confirm your choice'), ENT_QUOTES)
2290
        );
2291
2292
        foreach ($groupList as $group) {
2293
            $groupId = $group->getIid();
2294
2295
            // Validation when belongs to a session
2296
            $session_img = '';
2297
            //$session_img = api_get_session_image($group['session_id'], $user_info['status']);
2298
2299
            // All the tutors of this group
2300
            $tutors = $group->getTutors();
2301
            $isMember = self::is_subscribed($user_id, $group);
2302
2303
            // Create a new table-row
2304
            $row = [];
2305
            // Checkbox
2306
            if (api_is_allowed_to_edit(false, true) && count($groupList) > 1) {
2307
                $row[] = $groupId;
2308
            }
2309
2310
            if (self::userHasAccessToBrowse($user_id, $group, $session_id)) {
2311
                // Group name
2312
                $groupNameClass = null;
2313
                if (0 == $group->getStatus()) {
2314
                    $groupNameClass = 'muted';
2315
                }
2316
2317
                $group_name = '<a
2318
                    class="'.$groupNameClass.'"
2319
                    href="group_space.php?'.api_get_cidreq(true, false).'&gid='.$groupId.'">'.
2320
                    Security::remove_XSS($group->getTitle()).'</a> ';
2321
2322
                $group_name2 = '';
2323
                if (api_get_configuration_value('extra')) {
2324
                    $group_name2 = '<a
2325
                        href="group_space_tracking.php?'.api_get_cidreq(true, false).'&gid='.$groupId.'">'.
2326
                        get_lang('suivi_de').''.stripslashes($group->getTitle()).'</a>';
2327
                }
2328
2329
                /*
2330
                if (!empty($user_id) && !empty($this_group['id_tutor']) && $user_id == $this_group['id_tutor']) {
2331
                    $group_name .= Display::label(get_lang('my supervision'), 'success');
2332
                } elseif ($isMember) {
2333
                    $group_name .= Display::label(get_lang('my group'), 'success');
2334
                }*/
2335
2336
                /*if (api_is_allowed_to_edit() && !empty($this_group['session_name'])) {
2337
                    $group_name .= ' ('.$this_group['session_name'].')';
2338
                }
2339
                $group_name .= $session_img;*/
2340
2341
                $row[] = $group_name.$group_name2.'<br />'.stripslashes(trim($group->getDescription()));
2342
            } else {
2343
                if ('true' === $hideGroup) {
2344
                    continue;
2345
                }
2346
                $row[] = $group->getTitle().'<br />'.stripslashes(trim($group->getDescription()));
2347
            }
2348
2349
            // Tutor name
2350
            $tutor_info = '';
2351
            if (count($tutors) > 0) {
2352
                foreach ($tutors as $tutorGroup) {
2353
                    $tutor = $tutorGroup->getUser();
2354
                    $username = api_htmlentities(
2355
                        sprintf(get_lang('Login: %s'), $tutor->getUsername()),
2356
                        ENT_QUOTES
2357
                    );
2358
                    if ('true' === api_get_setting('show_email_addresses')) {
2359
                        $tutor_info .= Display::tag(
2360
                            'span',
2361
                            Display::encrypted_mailto_link(
2362
                                $tutor->getEmail(),
2363
                                UserManager::formatUserFullName($tutor)
2364
                            ),
2365
                            ['title' => $username]
2366
                        ).', ';
2367
                    } else {
2368
                        if (api_is_allowed_to_edit()) {
2369
                            $tutor_info .= Display::tag(
2370
                            'span',
2371
                                Display::encrypted_mailto_link(
2372
                                    $tutor->getEmail(),
2373
                                    UserManager::formatUserFullName($tutor)
2374
                                ),
2375
                                ['title' => $username]
2376
                            ).', ';
2377
                        } else {
2378
                            $tutor_info .= Display::tag(
2379
                                'span',
2380
                                    UserManager::formatUserFullName($tutor),
2381
                                ['title' => $username]
2382
                            ).', ';
2383
                        }
2384
                    }
2385
                }
2386
            }
2387
2388
            $tutor_info = api_substr(
2389
                $tutor_info,
2390
                0,
2391
                api_strlen($tutor_info) - 2
2392
            );
2393
            $row[] = $tutor_info;
2394
2395
            // Max number of members in group
2396
            $max_members = self::MEMBER_PER_GROUP_NO_LIMIT === $group->getMaxStudent() ? ' ' : ' / '.$group->getMaxStudent();
2397
            $registeredUsers = self::getStudentsCount($groupId);
2398
            // Number of members in group
2399
            $row[] = $registeredUsers.$max_members;
2400
2401
            // Self-registration / unregistration
2402
            if (!api_is_allowed_to_edit(false, true)) {
2403
                if (self::is_self_registration_allowed($user_id, $group)) {
2404
                    $row[] = '<a
2405
                        class = "btn btn--plain"
2406
                        href="group.php?'.api_get_cidreq().'&category='.$category_id.'&action=self_reg&group_id='.$groupId.'"
2407
                        onclick="javascript:if(!confirm('."'".$confirmMessage."'".')) return false;">'.get_lang('register').'</a>';
2408
                } elseif (self::is_self_unregistration_allowed($user_id, $group)) {
2409
                    $row[] = '<a
2410
                        class = "btn btn--plain"
2411
                        href="group.php?'.api_get_cidreq().'&category='.$category_id.'&action=self_unreg&group_id='.$groupId.'"
2412
                        onclick="javascript:if(!confirm('."'".$confirmMessage."'".')) return false;">'.get_lang('unregister').'</a>';
2413
                } else {
2414
                    $row[] = '-';
2415
                }
2416
            }
2417
2418
            // linked class
2419
            if (api_get_setting('allow_group_categories') === 'true') {
2420
                $usergroup = GroupManager::get_usergroup_link($group);
2421
                isset($usergroup) ? $row[] = $usergroup->getTitle() : $row[] = '-';
2422
            }
2423
2424
            // @todo fix group session access.
2425
            $groupSessionId = null;
2426
2427
            // Edit-links
2428
            if (api_is_allowed_to_edit(false, true) &&
2429
                !(api_is_session_general_coach() && $groupSessionId != $session_id)
2430
            ) {
2431
                $edit_actions = '<a
2432
                    href="'.$url.'settings.php?'.api_get_cidreq(true, false).'&gid='.$groupId.'"
2433
                    title="'.get_lang('Edit').'">'.
2434
                    Display::getMdiIcon(ActionIcon::EDIT, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Edit this group')).
2435
                    '</a>&nbsp;';
2436
2437
                if (1 == $group->getStatus()) {
2438
                    $edit_actions .= '<a
2439
                        href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=set_invisible&group_id='.$groupId.'"
2440
                        title="'.get_lang('Hide').'">'.
2441
                        Display::getMdiIcon('eye', 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Hide')).'</a>&nbsp;';
2442
                } else {
2443
                    $edit_actions .= '<a
2444
                        href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=set_visible&group_id='.$groupId.'"
2445
                        title="'.get_lang('Show').'">'.
2446
                        Display::getMdiIcon('eye-closed', 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Show')).'</a>&nbsp;';
2447
                }
2448
2449
                $edit_actions .= '<a
2450
                    href="'.$url.'member_settings.php?'.api_get_cidreq(true, false).'&gid='.$groupId.'"
2451
                    title="'.get_lang('Group members').'">'.
2452
                    Display::getMdiIcon(ToolIcon::MEMBER, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Group members')).'</a>&nbsp;';
2453
2454
                $edit_actions .= '<a
2455
                    href="'.$url.'group_overview.php?action=export&type=xls&'.api_get_cidreq(true, false).'&id='.$groupId.'"
2456
                    title="'.get_lang('Export users list').'">'.
2457
                    Display::getMdiIcon(ActionIcon::EXPORT_SPREADSHEET, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Export')).'</a>&nbsp;';
2458
2459
                if ($surveyGroupExists) {
2460
                    $edit_actions .= Display::url(
2461
                        Display::getMdiIcon(ToolIcon::SURVEY, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('ExportSurveyResults')),
2462
                        $url.'group_overview.php?action=export_surveys&'.api_get_cidreq(true, false).'&id='.$groupId
2463
                    ).'&nbsp;';
2464
                }
2465
                $edit_actions .= '<a
2466
                    href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=fill_one&group_id='.$groupId.'"
2467
                    onclick="javascript: if(!confirm('."'".$confirmMessage."'".')) return false;" title="'.get_lang('FillGroup').'">'.
2468
                    Display::getMdiIcon(ActionIcon::FILL, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('FillGroup')).'</a>&nbsp;';
2469
2470
                $edit_actions .= '<a
2471
                    href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=delete_one&group_id='.$groupId.'"
2472
                    onclick="javascript: if(!confirm('."'".$confirmMessage."'".')) return false;" title="'.get_lang('Delete').'">'.
2473
                    Display::getMdiIcon(ActionIcon::DELETE, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Delete')).'</a>&nbsp;';
2474
2475
                $row[] = $edit_actions;
2476
            }
2477
2478
            /*if (!empty($this_group['nbMember'])) {
2479
                $totalRegistered = $totalRegistered + $this_group['nbMember'];
2480
            }*/
2481
            $group_data[] = $row;
2482
        }
2483
2484
        // If no groups then don't show the table (only for students)
2485
        if (!api_is_allowed_to_edit(true, false)) {
2486
            if (empty($group_data)) {
2487
                return '';
2488
            }
2489
        }
2490
2491
        $table = new SortableTableFromArrayConfig(
2492
            $group_data,
2493
            1,
2494
            20,
2495
            'group_category_'.$category_id
2496
        );
2497
        $table->set_additional_parameters(['category' => $category_id]);
2498
        $column = 0;
2499
        if (api_is_allowed_to_edit(false, true) && count($groupList) > 1) {
2500
            $table->set_header($column++, '', false);
2501
        }
2502
        $table->set_header($column++, get_lang('Groups'));
2503
        $table->set_header($column++, get_lang('Group tutor'));
2504
        $table->set_header($column++, get_lang('Registered'), false);
2505
        if (api_get_setting('allow_group_categories') === 'true') {
2506
            $table->set_header($column++, get_lang('Classe liée'), false);
2507
        }
2508
2509
        if (!api_is_allowed_to_edit(false, true)) {
2510
            // If self-registration allowed
2511
            $table->set_header($column++, get_lang('Registration'), false);
2512
        }
2513
2514
        if (api_is_allowed_to_edit(false, true)) {
2515
            // Only for course administrator
2516
            $table->set_header($column++, get_lang('Edit'), false);
2517
            $form_actions = [];
2518
            $form_actions['fill_selected'] = get_lang('Fill the group randomly with course students');
2519
            $form_actions['empty_selected'] = get_lang('unsubscribe all users');
2520
            $form_actions['delete_selected'] = get_lang('Delete');
2521
            if (count($groupList) > 1) {
2522
                $table->set_form_actions($form_actions, 'group');
2523
            }
2524
        }
2525
2526
        return $table->return_table();
2527
    }
2528
2529
    /**
2530
     * @param array $groupData
2531
     * @param bool  $deleteNotInArray
2532
     *
2533
     * @return array
2534
     */
2535
    public static function importCategoriesAndGroupsFromArray($groupData, $deleteNotInArray = false)
2536
    {
2537
        $result = [];
2538
        $elementsFound = [
2539
            'categories' => [],
2540
            'groups' => [],
2541
        ];
2542
2543
        $courseCode = api_get_course_id();
2544
        $sessionId = api_get_session_id();
2545
        $groupCategories = self::get_categories();
2546
2547
        if (empty($groupCategories)) {
2548
            $result['error'][] = get_lang('Create a category');
2549
2550
            return $result;
2551
        }
2552
2553
        foreach ($groupData as $data) {
2554
            $isCategory = empty($data['group']) ? true : false;
2555
            if ($isCategory) {
2556
                $categoryInfo = self::getCategoryByTitle($data['category']);
2557
                $categoryId = $categoryInfo['iid'];
2558
2559
                if (!empty($categoryInfo)) {
2560
                    // Update
2561
                    self::update_category(
2562
                        $categoryId,
2563
                        $data['category'],
2564
                        $data['description'],
2565
                        $data['doc_state'],
2566
                        $data['work_state'],
2567
                        $data['calendar_state'],
2568
                        $data['announcements_state'],
2569
                        $data['forum_state'],
2570
                        $data['wiki_state'],
2571
                        $data['chat_state'],
2572
                        $data['self_reg_allowed'],
2573
                        $data['self_unreg_allowed'],
2574
                        $data['max_student'],
2575
                        $data['groups_per_user'],
2576
                        $data['document_access']
2577
                    );
2578
                    $data['category_id'] = $categoryId;
2579
                    $result['updated']['category'][] = $data;
2580
                } else {
2581
                    // Add
2582
                    $categoryId = self::create_category(
2583
                        $data['category'],
2584
                        $data['description'],
2585
                        $data['doc_state'],
2586
                        $data['work_state'],
2587
                        $data['calendar_state'],
2588
                        $data['announcements_state'],
2589
                        $data['forum_state'],
2590
                        $data['wiki_state'],
2591
                        $data['chat_state'],
2592
                        $data['self_reg_allowed'],
2593
                        $data['self_unreg_allowed'],
2594
                        $data['max_student'],
2595
                        $data['groups_per_user']
2596
                    );
2597
2598
                    if ($categoryId) {
2599
                        $data['category_id'] = $categoryId;
2600
                        $result['added']['category'][] = $data;
2601
                    }
2602
                }
2603
                $elementsFound['categories'][] = $categoryId;
2604
            } else {
2605
                $groupInfo = self::getGroupByName($data['group']);
2606
                $categoryInfo = [];
2607
                if (isset($data['category'])) {
2608
                    $categoryInfo = self::getCategoryByTitle($data['category']);
2609
                }
2610
                $categoryId = null;
2611
                if (!empty($categoryInfo)) {
2612
                    $categoryId = $categoryInfo['iid'];
2613
                } else {
2614
                    if (!empty($groupCategories) && isset($groupCategories[0])) {
2615
                        $defaultGroupCategory = $groupCategories[0];
2616
                        $categoryId = $defaultGroupCategory['iid'];
2617
                    }
2618
                }
2619
2620
                if (empty($groupInfo)) {
2621
                    // Add
2622
                    $groupId = self::create_group(
2623
                        $data['group'],
2624
                        $categoryId,
2625
                        null,
2626
                        $data['max_student']
2627
                    );
2628
2629
                    if ($groupId) {
2630
                        self::set_group_properties(
2631
                            $groupId,
2632
                            $data['group'],
2633
                            $data['description'],
2634
                            $data['max_student'],
2635
                            $data['doc_state'],
2636
                            $data['work_state'],
2637
                            $data['calendar_state'],
2638
                            $data['announcements_state'],
2639
                            $data['forum_state'],
2640
                            $data['wiki_state'],
2641
                            $data['chat_state'],
2642
                            $data['self_reg_allowed'],
2643
                            $data['self_unreg_allowed'],
2644
                            $categoryId
2645
                        );
2646
                        $data['group_id'] = $groupId;
2647
                        $result['added']['group'][] = $data;
2648
                    }
2649
                    $groupInfo = self::get_group_properties($groupId, true);
2650
                } else {
2651
                    // Update
2652
                    $groupId = $groupInfo['iid'];
2653
                    self::set_group_properties(
2654
                        $groupId,
2655
                        $data['group'],
2656
                        $data['description'],
2657
                        $data['max_student'],
2658
                        $data['doc_state'],
2659
                        $data['work_state'],
2660
                        $data['calendar_state'],
2661
                        $data['announcements_state'],
2662
                        $data['forum_state'],
2663
                        $data['wiki_state'],
2664
                        $data['chat_state'],
2665
                        $data['self_reg_allowed'],
2666
                        $data['self_unreg_allowed'],
2667
                        $categoryId
2668
                    );
2669
2670
                    $data['group_id'] = $groupId;
2671
                    $result['updated']['group'][] = $data;
2672
                    $groupInfo = self::get_group_properties($groupId);
2673
                }
2674
2675
                $students = isset($data['students']) ? explode(',', $data['students']) : [];
2676
                if (!empty($students)) {
2677
                    $studentUserIdList = [];
2678
                    foreach ($students as $student) {
2679
                        $userInfo = api_get_user_info_from_username($student);
2680
2681
                        if (!$userInfo) {
2682
                            continue;
2683
                        }
2684
2685
                        if (!CourseManager::is_user_subscribed_in_course(
2686
                                $userInfo['user_id'],
2687
                                $courseCode,
2688
                                !empty($sessionId),
2689
                                $sessionId
2690
                            )
2691
                        ) {
2692
                            Display::addFlash(
2693
                                Display::return_message(
2694
                                    sprintf(
2695
                                        get_lang('Student %s is no subscribed to this course'),
2696
                                        $userInfo['complete_name']
2697
                                    ),
2698
                                    'warning'
2699
                                )
2700
                            );
2701
                            continue;
2702
                        }
2703
2704
                        $studentUserIdList[] = $userInfo['user_id'];
2705
                    }
2706
                    self::subscribeUsers($studentUserIdList, api_get_group_entity($groupInfo['iid']));
2707
                }
2708
2709
                $tutors = isset($data['tutors']) ? explode(',', $data['tutors']) : [];
2710
                if (!empty($tutors)) {
2711
                    $tutorIdList = [];
2712
                    foreach ($tutors as $tutor) {
2713
                        $userInfo = api_get_user_info_from_username($tutor);
2714
2715
                        if (!$userInfo) {
2716
                            continue;
2717
                        }
2718
2719
                        if (!CourseManager::is_user_subscribed_in_course(
2720
                                $userInfo['user_id'],
2721
                                $courseCode,
2722
                                !empty($sessionId),
2723
                                $sessionId
2724
                            )
2725
                        ) {
2726
                            Display::addFlash(
2727
                                Display::return_message(
2728
                                    sprintf(get_lang('Tutor %s is no subscribed to this course'), $userInfo['complete_name']),
2729
                                    'warning'
2730
                                )
2731
                            );
2732
2733
                            continue;
2734
                        }
2735
2736
                        $tutorIdList[] = $userInfo['user_id'];
2737
                    }
2738
                    self::subscribeTutors($tutorIdList, api_get_group_entity($groupInfo['iid']));
2739
                }
2740
2741
                $elementsFound['groups'][] = $groupId;
2742
            }
2743
        }
2744
2745
        if ($deleteNotInArray) {
2746
            // Check categories
2747
            $categories = self::get_categories();
2748
            foreach ($categories as $category) {
2749
                if (!in_array($category['iid'], $elementsFound['categories'])) {
2750
                    self::delete_category($category['iid']);
2751
                    $category['category'] = $category['title'];
2752
                    $result['deleted']['category'][] = $category;
2753
                }
2754
            }
2755
2756
            $groups = self::get_groups();
2757
            foreach ($groups as $group) {
2758
                if (!in_array($group->getIid(), $elementsFound['groups'])) {
2759
                    self::deleteGroup($group);
2760
                    $result['deleted']['group'][] = $group;
2761
                }
2762
            }
2763
        }
2764
2765
        return $result;
2766
    }
2767
2768
    /**
2769
     * Export all categories/group from a course to an array.
2770
     * This function works only in a context of a course.
2771
     *
2772
     * @param int  $groupId
2773
     * @param bool $loadUsers
2774
     *
2775
     * @return array
2776
     */
2777
    public static function exportCategoriesAndGroupsToArray($groupId = null, $loadUsers = false)
2778
    {
2779
        $data = [];
2780
        $data[] = [
2781
            'category',
2782
            'group',
2783
            'description',
2784
            'announcements_state',
2785
            'calendar_state',
2786
            'chat_state',
2787
            'doc_state',
2788
            'forum_state',
2789
            'work_state',
2790
            'wiki_state',
2791
            'max_student',
2792
            'self_reg_allowed',
2793
            'self_unreg_allowed',
2794
            'groups_per_user',
2795
        ];
2796
2797
        $count = 1;
2798
2799
        if ($loadUsers) {
2800
            $data[0][] = 'students';
2801
            $data[0][] = 'tutors';
2802
        }
2803
2804
        if (false == $loadUsers) {
2805
            $categories = self::get_categories();
2806
2807
            foreach ($categories as $categoryInfo) {
2808
                $data[$count] = [
2809
                    $categoryInfo['title'],
2810
                    null,
2811
                    $categoryInfo['description'],
2812
                    $categoryInfo['announcements_state'],
2813
                    $categoryInfo['calendar_state'],
2814
                    $categoryInfo['chat_state'],
2815
                    $categoryInfo['doc_state'],
2816
                    $categoryInfo['forum_state'],
2817
                    $categoryInfo['work_state'],
2818
                    $categoryInfo['wiki_state'],
2819
                    $categoryInfo['max_student'],
2820
                    $categoryInfo['self_reg_allowed'],
2821
                    $categoryInfo['self_unreg_allowed'],
2822
                    $categoryInfo['groups_per_user'],
2823
                ];
2824
                $count++;
2825
            }
2826
        }
2827
2828
        $groups = self::get_group_list();
2829
        foreach ($groups as $groupInfo) {
2830
            $groupId = $groupInfo['iid'];
2831
            $categoryTitle = null;
2832
            $categoryInfo = [];
2833
            if (isset($groupInfo['category'])) {
2834
                $categoryInfo = self::get_category($groupInfo['category']);
2835
            }
2836
2837
            $groupSettings = self::get_group_properties($groupId);
2838
            if (!empty($categoryInfo)) {
2839
                $categoryTitle = $categoryInfo['title'];
2840
            }
2841
2842
            $users = self::getStudents($groupId);
2843
            $userList = [];
2844
            foreach ($users as $user) {
2845
                $user = api_get_user_info($user['user_id']);
2846
                $userList[] = $user['username'];
2847
            }
2848
2849
            $tutors = self::getTutors($groupInfo);
2850
            $tutorList = [];
2851
            foreach ($tutors as $user) {
2852
                $user = api_get_user_info($user['user_id']);
2853
                $tutorList[] = $user['username'];
2854
            }
2855
2856
            $userListToString = null;
2857
            if (!empty($userList)) {
2858
                $userListToString = implode(',', $userList);
2859
            }
2860
2861
            $tutorListToString = null;
2862
            if (!empty($tutorList)) {
2863
                $tutorListToString = implode(',', $tutorList);
2864
            }
2865
2866
            $data[$count] = [
2867
                $categoryTitle,
2868
                $groupSettings['name'],
2869
                $groupSettings['description'],
2870
                $groupSettings['announcements_state'],
2871
                $groupSettings['calendar_state'],
2872
                $groupSettings['chat_state'],
2873
                $groupSettings['doc_state'],
2874
                $groupSettings['forum_state'],
2875
                $groupSettings['work_state'],
2876
                $groupSettings['wiki_state'],
2877
                $groupSettings['maximum_number_of_students'],
2878
                $groupSettings['self_registration_allowed'],
2879
                $groupSettings['self_unregistration_allowed'],
2880
                null,
2881
            ];
2882
2883
            if ($loadUsers) {
2884
                $data[$count][] = $userListToString;
2885
                $data[$count][] = $tutorListToString;
2886
            }
2887
2888
            if (!empty($groupId)) {
2889
                if ($groupId == $groupInfo['iid']) {
2890
                    break;
2891
                }
2892
            }
2893
            $count++;
2894
        }
2895
2896
        return $data;
2897
    }
2898
2899
    /**
2900
     * @param string $default
2901
     */
2902
    public static function getSettingBar($default)
2903
    {
2904
        $activeSettings = null;
2905
        $activeTutor = null;
2906
        $activeMember = null;
2907
2908
        switch ($default) {
2909
            case 'settings':
2910
                $activeSettings = 'active';
2911
                break;
2912
            case 'tutor':
2913
                $activeTutor = 'active';
2914
                break;
2915
            case 'member':
2916
                $activeMember = 'active';
2917
                break;
2918
        }
2919
2920
        $url = api_get_path(WEB_CODE_PATH).'group/%s?'.api_get_cidreq();
2921
        $items = [
2922
            '<a class="nav-link '.$activeSettings.'"
2923
                id="group_settings_tab" href="'.sprintf($url, 'settings.php').'">
2924
                '.Display::getMdiIcon(
2925
                    ToolIcon::SETTINGS,
2926
                    'ch-tool-icon',
2927
                    null,
2928
                    ICON_SIZE_SMALL,
2929
                    get_lang('Settings')
2930
                ).'</a>'.
2931
            '<a class="nav-link '.$activeMember.'"
2932
                id="group_members_tab" href="'.sprintf($url, 'member_settings.php').'">
2933
                '.Display::getMdiIcon(
2934
                ToolIcon::MEMBER,
2935
                'ch-tool-icon',
2936
                null,
2937
                ICON_SIZE_SMALL,
2938
                get_lang('Group members')
2939
            ).'</a>'.
2940
            '<a class="nav-link  '.$activeTutor.'"
2941
                id="group_tutors_tab" href="'.sprintf($url, 'tutor_settings.php').'">
2942
                '.Display::getMdiIcon(
2943
                'human-male-board',
2944
                'ch-tool-icon',
2945
                null,
2946
                ICON_SIZE_SMALL,
2947
                get_lang('Group tutors')
2948
            ).'</a>',
2949
        ];
2950
2951
        echo Display::toolbarAction('group', $items);
2952
    }
2953
2954
    public static function groupOverview($group, $url)
2955
    {
2956
        $groupId = $group['iid'];
2957
        $content = '<li>';
2958
        $content .= Display::tag(
2959
            'h3',
2960
            Display::url(
2961
                Security::remove_XSS($group['title']),
2962
                $url.'&gid='.$groupId
2963
            )
2964
        );
2965
        $users = self::getTutors($group);
2966
        if (!empty($users)) {
2967
            $content .= '<ul>';
2968
            $content .= "<li>".Display::tag('h4', get_lang('Tutors'))."</li><ul>";
2969
            foreach ($users as $user) {
2970
                $userInfo = api_get_user_info($user['user_id']);
2971
                $content .= '<li title="'.$userInfo['username'].'">'.
2972
                    $userInfo['complete_name_with_username'].
2973
                    '</li>';
2974
            }
2975
            $content .= '</ul>';
2976
            $content .= '</ul>';
2977
        }
2978
2979
        $users = self::getStudents($group['iid']);
2980
        if (!empty($users)) {
2981
            $content .= '<ul>';
2982
            $content .= "<li>".Display::tag('h4', get_lang('Students'))."</li><ul>";
2983
            foreach ($users as $user) {
2984
                $userInfo = api_get_user_info($user['user_id']);
2985
                $content .= '<li title="'.$userInfo['username'].'">'.
2986
                    $userInfo['complete_name_with_username'].
2987
                    '</li>';
2988
            }
2989
            $content .= '</ul>';
2990
            $content .= '</ul>';
2991
        }
2992
        $content .= '</li>';
2993
2994
        return $content;
2995
    }
2996
2997
    public static function getOverview(Course $course, string $keyword = ''): string
2998
    {
2999
        $content = '';
3000
        $categories = self::get_categories();
3001
        $url = api_get_path(WEB_CODE_PATH).'group/group_space.php?'.api_get_cidreq(true, false);
3002
        if (!empty($categories)) {
3003
            foreach ($categories as $category) {
3004
                if ('true' === api_get_setting('allow_group_categories')) {
3005
                    $content .= '<h2>'.$category['title'].'</h2>';
3006
                }
3007
                $groups = self::get_group_list($category['iid'], $course, null, 0, false, $keyword);
3008
                $content .= '<ul>';
3009
                if (!empty($groups)) {
3010
                    foreach ($groups as $group) {
3011
                        $content .= self::groupOverview($group, $url);
3012
                    }
3013
                }
3014
                $content .= '</ul>';
3015
            }
3016
        }
3017
3018
        // Check groups with no categories.
3019
        $groups = self::get_group_list(null, $course, null, api_get_session_id(), false, true);
3020
        if (!empty($groups)) {
3021
            $content .= '<h2>'.get_lang('NoCategorySelected').'</h2>';
3022
            $content .= '<ul>';
3023
            foreach ($groups as $group) {
3024
                if (!empty($group['category_id'])) {
3025
                    continue;
3026
                }
3027
                $content .= self::groupOverview($group, $url);
3028
            }
3029
            $content .= '</ul>';
3030
        }
3031
3032
        return $content;
3033
    }
3034
3035
    public static function getSearchForm(): string
3036
    {
3037
        $url = api_get_path(WEB_CODE_PATH).'group/group_overview.php?'.api_get_cidreq();
3038
        $form = new FormValidator(
3039
            'search_groups',
3040
            'get',
3041
            $url,
3042
            null,
3043
            ['class' => 'form-search'],
3044
            FormValidator::LAYOUT_INLINE
3045
        );
3046
        $form->addElement('text', 'keyword');
3047
        $form->addCourseHiddenParams();
3048
        $form->addButtonSearch();
3049
3050
        return $form->toHtml();
3051
    }
3052
3053
    public static function setStatus(CGroup $group, $status)
3054
    {
3055
        $group->setStatus($status);
3056
        $em = Database::getManager();
3057
        $em->persist($group);
3058
        $em->flush();
3059
    }
3060
3061
    public static function setVisible(CGroup $group)
3062
    {
3063
        self::setStatus($group, true);
3064
    }
3065
3066
    public static function setInvisible(CGroup $group)
3067
    {
3068
        self::setStatus($group, false);
3069
    }
3070
3071
    /**
3072
     * @param int   $userId
3073
     * @param int   $courseId
3074
     * @param array $documentInfoToBeCheck
3075
     * @param bool  $blockPage
3076
     *
3077
     * @return bool
3078
     */
3079
    public static function allowUploadEditDocument(
3080
        $userId,
3081
        $courseId,
3082
        CGroup $group,
3083
        $documentInfoToBeCheck = null,
3084
        $blockPage = false
3085
    ) {
3086
        // Admin and teachers can make any change no matter what
3087
        if (api_is_platform_admin() || api_is_allowed_to_edit(false, true)) {
3088
            return true;
3089
        }
3090
3091
        if (empty($group)) {
3092
            if ($blockPage) {
3093
                api_not_allowed(true);
3094
            }
3095
3096
            return false;
3097
        }
3098
3099
        // Tutor can also make any change
3100
        $isTutor = self::isTutorOfGroup($userId, $group);
3101
3102
        if ($isTutor) {
3103
            return true;
3104
        }
3105
3106
        // Just in case also check if document in group is available
3107
        if (0 == $group->getDocState()) {
3108
            if ($blockPage) {
3109
                api_not_allowed(true);
3110
            }
3111
3112
            return false;
3113
        }
3114
3115
        // Default behaviour
3116
        $documentAccess = self::DOCUMENT_MODE_SHARE;
3117
3118
        // Check category document access
3119
        /*$allowCategoryGroupDocumentAccess = api_get_configuration_value('group_category_document_access');
3120
        if ($allowCategoryGroupDocumentAccess) {
3121
            $category = GroupManager::get_category_from_group($groupInfo['iid']);
3122
            if (!empty($category) && isset($category['document_access'])) {
3123
                $documentAccess = (int) $category['document_access'];
3124
            }
3125
        }*/
3126
3127
        // Check group document access
3128
        $allow = ('true' === api_get_setting('document.group_document_access'));
3129
        if ($allow) {
3130
            $documentAccess = $group->getDocumentAccess();
3131
        }
3132
3133
        // Check access for students
3134
        $result = false;
3135
        switch ($documentAccess) {
3136
            case self::DOCUMENT_MODE_SHARE:
3137
                // Default chamilo behaviour
3138
                // Student can upload his own content, cannot modify another content.
3139
                $isMember = self::is_subscribed($userId, $group);
3140
                if ($isMember) {
3141
                    // No document to check, allow access to document feature.
3142
                    if (empty($documentInfoToBeCheck)) {
3143
                        $result = true;
3144
                    } else {
3145
                        // Member can only edit his own document
3146
                        $authorId = isset($documentInfoToBeCheck['insert_user_id']) ? $documentInfoToBeCheck['insert_user_id'] : 0;
3147
                        // If "insert_user_id" is not set, check the author id from c_item_property
3148
                        if (empty($authorId) && isset($documentInfoToBeCheck['id'])) {
3149
                            // @todo use resources
3150
                            /*$documentInfo = api_get_item_property_info(
3151
                                $courseId,
3152
                                'document',
3153
                                $documentInfoToBeCheck['id'],
3154
                                0
3155
                            );
3156
                            // Try to find this document in the session
3157
                            if (!empty($sessionId)) {
3158
                                $documentInfo = api_get_item_property_info(
3159
                                    $courseId,
3160
                                    'document',
3161
                                    $documentInfoToBeCheck['id'],
3162
                                    api_get_session_id()
3163
                                );
3164
                            }
3165
3166
                            if (!empty($documentInfo) && isset($documentInfo['insert_user_id'])) {
3167
                                $authorId = $documentInfo['insert_user_id'];
3168
                            }*/
3169
                        }
3170
3171
                        if ($authorId == $userId) {
3172
                            $result = true;
3173
                        }
3174
                    }
3175
                }
3176
                break;
3177
            case self::DOCUMENT_MODE_READ_ONLY:
3178
                // Student cannot upload content, cannot modify another content.
3179
                $result = false;
3180
                break;
3181
            case self::DOCUMENT_MODE_COLLABORATION:
3182
                // Student can upload content, can modify another content.
3183
                $isMember = self::is_subscribed($userId, $group);
3184
                if ($isMember) {
3185
                    $result = true;
3186
                }
3187
                break;
3188
        }
3189
3190
        if ($blockPage && false == $result) {
3191
            api_not_allowed(true);
3192
        }
3193
3194
        return $result;
3195
    }
3196
}
3197