Passed
Push — master ( 50baa5...748ce8 )
by Julito
08:05
created

GroupManager::create_group()   C

Complexity

Conditions 12
Paths 70

Size

Total Lines 147
Code Lines 95

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 95
c 1
b 0
f 0
nop 4
dl 0
loc 147
rs 5.6824
nc 70

How to fix   Long Method    Complexity   

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:

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