Passed
Push — master ( f437d8...92f70a )
by Julito
10:14
created

GroupManager::get_users()   B

Complexity

Conditions 11
Paths 96

Size

Total Lines 61
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 36
nc 96
nop 8
dl 0
loc 61
rs 7.3166
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CourseBundle\Entity\CGroupRelUser;
5
6
/**
7
 * This library contains some functions for group-management.
8
 *
9
 * @author Bart Mollet
10
 *
11
 * @package chamilo.library
12
 *
13
 * @todo Add $course_code parameter to all functions. So this GroupManager can
14
 * be used outside a session.
15
 */
16
class GroupManager
17
{
18
    /* VIRTUAL_COURSE_CATEGORY:
19
    in this category groups are created based on the virtual course of a course*/
20
    public const VIRTUAL_COURSE_CATEGORY = 1;
21
22
    /* DEFAULT_GROUP_CATEGORY:
23
    When group categories aren't available (platform-setting),
24
    all groups are created in this 'dummy'-category*/
25
    public const DEFAULT_GROUP_CATEGORY = 2;
26
27
    /**
28
     * infinite.
29
     */
30
    public const INFINITE = 99999;
31
    /**
32
     * No limit on the number of users in a group.
33
     */
34
    public const MEMBER_PER_GROUP_NO_LIMIT = 0;
35
    /**
36
     * No limit on the number of groups per user.
37
     */
38
    public const GROUP_PER_MEMBER_NO_LIMIT = 0;
39
    /**
40
     * The tools of a group can have 3 states
41
     * - not available
42
     * - public
43
     * - private.
44
     */
45
    public const TOOL_NOT_AVAILABLE = 0;
46
    public const TOOL_PUBLIC = 1;
47
    public const TOOL_PRIVATE = 2;
48
49
    /**
50
     * Constants for the available group tools.
51
     */
52
    public const GROUP_TOOL_FORUM = 0;
53
    public const GROUP_TOOL_DOCUMENTS = 1;
54
    public const GROUP_TOOL_CALENDAR = 2;
55
    public const GROUP_TOOL_ANNOUNCEMENT = 3;
56
    public const GROUP_TOOL_WORK = 4;
57
    public const GROUP_TOOL_WIKI = 5;
58
    public const GROUP_TOOL_CHAT = 6;
59
60
    public const DOCUMENT_MODE_SHARE = 0; // By default
61
    public const DOCUMENT_MODE_READ_ONLY = 1;
62
    public const DOCUMENT_MODE_COLLABORATION = 2;
63
64
    /**
65
     * GroupManager constructor.
66
     */
67
    public function __construct()
68
    {
69
    }
70
71
    /**
72
     * @param int $courseId
73
     *
74
     * @return array
75
     */
76
    public static function get_groups($courseId = 0)
77
    {
78
        $table_group = Database::get_course_table(TABLE_GROUP);
79
        $courseId = !empty($courseId) ? (int) $courseId : api_get_course_int_id();
80
81
        $sql = "SELECT * FROM $table_group WHERE c_id = $courseId  ";
82
        $result = Database::query($sql);
83
84
        return Database::store_result($result, 'ASSOC');
85
    }
86
87
    /**
88
     * Get list of groups for current course.
89
     *
90
     * @param int   $categoryId  The id of the category from which the groups are
91
     *                           requested
92
     * @param array $course_info Default is current course
93
     * @param int   $status      group status
94
     * @param int   $sessionId
95
     * @param bool  $getCount
96
     *
97
     * @return array an array with all information about the groups
98
     */
99
    public static function get_group_list(
100
        $categoryId = null,
101
        $course_info = [],
102
        $status = null,
103
        $sessionId = 0,
104
        $getCount = false
105
    ) {
106
        $course_info = empty($course_info) ? api_get_course_info() : $course_info;
107
        if (empty($course_info)) {
108
            return [];
109
        }
110
        $sessionId = empty($sessionId) ? api_get_session_id() : (int) $sessionId;
111
        $course_id = $course_info['real_id'];
112
        $table_group = Database::get_course_table(TABLE_GROUP);
113
114
        $select = ' g.id,
115
                    g.iid,
116
                    g.name,
117
                    g.description,
118
                    g.category_id,
119
                    g.max_student maximum_number_of_members,
120
                    g.secret_directory,
121
                    g.self_registration_allowed,
122
                    g.self_unregistration_allowed,
123
                    g.session_id,
124
                    g.status';
125
        if ($getCount) {
126
            $select = ' DISTINCT count(g.iid) as count ';
127
        }
128
129
        $sql = "SELECT 
130
                $select    
131
                FROM $table_group g
132
                WHERE 1 = 1 ";
133
134
        if (!is_null($categoryId)) {
135
            $sql .= " AND g.category_id = '".intval($categoryId)."' ";
136
            $session_condition = api_get_session_condition($sessionId);
137
            if (!empty($session_condition)) {
138
                $sql .= $session_condition;
139
            }
140
        } else {
141
            $session_condition = api_get_session_condition($sessionId, true);
142
        }
143
144
        if (!is_null($status)) {
145
            $sql .= " AND g.status = '".intval($status)."' ";
146
        }
147
148
        $sql .= " AND g.c_id = $course_id ";
149
150
        if (!empty($session_condition)) {
151
            $sql .= $session_condition;
152
        }
153
        $sql .= ' ORDER BY UPPER(g.name)';
154
155
        $result = Database::query($sql);
156
157
        if ($getCount) {
158
            $row = Database::fetch_array($result);
159
160
            return $row['count'];
161
        }
162
163
        $groups = [];
164
        while ($thisGroup = Database::fetch_array($result)) {
165
            $thisGroup['number_of_members'] = count(self::get_subscribed_users($thisGroup));
166
            if ($thisGroup['session_id'] != 0) {
167
                $sql = 'SELECT name FROM '.Database::get_main_table(TABLE_MAIN_SESSION).'
168
                        WHERE id='.$thisGroup['session_id'];
169
                $rs_session = Database::query($sql);
170
                if (Database::num_rows($rs_session) > 0) {
171
                    $thisGroup['session_name'] = Database::result($rs_session, 0, 0);
172
                }
173
            }
174
            $groups[] = $thisGroup;
175
        }
176
177
        return $groups;
178
    }
179
180
    /**
181
     * Create a group.
182
     *
183
     * @param string $name        The name for this group
184
     * @param int    $category_id
185
     * @param int    $tutor       The user-id of the group's tutor
186
     * @param int    $places      How many people can subscribe to the new group
187
     *
188
     * @return int
189
     */
190
    public static function create_group($name, $category_id, $tutor, $places)
191
    {
192
        $_course = api_get_course_info();
193
        $session_id = api_get_session_id();
194
        $course_id = $_course['real_id'];
195
        $currentCourseRepository = $_course['path'];
196
        $category = self::get_category($category_id);
197
        $places = (int) $places;
198
199
        // Default values
200
        $docState = self::TOOL_PRIVATE;
201
        $calendarState = self::TOOL_PRIVATE;
202
        $workState = self::TOOL_PRIVATE;
203
        $anonuncementState = self::TOOL_PRIVATE;
204
        $forumState = self::TOOL_PRIVATE;
205
        $wikiState = self::TOOL_PRIVATE;
206
        $chatState = self::TOOL_PRIVATE;
207
        $selfRegAllowed = 0;
208
        $selfUnregAllwoed = 0;
209
        $documentAccess = 0;
210
211
        if ($category) {
212
            if ($places == 0) {
213
                //if the amount of users per group is not filled in, use the setting from the category
214
                $places = $category['max_student'];
215
            } else {
216
                if ($places > $category['max_student'] && $category['max_student'] != 0) {
217
                    $places = $category['max_student'];
218
                }
219
            }
220
            $docState = $category['doc_state'];
221
            $calendarState = $category['calendar_state'];
222
            $workState = $category['work_state'];
223
            $anonuncementState = $category['announcements_state'];
224
            $forumState = $category['forum_state'];
225
            $wikiState = $category['wiki_state'];
226
            $chatState = $category['chat_state'];
227
            $selfRegAllowed = $category['self_reg_allowed'];
228
            $selfUnregAllwoed = $category['self_unreg_allowed'];
229
            $documentAccess = isset($category['document_access']) ? $category['document_access'] : 0;
230
        }
231
232
        $allowDocumentAccess = api_get_configuration_value('group_document_access');
233
        $documentCondition = '';
234
        if ($allowDocumentAccess) {
235
            $documentAccess = (int) $documentAccess;
236
            $documentCondition = " document_access = $documentAccess, ";
237
        }
238
239
        $table_group = Database::get_course_table(TABLE_GROUP);
240
        $sql = "INSERT INTO $table_group SET
241
                c_id = $course_id,
242
                status = 1,
243
                category_id='".Database::escape_string($category_id)."',
244
                max_student = '".$places."',
245
                doc_state = '".$docState."',
246
                calendar_state = '".$calendarState."',
247
                work_state = '".$workState."',
248
                announcements_state = '".$anonuncementState."',
249
                forum_state = '".$forumState."',
250
                wiki_state = '".$wikiState."',
251
                chat_state = '".$chatState."',
252
                self_registration_allowed = '".$selfRegAllowed."',
253
                self_unregistration_allowed = '".$selfUnregAllwoed."',
254
                $documentCondition
255
                session_id='".$session_id."'";
256
257
        Database::query($sql);
258
        $lastId = Database::insert_id();
259
260
        if ($lastId) {
261
            $sql = "UPDATE $table_group SET id = iid WHERE iid = $lastId";
262
            Database::query($sql);
263
264
            $desired_dir_name = '/'.api_replace_dangerous_char($name).'_groupdocs';
265
            $my_path = api_get_path(SYS_COURSE_PATH).$currentCourseRepository.'/document';
266
267
            $newFolderData = create_unexisting_directory(
268
                $_course,
269
                api_get_user_id(),
270
                $session_id,
271
                $lastId,
272
                null,
273
                $my_path,
274
                $desired_dir_name,
275
                null,
276
                1
277
            );
278
279
            $unique_name = $newFolderData->getPath();
280
281
            /* Stores the directory path into the group table */
282
            $sql = "UPDATE $table_group SET
283
                        name = '".Database::escape_string($name)."',
284
                        secret_directory = '".$unique_name."'
285
                    WHERE c_id = $course_id AND id ='".$lastId."'";
286
287
            Database::query($sql);
288
289
            // create a forum if needed
290
            if ($forumState >= 0) {
291
                require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
292
293
                $forum_categories = get_forum_categories();
294
                if (empty($forum_categories)) {
295
                    $categoryParam = [
296
                        'forum_category_title' => get_lang('GroupForums'),
297
                    ];
298
                    store_forumcategory($categoryParam);
299
                    $forum_categories = get_forum_categories();
300
                }
301
302
                $counter = 0;
303
                foreach ($forum_categories as $key => $value) {
304
                    if ($counter == 0) {
305
                        $forum_category_id = $key;
306
                    }
307
                    $counter++;
308
                }
309
                // A sanity check.
310
                if (empty($forum_category_id)) {
311
                    $forum_category_id = 0;
312
                }
313
314
                $values = [];
315
                $values['forum_title'] = $name;
316
                $values['group_id'] = $lastId;
317
                $values['forum_category'] = $forum_category_id;
318
                $values['allow_anonymous_group']['allow_anonymous'] = 0;
319
                $values['students_can_edit_group']['students_can_edit'] = 0;
320
                $values['approval_direct_group']['approval_direct'] = 0;
321
                $values['allow_attachments_group']['allow_attachments'] = 1;
322
                $values['allow_new_threads_group']['allow_new_threads'] = 1;
323
                $values['default_view_type_group']['default_view_type'] = api_get_setting('default_forum_view');
324
                $values['group_forum'] = $lastId;
325
                if ($forumState == '1') {
326
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'public';
327
                } elseif ($forumState == '2') {
328
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'private';
329
                } elseif ($forumState == '0') {
330
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'unavailable';
331
                }
332
                store_forum($values);
333
            }
334
        }
335
336
        return $lastId;
337
    }
338
339
    /**
340
     * Create subgroups.
341
     * This function creates new groups based on an existing group. It will
342
     * create the specified number of groups and fill those groups with users
343
     * from the base group.
344
     *
345
     * @param int $group_id         the group from which subgroups have to be created
346
     * @param int $number_of_groups The number of groups that have to be created
347
     */
348
    public static function create_subgroups($group_id, $number_of_groups)
349
    {
350
        $courseId = api_get_course_int_id();
351
        $table_group = Database::get_course_table(TABLE_GROUP);
352
        $category_id = self::create_category(
353
            get_lang('Subgroups'),
354
            '',
355
            self::TOOL_PRIVATE,
356
            self::TOOL_PRIVATE,
357
            0,
358
            0,
359
            1,
360
            1
361
        );
362
        $users = self::get_users($group_id);
363
        $group_ids = [];
364
365
        for ($group_nr = 1; $group_nr <= $number_of_groups; $group_nr++) {
366
            $group_ids[] = self::create_group(
367
                get_lang('Subgroup').' '.$group_nr,
368
                $category_id,
369
                0,
370
                0
371
            );
372
        }
373
374
        $members = [];
375
        foreach ($users as $index => $user_id) {
376
            $groupId = $group_ids[$index % $number_of_groups];
377
            $groupInfo = self::get_group_properties($groupId);
378
            self::subscribe_users(
379
                $user_id,
380
                $groupInfo
381
            );
382
            $members[$group_ids[$groupId]]++;
383
        }
384
385
        foreach ($members as $group_id => $places) {
386
            $sql = "UPDATE $table_group SET max_student = $places
387
                    WHERE c_id = $courseId  AND id = $group_id";
388
            Database::query($sql);
389
        }
390
    }
391
392
    /**
393
     * Create a group for every class subscribed to the current course.
394
     *
395
     * @param int $categoryId The category in which the groups should be created
396
     *
397
     * @return array
398
     */
399
    public static function create_class_groups($categoryId)
400
    {
401
        $options['where'] = [' usergroup.course_id = ? ' => api_get_course_int_id()];
402
        $obj = new UserGroup();
403
        $classes = $obj->getUserGroupInCourse($options);
404
        $group_ids = [];
405
406
        foreach ($classes as $class) {
407
            $userList = $obj->get_users_by_usergroup($class['id']);
408
            $groupId = self::create_group(
409
                $class['name'],
410
                $categoryId,
411
                0,
412
                null
413
            );
414
415
            if ($groupId) {
416
                $groupInfo = self::get_group_properties($groupId);
417
                self::subscribe_users($userList, $groupInfo);
418
                $group_ids[] = $groupId;
419
            }
420
        }
421
422
        return $group_ids;
423
    }
424
425
    /**
426
     * Deletes groups and their data.
427
     *
428
     * @author Christophe Gesche <[email protected]>
429
     * @author Hugues Peeters <[email protected]>
430
     * @author Bart Mollet
431
     *
432
     * @param array  $groupInfo   iid
433
     * @param string $course_code Default is current course
434
     *
435
     * @return int - number of groups deleted
436
     */
437
    public static function deleteGroup($groupInfo, $course_code = null)
438
    {
439
        if (empty($groupInfo['iid'])) {
440
            return false;
441
        }
442
        $course_info = api_get_course_info($course_code);
443
        if (empty($course_info)) {
444
            return false;
445
        }
446
447
        $course_id = $course_info['real_id'];
448
449
        // Database table definitions
450
        $em = Database::getManager();
451
        $group_table = Database::get_course_table(TABLE_GROUP);
452
        $forum_table = Database::get_course_table(TABLE_FORUM);
453
        $groupInfo = self::get_group_properties($groupInfo['iid'], true);
454
        if ($groupInfo) {
455
            $groupIid = $groupInfo['iid'];
456
            $groupId = $groupInfo['id'];
457
            // Unsubscribe all users
458
            self::unsubscribe_all_users($groupInfo);
459
            self::unsubscribe_all_tutors($groupInfo);
460
461
            if (!empty($groupInfo['secret_directory'])) {
462
                $directory = $groupInfo['secret_directory'];
463
                // move group-documents to garbage
464
                $source_directory = api_get_path(SYS_COURSE_PATH).$course_info['path']."/document".$directory;
465
                // File to renamed
466
                $destination_dir = api_get_path(SYS_COURSE_PATH).$course_info['path']."/document".$directory.'_DELETED_'.$groupInfo['id'];
467
                //Deleting from document tool
468
                DocumentManager::delete_document(
469
                    $course_info,
470
                    $directory,
471
                    $source_directory
472
                );
473
474
                if (file_exists($source_directory)) {
475
                    if (api_get_setting('permanently_remove_deleted_files') === 'true') {
476
                        // Delete
477
                        my_delete($source_directory);
478
                    } else {
479
                        // Rename
480
                        rename($source_directory, $destination_dir);
481
                    }
482
                }
483
            }
484
485
            $em
486
                ->createQuery(
487
                    'DELETE FROM ChamiloCourseBundle:CForumForum f WHERE f.cId = :course AND f.forumOfGroup = :group'
488
                )
489
                ->execute(['course' => $course_id, 'group' => $groupId]);
490
491
            // Delete item properties of this group.
492
            // to_group_id is related to c_group_info.iid
493
            $em
494
                ->createQuery(
495
                    'DELETE FROM ChamiloCourseBundle:CItemProperty ci WHERE ci.course = :course AND ci.group = :group'
496
                )
497
                ->execute(['course' => $course_id, 'group' => $groupId]);
498
499
            // delete the groups
500
            $em
501
                ->createQuery(
502
                    'DELETE FROM ChamiloCourseBundle:CGroupInfo g WHERE g.course = :course AND g.iid = :id'
503
                )
504
                ->execute(['course' => $course_id, 'id' => $groupIid]);
505
        }
506
507
        return true;
508
    }
509
510
    /**
511
     * Function needed only when deleting a course, in order to be sure that all group ids are deleted.
512
     *
513
     * @param int $courseId
514
     *
515
     * @return bool
516
     */
517
    public static function deleteAllGroupsFromCourse($courseId)
518
    {
519
        $courseId = (int) $courseId;
520
521
        if (empty($courseId)) {
522
            return false;
523
        }
524
525
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
526
        $sql = "SELECT iid FROM $table
527
                WHERE c_id = $courseId ";
528
        Database::query($sql);
529
530
        // Database table definitions
531
        $table = Database::get_course_table(TABLE_GROUP_USER);
532
        $sql = "DELETE FROM $table
533
                WHERE c_id = $courseId";
534
        Database::query($sql);
535
536
        $table = Database::get_course_table(TABLE_GROUP_TUTOR);
537
        $sql = "DELETE FROM $table
538
                WHERE c_id = $courseId";
539
        Database::query($sql);
540
541
        $groupTable = Database::get_course_table(TABLE_GROUP);
542
        $sql = "DELETE FROM $groupTable
543
                WHERE c_id = $courseId";
544
        Database::query($sql);
545
546
        return true;
547
    }
548
549
    /**
550
     * Get group properties.
551
     *
552
     * @param int  $group_id the group from which properties are requested
553
     * @param bool $useIid
554
     *
555
     * @return array All properties. Array-keys are:
556
     *               name, tutor_id, description, maximum_number_of_students,
557
     *               directory and visibility of tools
558
     */
559
    public static function get_group_properties($group_id, $useIid = false)
560
    {
561
        $course_id = api_get_course_int_id();
562
        $group_id = (int) $group_id;
563
564
        if (empty($group_id)) {
565
            return null;
566
        }
567
568
        $table_group = Database::get_course_table(TABLE_GROUP);
569
        $sql = "SELECT * FROM $table_group
570
                WHERE c_id = $course_id AND id = ".$group_id;
571
572
        if ($useIid) {
573
            $sql = "SELECT * FROM $table_group
574
                    WHERE c_id = $course_id AND iid = ".$group_id;
575
        }
576
        $db_result = Database::query($sql);
577
        $db_object = Database::fetch_object($db_result);
578
579
        $result = [];
580
        if ($db_object) {
581
            $result['id'] = $db_object->id;
582
            $result['iid'] = $db_object->iid;
583
            $result['name'] = $db_object->name;
584
            $result['status'] = $db_object->status;
585
            $result['description'] = $db_object->description;
586
            $result['maximum_number_of_students'] = $db_object->max_student;
587
            $result['max_student'] = $db_object->max_student;
588
            $result['doc_state'] = $db_object->doc_state;
589
            $result['work_state'] = $db_object->work_state;
590
            $result['calendar_state'] = $db_object->calendar_state;
591
            $result['announcements_state'] = $db_object->announcements_state;
592
            $result['forum_state'] = $db_object->forum_state;
593
            $result['wiki_state'] = $db_object->wiki_state;
594
            $result['chat_state'] = $db_object->chat_state;
595
            $result['directory'] = $db_object->secret_directory;
596
            $result['self_registration_allowed'] = $db_object->self_registration_allowed;
597
            $result['self_unregistration_allowed'] = $db_object->self_unregistration_allowed;
598
            $result['count_users'] = count(
599
                self::get_subscribed_users($result)
600
            );
601
            $result['count_tutor'] = count(
602
                self::get_subscribed_tutors($result)
603
            );
604
            $result['count_all'] = $result['count_users'] + $result['count_tutor'];
605
            $result['document_access'] = isset($db_object->document_access) ? $db_object->document_access : self::DOCUMENT_MODE_SHARE;
606
        }
607
608
        return $result;
609
    }
610
611
    /**
612
     * @param string $name
613
     * @param string $courseCode
614
     * @param int    $sessionId
615
     *
616
     * @return array
617
     */
618
    public static function getGroupByName($name, $courseCode = null, $sessionId = 0)
619
    {
620
        $name = trim($name);
621
622
        if (empty($name)) {
623
            return [];
624
        }
625
626
        $course_info = api_get_course_info($courseCode);
627
        $course_id = $course_info['real_id'];
628
        $name = Database::escape_string($name);
629
        $sessionId = empty($sessionId) ? api_get_session_id() : (int) $sessionId;
630
        $sessionCondition = api_get_session_condition($sessionId);
631
632
        $table = Database::get_course_table(TABLE_GROUP);
633
        $sql = "SELECT * FROM $table
634
                WHERE 
635
                  c_id = $course_id AND 
636
                  name = '$name'
637
                  $sessionCondition
638
                LIMIT 1";
639
        $res = Database::query($sql);
640
        $group = [];
641
        if (Database::num_rows($res)) {
642
            $group = Database::fetch_array($res, 'ASSOC');
643
        }
644
645
        return $group;
646
    }
647
648
    /**
649
     * @param int    $courseId
650
     * @param int    $categoryId
651
     * @param string $name
652
     *
653
     * @return array
654
     */
655
    public static function getGroupListFilterByName($name, $categoryId, $courseId)
656
    {
657
        $name = trim($name);
658
        if (empty($name)) {
659
            return [];
660
        }
661
        $name = Database::escape_string($name);
662
        $courseId = (int) $courseId;
663
        $table_group = Database::get_course_table(TABLE_GROUP);
664
        $sql = "SELECT * FROM $table_group
665
                WHERE c_id = $courseId AND name LIKE '%$name%'";
666
667
        if (!empty($categoryId)) {
668
            $categoryId = intval($categoryId);
669
            $sql .= " AND category_id = $categoryId";
670
        }
671
        $sql .= " ORDER BY name";
672
        $result = Database::query($sql);
673
674
        return Database::store_result($result, 'ASSOC');
675
    }
676
677
    /**
678
     * Set group properties
679
     * Changes the group's properties.
680
     *
681
     * @param int       Group Id
682
     * @param string    Group name
683
     * @param string    Group description
684
     * @param int       Max number of students in group
685
     * @param int       Document tool's visibility (0=none,1=private,2=public)
686
     * @param int       Work tool's visibility (0=none,1=private,2=public)
687
     * @param int       Calendar tool's visibility (0=none,1=private,2=public)
688
     * @param int       Announcement tool's visibility (0=none,1=private,2=public)
689
     * @param int       Forum tool's visibility (0=none,1=private,2=public)
690
     * @param int       Wiki tool's visibility (0=none,1=private,2=public)
691
     * @param int       Chat tool's visibility (0=none,1=private,2=public)
692
     * @param bool Whether self registration is allowed or not
693
     * @param bool Whether self unregistration is allowed or not
694
     * @param int $categoryId
695
     * @param int $documentAccess
696
     *
697
     * @return bool TRUE if properties are successfully changed, false otherwise
698
     */
699
    public static function set_group_properties(
700
        $group_id,
701
        $name,
702
        $description,
703
        $maximum_number_of_students,
704
        $doc_state,
705
        $work_state,
706
        $calendar_state,
707
        $announcements_state,
708
        $forum_state,
709
        $wiki_state,
710
        $chat_state,
711
        $selfRegistrationAllowed,
712
        $selfUnRegistrationAllowed,
713
        $categoryId = null,
714
        $documentAccess = 0
715
    ) {
716
        $table_group = Database::get_course_table(TABLE_GROUP);
717
        $table_forum = Database::get_course_table(TABLE_FORUM);
718
        $categoryId = (int) $categoryId;
719
        $group_id = (int) $group_id;
720
        $courseId = api_get_course_int_id();
721
722
        $allowDocumentAccess = api_get_configuration_value('group_document_access');
723
        $documentCondition = '';
724
        if ($allowDocumentAccess) {
725
            $documentAccess = (int) $documentAccess;
726
            $documentCondition = " document_access = $documentAccess, ";
727
        }
728
729
        $sql = "UPDATE ".$table_group." SET
730
                    name='".Database::escape_string(trim($name))."',
731
                    doc_state = '".Database::escape_string($doc_state)."',
732
                    work_state = '".Database::escape_string($work_state)."',
733
                    calendar_state = '".Database::escape_string($calendar_state)."',
734
                    announcements_state = '".Database::escape_string($announcements_state)."',
735
                    forum_state = '".Database::escape_string($forum_state)."',
736
                    wiki_state = '".Database::escape_string($wiki_state)."',
737
                    chat_state = '".Database::escape_string($chat_state)."',
738
                    description ='".Database::escape_string(trim($description))."',
739
                    max_student = '".Database::escape_string($maximum_number_of_students)."',
740
                    self_registration_allowed = '".Database::escape_string($selfRegistrationAllowed)."',
741
                    self_unregistration_allowed = '".Database::escape_string($selfUnRegistrationAllowed)."',
742
                    $documentCondition
743
                    category_id = ".$categoryId."
744
                WHERE c_id = $courseId AND id=".$group_id;
745
        $result = Database::query($sql);
746
747
        /* Here we are updating a field in the table forum_forum that perhaps
748
        duplicates the table group_info.forum_state cvargas*/
749
        $forum_state = (int) $forum_state;
750
        $sql2 = "UPDATE ".$table_forum." SET ";
751
        if ($forum_state === 1) {
752
            $sql2 .= " forum_group_public_private='public' ";
753
        } elseif ($forum_state === 2) {
754
            $sql2 .= " forum_group_public_private='private' ";
755
        } elseif ($forum_state === 0) {
756
            $sql2 .= " forum_group_public_private='unavailable' ";
757
        }
758
        $sql2 .= " WHERE c_id = $courseId AND forum_of_group=".$group_id;
759
        Database::query($sql2);
760
761
        return $result;
762
    }
763
764
    /**
765
     * Get the total number of groups for the current course.
766
     *
767
     * @return int the number of groups for the current course
768
     */
769
    public static function get_number_of_groups()
770
    {
771
        $courseId = api_get_course_int_id();
772
        $table = Database::get_course_table(TABLE_GROUP);
773
        $sql = "SELECT COUNT(id) AS number_of_groups
774
                FROM $table
775
                WHERE c_id = $courseId ";
776
        $res = Database::query($sql);
777
        $obj = Database::fetch_object($res);
778
779
        return $obj->number_of_groups;
780
    }
781
782
    /**
783
     * Get all categories.
784
     *
785
     * @param string $course_code The course (default = current course)
786
     *
787
     * @return array
788
     */
789
    public static function get_categories($course_code = null)
790
    {
791
        $course_info = api_get_course_info($course_code);
792
        $courseId = $course_info['real_id'];
793
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
794
        $sql = "SELECT * FROM $table
795
                WHERE c_id = $courseId
796
                ORDER BY display_order";
797
        $res = Database::query($sql);
798
        $cats = [];
799
        while ($cat = Database::fetch_array($res)) {
800
            $cats[] = $cat;
801
        }
802
803
        return $cats;
804
    }
805
806
    /**
807
     * Get a group category.
808
     *
809
     * @param int    $id          The category id
810
     * @param string $course_code The course (default = current course)
811
     *
812
     * @return array
813
     */
814
    public static function get_category($id, $course_code = null)
815
    {
816
        if (empty($id)) {
817
            return [];
818
        }
819
820
        $courseInfo = api_get_course_info($course_code);
821
        $courseId = $courseInfo['real_id'];
822
        $id = intval($id);
823
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
824
        $sql = "SELECT * FROM $table
825
                WHERE c_id = $courseId AND id = $id
826
                LIMIT 1";
827
        $res = Database::query($sql);
828
829
        return Database::fetch_array($res);
830
    }
831
832
    /**
833
     * Get a group category.
834
     *
835
     * @param string $title
836
     * @param string $course_code The course (default = current course)
837
     *
838
     * @return array
839
     */
840
    public static function getCategoryByTitle($title, $course_code = null)
841
    {
842
        $title = trim($title);
843
844
        if (empty($title)) {
845
            return [];
846
        }
847
848
        $course_info = api_get_course_info($course_code);
849
        $courseId = $course_info['real_id'];
850
        $title = Database::escape_string($title);
851
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
852
        $sql = "SELECT * FROM $table
853
                WHERE c_id = $courseId AND title = '$title'
854
                LIMIT 1";
855
        $res = Database::query($sql);
856
        $category = [];
857
        if (Database::num_rows($res)) {
858
            $category = Database::fetch_array($res, 'ASSOC');
859
        }
860
861
        return $category;
862
    }
863
864
    /**
865
     * Get the unique category of a given group.
866
     *
867
     * @param int    $group_id    The iid of the group
868
     * @param string $course_code The course in which the group is (default =
869
     *                            current course)
870
     *
871
     * @return array The category
872
     */
873
    public static function get_category_from_group($group_id, $course_code = '')
874
    {
875
        $table_group = Database::get_course_table(TABLE_GROUP);
876
        $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
877
878
        $group_id = intval($group_id);
879
880
        if (empty($group_id)) {
881
            return [];
882
        }
883
884
        $course_info = api_get_course_info($course_code);
885
886
        if (empty($course_info)) {
887
            return false;
888
        }
889
890
        $courseId = $course_info['real_id'];
891
        $sql = "SELECT gc.* FROM $table_group_cat gc, $table_group g
892
                WHERE
893
                    gc.c_id = $courseId AND
894
                    g.c_id = $courseId AND
895
                    gc.id = g.category_id AND 
896
                    g.iid = $group_id
897
                LIMIT 1";
898
        $res = Database::query($sql);
899
        $cat = [];
900
        if (Database::num_rows($res)) {
901
            $cat = Database::fetch_array($res);
902
        }
903
904
        return $cat;
905
    }
906
907
    /**
908
     * Delete a group category.
909
     *
910
     * @param int    $cat_id      The id of the category to delete
911
     * @param string $course_code The code in which the category should be
912
     *                            deleted (default = current course)
913
     *
914
     * @return bool
915
     */
916
    public static function delete_category($cat_id, $course_code = '')
917
    {
918
        $course_info = api_get_course_info($course_code);
919
        if (empty($course_info)) {
920
            return false;
921
        }
922
        $course_id = $course_info['real_id'];
923
924
        $table_group = Database::get_course_table(TABLE_GROUP);
925
        $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
926
        $cat_id = intval($cat_id);
927
        $sql = "SELECT iid FROM $table_group
928
                WHERE c_id = $course_id AND category_id='".$cat_id."'";
929
        $res = Database::query($sql);
930
        if (Database::num_rows($res) > 0) {
931
            while ($group = Database::fetch_object($res)) {
932
                // Delete all groups in category
933
                /*$groupInfo = self::get_group_properties($group->iid, true);
934
                self::deleteGroup($groupInfo, $course_code);
935
                */
936
                // Set the category to NULL to avoid losing groups in sessions.
937
                $sql = "UPDATE $table_group SET category_id = NULL WHERE iid = ".$group->iid;
938
                Database::query($sql);
939
            }
940
        }
941
        $sql = "DELETE FROM $table_group_cat
942
                WHERE c_id = $course_id  AND id='".$cat_id."'";
943
        Database::query($sql);
944
945
        return true;
946
    }
947
948
    /**
949
     * Create group category.
950
     *
951
     * @param string $title                      The title of the new category
952
     * @param string $description                The description of the new category
953
     * @param int    $doc_state
954
     * @param int    $work_state
955
     * @param int    $calendar_state
956
     * @param int    $announcements_state
957
     * @param int    $forum_state
958
     * @param int    $wiki_state
959
     * @param int    $chat_state
960
     * @param int    $selfRegistrationAllowed    allow users to self register
961
     * @param int    $selfUnRegistrationAllowed  allow user to self unregister
962
     * @param int    $maximum_number_of_students
963
     * @param int    $groups_per_user
964
     * @param int    $documentAccess             document access
965
     *
966
     * @return mixed
967
     */
968
    public static function create_category(
969
        $title,
970
        $description,
971
        $doc_state,
972
        $work_state,
973
        $calendar_state,
974
        $announcements_state,
975
        $forum_state,
976
        $wiki_state,
977
        $chat_state = 1,
978
        $selfRegistrationAllowed = 0,
979
        $selfUnRegistrationAllowed = 0,
980
        $maximum_number_of_students = 8,
981
        $groups_per_user = 0,
982
        $documentAccess = 0
983
    ) {
984
        if (empty($title)) {
985
            return false;
986
        }
987
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
988
        $course_id = api_get_course_int_id();
989
990
        $sql = "SELECT MAX(display_order)+1 as new_order
991
                FROM $table
992
                WHERE c_id = $course_id ";
993
        $res = Database::query($sql);
994
        $obj = Database::fetch_object($res);
995
        if (!isset($obj->new_order)) {
996
            $obj->new_order = 1;
997
        }
998
999
        $params = [
1000
            'c_id' => $course_id,
1001
            'title' => $title,
1002
            'display_order' => $obj->new_order,
1003
            'description' => $description,
1004
            'doc_state' => $doc_state,
1005
            'work_state' => $work_state,
1006
            'calendar_state' => $calendar_state,
1007
            'announcements_state' => $announcements_state,
1008
            'forum_state' => $forum_state,
1009
            'wiki_state' => $wiki_state,
1010
            'chat_state' => $chat_state,
1011
            'groups_per_user' => $groups_per_user,
1012
            'self_reg_allowed' => $selfRegistrationAllowed,
1013
            'self_unreg_allowed' => $selfUnRegistrationAllowed,
1014
            'max_student' => $maximum_number_of_students,
1015
        ];
1016
1017
        $allowDocumentAccess = api_get_configuration_value('group_category_document_access');
1018
        if ($allowDocumentAccess) {
1019
            $params['document_access'] = $documentAccess;
1020
        }
1021
1022
        $categoryId = Database::insert($table, $params);
1023
        if ($categoryId) {
1024
            $sql = "UPDATE $table SET id = iid
1025
                    WHERE iid = $categoryId";
1026
            Database::query($sql);
1027
1028
            return $categoryId;
1029
        }
1030
1031
        return false;
1032
    }
1033
1034
    /**
1035
     * Update group category.
1036
     *
1037
     * @param int    $id
1038
     * @param string $title
1039
     * @param string $description
1040
     * @param $doc_state
1041
     * @param $work_state
1042
     * @param $calendar_state
1043
     * @param $announcements_state
1044
     * @param $forum_state
1045
     * @param $wiki_state
1046
     * @param $chat_state
1047
     * @param $selfRegistrationAllowed
1048
     * @param $selfUnRegistrationAllowed
1049
     * @param $maximum_number_of_students
1050
     * @param $groups_per_user
1051
     * @param $documentAccess
1052
     */
1053
    public static function update_category(
1054
        $id,
1055
        $title,
1056
        $description,
1057
        $doc_state,
1058
        $work_state,
1059
        $calendar_state,
1060
        $announcements_state,
1061
        $forum_state,
1062
        $wiki_state,
1063
        $chat_state,
1064
        $selfRegistrationAllowed,
1065
        $selfUnRegistrationAllowed,
1066
        $maximum_number_of_students,
1067
        $groups_per_user,
1068
        $documentAccess
1069
    ) {
1070
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
1071
        $id = (int) $id;
1072
1073
        $courseId = api_get_course_int_id();
1074
1075
        $allowDocumentAccess = api_get_configuration_value('group_category_document_access');
1076
        $documentCondition = '';
1077
        if ($allowDocumentAccess) {
1078
            $documentAccess = (int) $documentAccess;
1079
            $documentCondition = " document_access = $documentAccess, ";
1080
        }
1081
1082
        $sql = "UPDATE ".$table." SET
1083
                    title='".Database::escape_string($title)."',
1084
                    description='".Database::escape_string($description)."',
1085
                    doc_state = '".Database::escape_string($doc_state)."',
1086
                    work_state = '".Database::escape_string($work_state)."',
1087
                    calendar_state = '".Database::escape_string($calendar_state)."',
1088
                    announcements_state = '".Database::escape_string($announcements_state)."',
1089
                    forum_state = '".Database::escape_string($forum_state)."',
1090
                    wiki_state = '".Database::escape_string($wiki_state)."',
1091
                    chat_state = '".Database::escape_string($chat_state)."',
1092
                    groups_per_user   = '".Database::escape_string($groups_per_user)."',
1093
                    self_reg_allowed = '".Database::escape_string($selfRegistrationAllowed)."',
1094
                    self_unreg_allowed = '".Database::escape_string($selfUnRegistrationAllowed)."',
1095
                    $documentCondition
1096
                    max_student = ".intval($maximum_number_of_students)."
1097
                WHERE c_id = $courseId AND id = $id";
1098
1099
        Database::query($sql);
1100
1101
        // Updating all groups inside this category
1102
        $groups = self::get_group_list($id);
1103
1104
        if (!empty($groups)) {
1105
            foreach ($groups as $group) {
1106
                self::set_group_properties(
1107
                    $group['id'],
1108
                    $group['name'],
1109
                    $group['description'],
1110
                    $maximum_number_of_students,
1111
                    $doc_state,
1112
                    $work_state,
1113
                    $calendar_state,
1114
                    $announcements_state,
1115
                    $forum_state,
1116
                    $wiki_state,
1117
                    $chat_state,
1118
                    $selfRegistrationAllowed,
1119
                    $selfUnRegistrationAllowed,
1120
                    $id,
1121
                    $documentAccess
1122
                );
1123
            }
1124
        }
1125
    }
1126
1127
    /**
1128
     * Returns the number of groups of the user with the greatest number of
1129
     * subscriptions in the given category.
1130
     */
1131
    public static function get_current_max_groups_per_user(
1132
        $category_id = null,
1133
        $course_code = null
1134
    ) {
1135
        $course_info = api_get_course_info($course_code);
1136
        $group_table = Database::get_course_table(TABLE_GROUP);
1137
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1138
        $sql = 'SELECT COUNT(gu.group_id) AS current_max
1139
                FROM '.$group_user_table.' gu, '.$group_table.' g
1140
				WHERE g.c_id = '.$course_info['real_id'].'
1141
				AND gu.c_id = g.c_id
1142
				AND gu.group_id = g.iid ';
1143
        if ($category_id != null) {
1144
            $category_id = intval($category_id);
1145
            $sql .= ' AND g.category_id = '.$category_id;
1146
        }
1147
        $sql .= ' GROUP BY gu.user_id ORDER BY current_max DESC LIMIT 1';
1148
        $res = Database::query($sql);
1149
        $obj = Database::fetch_object($res);
1150
1151
        return $obj->current_max;
1152
    }
1153
1154
    /**
1155
     * Swaps the display-order of two categories.
1156
     *
1157
     * @param int $id1 The id of the first category
1158
     * @param int $id2 The id of the second category
1159
     */
1160
    public static function swap_category_order($id1, $id2)
1161
    {
1162
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
1163
        $id1 = intval($id1);
1164
        $id2 = intval($id2);
1165
        $course_id = api_get_course_int_id();
1166
1167
        $sql = "SELECT id, display_order FROM $table
1168
                WHERE id IN ($id1,$id2) AND c_id = $course_id ";
1169
        $res = Database::query($sql);
1170
        $cat1 = Database::fetch_object($res);
1171
        $cat2 = Database::fetch_object($res);
1172
        if ($cat1 && $cat2) {
1173
            $sql = "UPDATE $table SET display_order=$cat2->display_order
1174
                    WHERE id = $cat1->id AND c_id = $course_id ";
1175
            Database::query($sql);
1176
1177
            $sql = "UPDATE $table SET display_order=$cat1->display_order
1178
                    WHERE id = $cat2->id AND c_id = $course_id ";
1179
            Database::query($sql);
1180
        }
1181
    }
1182
1183
    /**
1184
     * Get all users from a given group.
1185
     *
1186
     * @param int  $group_id        The group
1187
     * @param bool $load_extra_info
1188
     * @param int  $start
1189
     * @param int  $limit
1190
     * @param bool $getCount
1191
     * @param int  $courseId
1192
     * @param $column
1193
     * @param $direction
1194
     *
1195
     * @return array list of user id
1196
     */
1197
    public static function get_users(
1198
        $group_id,
1199
        $load_extra_info = false,
1200
        $start = null,
1201
        $limit = null,
1202
        $getCount = false,
1203
        $courseId = null,
1204
        $column = null,
1205
        $direction = null
1206
    ) {
1207
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1208
        $groupTable = Database::get_course_table(TABLE_GROUP);
1209
        $user_table = Database::get_main_table(TABLE_MAIN_USER);
1210
        $group_id = intval($group_id);
1211
1212
        if (empty($courseId)) {
1213
            $courseId = api_get_course_int_id();
1214
        } else {
1215
            $courseId = intval($courseId);
1216
        }
1217
1218
        $select = " SELECT u.id, firstname, lastname ";
1219
        if ($getCount) {
1220
            $select = " SELECT count(u.id) count";
1221
        }
1222
        $sql = "$select
1223
                FROM $group_user_table gu
1224
                INNER JOIN $groupTable g
1225
                ON (gu.group_id = g.id and g.c_id = gu.c_id)
1226
                INNER JOIN $user_table u
1227
                ON (u.id = gu.user_id)
1228
                WHERE 
1229
                    gu.c_id = $courseId AND 
1230
                    g.id = $group_id";
1231
1232
        if (!empty($column) && !empty($direction)) {
1233
            $column = Database::escape_string($column, null, false);
1234
            $direction = ($direction == 'ASC' ? 'ASC' : 'DESC');
1235
            $sql .= " ORDER BY $column $direction";
1236
        }
1237
1238
        if (!empty($start) && !empty($limit)) {
1239
            $start = intval($start);
1240
            $limit = intval($limit);
1241
            $sql .= " LIMIT $start, $limit";
1242
        }
1243
        $res = Database::query($sql);
1244
        $users = [];
1245
        while ($obj = Database::fetch_object($res)) {
1246
            if ($getCount) {
1247
                return $obj->count;
1248
                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...
1249
            }
1250
            if ($load_extra_info) {
1251
                $users[] = api_get_user_info($obj->id);
1252
            } else {
1253
                $users[] = $obj->id;
1254
            }
1255
        }
1256
1257
        return $users;
1258
    }
1259
1260
    /**
1261
     * @param int $group_id id
1262
     *
1263
     * @return array
1264
     */
1265
    public static function getStudentsAndTutors($group_id)
1266
    {
1267
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1268
        $tutor_user_table = Database::get_course_table(TABLE_GROUP_TUTOR);
1269
        $groupTable = Database::get_course_table(TABLE_GROUP);
1270
1271
        $course_id = api_get_course_int_id();
1272
        $group_id = intval($group_id);
1273
        $sql = "SELECT user_id 
1274
                FROM $group_user_table gu
1275
                INNER JOIN $groupTable g
1276
                ON (gu.group_id = g.iid and g.c_id = gu.c_id)
1277
                WHERE gu.c_id = $course_id AND g.id = $group_id";
1278
        $res = Database::query($sql);
1279
        $users = [];
1280
1281
        while ($obj = Database::fetch_object($res)) {
1282
            $users[] = api_get_user_info($obj->user_id);
1283
        }
1284
1285
        $sql = "SELECT user_id 
1286
                FROM $tutor_user_table gu
1287
                INNER JOIN $groupTable g
1288
                ON (gu.group_id = g.id and g.c_id = gu.c_id)
1289
                WHERE gu.c_id = $course_id AND g.id = $group_id";
1290
        $res = Database::query($sql);
1291
        while ($obj = Database::fetch_object($res)) {
1292
            $users[] = api_get_user_info($obj->user_id);
1293
        }
1294
1295
        return $users;
1296
    }
1297
1298
    /**
1299
     * Get only tutors from a group.
1300
     *
1301
     * @param array $groupInfo
1302
     *
1303
     * @return array
1304
     */
1305
    public static function getTutors($groupInfo)
1306
    {
1307
        $groupTable = Database::get_course_table(TABLE_GROUP);
1308
        $tutor_user_table = Database::get_course_table(TABLE_GROUP_TUTOR);
1309
        $course_id = api_get_course_int_id();
1310
        $group_id = intval($groupInfo['iid']);
1311
1312
        $sql = "SELECT user_id 
1313
                FROM $tutor_user_table gu
1314
                INNER JOIN $groupTable g
1315
                ON (gu.group_id = g.id and g.c_id = gu.c_id)
1316
                WHERE gu.c_id = $course_id AND g.iid = $group_id";
1317
        $res = Database::query($sql);
1318
1319
        $users = [];
1320
        while ($obj = Database::fetch_object($res)) {
1321
            $users[] = api_get_user_info($obj->user_id);
1322
        }
1323
1324
        return $users;
1325
    }
1326
1327
    /**
1328
     * Get only students from a group (not tutors).
1329
     *
1330
     * @param int  $group_id         iid
1331
     * @param bool $filterOnlyActive
1332
     *
1333
     * @return array
1334
     */
1335
    public static function getStudents($group_id, $filterOnlyActive = false)
1336
    {
1337
        $activeCondition = $filterOnlyActive ? 'AND u.active = 1' : '';
1338
1339
        $em = Database::getManager();
1340
        $subscriptions = $em
1341
            ->createQuery("
1342
                SELECT u.id FROM ChamiloUserBundle:User u
1343
                INNER JOIN ChamiloCourseBundle:CGroupRelUser gu
1344
                    WITH u.id = gu.userId
1345
                INNER JOIN ChamiloCourseBundle:CGroupInfo g
1346
                WITH gu.groupId = g.id AND g.cId = gu.cId
1347
                WHERE gu.cId = :course AND g.id = :group
1348
                    $activeCondition
1349
            ")
1350
            ->setParameters([
1351
                'course' => api_get_course_int_id(),
1352
                'group' => intval($group_id),
1353
            ])
1354
            ->getResult();
1355
1356
        $users = [];
1357
        /** @var CGroupRelUser $subscription */
1358
        foreach ($subscriptions as $subscription) {
1359
            $users[] = api_get_user_info($subscription['id']);
1360
        }
1361
1362
        return $users;
1363
    }
1364
1365
    /**
1366
     * Returns users belonging to any of the group.
1367
     *
1368
     * @param array $groups list of group ids
1369
     *
1370
     * @return array list of user ids
1371
     */
1372
    public static function get_groups_users($groups = [])
1373
    {
1374
        $result = [];
1375
        $table = Database::get_course_table(TABLE_GROUP_USER);
1376
        $course_id = api_get_course_int_id();
1377
1378
        $groups = array_map('intval', $groups);
1379
        // protect individual elements with surrounding quotes
1380
        $groups = implode(', ', $groups);
1381
        $sql = "SELECT DISTINCT user_id
1382
                FROM $table gu
1383
                WHERE c_id = $course_id AND gu.group_id IN ($groups)";
1384
        $rs = Database::query($sql);
1385
        while ($row = Database::fetch_array($rs)) {
1386
            $result[] = $row['user_id'];
1387
        }
1388
1389
        return $result;
1390
    }
1391
1392
    /**
1393
     * Fill the groups with students.
1394
     * The algorithm takes care to first fill the groups with the least # of users.
1395
     * Analysis
1396
     * There was a problem with the "ALL" setting.
1397
     * When max # of groups is set to all, the value is sometimes NULL and sometimes ALL
1398
     * and in both cased the query does not work as expected.
1399
     * Stupid solution (currently implemented: set ALL to a big number (INFINITE) and things are solved :)
1400
     * Better solution: that's up to you.
1401
     *
1402
     * Note
1403
     * Throughout Dokeos there is some confusion about "course id" and "course code"
1404
     * The code is e.g. TEST101, but sometimes a variable that is called courseID also contains a course code string.
1405
     * However, there is also a integer course_id that uniquely identifies the course.
1406
     * ywarnier:> Now the course_id has been removed (25/1/2005)
1407
     * The databases are als very inconsistent in this.
1408
     *
1409
     * @param array $groupInfo
1410
     *
1411
     * @author Chrisptophe Gesche <[email protected]>,
1412
     *         Hugues Peeters     <[email protected]> - original version
1413
     * @author Roan Embrechts - virtual course support, code cleaning
1414
     * @author Bart Mollet - code cleaning, use other GroupManager-functions
1415
     *
1416
     * @return bool
1417
     */
1418
    public static function fillGroupWithUsers($groupInfo)
1419
    {
1420
        $_course = api_get_course_info();
1421
        if (empty($_course) || empty($groupInfo)) {
1422
            return false;
1423
        }
1424
        $session_id = api_get_session_id();
1425
        $complete_user_list = CourseManager::get_user_list_from_course_code(
1426
            $_course['code'],
1427
            $session_id
1428
        );
1429
        $groupIid = $groupInfo['iid'];
1430
        $category = self::get_category_from_group($groupIid);
1431
1432
        // Getting max numbers of user from group
1433
        $maxNumberStudents = empty($groupInfo['maximum_number_of_students']) ? self::INFINITE : $groupInfo['maximum_number_of_students'];
1434
        $groupsPerUser = self::INFINITE;
1435
        $categoryId = 0;
1436
        if ($category) {
1437
            $groupsPerUser = empty($category['groups_per_user']) ? self::INFINITE : $category['groups_per_user'];
1438
            $maxNumberStudentsCategory = empty($category['max_student']) ? self::INFINITE : $category['max_student'];
1439
            $categoryId = $category['id'];
1440
            if ($maxNumberStudentsCategory < $maxNumberStudents) {
1441
                $maxNumberStudents = $maxNumberStudentsCategory;
1442
            }
1443
        }
1444
1445
        $usersToAdd = [];
1446
        foreach ($complete_user_list as $userInfo) {
1447
            $isSubscribed = self::is_subscribed($userInfo['user_id'], $groupInfo);
1448
            if ($isSubscribed) {
1449
                continue;
1450
            }
1451
            $numberOfGroups = self::user_in_number_of_groups(
1452
                $userInfo['user_id'],
1453
                $categoryId
1454
            );
1455
            if ($groupsPerUser > $numberOfGroups) {
1456
                $usersToAdd[] = $userInfo['user_id'];
1457
            }
1458
            if (count($usersToAdd) == $maxNumberStudents) {
1459
                break;
1460
            }
1461
        }
1462
1463
        foreach ($usersToAdd as $userId) {
1464
            self::subscribe_users($userId, $groupInfo);
1465
        }
1466
    }
1467
1468
    /**
1469
     * Get the number of students in a group.
1470
     *
1471
     * @param int $group_id id
1472
     *
1473
     * @return int number of students in the given group
1474
     */
1475
    public static function number_of_students($group_id, $course_id = null)
1476
    {
1477
        $table = Database::get_course_table(TABLE_GROUP_USER);
1478
        $group_id = intval($group_id);
1479
        if (empty($course_id)) {
1480
            $course_id = api_get_course_int_id();
1481
        } else {
1482
            $course_id = intval($course_id);
1483
        }
1484
        $sql = "SELECT COUNT(*) AS number_of_students
1485
                FROM $table
1486
                WHERE c_id = $course_id AND group_id = $group_id";
1487
        $result = Database::query($sql);
1488
        $db_object = Database::fetch_object($result);
1489
1490
        return $db_object->number_of_students;
1491
    }
1492
1493
    /**
1494
     * Maximum number of students in a group.
1495
     *
1496
     * @param int $group_id iid
1497
     *
1498
     * @return int maximum number of students in the given group
1499
     */
1500
    public static function maximum_number_of_students($group_id)
1501
    {
1502
        $table = Database::get_course_table(TABLE_GROUP);
1503
        $group_id = intval($group_id);
1504
        $course_id = api_get_course_int_id();
1505
        $sql = "SELECT max_student FROM $table 
1506
                WHERE c_id = $course_id AND iid = $group_id";
1507
        $db_result = Database::query($sql);
1508
        $db_object = Database::fetch_object($db_result);
1509
        if ($db_object->max_student == 0) {
1510
            return self::INFINITE;
1511
        }
1512
1513
        return $db_object->max_student;
1514
    }
1515
1516
    /**
1517
     * Number of groups of a user.
1518
     *
1519
     * @param int $user_id
1520
     * @param int $cat_id
1521
     *
1522
     * @return int the number of groups the user is subscribed in
1523
     */
1524
    public static function user_in_number_of_groups($user_id, $cat_id = 0)
1525
    {
1526
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1527
        $table_group = Database::get_course_table(TABLE_GROUP);
1528
        $user_id = (int) $user_id;
1529
        $cat_id = (int) $cat_id;
1530
1531
        $course_id = api_get_course_int_id();
1532
        $cat_condition = '';
1533
        if (!empty($cat_id)) {
1534
            $cat_condition = " AND g.category_id =  $cat_id ";
1535
        }
1536
1537
        $sql = "SELECT COUNT(*) AS number_of_groups
1538
                FROM $table_group_user gu 
1539
                INNER JOIN $table_group g
1540
                ON (g.iid = gu.group_id AND gu.c_id = g.c_id)
1541
                WHERE
1542
                    gu.c_id = $course_id AND
1543
                    g.c_id = $course_id AND
1544
                    gu.user_id = $user_id                       
1545
                    $cat_condition";
1546
1547
        $result = Database::query($sql);
1548
        $db_object = Database::fetch_object($result);
1549
1550
        return $db_object->number_of_groups;
1551
    }
1552
1553
    /**
1554
     * Is sef-registration allowed?
1555
     *
1556
     * @param int   $user_id
1557
     * @param array $groupInfo
1558
     *
1559
     * @return bool TRUE if self-registration is allowed in the given group
1560
     */
1561
    public static function is_self_registration_allowed($user_id, $groupInfo)
1562
    {
1563
        $course_id = api_get_course_int_id();
1564
        if (empty($user_id)) {
1565
            return false;
1566
        }
1567
1568
        $groupIid = $groupInfo['iid'];
1569
        $table = Database::get_course_table(TABLE_GROUP);
1570
        if (isset($groupIid)) {
1571
            $sql = "SELECT status, self_registration_allowed
1572
                    FROM $table
1573
                    WHERE c_id = $course_id AND iid = $groupIid";
1574
            $result = Database::query($sql);
1575
            $group = Database::fetch_object($result);
1576
1577
            if ($group->status == 0 || $group->self_registration_allowed != 1) {
1578
                return false;
1579
            }
1580
1581
            return self::canUserSubscribe($user_id, $groupInfo);
1582
        } else {
1583
            return false;
1584
        }
1585
    }
1586
1587
    /**
1588
     * Is sef-unregistration allowed?
1589
     *
1590
     * @param int   $user_id
1591
     * @param array $groupInfo
1592
     *
1593
     * @return bool TRUE if self-unregistration is allowed in the given group
1594
     */
1595
    public static function is_self_unregistration_allowed($user_id, $groupInfo)
1596
    {
1597
        if (empty($user_id) || empty($groupInfo)) {
1598
            return false;
1599
        }
1600
        $groupIid = $groupInfo['iid'];
1601
        $table = Database::get_course_table(TABLE_GROUP);
1602
        $course_id = api_get_course_int_id();
1603
1604
        $sql = "SELECT status, self_unregistration_allowed
1605
                FROM $table
1606
                WHERE c_id = $course_id AND iid = $groupIid";
1607
        $result = Database::query($sql);
1608
        $group = Database::fetch_object($result);
1609
1610
        if ($group->status == 0 || $group->self_unregistration_allowed != 1) {
1611
            return false;
1612
        }
1613
1614
        return self::is_subscribed($user_id, $groupInfo);
1615
    }
1616
1617
    /**
1618
     * Is user subscribed in group?
1619
     *
1620
     * @param int   $user_id
1621
     * @param array $groupInfo
1622
     *
1623
     * @return bool TRUE if given user is subscribed in given group
1624
     */
1625
    public static function is_subscribed($user_id, $groupInfo)
1626
    {
1627
        $course_id = api_get_course_int_id();
1628
        if (empty($user_id) || empty($groupInfo) || empty($course_id)) {
1629
            return false;
1630
        }
1631
        $table = Database::get_course_table(TABLE_GROUP_USER);
1632
        $group_id = intval($groupInfo['id']);
1633
        $user_id = intval($user_id);
1634
1635
        $sql = "SELECT 1 FROM $table
1636
                WHERE
1637
                    c_id = $course_id AND
1638
                    group_id = $group_id AND
1639
                    user_id = $user_id
1640
                ";
1641
        $result = Database::query($sql);
1642
1643
        return Database::num_rows($result) > 0;
1644
    }
1645
1646
    /**
1647
     * Can a user subscribe to a specified group in a course.
1648
     *
1649
     * @param int   $user_id
1650
     * @param array $groupInfo
1651
     * @param bool  $checkMaxNumberStudents
1652
     *
1653
     * @return bool TRUE if given user  can be subscribed in given group
1654
     */
1655
    public static function canUserSubscribe(
1656
        $user_id,
1657
        $groupInfo,
1658
        $checkMaxNumberStudents = true
1659
    ) {
1660
        $group_id = $groupInfo['id'];
1661
        $groupIid = $groupInfo['iid'];
1662
        if ($checkMaxNumberStudents) {
1663
            $category = self::get_category_from_group($groupIid);
1664
            if ($category) {
1665
                if ($category['groups_per_user'] == self::GROUP_PER_MEMBER_NO_LIMIT) {
1666
                    $category['groups_per_user'] = self::INFINITE;
1667
                }
1668
                $result = self::user_in_number_of_groups($user_id, $category['id']) < $category['groups_per_user'];
1669
                if ($result == false) {
1670
                    return false;
1671
                }
1672
            }
1673
1674
            $result = self::number_of_students($group_id) < self::maximum_number_of_students($groupIid);
1675
1676
            if ($result == false) {
1677
                return false;
1678
            }
1679
        }
1680
1681
        $result = self::is_tutor_of_group($user_id, $groupInfo);
1682
1683
        if ($result) {
1684
            return false;
1685
        }
1686
1687
        $result = self::is_subscribed($user_id, $groupInfo);
1688
1689
        if ($result) {
1690
            return false;
1691
        }
1692
1693
        return true;
1694
    }
1695
1696
    /**
1697
     * Get all subscribed users (members) from a group.
1698
     *
1699
     * @param array $groupInfo
1700
     *
1701
     * @return array An array with information of all users from the given group.
1702
     *               (user_id, firstname, lastname, email)
1703
     */
1704
    public static function get_subscribed_users($groupInfo)
1705
    {
1706
        if (empty($groupInfo)) {
1707
            return [];
1708
        }
1709
1710
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
1711
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1712
        $order_clause = api_sort_by_first_name() ? ' ORDER BY u.firstname, u.lastname' : ' ORDER BY u.lastname, u.firstname';
1713
        $orderListByOfficialCode = api_get_setting('order_user_list_by_official_code');
1714
        if ($orderListByOfficialCode === 'true') {
1715
            $order_clause = ' ORDER BY u.official_code, u.firstname, u.lastname';
1716
        }
1717
1718
        $group_id = (int) $groupInfo['iid'];
1719
1720
        if (empty($group_id)) {
1721
            return [];
1722
        }
1723
1724
        $course_id = api_get_course_int_id();
1725
1726
        $sql = "SELECT 
1727
                    ug.id, 
1728
                    u.user_id, 
1729
                    u.lastname, 
1730
                    u.firstname, 
1731
                    u.email, 
1732
                    u.username
1733
                FROM $table_user u 
1734
                INNER JOIN $table_group_user ug
1735
                ON (ug.user_id = u.user_id)
1736
                WHERE ug.c_id = $course_id AND
1737
                      ug.group_id = $group_id
1738
                $order_clause";
1739
1740
        $db_result = Database::query($sql);
1741
        $users = [];
1742
        while ($user = Database::fetch_object($db_result)) {
1743
            $users[$user->user_id] = [
1744
                'user_id' => $user->user_id,
1745
                'firstname' => $user->firstname,
1746
                'lastname' => $user->lastname,
1747
                'email' => $user->email,
1748
                'username' => $user->username,
1749
            ];
1750
        }
1751
1752
        return $users;
1753
    }
1754
1755
    /**
1756
     * @author Patrick Cool <[email protected]>, Ghent University
1757
     * Get all subscribed tutors of a group
1758
     *
1759
     * @param array $groupInfo
1760
     *
1761
     * @return array An array with information of all users from the given group.
1762
     *               (user_id, firstname, lastname, email)
1763
     */
1764
    public static function get_subscribed_tutors($groupInfo, $id_only = false)
1765
    {
1766
        if (empty($groupInfo)) {
1767
            return [];
1768
        }
1769
1770
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
1771
        $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1772
        $order_clause = api_sort_by_first_name() ? ' ORDER BY u.firstname, u.lastname' : ' ORDER BY u.lastname, u.firstname';
1773
1774
        $orderListByOfficialCode = api_get_setting('order_user_list_by_official_code');
1775
        if ($orderListByOfficialCode === 'true') {
1776
            $order_clause = ' ORDER BY u.official_code, u.firstname, u.lastname';
1777
        }
1778
1779
        $group_id = (int) $groupInfo['iid'];
1780
        $course_id = api_get_course_int_id();
1781
1782
        $sql = "SELECT tg.id, u.user_id, u.lastname, u.firstname, u.email
1783
                FROM $table_user u, $table_group_tutor tg
1784
                WHERE
1785
                    tg.c_id = $course_id AND
1786
                    tg.group_id = $group_id AND
1787
                    tg.user_id = u.user_id 
1788
                $order_clause
1789
                ";
1790
        $db_result = Database::query($sql);
1791
        $users = [];
1792
        while ($user = Database::fetch_object($db_result)) {
1793
            if (!$id_only) {
1794
                $member['user_id'] = $user->user_id;
1795
                $member['firstname'] = $user->firstname;
1796
                $member['lastname'] = $user->lastname;
1797
                $member['email'] = $user->email;
1798
                $users[] = $member;
1799
            } else {
1800
                $users[] = $user->user_id;
1801
            }
1802
        }
1803
1804
        return $users;
1805
    }
1806
1807
    /**
1808
     * Subscribe user(s) to a specified group in current course (as a student).
1809
     *
1810
     * @param mixed $user_ids  Can be an array with user-id's or a single user-id
1811
     * @param array $groupInfo
1812
     * @param int   $course_id
1813
     *
1814
     * @return bool TRUE if successful
1815
     */
1816
    public static function subscribe_users($user_ids, $groupInfo, $course_id = null)
1817
    {
1818
        $user_ids = is_array($user_ids) ? $user_ids : [$user_ids];
1819
        $course_id = empty($course_id) ? api_get_course_int_id() : (int) $course_id;
1820
        $group_id = $groupInfo['id'];
1821
1822
        $table = Database::get_course_table(TABLE_GROUP_USER);
1823
        if (!empty($user_ids)) {
1824
            foreach ($user_ids as $user_id) {
1825
                if (self::canUserSubscribe($user_id, $groupInfo)) {
1826
                    $user_id = intval($user_id);
1827
                    $sql = "INSERT INTO ".$table." (c_id, user_id, group_id)
1828
                            VALUES ('$course_id', '".$user_id."', '".$group_id."')";
1829
                    Database::query($sql);
1830
                }
1831
            }
1832
        }
1833
1834
        return true;
1835
    }
1836
1837
    /**
1838
     * Subscribe tutor(s) to a specified group in current course.
1839
     *
1840
     * @param mixed $user_ids  Can be an array with user-id's or a single user-id
1841
     * @param array $groupInfo
1842
     * @param int   $course_id
1843
     *
1844
     * @author Patrick Cool <[email protected]>, Ghent University
1845
     *
1846
     * @see subscribe_users. This function is almost an exact copy of that function.
1847
     *
1848
     * @return bool TRUE if successful
1849
     */
1850
    public static function subscribe_tutors($user_ids, $groupInfo, $course_id = 0)
1851
    {
1852
        $user_ids = is_array($user_ids) ? $user_ids : [$user_ids];
1853
        $result = true;
1854
        $course_id = isset($course_id) && !empty($course_id) ? intval($course_id) : api_get_course_int_id();
1855
        $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1856
        $groupId = (int) $groupInfo['id'];
1857
1858
        foreach ($user_ids as $user_id) {
1859
            $user_id = intval($user_id);
1860
            if (self::canUserSubscribe($user_id, $groupInfo, false)) {
1861
                $sql = "INSERT INTO ".$table_group_tutor." (c_id, user_id, group_id)
1862
                        VALUES ('$course_id', '".$user_id."', '".$groupId."')";
1863
                $result = Database::query($sql);
1864
            }
1865
        }
1866
1867
        return $result;
1868
    }
1869
1870
    /**
1871
     * Unsubscribe user(s) from a specified group in current course.
1872
     *
1873
     * @param mixed $user_ids  Can be an array with user-id's or a single user-id
1874
     * @param array $groupInfo
1875
     *
1876
     * @return bool TRUE if successful
1877
     */
1878
    public static function unsubscribe_users($user_ids, $groupInfo)
1879
    {
1880
        $user_ids = is_array($user_ids) ? $user_ids : [$user_ids];
1881
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1882
        $group_id = intval($groupInfo['id']);
1883
        $course_id = api_get_course_int_id();
1884
        $sql = 'DELETE FROM '.$table_group_user.'
1885
                WHERE
1886
                    c_id = '.$course_id.' AND
1887
                    group_id = '.$group_id.' AND
1888
                    user_id IN ('.implode(',', $user_ids).')
1889
                ';
1890
        Database::query($sql);
1891
    }
1892
1893
    /**
1894
     * Unsubscribe all users from one or more groups.
1895
     *
1896
     * @param array $groupInfo
1897
     *
1898
     * @return bool TRUE if successful
1899
     */
1900
    public static function unsubscribe_all_users($groupInfo)
1901
    {
1902
        $course_id = api_get_course_int_id();
1903
        $groupId = (int) $groupInfo['id'];
1904
        if (empty($course_id) || empty($groupId)) {
1905
            return false;
1906
        }
1907
1908
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1909
        $sql = "DELETE FROM $table_group_user
1910
                WHERE 
1911
                    group_id = $groupId AND 
1912
                    c_id = $course_id";
1913
        $result = Database::query($sql);
1914
1915
        return $result;
1916
    }
1917
1918
    /**
1919
     * Unsubscribe all tutors from one or more groups.
1920
     *
1921
     * @param int $groupId iid
1922
     *
1923
     * @see unsubscribe_all_users. This function is almost an exact copy of that function.
1924
     *
1925
     * @return bool TRUE if successful
1926
     *
1927
     * @author Patrick Cool <[email protected]>, Ghent University
1928
     */
1929
    public static function unsubscribe_all_tutors($groupId)
1930
    {
1931
        $courseId = api_get_course_int_id();
1932
        $groupId = (int) $groupId;
1933
1934
        if (empty($courseId) || empty($groupId)) {
1935
            return false;
1936
        }
1937
1938
        if (!empty($groupId)) {
1939
            $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1940
            $sql = "DELETE FROM $table_group_tutor
1941
                    WHERE group_id = $groupId AND c_id = $courseId";
1942
            $result = Database::query($sql);
1943
1944
            return $result;
1945
        }
1946
1947
        return true;
1948
    }
1949
1950
    /**
1951
     * Is the user a tutor of this group?
1952
     *
1953
     * @param int   $user_id   the id of the user
1954
     * @param array $groupInfo
1955
     * @param int   $courseId
1956
     *
1957
     * @return bool true/false
1958
     *
1959
     * @todo use the function user_has_access that includes this function
1960
     *
1961
     * @author Patrick Cool <[email protected]>, Ghent University
1962
     */
1963
    public static function is_tutor_of_group($user_id, $groupInfo, $courseId = 0)
1964
    {
1965
        if (empty($groupInfo)) {
1966
            return false;
1967
        }
1968
1969
        $courseId = empty($courseId) ? api_get_course_int_id() : (int) $courseId;
1970
        if (empty($courseId)) {
1971
            return false;
1972
        }
1973
1974
        $user_id = intval($user_id);
1975
        $group_id = intval($groupInfo['id']);
1976
1977
        $table = Database::get_course_table(TABLE_GROUP_TUTOR);
1978
1979
        $sql = "SELECT * FROM $table
1980
                WHERE 
1981
                    c_id = $courseId AND 
1982
                    user_id = $user_id AND 
1983
                    group_id = $group_id";
1984
        $result = Database::query($sql);
1985
        if (Database::num_rows($result) > 0) {
1986
            return true;
1987
        } else {
1988
            return false;
1989
        }
1990
    }
1991
1992
    /**
1993
     * Is the user part of this group? This can be a tutor or a normal member
1994
     * you should use this function if the access to a tool or functionality is
1995
     * restricted to the people who are actually in the group
1996
     * before you had to check if the user was
1997
     * 1. a member of the group OR
1998
     * 2. a tutor of the group. This function combines both.
1999
     *
2000
     * @param int   $user_id   the id of the user
2001
     * @param array $groupInfo
2002
     *
2003
     * @return bool true/false
2004
     *
2005
     * @author Patrick Cool <[email protected]>, Ghent University
2006
     */
2007
    public static function is_user_in_group($user_id, $groupInfo)
2008
    {
2009
        $member = self::is_subscribed($user_id, $groupInfo);
2010
        $tutor = self::is_tutor_of_group($user_id, $groupInfo);
2011
        if ($member || $tutor) {
2012
            return true;
2013
        } else {
2014
            return false;
2015
        }
2016
    }
2017
2018
    /**
2019
     * Get all group's from a given course in which a given user is unsubscribed.
2020
     *
2021
     * @author  Patrick Cool
2022
     *
2023
     * @param int $course_id retrieve the groups for
2024
     * @param int $user_id   the ID of the user you want to know all its group memberships
2025
     *
2026
     * @return array
2027
     */
2028
    public static function get_group_ids($course_id, $user_id)
2029
    {
2030
        $groups = [];
2031
        $tbl_group = Database::get_course_table(TABLE_GROUP_USER);
2032
        $tbl_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
2033
        $user_id = intval($user_id);
2034
        $course_id = intval($course_id);
2035
2036
        $sql = "SELECT group_id FROM $tbl_group
2037
                WHERE c_id = $course_id AND user_id = '$user_id'";
2038
        $result = Database::query($sql);
2039
2040
        if ($result) {
2041
            while ($row = Database::fetch_array($result)) {
2042
                $groups[] = $row['group_id'];
2043
            }
2044
        }
2045
2046
        //Also loading if i'm the tutor
2047
        $sql = "SELECT group_id FROM $tbl_group_tutor
2048
                WHERE c_id = $course_id AND user_id = '$user_id'";
2049
        $result = Database::query($sql);
2050
        if ($result) {
2051
            while ($row = Database::fetch_array($result)) {
2052
                $groups[] = $row['group_id'];
2053
            }
2054
        }
2055
        if (!empty($groups)) {
2056
            array_filter($groups);
2057
        }
2058
2059
        return $groups;
2060
    }
2061
2062
    /**
2063
     * Remove all users that are not students and all users who have tutor status
2064
     * from  the list.
2065
     *
2066
     * @param array $user_array_in
2067
     *
2068
     * @return array
2069
     */
2070
    public static function filter_only_students($user_array_in)
2071
    {
2072
        $user_array_out = [];
2073
        foreach ($user_array_in as $this_user) {
2074
            if (api_get_session_id()) {
2075
                if ($this_user['status_session'] == 0) {
2076
                    $user_array_out[] = $this_user;
2077
                }
2078
            } else {
2079
                if ($this_user['status_rel'] == STUDENT) {
2080
                    $user_array_out[] = $this_user;
2081
                }
2082
            }
2083
        }
2084
2085
        return $user_array_out;
2086
    }
2087
2088
    /**
2089
     * Check if a user has access to a certain group tool.
2090
     *
2091
     * @param int    $user_id  The user id
2092
     * @param int    $group_id The group iid
2093
     * @param string $tool     The tool to check the access rights. This should be
2094
     *                         one of constants: GROUP_TOOL_DOCUMENTS
2095
     *
2096
     * @return bool true if the given user has access to the given tool in the
2097
     *              given course
2098
     */
2099
    public static function user_has_access($user_id, $group_id, $tool)
2100
    {
2101
        // Admin have access everywhere
2102
        if (api_is_platform_admin()) {
2103
            return true;
2104
        }
2105
2106
        // Course admin also have access to everything
2107
        if (api_is_allowed_to_edit()) {
2108
            return true;
2109
        }
2110
2111
        switch ($tool) {
2112
            case self::GROUP_TOOL_FORUM:
2113
                $key = 'forum_state';
2114
                break;
2115
            case self::GROUP_TOOL_DOCUMENTS:
2116
                $key = 'doc_state';
2117
                break;
2118
            case self::GROUP_TOOL_CALENDAR:
2119
                $key = 'calendar_state';
2120
                break;
2121
            case self::GROUP_TOOL_ANNOUNCEMENT:
2122
                $key = 'announcements_state';
2123
                break;
2124
            case self::GROUP_TOOL_WORK:
2125
                $key = 'work_state';
2126
                break;
2127
            case self::GROUP_TOOL_WIKI:
2128
                $key = 'wiki_state';
2129
                break;
2130
            case self::GROUP_TOOL_CHAT:
2131
                $key = 'chat_state';
2132
                break;
2133
            default:
2134
                return false;
2135
        }
2136
2137
        // Check group properties
2138
        $groupInfo = self::get_group_properties($group_id, true);
2139
2140
        if (empty($groupInfo)) {
2141
            return false;
2142
        }
2143
2144
        if ($groupInfo['status'] == 0) {
2145
            return false;
2146
        }
2147
2148
        if (!isset($groupInfo[$key])) {
2149
            return false;
2150
        }
2151
2152
        if (api_is_allowed_to_edit(false, true)) {
2153
            return true;
2154
        }
2155
2156
        $status = $groupInfo[$key];
2157
2158
        switch ($status) {
2159
            case self::TOOL_NOT_AVAILABLE:
2160
                return false;
2161
                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...
2162
            case self::TOOL_PUBLIC:
2163
                return true;
2164
                break;
2165
            case self::TOOL_PRIVATE:
2166
                $userIsInGroup = self::is_user_in_group($user_id, $groupInfo);
2167
                if ($userIsInGroup) {
2168
                    return true;
2169
                }
2170
                break;
2171
        }
2172
2173
        return false;
2174
    }
2175
2176
    /**
2177
     * @param int   $userId
2178
     * @param array $groupInfo
2179
     * @param int   $sessionId
2180
     *
2181
     * @return bool
2182
     */
2183
    public static function userHasAccessToBrowse($userId, $groupInfo, $sessionId = 0)
2184
    {
2185
        if (empty($groupInfo)) {
2186
            return false;
2187
        }
2188
2189
        if (api_is_platform_admin()) {
2190
            return true;
2191
        }
2192
2193
        if (api_is_allowed_to_edit(false, true)) {
2194
            return true;
2195
        }
2196
2197
        $groupId = $groupInfo['iid'];
2198
        $tutors = self::get_subscribed_tutors($groupInfo, true);
2199
2200
        if (in_array($userId, $tutors)) {
2201
            return true;
2202
        }
2203
2204
        if ($groupInfo['status'] == 0) {
2205
            return false;
2206
        }
2207
2208
        if (self::user_has_access($userId, $groupId, self::GROUP_TOOL_FORUM) ||
2209
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_DOCUMENTS) ||
2210
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_CALENDAR) ||
2211
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_ANNOUNCEMENT) ||
2212
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_WORK) ||
2213
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_WIKI) ||
2214
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_CHAT)
2215
        ) {
2216
            return true;
2217
        }
