Passed
Push — master ( 2c1297...2ffb1a )
by Julito
10:51
created

GroupManager::create_category()   A

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