Test Setup Failed
Push — master ( c7183e...00c715 )
by Julito
30:43
created

GroupManager::subscribe_tutors()   B

Complexity

Conditions 6
Paths 24

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 13
nc 24
nop 3
dl 0
loc 19
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CourseBundle\Entity\CGroupRelUser;
5
6
/**
7
 * This library contains some functions for group-management.
8
 * @author Bart Mollet
9
 * @package chamilo.library
10
 * @todo Add $course_code parameter to all functions. So this GroupManager can
11
 * be used outside a session.
12
 */
13
class GroupManager
14
{
15
    /* VIRTUAL_COURSE_CATEGORY:
16
    in this category groups are created based on the virtual course of a course*/
17
    const VIRTUAL_COURSE_CATEGORY = 1;
18
19
    /* DEFAULT_GROUP_CATEGORY:
20
    When group categories aren't available (platform-setting),
21
    all groups are created in this 'dummy'-category*/
22
    const DEFAULT_GROUP_CATEGORY = 2;
23
24
    /**
25
     * infinite
26
     */
27
    const INFINITE = 99999;
28
    /**
29
     * No limit on the number of users in a group
30
     */
31
    const MEMBER_PER_GROUP_NO_LIMIT = 0;
32
    /**
33
     * No limit on the number of groups per user
34
     */
35
    const GROUP_PER_MEMBER_NO_LIMIT = 0;
36
    /**
37
     * The tools of a group can have 3 states
38
     * - not available
39
     * - public
40
     * - private
41
     */
42
    const TOOL_NOT_AVAILABLE = 0;
43
    const TOOL_PUBLIC = 1;
44
    const TOOL_PRIVATE = 2;
45
    /**
46
     * Constants for the available group tools
47
     */
48
    const GROUP_TOOL_FORUM = 0;
49
    const GROUP_TOOL_DOCUMENTS = 1;
50
    const GROUP_TOOL_CALENDAR = 2;
51
    const GROUP_TOOL_ANNOUNCEMENT = 3;
52
    const GROUP_TOOL_WORK = 4;
53
    const GROUP_TOOL_WIKI = 5;
54
    const GROUP_TOOL_CHAT = 6;
55
56
    /**
57
     *
58
     */
59
    public function __construct()
60
    {
61
    }
62
63
    /**
64
     * @return array
65
     */
66 View Code Duplication
    public static function get_groups($courseId = null)
67
    {
68
        $table_group = Database::get_course_table(TABLE_GROUP);
69
        $courseId = !empty($courseId) ? (int) $courseId : api_get_course_int_id();
70
71
        $sql = "SELECT * FROM $table_group WHERE c_id = $courseId  ";
72
        $result = Database::query($sql);
73
        return Database::store_result($result, 'ASSOC');
74
    }
75
76
    /**
77
     * Get list of groups for current course.
78
     * @param int $categoryId The id of the category from which the groups are
79
     * requested
80
     * @param array $course_info Default is current course
81
     * @param int $status
82
     * @param int $sessionId
83
     * @return array An array with all information about the groups.
84
     */
85
    public static function get_group_list(
86
        $categoryId = null,
87
        $course_info = [],
88
        $status = null,
89
        $sessionId = 0
90
    ) {
91
        $course_info = empty($course_info) ? api_get_course_info() : $course_info;
92
        if (empty($course_info)) {
93
            return [];
94
        }
95
        $sessionId = empty($sessionId) ? api_get_session_id() : (int) $sessionId;
96
        $course_id = $course_info['real_id'];
97
        $table_group = Database::get_course_table(TABLE_GROUP);
98
99
        $sql = "SELECT 
100
                    g.id,
101
                    g.iid,
102
                    g.name,
103
                    g.description,
104
                    g.category_id,
105
                    g.max_student maximum_number_of_members,
106
                    g.secret_directory,
107
                    g.self_registration_allowed,
108
                    g.self_unregistration_allowed,
109
                    g.session_id,
110
                    g.status
111
                FROM $table_group g
112
                WHERE 1 = 1 ";
113
114
        if (!is_null($categoryId)) {
115
            $sql .= " AND g.category_id = '".intval($categoryId)."' ";
116
            $session_condition = api_get_session_condition($sessionId);
117
            if (!empty($session_condition)) {
118
                $sql .= $session_condition;
119
            }
120
        } else {
121
            $session_condition = api_get_session_condition($sessionId, true);
122
        }
123
124
        if (!is_null($status)) {
125
            $sql .= " AND g.status = '".intval($status)."' ";
126
        }
127
128
        $sql .= " AND g.c_id = $course_id ";
129
130
        if (!empty($session_condition)) {
131
            $sql .= $session_condition;
132
        }
133
        $sql .= "ORDER BY UPPER(g.name)";
134
135
        $groupList = Database::query($sql);
136
137
        $groups = array();
138
        while ($thisGroup = Database::fetch_array($groupList)) {
139
            $thisGroup['number_of_members'] = count(self::get_subscribed_users($thisGroup));
140
            if ($thisGroup['session_id'] != 0) {
141
                $sql = 'SELECT name FROM '.Database::get_main_table(TABLE_MAIN_SESSION).'
142
                        WHERE id='.$thisGroup['session_id'];
143
                $rs_session = Database::query($sql);
144
                if (Database::num_rows($rs_session) > 0) {
145
                    $thisGroup['session_name'] = Database::result($rs_session, 0, 0);
146
                }
147
            }
148
            $groups[] = $thisGroup;
149
        }
150
151
        return $groups;
152
    }
153
154
    /**
155
     * Create a group
156
     * @param string $name The name for this group
157
     * @param int $category_id
158
     * @param int $tutor The user-id of the group's tutor
159
     * @param int $places How many people can subscribe to the new group
160
     *
161
     * @return int
162
     */
163
    public static function create_group($name, $category_id, $tutor, $places)
164
    {
165
        $_course = api_get_course_info();
166
        $session_id = api_get_session_id();
167
        $course_id  = $_course['real_id'];
168
        $currentCourseRepository = $_course['path'];
169
        $category = self::get_category($category_id);
170
        $places = intval($places);
171
172
        if ($category) {
173
            if ($places == 0) {
174
                //if the amount of users per group is not filled in, use the setting from the category
175
                $places = $category['max_student'];
176
            } else {
177
                if ($places > $category['max_student'] && $category['max_student'] != 0) {
178
                    $places = $category['max_student'];
179
                }
180
            }
181
            $docState = $category['doc_state'];
182
            $calendarState = $category['calendar_state'];
183
            $workState = $category['work_state'];
184
            $anonuncementState = $category['announcements_state'];
185
            $forumState = $category['forum_state'];
186
            $wikiState = $category['wiki_state'];
187
            $chatState = $category['chat_state'];
188
            $selfRegAllowed = $category['self_reg_allowed'];
189
            $selfUnregAllwoed = $category['self_unreg_allowed'];
190
191
        } else {
192
            $docState = self::TOOL_PRIVATE;
193
            $calendarState = self::TOOL_PRIVATE;
194
            $workState = self::TOOL_PRIVATE;
195
            $anonuncementState = self::TOOL_PRIVATE;
196
            $forumState = self::TOOL_PRIVATE;
197
            $wikiState = self::TOOL_PRIVATE;
198
            $chatState = self::TOOL_PRIVATE;
199
            $selfRegAllowed = 0;
200
            $selfUnregAllwoed = 0;
201
        }
202
203
        $table_group = Database::get_course_table(TABLE_GROUP);
204
        $sql = "INSERT INTO $table_group SET
205
                c_id = $course_id,
206
                status = 1,
207
                category_id='".Database::escape_string($category_id)."',
208
                max_student = '".$places."',
209
                doc_state = '".$docState."',
210
                calendar_state = '".$calendarState."',
211
                work_state = '".$workState."',
212
                announcements_state = '".$anonuncementState."',
213
                forum_state = '".$forumState."',
214
                wiki_state = '".$wikiState."',
215
                chat_state = '".$chatState."',
216
                self_registration_allowed = '".$selfRegAllowed."',
217
                self_unregistration_allowed = '".$selfUnregAllwoed."',
218
                session_id='".intval($session_id)."'";
219
220
        Database::query($sql);
221
        $lastId = Database::insert_id();
222
223
        if ($lastId) {
224
            $sql = "UPDATE $table_group SET id = iid WHERE iid = $lastId";
225
            Database::query($sql);
226
227
            $desired_dir_name = '/'.api_replace_dangerous_char($name).'_groupdocs';
228
            $my_path = api_get_path(SYS_COURSE_PATH).$currentCourseRepository.'/document';
229
230
            $newFolderData = create_unexisting_directory(
231
                $_course,
232
                api_get_user_id(),
233
                $session_id,
234
                $lastId,
235
                null,
236
                $my_path,
237
                $desired_dir_name,
238
                null,
239
                1
240
            );
241
242
            $unique_name = $newFolderData['path'];
243
244
            /* Stores the directory path into the group table */
245
            $sql = "UPDATE $table_group SET
246
                        name = '".Database::escape_string($name)."',
247
                        secret_directory = '".$unique_name."'
248
                    WHERE c_id = $course_id AND id ='".$lastId."'";
249
250
            Database::query($sql);
251
252
            // create a forum if needed
253
            if ($forumState >= 0) {
254
                require_once api_get_path(SYS_CODE_PATH).'forum/forumconfig.inc.php';
255
                require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
256
257
                $forum_categories = get_forum_categories();
258
                if (empty($forum_categories)) {
259
                    $categoryParam = array(
260
                        'forum_category_title' => get_lang('GroupForums'),
261
                    );
262
                    store_forumcategory($categoryParam);
263
264
                    $forum_categories = get_forum_categories();
265
                }
266
267
                $counter = 0;
268
                foreach ($forum_categories as $key => $value) {
269
                    if ($counter == 0) {
270
                        $forum_category_id = $key;
271
                    }
272
                    $counter++;
273
                }
274
                // A sanity check.
275
                if (empty($forum_category_id)) {
276
                    $forum_category_id = 0;
277
                }
278
279
                $values = array();
280
                $values['forum_title'] = $name;
281
                $values['group_id'] = $lastId;
282
                $values['forum_category'] = $forum_category_id;
283
                $values['allow_anonymous_group']['allow_anonymous'] = 0;
284
                $values['students_can_edit_group']['students_can_edit'] = 0;
285
                $values['approval_direct_group']['approval_direct'] = 0;
286
                $values['allow_attachments_group']['allow_attachments'] = 1;
287
                $values['allow_new_threads_group']['allow_new_threads'] = 1;
288
                $values['default_view_type_group']['default_view_type'] = api_get_setting('default_forum_view');
289
                $values['group_forum'] = $lastId;
290
                if ($forumState == '1') {
291
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'public';
292
                } elseif ($forumState == '2') {
293
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'private';
294
                } elseif ($forumState == '0') {
295
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'unavailable';
296
                }
297
                store_forum($values);
298
            }
299
        }
300
301
        return $lastId;
302
    }
303
304
    /**
305
     * Create subgroups.
306
     * This function creates new groups based on an existing group. It will
307
     * create the specified number of groups and fill those groups with users
308
     * from the base group
309
     * @param int $group_id The group from which subgroups have to be created.
310
     * @param int $number_of_groups The number of groups that have to be created
311
     */
312
    public static function create_subgroups($group_id, $number_of_groups)
313
    {
314
        $course_id = api_get_course_int_id();
315
        $table_group = Database::get_course_table(TABLE_GROUP);
316
        $category_id = self::create_category(
317
            get_lang('Subgroups'),
318
            '',
319
            self::TOOL_PRIVATE,
320
            self::TOOL_PRIVATE,
321
            0,
322
            0,
323
            1,
324
            1
325
        );
326
        $users = self::get_users($group_id);
327
        $group_ids = array();
328
329
        for ($group_nr = 1; $group_nr <= $number_of_groups; $group_nr++) {
330
            $group_ids[] = self::create_group(
331
                get_lang('Subgroup').' '.$group_nr,
332
                $category_id,
333
                0,
334
                0
335
            );
336
        }
337
338
        $members = array();
339
        foreach ($users as $index => $user_id) {
340
            $groupId = $group_ids[$index % $number_of_groups];
341
            $groupInfo = self::get_group_properties($groupId);
342
            self::subscribe_users(
343
                $user_id,
344
                $groupInfo
0 ignored issues
show
Bug introduced by
It seems like $groupInfo defined by self::get_group_properties($groupId) on line 341 can also be of type null; however, GroupManager::subscribe_users() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
345
            );
346
            $members[$group_ids[$groupId]]++;
347
        }
348
349
        foreach ($members as $group_id => $places) {
350
            $sql = "UPDATE $table_group SET max_student = $places
351
                    WHERE c_id = $course_id  AND id = $group_id";
352
            Database::query($sql);
353
        }
354
    }
355
356
    /**
357
     * Create a group for every class subscribed to the current course
358
     * @param int $category_id The category in which the groups should be created
359
     * @return array
360
     */
361
    public static function create_class_groups($category_id)
362
    {
363
        $options['where'] = array(" usergroup.course_id = ? " => api_get_course_int_id());
364
        $obj = new UserGroup();
365
        $classes = $obj->getUserGroupInCourse($options);
366
        $group_ids = array();
367
        foreach ($classes as $class) {
368
            $users_ids = $obj->get_users_by_usergroup($class['id']);
369
            $group_id = self::create_group(
370
                $class['name'],
371
                $category_id,
372
                0,
373
                count($users_ids)
374
            );
375
            $groupInfo = self::get_group_properties($group_id);
376
            self::subscribe_users($users_ids, $groupInfo);
0 ignored issues
show
Bug introduced by
It seems like $groupInfo defined by self::get_group_properties($group_id) on line 375 can also be of type null; however, GroupManager::subscribe_users() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
377
            $group_ids[] = $group_id;
378
        }
379
        return $group_ids;
380
    }
381
382
    /**
383
     * Deletes groups and their data.
384
     * @author Christophe Gesche <[email protected]>
385
     * @author Hugues Peeters <[email protected]>
386
     * @author Bart Mollet
387
     * @param  array  $groupInfo iid
388
     * @param string $course_code Default is current course
389
     * @return integer              - number of groups deleted.
390
     */
391
    public static function delete_groups($groupInfo, $course_code = null)
392
    {
393
        $course_info = api_get_course_info($course_code);
394
        $course_id = $course_info['real_id'];
395
396
        // Database table definitions
397
        $group_table = Database::get_course_table(TABLE_GROUP);
398
        $forum_table = Database::get_course_table(TABLE_FORUM);
399
        $groupInfo = self::get_group_properties($groupInfo['iid'], true);
400
        if ($groupInfo) {
401
            $groupIid = $groupInfo['iid'];
402
            $groupId = $groupInfo['id'];
403
            $directory = $groupInfo['secret_directory'];
404
            // Unsubscribe all users
405
            self::unsubscribe_all_users($groupInfo);
406
            self::unsubscribe_all_tutors($groupInfo);
407
            // move group-documents to garbage
408
            $source_directory = api_get_path(SYS_COURSE_PATH).$course_info['path']."/document".$directory;
409
            // File to renamed
410
            $destination_dir = api_get_path(SYS_COURSE_PATH).$course_info['path']."/document".$directory.'_DELETED_'.$groupInfo['id'];
411
412
            if (!empty($directory)) {
413
                //Deleting from document tool
414
                DocumentManager::delete_document(
415
                    $course_info,
416
                    $directory,
417
                    $source_directory
418
                );
419
420 View Code Duplication
                if (file_exists($source_directory)) {
421
                    if (api_get_setting('permanently_remove_deleted_files') === 'true') {
422
                        // Delete
423
                        my_delete($source_directory);
424
                    } else {
425
                        // Rename
426
                        rename($source_directory, $destination_dir);
427
                    }
428
                }
429
            }
430
431
            $sql = "DELETE FROM $forum_table
432
                    WHERE c_id = $course_id AND forum_of_group = $groupId ";
433
            Database::query($sql);
434
435
            // Delete item properties of this group.
436
            // to_group_id is related to c_group_info.iid
437
            $itemPropertyTable = Database::get_course_table(TABLE_ITEM_PROPERTY);
438
            $sql = "DELETE FROM $itemPropertyTable
439
                    WHERE c_id = $course_id AND to_group_id = $groupIid ";
440
            Database::query($sql);
441
442
            // delete the groups
443
            $sql = "DELETE FROM $group_table
444
                    WHERE c_id = $course_id AND iid = $groupIid ";
445
            Database::query($sql);
446
        }
447
448
        return true;
449
    }
450
451
    /**
452
     * Get group properties
453
     * @param int $group_id The group from which properties are requested.
454
     * @param bool $useIid
455
     * @return array All properties. Array-keys are:
456
     * name, tutor_id, description, maximum_number_of_students,
457
     * directory and visibility of tools
458
     */
459
    public static function get_group_properties($group_id, $useIid = false)
460
    {
461
        $course_id = api_get_course_int_id();
462
        if (empty($group_id) || !is_integer(intval($group_id))) {
463
            return null;
464
        }
465
466
        $table_group = Database::get_course_table(TABLE_GROUP);
467
        $sql = "SELECT * FROM $table_group
468
                WHERE c_id = $course_id AND id = ".intval($group_id);
469
470
        if ($useIid) {
471
            $sql = "SELECT * FROM $table_group
472
                    WHERE c_id = $course_id AND iid = ".intval($group_id);
473
        }
474
        $db_result = Database::query($sql);
475
        $db_object = Database::fetch_object($db_result);
476
477
        $result = array();
478
        if ($db_object) {
479
            $result['id'] = $db_object->id;
480
            $result['iid'] = $db_object->iid;
481
            $result['name'] = $db_object->name;
482
            $result['status'] = $db_object->status;
483
            $result['description'] = $db_object->description;
484
            $result['maximum_number_of_students'] = $db_object->max_student;
485
            $result['max_student'] = $db_object->max_student;
486
            $result['doc_state'] = $db_object->doc_state;
487
            $result['work_state'] = $db_object->work_state;
488
            $result['calendar_state'] = $db_object->calendar_state;
489
            $result['announcements_state'] = $db_object->announcements_state;
490
            $result['forum_state'] = $db_object->forum_state;
491
            $result['wiki_state'] = $db_object->wiki_state;
492
            $result['chat_state'] = $db_object->chat_state;
493
            $result['directory'] = $db_object->secret_directory;
494
            $result['self_registration_allowed'] = $db_object->self_registration_allowed;
495
            $result['self_unregistration_allowed'] = $db_object->self_unregistration_allowed;
496
            $result['count_users'] = count(
497
                self::get_subscribed_users($result)
498
            );
499
            $result['count_tutor'] = count(
500
                self::get_subscribed_tutors($result)
501
            );
502
            $result['count_all'] = $result['count_users'] + $result['count_tutor'];
503
        }
504
505
        return $result;
506
    }
507
508
    /**
509
     * @param string $name
510
     * @param string $courseCode
511
     * @return array
512
     */
513 View Code Duplication
    public static function getGroupByName($name, $courseCode = null)
514
    {
515
        $name = trim($name);
516
517
        if (empty($name)) {
518
            return array();
519
        }
520
521
        $course_info = api_get_course_info($courseCode);
522
        $course_id = $course_info['real_id'];
523
        $name = Database::escape_string($name);
524
        $table_group = Database::get_course_table(TABLE_GROUP);
525
        $sql = "SELECT * FROM $table_group
526
                WHERE c_id = $course_id AND name = '$name'
527
                LIMIT 1";
528
        $res = Database::query($sql);
529
        $group = array();
530
        if (Database::num_rows($res)) {
531
            $group = Database::fetch_array($res, 'ASSOC');
532
        }
533
534
        return $group;
535
    }
536
537
    /**
538
     * @param int $courseId
539
     * @param int $categoryId
540
     * @param string $name
541
     * @return array
542
     */
543 View Code Duplication
    public static function getGroupListFilterByName($name, $categoryId, $courseId)
544
    {
545
        $name = trim($name);
546
        if (empty($name)) {
547
            return array();
548
        }
549
        $name = Database::escape_string($name);
550
        $courseId = intval($courseId);
551
        $table_group = Database::get_course_table(TABLE_GROUP);
552
        $sql = "SELECT * FROM $table_group
553
                WHERE c_id = $courseId AND name LIKE '%$name%'";
554
555
        if (!empty($categoryId)) {
556
            $categoryId = intval($categoryId);
557
            $sql .= " AND category_id = $categoryId";
558
        }
559
        $sql .= " ORDER BY name";
560
        $result = Database::query($sql);
561
562
        return Database::store_result($result, 'ASSOC');
563
    }
564
565
    /**
566
     * Set group properties
567
     * Changes the group's properties.
568
     * @param int       Group Id
569
     * @param string    Group name
570
     * @param string    Group description
571
     * @param int       Max number of students in group
572
     * @param int       Document tool's visibility (0=none,1=private,2=public)
573
     * @param int       Work tool's visibility (0=none,1=private,2=public)
574
     * @param int       Calendar tool's visibility (0=none,1=private,2=public)
575
     * @param int       Announcement tool's visibility (0=none,1=private,2=public)
576
     * @param int       Forum tool's visibility (0=none,1=private,2=public)
577
     * @param int       Wiki tool's visibility (0=none,1=private,2=public)
578
     * @param int       Chat tool's visibility (0=none,1=private,2=public)
579
     * @param bool Whether self registration is allowed or not
580
     * @param bool Whether self unregistration is allowed or not
581
     * @param int $categoryId
582
     * @return bool TRUE if properties are successfully changed, false otherwise
583
     */
584
    public static function set_group_properties(
585
        $group_id,
586
        $name,
587
        $description,
588
        $maximum_number_of_students,
589
        $doc_state,
590
        $work_state,
591
        $calendar_state,
592
        $announcements_state,
593
        $forum_state,
594
        $wiki_state,
595
        $chat_state,
596
        $self_registration_allowed,
597
        $self_unregistration_allowed,
598
        $categoryId = null
599
    ) {
600
        $table_group = Database::get_course_table(TABLE_GROUP);
601
        $table_forum = Database::get_course_table(TABLE_FORUM);
602
        $categoryId = intval($categoryId);
603
        $group_id = intval($group_id);
604
        $course_id = api_get_course_int_id();
605
606
        $sql = "UPDATE ".$table_group." SET
607
                    name='".Database::escape_string(trim($name))."',
608
                    doc_state = '".Database::escape_string($doc_state)."',
609
                    work_state = '".Database::escape_string($work_state)."',
610
                    calendar_state = '".Database::escape_string($calendar_state)."',
611
                    announcements_state = '".Database::escape_string($announcements_state)."',
612
                    forum_state = '".Database::escape_string($forum_state)."',
613
                    wiki_state = '".Database::escape_string($wiki_state)."',
614
                    chat_state = '".Database::escape_string($chat_state)."',
615
                    description ='".Database::escape_string(trim($description))."',
616
                    max_student = '".Database::escape_string($maximum_number_of_students)."',
617
                    self_registration_allowed = '".Database::escape_string($self_registration_allowed)."',
618
                    self_unregistration_allowed = '".Database::escape_string($self_unregistration_allowed)."',
619
                    category_id = ".intval($categoryId)."
620
                WHERE c_id = $course_id AND id=".$group_id;
621
        $result = Database::query($sql);
622
623
        /* Here we are updating a field in the table forum_forum that perhaps
624
        duplicates the table group_info.forum_state cvargas*/
625
        $forum_state = (int) $forum_state;
626
        $sql2 = "UPDATE ".$table_forum." SET ";
627
        if ($forum_state === 1) {
628
            $sql2 .= " forum_group_public_private='public' ";
629
        } elseif ($forum_state === 2) {
630
            $sql2 .= " forum_group_public_private='private' ";
631
        } elseif ($forum_state === 0) {
632
            $sql2 .= " forum_group_public_private='unavailable' ";
633
        }
634
        $sql2 .= " WHERE c_id = $course_id AND forum_of_group=".$group_id;
635
        Database::query($sql2);
636
        return $result;
637
    }
638
639
    /**
640
     * Get the total number of groups for the current course.
641
     * @return int The number of groups for the current course.
642
     */
643 View Code Duplication
    public static function get_number_of_groups()
644
    {
645
        $course_id = api_get_course_int_id();
646
        $table_group = Database::get_course_table(TABLE_GROUP);
647
        $sql = "SELECT COUNT(id) AS number_of_groups
648
                FROM $table_group
649
                WHERE c_id = $course_id ";
650
        $res = Database::query($sql);
651
        $obj = Database::fetch_object($res);
652
653
        return $obj->number_of_groups;
654
    }
655
656
    /**
657
     * Get all categories
658
     * @param string $course_code The course (default = current course)
659
     * @return array
660
     */
661 View Code Duplication
    public static function get_categories($course_code = null)
662
    {
663
        $course_info = api_get_course_info($course_code);
664
        $course_id = $course_info['real_id'];
665
        $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
666
        $sql = "SELECT * FROM $table_group_cat
667
                WHERE c_id = $course_id
668
                ORDER BY display_order";
669
        $res = Database::query($sql);
670
        $cats = array();
671
        while ($cat = Database::fetch_array($res)) {
672
            $cats[] = $cat;
673
        }
674
        return $cats;
675
    }
676
677
    /**
678
     * Get a group category
679
     * @param int $id The category id
680
     * @param string $course_code The course (default = current course)
681
     * @return array
682
     */
683
    public static function get_category($id, $course_code = null)
684
    {
685
        if (empty($id)) {
686
            return array();
687
        }
688
689
        $course_info = api_get_course_info($course_code);
690
        $course_id = $course_info['real_id'];
691
        $id = intval($id);
692
        $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
693
        $sql = "SELECT * FROM $table_group_cat
694
                WHERE c_id = $course_id AND id = $id
695
                LIMIT 1";
696
        $res = Database::query($sql);
697
698
        return Database::fetch_array($res);
699
    }
700
701
    /**
702
     * Get a group category
703
     * @param string $title
704
     * @param string $course_code The course (default = current course)
705
     * @return array
706
     */
707 View Code Duplication
    public static function getCategoryByTitle($title, $course_code = null)
708
    {
709
        $title = trim($title);
710
711
        if (empty($title)) {
712
            return array();
713
        }
714
715
        $course_info = api_get_course_info($course_code);
716
        $course_id = $course_info['real_id'];
717
        $title = Database::escape_string($title);
718
        $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
719
        $sql = "SELECT * FROM $table_group_cat
720
                WHERE c_id = $course_id AND title = '$title'
721
                LIMIT 1";
722
        $res = Database::query($sql);
723
        $category = array();
724
        if (Database::num_rows($res)) {
725
            $category = Database::fetch_array($res, 'ASSOC');
726
        }
727
        return $category;
728
    }
729
730
    /**
731
     * Get the unique category of a given group
732
     * @param int $group_id The iid of the group
733
     * @param string $course_code The course in which the group is (default =
734
     * current course)
735
     * @return array The category
736
     */
737 View Code Duplication
    public static function get_category_from_group($group_id, $course_code = '')
738
    {
739
        $table_group = Database::get_course_table(TABLE_GROUP);
740
        $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
741
742
        $group_id = intval($group_id);
743
744
        if (empty($group_id)) {
745
            return array();
746
        }
747
748
        $course_info = api_get_course_info($course_code);
749
750
        if (empty($course_info)) {
751
            return false;
752
        }
753
754
        $course_id = $course_info['real_id'];
755
        $sql = "SELECT gc.* FROM $table_group_cat gc, $table_group g
756
                WHERE
757
                    gc.c_id = $course_id AND
758
                    g.c_id = $course_id AND
759
                    gc.id = g.category_id AND 
760
                    g.iid = $group_id
761
                LIMIT 1";
762
        $res = Database::query($sql);
763
        $cat = array();
764
        if (Database::num_rows($res)) {
765
            $cat = Database::fetch_array($res);
766
        }
767
        return $cat;
768
    }
769
770
    /**
771
     * Delete a group category
772
     * @param int $cat_id The id of the category to delete
773
     * @param string $course_code The code in which the category should be
774
     * deleted (default = current course)
775
     * @return bool
776
     */
777
    public static function delete_category($cat_id, $course_code = '')
778
    {
779
        $course_info = api_get_course_info($course_code);
780
        if (empty($course_info)) {
781
            return false;
782
        }
783
        $course_id = $course_info['real_id'];
784
785
        $table_group = Database::get_course_table(TABLE_GROUP);
786
        $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
787
        $cat_id = intval($cat_id);
788
        $sql = "SELECT iid FROM $table_group
789
                WHERE c_id = $course_id AND category_id='".$cat_id."'";
790
        $res = Database::query($sql);
791 View Code Duplication
        if (Database::num_rows($res) > 0) {
792
            while ($group = Database::fetch_object($res)) {
793
                $groupInfo = self::get_group_properties($group->iid, true);
794
                self::delete_groups($groupInfo, $course_code);
0 ignored issues
show
Bug introduced by
It seems like $groupInfo defined by self::get_group_properties($group->iid, true) on line 793 can also be of type null; however, GroupManager::delete_groups() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
795
            }
796
        }
797
        $sql = "DELETE FROM $table_group_cat
798
                WHERE c_id = $course_id  AND id='".$cat_id."'";
799
        Database::query($sql);
800
801
        return true;
802
    }
803
804
    /**
805
     * Create group category
806
     * @param string $title The title of the new category
807
     * @param string $description The description of the new category
808
     * @param int $doc_state
809
     * @param int $work_state
810
     * @param int $calendar_state
811
     * @param int $announcements_state
812
     * @param int $forum_state
813
     * @param int $wiki_state
814
     * @param int $chat_state
815
     * @param int $self_registration_allowed
816
     * @param int $self_unregistration_allowed
817
     * @param int $maximum_number_of_students
818
     * @param int $groups_per_user
819
     * @return mixed
820
     */
821
    public static function create_category(
822
        $title,
823
        $description,
824
        $doc_state,
825
        $work_state,
826
        $calendar_state,
827
        $announcements_state,
828
        $forum_state,
829
        $wiki_state,
830
        $chat_state = 1,
831
        $self_registration_allowed = 0,
832
        $self_unregistration_allowed = 0,
833
        $maximum_number_of_students = 8,
834
        $groups_per_user = 0
835
    ) {
836
        if (empty($title)) {
837
            return false;
838
        }
839
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
840
        $course_id = api_get_course_int_id();
841
842
        $sql = "SELECT MAX(display_order)+1 as new_order
843
                FROM $table
844
                WHERE c_id = $course_id ";
845
        $res = Database::query($sql);
846
        $obj = Database::fetch_object($res);
847
        if (!isset($obj->new_order)) {
848
            $obj->new_order = 1;
849
        }
850
851
        $params = [
852
            'c_id' => $course_id,
853
            'title' => $title,
854
            'display_order' => $obj->new_order,
855
            'description' => $description,
856
            'doc_state' => $doc_state,
857
            'work_state' => $work_state,
858
            'calendar_state' => $calendar_state,
859
            'announcements_state' => $announcements_state,
860
            'forum_state' => $forum_state,
861
            'wiki_state' => $wiki_state,
862
            'chat_state' => $chat_state,
863
            'groups_per_user' => $groups_per_user,
864
            'self_reg_allowed' => $self_registration_allowed,
865
            'self_unreg_allowed' => $self_unregistration_allowed,
866
            'max_student' => $maximum_number_of_students
867
        ];
868
869
        $categoryId = Database::insert($table, $params);
870
        if ($categoryId) {
871
            $sql = "UPDATE $table SET id = iid
872
                    WHERE iid = $categoryId";
873
            Database::query($sql);
874
875
            return $categoryId;
876
        }
877
878
        return false;
879
    }
880
881
    /**
882
     * Update group category
883
     *
884
     * @param int $id
885
     * @param string $title
886
     * @param string $description
887
     * @param $doc_state
888
     * @param $work_state
889
     * @param $calendar_state
890
     * @param $announcements_state
891
     * @param $forum_state
892
     * @param $wiki_state
893
     * @param $chat_state
894
     * @param $self_registration_allowed
895
     * @param $self_unregistration_allowed
896
     * @param $maximum_number_of_students
897
     * @param $groups_per_user
898
     */
899
    public static function update_category(
900
        $id,
901
        $title,
902
        $description,
903
        $doc_state,
904
        $work_state,
905
        $calendar_state,
906
        $announcements_state,
907
        $forum_state,
908
        $wiki_state,
909
        $chat_state,
910
        $self_registration_allowed,
911
        $self_unregistration_allowed,
912
        $maximum_number_of_students,
913
        $groups_per_user
914
    ) {
915
        $table_group_category = Database::get_course_table(TABLE_GROUP_CATEGORY);
916
        $id = intval($id);
917
918
        $course_id = api_get_course_int_id();
919
920
        $sql = "UPDATE ".$table_group_category." SET
921
                    title='".Database::escape_string($title)."',
922
                    description='".Database::escape_string($description)."',
923
                    doc_state = '".Database::escape_string($doc_state)."',
924
                    work_state = '".Database::escape_string($work_state)."',
925
                    calendar_state = '".Database::escape_string($calendar_state)."',
926
                    announcements_state = '".Database::escape_string($announcements_state)."',
927
                    forum_state = '".Database::escape_string($forum_state)."',
928
                    wiki_state = '".Database::escape_string($wiki_state)."',
929
                    chat_state = '".Database::escape_string($chat_state)."',
930
                    groups_per_user   = '".Database::escape_string($groups_per_user)."',
931
                    self_reg_allowed = '".Database::escape_string($self_registration_allowed)."',
932
                    self_unreg_allowed = '".Database::escape_string($self_unregistration_allowed)."',
933
                    max_student = ".intval($maximum_number_of_students)."
934
                WHERE c_id = $course_id AND id = $id";
935
936
        Database::query($sql);
937
938
        // Updating all groups inside this category
939
        $groups = self::get_group_list($id);
940
941
        if (!empty($groups)) {
942
            foreach ($groups as $group) {
943
                self::set_group_properties(
944
                    $group['id'],
945
                    $group['name'],
946
                    $group['description'],
947
                    $maximum_number_of_students,
948
                    $doc_state,
949
                    $work_state,
950
                    $calendar_state,
951
                    $announcements_state,
952
                    $forum_state,
953
                    $wiki_state,
954
                    $chat_state,
955
                    $self_registration_allowed,
956
                    $self_unregistration_allowed,
957
                    $id
958
                );
959
            }
960
        }
961
    }
962
963
    /**
964
     * Returns the number of groups of the user with the greatest number of
965
     * subscriptions in the given category
966
     */
967
    public static function get_current_max_groups_per_user($category_id = null, $course_code = null)
968
    {
969
        $course_info = api_get_course_info($course_code);
970
        $group_table = Database::get_course_table(TABLE_GROUP);
971
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
972
        $sql = 'SELECT COUNT(gu.group_id) AS current_max
973
                FROM '.$group_user_table.' gu, '.$group_table.' g
974
				WHERE g.c_id = '.$course_info['real_id'].'
975
				AND gu.c_id = g.c_id
976
				AND gu.group_id = g.iid ';
977
        if ($category_id != null) {
978
            $category_id = intval($category_id);
979
            $sql .= ' AND g.category_id = '.$category_id;
980
        }
981
        $sql .= ' GROUP BY gu.user_id ORDER BY current_max DESC LIMIT 1';
982
        $res = Database::query($sql);
983
        $obj = Database::fetch_object($res);
984
985
        return $obj->current_max;
986
    }
987
988
    /**
989
     * Swaps the display-order of two categories
990
     * @param int $id1 The id of the first category
991
     * @param int $id2 The id of the second category
992
     */
993
    public static function swap_category_order($id1, $id2)
994
    {
995
        $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
996
        $id1 = intval($id1);
997
        $id2 = intval($id2);
998
        $course_id = api_get_course_int_id();
999
1000
        $sql = "SELECT id, display_order FROM $table_group_cat
1001
                WHERE id IN ($id1,$id2) AND c_id = $course_id ";
1002
        $res = Database::query($sql);
1003
        $cat1 = Database::fetch_object($res);
1004
        $cat2 = Database::fetch_object($res);
1005
        if ($cat1 && $cat2) {
1006
            $sql = "UPDATE $table_group_cat SET display_order=$cat2->display_order
1007
                WHERE id = $cat1->id AND c_id = $course_id ";
1008
            Database::query($sql);
1009
1010
            $sql = "UPDATE $table_group_cat SET display_order=$cat1->display_order
1011
                    WHERE id = $cat2->id AND c_id = $course_id ";
1012
            Database::query($sql);
1013
        }
1014
    }
1015
1016
    /**
1017
     * Get all users from a given group
1018
     * @param int $group_id The group
1019
     * @param bool $load_extra_info
1020
     * @param int $start
1021
     * @param int $limit
1022
     * @param bool $getCount
1023
     * @param int $courseId
1024
     * @return array list of user id
1025
     */
1026
    public static function get_users(
1027
        $group_id,
1028
        $load_extra_info = false,
1029
        $start = null,
1030
        $limit = null,
1031
        $getCount = false,
1032
        $courseId = null,
1033
        $column = null,
1034
        $direction = null
1035
    ) {
1036
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1037
        $groupTable = Database::get_course_table(TABLE_GROUP);
1038
        $user_table = Database::get_main_table(TABLE_MAIN_USER);
1039
        $group_id = intval($group_id);
1040
1041
        if (empty($courseId)) {
1042
            $courseId = api_get_course_int_id();
1043
        } else {
1044
            $courseId = intval($courseId);
1045
        }
1046
1047
        $select = " SELECT u.id, firstname, lastname ";
1048
        if ($getCount) {
1049
            $select = " SELECT count(u.id) count";
1050
        }
1051
        $sql = "$select
1052
                FROM $group_user_table gu
1053
                INNER JOIN $groupTable g
1054
                ON (gu.group_id = g.id and g.c_id = gu.c_id)
1055
                INNER JOIN $user_table u
1056
                ON (u.id = gu.user_id)
1057
                WHERE 
1058
                    gu.c_id = $courseId AND 
1059
                    g.id = $group_id";
1060
1061
        if (!empty($column) && !empty($direction)) {
1062
            $column = Database::escape_string($column, null, false);
1063
            $direction = ($direction == 'ASC' ? 'ASC' : 'DESC');
1064
            $sql .= " ORDER BY $column $direction";
1065
        }
1066
1067 View Code Duplication
        if (!empty($start) && !empty($limit)) {
1068
            $start = intval($start);
1069
            $limit = intval($limit);
1070
            $sql .= " LIMIT $start, $limit";
1071
        }
1072
        $res = Database::query($sql);
1073
        $users = array();
1074
        while ($obj = Database::fetch_object($res)) {
1075
            if ($getCount) {
1076
                return $obj->count;
1077
                break;
1078
            }
1079
            if ($load_extra_info) {
1080
                $users[] = api_get_user_info($obj->user_id);
1081
            } else {
1082
                $users[] = $obj->user_id;
1083
            }
1084
        }
1085
1086
        return $users;
1087
    }
1088
1089
    /**
1090
     * @param int $group_id id
1091
     * @return array
1092
     */
1093
    public static function getStudentsAndTutors($group_id)
1094
    {
1095
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1096
        $tutor_user_table = Database::get_course_table(TABLE_GROUP_TUTOR);
1097
        $groupTable = Database::get_course_table(TABLE_GROUP);
1098
1099
        $course_id = api_get_course_int_id();
1100
        $group_id = intval($group_id);
1101
        $sql = "SELECT user_id 
1102
                FROM $group_user_table gu
1103
                INNER JOIN $groupTable g
1104
                ON (gu.group_id = g.iid and g.c_id = gu.c_id)
1105
                WHERE gu.c_id = $course_id AND g.id = $group_id";
1106
        $res = Database::query($sql);
1107
        $users = array();
1108
1109
        while ($obj = Database::fetch_object($res)) {
1110
            $users[] = api_get_user_info($obj->user_id);
1111
        }
1112
1113
        $sql = "SELECT user_id 
1114
                FROM $tutor_user_table gu
1115
                INNER JOIN $groupTable g
1116
                ON (gu.group_id = g.id and g.c_id = gu.c_id)
1117
                WHERE gu.c_id = $course_id AND g.id = $group_id";
1118
        $res = Database::query($sql);
1119
        while ($obj = Database::fetch_object($res)) {
1120
            $users[] = api_get_user_info($obj->user_id);
1121
        }
1122
1123
        return $users;
1124
    }
1125
1126
    /**
1127
     * Get only tutors from a group
1128
     * @param array $groupInfo
1129
     * @return array
1130
     */
1131 View Code Duplication
    public static function getTutors($groupInfo)
1132
    {
1133
        $groupTable = Database::get_course_table(TABLE_GROUP);
1134
        $tutor_user_table = Database::get_course_table(TABLE_GROUP_TUTOR);
1135
        $course_id = api_get_course_int_id();
1136
        $group_id = intval($groupInfo['iid']);
1137
1138
        $sql = "SELECT user_id 
1139
                FROM $tutor_user_table gu
1140
                INNER JOIN $groupTable g
1141
                ON (gu.group_id = g.id and g.c_id = gu.c_id)
1142
                WHERE gu.c_id = $course_id AND g.iid = $group_id";
1143
        $res = Database::query($sql);
1144
1145
        $users = array();
1146
        while ($obj = Database::fetch_object($res)) {
1147
            $users[] = api_get_user_info($obj->user_id);
1148
        }
1149
1150
        return $users;
1151
    }
1152
1153
    /**
1154
     * Get only students from a group (not tutors)
1155
     * @param int $group_id iid
1156
     * @return array
1157
     */
1158
    public static function getStudents($group_id)
1159
    {
1160
        $em = Database::getManager();
1161
        $subscriptions = $em
1162
            ->createQuery('
1163
                SELECT gu
1164
                FROM ChamiloCourseBundle:CGroupRelUser gu
1165
                INNER JOIN ChamiloCourseBundle:CGroupInfo g
1166
                WITH gu.groupId = g.iid AND g.cId = gu.cId
1167
                WHERE gu.cId = :course AND g.id = :group
1168
            ')
1169
            ->setParameters([
1170
                'course' => api_get_course_int_id(),
1171
                'group' => intval($group_id)
1172
            ])
1173
            ->getResult();
1174
1175
        $users = [];
1176
1177
        /** @var CGroupRelUser $subscription */
1178
        foreach ($subscriptions as $subscription) {
1179
            $users[] = api_get_user_info($subscription->getUserId());
1180
        }
1181
1182
        return $users;
1183
    }
1184
1185
    /**
1186
     * Returns users belonging to any of the group
1187
     *
1188
     * @param array $groups list of group ids
1189
     * @return array list of user ids
1190
     */
1191
    public static function get_groups_users($groups = [])
1192
    {
1193
        $result = array();
1194
        $tbl_group_user = Database::get_course_table(TABLE_GROUP_USER);
1195
        $course_id = api_get_course_int_id();
1196
1197
        $groups = array_map('intval', $groups);
1198
        // protect individual elements with surrounding quotes
1199
        $groups = implode(', ', $groups);
1200
        $sql = "SELECT DISTINCT user_id
1201
                FROM $tbl_group_user gu
1202
                WHERE c_id = $course_id AND gu.group_id IN ($groups)";
1203
        $rs = Database::query($sql);
1204
        while ($row = Database::fetch_array($rs)) {
1205
            $result[] = $row['user_id'];
1206
        }
1207
1208
        return $result;
1209
    }
1210
1211
    /**
1212
     * Fill the groups with students.
1213
     * The algorithm takes care to first fill the groups with the least # of users.
1214
     * Analysis
1215
     * There was a problem with the "ALL" setting.
1216
     * When max # of groups is set to all, the value is sometimes NULL and sometimes ALL
1217
     * and in both cased the query does not work as expected.
1218
     * Stupid solution (currently implemented: set ALL to a big number (INFINITE) and things are solved :)
1219
     * Better solution: that's up to you.
1220
     *
1221
     * Note
1222
     * Throughout Dokeos there is some confusion about "course id" and "course code"
1223
     * The code is e.g. TEST101, but sometimes a variable that is called courseID also contains a course code string.
1224
     * However, there is also a integer course_id that uniquely identifies the course.
1225
     * ywarnier:> Now the course_id has been removed (25/1/2005)
1226
     * The databases are als very inconsistent in this.
1227
     *
1228
     * @param array $groupInfo
1229
     * @author Chrisptophe Gesche <[email protected]>,
1230
     *         Hugues Peeters     <[email protected]> - original version
1231
     * @author Roan Embrechts - virtual course support, code cleaning
1232
     * @author Bart Mollet - code cleaning, use other GroupManager-functions
1233
     * @return void
1234
     */
1235
    public static function fill_groups($groupInfo)
1236
    {
1237
        $_course = api_get_course_info();
1238
        $groupIid = $groupInfo['iid'];
1239
        $groupId = $groupInfo['id'];
1240
1241
        $category = self::get_category_from_group($groupIid);
1242
        $groups_per_user = isset($category['groups_per_user']) ? $category['groups_per_user'] : self::GROUP_PER_MEMBER_NO_LIMIT;
1243
        $group_table = Database::get_course_table(TABLE_GROUP);
1244
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1245
        $session_id = api_get_session_id();
1246
1247
        $complete_user_list = CourseManager::get_real_and_linked_user_list(
1248
            $_course['code'],
1249
            true,
1250
            $session_id
1251
        );
1252
        $number_groups_per_user = $groups_per_user == self::GROUP_PER_MEMBER_NO_LIMIT ? self::INFINITE : $groups_per_user;
1253
1254
        /*
1255
         * Retrieve all the groups where enrollment is still allowed
1256
         * (reverse) ordered by the number of place available
1257
         */
1258
1259
        $course_id = api_get_course_int_id();
1260
        $sql = "SELECT g.id gid, g.iid, g.max_student-count(ug.user_id) nbPlaces, g.max_student
1261
                FROM $group_table g
1262
                LEFT JOIN  $group_user_table ug ON
1263
                    g.c_id = $course_id AND 
1264
                    ug.c_id = $course_id AND 
1265
                    g.id = ug.group_id
1266
                WHERE
1267
                    g.id = $groupId
1268
                GROUP BY (g.iid)
1269
                HAVING (nbPlaces > 0 OR g.max_student = ".self::MEMBER_PER_GROUP_NO_LIMIT.")
1270
                ORDER BY nbPlaces DESC";
1271
        $sql_result = Database::query($sql);
1272
        $group_available_place = array();
1273
        while ($group = Database::fetch_array($sql_result, 'ASSOC')) {
1274
            $group_available_place[$group['iid']] = $group['nbPlaces'];
1275
        }
1276
1277
        /*
1278
         * Retrieve course users (reverse) ordered by the number
1279
         * of group they are already enrolled
1280
         */
1281
        for ($i = 0; $i < count($complete_user_list); $i++) {
1282
            //find # of groups the user is enrolled in
1283
            $number_of_groups = self::user_in_number_of_groups(
1284
                $complete_user_list[$i]["user_id"],
1285
                isset($category['id']) ? $category['id'] : null
1286
            );
1287
            //add # of groups to user list
1288
            $complete_user_list[$i]['number_groups_left'] = $number_groups_per_user - $number_of_groups;
1289
        }
1290
1291
        //first sort by user_id to filter out duplicates
1292
        $complete_user_list = TableSort::sort_table($complete_user_list, 'user_id');
1293
        $complete_user_list = self::filter_duplicates($complete_user_list, 'user_id');
1294
        $complete_user_list = self::filter_only_students($complete_user_list);
1295
1296
1297
        //now sort by # of group left
1298
        $complete_user_list = TableSort::sort_table($complete_user_list, 'number_groups_left', SORT_DESC);
1299
        $userToken = array();
1300
        foreach ($complete_user_list as $this_user) {
1301
            if ($this_user['number_groups_left'] > 0) {
1302
                $userToken[$this_user['user_id']] = $this_user['number_groups_left'];
1303
            }
1304
        }
1305
1306
        $changed = true;
1307
        while ($changed) {
1308
            $changed = false;
1309
            reset($group_available_place);
1310
            arsort($group_available_place);
1311
            reset($userToken);
1312
            arsort($userToken);
1313
1314
            foreach ($group_available_place as $groupIid => $place) {
1315
                foreach ($userToken as $user_id => $places) {
1316
                    $groupInfo = self::get_group_properties($groupIid, true);
1317
                    if (self::can_user_subscribe($user_id, $groupInfo)) {
0 ignored issues
show
Bug introduced by
It seems like $groupInfo defined by self::get_group_properties($groupIid, true) on line 1316 can also be of type null; however, GroupManager::can_user_subscribe() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1318
                        self::subscribe_users($user_id, $groupInfo);
0 ignored issues
show
Bug introduced by
It seems like $groupInfo defined by self::get_group_properties($groupIid, true) on line 1316 can also be of type null; however, GroupManager::subscribe_users() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1319
                        $group_available_place[$groupIid]--;
1320
                        unset($userToken[$user_id]);
1321
                        $changed = true;
1322
                        break;
1323
                    }
1324
                }
1325
                if ($changed) {
1326
                    break;
1327
                }
1328
            }
1329
        }
1330
    }
1331
1332
    /**
1333
     * Get the number of students in a group.
1334
     * @param int $group_id id
1335
     * @return int Number of students in the given group.
1336
     */
1337 View Code Duplication
    public static function number_of_students($group_id, $course_id = null)
1338
    {
1339
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1340
        $group_id = intval($group_id);
1341
        if (empty($course_id)) {
1342
            $course_id = api_get_course_int_id();
1343
        } else {
1344
            $course_id = intval($course_id);
1345
        }
1346
        $sql = "SELECT COUNT(*) AS number_of_students
1347
                FROM $table_group_user
1348
                WHERE c_id = $course_id AND group_id = $group_id";
1349
        $result = Database::query($sql);
1350
        $db_object = Database::fetch_object($result);
1351
1352
        return $db_object->number_of_students;
1353
    }
1354
1355
    /**
1356
     * Maximum number of students in a group
1357
     * @param int $group_id iid
1358
     * @return int Maximum number of students in the given group.
1359
     */
1360 View Code Duplication
    public static function maximum_number_of_students($group_id)
1361
    {
1362
        $table_group = Database::get_course_table(TABLE_GROUP);
1363
        $group_id = intval($group_id);
1364
        $course_id = api_get_course_int_id();
1365
        $sql = "SELECT max_student FROM $table_group 
1366
                WHERE c_id = $course_id AND iid = $group_id";
1367
        $db_result = Database::query($sql);
1368
        $db_object = Database::fetch_object($db_result);
1369
        if ($db_object->max_student == 0) {
1370
            return self::INFINITE;
1371
        }
1372
        return $db_object->max_student;
1373
    }
1374
1375
    /**
1376
     * Number of groups of a user
1377
     * @param int $user_id
1378
     * @return int The number of groups the user is subscribed in.
1379
     */
1380 View Code Duplication
    public static function user_in_number_of_groups($user_id, $cat_id = null)
1381
    {
1382
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1383
        $table_group = Database::get_course_table(TABLE_GROUP);
1384
        $user_id = intval($user_id);
1385
        $cat_id = intval($cat_id);
1386
1387
        $course_id = api_get_course_int_id();
1388
        $cat_condition = '';
1389
        if (!empty($cat_id)) {
1390
            $cat_condition = " AND g.category_id =  $cat_id ";
1391
        }
1392
1393
        $sql = "SELECT  COUNT(*) AS number_of_groups
1394
                FROM $table_group_user gu, $table_group g
1395
                WHERE
1396
                    gu.c_id = $course_id AND
1397
                    g.c_id = $course_id AND
1398
                    gu.user_id = $user_id AND
1399
                    g.iid = gu.group_id  
1400
                    $cat_condition";
1401
        $result = Database::query($sql);
1402
        $db_object = Database::fetch_object($result);
1403
1404
        return $db_object->number_of_groups;
1405
    }
1406
1407
    /**
1408
     * Is sef-registration allowed?
1409
     * @param int $user_id
1410
     * @param array $groupInfo
1411
     * @return bool TRUE if self-registration is allowed in the given group.
1412
     */
1413 View Code Duplication
    public static function is_self_registration_allowed($user_id, $groupInfo)
1414
    {
1415
        $course_id = api_get_course_int_id();
1416
        if (!$user_id > 0) {
1417
            return false;
1418
        }
1419
        $groupIid = $groupInfo['iid'];
1420
        $table_group = Database::get_course_table(TABLE_GROUP);
1421
        if (isset($groupIid)) {
1422
            $sql = "SELECT status, self_registration_allowed
1423
                    FROM $table_group
1424
                    WHERE c_id = $course_id AND iid = $groupIid";
1425
            $result = Database::query($sql);
1426
            $group = Database::fetch_object($result);
1427
1428
            if ($group->status == 0 || $group->self_registration_allowed != 1) {
1429
                return false;
1430
            }
1431
1432
            return self::can_user_subscribe($user_id, $groupInfo);
1433
        } else {
1434
            return false;
1435
        }
1436
    }
1437
1438
    /**
1439
     * Is sef-unregistration allowed?
1440
     * @param int $user_id
1441
     * @param array $groupInfo
1442
     * @return bool TRUE if self-unregistration is allowed in the given group.
1443
     */
1444 View Code Duplication
    public static function is_self_unregistration_allowed($user_id, $groupInfo)
1445
    {
1446
        if (!$user_id > 0 || empty($groupInfo)) {
1447
            return false;
1448
        }
1449
        $groupIid = $groupInfo['iid'];
1450
        $table_group = Database::get_course_table(TABLE_GROUP);
1451
        $course_id = api_get_course_int_id();
1452
1453
        $sql = "SELECT status, self_unregistration_allowed
1454
                FROM $table_group
1455
                WHERE c_id = $course_id AND iid = $groupIid";
1456
        $result = Database::query($sql);
1457
        $group = Database::fetch_object($result);
1458
1459
        if ($group->status == 0 || $group->self_unregistration_allowed != 1) {
1460
            return false;
1461
        }
1462
1463
        return self::is_subscribed($user_id, $groupInfo);
1464
    }
1465
1466
    /**
1467
     * Is user subscribed in group?
1468
     * @param int $user_id
1469
     * @param array $groupInfo
1470
     * @return bool TRUE if given user is subscribed in given group
1471
     */
1472
    public static function is_subscribed($user_id, $groupInfo)
1473
    {
1474
        $course_id = api_get_course_int_id();
1475
        if (empty($user_id) || empty($groupInfo) || empty($course_id)) {
1476
            return false;
1477
        }
1478
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1479
        $group_id = intval($groupInfo['id']);
1480
        $user_id = intval($user_id);
1481
1482
        $sql = "SELECT 1 FROM $table_group_user
1483
                WHERE
1484
                    c_id = $course_id AND
1485
                    group_id = $group_id AND
1486
                    user_id = $user_id
1487
                ";
1488
        $result = Database::query($sql);
1489
1490
        return Database::num_rows($result) > 0;
1491
    }
1492
1493
    /**
1494
     * Can a user subscribe to a specified group in a course
1495
     * @param int $user_id
1496
     * @param array $groupInfo
1497
     * @param bool $checkMaxNumberStudents
1498
     *
1499
     * @return bool TRUE if given user  can be subscribed in given group
1500
     */
1501
    public static function can_user_subscribe(
1502
        $user_id,
1503
        $groupInfo,
1504
        $checkMaxNumberStudents = true
1505
    ) {
1506
        $group_id = $groupInfo['id'];
1507
        $groupIid = $groupInfo['iid'];
1508
        if ($checkMaxNumberStudents) {
1509
            $category = self::get_category_from_group($groupIid);
1510
            if ($category) {
1511
                if ($category['groups_per_user'] == self::GROUP_PER_MEMBER_NO_LIMIT) {
1512
                    $category['groups_per_user'] = self::INFINITE;
1513
                }
1514
                $result = self:: user_in_number_of_groups($user_id, $category['id']) < $category['groups_per_user'];
1515
                if ($result == false) {
1516
                    return false;
1517
                }
1518
            }
1519
1520
            $result = self::number_of_students($group_id) < self:: maximum_number_of_students($groupIid);
1521
1522
            if ($result == false) {
1523
                return false;
1524
            }
1525
        }
1526
1527
        $result = self::is_tutor_of_group($user_id, $groupInfo);
1528
1529
        if ($result) {
1530
            return false;
1531
        }
1532
1533
        $result = self::is_subscribed($user_id, $groupInfo);
1534
1535
        if ($result) {
1536
            return false;
1537
        }
1538
1539
        return true;
1540
    }
1541
1542
    /**
1543
     * Get all subscribed users (members) from a group
1544
     * @param array $groupInfo
1545
     * @return array An array with information of all users from the given group.
1546
     *               (user_id, firstname, lastname, email)
1547
     */
1548
    public static function get_subscribed_users($groupInfo)
1549
    {
1550
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
1551
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1552
        $order_clause = api_sort_by_first_name() ? ' ORDER BY u.firstname, u.lastname' : ' ORDER BY u.lastname, u.firstname';
1553
        $orderListByOfficialCode = api_get_setting('order_user_list_by_official_code');
1554
        if ($orderListByOfficialCode === 'true') {
1555
            $order_clause = " ORDER BY u.official_code, u.firstname, u.lastname";
1556
        }
1557
1558
        $group_id = intval($groupInfo['id']);
1559
1560
        if (empty($group_id)) {
1561
            return array();
1562
        }
1563
1564
        $course_id = api_get_course_int_id();
1565
1566
        $sql = "SELECT 
1567
                    ug.id, 
1568
                    u.user_id, 
1569
                    u.lastname, 
1570
                    u.firstname, 
1571
                    u.email, 
1572
                    u.username
1573
                FROM $table_user u 
1574
                INNER JOIN $table_group_user ug
1575
                ON (ug.user_id = u.user_id)
1576
                WHERE ug.c_id = $course_id AND
1577
                      ug.group_id = $group_id
1578
                $order_clause";
1579
1580
        $db_result = Database::query($sql);
1581
        $users = array();
1582
        while ($user = Database::fetch_object($db_result)) {
1583
            $users[$user->user_id] = array(
1584
                'user_id'   => $user->user_id,
1585
                'firstname' => $user->firstname,
1586
                'lastname'  => $user->lastname,
1587
                'email'     => $user->email,
1588
                'username'  => $user->username
1589
            );
1590
        }
1591
1592
        return $users;
1593
    }
1594
1595
    /**
1596
     * @author Patrick Cool <[email protected]>, Ghent University
1597
     * Get all subscribed tutors of a group
1598
     * @param array $groupInfo
1599
     * @return array An array with information of all users from the given group.
1600
     *               (user_id, firstname, lastname, email)
1601
     */
1602
    public static function get_subscribed_tutors($groupInfo, $id_only = false)
1603
    {
1604
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
1605
        $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1606
        $order_clause = api_sort_by_first_name() ? ' ORDER BY u.firstname, u.lastname' : ' ORDER BY u.lastname, u.firstname';
1607
1608
        $orderListByOfficialCode = api_get_setting('order_user_list_by_official_code');
1609
        if ($orderListByOfficialCode === 'true') {
1610
            $order_clause = " ORDER BY u.official_code, u.firstname, u.lastname";
1611
        }
1612
1613
        $group_id = intval($groupInfo['id']);
1614
        $course_id = api_get_course_int_id();
1615
1616
        $sql = "SELECT tg.id, u.user_id, u.lastname, u.firstname, u.email
1617
                FROM $table_user u, $table_group_tutor tg
1618
                WHERE
1619
                    tg.c_id = $course_id AND
1620
                    tg.group_id = $group_id AND
1621
                    tg.user_id = u.user_id 
1622
                $order_clause
1623
                ";
1624
        $db_result = Database::query($sql);
1625
        $users = array();
1626
        while ($user = Database::fetch_object($db_result)) {
1627
            if (!$id_only) {
1628
                $member['user_id'] = $user->user_id;
1629
                $member['firstname'] = $user->firstname;
1630
                $member['lastname'] = $user->lastname;
1631
                $member['email'] = $user->email;
1632
                $users[] = $member;
1633
            } else {
1634
                $users[] = $user->user_id;
1635
            }
1636
        }
1637
1638
        return $users;
1639
    }
1640
1641
    /**
1642
     * Subscribe user(s) to a specified group in current course (as a student)
1643
     * @param mixed $user_ids Can be an array with user-id's or a single user-id
1644
     * @param array $groupInfo
1645
     * @param int $course_id
1646
     * @return bool TRUE if successful
1647
     */
1648
    public static function subscribe_users($user_ids, $groupInfo, $course_id = null)
1649
    {
1650
        $user_ids = is_array($user_ids) ? $user_ids : array($user_ids);
1651
        $course_id = isset($course_id) && !empty($course_id) ? intval($course_id) : api_get_course_int_id();
1652
        $group_id = $groupInfo['id'];
1653
1654
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1655
        if (!empty($user_ids)) {
1656
            foreach ($user_ids as $user_id) {
1657
                if (self::can_user_subscribe($user_id, $groupInfo)) {
1658
                    $user_id = intval($user_id);
1659
                    $sql = "INSERT INTO ".$table_group_user." (c_id, user_id, group_id)
1660
                            VALUES ('$course_id', '".$user_id."', '".$group_id."')";
1661
                    Database::query($sql);
1662
                }
1663
            }
1664
        }
1665
1666
        return true;
1667
    }
1668
1669
    /**
1670
     * Subscribe tutor(s) to a specified group in current course
1671
     * @param mixed $user_ids Can be an array with user-id's or a single user-id
1672
     * @param array $groupInfo
1673
     * @param int $course_id
1674
     *
1675
     * @author Patrick Cool <[email protected]>, Ghent University
1676
     * @see subscribe_users. This function is almost an exact copy of that function.
1677
     * @return bool TRUE if successful
1678
     */
1679
    public static function subscribe_tutors($user_ids, $groupInfo, $course_id = 0)
1680
    {
1681
        $user_ids = is_array($user_ids) ? $user_ids : array($user_ids);
1682
        $result = true;
1683
        $course_id = isset($course_id) && !empty($course_id) ? intval($course_id) : api_get_course_int_id();
1684
        $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1685
        $groupId = (int) $groupInfo['id'];
1686
1687
        foreach ($user_ids as $user_id) {
1688
            $user_id = intval($user_id);
1689
            if (self::can_user_subscribe($user_id, $groupInfo, false)) {
1690
                $sql = "INSERT INTO ".$table_group_tutor." (c_id, user_id, group_id)
1691
                        VALUES ('$course_id', '".$user_id."', '".$groupId."')";
1692
                $result = Database::query($sql);
1693
            }
1694
        }
1695
1696
        return $result;
1697
    }
1698
1699
    /**
1700
     * Unsubscribe user(s) from a specified group in current course
1701
     * @param mixed $user_ids Can be an array with user-id's or a single user-id
1702
     * @param array $groupInfo
1703
     * @return bool TRUE if successful
1704
     */
1705
    public static function unsubscribe_users($user_ids, $groupInfo)
1706
    {
1707
        $user_ids = is_array($user_ids) ? $user_ids : array($user_ids);
1708
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1709
        $group_id = intval($groupInfo['id']);
1710
        $course_id = api_get_course_int_id();
1711
        $sql = 'DELETE FROM '.$table_group_user.'
1712
                WHERE
1713
                    c_id = '.$course_id.' AND
1714
                    group_id = '.$group_id.' AND
1715
                    user_id IN ('.implode(',', $user_ids).')
1716
                ';
1717
        Database::query($sql);
1718
    }
1719
1720
    /**
1721
     * Unsubscribe all users from one or more groups
1722
     * @param array $groupInfo
1723
     * @return bool TRUE if successful
1724
     */
1725 View Code Duplication
    public static function unsubscribe_all_users($groupInfo)
1726
    {
1727
        $course_id = api_get_course_int_id();
1728
        $groupId = (int) $groupInfo['id'];
1729
        if (empty($course_id) || empty($groupId)) {
1730
            return false;
1731
        }
1732
1733
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1734
        $sql = "DELETE FROM $table_group_user
1735
                WHERE 
1736
                    group_id = $groupId AND 
1737
                    c_id = $course_id";
1738
        $result = Database::query($sql);
1739
1740
        return $result;
1741
    }
1742
1743
    /**
1744
     * Unsubscribe all tutors from one or more groups
1745
     * @param int $groupId iid
1746
     * @see unsubscribe_all_users. This function is almost an exact copy of that function.
1747
     * @return bool TRUE if successful
1748
     * @author Patrick Cool <[email protected]>, Ghent University
1749
     */
1750 View Code Duplication
    public static function unsubscribe_all_tutors($groupId)
1751
    {
1752
        $courseId = api_get_course_int_id();
1753
        $groupId = (int) $groupId;
1754
1755
        if (empty($courseId) || empty($groupId)) {
1756
            return false;
1757
        }
1758
1759
        if (!empty($groupId) > 0) {
1760
            $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1761
            $sql = "DELETE FROM $table_group_tutor
1762
                    WHERE group_id = $groupId AND c_id = $courseId";
1763
            $result = Database::query($sql);
1764
            return $result;
1765
        }
1766
        return true;
1767
    }
1768
1769
    /**
1770
     * Is the user a tutor of this group?
1771
     * @param int $user_id the id of the user
1772
     * @param array $groupInfo
1773
     * @return boolean true/false
1774
     * @todo use the function user_has_access that includes this function
1775
     * @author Patrick Cool <[email protected]>, Ghent University
1776
     */
1777 View Code Duplication
    public static function is_tutor_of_group($user_id, $groupInfo)
1778
    {
1779
        if (empty($groupInfo)) {
1780
            return false;
1781
        }
1782
1783
        $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1784
        $user_id = intval($user_id);
1785
        $group_id = intval($groupInfo['id']);
1786
        $course_id = api_get_course_int_id();
1787
1788
        $sql = "SELECT * FROM $table_group_tutor
1789
                WHERE 
1790
                    c_id = $course_id AND 
1791
                    user_id = $user_id AND 
1792
                    group_id = $group_id";
1793
        $result = Database::query($sql);
1794
        if (Database::num_rows($result) > 0) {
1795
            return true;
1796
        } else {
1797
            return false;
1798
        }
1799
    }
1800
1801
    /**
1802
     * Is the user part of this group? This can be a tutor or a normal member
1803
     * you should use this function if the access to a tool or functionality is
1804
     * restricted to the people who are actually in the group
1805
     * before you had to check if the user was
1806
     * 1. a member of the group OR
1807
     * 2. a tutor of the group. This function combines both
1808
     * @param int $user_id the id of the user
1809
     * @param array $groupInfo
1810
     * @return boolean true/false
1811
     * @author Patrick Cool <[email protected]>, Ghent University
1812
     */
1813
    public static function is_user_in_group($user_id, $groupInfo)
1814
    {
1815
        $member = self::is_subscribed($user_id, $groupInfo);
1816
        $tutor = self::is_tutor_of_group($user_id, $groupInfo);
1817
        if ($member || $tutor) {
1818
            return true;
1819
        } else {
1820
            return false;
1821
        }
1822
    }
1823
1824
    /**
1825
     * Get all group's from a given course in which a given user is unsubscribed
1826
     * @author  Patrick Cool
1827
     * @param int  $course_id retrieve the groups for
1828
     * @param int $user_id the ID of the user you want to know all its group memberships
1829
     * @return array
1830
     */
1831
    public static function get_group_ids($course_id, $user_id)
1832
    {
1833
        $groups = array();
1834
        $tbl_group = Database::get_course_table(TABLE_GROUP_USER);
1835
        $tbl_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1836
        $user_id = intval($user_id);
1837
        $course_id = intval($course_id);
1838
1839
        $sql = "SELECT group_id FROM $tbl_group
1840
                WHERE c_id = $course_id AND user_id = '$user_id'";
1841
        $result = Database::query($sql);
1842
1843
        if ($result) {
1844
            while ($row = Database::fetch_array($result)) {
1845
                $groups[] = $row['group_id'];
1846
            }
1847
        }
1848
1849
        //Also loading if i'm the tutor
1850
        $sql = "SELECT group_id FROM $tbl_group_tutor
1851
                WHERE c_id = $course_id AND user_id = '$user_id'";
1852
        $result = Database::query($sql);
1853
        if ($result) {
1854
            while ($row = Database::fetch_array($result)) {
1855
                $groups[] = $row['group_id'];
1856
            }
1857
        }
1858
        if (!empty($groups)) {
1859
            array_filter($groups);
1860
        }
1861
1862
        return $groups;
1863
    }
1864
1865
    /**
1866
     * Filter out duplicates in a multidimensional array
1867
     * by comparing field $compare_field.
1868
     *
1869
     * @param array $user_array_in List of users (must be sorted).
1870
     * @param string $compare_field The field to be compared
1871
     * @return array
1872
     */
1873
    public static function filter_duplicates($user_array_in, $compare_field)
1874
    {
1875
        $total_number = count($user_array_in);
1876
        $user_array_out[0] = $user_array_in[0];
1877
        $count_out = 0;
1878
        for ($count_in = 1; $count_in < $total_number; $count_in++) {
1879
            if ($user_array_in[$count_in][$compare_field] != $user_array_out[$count_out][$compare_field]) {
1880
                $count_out++;
1881
                $user_array_out[$count_out] = $user_array_in[$count_in];
1882
            }
1883
        }
1884
        return $user_array_out;
1885
    }
1886
1887
    /**
1888
     * Remove all users that are not students and all users who have tutor status
1889
     * from  the list.
1890
     * @param array $user_array_in
1891
     * @return array
1892
     */
1893
    public static function filter_only_students($user_array_in)
1894
    {
1895
        $user_array_out = array();
1896
        foreach ($user_array_in as $this_user) {
1897
            if (api_get_session_id()) {
1898
                if ($this_user['status_session'] == 0) {
1899
                    $user_array_out[] = $this_user;
1900
                }
1901
            } else {
1902
                if ($this_user['status_rel'] == STUDENT) {
1903
                    $user_array_out[] = $this_user;
1904
                }
1905
            }
1906
        }
1907
        return $user_array_out;
1908
    }
1909
1910
    /**
1911
     * Check if a user has access to a certain group tool
1912
     * @param int $user_id The user id
1913
     * @param int $group_id The group iid
1914
     * @param string $tool The tool to check the access rights. This should be
1915
     * one of constants: GROUP_TOOL_DOCUMENTS
1916
     * @return bool True if the given user has access to the given tool in the
1917
     * given course.
1918
     */
1919
    public static function user_has_access($user_id, $group_id, $tool)
1920
    {
1921
        // Admin have access everywhere
1922
        if (api_is_platform_admin()) {
1923
            return true;
1924
        }
1925
1926
        // Course admin also have access to everything
1927
        if (api_is_allowed_to_edit()) {
1928
            return true;
1929
        }
1930
1931
        switch ($tool) {
1932
            case self::GROUP_TOOL_FORUM:
1933
                $key = 'forum_state';
1934
                break;
1935
            case self::GROUP_TOOL_DOCUMENTS:
1936
                $key = 'doc_state';
1937
                break;
1938
            case self::GROUP_TOOL_CALENDAR:
1939
                $key = 'calendar_state';
1940
                break;
1941
            case self::GROUP_TOOL_ANNOUNCEMENT:
1942
                $key = 'announcements_state';
1943
                break;
1944
            case self::GROUP_TOOL_WORK:
1945
                $key = 'work_state';
1946
                break;
1947
            case self::GROUP_TOOL_WIKI:
1948
                $key = 'wiki_state';
1949
                break;
1950
            case self::GROUP_TOOL_CHAT:
1951
                $key = 'chat_state';
1952
                break;
1953
            default:
1954
                return false;
1955
        }
1956
1957
        // Check group properties
1958
        $groupInfo = self::get_group_properties($group_id, true);
1959
1960
        if (empty($groupInfo)) {
1961
            return false;
1962
        }
1963
1964
        if ($groupInfo['status'] == 0) {
1965
            return false;
1966
        }
1967
1968
        if (!isset($groupInfo[$key])) {
1969
            return false;
1970
        }
1971
1972
        if (api_is_allowed_to_edit(false, true)) {
1973
            return true;
1974
        }
1975
1976
        $status = $groupInfo[$key];
1977
1978
        switch ($status) {
1979
            case self::TOOL_NOT_AVAILABLE:
1980
                return false;
1981
                break;
1982
            case self::TOOL_PUBLIC:
1983
                return true;
1984
                break;
1985
            case self::TOOL_PRIVATE:
1986
                $userIsInGroup = self::is_user_in_group($user_id, $groupInfo);
1987
                if ($userIsInGroup) {
1988
                    return true;
1989
                }
1990
                break;
1991
        }
1992
1993
        return false;
1994
    }
1995
1996
    /**
1997
     * @param int $userId
1998
     * @param array $groupInfo
1999
     * @param int $sessionId
2000
     *
2001
     * @return bool
2002
     */
2003
    public static function userHasAccessToBrowse($userId, $groupInfo, $sessionId = 0)
2004
    {
2005
        if (empty($groupInfo)) {
2006
            return false;
2007
        }
2008
2009
        if (api_is_platform_admin()) {
2010
            return true;
2011
        }
2012
2013
        if (api_is_allowed_to_edit(false, true)) {
2014
            return true;
2015
        }
2016
2017
        $groupId = $groupInfo['iid'];
2018
        $tutors = self::get_subscribed_tutors($groupInfo, true);
2019
2020
        if (in_array($userId, $tutors)) {
2021
            return true;
2022
        }
2023
2024
        if ($groupInfo['status'] == 0) {
2025
            return false;
2026
        }
2027
2028
        if (self::user_has_access($userId, $groupId, self::GROUP_TOOL_FORUM) ||
2029
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_DOCUMENTS) ||
2030
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_CALENDAR) ||
2031
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_ANNOUNCEMENT) ||
2032
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_WORK) ||
2033
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_WIKI) ||
2034
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_CHAT)
2035
        ) {
2036
            return true;
2037
        }