2218
2219
        if (api_is_session_general_coach() && $groupInfo['session_id'] == $sessionId) {
2220
            return true;
2221
        }
2222
2223
        return false;
2224
    }
2225
2226
    /**
2227
     * Get all groups where a specific user is subscribed.
2228
     *
2229
     * @param int $user_id
2230
     *
2231
     * @return array
2232
     */
2233
    public static function get_user_group_name($user_id)
2234
    {
2235
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
2236
        $table_group = Database::get_course_table(TABLE_GROUP);
2237
        $user_id = intval($user_id);
2238
        $course_id = api_get_course_int_id();
2239
        $sql = "SELECT name
2240
                FROM $table_group g 
2241
                INNER JOIN $table_group_user gu
2242
                ON (gu.group_id = g.iid)
2243
                WHERE
2244
                  gu.c_id= $course_id AND
2245
                  g.c_id= $course_id AND
2246
                  gu.user_id = $user_id";
2247
        $res = Database::query($sql);
2248
        $groups = [];
2249
        while ($group = Database::fetch_array($res)) {
2250
            $groups[] .= $group['name'];
2251
        }
2252
2253
        return $groups;
2254
    }
2255
2256
    /**
2257
     * Get all groups where a specific user is subscribed.
2258
     *
2259
     * @param int $user_id
2260
     *
2261
     * @return array
2262
     */
