GroupManager::create_category()   A
last analyzed

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
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CourseBundle\Entity\CGroupRelUser;
6
7
/**
8
 * This library contains some functions for group-management.
9
 *
10
 * @author Bart Mollet
11
 *
12
 * @todo Add $course_code parameter to all functions. So this GroupManager can
13
 * be used outside a session.
14
 */
15
class GroupManager
16
{
17
    /* DEFAULT_GROUP_CATEGORY:
18
    When group categories aren't available (platform-setting),
19
    all groups are created in this 'dummy'-category*/
20
    public const DEFAULT_GROUP_CATEGORY = 2;
21
22
    /**
23
     * infinite.
24
     */
25
    public const INFINITE = 99999;
26
    /**
27
     * No limit on the number of users in a group.
28
     */
29
    public const MEMBER_PER_GROUP_NO_LIMIT = 0;
30
    /**
31
     * No limit on the number of groups per user.
32
     */
33
    public const GROUP_PER_MEMBER_NO_LIMIT = 0;
34
    /**
35
     * The tools of a group can have 3 states
36
     * - not available
37
     * - public
38
     * - private.
39
     */
40
    public const TOOL_NOT_AVAILABLE = 0;
41
    public const TOOL_PUBLIC = 1;
42
    public const TOOL_PRIVATE = 2;
43
    public const TOOL_PRIVATE_BETWEEN_USERS = 3;
44
45
    /**
46
     * Constants for the available group tools.
47
     */
48
    public const GROUP_TOOL_FORUM = 0;
49
    public const GROUP_TOOL_DOCUMENTS = 1;
50
    public const GROUP_TOOL_CALENDAR = 2;
51
    public const GROUP_TOOL_ANNOUNCEMENT = 3;
52
    public const GROUP_TOOL_WORK = 4;
53
    public const GROUP_TOOL_WIKI = 5;
54
    public const GROUP_TOOL_CHAT = 6;
55
56
    public const DOCUMENT_MODE_SHARE = 0; // By default
57
    public const DOCUMENT_MODE_READ_ONLY = 1;
58
    public const DOCUMENT_MODE_COLLABORATION = 2;
59
60
    /**
61
     * GroupManager constructor.
62
     */
63
    public function __construct()
64
    {
65
    }
66
67
    /**
68
     * @param int $courseId
69
     *
70
     * @return array
71
     */
72
    public static function get_groups($courseId = 0)
73
    {
74
        $table_group = Database::get_course_table(TABLE_GROUP);
75
        $courseId = !empty($courseId) ? (int) $courseId : api_get_course_int_id();
76
77
        $sql = "SELECT * FROM $table_group WHERE c_id = $courseId  ";
78
        $result = Database::query($sql);
79
80
        return Database::store_result($result, 'ASSOC');
81
    }
82
83
    /**
84
     * Get list of groups for current course.
85
     *
86
     * @param int   $categoryId  The id of the category from which the groups are
87
     *                           requested
88
     * @param array $course_info Default is current course
89
     * @param int   $status      group status
90
     * @param int   $sessionId
91
     * @param bool  $getCount
92
     * @param bool  $notInGroup  Get groups not in a category
93
     *
94
     * @return array an array with all information about the groups
95
     */
96
    public static function get_group_list(
97
        $categoryId = null,
98
        $course_info = [],
99
        $status = null,
100
        $sessionId = 0,
101
        $getCount = false,
102
        $notInGroup = false
103
    ) {
104
        $course_info = empty($course_info) ? api_get_course_info() : $course_info;
105
        if (empty($course_info)) {
106
            return [];
107
        }
108
        $sessionId = empty($sessionId) ? api_get_session_id() : (int) $sessionId;
109
        $course_id = $course_info['real_id'];
110
        $table_group = Database::get_course_table(TABLE_GROUP);
111
112
        $select = ' g.id,
113
                    g.iid,
114
                    g.name,
115
                    g.description,
116
                    g.category_id,
117
                    g.max_student maximum_number_of_members,
118
                    g.secret_directory,
119
                    g.self_registration_allowed,
120
                    g.self_unregistration_allowed,
121
                    g.session_id,
122
                    g.status';
123
        if ($getCount) {
124
            $select = ' DISTINCT count(g.iid) as count ';
125
        }
126
127
        $sql = "SELECT
128
                $select
129
                FROM $table_group g
130
                WHERE 1 = 1 ";
131
132
        if (!is_null($categoryId)) {
133
            $sql .= " AND g.category_id = '".intval($categoryId)."' ";
134
            $session_condition = api_get_session_condition($sessionId);
135
            if (!empty($session_condition)) {
136
                $sql .= $session_condition;
137
            }
138
        } else {
139
            $session_condition = api_get_session_condition($sessionId, true);
140
        }
141
142
        if (!is_null($status)) {
143
            $sql .= " AND g.status = '".intval($status)."' ";
144
        }
145
146
        $sql .= " AND g.c_id = $course_id ";
147
148
        if ($notInGroup) {
149
            $sql .= "  AND (g.category_id IS NULL OR g.category_id = 0) ";
150
        }
151
152
        if (!empty($session_condition)) {
153
            $sql .= $session_condition;
154
        }
155
        $sql .= ' ORDER BY UPPER(g.name)';
156
157
        $result = Database::query($sql);
158
159
        if ($getCount) {
160
            $row = Database::fetch_array($result);
161
162
            return $row['count'];
163
        }
164
165
        $groups = [];
166
        while ($thisGroup = Database::fetch_array($result)) {
167
            $thisGroup['number_of_members'] = count(self::get_subscribed_users($thisGroup));
168
            if ($thisGroup['session_id'] != 0) {
169
                $sql = 'SELECT name FROM '.Database::get_main_table(TABLE_MAIN_SESSION).'
170
                        WHERE id='.$thisGroup['session_id'];
171
                $rs_session = Database::query($sql);
172
                if (Database::num_rows($rs_session) > 0) {
173
                    $thisGroup['session_name'] = Database::result($rs_session, 0, 0);
174
                }
175
            }
176
            $groups[] = $thisGroup;
177
        }
178
179
        return $groups;
180
    }
181
182
    /**
183
     * Create a group.
184
     *
185
     * @param string $name        The name for this group
186
     * @param int    $category_id
187
     * @param int    $tutor       The user-id of the group's tutor
188
     * @param int    $places      How many people can subscribe to the new group
189
     *
190
     * @return int
191
     */
192
    public static function create_group($name, $category_id, $tutor, $places)
193
    {
194
        $_course = api_get_course_info();
195
        $session_id = api_get_session_id();
196
        $course_id = $_course['real_id'];
197
        $currentCourseRepository = $_course['path'];
198
        $category = self::get_category($category_id);
199
        $places = (int) $places;
200
201
        // Default values
202
        $docState = self::TOOL_PRIVATE;
203
        $calendarState = self::TOOL_PRIVATE;
204
        $workState = self::TOOL_PRIVATE;
205
        $anonuncementState = self::TOOL_PRIVATE;
206
        $forumState = self::TOOL_PRIVATE;
207
        $wikiState = self::TOOL_PRIVATE;
208
        $chatState = self::TOOL_PRIVATE;
209
        $selfRegAllowed = 0;
210
        $selfUnregAllwoed = 0;
211
        $documentAccess = 0;
212
213
        if ($category) {
214
            if ($places == 0) {
215
                //if the amount of users per group is not filled in, use the setting from the category
216
                $places = $category['max_student'];
217
            } else {
218
                if ($places > $category['max_student'] && $category['max_student'] != 0) {
219
                    $places = $category['max_student'];
220
                }
221
            }
222
            $docState = $category['doc_state'];
223
            $calendarState = $category['calendar_state'];
224
            $workState = $category['work_state'];
225
            $anonuncementState = $category['announcements_state'];
226
            $forumState = $category['forum_state'];
227
            $wikiState = $category['wiki_state'];
228
            $chatState = $category['chat_state'];
229
            $selfRegAllowed = $category['self_reg_allowed'];
230
            $selfUnregAllwoed = $category['self_unreg_allowed'];
231
            $documentAccess = isset($category['document_access']) ? $category['document_access'] : 0;
232
        }
233
234
        $allowDocumentAccess = api_get_configuration_value('group_document_access');
235
        $documentCondition = '';
236
        if ($allowDocumentAccess) {
237
            $documentAccess = (int) $documentAccess;
238
            $documentCondition = " document_access = $documentAccess, ";
239
        }
240
241
        $table_group = Database::get_course_table(TABLE_GROUP);
242
        $sql = "INSERT INTO $table_group SET
243
                c_id = $course_id,
244
                status = 1,
245
                category_id='".Database::escape_string($category_id)."',
246
                max_student = '".$places."',
247
                doc_state = '".$docState."',
248
                calendar_state = '".$calendarState."',
249
                work_state = '".$workState."',
250
                announcements_state = '".$anonuncementState."',
251
                forum_state = '".$forumState."',
252
                wiki_state = '".$wikiState."',
253
                chat_state = '".$chatState."',
254
                self_registration_allowed = '".$selfRegAllowed."',
255
                self_unregistration_allowed = '".$selfUnregAllwoed."',
256
                $documentCondition
257
                session_id='".$session_id."'";
258
259
        Database::query($sql);
260
        $lastId = Database::insert_id();
261
262
        if ($lastId) {
263
            $sql = "UPDATE $table_group SET id = iid WHERE iid = $lastId";
264
            Database::query($sql);
265
266
            $desired_dir_name = '/'.api_replace_dangerous_char($name).'_groupdocs';
267
            $my_path = api_get_path(SYS_COURSE_PATH).$currentCourseRepository.'/document';
268
269
            $newFolderData = create_unexisting_directory(
270
                $_course,
271
                api_get_user_id(),
272
                $session_id,
273
                $lastId,
274
                null,
275
                $my_path,
276
                $desired_dir_name,
277
                null,
278
                1
279
            );
280
281
            $unique_name = $newFolderData['path'];
282
283
            /* Stores the directory path into the group table */
284
            $sql = "UPDATE $table_group SET
285
                        name = '".Database::escape_string($name)."',
286
                        secret_directory = '".$unique_name."'
287
                    WHERE c_id = $course_id AND id ='".$lastId."'";
288
289
            Database::query($sql);
290
291
            // create a forum if needed
292
            if ($forumState >= 0) {
293
                require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
294
295
                $forum_categories = get_forum_categories();
296
                if (empty($forum_categories)) {
297
                    $categoryParam = [
298
                        'forum_category_title' => get_lang('GroupForums'),
299
                    ];
300
                    store_forumcategory($categoryParam);
301
                    $forum_categories = get_forum_categories();
302
                }
303
304
                $counter = 0;
305
                foreach ($forum_categories as $key => $value) {
306
                    if ($counter == 0) {
307
                        $forum_category_id = $key;
308
                    }
309
                    $counter++;
310
                }
311
                // A sanity check.
312
                if (empty($forum_category_id)) {
313
                    $forum_category_id = 0;
314
                }
315
316
                $values = [];
317
                $values['forum_title'] = $name;
318
                $values['group_id'] = $lastId;
319
                $values['forum_category'] = $forum_category_id;
320
                $values['allow_anonymous_group']['allow_anonymous'] = 0;
321
                $values['students_can_edit_group']['students_can_edit'] = 0;
322
                $values['approval_direct_group']['approval_direct'] = 0;
323
                $values['allow_attachments_group']['allow_attachments'] = 1;
324
                $values['allow_new_threads_group']['allow_new_threads'] = 1;
325
                $values['default_view_type_group']['default_view_type'] = api_get_setting('default_forum_view');
326
                $values['group_forum'] = $lastId;
327
                if ($forumState == '1') {
328
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'public';
329
                } elseif ($forumState == '2') {
330
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'private';
331
                } elseif ($forumState == '0') {
332
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'unavailable';
333
                }
334
                store_forum($values);
335
            }
336
        }
337
338
        return $lastId;
339
    }
340
341
    /**
342
     * Create subgroups.
343
     * This function creates new groups based on an existing group. It will
344
     * create the specified number of groups and fill those groups with users
345
     * from the base group.
346
     *
347
     * @param int $group_id         the group from which subgroups have to be created
348
     * @param int $number_of_groups The number of groups that have to be created
349
     */
350
    public static function create_subgroups($group_id, $number_of_groups)
351
    {
352
        $courseId = api_get_course_int_id();
353
        $table_group = Database::get_course_table(TABLE_GROUP);
354
        $category_id = self::create_category(
355
            get_lang('Subgroups'),
356
            '',
357
            self::TOOL_PRIVATE,
358
            self::TOOL_PRIVATE,
359
            0,
360
            0,
361
            1,
362
            1
363
        );
364
        $users = self::get_users($group_id);
365
        $group_ids = [];
366
367
        for ($group_nr = 1; $group_nr <= $number_of_groups; $group_nr++) {
368
            $group_ids[] = self::create_group(
369
                get_lang('Subgroup').' '.$group_nr,
370
                $category_id,
371
                0,
372
                0
373
            );
374
        }
375
376
        $members = [];
377
        foreach ($users as $index => $user_id) {
378
            $groupId = $group_ids[$index % $number_of_groups];
379
            $groupInfo = self::get_group_properties($groupId);
380
            self::subscribe_users(
381
                $user_id,
382
                $groupInfo
383
            );
384
            $members[$group_ids[$groupId]]++;
385
        }
386
387
        foreach ($members as $group_id => $places) {
388
            $sql = "UPDATE $table_group SET max_student = $places
389
                    WHERE c_id = $courseId  AND id = $group_id";
390
            Database::query($sql);
391
        }
392
    }
393
394
    /**
395
     * Create a group for every class subscribed to the current course.
396
     *
397
     * @param int $categoryId The category in which the groups should be created
398
     *
399
     * @return array
400
     */
401
    public static function create_class_groups($categoryId)
402
    {
403
        $options = [];
404
        $sessionId = api_get_session_id();
405
        if (empty($sessionId)) {
406
            $options['where'] = [' usergroup.course_id = ? ' => api_get_course_int_id()];
407
        } else {
408
            $options['session_id'] = $sessionId;
409
            $options['where'] = [' usergroup.session_id = ? ' => $sessionId];
410
        }
411
412
        $obj = new UserGroup();
413
        $classes = $obj->getUserGroupInCourse($options);
414
        $group_ids = [];
415
416
        foreach ($classes as $class) {
417
            $userList = $obj->get_users_by_usergroup($class['id']);
418
            $groupId = self::create_group(
419
                $class['name'],
420
                $categoryId,
421
                0,
422
                null
423
            );
424
425
            if ($groupId) {
426
                $groupInfo = self::get_group_properties($groupId);
427
                self::subscribe_users($userList, $groupInfo);
428
                $group_ids[] = $groupId;
429
            }
430
        }
431
432
        return $group_ids;
433
    }
434
435
    /**
436
     * Deletes groups and their data.
437
     *
438
     * @author Christophe Gesche <[email protected]>
439
     * @author Hugues Peeters <[email protected]>
440
     * @author Bart Mollet
441
     *
442
     * @param array  $groupInfo   iid
443
     * @param string $course_code Default is current course
444
     *
445
     * @return int - number of groups deleted
446
     */
447
    public static function deleteGroup($groupInfo, $course_code = null)
448
    {
449
        if (empty($groupInfo['iid'])) {
450
            return false;
451
        }
452
        $course_info = api_get_course_info($course_code);
453
        if (empty($course_info)) {
454
            return false;
455
        }
456
457
        $course_id = $course_info['real_id'];
458
459
        // Database table definitions
460
        $group_table = Database::get_course_table(TABLE_GROUP);
461
        $forum_table = Database::get_course_table(TABLE_FORUM);
462
        $groupInfo = self::get_group_properties($groupInfo['iid'], true);
463
        if ($groupInfo) {
464
            $groupIid = $groupInfo['iid'];
465
            $groupId = $groupInfo['id'];
466
            // Unsubscribe all users
467
            self::unsubscribe_all_users($groupInfo);
468
            self::unsubscribe_all_tutors($groupInfo);
469
470
            if (!empty($groupInfo['secret_directory'])) {
471
                $directory = $groupInfo['secret_directory'];
472
                // move group-documents to garbage
473
                $source_directory = api_get_path(SYS_COURSE_PATH).$course_info['path']."/document".$directory;
474
                // File to renamed
475
                $destination_dir = api_get_path(SYS_COURSE_PATH).$course_info['path']."/document".$directory.'_DELETED_'.$groupInfo['id'];
476
                //Deleting from document tool
477
                DocumentManager::delete_document(
478
                    $course_info,
479
                    $directory,
480
                    $source_directory
481
                );
482
483
                if (file_exists($source_directory)) {
484
                    if (api_get_setting('permanently_remove_deleted_files') === 'true') {
485
                        // Delete
486
                        my_delete($source_directory);
487
                    } else {
488
                        // Rename
489
                        rename($source_directory, $destination_dir);
490
                    }
491
                }
492
            }
493
494
            $sql = "DELETE FROM $forum_table
495
                    WHERE c_id = $course_id AND forum_of_group = $groupId ";
496
            Database::query($sql);
497
498
            // Delete item properties of this group.
499
            // to_group_id is related to c_group_info.iid
500
            $itemPropertyTable = Database::get_course_table(TABLE_ITEM_PROPERTY);
501
            $sql = "DELETE FROM $itemPropertyTable
502
                    WHERE to_group_id = $groupIid ";
503
            Database::query($sql);
504
505
            // delete the groups
506
            $sql = "DELETE FROM $group_table
507
                    WHERE c_id = $course_id AND iid = $groupIid ";
508
            Database::query($sql);
509
        }
510
511
        return true;
512
    }
513
514
    /**
515
     * Function needed only when deleting a course, in order to be sure that all group ids are deleted.
516
     *
517
     * @param int $courseId
518
     *
519
     * @return bool
520
     */
521
    public static function deleteAllGroupsFromCourse($courseId)
522
    {
523
        $courseId = (int) $courseId;
524
525
        if (empty($courseId)) {
526
            return false;
527
        }
528
529
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
530
        $sql = "SELECT iid FROM $table
531
                WHERE c_id = $courseId ";
532
        Database::query($sql);
533
534
        // Database table definitions
535
        $table = Database::get_course_table(TABLE_GROUP_USER);
536
        $sql = "DELETE FROM $table
537
                WHERE c_id = $courseId";
538
        Database::query($sql);
539
540
        $table = Database::get_course_table(TABLE_GROUP_TUTOR);
541
        $sql = "DELETE FROM $table
542
                WHERE c_id = $courseId";
543
        Database::query($sql);
544
545
        $groupTable = Database::get_course_table(TABLE_GROUP);
546
        $sql = "DELETE FROM $groupTable
547
                WHERE c_id = $courseId";
548
        Database::query($sql);
549
550
        return true;
551
    }
552
553
    /**
554
     * Get group properties.
555
     *
556
     * @param int  $group_id the group from which properties are requested
557
     * @param bool $useIid
558
     *
559
     * @return array All properties. Array-keys are:
560
     *               name, tutor_id, description, maximum_number_of_students,
561
     *               directory and visibility of tools
562
     */
563
    public static function get_group_properties($group_id, $useIid = false)
564
    {
565
        $course_id = api_get_course_int_id();
566
        $group_id = (int) $group_id;
567
568
        if (empty($group_id)) {
569
            return null;
570
        }
571
572
        $table_group = Database::get_course_table(TABLE_GROUP);
573
        $sql = "SELECT * FROM $table_group
574
                WHERE c_id = $course_id AND id = ".$group_id;
575
576
        if ($useIid) {
577
            $sql = "SELECT * FROM $table_group
578
                    WHERE c_id = $course_id AND iid = ".$group_id;
579
        }
580
        $db_result = Database::query($sql);
581
        $db_object = Database::fetch_object($db_result);
582
583
        $result = [];
584
        if ($db_object) {
585
            $result['id'] = $db_object->id;
586
            $result['iid'] = $db_object->iid;
587
            $result['name'] = $db_object->name;
588
            $result['status'] = $db_object->status;
589
            $result['description'] = $db_object->description;
590
            $result['maximum_number_of_students'] = $db_object->max_student;
591
            $result['max_student'] = $db_object->max_student;
592
            $result['doc_state'] = $db_object->doc_state;
593
            $result['work_state'] = $db_object->work_state;
594
            $result['calendar_state'] = $db_object->calendar_state;
595
            $result['announcements_state'] = $db_object->announcements_state;
596
            $result['forum_state'] = $db_object->forum_state;
597
            $result['wiki_state'] = $db_object->wiki_state;
598
            $result['chat_state'] = $db_object->chat_state;
599
            $result['directory'] = $db_object->secret_directory;
600
            $result['self_registration_allowed'] = $db_object->self_registration_allowed;
601
            $result['self_unregistration_allowed'] = $db_object->self_unregistration_allowed;
602
            $result['count_users'] = count(
603
                self::get_subscribed_users($result)
604
            );
605
            $result['count_tutor'] = count(
606
                self::get_subscribed_tutors($result)
607
            );
608
            $result['count_all'] = $result['count_users'] + $result['count_tutor'];
609
            $result['document_access'] = isset($db_object->document_access) ? $db_object->document_access : self::DOCUMENT_MODE_SHARE;
610
        }
611
612
        return $result;
613
    }
614
615
    /**
616
     * @param string $name
617
     * @param string $courseCode
618
     * @param int    $sessionId
619
     *
620
     * @return array
621
     */
622
    public static function getGroupByName($name, $courseCode = null, $sessionId = 0)
623
    {
624
        $name = trim($name);
625
626
        if (empty($name)) {
627
            return [];
628
        }
629
630
        $course_info = api_get_course_info($courseCode);
631
        $course_id = $course_info['real_id'];
632
        $name = Database::escape_string($name);
633
        $sessionId = empty($sessionId) ? api_get_session_id() : (int) $sessionId;
634
        $sessionCondition = api_get_session_condition($sessionId);
635
636
        $table = Database::get_course_table(TABLE_GROUP);
637
        $sql = "SELECT * FROM $table
638
                WHERE
639
                  c_id = $course_id AND
640
                  name = '$name'
641
                  $sessionCondition
642
                LIMIT 1";
643
        $res = Database::query($sql);
644
        $group = [];
645
        if (Database::num_rows($res)) {
646
            $group = Database::fetch_array($res, 'ASSOC');
647
        }
648
649
        return $group;
650
    }
651
652
    /**
653
     * @param int    $courseId
654
     * @param int    $categoryId
655
     * @param string $name
656
     *
657
     * @return array
658
     */
659
    public static function getGroupListFilterByName($name, $categoryId, $courseId)
660
    {
661
        $name = Database::escape_string(trim($name));
662
        $categoryId = (int) $categoryId;
663
        $courseId = (int) $courseId;
664
665
        if (empty($name)) {
666
            return [];
667
        }
668
        $table = Database::get_course_table(TABLE_GROUP);
669
        $sql = "SELECT * FROM $table
670
                WHERE c_id = $courseId AND name LIKE '%$name%'";
671
672
        if (!empty($categoryId)) {
673
            $sql .= " AND category_id = $categoryId";
674
        }
675
        $sql .= " ORDER BY name";
676
        $result = Database::query($sql);
677
678
        return Database::store_result($result, 'ASSOC');
679
    }
680
681
    /**
682
     * Set group properties
683
     * Changes the group's properties.
684
     *
685
     * @param int       Group Id
686
     * @param string    Group name
687
     * @param string    Group description
688
     * @param int       Max number of students in group
689
     * @param int       Document tool's visibility (0=none,1=private,2=public)
690
     * @param int       Work tool's visibility (0=none,1=private,2=public)
691
     * @param int       Calendar tool's visibility (0=none,1=private,2=public)
692
     * @param int       Announcement tool's visibility (0=none,1=private,2=public)
693
     * @param int       Forum tool's visibility (0=none,1=private,2=public)
694
     * @param int       Wiki tool's visibility (0=none,1=private,2=public)
695
     * @param int       Chat tool's visibility (0=none,1=private,2=public)
696
     * @param bool Whether self registration is allowed or not
697
     * @param bool Whether self unregistration is allowed or not
698
     * @param int $categoryId
699
     * @param int $documentAccess
700
     *
701
     * @return bool TRUE if properties are successfully changed, false otherwise
702
     */
703
    public static function set_group_properties(
704
        $group_id,
705
        $name,
706
        $description,
707
        $maximum_number_of_students,
708
        $doc_state,
709
        $work_state,
710
        $calendar_state,
711
        $announcements_state,
712
        $forum_state,
713
        $wiki_state,
714
        $chat_state,
715
        $selfRegistrationAllowed,
716
        $selfUnRegistrationAllowed,
717
        $categoryId = null,
718
        $documentAccess = 0
719
    ) {
720
        $table_group = Database::get_course_table(TABLE_GROUP);
721
        $table_forum = Database::get_course_table(TABLE_FORUM);
722
        $categoryId = (int) $categoryId;
723
        $group_id = (int) $group_id;
724
        $courseId = api_get_course_int_id();
725
726
        $allowDocumentAccess = api_get_configuration_value('group_document_access');
727
        $documentCondition = '';
728
        if ($allowDocumentAccess) {
729
            $documentAccess = (int) $documentAccess;
730
            $documentCondition = " document_access = $documentAccess, ";
731
        }
732
733
        $sql = "UPDATE ".$table_group." SET
734
                    name='".Database::escape_string(trim($name))."',
735
                    doc_state = '".Database::escape_string($doc_state)."',
736
                    work_state = '".Database::escape_string($work_state)."',
737
                    calendar_state = '".Database::escape_string($calendar_state)."',
738
                    announcements_state = '".Database::escape_string($announcements_state)."',
739
                    forum_state = '".Database::escape_string($forum_state)."',
740
                    wiki_state = '".Database::escape_string($wiki_state)."',
741
                    chat_state = '".Database::escape_string($chat_state)."',
742
                    description ='".Database::escape_string(trim($description))."',
743
                    max_student = '".Database::escape_string($maximum_number_of_students)."',
744
                    self_registration_allowed = '".Database::escape_string($selfRegistrationAllowed)."',
745
                    self_unregistration_allowed = '".Database::escape_string($selfUnRegistrationAllowed)."',
746
                    $documentCondition
747
                    category_id = ".$categoryId."
748
                WHERE c_id = $courseId AND id=".$group_id;
749
        $result = Database::query($sql);
750
751
        /* Here we are updating a field in the table forum_forum that perhaps
752
        duplicates the table group_info.forum_state cvargas*/
753
        $forum_state = (int) $forum_state;
754
        $sql2 = "UPDATE ".$table_forum." SET ";
755
        if (1 === $forum_state) {
756
            $sql2 .= " forum_group_public_private='public' ";
757
        } elseif (2 === $forum_state) {
758
            $sql2 .= " forum_group_public_private='private' ";
759
        } elseif (0 === $forum_state) {
760
            $sql2 .= " forum_group_public_private='unavailable' ";
761
        }
762
        $sql2 .= " WHERE c_id = $courseId AND forum_of_group=".$group_id;
763
        Database::query($sql2);
764
765
        return $result;
766
    }
767
768
    /**
769
     * Get the total number of groups for the current course.
770
     *
771
     * @return int the number of groups for the current course
772
     */
773
    public static function get_number_of_groups()
774
    {
775
        $courseId = api_get_course_int_id();
776
        $table = Database::get_course_table(TABLE_GROUP);
777
        $sql = "SELECT COUNT(id) AS number_of_groups
778
                FROM $table
779
                WHERE c_id = $courseId ";
780
        $res = Database::query($sql);
781
        $obj = Database::fetch_object($res);
782
783
        return $obj->number_of_groups;
784
    }
785
786
    /**
787
     * Get all categories.
788
     *
789
     * @param string $course_code The course (default = current course)
790
     *
791
     * @return array
792
     */
793
    public static function get_categories($course_code = null)
794
    {
795
        $course_info = api_get_course_info($course_code);
796
        $courseId = $course_info['real_id'];
797
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
798
        $sql = "SELECT * FROM $table
799
                WHERE c_id = $courseId
800
                ORDER BY display_order";
801
        $res = Database::query($sql);
802
        $cats = [];
803
        while ($cat = Database::fetch_array($res)) {
804
            $cats[] = $cat;
805
        }
806
807
        return $cats;
808
    }
809
810
    /**
811
     * Get a group category.
812
     *
813
     * @param int    $id          The category id
814
     * @param string $course_code The course (default = current course)
815
     *
816
     * @return array
817
     */
818
    public static function get_category($id, $course_code = null)
819
    {
820
        if (empty($id)) {
821
            return [];
822
        }
823
824
        $courseInfo = api_get_course_info($course_code);
825
        $courseId = $courseInfo['real_id'];
826
        $id = intval($id);
827
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
828
        $sql = "SELECT * FROM $table
829
                WHERE c_id = $courseId AND id = $id
830
                LIMIT 1";
831
        $res = Database::query($sql);
832
833
        return Database::fetch_array($res);
834
    }
835
836
    /**
837
     * Get a group category.
838
     *
839
     * @param string $title
840
     * @param string $course_code The course (default = current course)
841
     *
842
     * @return array
843
     */
844
    public static function getCategoryByTitle($title, $course_code = null)
845
    {
846
        $title = trim($title);
847
848
        if (empty($title)) {
849
            return [];
850
        }
851
852
        $course_info = api_get_course_info($course_code);
853
        $courseId = $course_info['real_id'];
854
        $title = Database::escape_string($title);
855
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
856
        $sql = "SELECT * FROM $table
857
                WHERE c_id = $courseId AND title = '$title'
858
                LIMIT 1";
859
        $res = Database::query($sql);
860
        $category = [];
861
        if (Database::num_rows($res)) {
862
            $category = Database::fetch_array($res, 'ASSOC');
863
        }
864
865
        return $category;
866
    }
867
868
    /**
869
     * Get the unique category of a given group.
870
     *
871
     * @param int    $group_id    The iid of the group
872
     * @param string $course_code The course in which the group is (default =
873
     *                            current course)
874
     *
875
     * @return array The category
876
     */
877
    public static function get_category_from_group($group_id, $course_code = '')
878
    {
879
        $table_group = Database::get_course_table(TABLE_GROUP);
880
        $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
881
882
        $group_id = (int) $group_id;
883
884
        if (empty($group_id)) {
885
            return [];
886
        }
887
888
        $course_info = api_get_course_info($course_code);
889
890
        if (empty($course_info)) {
891
            return false;
892
        }
893
894
        $courseId = $course_info['real_id'];
895
        $sql = "SELECT gc.* FROM $table_group_cat gc, $table_group g
896
                WHERE
897
                    gc.c_id = $courseId AND
898
                    g.c_id = $courseId AND
899
                    gc.id = g.category_id AND
900
                    g.iid = $group_id
901
                LIMIT 1";
902
        $res = Database::query($sql);
903
        $cat = [];
904
        if (Database::num_rows($res)) {
905
            $cat = Database::fetch_array($res);
906
        }
907
908
        return $cat;
909
    }
910
911
    /**
912
     * Delete a group category.
913
     *
914
     * @param int    $cat_id      The id of the category to delete
915
     * @param string $course_code The code in which the category should be
916
     *                            deleted (default = current course)
917
     *
918
     * @return bool
919
     */
920
    public static function delete_category($cat_id, $course_code = '')
921
    {
922
        $course_info = api_get_course_info($course_code);
923
        if (empty($course_info)) {
924
            return false;
925
        }
926
        $course_id = $course_info['real_id'];
927
928
        $table_group = Database::get_course_table(TABLE_GROUP);
929
        $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
930
        $cat_id = intval($cat_id);
931
        $sql = "SELECT iid FROM $table_group
932
                WHERE c_id = $course_id AND category_id='".$cat_id."'";
933
        $res = Database::query($sql);
934
        if (Database::num_rows($res) > 0) {
935
            while ($group = Database::fetch_object($res)) {
936
                // Delete all groups in category
937
                /*$groupInfo = self::get_group_properties($group->iid, true);
938
                self::deleteGroup($groupInfo, $course_code);
939
                */
940
                // Set the category to NULL to avoid losing groups in sessions.
941
                $sql = "UPDATE $table_group SET category_id = NULL WHERE iid = ".$group->iid;
942
                Database::query($sql);
943
            }
944
        }
945
        $sql = "DELETE FROM $table_group_cat
946
                WHERE c_id = $course_id  AND id='".$cat_id."'";
947
        Database::query($sql);
948
949
        return true;
950
    }
951
952
    /**
953
     * Create group category.
954
     *
955
     * @param string $title                      The title of the new category
956
     * @param string $description                The description of the new category
957
     * @param int    $doc_state
958
     * @param int    $work_state
959
     * @param int    $calendar_state
960
     * @param int    $announcements_state
961
     * @param int    $forum_state
962
     * @param int    $wiki_state
963
     * @param int    $chat_state
964
     * @param int    $selfRegistrationAllowed    allow users to self register
965
     * @param int    $selfUnRegistrationAllowed  allow user to self unregister
966
     * @param int    $maximum_number_of_students
967
     * @param int    $groups_per_user
968
     * @param int    $documentAccess             document access
969
     *
970
     * @return mixed
971
     */
972
    public static function create_category(
973
        $title,
974
        $description,
975
        $doc_state,
976
        $work_state,
977
        $calendar_state,
978
        $announcements_state,
979
        $forum_state,
980
        $wiki_state,
981
        $chat_state = 1,
982
        $selfRegistrationAllowed = 0,
983
        $selfUnRegistrationAllowed = 0,
984
        $maximum_number_of_students = 8,
985
        $groups_per_user = 0,
986
        $documentAccess = 0
987
    ) {
988
        if (empty($title)) {
989
            return false;
990
        }
991
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
992
        $course_id = api_get_course_int_id();
993
994
        $sql = "SELECT MAX(display_order)+1 as new_order
995
                FROM $table
996
                WHERE c_id = $course_id ";
997
        $res = Database::query($sql);
998
        $obj = Database::fetch_object($res);
999
        if (!isset($obj->new_order)) {
1000
            $obj->new_order = 1;
1001
        }
1002
1003
        $params = [
1004
            'c_id' => $course_id,
1005
            'title' => $title,
1006
            'display_order' => $obj->new_order,
1007
            'description' => $description,
1008
            'doc_state' => $doc_state,
1009
            'work_state' => $work_state,
1010
            'calendar_state' => $calendar_state,
1011
            'announcements_state' => $announcements_state,
1012
            'forum_state' => $forum_state,
1013
            'wiki_state' => $wiki_state,
1014
            'chat_state' => $chat_state,
1015
            'groups_per_user' => $groups_per_user,
1016
            'self_reg_allowed' => $selfRegistrationAllowed,
1017
            'self_unreg_allowed' => $selfUnRegistrationAllowed,
1018
            'max_student' => $maximum_number_of_students,
1019
        ];
1020
1021
        $allowDocumentAccess = api_get_configuration_value('group_category_document_access');
1022
        if ($allowDocumentAccess) {
1023
            $params['document_access'] = $documentAccess;
1024
        }
1025
1026
        $categoryId = Database::insert($table, $params);
1027
        if ($categoryId) {
1028
            $sql = "UPDATE $table SET id = iid
1029
                    WHERE iid = $categoryId";
1030
            Database::query($sql);
1031
1032
            return $categoryId;
1033
        }
1034
1035
        return false;
1036
    }
1037
1038
    /**
1039
     * Update group category.
1040
     *
1041
     * @param int    $id
1042
     * @param string $title
1043
     * @param string $description
1044
     * @param $doc_state
1045
     * @param $work_state
1046
     * @param $calendar_state
1047
     * @param $announcements_state
1048
     * @param $forum_state
1049
     * @param $wiki_state
1050
     * @param $chat_state
1051
     * @param $selfRegistrationAllowed
1052
     * @param $selfUnRegistrationAllowed
1053
     * @param $maximum_number_of_students
1054
     * @param $groups_per_user
1055
     * @param $documentAccess
1056
     */
1057
    public static function update_category(
1058
        $id,
1059
        $title,
1060
        $description,
1061
        $doc_state,
1062
        $work_state,
1063
        $calendar_state,
1064
        $announcements_state,
1065
        $forum_state,
1066
        $wiki_state,
1067
        $chat_state,
1068
        $selfRegistrationAllowed,
1069
        $selfUnRegistrationAllowed,
1070
        $maximum_number_of_students,
1071
        $groups_per_user,
1072
        $documentAccess
1073
    ) {
1074
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
1075
        $id = (int) $id;
1076
1077
        $courseId = api_get_course_int_id();
1078
1079
        $allowDocumentAccess = api_get_configuration_value('group_category_document_access');
1080
        $documentCondition = '';
1081
        if ($allowDocumentAccess) {
1082
            $documentAccess = (int) $documentAccess;
1083
            $documentCondition = " document_access = $documentAccess, ";
1084
        }
1085
1086
        $sql = "UPDATE ".$table." SET
1087
                    title='".Database::escape_string($title)."',
1088
                    description='".Database::escape_string($description)."',
1089
                    doc_state = '".Database::escape_string($doc_state)."',
1090
                    work_state = '".Database::escape_string($work_state)."',
1091
                    calendar_state = '".Database::escape_string($calendar_state)."',
1092
                    announcements_state = '".Database::escape_string($announcements_state)."',
1093
                    forum_state = '".Database::escape_string($forum_state)."',
1094
                    wiki_state = '".Database::escape_string($wiki_state)."',
1095
                    chat_state = '".Database::escape_string($chat_state)."',
1096
                    groups_per_user   = '".Database::escape_string($groups_per_user)."',
1097
                    self_reg_allowed = '".Database::escape_string($selfRegistrationAllowed)."',
1098
                    self_unreg_allowed = '".Database::escape_string($selfUnRegistrationAllowed)."',
1099
                    $documentCondition
1100
                    max_student = ".intval($maximum_number_of_students)."
1101
                WHERE c_id = $courseId AND id = $id";
1102
1103
        Database::query($sql);
1104
1105
        // Updating all groups inside this category
1106
        $groups = self::get_group_list($id);
1107
1108
        if (!empty($groups)) {
1109
            foreach ($groups as $group) {
1110
                self::set_group_properties(
1111
                    $group['id'],
1112
                    $group['name'],
1113
                    $group['description'],
1114
                    $maximum_number_of_students,
1115
                    $doc_state,
1116
                    $work_state,
1117
                    $calendar_state,
1118
                    $announcements_state,
1119
                    $forum_state,
1120
                    $wiki_state,
1121
                    $chat_state,
1122
                    $selfRegistrationAllowed,
1123
                    $selfUnRegistrationAllowed,
1124
                    $id,
1125
                    $documentAccess
1126
                );
1127
            }
1128
        }
1129
    }
1130
1131
    /**
1132
     * Returns the number of groups of the user with the greatest number of
1133
     * subscriptions in the given category.
1134
     */
1135
    public static function get_current_max_groups_per_user(
1136
        $category_id = null,
1137
        $course_code = null
1138
    ) {
1139
        $course_info = api_get_course_info($course_code);
1140
        $group_table = Database::get_course_table(TABLE_GROUP);
1141
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1142
        $sql = 'SELECT COUNT(gu.group_id) AS current_max
1143
                FROM '.$group_user_table.' gu, '.$group_table.' g
1144
				WHERE g.c_id = '.$course_info['real_id'].'
1145
				AND gu.c_id = g.c_id
1146
				AND gu.group_id = g.iid ';
1147
        if (null != $category_id) {
1148
            $category_id = intval($category_id);
1149
            $sql .= ' AND g.category_id = '.$category_id;
1150
        }
1151
        $sql .= ' GROUP BY gu.user_id ORDER BY current_max DESC LIMIT 1';
1152
        $res = Database::query($sql);
1153
        $obj = Database::fetch_object($res);
1154
1155
        return $obj->current_max;
1156
    }
1157
1158
    /**
1159
     * Swaps the display-order of two categories.
1160
     *
1161
     * @param int $id1 The id of the first category
1162
     * @param int $id2 The id of the second category
1163
     */
1164
    public static function swap_category_order($id1, $id2)
1165
    {
1166
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
1167
        $id1 = intval($id1);
1168
        $id2 = intval($id2);
1169
        $course_id = api_get_course_int_id();
1170
1171
        $sql = "SELECT id, display_order FROM $table
1172
                WHERE id IN ($id1,$id2) AND c_id = $course_id ";
1173
        $res = Database::query($sql);
1174
        $cat1 = Database::fetch_object($res);
1175
        $cat2 = Database::fetch_object($res);
1176
        if ($cat1 && $cat2) {
1177
            $sql = "UPDATE $table SET display_order=$cat2->display_order
1178
                    WHERE id = $cat1->id AND c_id = $course_id ";
1179
            Database::query($sql);
1180
1181
            $sql = "UPDATE $table SET display_order=$cat1->display_order
1182
                    WHERE id = $cat2->id AND c_id = $course_id ";
1183
            Database::query($sql);
1184
        }
1185
    }
1186
1187
    /**
1188
     * Get all users from a given group.
1189
     *
1190
     * @param int  $group_id        The group
1191
     * @param bool $load_extra_info
1192
     * @param int  $start
1193
     * @param int  $limit
1194
     * @param bool $getCount
1195
     * @param int  $courseId
1196
     * @param $column
1197
     * @param $direction
1198
     *
1199
     * @return array list of user id
1200
     */
1201
    public static function get_users(
1202
        $group_id,
1203
        $load_extra_info = false,
1204
        $start = null,
1205
        $limit = null,
1206
        $getCount = false,
1207
        $courseId = null,
1208
        $column = null,
1209
        $direction = null
1210
    ) {
1211
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1212
        $groupTable = Database::get_course_table(TABLE_GROUP);
1213
        $user_table = Database::get_main_table(TABLE_MAIN_USER);
1214
        $group_id = (int) $group_id;
1215
        $courseId = (int) $courseId;
1216
1217
        if (empty($courseId)) {
1218
            $courseId = api_get_course_int_id();
1219
        }
1220
1221
        $select = " SELECT u.id, firstname, lastname ";
1222
        if ($getCount) {
1223
            $select = " SELECT count(u.id) count";
1224
        }
1225
        $sql = "$select
1226
                FROM $group_user_table gu
1227
                INNER JOIN $groupTable g
1228
                ON (gu.group_id = g.id and g.c_id = gu.c_id)
1229
                INNER JOIN $user_table u
1230
                ON (u.id = gu.user_id)
1231
                WHERE
1232
                    gu.c_id = $courseId AND
1233
                    g.id = $group_id";
1234
1235
        if (!empty($column) && !empty($direction)) {
1236
            $column = Database::escape_string($column);
1237
            $columns = ['id', 'firstname', 'lastname'];
1238
            $column = in_array($column, $columns) ? $column : 'lastname';
1239
            $direction = ('ASC' === $direction ? 'ASC' : 'DESC');
1240
            $sql .= " ORDER BY $column $direction";
1241
        }
1242
1243
        if (!empty($start) && !empty($limit)) {
1244
            $start = (int) $start;
1245
            $limit = (int) $limit;
1246
            $sql .= " LIMIT $start, $limit";
1247
        }
1248
        $res = Database::query($sql);
1249
        $users = [];
1250
        while ($obj = Database::fetch_object($res)) {
1251
            if ($getCount) {
1252
                return $obj->count;
1253
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
1254
            }
1255
            if ($load_extra_info) {
1256
                $users[] = api_get_user_info($obj->id);
1257
            } else {
1258
                $users[] = $obj->id;
1259
            }
1260
        }
1261
1262
        return $users;
1263
    }
1264
1265
    /**
1266
     * @param int $group_id
1267
     *
1268
     * @return array
1269
     */
1270
    public static function getStudentsAndTutors($group_id)
1271
    {
1272
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1273
        $tutor_user_table = Database::get_course_table(TABLE_GROUP_TUTOR);
1274
        $groupTable = Database::get_course_table(TABLE_GROUP);
1275
1276
        $course_id = api_get_course_int_id();
1277
        $group_id = intval($group_id);
1278
        $sql = "SELECT user_id
1279
                FROM $group_user_table gu
1280
                INNER JOIN $groupTable g
1281
                ON (gu.group_id = g.iid and g.c_id = gu.c_id)
1282
                WHERE gu.c_id = $course_id AND g.id = $group_id";
1283
        $res = Database::query($sql);
1284
        $users = [];
1285
1286
        while ($obj = Database::fetch_object($res)) {
1287
            $users[] = api_get_user_info($obj->user_id);
1288
        }
1289
1290
        $sql = "SELECT user_id
1291
                FROM $tutor_user_table gu
1292
                INNER JOIN $groupTable g
1293
                ON (gu.group_id = g.id and g.c_id = gu.c_id)
1294
                WHERE gu.c_id = $course_id AND g.id = $group_id";
1295
        $res = Database::query($sql);
1296
        while ($obj = Database::fetch_object($res)) {
1297
            $users[] = api_get_user_info($obj->user_id);
1298
        }
1299
1300
        return $users;
1301
    }
1302
1303
    /**
1304
     * Get only tutors from a group.
1305
     *
1306
     * @param array $groupInfo
1307
     *
1308
     * @return array
1309
     */
1310
    public static function getTutors($groupInfo)
1311
    {
1312
        $groupTable = Database::get_course_table(TABLE_GROUP);
1313
        $tutor_user_table = Database::get_course_table(TABLE_GROUP_TUTOR);
1314
        $course_id = api_get_course_int_id();
1315
        $group_id = intval($groupInfo['iid']);
1316
1317
        $sql = "SELECT user_id
1318
                FROM $tutor_user_table gu
1319
                INNER JOIN $groupTable g
1320
                ON (gu.group_id = g.id and g.c_id = gu.c_id)
1321
                WHERE gu.c_id = $course_id AND g.iid = $group_id";
1322
        $res = Database::query($sql);
1323
1324
        $users = [];
1325
        while ($obj = Database::fetch_object($res)) {
1326
            $users[] = api_get_user_info($obj->user_id);
1327
        }
1328
1329
        return $users;
1330
    }
1331
1332
    /**
1333
     * Get only students from a group (not tutors).
1334
     *
1335
     * @param int  $group_id         iid
1336
     * @param bool $filterOnlyActive
1337
     *
1338
     * @return array
1339
     */
1340
    public static function getStudents($group_id, $filterOnlyActive = false)
1341
    {
1342
        $activeCondition = $filterOnlyActive ? 'AND u.active = 1' : '';
1343
1344
        $em = Database::getManager();
1345
        $subscriptions = $em
1346
            ->createQuery("
1347
                SELECT u.id FROM ChamiloUserBundle:User u
1348
                INNER JOIN ChamiloCourseBundle:CGroupRelUser gu
1349
                    WITH u.id = gu.userId
1350
                INNER JOIN ChamiloCourseBundle:CGroupInfo g
1351
                WITH gu.groupId = g.id AND g.cId = gu.cId
1352
                WHERE gu.cId = :course AND g.id = :group
1353
                    $activeCondition
1354
            ")
1355
            ->setParameters([
1356
                'course' => api_get_course_int_id(),
1357
                'group' => intval($group_id),
1358
            ])
1359
            ->getResult();
1360
1361
        $users = [];
1362
        /** @var CGroupRelUser $subscription */
1363
        foreach ($subscriptions as $subscription) {
1364
            $users[] = api_get_user_info($subscription['id']);
1365
        }
1366
1367
        return $users;
1368
    }
1369
1370
    /**
1371
     * Returns users belonging to any of the group.
1372
     *
1373
     * @param array $groups list of group ids
1374
     *
1375
     * @return array list of user ids
1376
     */
1377
    public static function get_groups_users($groups = [])
1378
    {
1379
        $result = [];
1380
        $table = Database::get_course_table(TABLE_GROUP_USER);
1381
        $course_id = api_get_course_int_id();
1382
1383
        $groups = array_map('intval', $groups);
1384
        // protect individual elements with surrounding quotes
1385
        $groups = implode(', ', $groups);
1386
        $sql = "SELECT DISTINCT user_id
1387
                FROM $table gu
1388
                WHERE c_id = $course_id AND gu.group_id IN ($groups)";
1389
        $rs = Database::query($sql);
1390
        while ($row = Database::fetch_array($rs)) {
1391
            $result[] = $row['user_id'];
1392
        }
1393
1394
        return $result;
1395
    }
1396
1397
    /**
1398
     * Fill the groups with students.
1399
     * The algorithm takes care to first fill the groups with the least # of users.
1400
     * Analysis
1401
     * There was a problem with the "ALL" setting.
1402
     * When max # of groups is set to all, the value is sometimes NULL and sometimes ALL
1403
     * and in both cased the query does not work as expected.
1404
     * Stupid solution (currently implemented: set ALL to a big number (INFINITE) and things are solved :)
1405
     * Better solution: that's up to you.
1406
     *
1407
     * Note
1408
     * Throughout Dokeos there is some confusion about "course id" and "course code"
1409
     * The code is e.g. TEST101, but sometimes a variable that is called courseID also contains a course code string.
1410
     * However, there is also a integer course_id that uniquely identifies the course.
1411
     * ywarnier:> Now the course_id has been removed (25/1/2005)
1412
     * The databases are als very inconsistent in this.
1413
     *
1414
     * @param array $groupInfo
1415
     *
1416
     * @author Chrisptophe Gesche <[email protected]>,
1417
     *         Hugues Peeters     <[email protected]> - original version
1418
     * @author Roan Embrechts - virtual course support, code cleaning
1419
     * @author Bart Mollet - code cleaning, use other GroupManager-functions
1420
     *
1421
     * @return bool
1422
     */
1423
    public static function fillGroupWithUsers($groupInfo)
1424
    {
1425
        $_course = api_get_course_info();
1426
        if (empty($_course) || empty($groupInfo)) {
1427
            return false;
1428
        }
1429
        $session_id = api_get_session_id();
1430
        $complete_user_list = CourseManager::get_user_list_from_course_code(
1431
            $_course['code'],
1432
            $session_id
1433
        );
1434
        $groupIid = $groupInfo['iid'];
1435
        $category = self::get_category_from_group($groupIid);
1436
1437
        // Getting max numbers of user from group
1438
        $maxNumberStudents = empty($groupInfo['maximum_number_of_students']) ? self::INFINITE : $groupInfo['maximum_number_of_students'];
1439
        $groupsPerUser = self::INFINITE;
1440
        $categoryId = 0;
1441
        if ($category) {
1442
            $groupsPerUser = empty($category['groups_per_user']) ? self::INFINITE : $category['groups_per_user'];
1443
            $maxNumberStudentsCategory = empty($category['max_student']) ? self::INFINITE : $category['max_student'];
1444
            $categoryId = $category['id'];
1445
            if ($maxNumberStudentsCategory < $maxNumberStudents) {
1446
                $maxNumberStudents = $maxNumberStudentsCategory;
1447
            }
1448
        }
1449
1450
        $usersToAdd = [];
1451
        foreach ($complete_user_list as $userInfo) {
1452
            $isSubscribed = self::is_subscribed($userInfo['user_id'], $groupInfo);
1453
            if ($isSubscribed) {
1454
                continue;
1455
            }
1456
            $numberOfGroups = self::user_in_number_of_groups(
1457
                $userInfo['user_id'],
1458
                $categoryId
1459
            );
1460
            if ($groupsPerUser > $numberOfGroups) {
1461
                $usersToAdd[] = $userInfo['user_id'];
1462
            }
1463
            if (count($usersToAdd) == $maxNumberStudents) {
1464
                break;
1465
            }
1466
        }
1467
1468
        foreach ($usersToAdd as $userId) {
1469
            self::subscribe_users($userId, $groupInfo);
1470
        }
1471
    }
1472
1473
    /**
1474
     * Get the number of students in a group.
1475
     *
1476
     * @param int $group_id id
1477
     *
1478
     * @return int number of students in the given group
1479
     */
1480
    public static function number_of_students($group_id, $course_id = null)
1481
    {
1482
        $table = Database::get_course_table(TABLE_GROUP_USER);
1483
        $group_id = (int) $group_id;
1484
        $course_id = (int) $course_id;
1485
1486
        if (empty($course_id)) {
1487
            $course_id = api_get_course_int_id();
1488
        }
1489
        $sql = "SELECT COUNT(*) AS number_of_students
1490
                FROM $table
1491
                WHERE c_id = $course_id AND group_id = $group_id";
1492
        $result = Database::query($sql);
1493
        $db_object = Database::fetch_object($result);
1494
1495
        return $db_object->number_of_students;
1496
    }
1497
1498
    /**
1499
     * Maximum number of students in a group.
1500
     *
1501
     * @param int $group_id iid
1502
     *
1503
     * @return int maximum number of students in the given group
1504
     */
1505
    public static function maximum_number_of_students($group_id)
1506
    {
1507
        $table = Database::get_course_table(TABLE_GROUP);
1508
        $group_id = (int) $group_id;
1509
        $course_id = api_get_course_int_id();
1510
        $sql = "SELECT max_student FROM $table
1511
                WHERE c_id = $course_id AND iid = $group_id";
1512
        $db_result = Database::query($sql);
1513
        $db_object = Database::fetch_object($db_result);
1514
        if (0 == $db_object->max_student) {
1515
            return self::INFINITE;
1516
        }
1517
1518
        return $db_object->max_student;
1519
    }
1520
1521
    /**
1522
     * Number of groups of a user.
1523
     *
1524
     * @param int $user_id
1525
     * @param int $cat_id
1526
     *
1527
     * @return int the number of groups the user is subscribed in
1528
     */
1529
    public static function user_in_number_of_groups($user_id, $cat_id = 0)
1530
    {
1531
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1532
        $table_group = Database::get_course_table(TABLE_GROUP);
1533
        $user_id = (int) $user_id;
1534
        $cat_id = (int) $cat_id;
1535
1536
        $course_id = api_get_course_int_id();
1537
        $cat_condition = '';
1538
        if (!empty($cat_id)) {
1539
            $cat_condition = " AND g.category_id =  $cat_id ";
1540
        }
1541
1542
        $sql = "SELECT COUNT(*) AS number_of_groups
1543
                FROM $table_group_user gu
1544
                INNER JOIN $table_group g
1545
                ON (g.iid = gu.group_id AND gu.c_id = g.c_id)
1546
                WHERE
1547
                    gu.c_id = $course_id AND
1548
                    g.c_id = $course_id AND
1549
                    gu.user_id = $user_id
1550
                    $cat_condition";
1551
1552
        $result = Database::query($sql);
1553
        $db_object = Database::fetch_object($result);
1554
1555
        return $db_object->number_of_groups;
1556
    }
1557
1558
    /**
1559
     * Is sef-registration allowed?
1560
     *
1561
     * @param int   $user_id
1562
     * @param array $groupInfo
1563
     *
1564
     * @return bool TRUE if self-registration is allowed in the given group
1565
     */
1566
    public static function is_self_registration_allowed($user_id, $groupInfo)
1567
    {
1568
        $course_id = api_get_course_int_id();
1569
        if (empty($user_id)) {
1570
            return false;
1571
        }
1572
1573
        $groupIid = $groupInfo['iid'];
1574
        $table = Database::get_course_table(TABLE_GROUP);
1575
        if (isset($groupIid)) {
1576
            $sql = "SELECT status, self_registration_allowed
1577
                    FROM $table
1578
                    WHERE c_id = $course_id AND iid = $groupIid";
1579
            $result = Database::query($sql);
1580
            $group = Database::fetch_object($result);
1581
1582
            if ($group->status == 0 || $group->self_registration_allowed != 1) {
1583
                return false;
1584
            }
1585
1586
            return self::canUserSubscribe($user_id, $groupInfo);
1587
        }
1588
1589
        return false;
1590
    }
1591
1592
    /**
1593
     * Is sef-unregistration allowed?
1594
     *
1595
     * @param int   $user_id
1596
     * @param array $groupInfo
1597
     *
1598
     * @return bool TRUE if self-unregistration is allowed in the given group
1599
     */
1600
    public static function is_self_unregistration_allowed($user_id, $groupInfo)
1601
    {
1602
        if (empty($user_id) || empty($groupInfo)) {
1603
            return false;
1604
        }
1605
        $groupIid = $groupInfo['iid'];
1606
        $table = Database::get_course_table(TABLE_GROUP);
1607
        $course_id = api_get_course_int_id();
1608
1609
        $sql = "SELECT status, self_unregistration_allowed
1610
                FROM $table
1611
                WHERE c_id = $course_id AND iid = $groupIid";
1612
        $result = Database::query($sql);
1613
        $group = Database::fetch_object($result);
1614
1615
        if ($group->status == 0 || $group->self_unregistration_allowed != 1) {
1616
            return false;
1617
        }
1618
1619
        return self::is_subscribed($user_id, $groupInfo);
1620
    }
1621
1622
    /**
1623
     * Is user subscribed in group?
1624
     *
1625
     * @param int   $user_id
1626
     * @param array $groupInfo
1627
     *
1628
     * @return bool TRUE if given user is subscribed in given group
1629
     */
1630
    public static function is_subscribed($user_id, $groupInfo)
1631
    {
1632
        $course_id = api_get_course_int_id();
1633
        if (empty($user_id) || empty($groupInfo) || empty($course_id)) {
1634
            return false;
1635
        }
1636
        $table = Database::get_course_table(TABLE_GROUP_USER);
1637
        $group_id = (int) $groupInfo['id'];
1638
        $user_id = (int) $user_id;
1639
1640
        $sql = "SELECT 1 FROM $table
1641
                WHERE
1642
                    c_id = $course_id AND
1643
                    group_id = $group_id AND
1644
                    user_id = $user_id
1645
                ";
1646
        $result = Database::query($sql);
1647
1648
        return Database::num_rows($result) > 0;
1649
    }
1650
1651
    /**
1652
     * Can a user subscribe to a specified group in a course.
1653
     *
1654
     * @param int   $user_id
1655
     * @param array $groupInfo
1656
     * @param bool  $checkMaxNumberStudents
1657
     *
1658
     * @return bool TRUE if given user  can be subscribed in given group
1659
     */
1660
    public static function canUserSubscribe(
1661
        $user_id,
1662
        $groupInfo,
1663
        $checkMaxNumberStudents = true
1664
    ) {
1665
        $group_id = $groupInfo['id'];
1666
        $groupIid = $groupInfo['iid'];
1667
        if ($checkMaxNumberStudents) {
1668
            $category = self::get_category_from_group($groupIid);
1669
            if ($category) {
1670
                if ($category['groups_per_user'] == self::GROUP_PER_MEMBER_NO_LIMIT) {
1671
                    $category['groups_per_user'] = self::INFINITE;
1672
                }
1673
                $result = self::user_in_number_of_groups($user_id, $category['id']) < $category['groups_per_user'];
1674
                if ($result == false) {
1675
                    return false;
1676
                }
1677
            }
1678
1679
            $result = self::number_of_students($group_id) < self::maximum_number_of_students($groupIid);
1680
1681
            if ($result == false) {
1682
                return false;
1683
            }
1684
        }
1685
1686
        $result = self::is_tutor_of_group($user_id, $groupInfo);
1687
1688
        if ($result) {
1689
            return false;
1690
        }
1691
1692
        $result = self::is_subscribed($user_id, $groupInfo);
1693
1694
        if ($result) {
1695
            return false;
1696
        }
1697
1698
        return true;
1699
    }
1700
1701
    /**
1702
     * Get all subscribed users (members) from a group.
1703
     *
1704
     * @param array $groupInfo
1705
     *
1706
     * @return array An array with information of all users from the given group.
1707
     *               (user_id, firstname, lastname, email)
1708
     */
1709
    public static function get_subscribed_users($groupInfo)
1710
    {
1711
        if (empty($groupInfo)) {
1712
            return [];
1713
        }
1714
1715
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
1716
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1717
        $order_clause = api_sort_by_first_name() ? ' ORDER BY u.firstname, u.lastname' : ' ORDER BY u.lastname, u.firstname';
1718
        $orderListByOfficialCode = api_get_setting('order_user_list_by_official_code');
1719
        if ($orderListByOfficialCode === 'true') {
1720
            $order_clause = ' ORDER BY u.official_code, u.firstname, u.lastname';
1721
        }
1722
1723
        $group_id = (int) $groupInfo['iid'];
1724
1725
        if (empty($group_id)) {
1726
            return [];
1727
        }
1728
1729
        $course_id = api_get_course_int_id();
1730
1731
        $sql = "SELECT
1732
                    ug.id,
1733
                    u.user_id,
1734
                    u.lastname,
1735
                    u.firstname,
1736
                    u.email,
1737
                    u.username
1738
                FROM $table_user u
1739
                INNER JOIN $table_group_user ug
1740
                ON (ug.user_id = u.user_id)
1741
                WHERE ug.c_id = $course_id AND
1742
                      ug.group_id = $group_id
1743
                $order_clause";
1744
1745
        $db_result = Database::query($sql);
1746
        $users = [];
1747
        while ($user = Database::fetch_object($db_result)) {
1748
            $users[$user->user_id] = [
1749
                'user_id' => $user->user_id,
1750
                'firstname' => $user->firstname,
1751
                'lastname' => $user->lastname,
1752
                'email' => $user->email,
1753
                'username' => $user->username,
1754
            ];
1755
        }
1756
1757
        return $users;
1758
    }
1759
1760
    /**
1761
     * @author Patrick Cool <[email protected]>, Ghent University
1762
     * Get all subscribed tutors of a group
1763
     *
1764
     * @param array $groupInfo
1765
     *
1766
     * @return array An array with information of all users from the given group.
1767
     *               (user_id, firstname, lastname, email)
1768
     */
1769
    public static function get_subscribed_tutors($groupInfo, $id_only = false)
1770
    {
1771
        if (empty($groupInfo)) {
1772
            return [];
1773
        }
1774
1775
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
1776
        $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1777
        $order_clause = api_sort_by_first_name() ? ' ORDER BY u.firstname, u.lastname' : ' ORDER BY u.lastname, u.firstname';
1778
1779
        $orderListByOfficialCode = api_get_setting('order_user_list_by_official_code');
1780
        if ($orderListByOfficialCode === 'true') {
1781
            $order_clause = ' ORDER BY u.official_code, u.firstname, u.lastname';
1782
        }
1783
1784
        $group_id = (int) $groupInfo['iid'];
1785
        $course_id = api_get_course_int_id();
1786
1787
        $sql = "SELECT tg.id, u.user_id, u.lastname, u.firstname, u.email
1788
                FROM $table_user u, $table_group_tutor tg
1789
                WHERE
1790
                    tg.c_id = $course_id AND
1791
                    tg.group_id = $group_id AND
1792
                    tg.user_id = u.user_id
1793
                $order_clause
1794
                ";
1795
        $db_result = Database::query($sql);
1796
        $users = [];
1797
        while ($user = Database::fetch_object($db_result)) {
1798
            if (!$id_only) {
1799
                $member['user_id'] = $user->user_id;
1800
                $member['firstname'] = $user->firstname;
1801
                $member['lastname'] = $user->lastname;
1802
                $member['email'] = $user->email;
1803
                $users[] = $member;
1804
            } else {
1805
                $users[] = $user->user_id;
1806
            }
1807
        }
1808
1809
        return $users;
1810
    }
1811
1812
    /**
1813
     * Subscribe user(s) to a specified group in current course (as a student).
1814
     *
1815
     * @param mixed $user_ids  Can be an array with user-id's or a single user-id
1816
     * @param array $groupInfo
1817
     * @param int   $course_id
1818
     *
1819
     * @return bool TRUE if successful
1820
     */
1821
    public static function subscribe_users($user_ids, $groupInfo, $course_id = null)
1822
    {
1823
        $user_ids = is_array($user_ids) ? $user_ids : [$user_ids];
1824
        $course_id = empty($course_id) ? api_get_course_int_id() : (int) $course_id;
1825
        $group_id = $groupInfo['id'];
1826
1827
        if (!empty($user_ids)) {
1828
            $table = Database::get_course_table(TABLE_GROUP_USER);
1829
            foreach ($user_ids as $user_id) {
1830
                if (self::canUserSubscribe($user_id, $groupInfo)) {
1831
                    $user_id = (int) $user_id;
1832
                    $sql = "INSERT INTO ".$table." (c_id, user_id, group_id)
1833
                            VALUES ('$course_id', '".$user_id."', '".$group_id."')";
1834
                    Database::query($sql);
1835
                }
1836
            }
1837
        }
1838
1839
        return true;
1840
    }
1841
1842
    /**
1843
     * Subscribe tutor(s) to a specified group in current course.
1844
     *
1845
     * @param mixed $user_ids  Can be an array with user-id's or a single user-id
1846
     * @param array $groupInfo
1847
     * @param int   $course_id
1848
     *
1849
     * @author Patrick Cool <[email protected]>, Ghent University
1850
     *
1851
     * @see subscribe_users. This function is almost an exact copy of that function.
1852
     *
1853
     * @return bool TRUE if successful
1854
     */
1855
    public static function subscribe_tutors($user_ids, $groupInfo, $course_id = 0)
1856
    {
1857
        $user_ids = is_array($user_ids) ? $user_ids : [$user_ids];
1858
        $result = true;
1859
        $course_id = isset($course_id) && !empty($course_id) ? intval($course_id) : api_get_course_int_id();
1860
        $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1861
        $groupId = (int) $groupInfo['id'];
1862
1863
        foreach ($user_ids as $user_id) {
1864
            $user_id = intval($user_id);
1865
            if (self::canUserSubscribe($user_id, $groupInfo, false)) {
1866
                $sql = "INSERT INTO ".$table_group_tutor." (c_id, user_id, group_id)
1867
                        VALUES ('$course_id', '".$user_id."', '".$groupId."')";
1868
                $result = Database::query($sql);
1869
            }
1870
        }
1871
1872
        return $result;
1873
    }
1874
1875
    /**
1876
     * Unsubscribe user(s) from a specified group in current course.
1877
     *
1878
     * @param mixed $user_ids  Can be an array with user-id's or a single user-id
1879
     * @param array $groupInfo
1880
     *
1881
     * @return bool TRUE if successful
1882
     */
1883
    public static function unsubscribe_users($user_ids, $groupInfo)
1884
    {
1885
        $user_ids = is_array($user_ids) ? $user_ids : [$user_ids];
1886
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1887
        $group_id = intval($groupInfo['id']);
1888
        $course_id = api_get_course_int_id();
1889
        $sql = 'DELETE FROM '.$table_group_user.'
1890
                WHERE
1891
                    c_id = '.$course_id.' AND
1892
                    group_id = '.$group_id.' AND
1893
                    user_id IN ('.implode(',', $user_ids).')
1894
                ';
1895
        Database::query($sql);
1896
    }
1897
1898
    /**
1899
     * Unsubscribe all users from one or more groups.
1900
     *
1901
     * @param array $groupInfo
1902
     *
1903
     * @return bool TRUE if successful
1904
     */
1905
    public static function unsubscribe_all_users($groupInfo)
1906
    {
1907
        $course_id = api_get_course_int_id();
1908
        $groupId = (int) $groupInfo['id'];
1909
        if (empty($course_id) || empty($groupId)) {
1910
            return false;
1911
        }
1912
1913
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1914
        $sql = "DELETE FROM $table_group_user
1915
                WHERE
1916
                    group_id = $groupId AND
1917
                    c_id = $course_id";
1918
        $result = Database::query($sql);
1919
1920
        return $result;
1921
    }
1922
1923
    /**
1924
     * Unsubscribe all tutors from one or more groups.
1925
     *
1926
     * @param int $groupId iid
1927
     *
1928
     * @see unsubscribe_all_users. This function is almost an exact copy of that function.
1929
     *
1930
     * @return bool TRUE if successful
1931
     *
1932
     * @author Patrick Cool <[email protected]>, Ghent University
1933
     */
1934
    public static function unsubscribe_all_tutors($groupId)
1935
    {
1936
        $courseId = api_get_course_int_id();
1937
        $groupId = (int) $groupId;
1938
1939
        if (empty($courseId) || empty($groupId)) {
1940
            return false;
1941
        }
1942
1943
        if (!empty($groupId)) {
1944
            $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1945
            $sql = "DELETE FROM $table_group_tutor
1946
                    WHERE group_id = $groupId AND c_id = $courseId";
1947
            $result = Database::query($sql);
1948
1949
            return $result;
1950
        }
1951
1952
        return true;
1953
    }
1954
1955
    /**
1956
     * Is the user a tutor of this group?
1957
     *
1958
     * @param int   $user_id   the id of the user
1959
     * @param array $groupInfo
1960
     * @param int   $courseId
1961
     *
1962
     * @return bool true/false
1963
     *
1964
     * @todo use the function user_has_access that includes this function
1965
     *
1966
     * @author Patrick Cool <[email protected]>, Ghent University
1967
     */
1968
    public static function is_tutor_of_group($user_id, $groupInfo, $courseId = 0)
1969
    {
1970
        if (empty($groupInfo)) {
1971
            return false;
1972
        }
1973
1974
        $courseId = empty($courseId) ? api_get_course_int_id() : (int) $courseId;
1975
        if (empty($courseId)) {
1976
            return false;
1977
        }
1978
1979
        $user_id = (int) $user_id;
1980
        $group_id = (int) $groupInfo['id'];
1981
1982
        $table = Database::get_course_table(TABLE_GROUP_TUTOR);
1983
1984
        $sql = "SELECT * FROM $table
1985
                WHERE
1986
                    c_id = $courseId AND
1987
                    user_id = $user_id AND
1988
                    group_id = $group_id";
1989
        $result = Database::query($sql);
1990
        if (Database::num_rows($result) > 0) {
1991
            return true;
1992
        }
1993
1994
        return false;
1995
    }
1996
1997
    /**
1998
     * Is the user part of this group? This can be a tutor or a normal member
1999
     * you should use this function if the access to a tool or functionality is
2000
     * restricted to the people who are actually in the group
2001
     * before you had to check if the user was
2002
     * 1. a member of the group OR
2003
     * 2. a tutor of the group. This function combines both.
2004
     *
2005
     * @param int   $user_id   the id of the user
2006
     * @param array $groupInfo
2007
     *
2008
     * @return bool true/false
2009
     *
2010
     * @author Patrick Cool <[email protected]>, Ghent University
2011
     */
2012
    public static function is_user_in_group($user_id, $groupInfo)
2013
    {
2014
        $member = self::is_subscribed($user_id, $groupInfo);
2015
        if ($member) {
2016
            return true;
2017
        }
2018
2019
        $tutor = self::is_tutor_of_group($user_id, $groupInfo);
2020
        if ($tutor) {
2021
            return true;
2022
        }
2023
2024
        return false;
2025
    }
2026
2027
    /**
2028
     * Get all group's from a given course in which a given user is unsubscribed.
2029
     *
2030
     * @author  Patrick Cool
2031
     *
2032
     * @param int $course_id retrieve the groups for
2033
     * @param int $user_id   the ID of the user you want to know all its group memberships
2034
     *
2035
     * @return array
2036
     */
2037
    public static function get_group_ids($course_id, $user_id)
2038
    {
2039
        $groups = [];
2040
        $tbl_group = Database::get_course_table(TABLE_GROUP_USER);
2041
        $tbl_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
2042
        $user_id = intval($user_id);
2043
        $course_id = intval($course_id);
2044
2045
        $sql = "SELECT group_id FROM $tbl_group
2046
                WHERE c_id = $course_id AND user_id = '$user_id'";
2047
        $result = Database::query($sql);
2048
2049
        if ($result) {
2050
            while ($row = Database::fetch_array($result)) {
2051
                $groups[] = $row['group_id'];
2052
            }
2053
        }
2054
2055
        //Also loading if i'm the tutor
2056
        $sql = "SELECT group_id FROM $tbl_group_tutor
2057
                WHERE c_id = $course_id AND user_id = '$user_id'";
2058
        $result = Database::query($sql);
2059
        if ($result) {
2060
            while ($row = Database::fetch_array($result)) {
2061
                $groups[] = $row['group_id'];
2062
            }
2063
        }
2064
        if (!empty($groups)) {
2065
            array_filter($groups);
2066
        }
2067
2068
        return $groups;
2069
    }
2070
2071
    /**
2072
     * Check if a user has access to a certain group tool.
2073
     *
2074
     * @param int    $user_id  The user id
2075
     * @param int    $group_id The group iid
2076
     * @param string $tool     The tool to check the access rights. This should be
2077
     *                         one of constants: GROUP_TOOL_DOCUMENTS
2078
     *
2079
     * @return bool true if the given user has access to the given tool in the
2080
     *              given course
2081
     */
2082
    public static function user_has_access($user_id, $group_id, $tool)
2083
    {
2084
        // Admin have access everywhere
2085
        if (api_is_platform_admin()) {
2086
            return true;
2087
        }
2088
2089
        // Course admin also have access to everything
2090
        if (api_is_allowed_to_edit(false, true, true)) {
2091
            return true;
2092
        }
2093
2094
        switch ($tool) {
2095
            case self::GROUP_TOOL_FORUM:
2096
                $key = 'forum_state';
2097
                break;
2098
            case self::GROUP_TOOL_DOCUMENTS:
2099
                $key = 'doc_state';
2100
                break;
2101
            case self::GROUP_TOOL_CALENDAR:
2102
                $key = 'calendar_state';
2103
                break;
2104
            case self::GROUP_TOOL_ANNOUNCEMENT:
2105
                $key = 'announcements_state';
2106
                break;
2107
            case self::GROUP_TOOL_WORK:
2108
                $key = 'work_state';
2109
                break;
2110
            case self::GROUP_TOOL_WIKI:
2111
                $key = 'wiki_state';
2112
                break;
2113
            case self::GROUP_TOOL_CHAT:
2114
                $key = 'chat_state';
2115
                break;
2116
            default:
2117
                return false;
2118
        }
2119
2120
        // Check group properties
2121
        $groupInfo = self::get_group_properties($group_id, true);
2122
2123
        if (empty($groupInfo)) {
2124
            return false;
2125
        }
2126
2127
        if ($groupInfo['status'] == 0) {
2128
            return false;
2129
        }
2130
2131
        if (!isset($groupInfo[$key])) {
2132
            return false;
2133
        }
2134
2135
        $status = $groupInfo[$key];
2136
2137
        switch ($status) {
2138
            case self::TOOL_NOT_AVAILABLE:
2139
                return false;
2140
                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...
2141
            case self::TOOL_PUBLIC:
2142
                return true;
2143
                break;
2144
            case self::TOOL_PRIVATE:
2145
                $userIsInGroup = self::is_user_in_group($user_id, $groupInfo);
2146
                if ($userIsInGroup) {
2147
                    return true;
2148
                }
2149
                break;
2150
            case self::TOOL_PRIVATE_BETWEEN_USERS:
2151
                // Only works for announcements for now
2152
                $userIsInGroup = self::is_user_in_group($user_id, $groupInfo);
2153
                if ($userIsInGroup && $tool == self::GROUP_TOOL_ANNOUNCEMENT) {
2154
                    return true;
2155
                }
2156
                break;
2157
        }
2158
2159
        return false;
2160
    }
2161
2162
    /**
2163
     * @param int   $userId
2164
     * @param array $groupInfo
2165
     * @param int   $sessionId
2166
     *
2167
     * @return bool
2168
     */
2169
    public static function userHasAccessToBrowse($userId, $groupInfo, $sessionId = 0)
2170
    {
2171
        if (empty($groupInfo)) {
2172
            return false;
2173
        }
2174
2175
        if (api_is_platform_admin()) {
2176
            return true;
2177
        }
2178
2179
        if (api_is_allowed_to_edit(false, true, true)) {
2180
            return true;
2181
        }
2182
2183
        if (!empty($sessionId)) {
2184
            if (api_is_coach($sessionId, api_get_course_int_id())) {
2185
                return true;
2186
            }
2187
2188
            if (api_is_drh()) {
2189
                if (SessionManager::isUserSubscribedAsHRM($sessionId, $userId)) {
2190
                    return true;
2191
                }
2192
            }
2193
        }
2194
2195
        $groupId = $groupInfo['iid'];
2196
        if (self::is_tutor_of_group($userId, $groupInfo)) {
2197
            return true;
2198
        }
2199
2200
        if ($groupInfo['status'] == 0) {
2201
            return false;
2202
        }
2203
2204
        if (self::user_has_access($userId, $groupId, self::GROUP_TOOL_FORUM) ||
2205
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_DOCUMENTS) ||
2206
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_CALENDAR) ||
2207
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_ANNOUNCEMENT) ||
2208
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_WORK) ||
2209
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_WIKI) ||
2210
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_CHAT)
2211
        ) {
2212
            return true;
2213
        }
