Completed
Push — master ( 441dc8...d4012c )
by Julito
09:56
created

GroupManager::create_category()   A

Complexity

Conditions 5
Paths 9

Size

Total Lines 64
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

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

How to fix   Long Method    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

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

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

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

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

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