2263
    public static function getAllGroupPerUserSubscription($user_id)
2264
    {
2265
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
2266
        $table_tutor_user = Database::get_course_table(TABLE_GROUP_TUTOR);
2267
        $table_group = Database::get_course_table(TABLE_GROUP);
2268
        $user_id = intval($user_id);
2269
        $course_id = api_get_course_int_id();
2270
        $sql = "SELECT DISTINCT g.*
2271
               FROM $table_group g
2272
               LEFT JOIN $table_group_user gu
2273
               ON (gu.group_id = g.iid AND g.c_id = gu.c_id)
2274
               LEFT JOIN $table_tutor_user tu
2275
               ON (tu.group_id = g.iid AND g.c_id = tu.c_id)
2276
               WHERE
2277
                  g.c_id = $course_id AND
2278
                  (gu.user_id = $user_id OR tu.user_id = $user_id) ";
2279
        $res = Database::query($sql);
2280
        $groups = [];
2281
        while ($group = Database::fetch_array($res, 'ASSOC')) {
2282
            $groups[] = $group;
2283
        }
2284
2285
        return $groups;
2286
    }
2287
2288
    /**
2289
     * @param array $userList
2290
     * @param array $groupInfo
2291
     *
2292
     * @return mixed
2293
     */
2294
    public static function getNumberLeftFromGroupFromUserList($userList, $groupInfo)