2214
2215
        if (api_is_session_general_coach() && $groupInfo['session_id'] == $sessionId) {
2216
            return true;
2217
        }
2218
2219
        return false;
2220
    }
2221
2222
    /**
2223
     * Get all groups where a specific user is subscribed.
2224
     *
2225
     * @param int $user_id
2226
     *
2227
     * @return array
2228
     */
2229
    public static function get_user_group_name($user_id)
2230
    {
2231
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
2232
        $table_group = Database::get_course_table(TABLE_GROUP);
2233
        $user_id = intval($user_id);
2234
        $course_id = api_get_course_int_id();
2235
        $sql = "SELECT name
2236
                FROM $table_group g
2237
                INNER JOIN $table_group_user gu
2238
                ON (gu.group_id = g.iid)
2239
                WHERE
2240
                  gu.c_id= $course_id AND
2241
                  g.c_id= $course_id AND
2242
                  gu.user_id = $user_id";
2243
        $res = Database::query($sql);
2244
        $groups = [];
2245
        while ($group = Database::fetch_array($res)) {
2246
            $groups[] .= $group['name'];
2247
        }
2248
2249
        return $groups;
2250
    }
2251
2252
    /**
2253
     * Get all groups where a specific user is subscribed.
2254
     *
2255
     * @param int      $user_id
2256
     * @param int      $courseId
2257
     * @param int|null $sessionId
2258
     *
2259
     * @return array
2260
     */
