Completed
Push — master ( b77cfe...000f93 )
by Julito
22:58 queued 11:19
created

GroupManager::create_category()   B

Complexity

Conditions 5
Paths 9

Size

Total Lines 64
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 37
nc 9
nop 14
dl 0
loc 64
rs 8.6346
c 0
b 0
f 0

How to fix   Long Method    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

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