2295
    {
2296
        $groupIid = (int) $groupInfo['iid'];
2297
        $category = self::get_category_from_group($groupIid);
2298
        $number_groups_per_user = $groupInfo['maximum_number_of_students'];
2299
        $categoryId = 0;
2300
        if ($category) {
2301
            $groups_per_user = $category['groups_per_user'];
2302
            $number_groups_per_user = $groups_per_user == self::GROUP_PER_MEMBER_NO_LIMIT ? self::INFINITE : $groups_per_user;
2303
            $categoryId = $category['id'];
2304
        }
2305
2306
        $usersAdded = [];
2307
        foreach ($userList as &$userInfo) {
2308
            // find # of groups the user is enrolled in
2309
            $numberOfGroups = self::user_in_number_of_groups(
2310
                $userInfo['user_id'],
2311
                $categoryId
2312
            );
2313
2314
            if (in_array($userInfo['user_id'], $usersAdded)) {
2315
                continue;
2316
            }
2317
2318
            $usersAdded[] = $userInfo['user_id'];
2319
2320
            // add # of groups to user list
2321
            $userInfo['number_groups_left'] = $number_groups_per_user - $numberOfGroups;
2322
        }
2323
2324
        return $userList;
2325
    }
2326
2327
    /**
2328
     * @param array $group_list
2329
     * @param int   $category_id
2330
     *
2331
     * @return string
2332
     */
