Passed
Push — master ( 4aec42...69e1de )
by Julito
17:30
created

GroupManager::subscribe_users()   A

Complexity

Conditions 6
Paths 8

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 6
eloc 12
nc 8
nop 3
dl 0
loc 19
rs 9.2222
c 1
b 1
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A GroupManager::unsubscribe_all_tutors() 0 17 4
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\Course;
6
use Chamilo\CoreBundle\Framework\Container;
7
use Chamilo\CourseBundle\Entity\CGroup;
8
use Chamilo\CourseBundle\Entity\CGroupCategory;
9
10
/**
11
 * This library contains some functions for group-management.
12
 *
13
 * @author Bart Mollet
14
 *
15
 * @todo Add $course_code parameter to all functions. So this GroupManager can
16
 * be used outside a session.
17
 */
18
class GroupManager
19
{
20
    /* DEFAULT_GROUP_CATEGORY:
21
    When group categories aren't available (platform-setting),
22
    all groups are created in this 'dummy'-category*/
23
    public const DEFAULT_GROUP_CATEGORY = 2;
24
25
    /**
26
     * infinite.
27
     */
28
    public const INFINITE = 99999;
29
    /**
30
     * No limit on the number of users in a group.
31
     */
32
    public const MEMBER_PER_GROUP_NO_LIMIT = 0;
33
    /**
34
     * No limit on the number of groups per user.
35
     */
36
    public const GROUP_PER_MEMBER_NO_LIMIT = 0;
37
    /**
38
     * The tools of a group can have 3 states
39
     * - not available
40
     * - public
41
     * - private.
42
     */
43
    public const TOOL_NOT_AVAILABLE = 0;
44
    public const TOOL_PUBLIC = 1;
45
    public const TOOL_PRIVATE = 2;
46
    public const TOOL_PRIVATE_BETWEEN_USERS = 3;
47
48
    /**
49
     * Constants for the available group tools.
50
     */
51
    public const GROUP_TOOL_FORUM = 0;
52
    public const GROUP_TOOL_DOCUMENTS = 1;
53
    public const GROUP_TOOL_CALENDAR = 2;
54
    public const GROUP_TOOL_ANNOUNCEMENT = 3;
55
    public const GROUP_TOOL_WORK = 4;
56
    public const GROUP_TOOL_WIKI = 5;
57
    public const GROUP_TOOL_CHAT = 6;
58
59
    public const DOCUMENT_MODE_SHARE = 0; // By default
60
    public const DOCUMENT_MODE_READ_ONLY = 1;
61
    public const DOCUMENT_MODE_COLLABORATION = 2;
62
63
    /**
64
     * GroupManager constructor.
65
     */
66
    public function __construct()
67
    {
68
    }
69
70
    /**
71
     * @param int $courseId
72
     *
73
     * @return CGroup[]
74
     */
75
    public static function get_groups($courseId = 0)
76
    {
77
        $repo = Container::getGroupRepository();
78
        $course = api_get_course_entity($courseId);
79
80
        $qb = $repo->getResourcesByCourse($course);
81
82
        return $qb->getQuery()->getResult();
83
84
        $table_group = Database::get_course_table(TABLE_GROUP);
0 ignored issues
show
Unused Code introduced by
$table_group = Database:...urse_table(TABLE_GROUP) is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
85
        $courseId = !empty($courseId) ? (int) $courseId : api_get_course_int_id();
86
87
        $sql = "SELECT * FROM $table_group WHERE c_id = $courseId  ";
88
        $result = Database::query($sql);
89
90
        return Database::store_result($result, 'ASSOC');
91
    }
92
93
    /**
94
     * Get list of groups for current course.
95
     *
96
     * @param int   $categoryId  The id of the category from which the groups are
97
     *                           requested
98
     * @param array $course_info Default is current course
99
     * @param int   $status      group status
100
     * @param int   $sessionId
101
     * @param bool  $getCount
102
     * @param bool  $notInGroup  Get groups not in a category
103
     *
104
     * @return array an array with all information about the groups
105
     */
106
    public static function get_group_list(
107
        $categoryId = null,
108
        $course_info = [],
109
        $status = null,
110
        $sessionId = 0,
111
        $getCount = false,
112
        $filterByKeyword = '',
113
        $returnEntityList = false
114
    ) {
115
        $course_info = empty($course_info) ? api_get_course_info() : $course_info;
116
117
        if (empty($course_info)) {
118
            return [];
119
        }
120
121
        $sessionId = empty($sessionId) ? api_get_session_id() : (int) $sessionId;
122
        $course_id = $course_info['real_id'];
123
124
        $repo = Container::getGroupRepository();
125
        $course = api_get_course_entity($course_id);
126
        $session = api_get_session_entity($sessionId);
127
        //$group = api_get_group_entity(api_get_group_id());
128
        $group = null;
129
        $qb = $repo->getResourcesByCourse($course, $session, $group);
130
131
        if (null === $categoryId) {
132
            $qb
133
                ->andWhere('resource.category is NULL');
134
        } else {
135
            $qb
136
                ->andWhere('resource.category = :category')
137
                ->setParameter('category', $categoryId);
138
        }
139
140
        if (!empty($filterByKeyword)) {
141
            $qb->andWhere($qb->expr()->like('resource.name', ':keyword'));
142
            $qb->setParameter('keyword', "%$filterByKeyword%");
143
        }
144
145
        if ($getCount) {
146
            $qb->select('count(resource)');
147
148
            return $qb->getQuery()->getSingleScalarResult();
149
        }
150
151
        if ($returnEntityList) {
152
            return $qb->getQuery()->getResult();
153
        }
154
155
        return $qb->getQuery()->getArrayResult();
156
157
        $table_group = Database::get_course_table(TABLE_GROUP);
0 ignored issues
show
Unused Code introduced by
$table_group = Database:...urse_table(TABLE_GROUP) is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
158
159
        $select = ' g.iid,
160
                    g.name,
161
                    g.description,
162
                    g.category_id,
163
                    g.max_student maximum_number_of_members,
164
                    g.secret_directory,
165
                    g.self_registration_allowed,
166
                    g.self_unregistration_allowed,
167
                    g.status
168
                    ';
169
        if ($getCount) {
170
            $select = ' DISTINCT count(g.iid) as count ';
171
        }
172
173
        $sql = "SELECT
174
                $select
175
                FROM $table_group g
176
                WHERE 1 = 1 ";
177
178
        if (!is_null($categoryId)) {
179
            $sql .= " AND g.category_id = '".intval($categoryId)."' ";
180
            $session_condition = api_get_session_condition($sessionId);
181
            if (!empty($session_condition)) {
182
                //$sql .= $session_condition;
183
            }
184
        } else {
185
            $session_condition = api_get_session_condition($sessionId, true);
186
        }
187
188
        $session_condition = '';
189
190
        if (!is_null($status)) {
191
            $sql .= " AND g.status = '".intval($status)."' ";
192
        }
193
194
        //$sql .= " AND g.c_id = $course_id ";
195
        if ($notInGroup) {
196
            $sql .= "  AND (g.category_id IS NULL OR g.category_id = 0) ";
197
        }
198
199
        if (!empty($session_condition)) {
200
            $sql .= $session_condition;
201
        }
202
        $sql .= ' ORDER BY UPPER(g.name)';
203
204
        $result = Database::query($sql);
205
206
        if ($getCount) {
207
            $row = Database::fetch_array($result);
208
209
            return $row['count'];
210
        }
211
212
        $groups = [];
213
        while ($thisGroup = Database::fetch_array($result)) {
214
            $thisGroup['number_of_members'] = count(self::get_subscribed_users($thisGroup));
215
            if (0 != $thisGroup['session_id']) {
216
                $sql = 'SELECT name FROM '.Database::get_main_table(TABLE_MAIN_SESSION).'
217
                        WHERE id='.$thisGroup['session_id'];
218
                $rs_session = Database::query($sql);
219
                if (Database::num_rows($rs_session) > 0) {
220
                    $thisGroup['session_name'] = Database::result($rs_session, 0, 0);
221
                }
222
            }
223
            $groups[] = $thisGroup;
224
        }
225
226
        return $groups;
227
    }
228
229
    /**
230
     * Create a group.
231
     *
232
     * @param string $name        The name for this group
233
     * @param int    $category_id
234
     * @param int    $tutor       The user-id of the group's tutor
235
     * @param int    $places      How many people can subscribe to the new group
236
     *
237
     * @return int
238
     */
239
    public static function create_group($name, $category_id, $tutor, $places)
240
    {
241
        $_course = api_get_course_info();
242
        $session_id = api_get_session_id();
243
        $course_id = $_course['real_id'];
244
        $category = self::get_category($category_id);
245
        $places = (int) $places;
246
247
        // Default values
248
        $docState = self::TOOL_PRIVATE;
249
        $calendarState = self::TOOL_PRIVATE;
250
        $workState = self::TOOL_PRIVATE;
251
        $anonuncementState = self::TOOL_PRIVATE;
252
        $forumState = self::TOOL_PRIVATE;
253
        $wikiState = self::TOOL_PRIVATE;
254
        $chatState = self::TOOL_PRIVATE;
255
        $selfRegAllowed = 0;
256
        $selfUnregAllwoed = 0;
257
        $documentAccess = 0;
258
259
        if ($category) {
260
            if (0 == $places) {
261
                //if the amount of users per group is not filled in, use the setting from the category
262
                $places = $category['max_student'];
263
            } else {
264
                if ($places > $category['max_student'] && 0 != $category['max_student']) {
265
                    $places = $category['max_student'];
266
                }
267
            }
268
            $docState = $category['doc_state'];
269
            $calendarState = $category['calendar_state'];
270
            $workState = $category['work_state'];
271
            $anonuncementState = $category['announcements_state'];
272
            $forumState = $category['forum_state'];
273
            $wikiState = $category['wiki_state'];
274
            $chatState = $category['chat_state'];
275
            $selfRegAllowed = $category['self_reg_allowed'];
276
            $selfUnregAllwoed = $category['self_unreg_allowed'];
277
            $documentAccess = isset($category['document_access']) ? $category['document_access'] : 0;
278
        }
279
280
        $course = api_get_course_entity($course_id);
281
        $session = api_get_session_entity($session_id);
282
283
        $category = null;
284
        if (!empty($category_id)) {
285
            $category = Container::getGroupCategoryRepository()->find($category_id);
286
        }
287
288
        $group = new CGroup();
289
        $group
290
            ->setName($name)
291
            ->setCategory($category)
292
            ->setMaxStudent($places)
293
            ->setDocState($docState)
294
            ->setCalendarState($calendarState)
295
            ->setWorkState($workState)
296
            ->setForumState($forumState)
297
            ->setWikiState($wikiState)
298
            ->setAnnouncementsState($anonuncementState)
299
            ->setChatState($chatState)
300
            ->setSelfRegistrationAllowed($selfRegAllowed)
301
            ->setSelfUnregistrationAllowed($selfUnregAllwoed)
302
            ->setDocumentAccess($documentAccess)
303
            ->setParent($course)
304
            ->addCourseLink($course, $session)
305
        ;
306
307
        $repo = Container::getGroupRepository();
308
        $repo->create($group);
309
        $lastId = $group->getIid();
310
311
        if ($lastId) {
312
            /*$desired_dir_name = '/'.api_replace_dangerous_char($name).'_groupdocs';
313
314
            $newFolderData = create_unexisting_directory(
315
                $_course,
316
                api_get_user_id(),
317
                $session_id,
318
                $lastId,
319
                null,
320
                null,
321
                    $desired_dir_name,
322
                $desired_dir_name,
323
                1
324
            );*/
325
326
            //$unique_name = $newFolderData->getPath();
327
328
            /* Stores the directory path into the group table */
329
            /*$sql = "UPDATE $table_group SET
330
                        name = '".Database::escape_string($name)."',
331
                        secret_directory = '".$unique_name."'
332
                    WHERE c_id = $course_id AND id ='".$lastId."'";
333
334
            Database::query($sql);*/
335
336
            // create a forum if needed
337
            if ($forumState >= 0) {
338
                require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
339
340
                $forumName = get_lang('Group forums');
341
                $repo = Container::getForumCategoryRepository();
342
                $criteria = ['cId' => $course_id, 'catTitle' => $forumName];
343
                $category = $repo->findOneBy($criteria);
344
345
                if (empty($category)) {
346
                    $categoryParam = [
347
                        'forum_category_title' => $forumName,
348
                    ];
349
                    $categoryId = store_forumcategory($categoryParam);
350
                } else {
351
                    $categoryId = $category->getIid();
352
                }
353
354
                $values = [];
355
                $values['forum_title'] = $name;
356
                $values['group_id'] = $lastId;
357
                $values['forum_category'] = $categoryId;
358
                $values['allow_anonymous_group']['allow_anonymous'] = 0;
359
                $values['students_can_edit_group']['students_can_edit'] = 0;
360
                $values['approval_direct_group']['approval_direct'] = 0;
361
                $values['allow_attachments_group']['allow_attachments'] = 1;
362
                $values['allow_new_threads_group']['allow_new_threads'] = 1;
363
                $values['default_view_type_group']['default_view_type'] = api_get_setting('default_forum_view');
364
                $values['group_forum'] = $lastId;
365
                if ('1' == $forumState) {
366
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'public';
367
                } elseif ('2' == $forumState) {
368
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'private';
369
                } elseif ('0' == $forumState) {
370
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'unavailable';
371
                }
372
                store_forum($values);
373
            }
374
        }
375
376
        return $lastId;
377
    }
378
379
    /**
380
     * Create subgroups.
381
     * This function creates new groups based on an existing group. It will
382
     * create the specified number of groups and fill those groups with users
383
     * from the base group.
384
     *
385
     * @param int $group_id         the group from which subgroups have to be created
386
     * @param int $number_of_groups The number of groups that have to be created
387
     */
388
    public static function create_subgroups($group_id, $number_of_groups)
389
    {
390
        $courseId = api_get_course_int_id();
391
        $table_group = Database::get_course_table(TABLE_GROUP);
392
        $category_id = self::create_category(
393
            get_lang('Subgroups'),
394
            '',
395
            self::TOOL_PRIVATE,
396
            self::TOOL_PRIVATE,
397
            0,
398
            0,
399
            1,
400
            1
401
        );
402
        $users = self::get_users($group_id);
403
        $group_ids = [];
404
405
        for ($group_nr = 1; $group_nr <= $number_of_groups; $group_nr++) {
406
            $group_ids[] = self::create_group(
407
                get_lang('Subgroup').' '.$group_nr,
408
                $category_id,
409
                0,
410
                0
411
            );
412
        }
413
414
        $members = [];
415
        foreach ($users as $index => $user_id) {
416
            $groupId = $group_ids[$index % $number_of_groups];
417
            self::subscribeUsers(
418
                $user_id,
419
                api_get_group_entity($groupId)
420
            );
421
            $members[$group_ids[$groupId]]++;
422
        }
423
424
        foreach ($members as $group_id => $places) {
425
            $sql = "UPDATE $table_group SET max_student = $places
426
                    WHERE c_id = $courseId  AND id = $group_id";
427
            Database::query($sql);
428
        }
429
    }
430
431
    /**
432
     * Create a group for every class subscribed to the current course.
433
     *
434
     * @param int $categoryId The category in which the groups should be created
435
     *
436
     * @return array
437
     */
438
    public static function create_class_groups($categoryId)
439
    {
440
        $options['where'] = [' usergroup.course_id = ? ' => api_get_course_int_id()];
441
        $obj = new UserGroup();
442
        $classes = $obj->getUserGroupInCourse($options);
443
        $group_ids = [];
444
445
        foreach ($classes as $class) {
446
            $userList = $obj->get_users_by_usergroup($class['id']);
447
            $groupId = self::create_group(
448
                $class['name'],
449
                $categoryId,
450
                0,
451
                null
452
            );
453
454
            if ($groupId) {
455
                self::subscribeUsers($userList, api_get_group_entity($groupId));
456
                $group_ids[] = $groupId;
457
            }
458
        }
459
460
        return $group_ids;
461
    }
462
463
    /**
464
     * Deletes groups and their data.
465
     *
466
     * @author Christophe Gesche <[email protected]>
467
     * @author Hugues Peeters <[email protected]>
468
     * @author Bart Mollet
469
     *
470
     * @param string $course_code Default is current course
471
     *
472
     * @return int - number of groups deleted
473
     */
474
    public static function deleteGroup(CGroup $group, $course_code = null)
475
    {
476
        if (empty($group)) {
477
            return false;
478
        }
479
        $course_info = api_get_course_info($course_code);
480
        if (empty($course_info)) {
481
            return false;
482
        }
483
484
        $em = Database::getManager();
485
        $groupIid = $group->getIid();
486
487
        // Unsubscribe all users
488
        self::unsubscribeAllUsers($groupIid);
489
        self::unsubscribe_all_tutors($groupIid);
490
491
        $em
492
            ->createQuery(
493
                'DELETE FROM ChamiloCourseBundle:CForumForum f WHERE f.forumOfGroup = :group'
494
            )
495
            ->execute(['group' => $groupIid]);
496
497
        // delete the groups
498
        $repo = Container::getGroupRepository();
499
        $em->remove($group);
500
        $em->flush();
501
502
        return true;
503
    }
504
505
    /**
506
     * @deprecated Should be deleted by the resources.
507
     *
508
     * Function needed only when deleting a course, in order to be sure that all group ids are deleted.
509
     *
510
     * @param int $courseId
511
     *
512
     * @return bool
513
     */
514
    public static function deleteAllGroupsFromCourse($courseId)
515
    {
516
        $courseId = (int) $courseId;
517
518
        if (empty($courseId)) {
519
            return false;
520
        }
521
522
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
523
        $sql = "SELECT iid FROM $table
524
                WHERE c_id = $courseId ";
525
        Database::query($sql);
526
527
        // Database table definitions
528
        $table = Database::get_course_table(TABLE_GROUP_USER);
529
        $sql = "DELETE FROM $table
530
                WHERE c_id = $courseId";
531
        Database::query($sql);
532
533
        $table = Database::get_course_table(TABLE_GROUP_TUTOR);
534
        $sql = "DELETE FROM $table
535
                WHERE c_id = $courseId";
536
        Database::query($sql);
537
538
        $groupTable = Database::get_course_table(TABLE_GROUP);
539
        $sql = "DELETE FROM $groupTable
540
                WHERE c_id = $courseId";
541
        Database::query($sql);
542
543
        return true;
544
    }
545
546
    /**
547
     * Get group properties.
548
     *
549
     * @param int $group_id the group from which properties are requested
550
     *
551
     * @return array All properties. Array-keys are:
552
     *               name, tutor_id, description, maximum_number_of_students,
553
     *               directory and visibility of tools
554
     */
555
    public static function get_group_properties($group_id)
556
    {
557
        $group_id = (int) $group_id;
558
559
        if (empty($group_id)) {
560
            return null;
561
        }
562
563
        $table_group = Database::get_course_table(TABLE_GROUP);
564
565
        $sql = "SELECT * FROM $table_group
566
                WHERE iid = ".$group_id;
567
568
        $db_result = Database::query($sql);
569
        $db_object = Database::fetch_object($db_result);
570
571
        $result = [];
572
        if ($db_object) {
573
            $result['id'] = $db_object->iid;
574
            $result['iid'] = $db_object->iid;
575
            $result['name'] = $db_object->name;
576
            $result['status'] = $db_object->status;
577
            $result['description'] = $db_object->description;
578
            $result['maximum_number_of_students'] = $db_object->max_student;
579
            $result['max_student'] = $db_object->max_student;
580
            $result['doc_state'] = $db_object->doc_state;
581
            $result['work_state'] = $db_object->work_state;
582
            $result['calendar_state'] = $db_object->calendar_state;
583
            $result['announcements_state'] = $db_object->announcements_state;
584
            $result['forum_state'] = $db_object->forum_state;
585
            $result['wiki_state'] = $db_object->wiki_state;
586
            $result['chat_state'] = $db_object->chat_state;
587
            $result['directory'] = $db_object->secret_directory;
588
            $result['self_registration_allowed'] = $db_object->self_registration_allowed;
589
            $result['self_unregistration_allowed'] = $db_object->self_unregistration_allowed;
590
            $result['count_users'] = count(
591
                self::get_subscribed_users($result)
592
            );
593
            /*$result['count_tutor'] = count(
594
                self::get_subscribed_tutors($result)
595
            );*/
596
            //$result['count_all'] = $result['count_users'] + $result['count_tutor'];
597
            $result['count_all'] = null;
598
            $result['document_access'] = isset($db_object->document_access) ? $db_object->document_access : self::DOCUMENT_MODE_SHARE;
599
        }
600
601
        return $result;
602
    }
603
604
    /**
605
     * @param string $name
606
     * @param string $courseCode
607
     * @param int    $sessionId
608
     *
609
     * @return array
610
     */
611
    public static function getGroupByName($name, $courseCode = null, $sessionId = 0)
612
    {
613
        $name = trim($name);
614
615
        if (empty($name)) {
616
            return [];
617
        }
618
619
        $course_info = api_get_course_info($courseCode);
620
        $course_id = $course_info['real_id'];
621
        $name = Database::escape_string($name);
622
        $sessionId = empty($sessionId) ? api_get_session_id() : (int) $sessionId;
623
        $sessionCondition = api_get_session_condition($sessionId);
624
625
        $table = Database::get_course_table(TABLE_GROUP);
626
        $sql = "SELECT * FROM $table
627
                WHERE
628
                  c_id = $course_id AND
629
                  name = '$name'
630
                  $sessionCondition
631
                LIMIT 1";
632
        $res = Database::query($sql);
633
        $group = [];
634
        if (Database::num_rows($res)) {
635
            $group = Database::fetch_array($res, 'ASSOC');
636
        }
637
638
        return $group;
639
    }
640
641
    /**
642
     * Set group properties
643
     * Changes the group's properties.
644
     *
645
     * @param int       Group Id
646
     * @param string    Group name
647
     * @param string    Group description
648
     * @param int       Max number of students in group
649
     * @param int       Document tool's visibility (0=none,1=private,2=public)
650
     * @param int       Work tool's visibility (0=none,1=private,2=public)
651
     * @param int       Calendar tool's visibility (0=none,1=private,2=public)
652
     * @param int       Announcement tool's visibility (0=none,1=private,2=public)
653
     * @param int       Forum tool's visibility (0=none,1=private,2=public)
654
     * @param int       Wiki tool's visibility (0=none,1=private,2=public)
655
     * @param int       Chat tool's visibility (0=none,1=private,2=public)
656
     * @param bool Whether self registration is allowed or not
657
     * @param bool Whether self unregistration is allowed or not
658
     * @param int $categoryId
659
     * @param int $documentAccess
660
     *
661
     * @return bool TRUE if properties are successfully changed, false otherwise
662
     */
663
    public static function set_group_properties(
664
        $group_id,
665
        $name,
666
        $description,
667
        $maxStudent,
668
        $docState,
669
        $workState,
670
        $calendarState,
671
        $anonuncementState,
672
        $forumState,
673
        $wikiState,
674
        $chatState,
675
        $selfRegistrationAllowed,
676
        $selfUnRegistrationAllowed,
677
        $categoryId = null,
678
        $documentAccess = 0
679
    ) {
680
        $table_group = Database::get_course_table(TABLE_GROUP);
681
        $table_forum = Database::get_course_table(TABLE_FORUM);
682
        $categoryId = (int) $categoryId;
683
        $group_id = (int) $group_id;
684
        $repo = Container::getGroupRepository();
685
686
        /** @var CGroup $group */
687
        $group = $repo->find($group_id);
688
689
        $category = null;
690
        if (!empty($categoryId)) {
691
            $category = Container::getGroupCategoryRepository()->find($categoryId);
692
        }
693
694
        $group
695
            ->setName($name)
696
            ->setCategory($category)
697
            ->setMaxStudent($maxStudent)
698
            ->setDocState($docState)
699
            ->setCalendarState($calendarState)
700
            ->setWorkState($workState)
701
            ->setForumState($forumState)
702
            ->setWikiState($wikiState)
703
            ->setAnnouncementsState($anonuncementState)
704
            ->setChatState($chatState)
705
            ->setSelfRegistrationAllowed($selfRegistrationAllowed)
706
            ->setSelfUnregistrationAllowed($selfUnRegistrationAllowed)
707
            ->setDocumentAccess($documentAccess)
708
        ;
709
710
        $repo->update($group);
711
712
        /* Here we are updating a field in the table forum_forum that perhaps
713
        duplicates the table group_info.forum_state cvargas*/
714
        $forumState = (int) $forumState;
715
        $sql2 = "UPDATE $table_forum SET ";
716
        if (1 === $forumState) {
717
            $sql2 .= " forum_group_public_private='public' ";
718
        } elseif (2 === $forumState) {
719
            $sql2 .= " forum_group_public_private='private' ";
720
        } elseif (0 === $forumState) {
721
            $sql2 .= " forum_group_public_private='unavailable' ";
722
        }
723
        $sql2 .= ' WHERE forum_of_group='.$group_id;
724
        Database::query($sql2);
725
726
        return true;
727
    }
728
729
    /**
730
     * Get the total number of groups for the current course.
731
     *
732
     * @return int the number of groups for the current course
733
     */
734
    public static function get_number_of_groups()
735
    {
736
        $repo = Container::getGroupRepository();
737
738
        $course = api_get_course_entity(api_get_course_int_id());
739
        $session = api_get_session_entity(api_get_session_id());
740
        $group = api_get_group_entity(api_get_group_id());
741
742
        $qb = $repo->getResourcesByCourse($course, $session, $group);
743
        $qb->select('count(resource)');
744
745
        return $qb->getQuery()->getSingleScalarResult();
746
747
        $courseId = api_get_course_int_id();
0 ignored issues
show
Unused Code introduced by
$courseId = api_get_course_int_id() is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
748
        $table = Database::get_course_table(TABLE_GROUP);
749
        $sql = "SELECT COUNT(id) AS number_of_groups
750
                FROM $table
751
                WHERE c_id = $courseId ";
752
        $res = Database::query($sql);
753
        $obj = Database::fetch_object($res);
754
755
        return $obj->number_of_groups;
756
    }
757
758
    /**
759
     * Get all categories.
760
     */
761
    public static function get_categories(Course $course = null): array
762
    {
763
        $repo = Container::getGroupCategoryRepository();
764
765
        if (null === $course) {
766
            $course = api_get_course_entity(api_get_course_int_id());
767
        }
768
769
        $session = api_get_session_entity(api_get_session_id());
770
        //$group = api_get_group_entity(api_get_group_id());
771
        $group = null;
772
773
        $qb = $repo->getResourcesByCourse($course, $session, $group);
774
775
        return $qb->getQuery()->getArrayResult();
776
777
        $course_info = api_get_course_info($course_code);
0 ignored issues
show
Unused Code introduced by
$course_info = api_get_course_info($course_code) is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
778
        $courseId = $course_info['real_id'];
779
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
780
        $sql = "SELECT * FROM $table
781
                WHERE c_id = $courseId
782
                ORDER BY display_order";
783
        $res = Database::query($sql);
784
        $cats = [];
785
        while ($cat = Database::fetch_array($res)) {
786
            $cats[] = $cat;
787
        }
788
789
        return $cats;
790
    }
791
792
    /**
793
     * Get a group category.
794
     *
795
     * @param int    $id          The category id
796
     * @param string $course_code The course (default = current course)
797
     *
798
     * @return array
799
     */
800
    public static function get_category($id, $course_code = null)
801
    {
802
        if (empty($id)) {
803
            return [];
804
        }
805
806
        $courseInfo = api_get_course_info($course_code);
807
        $courseId = $courseInfo['real_id'];
808
        $id = intval($id);
809
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
810
        $sql = "SELECT * FROM $table
811
                WHERE  iid = $id
812
                LIMIT 1";
813
        $res = Database::query($sql);
814
815
        return Database::fetch_array($res);
816
    }
817
818
    /**
819
     * Get a group category.
820
     *
821
     * @param string $title
822
     * @param string $course_code The course (default = current course)
823
     *
824
     * @return array
825
     */
826
    public static function getCategoryByTitle($title, $course_code = null)
827
    {
828
        $title = trim($title);
829
830
        if (empty($title)) {
831
            return [];
832
        }
833
834
        $course_info = api_get_course_info($course_code);
835
        $courseId = $course_info['real_id'];
836
        $title = Database::escape_string($title);
837
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
838
        $sql = "SELECT * FROM $table
839
                WHERE c_id = $courseId AND title = '$title'
840
                LIMIT 1";
841
        $res = Database::query($sql);
842
        $category = [];
843
        if (Database::num_rows($res)) {
844
            $category = Database::fetch_array($res, 'ASSOC');
845
        }
846
847
        return $category;
848
    }
849
850
    /**
851
     * Get the unique category of a given group.
852
     *
853
     * @param int    $group_id    The iid of the group
854
     * @param string $course_code The course in which the group is (default =
855
     *                            current course)
856
     *
857
     * @return array The category
858
     */
859
    public static function get_category_from_group($group_id, $course_code = '')
860
    {
861
        $table_group = Database::get_course_table(TABLE_GROUP);
862
        $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
863
864
        $group_id = (int) $group_id;
865
866
        if (empty($group_id)) {
867
            return [];
868
        }
869
870
        $course_info = api_get_course_info($course_code);
871
872
        if (empty($course_info)) {
873
            return false;
874
        }
875
876
        $courseId = $course_info['real_id'];
877
        $sql = "SELECT gc.* FROM $table_group_cat gc
878
                INNER JOIN $table_group g
879
                ON (gc.iid = g.category_id)
880
                WHERE
881
                    g.iid = $group_id
882
                LIMIT 1";
883
        $res = Database::query($sql);
884
        $cat = [];
885
        if (Database::num_rows($res)) {
886
            $cat = Database::fetch_array($res);
887
        }
888
889
        return $cat;
890
    }
891
892
    /**
893
     * Delete a group category.
894
     *
895
     * @param int    $cat_id      The id of the category to delete
896
     * @param string $course_code The code in which the category should be
897
     *                            deleted (default = current course)
898
     *
899
     * @return bool
900
     */
901
    public static function delete_category($cat_id, $course_code = '')
902
    {
903
        $course_info = api_get_course_info($course_code);
904
        if (empty($course_info)) {
905
            return false;
906
        }
907
        $course_id = $course_info['real_id'];
908
909
        $table_group = Database::get_course_table(TABLE_GROUP);
910
        $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
911
        $cat_id = (int) $cat_id;
912
        $sql = "SELECT iid FROM $table_group
913
                WHERE category_id='".$cat_id."'";
914
        $res = Database::query($sql);
915
        if (Database::num_rows($res) > 0) {
916
            while ($group = Database::fetch_object($res)) {
917
                // Delete all groups in category
918
                /*$groupInfo = self::get_group_properties($group->iid, true);
919
                self::deleteGroup($groupInfo, $course_code);
920
                */
921
                // Set the category to NULL to avoid losing groups in sessions.
922
                $sql = "UPDATE $table_group SET category_id = NULL WHERE iid = ".$group->iid;
923
                Database::query($sql);
924
            }
925
        }
926
927
        $category = Database::getManager()->getRepository(CGroupCategory::class)->find($cat_id);
928
        if ($category) {
929
            Database::getManager()->remove($category);
930
            Database::getManager()->flush();
931
        }
932
933
        /*$sql = "DELETE FROM $table_group_cat
934
                WHERE iid='".$cat_id."'";
935
        Database::query($sql);*/
936
937
        return true;
938
    }
939
940
    /**
941
     * Create group category.
942
     *
943
     * @param string $title                     The title of the new category
944
     * @param string $description               The description of the new category
945
     * @param int    $selfRegistrationAllowed   allow users to self register
946
     * @param int    $selfUnRegistrationAllowed allow user to self unregister
947
     * @param int    $documentAccess            document access
948
     *
949
     * @return mixed
950
     */
951
    public static function create_category(
952
        $title,
953
        $description,
954
        $docState,
955
        $workState,
956
        $calendarState,
957
        $anonuncementState,
958
        $forumState,
959
        $wikiState,
960
        $chatState = 1,
961
        $selfRegistrationAllowed = 0,
962
        $selfUnRegistrationAllowed = 0,
963
        $maxStudent = 8,
964
        $groupsPerUser = 0,
965
        $documentAccess = 0
966
    ) {
967
        if (empty($title)) {
968
            return false;
969
        }
970
        /*$sql = "SELECT MAX(display_order)+1 as new_order
971
                FROM $table
972
                WHERE c_id = $course_id ";
973
        $res = Database::query($sql);
974
        $obj = Database::fetch_object($res);
975
        if (!isset($obj->new_order)) {
976
            $obj->new_order = 1;
977
        }*/
978
979
        $course = api_get_course_entity(api_get_course_int_id());
980
        $session = api_get_session_entity(api_get_session_id());
981
982
        $category = new CGroupCategory();
983
        $category
984
            ->setTitle($title)
985
            ->setDescription($description)
986
            ->setMaxStudent($maxStudent)
987
            ->setDocState($docState)
988
            ->setCalendarState($calendarState)
989
            ->setWorkState($workState)
990
            ->setForumState($forumState)
991
            ->setWikiState($wikiState)
992
            ->setAnnouncementsState($anonuncementState)
993
            ->setChatState($chatState)
994
            ->setSelfRegAllowed($selfRegistrationAllowed)
995
            ->setSelfUnregAllowed($selfUnRegistrationAllowed)
996
            ->setDocumentAccess($documentAccess)
997
            ->setGroupsPerUser($groupsPerUser)
998
            ->setParent($course)
999
            ->addCourseLink($course, $session)
1000
        ;
1001
1002
        $repo = Container::getGroupCategoryRepository();
1003
        $repo->create($category);
1004
1005
        return $category->getIid();
1006
    }
1007
1008
    /**
1009
     * Update group category.
1010
     *
1011
     * @param int    $id
1012
     * @param string $title
1013
     * @param string $description
1014
     * @param $doc_state
1015
     * @param $work_state
1016
     * @param $calendar_state
1017
     * @param $announcements_state
1018
     * @param $forum_state
1019
     * @param $wiki_state
1020
     * @param $chat_state
1021
     * @param $selfRegistrationAllowed
1022
     * @param $selfUnRegistrationAllowed
1023
     * @param $maximum_number_of_students
1024
     * @param $groups_per_user
1025
     * @param $documentAccess
1026
     */
1027
    public static function update_category(
1028
        $id,
1029
        $title,
1030
        $description,
1031
        $doc_state,
1032
        $work_state,
1033
        $calendar_state,
1034
        $announcements_state,
1035
        $forum_state,
1036
        $wiki_state,
1037
        $chat_state,
1038
        $selfRegistrationAllowed,
1039
        $selfUnRegistrationAllowed,
1040
        $maximum_number_of_students,
1041
        $groups_per_user,
1042
        $documentAccess
1043
    ) {
1044
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
1045
        $id = (int) $id;
1046
1047
        $courseId = api_get_course_int_id();
1048
1049
        $allowDocumentAccess = api_get_configuration_value('group_category_document_access');
1050
        $documentCondition = '';
1051
        if ($allowDocumentAccess) {
1052
            $documentAccess = (int) $documentAccess;
1053
            $documentCondition = " document_access = $documentAccess, ";
1054
        }
1055
1056
        $sql = 'UPDATE '.$table." SET
1057
                    title='".Database::escape_string($title)."',
1058
                    description='".Database::escape_string($description)."',
1059
                    doc_state = '".Database::escape_string($doc_state)."',
1060
                    work_state = '".Database::escape_string($work_state)."',
1061
                    calendar_state = '".Database::escape_string($calendar_state)."',
1062
                    announcements_state = '".Database::escape_string($announcements_state)."',
1063
                    forum_state = '".Database::escape_string($forum_state)."',
1064
                    wiki_state = '".Database::escape_string($wiki_state)."',
1065
                    chat_state = '".Database::escape_string($chat_state)."',
1066
                    groups_per_user   = '".Database::escape_string($groups_per_user)."',
1067
                    self_reg_allowed = '".Database::escape_string($selfRegistrationAllowed)."',
1068
                    self_unreg_allowed = '".Database::escape_string($selfUnRegistrationAllowed)."',
1069
                    $documentCondition
1070
                    max_student = ".intval($maximum_number_of_students)."
1071
                WHERE iid = $id";
1072
1073
        Database::query($sql);
1074
1075
        // Updating all groups inside this category
1076
        $groups = self::get_group_list($id);
1077
1078
        if (!empty($groups)) {
1079
            foreach ($groups as $group) {
1080
                self::set_group_properties(
1081
                    $group['iid'],
1082
                    $group['name'],
1083
                    $group['description'],
1084
                    $maximum_number_of_students,
1085
                    $doc_state,
1086
                    $work_state,
1087
                    $calendar_state,
1088
                    $announcements_state,
1089
                    $forum_state,
1090
                    $wiki_state,
1091
                    $chat_state,
1092
                    $selfRegistrationAllowed,
1093
                    $selfUnRegistrationAllowed,
1094
                    $id,
1095
                    $documentAccess
1096
                );
1097
            }
1098
        }
1099
    }
1100
1101
    /**
1102
     * Returns the number of groups of the user with the greatest number of
1103
     * subscriptions in the given category.
1104
     */
1105
    public static function get_current_max_groups_per_user($category_id = null, $course_code = null)
1106
    {
1107
        $course_info = api_get_course_info($course_code);
1108
        $group_table = Database::get_course_table(TABLE_GROUP);
1109
1110
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1111
        $sql = "SELECT COUNT(gu.group_id) AS current_max
1112
                FROM $group_user_table gu
1113
                INNER JOIN $group_table g
1114
                ON (gu.group_id = g.iid)
1115
                WHERE 1= 1 ";
1116
        if (null != $category_id) {
1117
            $category_id = intval($category_id);
1118
            $sql .= ' AND g.category_id = '.$category_id;
1119
        }
1120
        $sql .= ' GROUP BY gu.user_id
1121
                  ORDER BY current_max DESC LIMIT 1';
1122
1123
        $res = Database::query($sql);
1124
        $obj = Database::fetch_object($res);
1125
1126
        if ($obj) {
1127
            return $obj->current_max;
1128
        }
1129
1130
        return 0;
1131
    }
1132
1133
    /**
1134
     * Swaps the display-order of two categories.
1135
     *
1136
     * @param int $id1 The id of the first category
1137
     * @param int $id2 The id of the second category
1138
     */
1139
    public static function swap_category_order($id1, $id2)
1140
    {
1141
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
1142
        $id1 = intval($id1);
1143
        $id2 = intval($id2);
1144
        $course_id = api_get_course_int_id();
1145
1146
        $sql = "SELECT id, display_order FROM $table
1147
                WHERE id IN ($id1,$id2) AND c_id = $course_id ";
1148
        $res = Database::query($sql);
1149
        $cat1 = Database::fetch_object($res);
1150
        $cat2 = Database::fetch_object($res);
1151
        if ($cat1 && $cat2) {
1152
            $sql = "UPDATE $table SET display_order=$cat2->display_order
1153
                    WHERE id = $cat1->id AND c_id = $course_id ";
1154
            Database::query($sql);
1155
1156
            $sql = "UPDATE $table SET display_order=$cat1->display_order
1157
                    WHERE id = $cat2->id AND c_id = $course_id ";
1158
            Database::query($sql);
1159
        }
1160
    }
1161
1162
    /**
1163
     * Get all users from a given group.
1164
     *
1165
     * @param int  $group_id        The group
1166
     * @param bool $load_extra_info
1167
     * @param int  $start
1168
     * @param int  $limit
1169
     * @param bool $getCount
1170
     * @param int  $courseId
1171
     * @param $column
1172
     * @param $direction
1173
     *
1174
     * @return array list of user id
1175
     */
1176
    public static function get_users(
1177
        $group_id,
1178
        $load_extra_info = false,
1179
        $start = null,
1180
        $limit = null,
1181
        $getCount = false,
1182
        $courseId = null,
1183
        $column = null,
1184
        $direction = null
1185
    ) {
1186
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1187
        $groupTable = Database::get_course_table(TABLE_GROUP);
1188
        $user_table = Database::get_main_table(TABLE_MAIN_USER);
1189
        $group_id = (int) $group_id;
1190
1191
        if (empty($courseId)) {
1192
            $courseId = api_get_course_int_id();
1193
        } else {
1194
            $courseId = (int) $courseId;
1195
        }
1196
1197
        $select = ' SELECT u.id, firstname, lastname ';
1198
        if ($getCount) {
1199
            $select = ' SELECT count(u.id) count';
1200
        }
1201
        $sql = "$select
1202
                FROM $group_user_table gu
1203
                INNER JOIN $groupTable g
1204
                ON (gu.group_id = g.iid and g.c_id = gu.c_id)
1205
                INNER JOIN $user_table u
1206
                ON (u.id = gu.user_id)
1207
                WHERE
1208
                    gu.c_id = $courseId AND
1209
                    g.iid = $group_id";
1210
1211
        if (!empty($column) && !empty($direction)) {
1212
            $column = Database::escape_string($column, null, false);
1213
            $direction = ('ASC' == $direction ? 'ASC' : 'DESC');
1214
            $sql .= " ORDER BY $column $direction";
1215
        }
1216
1217
        if (!empty($start) && !empty($limit)) {
1218
            $start = (int) $start;
1219
            $limit = (int) $limit;
1220
            $sql .= " LIMIT $start, $limit";
1221
        }
1222
        $res = Database::query($sql);
1223
        $users = [];
1224
        while ($obj = Database::fetch_object($res)) {
1225
            if ($getCount) {
1226
                return $obj->count;
1227
                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...
1228
            }
1229
            if ($load_extra_info) {
1230
                $users[] = api_get_user_info($obj->id);
1231
            } else {
1232
                $users[] = $obj->id;
1233
            }
1234
        }
1235
1236
        return $users;
1237
    }
1238
1239
    /**
1240
     * @param int $group_id id
1241
     *
1242
     * @return array
1243
     */
1244
    public static function getStudentsAndTutors($group_id)
1245
    {
1246
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1247
        $tutor_user_table = Database::get_course_table(TABLE_GROUP_TUTOR);
1248
        $groupTable = Database::get_course_table(TABLE_GROUP);
1249
1250
        $course_id = api_get_course_int_id();
1251
        $group_id = (int) $group_id;
1252
1253
        $sql = "SELECT user_id
1254
                FROM $group_user_table gu
1255
                INNER JOIN $groupTable g
1256
                ON (gu.group_id = g.iid)
1257
                WHERE g.iid = $group_id";
1258
        $res = Database::query($sql);
1259
        $users = [];
1260
1261
        while ($obj = Database::fetch_object($res)) {
1262
            $users[] = api_get_user_info($obj->user_id);
1263
        }
1264
1265
        $sql = "SELECT user_id
1266
                FROM $tutor_user_table gu
1267
                INNER JOIN $groupTable g
1268
                ON (gu.group_id = g.iid)
1269
                WHERE g.iid = $group_id";
1270
        $res = Database::query($sql);
1271
        while ($obj = Database::fetch_object($res)) {
1272
            $users[] = api_get_user_info($obj->user_id);
1273
        }
1274
1275
        return $users;
1276
    }
1277
1278
    /**
1279
     * Get only tutors from a group.
1280
     *
1281
     * @param array $groupInfo
1282
     *
1283
     * @return array
1284
     */
1285
    public static function getTutors($groupInfo)
1286
    {
1287
        $groupTable = Database::get_course_table(TABLE_GROUP);
1288
        $tutor_user_table = Database::get_course_table(TABLE_GROUP_TUTOR);
1289
        $course_id = api_get_course_int_id();
1290
        $group_id = (int) $groupInfo['iid'];
1291
1292
        $sql = "SELECT user_id
1293
                FROM $tutor_user_table gu
1294
                INNER JOIN $groupTable g
1295
                ON (gu.group_id = g.iid)
1296
                WHERE g.iid = $group_id";
1297
        $res = Database::query($sql);
1298
1299
        $users = [];
1300
        while ($obj = Database::fetch_object($res)) {
1301
            $users[] = api_get_user_info($obj->user_id);
1302
        }
1303
1304
        return $users;
1305
    }
1306
1307
    /**
1308
     * Get only students from a group (not tutors).
1309
     *
1310
     * @param bool $filterOnlyActive
1311
     *
1312
     * @return array
1313
     */
1314
    public static function getStudents($groupId, $filterOnlyActive = false)
1315
    {
1316
        $groupId = (int) $groupId;
1317
        $activeCondition = $filterOnlyActive ? 'AND u.active = 1' : '';
1318
1319
        $em = Database::getManager();
1320
        $subscriptions = $em
1321
            ->createQuery("
1322
                SELECT u.id FROM ChamiloCoreBundle:User u
1323
                INNER JOIN ChamiloCourseBundle:CGroupRelUser gu
1324
                WITH u.id = gu.user
1325
                INNER JOIN ChamiloCourseBundle:CGroup g
1326
                WITH gu.group = g.iid
1327
                WHERE g.iid = :group
1328
                    $activeCondition
1329
            ")
1330
            ->setParameters([
1331
                'group' => $groupId,
1332
            ])
1333
            ->getResult();
1334
1335
        $users = [];
1336
        foreach ($subscriptions as $subscription) {
1337
            $users[] = api_get_user_info($subscription['id']);
1338
        }
1339
1340
        return $users;
1341
    }
1342
1343
    public static function getStudentsCount($groupId, $filterOnlyActive = false)
1344
    {
1345
        $groupId = (int) $groupId;
1346
        $activeCondition = $filterOnlyActive ? 'AND u.active = 1' : '';
1347
1348
        $em = Database::getManager();
1349
1350
        return $em
1351
            ->createQuery("
1352
                SELECT COUNT(u.id) FROM ChamiloCoreBundle:User u
1353
                INNER JOIN ChamiloCourseBundle:CGroupRelUser gu
1354
                WITH u.id = gu.user
1355
                INNER JOIN ChamiloCourseBundle:CGroup g
1356
                WITH gu.group = g.iid
1357
                WHERE g.iid = :group
1358
                    $activeCondition
1359
            ")
1360
            ->setParameters([
1361
                'group' => $groupId,
1362
            ])
1363
            ->getSingleScalarResult();
1364
    }
1365
1366
    /**
1367
     * Returns users belonging to any of the group.
1368
     *
1369
     * @param array $groups list of group ids
1370
     *
1371
     * @return array list of user ids
1372
     */
1373
    public static function get_groups_users($groups = [])
1374
    {
1375
        $result = [];
1376
        $table = Database::get_course_table(TABLE_GROUP_USER);
1377
        $course_id = api_get_course_int_id();
1378
1379
        $groups = array_map('intval', $groups);
1380
        // protect individual elements with surrounding quotes
1381
        $groups = implode(', ', $groups);
1382
        $sql = "SELECT DISTINCT user_id
1383
                FROM $table gu
1384
                WHERE gu.group_id IN ($groups)";
1385
        $rs = Database::query($sql);
1386
        while ($row = Database::fetch_array($rs)) {
1387
            $result[] = $row['user_id'];
1388
        }
1389
1390
        return $result;
1391
    }
1392
1393
    /**
1394
     * Fill the groups with students.
1395
     * The algorithm takes care to first fill the groups with the least # of users.
1396
     * Analysis
1397
     * There was a problem with the "ALL" setting.
1398
     * When max # of groups is set to all, the value is sometimes NULL and sometimes ALL
1399
     * and in both cased the query does not work as expected.
1400
     * Stupid solution (currently implemented: set ALL to a big number (INFINITE) and things are solved :)
1401
     * Better solution: that's up to you.
1402
     *
1403
     * Note
1404
     * Throughout Dokeos there is some confusion about "course id" and "course code"
1405
     * The code is e.g. TEST101, but sometimes a variable that is called courseID also contains a course code string.
1406
     * However, there is also a integer course_id that uniquely identifies the course.
1407
     * ywarnier:> Now the course_id has been removed (25/1/2005)
1408
     * The databases are als very inconsistent in this.
1409
     *
1410
     * @author Chrisptophe Gesche <[email protected]>,
1411
     *         Hugues Peeters     <[email protected]> - original version
1412
     * @author Roan Embrechts - virtual course support, code cleaning
1413
     * @author Bart Mollet - code cleaning, use other GroupManager-functions
1414
     *
1415
     * @return bool
1416
     */
1417
    public static function fillGroupWithUsers(CGroup $group)
1418
    {
1419
        $_course = api_get_course_info();
1420
        if (empty($_course) || empty($group)) {
1421
            return false;
1422
        }
1423
        $session_id = api_get_session_id();
1424
        $complete_user_list = CourseManager::get_user_list_from_course_code(
1425
            $_course['code'],
1426
            $session_id
1427
        );
1428
        $groupIid = $group->getIid();
1429
        $category = self::get_category_from_group($groupIid);
1430
1431
        // Getting max numbers of user from group
1432
        $maxNumberStudents = empty($group->getMaxStudent()) ? self::INFINITE : $group->getMaxStudent();
1433
        $groupsPerUser = self::INFINITE;
1434
        $categoryId = 0;
1435
        if ($category) {
1436
            $groupsPerUser = empty($category['groups_per_user']) ? self::INFINITE : $category['groups_per_user'];
1437
            $maxNumberStudentsCategory = empty($category['max_student']) ? self::INFINITE : $category['max_student'];
1438
            $categoryId = $category['iid'];
1439
            if ($maxNumberStudentsCategory < $maxNumberStudents) {
1440
                $maxNumberStudents = $maxNumberStudentsCategory;
1441
            }
1442
        }
1443
1444
        $usersToAdd = [];
1445
        foreach ($complete_user_list as $userInfo) {
1446
            $isSubscribed = self::is_subscribed($userInfo['user_id'], $group);
1447
            if ($isSubscribed) {
1448
                continue;
1449
            }
1450
            $numberOfGroups = self::user_in_number_of_groups(
1451
                $userInfo['user_id'],
1452
                $categoryId
1453
            );
1454
            if ($groupsPerUser > $numberOfGroups) {
1455
                $usersToAdd[] = $userInfo['user_id'];
1456
            }
1457
            if (count($usersToAdd) == $maxNumberStudents) {
1458
                break;
1459
            }
1460
        }
1461
1462
        foreach ($usersToAdd as $userId) {
1463
            self::subscribeUsers($userId, $group);
1464
        }
1465
    }
1466
1467
    /**
1468
     * Get the number of students in a group.
1469
     *
1470
     * @param int $group_id id
1471
     *
1472
     * @return int number of students in the given group
1473
     */
1474
    public static function number_of_students($group_id, $course_id = null)
1475
    {
1476
        $table = Database::get_course_table(TABLE_GROUP_USER);
1477
        $group_id = (int) $group_id;
1478
        $course_id = (int) $course_id;
1479
1480
        if (empty($course_id)) {
1481
            $course_id = api_get_course_int_id();
1482
        }
1483
        $sql = "SELECT COUNT(*) AS number_of_students
1484
                FROM $table
1485
                WHERE c_id = $course_id AND group_id = $group_id";
1486
        $result = Database::query($sql);
1487
        $db_object = Database::fetch_object($result);
1488
1489
        return $db_object->number_of_students;
1490
    }
1491
1492
    /**
1493
     * Maximum number of students in a group.
1494
     *
1495
     * @param int $group_id iid
1496
     *
1497
     * @return int maximum number of students in the given group
1498
     */
1499
    public static function maximum_number_of_students($group_id)
1500
    {
1501
        $table = Database::get_course_table(TABLE_GROUP);
1502
        $group_id = (int) $group_id;
1503
        $course_id = api_get_course_int_id();
1504
        $sql = "SELECT max_student FROM $table
1505
                WHERE iid = $group_id";
1506
        $db_result = Database::query($sql);
1507
        $db_object = Database::fetch_object($db_result);
1508
        if (0 == $db_object->max_student) {
1509
            return self::INFINITE;
1510
        }
1511
1512
        return $db_object->max_student;
1513
    }
1514
1515
    /**
1516
     * Number of groups of a user.
1517
     *
1518
     * @param int $user_id
1519
     * @param int $cat_id
1520
     *
1521
     * @return int the number of groups the user is subscribed in
1522
     */
1523
    public static function user_in_number_of_groups($user_id, $cat_id = 0)
1524
    {
1525
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1526
        $table_group = Database::get_course_table(TABLE_GROUP);
1527
        $user_id = (int) $user_id;
1528
        $cat_id = (int) $cat_id;
1529
1530
        $course_id = api_get_course_int_id();
1531
        $cat_condition = '';
1532
        if (!empty($cat_id)) {
1533
            $cat_condition = " AND g.category_id =  $cat_id ";
1534
        }
1535
1536
        $sql = "SELECT COUNT(*) AS number_of_groups
1537
                FROM $table_group_user gu
1538
                INNER JOIN $table_group g
1539
                ON (g.iid = gu.group_id)
1540
                WHERE
1541
                    gu.user_id = $user_id
1542
                    $cat_condition";
1543
1544
        $result = Database::query($sql);
1545
        $db_object = Database::fetch_object($result);
1546
1547
        return $db_object->number_of_groups;
1548
    }
1549
1550
    /**
1551
     * Is sef-registration allowed?
1552
     *
1553
     * @param int   $user_id
1554
     *
1555
     * @return bool TRUE if self-registration is allowed in the given group
1556
     */
1557
    public static function is_self_registration_allowed($user_id, CGroup $group)
1558
    {
1559
        if (empty($user_id)) {
1560
            return false;
1561
        }
1562
1563
        if ($group) {
1564
            if (0 == $group->getStatus() || 1 != $group->getSelfRegistrationAllowed()) {
1565
                return false;
1566
            }
1567
1568
            return self::canUserSubscribe($user_id, $group);
1569
        }
1570
1571
        return false;
1572
    }
1573
1574
    /**
1575
     * Is sef-unregistration allowed?
1576
     *
1577
     * @param int   $user_id
1578
     *
1579
     * @return bool TRUE if self-unregistration is allowed in the given group
1580
     */
1581
    public static function is_self_unregistration_allowed($user_id, CGroup $group)
1582
    {
1583
        if (empty($user_id) || empty($group)) {
1584
            return false;
1585
        }
1586
        if (0 == $group->getStatus() || 1 != $group->getSelfUnregistrationAllowed()) {
1587
            return false;
1588
        }
1589
1590
        return self::is_subscribed($user_id, $group);
1591
    }
1592
1593
    /**
1594
     * Is user subscribed in group?
1595
     *
1596
     * @param int    $user_id
1597
     *
1598
     * @return bool TRUE if given user is subscribed in given group
1599
     */
1600
    public static function is_subscribed($user_id, CGroup $group)
1601
    {
1602
        $course_id = api_get_course_int_id();
1603
        if (empty($user_id) || empty($group) || empty($course_id)) {
1604
            return false;
1605
        }
1606
        $table = Database::get_course_table(TABLE_GROUP_USER);
1607
        $group_id = $group->getIid();
1608
        $user_id = (int) $user_id;
1609
1610
        $sql = "SELECT 1 FROM $table
1611
                WHERE
1612
                    group_id = $group_id AND
1613
                    user_id = $user_id
1614
                ";
1615
        $result = Database::query($sql);
1616
1617
        return Database::num_rows($result) > 0;
1618
    }
1619
1620
    /**
1621
     * Can a user subscribe to a specified group in a course.
1622
     *
1623
     * @param int   $user_id
1624
     * @param bool  $checkMaxNumberStudents
1625
     *
1626
     * @return bool true if success
1627
     */
1628
    public static function canUserSubscribe(
1629
        $user_id,
1630
        CGroup $group,
1631
        $checkMaxNumberStudents = true
1632
    ) {
1633
        $groupIid =  $group->getIid();
1634
        if ($checkMaxNumberStudents) {
1635
            $category = self::get_category_from_group($group->getIid());
1636
            if ($category) {
1637
                if (self::GROUP_PER_MEMBER_NO_LIMIT == $category['groups_per_user']) {
1638
                    $category['groups_per_user'] = self::INFINITE;
1639
                }
1640
                $result = self::user_in_number_of_groups($user_id, $category['iid']) < $category['groups_per_user'];
1641
                if (false == $result) {
1642
                    return false;
1643
                }
1644
            }
1645
1646
            $result = self::number_of_students($groupIid) < self::maximum_number_of_students($groupIid);
1647
1648
            if (false == $result) {
1649
                return false;
1650
            }
1651
        }
1652
1653
        $result = self::isTutorOfGroup($user_id, $group);
1654
1655
        if ($result) {
1656
            return false;
1657
        }
1658
1659
        $result = self::is_subscribed($user_id, $group);
1660
1661
        if ($result) {
1662
            return false;
1663
        }
1664
1665
        return true;
1666
    }
1667
1668
    /**
1669
     * Get all subscribed users (members) from a group.
1670
     *
1671
     * @param array $groupInfo
1672
     *
1673
     * @return array An array with information of all users from the given group.
1674
     *               (user_id, firstname, lastname, email)
1675
     */
1676
    public static function get_subscribed_users($groupInfo)
1677
    {
1678
        if (empty($groupInfo)) {
1679
            return [];
1680
        }
1681
1682
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
1683
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1684
        $order_clause = api_sort_by_first_name() ? ' ORDER BY u.firstname, u.lastname' : ' ORDER BY u.lastname, u.firstname';
1685
        $orderListByOfficialCode = api_get_setting('order_user_list_by_official_code');
1686
        if ('true' === $orderListByOfficialCode) {
1687
            $order_clause = ' ORDER BY u.official_code, u.firstname, u.lastname';
1688
        }
1689
1690
        $group_id = (int) $groupInfo['iid'];
1691
1692
        if (empty($group_id)) {
1693
            return [];
1694
        }
1695
1696
        $course_id = api_get_course_int_id();
1697
1698
        $sql = "SELECT
1699
                    ug.iid,
1700
                    u.id as user_id,
1701
                    u.lastname,
1702
                    u.firstname,
1703
                    u.email,
1704
                    u.username
1705
                FROM $table_user u
1706
                INNER JOIN $table_group_user ug
1707
                ON (ug.user_id = u.id)
1708
                WHERE
1709
                      ug.group_id = $group_id
1710
                $order_clause";
1711
1712
        $db_result = Database::query($sql);
1713
        $users = [];
1714
        while ($user = Database::fetch_object($db_result)) {
1715
            $users[$user->user_id] = [
1716
                'user_id' => $user->user_id,
1717
                'firstname' => $user->firstname,
1718
                'lastname' => $user->lastname,
1719
                'email' => $user->email,
1720
                'username' => $user->username,
1721
            ];
1722
        }
1723
1724
        return $users;
1725
    }
1726
1727
    /**
1728
     * Subscribe user(s) to a specified group in current course (as a student).
1729
     *
1730
     * @param mixed $userList  Can be an array with user-id's or a single user-id
1731
     * @param CGroup $group
1732
     * @param int   $course_id
1733
     *
1734
     * @return bool
1735
     */
1736
    public static function subscribeUsers($userList, CGroup $group = null, $course_id = null)
1737
    {
1738
        if (empty($group)) {
1739
            return false;
1740
        }
1741
        $userList = is_array($userList) ? $userList : [$userList];
1742
        $course_id = empty($course_id) ? api_get_course_int_id() : (int) $course_id;
1743
        $group_id = $group->getIid();
1744
1745
        if (!empty($userList)) {
1746
            $table = Database::get_course_table(TABLE_GROUP_USER);
1747
            foreach ($userList as $user_id) {
1748
                if (self::canUserSubscribe($user_id, $group)) {
1749
                    $user_id = (int) $user_id;
1750
                    $sql = "INSERT INTO $table (c_id, user_id, group_id, status, role)
1751
                            VALUES ('$course_id', '".$user_id."', '".$group_id."', 0, '')";
1752
                    Database::query($sql);
1753
                }
1754
            }
1755
        }
1756
1757
        return true;
1758
    }
1759
1760
    /**
1761
     * Subscribe tutor(s) to a specified group in current course.
1762
     *
1763
     * @param mixed $userList  Can be an array with user-id's or a single user-id
1764
     * @param array $groupInfo
1765
     * @param int   $course_id
1766
     */
1767
    public static function subscribeTutors($userList, CGroup $group = null, $course_id = 0)
1768
    {
1769
        if (empty($group)) {
1770
            return false;
1771
        }
1772
        $userList = is_array($userList) ? $userList : [$userList];
1773
        $result = true;
1774
        $course_id = isset($course_id) && !empty($course_id) ? intval($course_id) : api_get_course_int_id();
1775
        $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1776
        $groupId = (int) $group->getIid();
1777
1778
        foreach ($userList as $user_id) {
1779
            $user_id = intval($user_id);
1780
            if (self::canUserSubscribe($user_id, $group, false)) {
1781
                $sql = 'INSERT INTO '.$table_group_tutor." (c_id, user_id, group_id)
1782
                        VALUES ('$course_id', '".$user_id."', '".$groupId."')";
1783
                $result = Database::query($sql);
1784
            }
1785
        }
1786
1787
        return $result;
1788
    }
1789
1790
    /**
1791
     * Unsubscribe user(s) from a specified group in current course.
1792
     *
1793
     * @param mixed $userList  Can be an array with user-id's or a single user-id
1794
     *
1795
     * @return bool
1796
     */
1797
    public static function unsubscribeUsers($userList, CGroup $group = null)
1798
    {
1799
        if (empty($group)) {
1800
            return false;
1801
        }
1802
        $userList = is_array($userList) ? $userList : [$userList];
1803
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1804
        $group_id = $group->getIid();
1805
        $course_id = api_get_course_int_id();
1806
        $sql = 'DELETE FROM '.$table_group_user.'
1807
                WHERE
1808
                    group_id = '.$group_id.' AND
1809
                    user_id IN ('.implode(',', $userList).')
1810
                ';
1811
        Database::query($sql);
1812
    }
1813
1814
    /**
1815
     * Unsubscribe all users from one or more groups.
1816
     *
1817
     * @param int $groupId
1818
     *
1819
     * @return bool
1820
     */
1821
    public static function unsubscribeAllUsers($groupId)
1822
    {
1823
        $groupId = (int) $groupId;
1824
        if (empty($groupId)) {
1825
            return false;
1826
        }
1827
1828
        $table = Database::get_course_table(TABLE_GROUP_USER);
1829
        $sql = "DELETE FROM $table
1830
                WHERE
1831
                    group_id = $groupId ";
1832
1833
        return Database::query($sql);
1834
    }
1835
1836
    /**
1837
     * Unsubscribe all tutors from one or more groups.
1838
     *
1839
     * @param int $groupId iid
1840
     *
1841
     * @see unsubscribe_all_users. This function is almost an exact copy of that function.
1842
     *
1843
     * @return bool TRUE if successful
1844
     *
1845
     * @author Patrick Cool <[email protected]>, Ghent University
1846
     */
1847
    public static function unsubscribe_all_tutors($groupId)
1848
    {
1849
        $courseId = api_get_course_int_id();
1850
        $groupId = (int) $groupId;
1851
1852
        if (empty($courseId) || empty($groupId)) {
1853
            return false;
1854
        }
1855
1856
        if (!empty($groupId)) {
1857
            $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1858
            $sql = "DELETE FROM $table_group_tutor
1859
                    WHERE group_id = $groupId ";
1860
            Database::query($sql);
1861
        }
1862
1863
        return true;
1864
    }
1865
1866
    /**
1867
     * Is the user a tutor of this group?
1868
     * @todo replace this function with $group->isUserTutor
1869
     */
1870
    public static function isTutorOfGroup($userId, CGroup $group = null)
1871
    {
1872
        if (empty($group)) {
1873
            return false;
1874
        }
1875
1876
        $userId = (int) $userId;
1877
        $group_id = (int) $group->getIid();
1878
1879
        $table = Database::get_course_table(TABLE_GROUP_TUTOR);
1880
1881
        $sql = "SELECT * FROM $table
1882
                WHERE
1883
                    user_id = $userId AND
1884
                    group_id = $group_id";
1885
        $result = Database::query($sql);
1886
1887
        return Database::num_rows($result) > 0;
1888
    }
1889
1890
    /**
1891
     * Is the user part of this group? This can be a tutor or a normal member
1892
     * you should use this function if the access to a tool or functionality is
1893
     * restricted to the people who are actually in the group
1894
     * before you had to check if the user was
1895
     * 1. a member of the group OR
1896
     * 2. a tutor of the group. This function combines both.
1897
     */
1898
    public static function isUserInGroup($user_id, CGroup $group)
1899
    {
1900
        $member = self::is_subscribed($user_id, $group);
1901
        if ($member) {
1902
            return true;
1903
        }
1904
1905
        $tutor = self::isTutorOfGroup($user_id, $group);
1906
        if ($tutor) {
1907
            return true;
1908
        }
1909
1910
        return false;
1911
    }
1912
1913
    /**
1914
     * Get all group's from a given course in which a given user is unsubscribed.
1915
     *
1916
     * @author  Patrick Cool
1917
     *
1918
     * @param int $course_id retrieve the groups for
1919
     * @param int $user_id   the ID of the user you want to know all its group memberships
1920
     *
1921
     * @return array
1922
     */
1923
    public static function get_group_ids($course_id, $user_id)
1924
    {
1925
        $groups = [];
1926
        $tbl_group = Database::get_course_table(TABLE_GROUP_USER);
1927
        $tbl_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1928
        $user_id = intval($user_id);
1929
        $course_id = intval($course_id);
1930
1931
        $sql = "SELECT group_id FROM $tbl_group
1932
                WHERE user_id = '$user_id'";
1933
        $result = Database::query($sql);
1934
1935
        if ($result) {
1936
            while ($row = Database::fetch_array($result)) {
1937
                $groups[] = $row['group_id'];
1938
            }
1939
        }
1940
1941
        //Also loading if i'm the tutor
1942
        $sql = "SELECT group_id FROM $tbl_group_tutor
1943
                WHERE user_id = '$user_id'";
1944
        $result = Database::query($sql);
1945
        if ($result) {
1946
            while ($row = Database::fetch_array($result)) {
1947
                $groups[] = $row['group_id'];
1948
            }
1949
        }
1950
        if (!empty($groups)) {
1951
            array_filter($groups);
1952
        }
1953
1954
        return $groups;
1955
    }
1956
1957
    /**
1958
     * Check if a user has access to a certain group tool.
1959
     *
1960
     * @param int    $user_id  The user id
1961
     * @param int    $group_id The group iid
1962
     * @param string $tool     The tool to check the access rights. This should be
1963
     *                         one of constants: GROUP_TOOL_DOCUMENTS
1964
     *
1965
     * @return bool true if the given user has access to the given tool in the
1966
     *              given course
1967
     */
1968
    public static function user_has_access($user_id, $group_id, $tool)
1969
    {
1970
        // Admin have access everywhere
1971
        if (api_is_platform_admin()) {
1972
            return true;
1973
        }
1974
1975
        // Course admin also have access to everything
1976
        if (api_is_allowed_to_edit(false, true, true)) {
1977
            return true;
1978
        }
1979
1980
        switch ($tool) {
1981
            case self::GROUP_TOOL_FORUM:
1982
                $key = 'forum_state';
1983
                break;
1984
            case self::GROUP_TOOL_DOCUMENTS:
1985
                $key = 'doc_state';
1986
                break;
1987
            case self::GROUP_TOOL_CALENDAR:
1988
                $key = 'calendar_state';
1989
                break;
1990
            case self::GROUP_TOOL_ANNOUNCEMENT:
1991
                $key = 'announcements_state';
1992
                break;
1993
            case self::GROUP_TOOL_WORK:
1994
                $key = 'work_state';
1995
                break;
1996
            case self::GROUP_TOOL_WIKI:
1997
                $key = 'wiki_state';
1998
                break;
1999
            case self::GROUP_TOOL_CHAT:
2000
                $key = 'chat_state';
2001
                break;
2002
            default:
2003
                return false;
2004
        }
2005
2006
        // Check group properties
2007
        $groupInfo = self::get_group_properties($group_id, true);
2008
2009
        if (empty($groupInfo)) {
2010
            return false;
2011
        }
2012
2013
        if (0 == $groupInfo['status']) {
2014
            return false;
2015
        }
2016
2017
        if (!isset($groupInfo[$key])) {
2018
            return false;
2019
        }
2020
2021
        $status = $groupInfo[$key];
2022
2023
        switch ($status) {
2024
            case self::TOOL_NOT_AVAILABLE:
2025
                return false;
2026
                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...
2027
            case self::TOOL_PUBLIC:
2028
                return true;
2029
                break;
2030
            case self::TOOL_PRIVATE:
2031
                $userIsInGroup = self::isUserInGroup($user_id, $groupInfo);
2032
                if ($userIsInGroup) {
2033
                    return true;
2034
                }
2035
                break;
2036
            case self::TOOL_PRIVATE_BETWEEN_USERS:
2037
                // Only works for announcements for now
2038
                $userIsInGroup = self::isUserInGroup($user_id, $groupInfo);
2039
                if ($userIsInGroup && self::GROUP_TOOL_ANNOUNCEMENT == $tool) {
2040
                    return true;
2041
                }
2042
                break;
2043
        }
2044
2045
        return false;
2046
    }
2047
2048
    /**
2049
     * @param int    $userId
2050
     * @param CGroup $group
2051
     * @param int    $sessionId
2052
     *
2053
     * @return bool
2054
     */
2055
    public static function userHasAccessToBrowse($userId, CGroup $group, $sessionId = 0)
2056
    {
2057
        if (empty($group)) {
2058
            return false;
2059
        }
2060
2061
        if (api_is_platform_admin()) {
2062
            return true;
2063
        }
2064
2065
        if (api_is_allowed_to_edit(false, true, true)) {
2066
            return true;
2067
        }
2068
2069
        if (!empty($sessionId)) {
2070
            if (api_is_coach($sessionId, api_get_course_int_id())) {
2071
                return true;
2072
            }
2073
2074
            if (api_is_drh()) {
2075
                if (SessionManager::isUserSubscribedAsHRM($sessionId, $userId)) {
2076
                    return true;
2077
                }
2078
            }
2079
        }
2080
2081
        if (self::isTutorOfGroup($userId, $group)) {
2082
            return true;
2083
        }
2084
2085
        if (0 == $group->getStatus()) {
2086
            return false;
2087
        }
2088
        $groupId = $group->getIid();
2089
2090
        if (self::user_has_access($userId, $groupId, self::GROUP_TOOL_FORUM) ||
2091
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_DOCUMENTS) ||
2092
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_CALENDAR) ||
2093
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_ANNOUNCEMENT) ||
2094
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_WORK) ||
2095
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_WIKI) ||
2096
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_CHAT)
2097
        ) {
2098
            return true;
2099
        }