2261
    public static function getAllGroupPerUserSubscription($user_id, $courseId = 0, $sessionId = null)
2262
    {
2263
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
2264
        $table_tutor_user = Database::get_course_table(TABLE_GROUP_TUTOR);
2265
        $table_group = Database::get_course_table(TABLE_GROUP);
2266
        $user_id = (int) $user_id;
2267
        $courseId = empty($courseId) ? api_get_course_int_id() : (int) $courseId;
2268
2269
        $sql = "SELECT DISTINCT g.*
2270
               FROM $table_group g
2271
               LEFT JOIN $table_group_user gu
2272
               ON (gu.group_id = g.iid AND g.c_id = gu.c_id)
2273
               LEFT JOIN $table_tutor_user tu
2274
               ON (tu.group_id = g.iid AND g.c_id = tu.c_id)
2275
               WHERE
2276
                  g.c_id = $courseId AND
2277
                  (gu.user_id = $user_id OR tu.user_id = $user_id) ";
2278
2279
        if (null !== $sessionId) {
2280
            $sessionId = (int) $sessionId;
2281
            $sql .= " AND g.session_id = $sessionId ";
2282
        }
2283
2284
        $res = Database::query($sql);
2285
        $groups = [];
2286
        while ($group = Database::fetch_array($res, 'ASSOC')) {
2287
            $groups[] = $group;
2288
        }
2289
2290
        return $groups;
2291
    }
