Passed
Push — 1.11.x ( 08debf...ab212d )
by
unknown
17:19 queued 05:33
created

GroupManager::get_users()   C

Complexity

Conditions 12
Paths 160

Size

Total Lines 62
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

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