2333
    public static function process_groups($group_list, $category_id = 0)
2334
    {
2335
        global $charset;
2336
        $category_id = (int) $category_id;
2337
        $totalRegistered = 0;
2338
        $group_data = [];
2339
        $user_info = api_get_user_info();
2340
        $session_id = api_get_session_id();
2341
        $user_id = $user_info['user_id'];
2342
        $hideGroup = api_get_setting('hide_course_group_if_no_tools_available');
2343
2344
        foreach ($group_list as $this_group) {
2345
            // Validation when belongs to a session
2346
            $session_img = api_get_session_image($this_group['session_id'], $user_info['status']);
2347
2348
            // All the tutors of this group
2349
            $tutorsids_of_group = self::get_subscribed_tutors($this_group, true);
2350
            $isMember = self::is_subscribed($user_id, $this_group);
2351
2352
            // Create a new table-row
2353
            $row = [];
2354
            // Checkbox
2355
            if (api_is_allowed_to_edit(false, true) && count($group_list) > 1) {
2356
                $row[] = $this_group['id'];
2357
            }
2358
2359
            if (self::userHasAccessToBrowse($user_id, $this_group, $session_id)) {
2360
                // Group name
2361
                $groupNameClass = null;
2362
                if ($this_group['status'] == 0) {
2363
                    $groupNameClass = 'muted';
2364
                }
2365
2366
                $group_name = '<a class="'.$groupNameClass.'" href="group_space.php?'.api_get_cidreq(true, false).'&gidReq='.$this_group['id'].'">'.
2367
                    Security::remove_XSS($this_group['name']).'</a> ';
2368
2369
                $group_name2 = '';
2370
                if (api_get_configuration_value('extra')) {
2371
                    $group_name2 = '<a href="group_space_tracking.php?cidReq='.api_get_course_id().'&gidReq='
2372
                        .$this_group['id'].'">'.get_lang('suivi_de').''.stripslashes($this_group['name']).'</a>';
2373
                }
2374
2375
                if (!empty($user_id) && !empty($this_group['id_tutor']) && $user_id == $this_group['id_tutor']) {
2376
                    $group_name .= Display::label(get_lang('OneMyGroups'), 'success');
2377
                } elseif ($isMember) {
2378
                    $group_name .= Display::label(get_lang('MyGroup'), 'success');
2379
                }
2380
2381
                if (api_is_allowed_to_edit() && !empty($this_group['session_name'])) {
2382
                    $group_name .= ' ('.$this_group['session_name'].')';
2383
                }
2384
                $group_name .= $session_img;
2385
                $row[] = $group_name.$group_name2.'<br />'.stripslashes(trim($this_group['description']));
2386
            } else {
2387
                if ($hideGroup === 'true') {
2388
                    continue;
2389
                }
2390
                $row[] = $this_group['name'].'<br />'.stripslashes(trim($this_group['description']));
2391
            }
2392
2393
            // Tutor name
2394
            $tutor_info = '';
2395
            if (count($tutorsids_of_group) > 0) {
2396
                foreach ($tutorsids_of_group as $tutor_id) {
2397
                    $tutor = api_get_user_info($tutor_id);
2398
                    $username = api_htmlentities(
2399
                        sprintf(get_lang('LoginX'), $tutor['username']),
2400
                        ENT_QUOTES
2401
                    );
2402
                    if (api_get_setting('show_email_addresses') === 'true') {
2403
                        $tutor_info .= Display::tag(
2404
                            'span',
2405
                            Display::encrypted_mailto_link(
2406
                                $tutor['mail'],
2407
                                $tutor['complete_name']
2408
                            ),
2409
                            ['title' => $username]
2410
                        ).', ';
2411
                    } else {
2412
                        if (api_is_allowed_to_edit()) {
2413
                            $tutor_info .= Display::tag(
2414
                            'span',
2415
                                Display::encrypted_mailto_link(
2416
                                    $tutor['mail'],
2417
                                    $tutor['complete_name_with_username']
2418
                                ),
2419
                                ['title' => $username]
2420
                            ).', ';
2421
                        } else {
2422
                            $tutor_info .= Display::tag(
2423
                                'span',
2424
                                $tutor['complete_name'],
2425
                                ['title' => $username]
2426
                            ).', ';
2427
                        }
2428
                    }
2429
                }
2430
            }
2431
2432
            $tutor_info = api_substr(
2433
                $tutor_info,
2434
                0,
2435
                api_strlen($tutor_info) - 2
2436
            );
2437
            $row[] = $tutor_info;
2438
2439
            // Max number of members in group
2440
            $max_members = $this_group['maximum_number_of_members'] == self::MEMBER_PER_GROUP_NO_LIMIT ? ' ' : ' / '.$this_group['maximum_number_of_members'];
2441
2442
            // Number of members in group
2443
            $row[] = $this_group['number_of_members'].$max_members;
2444
2445
            // Self-registration / unregistration
2446
            if (!api_is_allowed_to_edit(false, true)) {
2447
                if (self::is_self_registration_allowed($user_id, $this_group)) {
2448
                    $row[] = '<a class = "btn btn-default" href="group.php?'.api_get_cidreq().'&category='.$category_id.'&action=self_reg&group_id='.$this_group['id'].'" onclick="javascript:if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES, $charset))."'".')) return false;">'.get_lang('GroupSelfRegInf').'</a>';
2449
                } elseif (self::is_self_unregistration_allowed($user_id, $this_group)) {
2450
                    $row[] = '<a class = "btn btn-default" href="group.php?'.api_get_cidreq().'&category='.$category_id.'&action=self_unreg&group_id='.$this_group['id'].'" onclick="javascript:if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES, $charset))."'".')) return false;">'.get_lang('GroupSelfUnRegInf').'</a>';
2451
                } else {
2452
                    $row[] = '-';
2453
                }
2454
            }
2455
2456
            $url = api_get_path(WEB_CODE_PATH).'group/';
2457
            // Edit-links
2458
            if (api_is_allowed_to_edit(false, true) &&
2459
                !(api_is_session_general_coach() && intval($this_group['session_id']) != $session_id)
2460
            ) {
2461
                $edit_actions = '<a href="'.$url.'settings.php?'.api_get_cidreq(true, false).'&gidReq='.$this_group['id'].'"  title="'.get_lang('Edit').'">'.
2462
                    Display::return_icon('edit.png', get_lang('EditGroup'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2463
2464
                if ($this_group['status'] == 1) {
2465
                    $edit_actions .= '<a href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=set_invisible&id='.$this_group['id'].'" title="'.get_lang('Hide').'">'.
2466
                        Display::return_icon('visible.png', get_lang('Hide'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2467
                } else {
2468
                    $edit_actions .= '<a href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=set_visible&id='.$this_group['id'].'" title="'.get_lang('Show').'">'.
2469
                        Display::return_icon('invisible.png', get_lang('Show'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2470
                }
2471
2472
                $edit_actions .= '<a href="'.$url.'member_settings.php?'.api_get_cidreq(true, false).'&gidReq='.$this_group['id'].'"  title="'.get_lang('GroupMembers').'">'.
2473
                    Display::return_icon('user.png', get_lang('GroupMembers'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2474
2475
                $edit_actions .= '<a href="'.$url.'group_overview.php?action=export&type=xls&'.api_get_cidreq(true, false).'&id='.$this_group['id'].'"  title="'.get_lang('ExportUsers').'">'.
2476
                    Display::return_icon('export_excel.png', get_lang('Export'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2477
2478
                $edit_actions .= '<a href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=fill_one&id='.$this_group['id'].'" onclick="javascript: if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES))."'".')) return false;" title="'.get_lang('FillGroup').'">'.
2479
                    Display::return_icon('fill.png', get_lang('FillGroup'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2480
2481
                $edit_actions .= '<a href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=delete_one&id='.$this_group['id'].'" onclick="javascript: if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES))."'".')) return false;" title="'.get_lang('Delete').'">'.
2482
                    Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2483
2484
                $row[] = $edit_actions;
2485
            }
2486
            if (!empty($this_group['nbMember'])) {
2487
                $totalRegistered = $totalRegistered + $this_group['nbMember'];
2488
            }
2489
            $group_data[] = $row;
2490
        } // end loop
2491
2492
        // If no groups then don't show the table (only for students)
2493
        if (!api_is_allowed_to_edit(true, false)) {
2494
            if (empty($group_data)) {
2495
                return '';
2496
            }
2497
        }
2498
2499
        $table = new SortableTableFromArrayConfig(
2500
            $group_data,
2501
            1,
2502
            20,
2503
            'group_category_'.$category_id
2504
        );
2505
        $table->set_additional_parameters(['category' => $category_id]);
2506
        $column = 0;
2507
        if (api_is_allowed_to_edit(false, true) and count($group_list) > 1) {
2508
            $table->set_header($column++, '', false);
2509
        }
2510
        $table->set_header($column++, get_lang('Groups'));
2511
        $table->set_header($column++, get_lang('GroupTutor'));
2512
        $table->set_header($column++, get_lang('Registered'), false);
2513
2514
        if (!api_is_allowed_to_edit(false, true)) {
2515
            // If self-registration allowed
2516
            $table->set_header($column++, get_lang('GroupSelfRegistration'), false);
2517
        }
2518
2519
        if (api_is_allowed_to_edit(false, true)) {
2520
            // Only for course administrator
2521
            $table->set_header($column++, get_lang('Modify'), false);
2522
            $form_actions = [];
2523
            $form_actions['fill_selected'] = get_lang('FillGroup');
2524
            $form_actions['empty_selected'] = get_lang('EmptyGroup');
2525
            $form_actions['delete_selected'] = get_lang('Delete');
2526
            if (count($group_list) > 1) {
2527
                $table->set_form_actions($form_actions, 'group');
2528
            }
2529
        }
2530
2531
        return $table->return_table();
2532
    }
2533
2534
    /**
2535
     * @param array $groupData
2536
     * @param bool  $deleteNotInArray
2537
     *
2538
     * @return array
2539
     */
2540
    public static function importCategoriesAndGroupsFromArray(
2541
        $groupData,
2542
        $deleteNotInArray = false
2543
    ) {
2544
        $result = [];
2545
        $elementsFound = [
2546
            'categories' => [],
2547
            'groups' => [],
2548
        ];
2549
2550
        $courseCode = api_get_course_id();
2551
        $sessionId = api_get_session_id();
2552
        $groupCategories = self::get_categories();
2553
2554
        if (empty($groupCategories)) {
2555
            $result['error'][] = get_lang('CreateACategory');
2556
2557
            return $result;
2558
        }
2559
2560
        foreach ($groupData as $data) {
2561
            $isCategory = empty($data['group']) ? true : false;
2562
            if ($isCategory) {
2563
                $categoryInfo = self::getCategoryByTitle($data['category']);
2564
                $categoryId = $categoryInfo['id'];
2565
2566
                if (!empty($categoryInfo)) {
2567
                    // Update
2568
                    self::update_category(
2569
                        $categoryId,
2570
                        $data['category'],
2571
                        $data['description'],
2572
                        $data['doc_state'],
2573
                        $data['work_state'],
2574
                        $data['calendar_state'],
2575
                        $data['announcements_state'],
2576
                        $data['forum_state'],
2577
                        $data['wiki_state'],
2578
                        $data['chat_state'],
2579
                        $data['self_reg_allowed'],
2580
                        $data['self_unreg_allowed'],
2581
                        $data['max_student'],
2582
                        $data['groups_per_user']
2583
                    );
2584
                    $data['category_id'] = $categoryId;
2585
                    $result['updated']['category'][] = $data;
2586
                } else {
2587
                    // Add
2588
                    $categoryId = self::create_category(
2589
                        $data['category'],
2590
                        $data['description'],
2591
                        $data['doc_state'],
2592
                        $data['work_state'],
2593
                        $data['calendar_state'],
2594
                        $data['announcements_state'],
2595
                        $data['forum_state'],
2596
                        $data['wiki_state'],
2597
                        $data['chat_state'],
2598
                        $data['self_reg_allowed'],
2599
                        $data['self_unreg_allowed'],
2600
                        $data['max_student'],
2601
                        $data['groups_per_user']
2602
                    );
2603
2604
                    if ($categoryId) {
2605
                        $data['category_id'] = $categoryId;
2606
                        $result['added']['category'][] = $data;
2607
                    }
2608
                }
2609
                $elementsFound['categories'][] = $categoryId;
2610
            } else {
2611
                $groupInfo = self::getGroupByName($data['group']);
2612
                $categoryInfo = [];
2613
                if (isset($data['category'])) {
2614
                    $categoryInfo = self::getCategoryByTitle($data['category']);
2615
                }
2616
                $categoryId = null;
2617
                if (!empty($categoryInfo)) {
2618
                    $categoryId = $categoryInfo['id'];
2619
                } else {
2620
                    if (!empty($groupCategories) && isset($groupCategories[0])) {
2621
                        $defaultGroupCategory = $groupCategories[0];
2622
                        $categoryId = $defaultGroupCategory['id'];
2623
                    }
2624
                }
2625
2626
                if (empty($groupInfo)) {
2627
                    // Add
2628
                    $groupId = self::create_group(
2629
                        $data['group'],
2630
                        $categoryId,
2631
                        null,
2632
                        $data['max_student']
2633
                    );
2634
2635
                    if ($groupId) {
2636
                        self::set_group_properties(
2637
                            $groupId,
2638
                            $data['group'],
2639
                            $data['description'],
2640
                            $data['max_student'],
2641
                            $data['doc_state'],
2642
                            $data['work_state'],
2643
                            $data['calendar_state'],
2644
                            $data['announcements_state'],
2645
                            $data['forum_state'],
2646
                            $data['wiki_state'],
2647
                            $data['chat_state'],
2648
                            $data['self_reg_allowed'],
2649
                            $data['self_unreg_allowed'],
2650
                            $categoryId
2651
                        );
2652
                        $data['group_id'] = $groupId;
2653
                        $result['added']['group'][] = $data;
2654
                    }
2655
                    $groupInfo = self::get_group_properties($groupId, true);
2656
                } else {
2657
                    // Update
2658
                    $groupId = $groupInfo['id'];
2659
                    self::set_group_properties(
2660
                        $groupId,
2661
                        $data['group'],
2662
                        $data['description'],
2663
                        $data['max_student'],
2664
                        $data['doc_state'],
2665
                        $data['work_state'],
2666
                        $data['calendar_state'],
2667
                        $data['announcements_state'],
2668
                        $data['forum_state'],
2669
                        $data['wiki_state'],
2670
                        $data['chat_state'],
2671
                        $data['self_reg_allowed'],
2672
                        $data['self_unreg_allowed'],
2673
                        $categoryId
2674
                    );
2675
2676
                    $data['group_id'] = $groupId;
2677
                    $result['updated']['group'][] = $data;
2678
                    $groupInfo = self::get_group_properties($groupId);
2679
                }
2680
2681
                $students = isset($data['students']) ? explode(',', $data['students']) : [];
2682
                if (!empty($students)) {
2683
                    $studentUserIdList = [];
2684
                    foreach ($students as $student) {
2685
                        $userInfo = api_get_user_info_from_username($student);
2686
2687
                        if (!$userInfo) {
2688
                            continue;
2689
                        }
2690
2691
                        if (!CourseManager::is_user_subscribed_in_course(
2692
                                $userInfo['user_id'],
2693
                                $courseCode,
2694
                                !empty($sessionId),
2695
                                $sessionId
2696
                            )
2697
                        ) {
2698
                            Display::addFlash(
2699
                                Display::return_message(
2700
                                    sprintf(
2701
                                        get_lang('StudentXIsNotSubscribedToCourse'),
2702
                                        $userInfo['complete_name']
2703
                                    ),
2704
                                    'warning'
2705
                                )
2706
                            );
2707
                            continue;
2708
                        }
2709
2710
                        $studentUserIdList[] = $userInfo['user_id'];
2711
                    }
2712
                    self::subscribe_users($studentUserIdList, $groupInfo);
2713
                }
2714
2715
                $tutors = isset($data['tutors']) ? explode(',', $data['tutors']) : [];
2716
                if (!empty($tutors)) {
2717
                    $tutorIdList = [];
2718
                    foreach ($tutors as $tutor) {
2719
                        $userInfo = api_get_user_info_from_username($tutor);
2720
2721
                        if (!$userInfo) {
2722
                            continue;
2723
                        }
2724
2725
                        if (!CourseManager::is_user_subscribed_in_course(
2726
                                $userInfo['user_id'],
2727
                                $courseCode,
2728
                                !empty($sessionId),
2729
                                $sessionId
2730
                            )
2731
                        ) {
2732
                            Display::addFlash(
2733
                                Display::return_message(
2734
                                    sprintf(get_lang('TutorXIsNotSubscribedToCourse'), $userInfo['complete_name']),
2735
                                    'warning'
2736
                                )
2737
                            );
2738
2739
                            continue;
2740
                        }
2741
2742
                        $tutorIdList[] = $userInfo['user_id'];
2743
                    }
2744
                    self::subscribe_tutors($tutorIdList, $groupInfo);
2745
                }
2746
2747
                $elementsFound['groups'][] = $groupId;
2748
            }
2749
        }
2750
2751
        if ($deleteNotInArray) {
2752
            // Check categories
2753
            $categories = self::get_categories();
2754
            foreach ($categories as $category) {
2755
                if (!in_array($category['id'], $elementsFound['categories'])) {
2756
                    self::delete_category($category['id']);
2757
                    $category['category'] = $category['title'];
2758
                    $result['deleted']['category'][] = $category;
2759
                }
2760
            }
2761
2762
            $groups = self::get_groups();
2763
            foreach ($groups as $group) {
2764
                if (!in_array($group['iid'], $elementsFound['groups'])) {
2765
                    self::deleteGroup($group);
2766
                    $group['group'] = $group['name'];
2767
                    $result['deleted']['group'][] = $group;
2768
                }
2769
            }
2770
        }
2771
2772
        return $result;
2773
    }
2774
2775
    /**
2776
     * Export all categories/group from a course to an array.
2777
     * This function works only in a context of a course.
2778
     *
2779
     * @param int  $groupId
2780
     * @param bool $loadUsers
2781
     *
2782
     * @return array
2783
     */
2784
    public static function exportCategoriesAndGroupsToArray($groupId = null, $loadUsers = false)
2785
    {
2786
        $data = [];
2787
        $data[] = [
2788
            'category',
2789
            'group',
2790
            'description',
2791
            'announcements_state',
2792
            'calendar_state',
2793
            'chat_state',
2794
            'doc_state',
2795
            'forum_state',
2796
            'work_state',
2797
            'wiki_state',
2798
            'max_student',
2799
            'self_reg_allowed',
2800
            'self_unreg_allowed',
2801
            'groups_per_user',
2802
        ];
2803
2804
        $count = 1;
2805
2806
        if ($loadUsers) {
2807
            $data[0][] = 'students';
2808
            $data[0][] = 'tutors';
2809
        }
2810
2811
        if ($loadUsers == false) {
2812
            $categories = self::get_categories();
2813
2814
            foreach ($categories as $categoryInfo) {
2815
                $data[$count] = [
2816
                    $categoryInfo['title'],
2817
                    null,
2818
                    $categoryInfo['description'],
2819
                    $categoryInfo['announcements_state'],
2820
                    $categoryInfo['calendar_state'],
2821
                    $categoryInfo['chat_state'],
2822
                    $categoryInfo['doc_state'],
2823
                    $categoryInfo['forum_state'],
2824
                    $categoryInfo['work_state'],
2825
                    $categoryInfo['wiki_state'],
2826
                    $categoryInfo['max_student'],
2827
                    $categoryInfo['self_reg_allowed'],
2828
                    $categoryInfo['self_unreg_allowed'],
2829
                    $categoryInfo['groups_per_user'],
2830
                ];
2831
                $count++;
2832
            }
2833
        }
2834
2835
        $groups = self::get_group_list();
2836
2837
        foreach ($groups as $groupInfo) {
2838
            $categoryTitle = null;
2839
            $categoryInfo = self::get_category($groupInfo['category_id']);
2840
            $groupSettings = self::get_group_properties($groupInfo['id']);
2841
            if (!empty($categoryInfo)) {
2842
                $categoryTitle = $categoryInfo['title'];
2843
            }
2844
2845
            $users = self::getStudents($groupInfo['iid']);
2846
            $userList = [];
2847
            foreach ($users as $user) {
2848
                $user = api_get_user_info($user['user_id']);
2849
                $userList[] = $user['username'];
2850
            }
2851
2852
            $tutors = self::getTutors($groupInfo);
2853
            $tutorList = [];
2854
            foreach ($tutors as $user) {
2855
                $user = api_get_user_info($user['user_id']);
2856
                $tutorList[] = $user['username'];
2857
            }
2858
2859
            $userListToString = null;
2860
            if (!empty($userList)) {
2861
                $userListToString = implode(',', $userList);
2862
            }
2863
2864
            $tutorListToString = null;
2865
            if (!empty($tutorList)) {
2866
                $tutorListToString = implode(',', $tutorList);
2867
            }
2868
2869
            $data[$count] = [
2870
                $categoryTitle,
2871
                $groupSettings['name'],
2872
                $groupSettings['description'],
2873
                $groupSettings['announcements_state'],
2874
                $groupSettings['calendar_state'],
2875
                $groupSettings['chat_state'],
2876
                $groupSettings['doc_state'],
2877
                $groupSettings['forum_state'],
2878
                $groupSettings['work_state'],
2879
                $groupSettings['wiki_state'],
2880
                $groupSettings['maximum_number_of_students'],
2881
                $groupSettings['self_registration_allowed'],
2882
                $groupSettings['self_unregistration_allowed'],
2883
                null,
2884
            ];
2885
2886
            if ($loadUsers) {
2887
                $data[$count][] = $userListToString;
2888
                $data[$count][] = $tutorListToString;
2889
            }
2890
2891
            if (!empty($groupId)) {
2892
                if ($groupId == $groupInfo['id']) {
2893
                    break;
2894
                }
2895
            }
2896
            $count++;
2897
        }
2898
2899
        return $data;
2900
    }
2901
2902
    /**
2903
     * @param string $default
2904
     */
2905
    public static function getSettingBar($default)
2906
    {
2907
        $activeSettings = null;
2908
        $activeTutor = null;
2909
        $activeMember = null;
2910
2911
        switch ($default) {
2912
            case 'settings':
2913
                $activeSettings = 'active';
2914
                break;
2915
            case'tutor':
2916
                $activeTutor = 'active';
2917
                break;
2918
            case 'member':
2919
                $activeMember = 'active';
2920
                break;
2921
        }
2922
2923
        $url = api_get_path(WEB_CODE_PATH).'group/%s?'.api_get_cidreq();
2924
2925
        echo '
2926
            <ul class="toolbar-groups nav nav-tabs">
2927
                <li class="'.$activeSettings.'">
2928
                    <a href="'.sprintf($url, 'settings.php').'">
2929
                    '.Display::return_icon('settings.png').' '.get_lang('Settings').'
2930
                    </a>
2931
                </li>
2932
                <li class="'.$activeMember.'">
2933
                    <a href="'.sprintf($url, 'member_settings.php').'">
2934
                    '.Display::return_icon('user.png').' '.get_lang('GroupMembers').'
2935
                    </a>
2936
                </li>
2937
                <li class="'.$activeTutor.'">
2938
                    <a href="'.sprintf($url, 'tutor_settings.php').'">
2939
                    '.Display::return_icon('teacher.png').' '.get_lang('GroupTutors').'
2940
                    </a>
2941
                </li>
2942
            </ul>';
2943
    }
2944
2945
    /**
2946
     * @param int    $courseId
2947
     * @param string $keyword
2948
     *
2949
     * @return string
2950
     */
2951
    public static function getOverview($courseId, $keyword = null)
2952
    {
2953
        $content = null;
2954
        $categories = self::get_categories();
2955
        if (!empty($categories)) {
2956
            foreach ($categories as $category) {
2957
                if (api_get_setting('allow_group_categories') == 'true') {
2958
                    $content .= '<h2>'.$category['title'].'</h2>';
2959
                }
2960
                if (!empty($keyword)) {
2961
                    $groups = self::getGroupListFilterByName(
2962
                        $keyword,
2963
                        $category['id'],
2964
                        $courseId
2965
                    );
2966
                } else {
2967
                    $groups = self::get_group_list($category['id']);
2968
                }
2969
2970
                if (empty($groups)) {
2971
                    $groups = self::get_group_list();
2972
                }
2973
2974
                $content .= '<ul>';
2975
                if (!empty($groups)) {
2976
                    foreach ($groups as $group) {
2977
                        $content .= '<li>';
2978
                        $content .= Display::tag(
2979
                            'h3',
2980
                            Security::remove_XSS($group['name'])
2981
                        );
2982
                        $users = self::getTutors($group);
2983
                        if (!empty($users)) {
2984
                            $content .= '<ul>';
2985
                            $content .= "<li>".Display::tag('h4', get_lang('Tutors'))."</li><ul>";
2986
                            foreach ($users as $user) {
2987
                                $user_info = api_get_user_info($user['user_id']);
2988
                                $content .= '<li title="'.$user_info['username'].'">'.
2989
                                    $user_info['complete_name_with_username'].
2990
                                '</li>';
2991
                            }
2992
                            $content .= '</ul>';
2993
                            $content .= '</ul>';
2994
                        }
2995
2996
                        $users = self::getStudents($group['id']);
2997
                        if (!empty($users)) {
2998
                            $content .= '<ul>';
2999
                            $content .= "<li>".Display::tag('h4', get_lang('Students'))."</li><ul>";
3000
                            foreach ($users as $user) {
3001
                                $user_info = api_get_user_info($user['user_id']);
3002
                                $content .= '<li title="'.$user_info['username'].'">'.
3003
                                    $user_info['complete_name_with_username'].
3004
                                    '</li>';
3005
                            }
3006
                            $content .= '</ul>';
3007
                            $content .= '</ul>';
3008
                        }
3009
                        $content .= '</li>';
3010
                    }
3011
                }
3012
                $content .= '</ul>';
3013
            }
3014
        }
3015
3016
        return $content;
3017
    }
3018
3019
    /**
3020
     * Returns the search form.
3021
     *
3022
     * @return string
3023
     */
3024
    public static function getSearchForm()
3025
    {
3026
        $url = api_get_path(WEB_CODE_PATH).'group/group_overview.php?'.api_get_cidreq();
3027
        $form = new FormValidator(
3028
            'search_groups',
3029
            'get',
3030
            $url,
3031
            null,
3032
            ['class' => 'form-search'],
3033
            FormValidator::LAYOUT_INLINE
3034
        );
3035
        $form->addElement('text', 'keyword');
3036
        $form->addButtonSearch();
3037
3038
        return $form->toHtml();
3039
    }
3040
3041
    /**
3042
     * @param int $groupId
3043
     * @param int $status
3044
     */
3045
    public static function setStatus($groupId, $status)
3046
    {
3047
        $groupInfo = self::get_group_properties($groupId);
3048
3049
        $courseId = api_get_course_int_id();
3050
        if (!empty($groupInfo)) {
3051
            $table = Database::get_course_table(TABLE_GROUP);
3052
            $params = [
3053
                'status' => intval($status),
3054
            ];
3055
            Database::update(
3056
                $table,
3057
                $params,
3058
                ['c_id = ? AND id = ?' => [$courseId, $groupId]]
3059
            );
3060
        }
3061
    }
3062
3063
    /**
3064
     * @param int $groupId
3065
     */
3066
    public static function setVisible($groupId)
3067
    {
3068
        self::setStatus($groupId, 1);
3069
    }
3070
3071
    /**
3072
     * @param int $groupId
3073
     */
3074
    public static function setInvisible($groupId)
3075
    {
3076
        self::setStatus($groupId, 0);
3077
    }
3078
3079
    /**
3080
     * @param int   $userId
3081
     * @param int   $courseId
3082
     * @param array $groupInfo
3083
     * @param array $documentInfoToBeCheck
3084
     * @param bool  $blockPage
3085
     *
3086
     * @return bool
3087
     */
3088
    public static function allowUploadEditDocument(
3089
        $userId,
3090
        $courseId,
3091
        $groupInfo,
3092
        $documentInfoToBeCheck = null,
3093
        $blockPage = false
3094
    ) {
3095
        // Admin and teachers can make any change no matter what
3096
        if (api_is_platform_admin() || api_is_allowed_to_edit(false, true)) {
3097
            return true;
3098
        }
3099
3100
        if (empty($groupInfo) || !isset($groupInfo['id'])) {
3101
            if ($blockPage) {
3102
                api_not_allowed(true);
3103
            }
3104
3105
            return false;
3106
        }
3107
3108
        // Tutor can also make any change
3109
        $isTutor = self::is_tutor_of_group($userId, $groupInfo, $courseId);
3110
3111
        if ($isTutor) {
3112
            return true;
3113
        }
3114
3115
        // Just in case also check if document in group is available
3116
        if ($groupInfo['doc_state'] == 0) {
3117
            if ($blockPage) {
3118
                api_not_allowed(true);
3119
            }
3120
3121
            return false;
3122
        }
3123
3124
        // Default behaviour
3125
        $documentAccess = self::DOCUMENT_MODE_SHARE;
3126
3127
        // Check category document access
3128
        /*$allowCategoryGroupDocumentAccess = api_get_configuration_value('group_category_document_access');
3129
        if ($allowCategoryGroupDocumentAccess) {
3130
            $category = GroupManager::get_category_from_group($groupInfo['iid']);
3131
            if (!empty($category) && isset($category['document_access'])) {
3132
                $documentAccess = (int) $category['document_access'];
3133
            }
3134
        }*/
3135
3136
        // Check group document access
3137
        $allow = api_get_configuration_value('group_document_access');
3138
        if ($allow) {
3139
            if (isset($groupInfo['document_access'])) {
3140
                $documentAccess = (int) $groupInfo['document_access'];
3141
            }
3142
        }
3143
3144
        // Check access for students
3145
        $result = false;
3146
        switch ($documentAccess) {
3147
            case self::DOCUMENT_MODE_SHARE:
3148
                // Default chamilo behaviour
3149
                // Student can upload his own content, cannot modify another content.
3150
                $isMember = self::is_subscribed($userId, $groupInfo);
3151
                if ($isMember) {
3152
                    // No document to check, allow access to document feature.
3153
                    if (empty($documentInfoToBeCheck)) {
3154
                        $result = true;
3155
                    } else {
3156
                        // Member can only edit his own document
3157
                        $authorId = isset($documentInfoToBeCheck['insert_user_id']) ? $documentInfoToBeCheck['insert_user_id'] : 0;
3158
                        // If "insert_user_id" is not set, check the author id from c_item_property
3159
                        if (empty($authorId) && isset($documentInfoToBeCheck['id'])) {
3160
                            $documentInfo = api_get_item_property_info(
3161
                                $courseId,
3162
                                'document',
3163
                                $documentInfoToBeCheck['id'],
3164
                                0
3165
                            );
3166
                            // Try to find this document in the session
3167
                            if (!empty($sessionId)) {
3168
                                $documentInfo = api_get_item_property_info(
3169
                                    $courseId,
3170
                                    'document',
3171
                                    $documentInfoToBeCheck['id'],
3172
                                    api_get_session_id()
3173
                                );
3174
                            }
3175
3176
                            if (!empty($documentInfo) && isset($documentInfo['insert_user_id'])) {
3177
                                $authorId = $documentInfo['insert_user_id'];
3178
                            }
3179
                        }
3180
3181
                        if ($authorId == $userId) {
3182
                            $result = true;
3183
                        }
3184
                    }
3185
                }
3186
                break;
3187
            case self::DOCUMENT_MODE_READ_ONLY:
3188
                // Student cannot upload content, cannot modify another content.
3189
                $result = false;
3190
                break;
3191
            case self::DOCUMENT_MODE_COLLABORATION:
3192
                // Student can upload content, can modify another content.
3193
                $isMember = self::is_subscribed($userId, $groupInfo);
3194
                if ($isMember) {
3195
                    $result = true;
3196
                }
3197
                break;
3198
        }
3199
3200
        if ($blockPage && $result == false) {
3201
            api_not_allowed(true);
3202
        }
3203
3204
        return $result;
3205
    }
3206
}
3207