2038
2039
        if (api_is_session_general_coach() && $groupInfo['session_id'] == $sessionId) {
2040
            return true;
2041
        }
2042
2043
        return false;
2044
    }
2045
2046
2047
    /**
2048
     * Get all groups where a specific user is subscribed
2049
     * @param int $user_id
2050
     * @return array
2051
     */
2052 View Code Duplication
    public static function get_user_group_name($user_id)
2053
    {
2054
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
2055
        $table_group = Database::get_course_table(TABLE_GROUP);
2056
        $user_id = intval($user_id);
2057
        $course_id = api_get_course_int_id();
2058
        $sql = "SELECT name
2059
                FROM $table_group g 
2060
                INNER JOIN $table_group_user gu
2061
                ON (gu.group_id = g.iid)
2062
                WHERE
2063
                  gu.c_id= $course_id AND
2064
                  g.c_id= $course_id AND
2065
                  gu.user_id = $user_id";
2066
        $res = Database::query($sql);
2067
        $groups = array();
2068
        while ($group = Database::fetch_array($res)) {
2069
            $groups[] .= $group['name'];
2070
        }
2071
        return $groups;
2072
    }
2073
2074
    /**
2075
     * Get all groups where a specific user is subscribed
2076
     * @param int $user_id
2077
     * @return array
2078
     */