2292
2293
    /**
2294
     * @param array $group_list
2295
     * @param int   $category_id
2296
     *
2297
     * @return string
2298
     */
2299
    public static function process_groups($group_list, $category_id = 0)
2300
    {
2301
        $charset = 'UTF-8';
2302
        $category_id = (int) $category_id;
2303
        $totalRegistered = 0;
2304
        $group_data = [];
2305
        $user_info = api_get_user_info();
2306
        $session_id = api_get_session_id();
2307
        $user_id = $user_info['user_id'];
2308
        $hideGroup = api_get_setting('hide_course_group_if_no_tools_available');
2309
        $extraField = new ExtraField('survey');
2310
        $surveyGroupExists = $extraField->get_handler_field_info_by_field_variable('group_id') ? true : false;
2311
        $url = api_get_path(WEB_CODE_PATH).'group/';
2312
2313
        foreach ($group_list as $this_group) {
2314
            // Validation when belongs to a session
2315
            $session_img = api_get_session_image($this_group['session_id'], $user_info['status']);
2316
2317
            // All the tutors of this group
2318
            $tutors = self::get_subscribed_tutors($this_group, true);
2319
            $isMember = self::is_subscribed($user_id, $this_group);
2320
2321
            // Create a new table-row
2322
            $row = [];
2323
            // Checkbox
2324
            if (api_is_allowed_to_edit(false, true) && count($group_list) > 1) {
2325
                $row[] = $this_group['id'];
2326
            }
2327
2328
            if (self::userHasAccessToBrowse($user_id, $this_group, $session_id)) {
2329
                // Group name
2330
                $groupNameClass = null;
2331
                if (0 == $this_group['status']) {
2332
                    $groupNameClass = 'muted';
2333
                }
2334
2335
                $group_name = '<a class="'.$groupNameClass.'" href="group_space.php?'.api_get_cidreq(true, false).'&gidReq='.$this_group['id'].'">'.
2336
                    Security::remove_XSS($this_group['name']).'</a> ';
2337
2338
                $group_name2 = '';
2339
                if (api_get_configuration_value('extra')) {
2340
                    $group_name2 = '<a href="group_space_tracking.php?cidReq='.api_get_course_id().'&gidReq='
2341
                        .$this_group['id'].'">'.get_lang('suivi_de').''.stripslashes($this_group['name']).'</a>';
2342
                }
2343
2344
                if (!empty($user_id) && !empty($this_group['id_tutor']) && $user_id == $this_group['id_tutor']) {
2345
                    $group_name .= Display::label(get_lang('OneMyGroups'), 'success');
2346
                } elseif ($isMember) {
2347
                    $group_name .= Display::label(get_lang('MyGroup'), 'success');
2348
                }
2349
2350
                if (api_is_allowed_to_edit() && !empty($this_group['session_name'])) {
2351
                    $group_name .= ' ('.$this_group['session_name'].')';
2352
                }
2353
                $group_name .= $session_img;
2354
                $row[] = Security::remove_XSS($group_name).
2355
                    $group_name2.'<br />'.Security::remove_XSS(stripslashes(trim($this_group['description'])));
2356
            } else {
2357
                if ('true' === $hideGroup) {
2358
                    continue;
2359
                }
2360
                $row[] = Security::remove_XSS($this_group['name']).'<br />'.
2361
                    Security::remove_XSS(stripslashes(trim($this_group['description'])));
2362
            }
2363
2364
            // Tutor name
2365
            $tutor_info = '';
2366
            if (count($tutors) > 0) {
2367
                foreach ($tutors as $tutor_id) {
2368
                    $tutor = api_get_user_info($tutor_id);
2369
                    $username = api_htmlentities(
2370
                        sprintf(get_lang('LoginX'), $tutor['username']),
2371
                        ENT_QUOTES
2372
                    );
2373
                    if ('true' === api_get_setting('show_email_addresses')) {
2374
                        $tutor_info .= Display::tag(
2375
                            'span',
2376
                            Display::encrypted_mailto_link(
2377
                                $tutor['mail'],
2378
                                $tutor['complete_name']
2379
                            ),
2380
                            ['title' => $username]
2381
                        ).', ';
2382
                    } else {
2383
                        if (api_is_allowed_to_edit()) {
2384
                            $tutor_info .= Display::tag(
2385
                            'span',
2386
                                Display::encrypted_mailto_link(
2387
                                    $tutor['mail'],
2388
                                    $tutor['complete_name_with_username']
2389
                                ),
2390
                                ['title' => $username]
2391
                            ).', ';
2392
                        } else {
2393
                            $tutor_info .= Display::tag(
2394
                                'span',
2395
                                $tutor['complete_name'],
2396
                                ['title' => $username]
2397
                            ).', ';
2398
                        }
2399
                    }
2400
                }
2401
            }
2402
2403
            $tutor_info = api_substr(
2404
                $tutor_info,
2405
                0,
2406
                api_strlen($tutor_info) - 2
2407
            );
2408
            $row[] = $tutor_info;
2409
2410
            // Max number of members in group
2411
            $max_members = $this_group['maximum_number_of_members'] == self::MEMBER_PER_GROUP_NO_LIMIT ? ' ' : ' / '.$this_group['maximum_number_of_members'];
2412
2413
            // Number of members in group
2414
            $row[] = $this_group['number_of_members'].$max_members;
2415
2416
            // Self-registration / unregistration
2417
            if (!api_is_allowed_to_edit(false, true)) {
2418
                if (self::is_self_registration_allowed($user_id, $this_group)) {
2419
                    $row[] = '<a class = "btn btn-default"
2420
                        href="group.php?'.api_get_cidreq().'&category='.$category_id.'&action=self_reg&group_id='.$this_group['id'].'"
2421
                        onclick="javascript:if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES, $charset))."'".')) return false;">'.get_lang('GroupSelfRegInf').'</a>';
2422
                } elseif (self::is_self_unregistration_allowed($user_id, $this_group)) {
2423
                    $row[] = '<a class = "btn btn-default"
2424
                        href="group.php?'.api_get_cidreq().'&category='.$category_id.'&action=self_unreg&group_id='.$this_group['id'].'"
2425
                        onclick="javascript:if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES, $charset))."'".')) return false;">'.get_lang('GroupSelfUnRegInf').'</a>';