2100
        //@todo check group session id
2101
        $groupSessionId = null;
2102
2103
        if (api_is_session_general_coach() && $groupSessionId == $sessionId) {
2104
            return true;
2105
        }
2106
2107
        return false;
2108
    }
2109
2110
    /**
2111
     * Get all groups where a specific user is subscribed.
2112
     *
2113
     * @param int $user_id
2114
     *
2115
     * @return array
2116
     */
2117
    public static function get_user_group_name($user_id)
2118
    {
2119
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
2120
        $table_group = Database::get_course_table(TABLE_GROUP);
2121
        $user_id = intval($user_id);
2122
        $course_id = api_get_course_int_id();
2123
        $sql = "SELECT name
2124
                FROM $table_group g
2125
                INNER JOIN $table_group_user gu
2126
                ON (gu.group_id = g.iid)
2127
                WHERE
2128
                  gu.user_id = $user_id";
2129
        $res = Database::query($sql);
2130
        $groups = [];
2131
        while ($group = Database::fetch_array($res)) {
2132
            $groups[] .= $group['name'];
2133
        }
2134
2135
        return $groups;
2136
    }
2137
2138
    /**
2139
     * Get all groups where a specific user is subscribed.
2140
     *
2141
     * @param int      $user_id
2142
     * @param int      $courseId
2143
     * @param int|null $sessionId
2144
     *
2145
     * @return array
2146
     */