2079
    public static function getAllGroupPerUserSubscription($user_id)
2080
    {
2081
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
2082
        $table_tutor_user = Database::get_course_table(TABLE_GROUP_TUTOR);
2083
        $table_group = Database::get_course_table(TABLE_GROUP);
2084
        $user_id = intval($user_id);
2085
        $course_id = api_get_course_int_id();
2086
        $sql = "SELECT DISTINCT g.*
2087
               FROM $table_group g
2088
               LEFT JOIN $table_group_user gu
2089
               ON (gu.group_id = g.iid AND g.c_id = gu.c_id)
2090
               LEFT JOIN $table_tutor_user tu
2091
               ON (tu.group_id = g.iid AND g.c_id = tu.c_id)
2092
               WHERE
2093
                  g.c_id = $course_id AND
2094
                  (gu.user_id = $user_id OR tu.user_id = $user_id) ";
2095
        $res = Database::query($sql);
2096
        $groups = array();
2097
        while ($group = Database::fetch_array($res, 'ASSOC')) {
2098
            $groups[] = $group;
2099
        }
2100
2101
        return $groups;
2102
    }
2103
2104
    /**
2105
     *
2106
     * See : fill_groups
2107
     *       Fill the groups with students.
2108
     *
2109
     * note : optimize fill_groups_list <--> fill_groups
2110
     * @param array $groupInfo
2111
     * @return array|bool
2112
     */