2426
                } else {
2427
                    $row[] = '-';
2428
                }
2429
            }
2430
2431
            // Edit-links
2432
            if (api_is_allowed_to_edit(false, true) &&
2433
                !(api_is_session_general_coach() && intval($this_group['session_id']) != $session_id)
2434
            ) {
2435
                $edit_actions = '<a href="'.$url.'settings.php?'.api_get_cidreq(true, false).'&gidReq='.$this_group['id'].'" title="'.get_lang('Edit').'">'.
2436
                    Display::return_icon('edit.png', get_lang('EditGroup'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2437
2438
                if ($this_group['status'] == 1) {
2439
                    $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').'">'.
2440
                        Display::return_icon('visible.png', get_lang('Hide'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2441
                } else {
2442
                    $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').'">'.
2443
                        Display::return_icon('invisible.png', get_lang('Show'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2444
                }
2445
2446
                $edit_actions .= '<a href="'.$url.'member_settings.php?'.api_get_cidreq(true, false).'&gidReq='.$this_group['id'].'" title="'.get_lang('GroupMembers').'">'.
2447
                    Display::return_icon('user.png', get_lang('GroupMembers'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2448
2449
                $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').'">'.
2450
                    Display::return_icon('export_group_excel.png', get_lang('Export'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2451
2452
                $edit_actions .= '<a href="'.$url.'group_overview.php?action=export_users&'.api_get_cidreq(true, false).'&id='.$this_group['id'].'" title="'.get_lang('ExportUsers').'">'.
2453
                    Display::return_icon('export_users_csv.png', get_lang('ExportUsers'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2454
2455
                if ($surveyGroupExists) {
2456
                    $edit_actions .= Display::url(
2457
                            Display::return_icon('survey.png', get_lang('ExportSurveyResults'), '', ICON_SIZE_SMALL),
2458
                            $url.'group_overview.php?action=export_surveys&'.api_get_cidreq(true, false).'&id='.$this_group['id']
2459
                        ).'&nbsp;';
2460
                }
2461
                $edit_actions .= '<a href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=fill_one&id='.$this_group['id'].'"
2462
                    onclick="javascript: if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES))."'".')) return false;" title="'.get_lang('FillGroup').'">'.
2463
                    Display::return_icon('fill.png', get_lang('FillGroup'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2464
2465
                $edit_actions .= '<a href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=delete_one&id='.$this_group['id'].'"
2466
                    onclick="javascript: if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES))."'".')) return false;" title="'.get_lang('Delete').'">'.
2467
                    Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2468
2469
                $row[] = $edit_actions;
2470
            }
2471
            if (!empty($this_group['nbMember'])) {
2472
                $totalRegistered = $totalRegistered + $this_group['nbMember'];
2473
            }
2474
            $group_data[] = $row;
2475
        }
2476
2477
        // If no groups then don't show the table (only for students)
2478
        if (!api_is_allowed_to_edit(true, false)) {
2479
            if (empty($group_data)) {
2480
                return '';
2481
            }
2482
        }
2483
2484
        $table = new SortableTableFromArrayConfig(
2485
            $group_data,
2486
            1,
2487
            20,
2488
            'group_category_'.$category_id
2489
        );
2490
        $table->set_additional_parameters(['category' => $category_id]);
2491
        $column = 0;
2492
        if (api_is_allowed_to_edit(false, true) && count($group_list) > 1) {
2493
            $table->set_header($column++, '', false);
2494
        }
2495
        $table->set_header($column++, get_lang('Groups'));
2496
        $table->set_header($column++, get_lang('GroupTutor'));
2497
        $table->set_header($column++, get_lang('Registered'), false);
2498
2499
        if (!api_is_allowed_to_edit(false, true)) {
2500
            // If self-registration allowed
2501
            $table->set_header($column++, get_lang('GroupSelfRegistration'), false);
2502
        }
2503
2504
        if (api_is_allowed_to_edit(false, true)) {
2505
            // Only for course administrator
2506
            $table->set_header($column++, get_lang('Modify'), false);
2507
            $form_actions = [];
2508
            $form_actions['fill_selected'] = get_lang('FillGroup');
2509
            $form_actions['empty_selected'] = get_lang('EmptyGroup');
2510
            $form_actions['delete_selected'] = get_lang('Delete');
2511
            if (count($group_list) > 1) {
2512
                $table->set_form_actions($form_actions, 'group');
2513
            }
2514
        }
2515
2516
        return $table->return_table();
2517
    }
2518
2519
    /**
2520
     * @param array $groupData
2521
     * @param bool  $deleteNotInArray
2522
     *
2523
     * @return array
2524
     */
2525
    public static function importCategoriesAndGroupsFromArray(
2526
        $groupData,
2527
        $deleteNotInArray = false
2528
    ) {
2529
        $result = [];
2530
        $elementsFound = [
2531
            'categories' => [],
2532
            'groups' => [],
2533
        ];
2534
2535
        $courseCode = api_get_course_id();
2536
        $sessionId = api_get_session_id();
2537
        $groupCategories = self::get_categories();
2538
2539
        if (empty($groupCategories)) {
2540
            $result['error'][] = get_lang('CreateACategory');
2541
2542
            return $result;
2543
        }
2544
2545
        foreach ($groupData as $data) {
2546
            $isCategory = empty($data['group']) ? true : false;
2547
            if ($isCategory) {
2548
                $categoryInfo = self::getCategoryByTitle($data['category']);
2549
                $categoryId = $categoryInfo['id'];
2550
2551
                if (!empty($categoryInfo)) {
2552
                    // Update
2553
                    self::update_category(
2554
                        $categoryId,
2555
                        $data['category'],
2556
                        $data['description'],
2557
                        $data['doc_state'],
2558
                        $data['work_state'],
2559
                        $data['calendar_state'],
2560
                        $data['announcements_state'],
2561
                        $data['forum_state'],
2562
                        $data['wiki_state'],
2563
                        $data['chat_state'],
2564
                        $data['self_reg_allowed'],
2565
                        $data['self_unreg_allowed'],
2566
                        $data['max_student'],
2567
                        $data['groups_per_user'],
2568
                        isset($data['document_access']) ? $data['document_access'] : null
2569
                    );
2570
                    $data['category_id'] = $categoryId;
2571
                    $result['updated']['category'][] = $data;
2572
                } else {
2573
                    // Add
2574
                    $categoryId = self::create_category(
2575
                        $data['category'],
2576
                        $data['description'],
2577
                        $data['doc_state'],
2578
                        $data['work_state'],
2579
                        $data['calendar_state'],
2580
                        $data['announcements_state'],
2581
                        $data['forum_state'],
2582
                        $data['wiki_state'],
2583
                        $data['chat_state'],
2584
                        $data['self_reg_allowed'],
2585
                        $data['self_unreg_allowed'],
2586
                        $data['max_student'],
2587
                        $data['groups_per_user']
2588
                    );
2589
2590
                    if ($categoryId) {
2591
                        $data['category_id'] = $categoryId;
2592
                        $result['added']['category'][] = $data;
2593
                    }
2594
                }
2595
                $elementsFound['categories'][] = $categoryId;
2596
            } else {
2597
                $groupInfo = self::getGroupByName($data['group']);
2598
                $categoryInfo = [];
2599
                if (isset($data['category'])) {
2600
                    $categoryInfo = self::getCategoryByTitle($data['category']);
2601
                }
2602
                $categoryId = null;
2603
                if (!empty($categoryInfo)) {
2604
                    $categoryId = $categoryInfo['id'];
2605
                } else {
2606
                    if (!empty($groupCategories) && isset($groupCategories[0])) {
2607
                        $defaultGroupCategory = $groupCategories[0];
2608
                        $categoryId = $defaultGroupCategory['id'];
2609
                    }
2610
                }
2611
2612
                if (empty($groupInfo)) {
2613
                    // Add
2614
                    $groupId = self::create_group(
2615
                        $data['group'],
2616
                        $categoryId,
2617
                        null,
2618
                        $data['max_student']
2619
                    );
2620
2621
                    if ($groupId) {
2622
                        self::set_group_properties(
2623
                            $groupId,
2624
                            $data['group'],
2625
                            $data['description'],
2626
                            $data['max_student'],
2627
                            $data['doc_state'],
2628
                            $data['work_state'],
2629
                            $data['calendar_state'],
2630
                            $data['announcements_state'],
2631
                            $data['forum_state'],
2632
                            $data['wiki_state'],
2633
                            $data['chat_state'],
2634
                            $data['self_reg_allowed'],
2635
                            $data['self_unreg_allowed'],
2636
                            $categoryId
2637
                        );
2638
                        $data['group_id'] = $groupId;
2639
                        $result['added']['group'][] = $data;
2640
                    }
2641
                    $groupInfo = self::get_group_properties($groupId, true);
2642
                } else {
2643
                    // Update
2644
                    $groupId = $groupInfo['id'];
2645
                    self::set_group_properties(
2646
                        $groupId,
2647
                        $data['group'],
2648
                        $data['description'],
2649
                        $data['max_student'],
2650
                        $data['doc_state'],
2651
                        $data['work_state'],
2652
                        $data['calendar_state'],
2653
                        $data['announcements_state'],
2654
                        $data['forum_state'],
2655
                        $data['wiki_state'],
2656
                        $data['chat_state'],
2657
                        $data['self_reg_allowed'],
2658
                        $data['self_unreg_allowed'],
2659
                        $categoryId
2660
                    );
2661
2662
                    $data['group_id'] = $groupId;
2663
                    $result['updated']['group'][] = $data;
2664
                    $groupInfo = self::get_group_properties($groupId);
2665
                }
2666
2667
                $students = isset($data['students']) ? explode(',', $data['students']) : [];
2668
                if (!empty($students)) {
2669
                    $studentUserIdList = [];
2670
                    foreach ($students as $student) {
2671
                        $userInfo = api_get_user_info_from_username($student);
2672
2673
                        if (!$userInfo) {
2674
                            continue;
2675
                        }
2676
2677
                        if (!CourseManager::is_user_subscribed_in_course(
2678
                                $userInfo['user_id'],
2679
                                $courseCode,
2680
                                !empty($sessionId),
2681
                                $sessionId
2682
                            )
2683
                        ) {
2684
                            Display::addFlash(
2685
                                Display::return_message(
2686
                                    sprintf(
2687
                                        get_lang('StudentXIsNotSubscribedToCourse'),
2688
                                        $userInfo['complete_name']
2689
                                    ),
2690
                                    'warning'
2691
                                )
2692
                            );
2693
                            continue;
2694
                        }
2695
2696
                        $studentUserIdList[] = $userInfo['user_id'];
2697
                    }
2698
                    self::subscribe_users($studentUserIdList, $groupInfo);
2699
                }
2700
2701
                $tutors = isset($data['tutors']) ? explode(',', $data['tutors']) : [];
2702
                if (!empty($tutors)) {
2703
                    $tutorIdList = [];
2704
                    foreach ($tutors as $tutor) {
2705
                        $userInfo = api_get_user_info_from_username($tutor);
2706
2707
                        if (!$userInfo) {
2708
                            continue;
2709
                        }
2710
2711
                        if (!CourseManager::is_user_subscribed_in_course(
2712
                                $userInfo['user_id'],
2713
                                $courseCode,
2714
                                !empty($sessionId),
2715
                                $sessionId
2716
                            )
2717
                        ) {
2718
                            Display::addFlash(
2719
                                Display::return_message(
2720
                                    sprintf(get_lang('TutorXIsNotSubscribedToCourse'), $userInfo['complete_name']),
2721
                                    'warning'
2722
                                )
2723
                            );
2724
2725
                            continue;
2726
                        }
2727
2728
                        $tutorIdList[] = $userInfo['user_id'];
2729
                    }
2730
                    self::subscribe_tutors($tutorIdList, $groupInfo);
2731
                }
2732
2733
                $elementsFound['groups'][] = $groupId;
2734
            }
2735
        }
2736
2737
        if ($deleteNotInArray) {
2738
            // Check categories
2739
            $categories = self::get_categories();
2740
            foreach ($categories as $category) {
2741
                if (!in_array($category['id'], $elementsFound['categories'])) {
2742
                    self::delete_category($category['id']);
2743
                    $category['category'] = $category['title'];
2744
                    $result['deleted']['category'][] = $category;
2745
                }
2746
            }
2747
2748
            $groups = self::get_groups();
2749
            foreach ($groups as $group) {
2750
                if (!in_array($group['iid'], $elementsFound['groups'])) {
2751
                    self::deleteGroup($group);
2752
                    $group['group'] = $group['name'];
2753
                    $result['deleted']['group'][] = $group;
2754
                }
2755
            }
2756
        }
2757
2758
        return $result;
2759
    }
2760
2761
    /**
2762
     * Export all students from a group to an array.
2763
     * This function works only in a context of a course.
2764
     *
2765
     * @param int $groupId
2766
     *
2767
     * @return array
2768
     */
2769
    public static function exportStudentsToArray($groupId = null)
2770
    {
2771
        if (empty($groupId)) {
2772
            return false;
2773
        }
2774
        $data = [];
2775
        $data[] = [
2776
            'OfficialCode',
2777
            'Lastname',
2778
            'Firsname',
2779
            'Email',
2780
        ];
2781
        $users = self::getStudents($groupId);
2782
        $count = 1;
2783
        foreach ($users as $user) {
2784
            $user = api_get_user_info($user['user_id']);
2785
            $data[$count][] = $user['official_code'];
2786
            $data[$count][] = $user['lastname'];
2787
            $data[$count][] = $user['firstname'];
2788
            $data[$count][] = $user['email'];
2789
            $count++;
2790
        }
2791
2792
        return $data;
2793
    }
2794
2795
    /**
2796
     * Export all categories/group from a course to an array.
2797
     * This function works only in a context of a course.
2798
     *
2799
     * @param int  $groupId
2800
     * @param bool $loadUsers
2801
     *
2802
     * @return array
2803
     */
2804
    public static function exportCategoriesAndGroupsToArray($groupId = null, $loadUsers = false)
2805
    {
2806
        $data = [];
2807
        $data[] = [
2808
            'category',
2809
            'group',
2810
            'description',
2811
            'announcements_state',
2812
            'calendar_state',
2813
            'chat_state',
2814
            'doc_state',
2815
            'forum_state',
2816
            'work_state',
2817
            'wiki_state',
2818
            'max_student',
2819
            'self_reg_allowed',
2820
            'self_unreg_allowed',
2821
            'groups_per_user',
2822
        ];
2823
2824
        $count = 1;
2825
2826
        if ($loadUsers) {
2827
            $data[0][] = 'students';
2828
            $data[0][] = 'tutors';
2829
            $data[0][] = 'emails';
2830
        }
2831
2832
        if (false == $loadUsers) {
2833
            $categories = self::get_categories();
2834
2835
            foreach ($categories as $categoryInfo) {
2836
                $data[$count] = [
2837
                    $categoryInfo['title'],
2838
                    null,
2839
                    $categoryInfo['description'],
2840
                    $categoryInfo['announcements_state'],
2841
                    $categoryInfo['calendar_state'],
2842
                    $categoryInfo['chat_state'],
2843
                    $categoryInfo['doc_state'],
2844
                    $categoryInfo['forum_state'],
2845
                    $categoryInfo['work_state'],
2846
                    $categoryInfo['wiki_state'],
2847
                    $categoryInfo['max_student'],
2848
                    $categoryInfo['self_reg_allowed'],
2849
                    $categoryInfo['self_unreg_allowed'],
2850
                    $categoryInfo['groups_per_user'],
2851
                ];
2852
                $count++;
2853
            }
2854
        }
2855
2856
        $groups = self::get_group_list();
2857
2858
        foreach ($groups as $groupInfo) {
2859
            $categoryTitle = null;
2860
            $categoryInfo = self::get_category($groupInfo['category_id']);
2861
            $groupSettings = self::get_group_properties($groupInfo['id']);
2862
            if (!empty($categoryInfo)) {
2863
                $categoryTitle = $categoryInfo['title'];
2864
            }
2865
2866
            $users = self::getStudents($groupInfo['iid']);
2867
            $userList = [];
2868
            $emailList = [];
2869
            foreach ($users as $user) {
2870
                $user = api_get_user_info($user['user_id']);
2871
                $userList[] = $user['username'];
2872
                $emailList[] = $user['email'];
2873
            }
2874
2875
            $tutors = self::getTutors($groupInfo);
2876
            $tutorList = [];
2877
            foreach ($tutors as $user) {
2878
                $user = api_get_user_info($user['user_id']);
2879
                $tutorList[] = $user['username'];
2880
                $emailList[] = $user['email'];
2881
            }
2882
2883
            $userListToString = null;
2884
            if (!empty($userList)) {
2885
                $userListToString = implode(',', $userList);
2886
            }
2887
2888
            $tutorListToString = null;
2889
            if (!empty($tutorList)) {
2890
                $tutorListToString = implode(',', $tutorList);
2891
            }
2892
2893
            $data[$count] = [
2894
                $categoryTitle,
2895
                $groupSettings['name'],
2896
                $groupSettings['description'],
2897
                $groupSettings['announcements_state'],
2898
                $groupSettings['calendar_state'],
2899
                $groupSettings['chat_state'],
2900
                $groupSettings['doc_state'],
2901
                $groupSettings['forum_state'],
2902
                $groupSettings['work_state'],
2903
                $groupSettings['wiki_state'],
2904
                $groupSettings['maximum_number_of_students'],
2905
                $groupSettings['self_registration_allowed'],
2906
                $groupSettings['self_unregistration_allowed'],
2907
                null,
2908
            ];
2909
2910
            if ($loadUsers) {
2911
                $data[$count][] = $userListToString;
2912
                $data[$count][] = $tutorListToString;
2913
                if (!empty($emailList)) {
2914
                    $data[$count][] = implode(',', $emailList);
2915
                }
2916
            }
2917
2918
            if (!empty($groupId)) {
2919
                if ($groupId == $groupInfo['id']) {
2920
                    break;
2921
                }
2922
            }
2923
            $count++;
2924
        }
2925
2926
        return $data;
2927
    }
2928
2929
    /**
2930
     * @param string $default
2931
     */
2932
    public static function getSettingBar($default)
2933
    {
2934
        $activeSettings = null;
2935
        $activeTutor = null;
2936
        $activeMember = null;
2937
2938
        switch ($default) {
2939
            case 'settings':
2940
                $activeSettings = 'active';
2941
                break;
2942
            case 'tutor':
2943
                $activeTutor = 'active';
2944
                break;
2945
            case 'member':
2946
                $activeMember = 'active';
2947
                break;
2948
        }
2949
2950
        $url = api_get_path(WEB_CODE_PATH).'group/%s?'.api_get_cidreq();
2951
2952
        echo '
2953
            <ul class="toolbar-groups nav nav-tabs">
2954
                <li class="'.$activeSettings.'">
2955
                    <a id="group_settings_tab" href="'.sprintf($url, 'settings.php').'">
2956
                    '.Display::return_icon('settings.png').' '.get_lang('Settings').'
2957
                    </a>
2958
                </li>
2959
                <li class="'.$activeMember.'">
2960
                    <a id="group_members_tab" href="'.sprintf($url, 'member_settings.php').'">
2961
                    '.Display::return_icon('user.png').' '.get_lang('GroupMembers').'</a>
2962
                </li>
2963
                <li class="'.$activeTutor.'">
2964
                    <a id="group_tutors_tab" href="'.sprintf($url, 'tutor_settings.php').'">
2965
                    '.Display::return_icon('teacher.png').' '.get_lang('GroupTutors').'
2966
                    </a>
2967
                </li>
2968
            </ul>';
2969
    }
2970
2971
    public static function groupOverview($group, $url)
2972
    {
2973
        $groupId = $group['id'];
2974
        $content = '<li>';
2975
        $content .= Display::tag(
2976
            'h3',
2977
            Display::url(
2978
                Security::remove_XSS($group['name']),
2979
                $url.'&gidReq='.$groupId
2980
            )
2981
        );
2982
        $users = self::getTutors($group);
2983
        if (!empty($users)) {
2984
            $content .= '<ul>';
2985
            $content .= "<li>".Display::tag('h4', get_lang('Tutors'))."</li><ul>";
2986
            foreach ($users as $user) {
2987
                $userInfo = api_get_user_info($user['user_id']);
2988
                $content .= '<li title="'.$userInfo['username'].'">'.
2989
                    $userInfo['complete_name_with_username'].
2990
                    '</li>';
2991
            }
2992
            $content .= '</ul>';
2993
            $content .= '</ul>';
2994
        }
2995
2996
        $users = self::getStudents($group['id']);
2997
        if (!empty($users)) {
2998
            $content .= '<ul>';
2999
            $content .= "<li>".Display::tag('h4', get_lang('Students'))."</li><ul>";
3000
            foreach ($users as $user) {
3001
                $userInfo = api_get_user_info($user['user_id']);
3002
                $content .= '<li title="'.$userInfo['username'].'">'.
3003
                    $userInfo['complete_name_with_username'].
3004
                    '</li>';
3005
            }
3006
            $content .= '</ul>';
3007
            $content .= '</ul>';
3008
        }
3009
        $content .= '</li>';
3010
3011
        return $content;
3012
    }
3013
3014
    /**
3015
     * @param int    $courseId
3016
     * @param string $keyword
3017
     *
3018
     * @return string
3019
     */
3020
    public static function getOverview($courseId, $keyword = '')
3021
    {
3022
        $content = null;
3023
        $categories = self::get_categories();
3024
        $url = api_get_path(WEB_CODE_PATH).'group/group_space.php?'.api_get_cidreq(true, false);
3025
        if (!empty($categories)) {
3026
            foreach ($categories as $category) {
3027
                if ('true' === api_get_setting('allow_group_categories')) {
3028
                    $content .= '<h2>'.$category['title'].'</h2>';
3029
                }
3030
3031
                if (!empty($keyword)) {
3032
                    $groups = self::getGroupListFilterByName(
3033
                        $keyword,
3034
                        $category['id'],
3035
                        $courseId
3036
                    );
3037
                } else {
3038
                    $groups = self::get_group_list($category['id']);
3039
                }
3040
3041
                $content .= '<ul>';
3042
                if (!empty($groups)) {
3043
                    foreach ($groups as $group) {
3044
                        $content .= self::groupOverview($group, $url);
3045
                    }
3046
                }
3047
                $content .= '</ul>';
3048
            }
3049
        }
3050
3051
        // Check groups with no categories.
3052
        $groups = self::get_group_list(null, api_get_course_info(), null, api_get_session_id(), false, true);
3053
        if (!empty($groups)) {
3054
            $content .= '<h2>'.get_lang('NoCategorySelected').'</h2>';
3055
            $content .= '<ul>';
3056
            foreach ($groups as $group) {
3057
                if (!empty($group['category_id'])) {
3058
                    continue;
3059
                }
3060
                $content .= self::groupOverview($group, $url);
3061
            }
3062
            $content .= '</ul>';
3063
        }
3064
3065
        return $content;
3066
    }
3067
3068
    /**
3069
     * Returns the search form.
3070
     *
3071
     * @return string
3072
     */
3073
    public static function getSearchForm()
3074
    {
3075
        $url = api_get_path(WEB_CODE_PATH).'group/group_overview.php?'.api_get_cidreq();
3076
        $form = new FormValidator(
3077
            'search_groups',
3078
            'get',
3079
            $url,
3080
            null,
3081
            ['class' => 'form-search'],
3082
            FormValidator::LAYOUT_INLINE
3083
        );
3084
        $form->addElement('text', 'keyword');
3085
        $form->addButtonSearch();
3086
3087
        return $form->toHtml();
3088
    }
3089
3090
    /**
3091
     * @param int $groupId
3092
     * @param int $status
3093
     */
3094
    public static function setStatus($groupId, $status)
3095
    {
3096
        $groupInfo = self::get_group_properties($groupId);
3097
3098
        $courseId = api_get_course_int_id();
3099
        if (!empty($groupInfo)) {
3100
            $table = Database::get_course_table(TABLE_GROUP);
3101
            $params = [
3102
                'status' => intval($status),
3103
            ];
3104
            Database::update(
3105
                $table,
3106
                $params,
3107
                ['c_id = ? AND id = ?' => [$courseId, $groupId]]
3108
            );
3109
        }
3110
    }
3111
3112
    /**
3113
     * @param int $groupId
3114
     */
3115
    public static function setVisible($groupId)
3116
    {
3117
        self::setStatus($groupId, 1);
3118
    }
3119
3120
    /**
3121
     * @param int $groupId
3122
     */
3123
    public static function setInvisible($groupId)
3124
    {
3125
        self::setStatus($groupId, 0);
3126
    }
3127
3128
    /**
3129
     * @param int   $userId
3130
     * @param int   $courseId
3131
     * @param array $groupInfo
3132
     * @param array $documentInfoToBeCheck
3133
     * @param bool  $blockPage
3134
     *
3135
     * @return bool
3136
     */
3137
    public static function allowUploadEditDocument(
3138
        $userId,
3139
        $courseId,
3140
        $groupInfo,
3141
        $documentInfoToBeCheck = null,
3142
        $blockPage = false
3143
    ) {
3144
        // Admin and teachers can make any change no matter what
3145
        if (api_is_platform_admin() || api_is_allowed_to_edit(false, true)) {
3146
            return true;
3147
        }
3148
3149
        if (empty($groupInfo) || !isset($groupInfo['id'])) {
3150
            if ($blockPage) {
3151
                api_not_allowed(true);
3152
            }
3153
3154
            return false;
3155
        }
3156
3157
        // Tutor can also make any change
3158
        $isTutor = self::is_tutor_of_group($userId, $groupInfo, $courseId);
3159
3160
        if ($isTutor) {
3161
            return true;
3162
        }
3163
3164
        // Just in case also check if document in group is available
3165
        if ($groupInfo['doc_state'] == 0) {
3166
            if ($blockPage) {
3167
                api_not_allowed(true);
3168
            }
3169
3170
            return false;
3171
        }
3172
3173
        // Default behaviour
3174
        $documentAccess = self::DOCUMENT_MODE_SHARE;
3175
3176
        // Check category document access
3177
        /*$allowCategoryGroupDocumentAccess = api_get_configuration_value('group_category_document_access');
3178
        if ($allowCategoryGroupDocumentAccess) {
3179
            $category = GroupManager::get_category_from_group($groupInfo['iid']);
3180
            if (!empty($category) && isset($category['document_access'])) {
3181
                $documentAccess = (int) $category['document_access'];
3182
            }
3183
        }*/
3184
3185
        // Check group document access
3186
        $allow = api_get_configuration_value('group_document_access');
3187
        if ($allow) {
3188
            if (isset($groupInfo['document_access'])) {
3189
                $documentAccess = (int) $groupInfo['document_access'];
3190
            }
3191
        }
3192
3193
        // Check access for students
3194
        $result = false;
3195
        switch ($documentAccess) {
3196
            case self::DOCUMENT_MODE_SHARE:
3197
                // Default chamilo behaviour
3198
                // Student can upload his own content, cannot modify another content.
3199
                $isMember = self::is_subscribed($userId, $groupInfo);
3200
                if ($isMember) {
3201
                    // No document to check, allow access to document feature.
3202
                    if (empty($documentInfoToBeCheck)) {
3203
                        $result = true;
3204
                    } else {
3205
                        // Member can only edit his own document
3206
                        $authorId = isset($documentInfoToBeCheck['insert_user_id']) ? $documentInfoToBeCheck['insert_user_id'] : 0;
3207
                        // If "insert_user_id" is not set, check the author id from c_item_property
3208
                        if (empty($authorId) && isset($documentInfoToBeCheck['id'])) {
3209
                            $documentInfo = api_get_item_property_info(
3210
                                $courseId,
3211
                                'document',
3212
                                $documentInfoToBeCheck['id'],
3213
                                0
3214
                            );
3215
                            // Try to find this document in the session
3216
                            if (!empty($sessionId)) {
3217
                                $documentInfo = api_get_item_property_info(
3218
                                    $courseId,
3219
                                    'document',
3220
                                    $documentInfoToBeCheck['id'],
3221
                                    api_get_session_id()
3222
                                );
3223
                            }
3224
3225
                            if (!empty($documentInfo) && isset($documentInfo['insert_user_id'])) {
3226
                                $authorId = $documentInfo['insert_user_id'];
3227
                            }
3228
                        }
3229
3230
                        if ($authorId == $userId) {
3231
                            $result = true;
3232
                        }
3233
                    }
3234
                }
3235
                break;
3236
            case self::DOCUMENT_MODE_READ_ONLY:
3237
                // Student cannot upload content, cannot modify another content.
3238
                $result = false;
3239
                break;
3240
            case self::DOCUMENT_MODE_COLLABORATION:
3241
                // Student can upload content, can modify another content.
3242
                $isMember = self::is_subscribed($userId, $groupInfo);
3243
                if ($isMember) {
3244
                    $result = true;
3245
                }
3246
                break;
3247
        }
3248
3249
        if ($blockPage && $result == false) {
3250
            api_not_allowed(true);
3251
        }
3252
3253
        return $result;
3254
    }
3255
}
3256