2147
    public static function getAllGroupPerUserSubscription($user_id, $courseId = 0, $sessionId = null)
2148
    {
2149
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
2150
        $table_tutor_user = Database::get_course_table(TABLE_GROUP_TUTOR);
2151
        $table_group = Database::get_course_table(TABLE_GROUP);
2152
        $user_id = (int) $user_id;
2153
        $courseId = empty($courseId) ? api_get_course_int_id() : (int) $courseId;
2154
2155
        $sql = "SELECT DISTINCT g.*
2156
               FROM $table_group g
2157
               LEFT JOIN $table_group_user gu
2158
               ON (gu.group_id = g.iid)
2159
               LEFT JOIN $table_tutor_user tu
2160
               ON (tu.group_id = g.iid)
2161
               WHERE
2162
                  (gu.user_id = $user_id OR tu.user_id = $user_id) ";
2163
2164
        if (null !== $sessionId) {
2165
            $sessionId = (int) $sessionId;
2166
            $sql .= " AND g.session_id = $sessionId ";
2167
        }
2168
2169
        $res = Database::query($sql);
2170
        $groups = [];
2171
        while ($group = Database::fetch_array($res, 'ASSOC')) {
2172
            $groups[] = $group;
2173
        }
2174
2175
        return $groups;
2176
    }
