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

GroupManager::create_category()   A

Complexity

Conditions 5
Paths 9

Size

Total Lines 64
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

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

How to fix   Long Method    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\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