2113
    public static function fill_groups_list($groupInfo)
2114
    {
2115
        if (empty($groupInfo)) {
2116
            return [];
2117
        }
2118
        $groupIid = (int) $groupInfo['iid'];
2119
        $groupId = (int) $groupInfo['id'];
2120
2121
        $_course = api_get_course_info();
2122
        if (empty($_course) || empty($groupId)) {
2123
            return [];
2124
        }
2125
2126
        $category = self::get_category_from_group($groupIid);
2127
        $number_groups_per_user = self::GROUP_PER_MEMBER_NO_LIMIT;
2128
        $categoryId = 0;
2129
        if ($category) {
2130
            $groups_per_user = $category['groups_per_user'];
2131
            $number_groups_per_user = ($groups_per_user == self::GROUP_PER_MEMBER_NO_LIMIT ? self::INFINITE : $groups_per_user);
2132
            $categoryId = $category['id'];
2133
        }
2134
2135
        $session_id = api_get_session_id();
2136
        $complete_user_list = CourseManager::get_real_and_linked_user_list(
2137
            $_course['code'],
2138
            true,
2139
            $session_id
2140
        );
2141
2142
        /*
2143
         * Retrieve course users (reverse) ordered by the number
2144
         * of group they are already enrolled
2145
         */
2146
        for ($i = 0; $i < count($complete_user_list); $i++) {
2147
            // find # of groups the user is enrolled in
2148
            $number_of_groups = self:: user_in_number_of_groups(
2149
                $complete_user_list[$i]['user_id'],
2150
                $categoryId
2151
            );
2152
            // add # of groups to user list
2153
            $complete_user_list[$i]['number_groups_left'] = $number_groups_per_user - $number_of_groups;
2154
        }
2155
        //first sort by user_id to filter out duplicates
2156
        $complete_user_list = TableSort::sort_table(
2157
            $complete_user_list,
2158
            'user_id'
2159
        );
2160
        $complete_user_list = self::filter_duplicates(
2161
            $complete_user_list,
2162
            'user_id'
2163
        );
2164
        //now sort by # of group left
2165
        $complete_user_list = TableSort::sort_table(
2166
            $complete_user_list,
2167
            'number_groups_left',
2168
            SORT_DESC
2169
        );
2170
2171
        return $complete_user_list;
2172
    }
