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

GroupManager::create_usergroup_consistent_groups()   B

Complexity

Conditions 7
Paths 24

Size

Total Lines 83
Code Lines 47

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 7
eloc 47
nc 24
nop 2
dl 0
loc 83
rs 8.223
c 1
b 0
f 1

How to fix   Long Method   

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:

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