2177
2178
    /**
2179
     * @param CGroup[] $groupList
2180
     * @param int   $category_id
2181
     *
2182
     * @return string
2183
     */
2184
    public static function processGroups($groupList, $category_id = 0)
2185
    {
2186
        $charset = 'UTF-8';
2187
        $category_id = (int) $category_id;
2188
        $totalRegistered = 0;
2189
        $group_data = [];
2190
        $user_info = api_get_user_info();
2191
        $session_id = api_get_session_id();
2192
        $user_id = $user_info['user_id'];
2193
        $hideGroup = api_get_setting('hide_course_group_if_no_tools_available');
2194
        $extraField = new ExtraField('survey');
2195
        $surveyGroupExists = $extraField->get_handler_field_info_by_field_variable('group_id') ? true : false;
2196
        $url = api_get_path(WEB_CODE_PATH).'group/';
2197
2198
        foreach ($groupList as $group) {
2199
            $groupId = $group->getIid();
2200
2201
            // Validation when belongs to a session
2202
            $session_img = '';
2203
            //$session_img = api_get_session_image($group['session_id'], $user_info['status']);
2204
2205
            // All the tutors of this group
2206
            $tutors = $group->getTutors();
2207
            $isMember = self::is_subscribed($user_id, $group);
2208
2209
            // Create a new table-row
2210
            $row = [];
2211
            // Checkbox
2212
            if (api_is_allowed_to_edit(false, true) && count($groupList) > 1) {
2213
                $row[] = $groupId;
2214
            }
2215
2216
            if (self::userHasAccessToBrowse($user_id, $group, $session_id)) {
2217
                // Group name
2218
                $groupNameClass = null;
2219
                if (0 == $group->getStatus()) {
2220
                    $groupNameClass = 'muted';
2221
                }
2222
2223
                $group_name = '<a
2224
                    class="'.$groupNameClass.'"
2225
                    href="group_space.php?'.api_get_cidreq(true, false).'&gid='.$groupId.'">'.
2226
                    Security::remove_XSS($group->getName()).'</a> ';
2227
2228
                $group_name2 = '';
2229
                if (api_get_configuration_value('extra')) {
2230
                    $group_name2 = '<a
2231
                        href="group_space_tracking.php?cid='.api_get_course_int_id().'&gid='.$groupId.'">'.
2232
                        get_lang('suivi_de').''.stripslashes($group->getName()).'</a>';
2233
                }
2234
2235
                /*
2236
                if (!empty($user_id) && !empty($this_group['id_tutor']) && $user_id == $this_group['id_tutor']) {
2237
                    $group_name .= Display::label(get_lang('my supervision'), 'success');
2238
                } elseif ($isMember) {
2239
                    $group_name .= Display::label(get_lang('my group'), 'success');
2240
                }*/
2241
2242
                /*if (api_is_allowed_to_edit() && !empty($this_group['session_name'])) {
2243
                    $group_name .= ' ('.$this_group['session_name'].')';
2244
                }
2245
                $group_name .= $session_img;*/
2246
2247
                $row[] = $group_name.$group_name2.'<br />'.stripslashes(trim($group->getDescription()));
2248
            } else {
2249
                if ('true' === $hideGroup) {
2250
                    continue;
2251
                }
2252
                $row[] = $group->getName().'<br />'.stripslashes(trim($group->getDescription()));
2253
            }
2254
2255
            // Tutor name
2256
            $tutor_info = '';
2257
            if (count($tutors) > 0) {
2258
                foreach ($tutors as $tutorGroup) {
2259
                    $tutor = $tutorGroup->getUser();
2260
                    $username = api_htmlentities(
2261
                        sprintf(get_lang('Login: %s'), $tutor->getUsername()),
2262
                        ENT_QUOTES
2263
                    );
2264
                    if ('true' === api_get_setting('show_email_addresses')) {
2265
                        $tutor_info .= Display::tag(
2266
                            'span',
2267
                            Display::encrypted_mailto_link(
2268
                                $tutor->getEmail(),
2269
                                UserManager::formatUserFullName($tutor)
2270
                            ),
2271
                            ['title' => $username]
2272
                        ).', ';
2273
                    } else {
2274
                        if (api_is_allowed_to_edit()) {
2275
                            $tutor_info .= Display::tag(
2276
                            'span',
2277
                                Display::encrypted_mailto_link(
2278
                                    $tutor->getEmail(),
2279
                                    UserManager::formatUserFullName($tutor)
2280
                                ),
2281
                                ['title' => $username]
2282
                            ).', ';
2283
                        } else {
2284
                            $tutor_info .= Display::tag(
2285
                                'span',
2286
                                    UserManager::formatUserFullName($tutor),
2287
                                ['title' => $username]
2288
                            ).', ';
2289
                        }
2290
                    }
2291
                }
2292
            }
2293
2294
            $tutor_info = api_substr(
2295
                $tutor_info,
2296
                0,
2297
                api_strlen($tutor_info) - 2
2298
            );
2299
            $row[] = $tutor_info;
2300
2301
            // Max number of members in group
2302
            $max_members = self::MEMBER_PER_GROUP_NO_LIMIT == $group->getMaxStudent() ? ' ' : ' / '.$group->getMaxStudent();
2303
            $registeredUsers = self::getStudentsCount($groupId);
2304
            // Number of members in group
2305
            $row[] = $registeredUsers.$max_members;
2306
            $confirmMessage = addslashes(
2307
                api_htmlentities(get_lang('Please confirm your choice'), ENT_QUOTES, $charset)
2308
            );
2309
            // Self-registration / unregistration
2310
            if (!api_is_allowed_to_edit(false, true)) {
2311
                if (self::is_self_registration_allowed($user_id, $group)) {
2312
                    $row[] = '<a
2313
                        class = "btn btn-default"
2314
                        href="group.php?'.api_get_cidreq().'&category='.$category_id.'&action=self_reg&group_id='.$groupId.'"
2315
                        onclick="javascript:if(!confirm('."'".$confirmMessage."'".')) return false;">'.get_lang('register').'</a>';
2316
                } elseif (self::is_self_unregistration_allowed($user_id, $group)) {
2317
                    $row[] = '<a
2318
                        class = "btn btn-default"
2319
                        href="group.php?'.api_get_cidreq().'&category='.$category_id.'&action=self_unreg&group_id='.$groupId.'"
2320
                        onclick="javascript:if(!confirm('."'".$confirmMessage."'".')) return false;">'.get_lang('unregister').'</a>';
2321
                } else {
2322
                    $row[] = '-';
2323
                }
2324
            }
2325
2326
            // @todo fix group session access.
2327
            $groupSessionId = null;
2328
2329
            // Edit-links
2330
            if (api_is_allowed_to_edit(false, true) &&
2331
                !(api_is_session_general_coach() && $groupSessionId != $session_id)
2332
            ) {
2333
                $edit_actions = '<a
2334
                    href="'.$url.'settings.php?'.api_get_cidreq(true, false).'&gid='.$groupId.'"
2335
                    title="'.get_lang('Edit').'">'.
2336
                    Display::return_icon('edit.png', get_lang('Edit this group'), '', ICON_SIZE_SMALL).
2337
                    '</a>&nbsp;';
2338
2339
                if (1 == $group->getStatus()) {
2340
                    $edit_actions .= '<a
2341
                        href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=set_invisible&group_id='.$groupId.'"
2342
                        title="'.get_lang('Hide').'">'.
2343
                        Display::return_icon('visible.png', get_lang('Hide'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2344
                } else {
2345
                    $edit_actions .= '<a
2346
                        href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=set_visible&group_id='.$groupId.'"
2347
                        title="'.get_lang('Show').'">'.
2348
                        Display::return_icon('invisible.png', get_lang('Show'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2349
                }
2350
2351
                $edit_actions .= '<a
2352
                    href="'.$url.'member_settings.php?'.api_get_cidreq(true, false).'&gid='.$groupId.'"
2353
                    title="'.get_lang('Group members').'">'.
2354
                    Display::return_icon('user.png', get_lang('Group members'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2355
2356
                $edit_actions .= '<a
2357
                    href="'.$url.'group_overview.php?action=export&type=xls&'.api_get_cidreq(true, false).'&id='.$groupId.'"
2358
                    title="'.get_lang('Export users list').'">'.
2359
                    Display::return_icon('export_excel.png', get_lang('Export'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2360
2361
                if ($surveyGroupExists) {
2362
                    $edit_actions .= Display::url(
2363
                        Display::return_icon('survey.png', get_lang('ExportSurveyResults'), '', ICON_SIZE_SMALL),
2364
                        $url.'group_overview.php?action=export_surveys&'.api_get_cidreq(true, false).'&id='.$groupId
2365
                    ).'&nbsp;';
2366
                }
2367
                $edit_actions .= '<a
2368
                    href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=fill_one&group_id='.$groupId.'"
2369
                    onclick="javascript: if(!confirm('."'".$confirmMessage."'".')) return false;" title="'.get_lang('FillGroup').'">'.
2370
                    Display::return_icon('fill.png', get_lang('FillGroup'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2371
2372
                $edit_actions .= '<a
2373
                    href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=delete_one&group_id='.$groupId.'"
2374
                    onclick="javascript: if(!confirm('."'".$confirmMessage."'".')) return false;" title="'.get_lang('Delete').'">'.
2375
                    Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2376
2377
                $row[] = $edit_actions;
2378
            }
2379
2380
            /*if (!empty($this_group['nbMember'])) {
2381
                $totalRegistered = $totalRegistered + $this_group['nbMember'];
2382
            }*/
2383
            $group_data[] = $row;
2384
        }
2385
2386
        // If no groups then don't show the table (only for students)
2387
        if (!api_is_allowed_to_edit(true, false)) {
2388
            if (empty($group_data)) {
2389
                return '';
2390
            }
2391
        }
2392
2393
        $table = new SortableTableFromArrayConfig(
2394
            $group_data,
2395
            1,
2396
            20,
2397
            'group_category_'.$category_id
2398
        );
2399
        $table->set_additional_parameters(['category' => $category_id]);
2400
        $column = 0;
2401
        if (api_is_allowed_to_edit(false, true) && count($groupList) > 1) {
2402
            $table->set_header($column++, '', false);
2403
        }
2404
        $table->set_header($column++, get_lang('Groups'));
2405
        $table->set_header($column++, get_lang('Group tutor'));
2406
        $table->set_header($column++, get_lang('Registered'), false);
2407
2408
        if (!api_is_allowed_to_edit(false, true)) {
2409
            // If self-registration allowed
2410
            $table->set_header($column++, get_lang('Registration'), false);
2411
        }
2412
2413
        if (api_is_allowed_to_edit(false, true)) {
2414
            // Only for course administrator
2415
            $table->set_header($column++, get_lang('Edit'), false);
2416
            $form_actions = [];
2417
            $form_actions['fill_selected'] = get_lang('Fill the group randomly with course students');
2418
            $form_actions['empty_selected'] = get_lang('unsubscribe all users');
2419
            $form_actions['delete_selected'] = get_lang('Delete');
2420
            if (count($groupList) > 1) {
2421
                $table->set_form_actions($form_actions, 'group');
2422
            }
2423
        }
2424
2425
        return $table->return_table();
2426
    }
2427
2428
    /**
2429
     * @param array $groupData
2430
     * @param bool  $deleteNotInArray
2431
     *
2432
     * @return array
2433
     */
2434
    public static function importCategoriesAndGroupsFromArray($groupData, $deleteNotInArray = false)
2435
    {
2436
        $result = [];
2437
        $elementsFound = [
2438
            'categories' => [],
2439
            'groups' => [],
2440
        ];
2441
2442
        $courseCode = api_get_course_id();
2443
        $sessionId = api_get_session_id();
2444
        $groupCategories = self::get_categories();
2445
2446
        if (empty($groupCategories)) {
2447
            $result['error'][] = get_lang('Create a category');
2448
2449
            return $result;
2450
        }
2451
2452
        foreach ($groupData as $data) {
2453
            $isCategory = empty($data['group']) ? true : false;
2454
            if ($isCategory) {
2455
                $categoryInfo = self::getCategoryByTitle($data['category']);
2456
                $categoryId = $categoryInfo['iid'];
2457
2458
                if (!empty($categoryInfo)) {
2459
                    // Update
2460
                    self::update_category(
2461
                        $categoryId,
2462
                        $data['category'],
2463
                        $data['description'],
2464
                        $data['doc_state'],
2465
                        $data['work_state'],
2466
                        $data['calendar_state'],
2467
                        $data['announcements_state'],
2468
                        $data['forum_state'],
2469
                        $data['wiki_state'],
2470
                        $data['chat_state'],
2471
                        $data['self_reg_allowed'],
2472
                        $data['self_unreg_allowed'],
2473
                        $data['max_student'],
2474
                        $data['groups_per_user'],
2475
                        $data['document_access']
2476
                    );
2477
                    $data['category_id'] = $categoryId;
2478
                    $result['updated']['category'][] = $data;
2479
                } else {
2480
                    // Add
2481
                    $categoryId = self::create_category(
2482
                        $data['category'],
2483
                        $data['description'],
2484
                        $data['doc_state'],
2485
                        $data['work_state'],
2486
                        $data['calendar_state'],
2487
                        $data['announcements_state'],
2488
                        $data['forum_state'],
2489
                        $data['wiki_state'],
2490
                        $data['chat_state'],
2491
                        $data['self_reg_allowed'],
2492
                        $data['self_unreg_allowed'],
2493
                        $data['max_student'],
2494
                        $data['groups_per_user']
2495
                    );
2496
2497
                    if ($categoryId) {
2498
                        $data['category_id'] = $categoryId;
2499
                        $result['added']['category'][] = $data;
2500
                    }
2501
                }
2502
                $elementsFound['categories'][] = $categoryId;
2503
            } else {
2504
                $groupInfo = self::getGroupByName($data['group']);
2505
                $categoryInfo = [];
2506
                if (isset($data['category'])) {
2507
                    $categoryInfo = self::getCategoryByTitle($data['category']);
2508
                }
2509
                $categoryId = null;
2510
                if (!empty($categoryInfo)) {
2511
                    $categoryId = $categoryInfo['iid'];
2512
                } else {
2513
                    if (!empty($groupCategories) && isset($groupCategories[0])) {
2514
                        $defaultGroupCategory = $groupCategories[0];
2515
                        $categoryId = $defaultGroupCategory['iid'];
2516
                    }
2517
                }
2518
2519
                if (empty($groupInfo)) {
2520
                    // Add
2521
                    $groupId = self::create_group(
2522
                        $data['group'],
2523
                        $categoryId,
2524
                        null,
2525
                        $data['max_student']
2526
                    );
2527
2528
                    if ($groupId) {
2529
                        self::set_group_properties(
2530
                            $groupId,
2531
                            $data['group'],
2532
                            $data['description'],
2533
                            $data['max_student'],
2534
                            $data['doc_state'],
2535
                            $data['work_state'],
2536
                            $data['calendar_state'],
2537
                            $data['announcements_state'],
2538
                            $data['forum_state'],
2539
                            $data['wiki_state'],
2540
                            $data['chat_state'],
2541
                            $data['self_reg_allowed'],
2542
                            $data['self_unreg_allowed'],
2543
                            $categoryId
2544
                        );
2545
                        $data['group_id'] = $groupId;
2546
                        $result['added']['group'][] = $data;
2547
                    }
2548
                    $groupInfo = self::get_group_properties($groupId, true);
2549
                } else {
2550
                    // Update
2551
                    $groupId = $groupInfo['iid'];
2552
                    self::set_group_properties(
2553
                        $groupId,
2554
                        $data['group'],
2555
                        $data['description'],
2556
                        $data['max_student'],
2557
                        $data['doc_state'],
2558
                        $data['work_state'],
2559
                        $data['calendar_state'],
2560
                        $data['announcements_state'],
2561
                        $data['forum_state'],
2562
                        $data['wiki_state'],
2563
                        $data['chat_state'],
2564
                        $data['self_reg_allowed'],
2565
                        $data['self_unreg_allowed'],
2566
                        $categoryId
2567
                    );
2568
2569
                    $data['group_id'] = $groupId;
2570
                    $result['updated']['group'][] = $data;
2571
                    $groupInfo = self::get_group_properties($groupId);
2572
                }
2573
2574
                $students = isset($data['students']) ? explode(',', $data['students']) : [];
2575
                if (!empty($students)) {
2576
                    $studentUserIdList = [];
2577
                    foreach ($students as $student) {
2578
                        $userInfo = api_get_user_info_from_username($student);
2579
2580
                        if (!$userInfo) {
2581
                            continue;
2582
                        }
2583
2584
                        if (!CourseManager::is_user_subscribed_in_course(
2585
                                $userInfo['user_id'],
2586
                                $courseCode,
2587
                                !empty($sessionId),
2588
                                $sessionId
2589
                            )
2590
                        ) {
2591
                            Display::addFlash(
2592
                                Display::return_message(
2593
                                    sprintf(
2594
                                        get_lang('Student %s is no subscribed to this course'),
2595
                                        $userInfo['complete_name']
2596
                                    ),
2597
                                    'warning'
2598
                                )
2599
                            );
2600
                            continue;
2601
                        }
2602
2603
                        $studentUserIdList[] = $userInfo['user_id'];
2604
                    }
2605
                    self::subscribeUsers($studentUserIdList, api_get_group_entity($groupInfo['iid']));
2606
                }
2607
2608
                $tutors = isset($data['tutors']) ? explode(',', $data['tutors']) : [];
2609
                if (!empty($tutors)) {
2610
                    $tutorIdList = [];
2611
                    foreach ($tutors as $tutor) {
2612
                        $userInfo = api_get_user_info_from_username($tutor);
2613
2614
                        if (!$userInfo) {
2615
                            continue;
2616
                        }
2617
2618
                        if (!CourseManager::is_user_subscribed_in_course(
2619
                                $userInfo['user_id'],
2620
                                $courseCode,
2621
                                !empty($sessionId),
2622
                                $sessionId
2623
                            )
2624
                        ) {
2625
                            Display::addFlash(
2626
                                Display::return_message(
2627
                                    sprintf(get_lang('Tutor %s is no subscribed to this course'), $userInfo['complete_name']),
2628
                                    'warning'
2629
                                )
2630
                            );
2631
2632
                            continue;
2633
                        }
2634
2635
                        $tutorIdList[] = $userInfo['user_id'];
2636
                    }
2637
                    self::subscribeTutors($tutorIdList, api_get_group_entity($groupInfo['iid']));
2638
                }
2639
2640
                $elementsFound['groups'][] = $groupId;
2641
            }
2642
        }
2643
2644
        if ($deleteNotInArray) {
2645
            // Check categories
2646
            $categories = self::get_categories();
2647
            foreach ($categories as $category) {
2648
                if (!in_array($category['iid'], $elementsFound['categories'])) {
2649
                    self::delete_category($category['iid']);
2650
                    $category['category'] = $category['title'];
2651
                    $result['deleted']['category'][] = $category;
2652
                }
2653
            }
2654
2655
            $groups = self::get_groups();
2656
            foreach ($groups as $group) {
2657
                if (!in_array($group->getIid(), $elementsFound['groups'])) {
2658
                    self::deleteGroup($group);
2659
                    $result['deleted']['group'][] = $group;
2660
                }
2661
            }
2662
        }
2663
2664
        return $result;
2665
    }
2666
2667
    /**
2668
     * Export all categories/group from a course to an array.
2669
     * This function works only in a context of a course.
2670
     *
2671
     * @param int  $groupId
2672
     * @param bool $loadUsers
2673
     *
2674
     * @return array
2675
     */
2676
    public static function exportCategoriesAndGroupsToArray($groupId = null, $loadUsers = false)
2677
    {
2678
        $data = [];
2679
        $data[] = [
2680
            'category',
2681
            'group',
2682
            'description',
2683
            'announcements_state',
2684
            'calendar_state',
2685
            'chat_state',
2686
            'doc_state',
2687
            'forum_state',
2688
            'work_state',
2689
            'wiki_state',
2690
            'max_student',
2691
            'self_reg_allowed',
2692
            'self_unreg_allowed',
2693
            'groups_per_user',
2694
        ];
2695
2696
        $count = 1;
2697
2698
        if ($loadUsers) {
2699
            $data[0][] = 'students';
2700
            $data[0][] = 'tutors';
2701
        }
2702
2703
        if (false == $loadUsers) {
2704
            $categories = self::get_categories();
2705
2706
            foreach ($categories as $categoryInfo) {
2707
                $data[$count] = [
2708
                    $categoryInfo['title'],
2709
                    null,
2710
                    $categoryInfo['description'],
2711
                    $categoryInfo['announcements_state'],
2712
                    $categoryInfo['calendar_state'],
2713
                    $categoryInfo['chat_state'],
2714
                    $categoryInfo['doc_state'],
2715
                    $categoryInfo['forum_state'],
2716
                    $categoryInfo['work_state'],
2717
                    $categoryInfo['wiki_state'],
2718
                    $categoryInfo['max_student'],
2719
                    $categoryInfo['self_reg_allowed'],
2720
                    $categoryInfo['self_unreg_allowed'],
2721
                    $categoryInfo['groups_per_user'],
2722
                ];
2723
                $count++;
2724
            }
2725
        }
2726
2727
        $groups = self::get_group_list();
2728
        foreach ($groups as $groupInfo) {
2729
            $groupId = $groupInfo['iid'];
2730
            $categoryTitle = null;
2731
            $categoryInfo = [];
2732
            if (isset($groupInfo['category'])) {
2733
                $categoryInfo = self::get_category($groupInfo['category']);
2734
            }
2735
2736
            $groupSettings = self::get_group_properties($groupId);
2737
            if (!empty($categoryInfo)) {
2738
                $categoryTitle = $categoryInfo['title'];
2739
            }
2740
2741
            $users = self::getStudents($groupId);
2742
            $userList = [];
2743
            foreach ($users as $user) {
2744
                $user = api_get_user_info($user['user_id']);
2745
                $userList[] = $user['username'];
2746
            }
2747
2748
            $tutors = self::getTutors($groupInfo);
2749
            $tutorList = [];
2750
            foreach ($tutors as $user) {
2751
                $user = api_get_user_info($user['user_id']);
2752
                $tutorList[] = $user['username'];
2753
            }
2754
2755
            $userListToString = null;
2756
            if (!empty($userList)) {
2757
                $userListToString = implode(',', $userList);
2758
            }
2759
2760
            $tutorListToString = null;
2761
            if (!empty($tutorList)) {
2762
                $tutorListToString = implode(',', $tutorList);
2763
            }
2764
2765
            $data[$count] = [
2766
                $categoryTitle,
2767
                $groupSettings['name'],
2768
                $groupSettings['description'],
2769
                $groupSettings['announcements_state'],
2770
                $groupSettings['calendar_state'],
2771
                $groupSettings['chat_state'],
2772
                $groupSettings['doc_state'],
2773
                $groupSettings['forum_state'],
2774
                $groupSettings['work_state'],
2775
                $groupSettings['wiki_state'],
2776
                $groupSettings['maximum_number_of_students'],
2777
                $groupSettings['self_registration_allowed'],
2778
                $groupSettings['self_unregistration_allowed'],
2779
                null,
2780
            ];
2781
2782
            if ($loadUsers) {
2783
                $data[$count][] = $userListToString;
2784
                $data[$count][] = $tutorListToString;
2785
            }
2786
2787
            if (!empty($groupId)) {
2788
                if ($groupId == $groupInfo['iid']) {
2789
                    break;
2790
                }
2791
            }
2792
            $count++;
2793
        }
2794
2795
        return $data;
2796
    }
2797
2798
    /**
2799
     * @param string $default
2800
     */
2801
    public static function getSettingBar($default)
2802
    {
2803
        $activeSettings = null;
2804
        $activeTutor = null;
2805
        $activeMember = null;
2806
2807
        switch ($default) {
2808
            case 'settings':
2809
                $activeSettings = 'active';
2810
                break;
2811
            case 'tutor':
2812
                $activeTutor = 'active';
2813
                break;
2814
            case 'member':
2815
                $activeMember = 'active';
2816
                break;
2817
        }
2818
2819
        $url = api_get_path(WEB_CODE_PATH).'group/%s?'.api_get_cidreq();
2820
2821
        echo '
2822
            <ul class="nav nav-tabs">
2823
                <li class="nav-item">
2824
                    <a class="nav-link '.$activeSettings.'" id="group_settings_tab" href="'.sprintf($url, 'settings.php').'">
2825
                    '.Display::return_icon('settings.png').' '.get_lang('Settings').'
2826
                    </a>
2827
                </li>
2828
                <li class="nav-item">
2829
                    <a class="nav-link '.$activeMember.'" id="group_members_tab" href="'.sprintf($url, 'member_settings.php').'">
2830
                    '.Display::return_icon('user.png').' '.get_lang('Group members').'</a>
2831
                </li>
2832
                <li class="nav-item">
2833
                    <a class="nav-link  '.$activeTutor.'" id="group_tutors_tab" href="'.sprintf($url, 'tutor_settings.php').'">
2834
                    '.Display::return_icon('teacher.png').' '.get_lang('Group tutors').'
2835
                    </a>
2836
                </li>
2837
            </ul>';
2838
    }
2839
2840
    public static function groupOverview($group, $url)
2841
    {
2842
        $groupId = $group['iid'];
2843
        $content = '<li>';
2844
        $content .= Display::tag(
2845
            'h3',
2846
            Display::url(
2847
                Security::remove_XSS($group['name']),
2848
                $url.'&gidReq='.$groupId
2849
            )
2850
        );
2851
        $users = self::getTutors($group);
2852
        if (!empty($users)) {
2853
            $content .= '<ul>';
2854
            $content .= "<li>".Display::tag('h4', get_lang('Tutors'))."</li><ul>";
2855
            foreach ($users as $user) {
2856
                $userInfo = api_get_user_info($user['user_id']);
2857
                $content .= '<li title="'.$userInfo['username'].'">'.
2858
                    $userInfo['complete_name_with_username'].
2859
                    '</li>';
2860
            }
2861
            $content .= '</ul>';
2862
            $content .= '</ul>';
2863
        }
2864
2865
        $users = self::getStudents($group['iid']);
2866
        if (!empty($users)) {
2867
            $content .= '<ul>';
2868
            $content .= "<li>".Display::tag('h4', get_lang('Students'))."</li><ul>";
2869
            foreach ($users as $user) {
2870
                $userInfo = api_get_user_info($user['user_id']);
2871
                $content .= '<li title="'.$userInfo['username'].'">'.
2872
                    $userInfo['complete_name_with_username'].
2873
                    '</li>';
2874
            }
2875
            $content .= '</ul>';
2876
            $content .= '</ul>';
2877
        }
2878
        $content .= '</li>';
2879
2880
        return $content;
2881
    }
2882
2883
    /**
2884
     * @param array  $courseInfo
2885
     * @param string $keyword
2886
     *
2887
     * @return string
2888
     */
2889
    public static function getOverview($courseInfo, $keyword = '')
2890
    {
2891
        $content = null;
2892
        $categories = self::get_categories();
2893
        $url = api_get_path(WEB_CODE_PATH).'group/group_space.php?'.api_get_cidreq(true, false);
2894
        if (!empty($categories)) {
2895
            foreach ($categories as $category) {
2896
                if ('true' === api_get_setting('allow_group_categories')) {
2897
                    $content .= '<h2>'.$category['title'].'</h2>';
2898
                }
2899
                $groups = self::get_group_list($category['iid'], $courseInfo, null, 0, false, $keyword);
2900
                $content .= '<ul>';
2901
                if (!empty($groups)) {
2902
                    foreach ($groups as $group) {
2903
                        $content .= self::groupOverview($group, $url);
2904
                    }
2905
                }
2906
                $content .= '</ul>';
2907
            }
2908
        }
2909
2910
        // Check groups with no categories.
2911
        $groups = self::get_group_list(null, api_get_course_info(), null, api_get_session_id(), false, true);
2912
        if (!empty($groups)) {
2913
            $content .= '<h2>'.get_lang('NoCategorySelected').'</h2>';
2914
            $content .= '<ul>';
2915
            foreach ($groups as $group) {
2916
                if (!empty($group['category_id'])) {
2917
                    continue;
2918
                }
2919
                $content .= self::groupOverview($group, $url);
2920
            }
2921
            $content .= '</ul>';
2922
        }
2923
2924
        return $content;
2925
    }
2926
2927
    /**
2928
     * Returns the search form.
2929
     *
2930
     * @return string
2931
     */
2932
    public static function getSearchForm()
2933
    {
2934
        $url = api_get_path(WEB_CODE_PATH).'group/group_overview.php?'.api_get_cidreq();
2935
        $form = new FormValidator(
2936
            'search_groups',
2937
            'get',
2938
            $url,
2939
            null,
2940
            ['class' => 'form-search'],
2941
            FormValidator::LAYOUT_INLINE
2942
        );
2943
        $form->addElement('text', 'keyword');
2944
        $form->addCourseHiddenParams();
2945
        $form->addButtonSearch();
2946
2947
        return $form->toHtml();
2948
    }
2949
2950
    public static function setStatus(CGroup $group, $status)
2951
    {
2952
        $group->setStatus($status);
2953
        $em = Database::getManager();
2954
        $em->persist($group);
2955
        $em->flush();
2956
    }
2957
2958
    public static function setVisible(CGroup $group)
2959
    {
2960
        self::setStatus($group, true);
2961
    }
2962
2963
    public static function setInvisible(CGroup $group)
2964
    {
2965
        self::setStatus($group, false);
2966
    }
2967
2968
    /**
2969
     * @param int   $userId
2970
     * @param int   $courseId
2971
     * @param CGroup  $group
2972
     * @param array $documentInfoToBeCheck
2973
     * @param bool  $blockPage
2974
     *
2975
     * @return bool
2976
     */
2977
    public static function allowUploadEditDocument(
2978
        $userId,
2979
        $courseId,
2980
        CGroup $group,
2981
        $documentInfoToBeCheck = null,
2982
        $blockPage = false
2983
    ) {
2984
        // Admin and teachers can make any change no matter what
2985
        if (api_is_platform_admin() || api_is_allowed_to_edit(false, true)) {
2986
            return true;
2987
        }
2988
2989
        if (empty($group)) {
2990
            if ($blockPage) {
2991
                api_not_allowed(true);
2992
            }
2993
2994
            return false;
2995
        }
2996
2997
        // Tutor can also make any change
2998
        $isTutor = self::isTutorOfGroup($userId, $group);
2999
3000
        if ($isTutor) {
3001
            return true;
3002
        }
3003
3004
        // Just in case also check if document in group is available
3005
        if (0 == $group->getDocState()) {
3006
            if ($blockPage) {
3007
                api_not_allowed(true);
3008
            }
3009
3010
            return false;
3011
        }
3012
3013
        // Default behaviour
3014
        $documentAccess = self::DOCUMENT_MODE_SHARE;
3015
3016
        // Check category document access
3017
        /*$allowCategoryGroupDocumentAccess = api_get_configuration_value('group_category_document_access');
3018
        if ($allowCategoryGroupDocumentAccess) {
3019
            $category = GroupManager::get_category_from_group($groupInfo['iid']);
3020
            if (!empty($category) && isset($category['document_access'])) {
3021
                $documentAccess = (int) $category['document_access'];
3022
            }
3023
        }*/
3024
3025
        // Check group document access
3026
        $allow = api_get_configuration_value('group_document_access');
3027
        if ($allow) {
3028
            $documentAccess = (int) $group->getDocumentAccess();
3029
        }
3030
3031
        // Check access for students
3032
        $result = false;
3033
        switch ($documentAccess) {
3034
            case self::DOCUMENT_MODE_SHARE:
3035
                // Default chamilo behaviour
3036
                // Student can upload his own content, cannot modify another content.
3037
                $isMember = self::is_subscribed($userId, $group);
3038
                if ($isMember) {
3039
                    // No document to check, allow access to document feature.
3040
                    if (empty($documentInfoToBeCheck)) {
3041
                        $result = true;
3042
                    } else {
3043
                        // Member can only edit his own document
3044
                        $authorId = isset($documentInfoToBeCheck['insert_user_id']) ? $documentInfoToBeCheck['insert_user_id'] : 0;
3045
                        // If "insert_user_id" is not set, check the author id from c_item_property
3046
                        if (empty($authorId) && isset($documentInfoToBeCheck['id'])) {
3047
                            // @todo use resources
3048
                            /*$documentInfo = api_get_item_property_info(
3049
                                $courseId,
3050
                                'document',
3051
                                $documentInfoToBeCheck['id'],
3052
                                0
3053
                            );
3054
                            // Try to find this document in the session
3055
                            if (!empty($sessionId)) {
3056
                                $documentInfo = api_get_item_property_info(
3057
                                    $courseId,
3058
                                    'document',
3059
                                    $documentInfoToBeCheck['id'],
3060
                                    api_get_session_id()
3061
                                );
3062
                            }
3063
3064
                            if (!empty($documentInfo) && isset($documentInfo['insert_user_id'])) {
3065
                                $authorId = $documentInfo['insert_user_id'];
3066
                            }*/
3067
                        }
3068
3069
                        if ($authorId == $userId) {
3070
                            $result = true;
3071
                        }
3072
                    }
3073
                }
3074
                break;
3075
            case self::DOCUMENT_MODE_READ_ONLY:
3076
                // Student cannot upload content, cannot modify another content.
3077
                $result = false;
3078
                break;
3079
            case self::DOCUMENT_MODE_COLLABORATION:
3080
                // Student can upload content, can modify another content.
3081
                $isMember = self::is_subscribed($userId, $group);
3082
                if ($isMember) {
3083
                    $result = true;
3084
                }
3085
                break;
3086
        }
3087
3088
        if ($blockPage && false == $result) {
3089
            api_not_allowed(true);
3090
        }
3091
3092
        return $result;
3093
    }
3094
}
3095