2173
2174
    /**
2175
     * @param array $group_list
2176
     * @param int $category_id
2177
     *
2178
     * @return string
2179
     */
2180
    public static function process_groups($group_list, $category_id = null)
2181
    {
2182
        global $charset;
2183
        $category_id = intval($category_id);
2184
2185
        $totalRegistered = 0;
2186
        $group_data = array();
2187
        $user_info = api_get_user_info();
2188
        $session_id = api_get_session_id();
2189
        $user_id = $user_info['user_id'];
2190
        $hideGroup = api_get_setting('hide_course_group_if_no_tools_available');
2191
2192
        foreach ($group_list as $this_group) {
2193
            // Validation when belongs to a session
2194
            $session_img = api_get_session_image($this_group['session_id'], $user_info['status']);
2195
2196
            // All the tutors of this group
2197
            $tutorsids_of_group = self::get_subscribed_tutors($this_group, true);
2198
            $isMember = self::is_subscribed($user_id, $this_group);
2199
2200
            // Create a new table-row
2201
            $row = array();
2202
2203
            // Checkbox
2204
            if (api_is_allowed_to_edit(false, true) && count($group_list) > 1) {
2205
                $row[] = $this_group['id'];
2206
            }
2207
2208
            if (self::userHasAccessToBrowse($user_id, $this_group, $session_id)) {
2209
                // Group name
2210
                $groupNameClass = null;
2211
                if ($this_group['status'] == 0) {
2212
                    $groupNameClass = 'muted';
2213
                }
2214
2215
                $group_name = '<a class="'.$groupNameClass.'" href="group_space.php?'.api_get_cidreq(true, false).'&gidReq='.$this_group['id'].'">'.
2216
                    Security::remove_XSS($this_group['name']).'</a> ';
2217
                if (!empty($user_id) && !empty($this_group['id_tutor']) && $user_id == $this_group['id_tutor']) {
2218
                    $group_name .= Display::label(get_lang('OneMyGroups'), 'success');
2219
                } elseif ($isMember) {
2220
                    $group_name .= Display::label(get_lang('MyGroup'), 'success');
2221
                }
2222
2223
                if (api_is_allowed_to_edit() && !empty($this_group['session_name'])) {
2224
                    $group_name .= ' ('.$this_group['session_name'].')';
2225
                }
2226
                $group_name .= $session_img;
2227
                $row[] = $group_name.'<br />'.stripslashes(trim($this_group['description']));
2228
            } else {
2229
                if ($hideGroup === 'true') {
2230
                    continue;
2231
                }
2232
                $row[] = $this_group['name'].'<br />'.stripslashes(trim($this_group['description']));
2233
            }
2234
2235
            // Tutor name
2236
            $tutor_info = null;
2237
2238
            if (count($tutorsids_of_group) > 0) {
2239
                foreach ($tutorsids_of_group as $tutor_id) {
2240
                    $tutor = api_get_user_info($tutor_id);
2241
                    $username = api_htmlentities(sprintf(get_lang('LoginX'), $tutor['username']), ENT_QUOTES);
2242
                    if (api_get_setting('show_email_addresses') === 'true') {
2243
                        $tutor_info .= Display::tag(
2244
                            'span',
2245
                            Display::encrypted_mailto_link($tutor['mail'], api_get_person_name($tutor['firstName'], $tutor['lastName'])),
2246
                            array('title'=>$username)
2247
                        ).', ';
2248
                    } else {
2249
                        if (api_is_allowed_to_edit()) {
2250
                            $tutor_info .= Display::tag(
2251
                                'span',
2252
                                Display::encrypted_mailto_link($tutor['mail'], api_get_person_name($tutor['firstName'], $tutor['lastName'])),
2253
                                array('title'=>$username)
2254
                            ).', ';
2255
                        } else {
2256
                            $tutor_info .= Display::tag(
2257
                                'span',
2258
                                api_get_person_name($tutor['firstName'], $tutor['lastName']),
2259
                                array('title'=>$username)
2260
                            ).', ';
2261
                        }
2262
                    }
2263
                }
2264
            }
2265
2266
            $tutor_info = api_substr($tutor_info, 0, api_strlen($tutor_info) - 2);
2267
            $row[] = $tutor_info;
2268
2269
            // Max number of members in group
2270
            $max_members = $this_group['maximum_number_of_members'] == self::MEMBER_PER_GROUP_NO_LIMIT ? ' ' : ' / '.$this_group['maximum_number_of_members'];
2271
2272
            // Number of members in group
2273
            $row[] = $this_group['number_of_members'].$max_members;
2274
2275
            // Self-registration / unregistration
2276
            if (!api_is_allowed_to_edit(false, true)) {
2277
                if (self::is_self_registration_allowed($user_id, $this_group)) {
2278
                    $row[] = '<a class = "btn btn-default" href="group.php?'.api_get_cidreq().'&category='.$category_id.'&action=self_reg&group_id='.$this_group['id'].'" onclick="javascript:if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES, $charset))."'".')) return false;">'.get_lang('GroupSelfRegInf').'</a>';
2279
                } elseif (self::is_self_unregistration_allowed($user_id, $this_group)) {
2280
                    $row[] = '<a class = "btn btn-default" href="group.php?'.api_get_cidreq().'&category='.$category_id.'&action=self_unreg&group_id='.$this_group['id'].'" onclick="javascript:if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES, $charset))."'".')) return false;">'.get_lang('GroupSelfUnRegInf').'</a>';
2281
                } else {
2282
                    $row[] = '-';
2283
                }
2284
            }
2285
2286
            $url = api_get_path(WEB_CODE_PATH).'group/';
2287
            // Edit-links
2288
            if (api_is_allowed_to_edit(false, true) &&
2289
                !(api_is_session_general_coach() && intval($this_group['session_id']) != $session_id)
2290
            ) {
2291
                $edit_actions = '<a href="'.$url.'settings.php?'.api_get_cidreq(true, false).'&gidReq='.$this_group['id'].'"  title="'.get_lang('Edit').'">'.
2292
                    Display::return_icon('edit.png', get_lang('EditGroup'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2293
2294
                if ($this_group['status'] == 1) {
2295
                    $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').'">'.
2296
                        Display::return_icon('visible.png', get_lang('Hide'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2297 View Code Duplication
                } else {
2298
                    $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').'">'.
2299
                        Display::return_icon('invisible.png', get_lang('Show'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2300
                }
2301
2302
                $edit_actions .= '<a href="'.$url.'member_settings.php?'.api_get_cidreq(true, false).'&gidReq='.$this_group['id'].'"  title="'.get_lang('GroupMembers').'">'.
2303
                    Display::return_icon('user.png', get_lang('GroupMembers'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2304
2305
                $edit_actions .= '<a href="'.$url.'group_overview.php?action=export&type=xls&'.api_get_cidreq(true, false).'&id='.$this_group['id'].'"  title="'.get_lang('ExportUsers').'">'.
2306
                    Display::return_icon('export_excel.png', get_lang('Export'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2307
2308
                $edit_actions .= '<a href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=fill_one&id='.$this_group['id'].'" onclick="javascript: if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES))."'".')) return false;" title="'.get_lang('FillGroup').'">'.
2309
                    Display::return_icon('fill.png', get_lang('FillGroup'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2310
2311
                $edit_actions .= '<a href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=delete_one&id='.$this_group['id'].'" onclick="javascript: if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES))."'".')) return false;" title="'.get_lang('Delete').'">'.
2312
                    Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2313
2314
                $row[] = $edit_actions;
2315
            }
2316
            if (!empty($this_group['nbMember'])) {
2317
                $totalRegistered = $totalRegistered + $this_group['nbMember'];
2318
            }
2319
            $group_data[] = $row;
2320
        } // end loop
2321
2322
        // If no groups then don't show the table (only for students)
2323
        if (!api_is_allowed_to_edit(true, false)) {
2324
            if (empty($group_data)) {
2325
                return '';
2326
            }
2327
        }
2328
2329
        $table = new SortableTableFromArrayConfig(
2330
            $group_data,
2331
            1,
2332
            20,
2333
            'group_category_'.$category_id
2334
        );
2335
        $table->set_additional_parameters(array('category' => $category_id));
2336
        $column = 0;
2337
        if (api_is_allowed_to_edit(false, true) and count($group_list) > 1) {
2338
            $table->set_header($column++, '', false);
2339
        }
2340
        $table->set_header($column++, get_lang('Groups'));
2341
        $table->set_header($column++, get_lang('GroupTutor'));
2342
        $table->set_header($column++, get_lang('Registered'), false);
2343
2344
        if (!api_is_allowed_to_edit(false, true)) {
2345
            // If self-registration allowed
2346
            $table->set_header($column++, get_lang('GroupSelfRegistration'), false);
2347
        }
2348
2349
        if (api_is_allowed_to_edit(false, true)) {
2350
            // Only for course administrator
2351
            $table->set_header($column++, get_lang('Modify'), false);
2352
            $form_actions = array();
2353
            $form_actions['fill_selected'] = get_lang('FillGroup');
2354
            $form_actions['empty_selected'] = get_lang('EmptyGroup');
2355
            $form_actions['delete_selected'] = get_lang('Delete');
2356
            if (count($group_list) > 1) {
2357
                $table->set_form_actions($form_actions, 'group');
2358
            }
2359
        }
2360
2361
        return $table->return_table();
2362
    }
2363
2364
    /**
2365
     * @param array $groupData
2366
     * @param bool $deleteNotInArray
2367
     * @return array
2368
     */
2369
    public static function importCategoriesAndGroupsFromArray($groupData, $deleteNotInArray = false)
2370
    {
2371
        $result = array();
2372
        $elementsFound = array(
2373
            'categories' => array(),
2374
            'groups' => array()
2375
        );
2376
2377
        $courseCode = api_get_course_id();
2378
        $sessionId = api_get_session_id();
2379
        $groupCategories = self::get_categories();
2380
2381
        if (empty($groupCategories)) {
2382
            $result['error'][] = get_lang('CreateACategory');
2383
            return $result;
2384
        }
2385
2386
        foreach ($groupData as $data) {
2387
            $isCategory = empty($data['group']) ? true : false;
2388
            if ($isCategory) {
2389
                $categoryInfo = self::getCategoryByTitle($data['category']);
2390
                $categoryId = $categoryInfo['id'];
2391
2392
                if (!empty($categoryInfo)) {
2393
                    // Update
2394
                    self::update_category(
2395
                        $categoryId,
2396
                        $data['category'],
2397
                        $data['description'],
2398
                        $data['doc_state'],
2399
                        $data['work_state'],
2400
                        $data['calendar_state'],
2401
                        $data['announcements_state'],
2402
                        $data['forum_state'],
2403
                        $data['wiki_state'],
2404
                        $data['chat_state'],
2405
                        $data['self_reg_allowed'],
2406
                        $data['self_unreg_allowed'],
2407
                        $data['max_student'],
2408
                        $data['groups_per_user']
2409
                    );
2410
                    $data['category_id'] = $categoryId;
2411
                    $result['updated']['category'][] = $data;
2412 View Code Duplication
                } else {
2413
2414
                    // Add
2415
                    $categoryId = self::create_category(
2416
                        $data['category'],
2417
                        $data['description'],
2418
                        $data['doc_state'],
2419
                        $data['work_state'],
2420
                        $data['calendar_state'],
2421
                        $data['announcements_state'],
2422
                        $data['forum_state'],
2423
                        $data['wiki_state'],
2424
                        $data['chat_state'],
2425
                        $data['self_reg_allowed'],
2426
                        $data['self_unreg_allowed'],
2427
                        $data['max_student'],
2428
                        $data['groups_per_user']
2429
                    );
2430
2431
                    if ($categoryId) {
2432
                        $data['category_id'] = $categoryId;
2433
                        $result['added']['category'][] = $data;
2434
                    }
2435
                }
2436
                $elementsFound['categories'][] = $categoryId;
2437
            } else {
2438
                $groupInfo = self::getGroupByName($data['group']);
2439
                $categoryInfo = self::getCategoryByTitle($data['category']);
2440
                $categoryId = null;
2441
                if (!empty($categoryInfo)) {
2442
                    $categoryId = $categoryInfo['id'];
2443
                } else {
2444
                    if (!empty($groupCategories) && isset($groupCategories[0])) {
2445
                        $defaultGroupCategory = $groupCategories[0];
2446
                        $categoryId = $defaultGroupCategory['id'];
2447
                    }
2448
                }
2449
2450
                if (empty($groupInfo)) {
2451
2452
                    // Add
2453
                    $groupId = self::create_group(
2454
                        $data['group'],
2455
                        $categoryId,
2456
                        null,
2457
                        $data['max_student']
2458
                    );
2459
2460 View Code Duplication
                    if ($groupId) {
2461
                        self::set_group_properties(
2462
                            $groupId,
2463
                            $data['group'],
2464
                            $data['description'],
2465
                            $data['max_student'],
2466
                            $data['doc_state'],
2467
                            $data['work_state'],
2468
                            $data['calendar_state'],
2469
                            $data['announcements_state'],
2470
                            $data['forum_state'],
2471
                            $data['wiki_state'],
2472
                            $data['chat_state'],
2473
                            $data['self_reg_allowed'],
2474
                            $data['self_unreg_allowed'],
2475
                            $categoryId
2476
                        );
2477
                        $data['group_id'] = $groupId;
2478
                        $result['added']['group'][] = $data;
2479
                    }
2480
                    $groupInfo = self::get_group_properties($groupId, true);
2481
                } else {
2482
                    // Update
2483
                    $groupId = $groupInfo['id'];
2484
                    self::set_group_properties(
2485
                        $groupId,
2486
                        $data['group'],
2487
                        $data['description'],
2488
                        $data['max_student'],
2489
                        $data['doc_state'],
2490
                        $data['work_state'],
2491
                        $data['calendar_state'],
2492
                        $data['announcements_state'],
2493
                        $data['forum_state'],
2494
                        $data['wiki_state'],
2495
                        $data['chat_state'],
2496
                        $data['self_reg_allowed'],
2497
                        $data['self_unreg_allowed'],
2498
                        $categoryId
2499
                    );
2500
2501
                    $data['group_id'] = $groupId;
2502
                    $result['updated']['group'][] = $data;
2503
                    $groupInfo = self::get_group_properties($groupId);
2504
                }
2505
2506
2507
2508
                $students = isset($data['students']) ? explode(',', $data['students']) : [];
2509 View Code Duplication
                if (!empty($students)) {
2510
                    $studentUserIdList = array();
2511
                    foreach ($students as $student) {
2512
                        $userInfo = api_get_user_info_from_username($student);
2513
2514
                        if (!$userInfo) {
2515
                            continue;
2516
                        }
2517
2518
                        if (
2519
                            !CourseManager::is_user_subscribed_in_course(
2520
                                $userInfo['user_id'],
2521
                                $courseCode,
2522
                                !empty($sessionId),
2523
                                $sessionId
2524
                            )
2525
                        ) {
2526
                            Display::addFlash(
2527
                                Display::return_message(
2528
                                    sprintf(get_lang('StudentXIsNotSubscribedToCourse'), $userInfo['complete_name']),
2529
                                    'warning'
2530
                                )
2531
                            );
2532
2533
                            continue;
2534
                        }
2535
2536
                        $studentUserIdList[] = $userInfo['user_id'];
2537
                    }
2538
                    self::subscribe_users($studentUserIdList, $groupInfo);
0 ignored issues
show
Bug introduced by
It seems like $groupInfo can also be of type null; however, GroupManager::subscribe_users() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
2539
                }
2540
2541
                $tutors = isset($data['tutors']) ? explode(',', $data['tutors']) : [];
2542 View Code Duplication
                if (!empty($tutors)) {
2543
                    $tutorIdList = array();
2544
                    foreach ($tutors as $tutor) {
2545
                        $userInfo = api_get_user_info_from_username($tutor);
2546
2547
                        if (!$userInfo) {
2548
                            continue;
2549
                        }
2550
2551
                        if (
2552
                            !CourseManager::is_user_subscribed_in_course(
2553
                                $userInfo['user_id'],
2554
                                $courseCode,
2555
                                !empty($sessionId),
2556
                                $sessionId
2557
                            )
2558
                        ) {
2559
                            Display::addFlash(
2560
                                Display::return_message(
2561
                                    sprintf(get_lang('TutorXIsNotSubscribedToCourse'), $userInfo['complete_name']),
2562
                                    'warning'
2563
                                )
2564
                            );
2565
2566
                            continue;
2567
                        }
2568
2569
                        $tutorIdList[] = $userInfo['user_id'];
2570
                    }
2571
                    self::subscribe_tutors($tutorIdList, $groupInfo);
0 ignored issues
show
Bug introduced by
It seems like $groupInfo can also be of type null; however, GroupManager::subscribe_tutors() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
2572
                }
2573
2574
                $elementsFound['groups'][] = $groupId;
2575
            }
2576
        }
2577
2578
        if ($deleteNotInArray) {
2579
            // Check categories
2580
            $categories = self::get_categories();
2581
            foreach ($categories as $category) {
2582
                if (!in_array($category['id'], $elementsFound['categories'])) {
2583
                    self::delete_category($category['id']);
2584
                    $category['category'] = $category['title'];
2585
                    $result['deleted']['category'][] = $category;
2586
                }
2587
            }
2588
2589
            $groups = self::get_groups();
2590
            foreach ($groups as $group) {
2591
                if (!in_array($group['iid'], $elementsFound['groups'])) {
2592
                    self::delete_groups($group);
2593
                    $group['group'] = $group['name'];
2594
                    $result['deleted']['group'][] = $group;
2595
                }
2596
            }
2597
        }
2598
2599
        return $result;
2600
    }
2601
2602
    /**
2603
     * Export all categories/group from a course to an array.
2604
     * This function works only in a context of a course.
2605
     * @param int $groupId
2606
     * @param bool $loadUsers
2607
     * @return array
2608
     */
2609
    public static function exportCategoriesAndGroupsToArray($groupId = null, $loadUsers = false)
2610
    {
2611
        $data = array();
2612
        $data[] = array(
2613
            'category',
2614
            'group',
2615
            'description',
2616
            'announcements_state',
2617
            'calendar_state',
2618
            'chat_state',
2619
            'doc_state',
2620
            'forum_state',
2621
            'work_state',
2622
            'wiki_state',
2623
            'max_student',
2624
            'self_reg_allowed',
2625
            'self_unreg_allowed',
2626
            'groups_per_user'
2627
        );
2628
2629
        $count = 1;
2630
2631
        if ($loadUsers) {
2632
            $data[0][] = 'students';
2633
            $data[0][] = 'tutors';
2634
        }
2635
2636
        if ($loadUsers == false) {
2637
            $categories = self::get_categories();
2638
2639
            foreach ($categories as $categoryInfo) {
2640
                $data[$count] = array(
2641
                    $categoryInfo['title'],
2642
                    null,
2643
                    $categoryInfo['description'],
2644
                    $categoryInfo['announcements_state'],
2645
                    $categoryInfo['calendar_state'],
2646
                    $categoryInfo['chat_state'],
2647
                    $categoryInfo['doc_state'],
2648
                    $categoryInfo['forum_state'],
2649
                    $categoryInfo['work_state'],
2650
                    $categoryInfo['wiki_state'],
2651
                    $categoryInfo['max_student'],
2652
                    $categoryInfo['self_reg_allowed'],
2653
                    $categoryInfo['self_unreg_allowed'],
2654
                    $categoryInfo['groups_per_user']
2655
                );
2656
                $count++;
2657
            }
2658
        }
2659
2660
        $groups = self::get_group_list();
2661
2662
        foreach ($groups as $groupInfo) {
2663
            $categoryTitle = null;
2664
            $categoryInfo = self::get_category($groupInfo['category_id']);
2665
            $groupSettings = self::get_group_properties($groupInfo['id']);
2666
            if (!empty($categoryInfo)) {
2667
                $categoryTitle = $categoryInfo['title'];
2668
            }
2669
2670
            $users = self::getStudents($groupInfo['iid']);
2671
            $userList = array();
2672
            foreach ($users as $user) {
2673
                $user = api_get_user_info($user['user_id']);
2674
                $userList[] = $user['username'];
2675
            }
2676
2677
            $tutors = self::getTutors($groupInfo);
2678
            $tutorList = array();
2679
            foreach ($tutors as $user) {
2680
                $user = api_get_user_info($user['user_id']);
2681
                $tutorList[] = $user['username'];
2682
            }
2683
2684
            $userListToString = null;
2685
            if (!empty($userList)) {
2686
                $userListToString = implode(',', $userList);
2687
            }
2688
2689
            $tutorListToString = null;
2690
            if (!empty($tutorList)) {
2691
                $tutorListToString = implode(',', $tutorList);
2692
            }
2693
2694
            $data[$count] = array(
2695
                $categoryTitle,
2696
                $groupSettings['name'],
2697
                $groupSettings['description'],
2698
                $groupSettings['announcements_state'],
2699
                $groupSettings['calendar_state'],
2700
                $groupSettings['chat_state'],
2701
                $groupSettings['doc_state'],
2702
                $groupSettings['forum_state'],
2703
                $groupSettings['work_state'],
2704
                $groupSettings['wiki_state'],
2705
                $groupSettings['maximum_number_of_students'],
2706
                $groupSettings['self_registration_allowed'],
2707
                $groupSettings['self_unregistration_allowed'],
2708
                null
2709
            );
2710
2711
            if ($loadUsers) {
2712
                $data[$count][] = $userListToString;
2713
                $data[$count][] = $tutorListToString;
2714
            }
2715
2716
            if (!empty($groupId)) {
2717
                if ($groupId == $groupInfo['id']) {
2718
                    break;
2719
                }
2720
            }
2721
            $count++;
2722
        }
2723
2724
        return $data;
2725
    }
2726
2727
    /**
2728
     * @param string $default
2729
     */
2730
    public static function getSettingBar($default)
2731
    {
2732
        $activeSettings = null;
2733
        $activeTutor = null;
2734
        $activeMember = null;
2735
2736
        switch ($default) {
2737
            case 'settings':
2738
                $activeSettings = 'active';
2739
                break;
2740
            case'tutor':
2741
                $activeTutor = 'active';
2742
                break;
2743
            case 'member':
2744
                $activeMember = 'active';
2745
                break;
2746
        }
2747
2748
        $url = api_get_path(WEB_CODE_PATH).'group/%s?'.api_get_cidreq();
2749
2750
        echo '
2751
            <ul class="toolbar-groups nav nav-tabs">
2752
                <li class="'.$activeSettings.'">
2753
                    <a href="'.sprintf($url, 'settings.php').'">
2754
                    '.Display::return_icon('settings.png').' '.get_lang('Settings').'
2755
                    </a>
2756
                </li>
2757
                <li class="'.$activeMember.'">
2758
                    <a href="'.sprintf($url, 'member_settings.php').'">
2759
                    '.Display::return_icon('user.png').' '.get_lang('GroupMembers').'
2760
                    </a>
2761
                </li>
2762
                <li class="'.$activeTutor.'">
2763
                    <a href="'.sprintf($url, 'tutor_settings.php').'">
2764
                    '.Display::return_icon('teacher.png').' '.get_lang('GroupTutors').'
2765
                    </a>
2766
                </li>
2767
            </ul>';
2768
    }
2769
2770
    /**
2771
     * @param int $courseId
2772
     * @param string $keyword
2773
     * @return string
2774
     */
2775
    public static function getOverview($courseId, $keyword = null)
2776
    {
2777
        $content = null;
2778
        $categories = self::get_categories();
2779
        if (!empty($categories)) {
2780
2781
            foreach ($categories as $category) {
2782
                if (api_get_setting('allow_group_categories') == 'true') {
2783
                    $content .= '<h2>'.$category['title'].'</h2>';
2784
                }
2785
                if (!empty($keyword)) {
2786
                    $groups = self::getGroupListFilterByName($keyword, $category['id'], $courseId);
2787
                } else {
2788
                    $groups = self::get_group_list($category['id']);
2789
                }
2790
2791
                if (empty($groups)) {
2792
                    $groups = self::get_group_list();
2793
                }
2794
2795
                $content .= '<ul>';
2796
                if (!empty($groups)) {
2797
                    foreach ($groups as $group) {
2798
                        $content .= '<li>';
2799
                        $content .= Display::tag('h3', Security::remove_XSS($group['name']));
2800
                        $users = self::getTutors($group);
2801 View Code Duplication
                        if (!empty($users)) {
2802
                            $content .= '<ul>';
2803
                            $content .= "<li>".Display::tag('h4', get_lang('Tutors'))."</li><ul>";
2804
                            foreach ($users as $user) {
2805
                                $user_info = api_get_user_info($user['user_id']);
2806
                                $content .= '<li title="'.$user_info['username'].'">'.
2807
                                    $user_info['complete_name_with_username'].
2808
                                '</li>';
2809
                            }
2810
                            $content .= '</ul>';
2811
                            $content .= '</ul>';
2812
                        }
2813
2814
                        $users = self::getStudents($group['iid']);
2815 View Code Duplication
                        if (!empty($users)) {
2816
                            $content .= '<ul>';
2817
                            $content .= "<li>".Display::tag('h4', get_lang('Students'))."</li><ul>";
2818
                            foreach ($users as $user) {
2819
                                $user_info = api_get_user_info($user['user_id']);
2820
                                $content .= '<li title="'.$user_info['username'].'">'.
2821
                                    $user_info['complete_name_with_username'].
2822
                                    '</li>';
2823
                            }
2824
                            $content .= '</ul>';
2825
                            $content .= '</ul>';
2826
                        }
2827
                        $content .= '</li>';
2828
                    }
2829
                }
2830
                $content .= '</ul>';
2831
            }
2832
        }
2833
2834
        return $content;
2835
    }
2836
2837
    /**
2838
     * Returns the search form
2839
     * @return string
2840
     */
2841 View Code Duplication
    public static function getSearchForm()
2842
    {
2843
        $url = api_get_path(WEB_CODE_PATH).'group/group_overview.php?'.api_get_cidreq();
2844
        $form = new FormValidator(
2845
            'search_groups',
2846
            'get',
2847
            $url,
2848
            null,
2849
            array('class' => 'form-search'),
2850
            FormValidator::LAYOUT_INLINE
2851
        );
2852
        $form->addElement('text', 'keyword');
2853
        $form->addButtonSearch();
2854
        return $form->toHtml();
2855
    }
2856
2857
    /**
2858
     * @param int $groupId
2859
     * @param int $status
2860
     */
2861
    public static function setStatus($groupId, $status)
2862
    {
2863
        $groupInfo = self::get_group_properties($groupId);
2864
2865
        $courseId = api_get_course_int_id();
2866
        if (!empty($groupInfo)) {
2867
            $table = Database::get_course_table(TABLE_GROUP);
2868
            $params = array(
2869
                'status' => intval($status)
2870
            );
2871
            Database::update(
2872
                $table,
2873
                $params,
2874
                array('c_id = ? AND id = ?' => array($courseId, $groupId))
2875
            );
2876
        }
2877
    }
2878
2879
    /**
2880
     * @param int $groupId
2881
     */
2882
    public static function setVisible($groupId)
2883
    {
2884
        self::setStatus($groupId, 1);
2885
    }
2886
2887
    /**
2888
     * @param int $groupId
2889
     */
2890
    public static function setInvisible($groupId)
2891
    {
2892
        self::setStatus($groupId, 0);
2893
    }
2894
}
2895