Completed
Push — master ( 27e209...a08afa )
by Julito
186:04 queued 150:53
created

GroupManager::get_users()   C

Complexity

Conditions 11
Paths 96

Size

Total Lines 61
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 36
nc 96
nop 8
dl 0
loc 61
rs 6.2318
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CourseBundle\Entity\CGroupRelUser;
5
6
/**
7
 * This library contains some functions for group-management.
8
 * @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
     * GroupManager constructor.
58
     */
59
    public function __construct()
60
    {
61
    }
62
63
    /**
64
     * @return array
65
     */
66
    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 group status
82
     * @param int $sessionId
83
     * @param bool $getCount
84
     * @return array An array with all information about the groups.
85
     */
86
    public static function get_group_list(
87
        $categoryId = null,
88
        $course_info = [],
89
        $status = null,
90
        $sessionId = 0,
91
        $getCount = false
92
    ) {
93
        $course_info = empty($course_info) ? api_get_course_info() : $course_info;
94
        if (empty($course_info)) {
95
            return [];
96
        }
97
        $sessionId = empty($sessionId) ? api_get_session_id() : (int) $sessionId;
98
        $course_id = $course_info['real_id'];
99
        $table_group = Database::get_course_table(TABLE_GROUP);
100
101
        $select = " g.id,
102
                    g.iid,
103
                    g.name,
104
                    g.description,
105
                    g.category_id,
106
                    g.max_student maximum_number_of_members,
107
                    g.secret_directory,
108
                    g.self_registration_allowed,
109
                    g.self_unregistration_allowed,
110
                    g.session_id,
111
                    g.status";
112
        if ($getCount) {
113
            $select = " DISTINCT count(g.iid) as count ";
114
        }
115
116
        $sql = "SELECT 
117
                $select    
118
                FROM $table_group g
119
                WHERE 1 = 1 ";
120
121
        if (!is_null($categoryId)) {
122
            $sql .= " AND g.category_id = '".intval($categoryId)."' ";
123
            $session_condition = api_get_session_condition($sessionId);
124
            if (!empty($session_condition)) {
125
                $sql .= $session_condition;
126
            }
127
        } else {
128
            $session_condition = api_get_session_condition($sessionId, true);
129
        }
130
131
        if (!is_null($status)) {
132
            $sql .= " AND g.status = '".intval($status)."' ";
133
        }
134
135
        $sql .= " AND g.c_id = $course_id ";
136
137
        if (!empty($session_condition)) {
138
            $sql .= $session_condition;
139
        }
140
        $sql .= "ORDER BY UPPER(g.name)";
141
142
        $result = Database::query($sql);
143
144
        if ($getCount) {
145
            $row = Database::fetch_array($result);
146
            return $row['count'];
147
        }
148
149
        $groups = [];
150
        while ($thisGroup = Database::fetch_array($result)) {
151
            $thisGroup['number_of_members'] = count(self::get_subscribed_users($thisGroup));
152
            if ($thisGroup['session_id'] != 0) {
153
                $sql = 'SELECT name FROM '.Database::get_main_table(TABLE_MAIN_SESSION).'
154
                        WHERE id='.$thisGroup['session_id'];
155
                $rs_session = Database::query($sql);
156
                if (Database::num_rows($rs_session) > 0) {
157
                    $thisGroup['session_name'] = Database::result($rs_session, 0, 0);
158
                }
159
            }
160
            $groups[] = $thisGroup;
161
        }
162
163
        return $groups;
164
    }
165
166
    /**
167
     * Create a group
168
     * @param string $name The name for this group
169
     * @param int $category_id
170
     * @param int $tutor The user-id of the group's tutor
171
     * @param int $places How many people can subscribe to the new group
172
     *
173
     * @return int
174
     */
175
    public static function create_group($name, $category_id, $tutor, $places)
0 ignored issues
show
Unused Code introduced by
The parameter $tutor is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

175
    public static function create_group($name, $category_id, /** @scrutinizer ignore-unused */ $tutor, $places)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
176
    {
177
        $_course = api_get_course_info();
178
        $session_id = api_get_session_id();
179
        $course_id  = $_course['real_id'];
180
        $currentCourseRepository = $_course['path'];
181
        $category = self::get_category($category_id);
182
        $places = intval($places);
183
184
        if ($category) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $category of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
185
            if ($places == 0) {
186
                //if the amount of users per group is not filled in, use the setting from the category
187
                $places = $category['max_student'];
188
            } else {
189
                if ($places > $category['max_student'] && $category['max_student'] != 0) {
190
                    $places = $category['max_student'];
191
                }
192
            }
193
            $docState = $category['doc_state'];
194
            $calendarState = $category['calendar_state'];
195
            $workState = $category['work_state'];
196
            $anonuncementState = $category['announcements_state'];
197
            $forumState = $category['forum_state'];
198
            $wikiState = $category['wiki_state'];
199
            $chatState = $category['chat_state'];
200
            $selfRegAllowed = $category['self_reg_allowed'];
201
            $selfUnregAllwoed = $category['self_unreg_allowed'];
202
        } else {
203
            $docState = self::TOOL_PRIVATE;
204
            $calendarState = self::TOOL_PRIVATE;
205
            $workState = self::TOOL_PRIVATE;
206
            $anonuncementState = self::TOOL_PRIVATE;
207
            $forumState = self::TOOL_PRIVATE;
208
            $wikiState = self::TOOL_PRIVATE;
209
            $chatState = self::TOOL_PRIVATE;
210
            $selfRegAllowed = 0;
211
            $selfUnregAllwoed = 0;
212
        }
213
214
        $table_group = Database::get_course_table(TABLE_GROUP);
215
        $sql = "INSERT INTO $table_group SET
216
                c_id = $course_id,
217
                status = 1,
218
                category_id='".Database::escape_string($category_id)."',
219
                max_student = '".$places."',
220
                doc_state = '".$docState."',
221
                calendar_state = '".$calendarState."',
222
                work_state = '".$workState."',
223
                announcements_state = '".$anonuncementState."',
224
                forum_state = '".$forumState."',
225
                wiki_state = '".$wikiState."',
226
                chat_state = '".$chatState."',
227
                self_registration_allowed = '".$selfRegAllowed."',
228
                self_unregistration_allowed = '".$selfUnregAllwoed."',
229
                session_id='".intval($session_id)."'";
230
231
        Database::query($sql);
232
        $lastId = Database::insert_id();
233
234
        if ($lastId) {
235
            $sql = "UPDATE $table_group SET id = iid WHERE iid = $lastId";
236
            Database::query($sql);
237
238
            $desired_dir_name = '/'.api_replace_dangerous_char($name).'_groupdocs';
239
            $my_path = api_get_path(SYS_COURSE_PATH).$currentCourseRepository.'/document';
240
241
            $newFolderData = create_unexisting_directory(
242
                $_course,
243
                api_get_user_id(),
244
                $session_id,
245
                $lastId,
246
                null,
247
                $my_path,
248
                $desired_dir_name,
249
                null,
250
                1
251
            );
252
253
            $unique_name = $newFolderData['path'];
254
255
            /* Stores the directory path into the group table */
256
            $sql = "UPDATE $table_group SET
257
                        name = '".Database::escape_string($name)."',
258
                        secret_directory = '".$unique_name."'
259
                    WHERE c_id = $course_id AND id ='".$lastId."'";
260
261
            Database::query($sql);
262
263
            // create a forum if needed
264
            if ($forumState >= 0) {
265
                require_once api_get_path(SYS_CODE_PATH).'forum/forumconfig.inc.php';
266
                require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
267
268
                $forum_categories = get_forum_categories();
269
                if (empty($forum_categories)) {
270
                    $categoryParam = [
271
                        'forum_category_title' => get_lang('GroupForums'),
272
                    ];
273
                    store_forumcategory($categoryParam);
274
275
                    $forum_categories = get_forum_categories();
276
                }
277
278
                $counter = 0;
279
                foreach ($forum_categories as $key => $value) {
280
                    if ($counter == 0) {
281
                        $forum_category_id = $key;
282
                    }
283
                    $counter++;
284
                }
285
                // A sanity check.
286
                if (empty($forum_category_id)) {
287
                    $forum_category_id = 0;
288
                }
289
290
                $values = [];
291
                $values['forum_title'] = $name;
292
                $values['group_id'] = $lastId;
293
                $values['forum_category'] = $forum_category_id;
294
                $values['allow_anonymous_group']['allow_anonymous'] = 0;
295
                $values['students_can_edit_group']['students_can_edit'] = 0;
296
                $values['approval_direct_group']['approval_direct'] = 0;
297
                $values['allow_attachments_group']['allow_attachments'] = 1;
298
                $values['allow_new_threads_group']['allow_new_threads'] = 1;
299
                $values['default_view_type_group']['default_view_type'] = api_get_setting('default_forum_view');
300
                $values['group_forum'] = $lastId;
301
                if ($forumState == '1') {
302
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'public';
303
                } elseif ($forumState == '2') {
304
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'private';
305
                } elseif ($forumState == '0') {
306
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'unavailable';
307
                }
308
                store_forum($values);
309
            }
310
        }
311
312
        return $lastId;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $lastId returns the type string which is incompatible with the documented return type integer.
Loading history...
313
    }
314
315
    /**
316
     * Create subgroups.
317
     * This function creates new groups based on an existing group. It will
318
     * create the specified number of groups and fill those groups with users
319
     * from the base group
320
     * @param int $group_id The group from which subgroups have to be created.
321
     * @param int $number_of_groups The number of groups that have to be created
322
     */
323
    public static function create_subgroups($group_id, $number_of_groups)
324
    {
325
        $course_id = api_get_course_int_id();
326
        $table_group = Database::get_course_table(TABLE_GROUP);
327
        $category_id = self::create_category(
328
            get_lang('Subgroups'),
329
            '',
330
            self::TOOL_PRIVATE,
331
            self::TOOL_PRIVATE,
332
            0,
333
            0,
334
            1,
335
            1
336
        );
337
        $users = self::get_users($group_id);
338
        $group_ids = [];
339
340
        for ($group_nr = 1; $group_nr <= $number_of_groups; $group_nr++) {
341
            $group_ids[] = self::create_group(
342
                get_lang('Subgroup').' '.$group_nr,
343
                $category_id,
0 ignored issues
show
Bug introduced by
It seems like $category_id can also be of type false; however, parameter $category_id of GroupManager::create_group() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

343
                /** @scrutinizer ignore-type */ $category_id,
Loading history...
344
                0,
345
                0
346
            );
347
        }
348
349
        $members = [];
350
        foreach ($users as $index => $user_id) {
351
            $groupId = $group_ids[$index % $number_of_groups];
352
            $groupInfo = self::get_group_properties($groupId);
353
            self::subscribe_users(
354
                $user_id,
355
                $groupInfo
356
            );
357
            $members[$group_ids[$groupId]]++;
358
        }
359
360
        foreach ($members as $group_id => $places) {
361
            $sql = "UPDATE $table_group SET max_student = $places
362
                    WHERE c_id = $course_id  AND id = $group_id";
363
            Database::query($sql);
364
        }
365
    }
366
367
    /**
368
     * Create a group for every class subscribed to the current course
369
     * @param int $category_id The category in which the groups should be created
370
     * @return array
371
     */
372
    public static function create_class_groups($category_id)
373
    {
374
        $options['where'] = [" usergroup.course_id = ? " => api_get_course_int_id()];
0 ignored issues
show
Comprehensibility Best Practice introduced by
$options was never initialized. Although not strictly required by PHP, it is generally a good practice to add $options = array(); before regardless.
Loading history...
375
        $obj = new UserGroup();
376
        $classes = $obj->getUserGroupInCourse($options);
377
        $group_ids = [];
378
        foreach ($classes as $class) {
379
            $users_ids = $obj->get_users_by_usergroup($class['id']);
380
            $group_id = self::create_group(
381
                $class['name'],
382
                $category_id,
383
                0,
384
                count($users_ids)
385
            );
386
            $groupInfo = self::get_group_properties($group_id);
387
            self::subscribe_users($users_ids, $groupInfo);
388
            $group_ids[] = $group_id;
389
        }
390
        return $group_ids;
391
    }
392
393
    /**
394
     * Deletes groups and their data.
395
     * @author Christophe Gesche <[email protected]>
396
     * @author Hugues Peeters <[email protected]>
397
     * @author Bart Mollet
398
     * @param  array  $groupInfo iid
399
     * @param string $course_code Default is current course
400
     * @return integer              - number of groups deleted.
401
     */
402
    public static function delete_groups($groupInfo, $course_code = null)
403
    {
404
        if (empty($groupInfo['iid'])) {
405
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type integer.
Loading history...
406
        }
407
        $course_info = api_get_course_info($course_code);
408
        $course_id = $course_info['real_id'];
409
410
        // Database table definitions
411
        $group_table = Database::get_course_table(TABLE_GROUP);
412
        $forum_table = Database::get_course_table(TABLE_FORUM);
413
        $groupInfo = self::get_group_properties($groupInfo['iid'], true);
414
        if ($groupInfo) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $groupInfo of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
415
            $groupIid = $groupInfo['iid'];
416
            $groupId = $groupInfo['id'];
417
            // Unsubscribe all users
418
            self::unsubscribe_all_users($groupInfo);
419
            self::unsubscribe_all_tutors($groupInfo);
420
421
            if (!empty($groupInfo['secret_directory'])) {
422
                $directory = $groupInfo['secret_directory'];
423
                // move group-documents to garbage
424
                $source_directory = api_get_path(SYS_COURSE_PATH).$course_info['path']."/document".$directory;
425
                // File to renamed
426
                $destination_dir = api_get_path(SYS_COURSE_PATH).$course_info['path']."/document".$directory.'_DELETED_'.$groupInfo['id'];
427
                //Deleting from document tool
428
                DocumentManager::delete_document(
429
                    $course_info,
430
                    $directory,
431
                    $source_directory
432
                );
433
434
                if (file_exists($source_directory)) {
435
                    if (api_get_setting('permanently_remove_deleted_files') === 'true') {
436
                        // Delete
437
                        my_delete($source_directory);
438
                    } else {
439
                        // Rename
440
                        rename($source_directory, $destination_dir);
441
                    }
442
                }
443
            }
444
445
            $sql = "DELETE FROM $forum_table
446
                    WHERE c_id = $course_id AND forum_of_group = $groupId ";
447
            Database::query($sql);
448
449
            // Delete item properties of this group.
450
            // to_group_id is related to c_group_info.iid
451
            $itemPropertyTable = Database::get_course_table(TABLE_ITEM_PROPERTY);
452
            $sql = "DELETE FROM $itemPropertyTable
453
                    WHERE c_id = $course_id AND to_group_id = $groupIid ";
454
            Database::query($sql);
455
456
            // delete the groups
457
            $sql = "DELETE FROM $group_table
458
                    WHERE c_id = $course_id AND iid = $groupIid ";
459
            Database::query($sql);
460
        }
461
462
        return true;
0 ignored issues
show
Bug Best Practice introduced by
The expression return true returns the type true which is incompatible with the documented return type integer.
Loading history...
463
    }
464
465
    /**
466
     * Get group properties
467
     * @param int $group_id The group from which properties are requested.
468
     * @param bool $useIid
469
     * @return array All properties. Array-keys are:
470
     * name, tutor_id, description, maximum_number_of_students,
471
     * directory and visibility of tools
472
     */
473
    public static function get_group_properties($group_id, $useIid = false)
474
    {
475
        $course_id = api_get_course_int_id();
476
        if (empty($group_id) || !is_integer(intval($group_id))) {
477
            return null;
478
        }
479
480
        $table_group = Database::get_course_table(TABLE_GROUP);
481
        $sql = "SELECT * FROM $table_group
482
                WHERE c_id = $course_id AND id = ".intval($group_id);
483
484
        if ($useIid) {
485
            $sql = "SELECT * FROM $table_group
486
                    WHERE c_id = $course_id AND iid = ".intval($group_id);
487
        }
488
        $db_result = Database::query($sql);
489
        $db_object = Database::fetch_object($db_result);
490
491
        $result = [];
492
        if ($db_object) {
493
            $result['id'] = $db_object->id;
494
            $result['iid'] = $db_object->iid;
495
            $result['name'] = $db_object->name;
496
            $result['status'] = $db_object->status;
497
            $result['description'] = $db_object->description;
498
            $result['maximum_number_of_students'] = $db_object->max_student;
499
            $result['max_student'] = $db_object->max_student;
500
            $result['doc_state'] = $db_object->doc_state;
501
            $result['work_state'] = $db_object->work_state;
502
            $result['calendar_state'] = $db_object->calendar_state;
503
            $result['announcements_state'] = $db_object->announcements_state;
504
            $result['forum_state'] = $db_object->forum_state;
505
            $result['wiki_state'] = $db_object->wiki_state;
506
            $result['chat_state'] = $db_object->chat_state;
507
            $result['directory'] = $db_object->secret_directory;
508
            $result['self_registration_allowed'] = $db_object->self_registration_allowed;
509
            $result['self_unregistration_allowed'] = $db_object->self_unregistration_allowed;
510
            $result['count_users'] = count(
511
                self::get_subscribed_users($result)
512
            );
513
            $result['count_tutor'] = count(
514
                self::get_subscribed_tutors($result)
515
            );
516
            $result['count_all'] = $result['count_users'] + $result['count_tutor'];
517
        }
518
519
        return $result;
520
    }
521
522
    /**
523
     * @param string $name
524
     * @param string $courseCode
525
     * @param int $sessionId
526
     * @return array
527
     */
528
    public static function getGroupByName($name, $courseCode = null, $sessionId = 0)
529
    {
530
        $name = trim($name);
531
532
        if (empty($name)) {
533
            return [];
534
        }
535
536
        $course_info = api_get_course_info($courseCode);
537
        $course_id = $course_info['real_id'];
538
        $name = Database::escape_string($name);
539
        $sessionId = empty($sessionId) ? api_get_session_id() : (int) $sessionId;
540
        $sessionCondition = api_get_session_condition($sessionId);
541
542
        $table = Database::get_course_table(TABLE_GROUP);
543
        $sql = "SELECT * FROM $table
544
                WHERE 
545
                  c_id = $course_id AND 
546
                  name = '$name'
547
                  $sessionCondition
548
                LIMIT 1";
549
        $res = Database::query($sql);
550
        $group = [];
551
        if (Database::num_rows($res)) {
552
            $group = Database::fetch_array($res, 'ASSOC');
553
        }
554
555
        return $group;
556
    }
557
558
    /**
559
     * @param int $courseId
560
     * @param int $categoryId
561
     * @param string $name
562
     * @return array
563
     */
564
    public static function getGroupListFilterByName($name, $categoryId, $courseId)
565
    {
566
        $name = trim($name);
567
        if (empty($name)) {
568
            return [];
569
        }
570
        $name = Database::escape_string($name);
571
        $courseId = intval($courseId);
572
        $table_group = Database::get_course_table(TABLE_GROUP);
573
        $sql = "SELECT * FROM $table_group
574
                WHERE c_id = $courseId AND name LIKE '%$name%'";
575
576
        if (!empty($categoryId)) {
577
            $categoryId = intval($categoryId);
578
            $sql .= " AND category_id = $categoryId";
579
        }
580
        $sql .= " ORDER BY name";
581
        $result = Database::query($sql);
582
583
        return Database::store_result($result, 'ASSOC');
584
    }
585
586
    /**
587
     * Set group properties
588
     * Changes the group's properties.
589
     * @param int       Group Id
590
     * @param string    Group name
591
     * @param string    Group description
592
     * @param int       Max number of students in group
593
     * @param int       Document tool's visibility (0=none,1=private,2=public)
594
     * @param int       Work tool's visibility (0=none,1=private,2=public)
595
     * @param int       Calendar tool's visibility (0=none,1=private,2=public)
596
     * @param int       Announcement tool's visibility (0=none,1=private,2=public)
597
     * @param int       Forum tool's visibility (0=none,1=private,2=public)
598
     * @param int       Wiki tool's visibility (0=none,1=private,2=public)
599
     * @param int       Chat tool's visibility (0=none,1=private,2=public)
600
     * @param bool Whether self registration is allowed or not
601
     * @param bool Whether self unregistration is allowed or not
602
     * @param int $categoryId
603
     * @return bool TRUE if properties are successfully changed, false otherwise
604
     */
605
    public static function set_group_properties(
606
        $group_id,
607
        $name,
608
        $description,
609
        $maximum_number_of_students,
610
        $doc_state,
611
        $work_state,
612
        $calendar_state,
613
        $announcements_state,
614
        $forum_state,
615
        $wiki_state,
616
        $chat_state,
617
        $self_registration_allowed,
618
        $self_unregistration_allowed,
619
        $categoryId = null
620
    ) {
621
        $table_group = Database::get_course_table(TABLE_GROUP);
622
        $table_forum = Database::get_course_table(TABLE_FORUM);
623
        $categoryId = intval($categoryId);
624
        $group_id = intval($group_id);
625
        $course_id = api_get_course_int_id();
626
627
        $sql = "UPDATE ".$table_group." SET
628
                    name='".Database::escape_string(trim($name))."',
629
                    doc_state = '".Database::escape_string($doc_state)."',
630
                    work_state = '".Database::escape_string($work_state)."',
631
                    calendar_state = '".Database::escape_string($calendar_state)."',
632
                    announcements_state = '".Database::escape_string($announcements_state)."',
633
                    forum_state = '".Database::escape_string($forum_state)."',
634
                    wiki_state = '".Database::escape_string($wiki_state)."',
635
                    chat_state = '".Database::escape_string($chat_state)."',
636
                    description ='".Database::escape_string(trim($description))."',
637
                    max_student = '".Database::escape_string($maximum_number_of_students)."',
638
                    self_registration_allowed = '".Database::escape_string($self_registration_allowed)."',
639
                    self_unregistration_allowed = '".Database::escape_string($self_unregistration_allowed)."',
640
                    category_id = ".intval($categoryId)."
641
                WHERE c_id = $course_id AND id=".$group_id;
642
        $result = Database::query($sql);
643
644
        /* Here we are updating a field in the table forum_forum that perhaps
645
        duplicates the table group_info.forum_state cvargas*/
646
        $forum_state = (int) $forum_state;
647
        $sql2 = "UPDATE ".$table_forum." SET ";
648
        if ($forum_state === 1) {
649
            $sql2 .= " forum_group_public_private='public' ";
650
        } elseif ($forum_state === 2) {
651
            $sql2 .= " forum_group_public_private='private' ";
652
        } elseif ($forum_state === 0) {
653
            $sql2 .= " forum_group_public_private='unavailable' ";
654
        }
655
        $sql2 .= " WHERE c_id = $course_id AND forum_of_group=".$group_id;
656
        Database::query($sql2);
657
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result returns the type Doctrine\DBAL\Driver\Statement which is incompatible with the documented return type boolean.
Loading history...
658
    }
659
660
    /**
661
     * Get the total number of groups for the current course.
662
     * @return int The number of groups for the current course.
663
     */
664
    public static function get_number_of_groups()
665
    {
666
        $course_id = api_get_course_int_id();
667
        $table = Database::get_course_table(TABLE_GROUP);
668
        $sql = "SELECT COUNT(id) AS number_of_groups
669
                FROM $table
670
                WHERE c_id = $course_id ";
671
        $res = Database::query($sql);
672
        $obj = Database::fetch_object($res);
673
674
        return $obj->number_of_groups;
675
    }
676
677
    /**
678
     * Get all categories
679
     * @param string $course_code The course (default = current course)
680
     * @return array
681
     */
682
    public static function get_categories($course_code = null)
683
    {
684
        $course_info = api_get_course_info($course_code);
685
        $course_id = $course_info['real_id'];
686
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
687
        $sql = "SELECT * FROM $table
688
                WHERE c_id = $course_id
689
                ORDER BY display_order";
690
        $res = Database::query($sql);
691
        $cats = [];
692
        while ($cat = Database::fetch_array($res)) {
693
            $cats[] = $cat;
694
        }
695
        return $cats;
696
    }
697
698
    /**
699
     * Get a group category
700
     * @param int $id The category id
701
     * @param string $course_code The course (default = current course)
702
     * @return array
703
     */
704
    public static function get_category($id, $course_code = null)
705
    {
706
        if (empty($id)) {
707
            return [];
708
        }
709
710
        $course_info = api_get_course_info($course_code);
711
        $course_id = $course_info['real_id'];
712
        $id = intval($id);
713
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
714
        $sql = "SELECT * FROM $table
715
                WHERE c_id = $course_id AND id = $id
716
                LIMIT 1";
717
        $res = Database::query($sql);
718
719
        return Database::fetch_array($res);
720
    }
721
722
    /**
723
     * Get a group category
724
     * @param string $title
725
     * @param string $course_code The course (default = current course)
726
     * @return array
727
     */
728
    public static function getCategoryByTitle($title, $course_code = null)
729
    {
730
        $title = trim($title);
731
732
        if (empty($title)) {
733
            return [];
734
        }
735
736
        $course_info = api_get_course_info($course_code);
737
        $course_id = $course_info['real_id'];
738
        $title = Database::escape_string($title);
739
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
740
        $sql = "SELECT * FROM $table
741
                WHERE c_id = $course_id AND title = '$title'
742
                LIMIT 1";
743
        $res = Database::query($sql);
744
        $category = [];
745
        if (Database::num_rows($res)) {
746
            $category = Database::fetch_array($res, 'ASSOC');
747
        }
748
        return $category;
749
    }
750
751
    /**
752
     * Get the unique category of a given group
753
     * @param int $group_id The iid of the group
754
     * @param string $course_code The course in which the group is (default =
755
     * current course)
756
     * @return array The category
757
     */
758
    public static function get_category_from_group($group_id, $course_code = '')
759
    {
760
        $table_group = Database::get_course_table(TABLE_GROUP);
761
        $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
762
763
        $group_id = intval($group_id);
764
765
        if (empty($group_id)) {
766
            return [];
767
        }
768
769
        $course_info = api_get_course_info($course_code);
770
771
        if (empty($course_info)) {
772
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type array.
Loading history...
773
        }
774
775
        $course_id = $course_info['real_id'];
776
        $sql = "SELECT gc.* FROM $table_group_cat gc, $table_group g
777
                WHERE
778
                    gc.c_id = $course_id AND
779
                    g.c_id = $course_id AND
780
                    gc.id = g.category_id AND 
781
                    g.iid = $group_id
782
                LIMIT 1";
783
        $res = Database::query($sql);
784
        $cat = [];
785
        if (Database::num_rows($res)) {
786
            $cat = Database::fetch_array($res);
787
        }
788
        return $cat;
789
    }
790
791
    /**
792
     * Delete a group category
793
     * @param int $cat_id The id of the category to delete
794
     * @param string $course_code The code in which the category should be
795
     * deleted (default = current course)
796
     * @return bool
797
     */
798
    public static function delete_category($cat_id, $course_code = '')
799
    {
800
        $course_info = api_get_course_info($course_code);
801
        if (empty($course_info)) {
802
            return false;
803
        }
804
        $course_id = $course_info['real_id'];
805
806
        $table_group = Database::get_course_table(TABLE_GROUP);
807
        $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
808
        $cat_id = intval($cat_id);
809
        $sql = "SELECT iid FROM $table_group
810
                WHERE c_id = $course_id AND category_id='".$cat_id."'";
811
        $res = Database::query($sql);
812
        if (Database::num_rows($res) > 0) {
813
            while ($group = Database::fetch_object($res)) {
814
                // Delete all groups in category
815
                /*$groupInfo = self::get_group_properties($group->iid, true);
816
                self::delete_groups($groupInfo, $course_code);
817
                */
818
                // Set the category to NULL to avoid losing groups in sessions.
819
                $sql = "UPDATE $table_group SET category_id = NULL WHERE iid = ".$group->iid;
820
                Database::query($sql);
821
            }
822
        }
823
        $sql = "DELETE FROM $table_group_cat
824
                WHERE c_id = $course_id  AND id='".$cat_id."'";
825
        Database::query($sql);
826
827
        return true;
828
    }
829
830
    /**
831
     * Create group category
832
     * @param string $title The title of the new category
833
     * @param string $description The description of the new category
834
     * @param int $doc_state
835
     * @param int $work_state
836
     * @param int $calendar_state
837
     * @param int $announcements_state
838
     * @param int $forum_state
839
     * @param int $wiki_state
840
     * @param int $chat_state
841
     * @param int $self_registration_allowed
842
     * @param int $self_unregistration_allowed
843
     * @param int $maximum_number_of_students
844
     * @param int $groups_per_user
845
     * @return mixed
846
     */
847
    public static function create_category(
848
        $title,
849
        $description,
850
        $doc_state,
851
        $work_state,
852
        $calendar_state,
853
        $announcements_state,
854
        $forum_state,
855
        $wiki_state,
856
        $chat_state = 1,
857
        $self_registration_allowed = 0,
858
        $self_unregistration_allowed = 0,
859
        $maximum_number_of_students = 8,
860
        $groups_per_user = 0
861
    ) {
862
        if (empty($title)) {
863
            return false;
864
        }
865
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
866
        $course_id = api_get_course_int_id();
867
868
        $sql = "SELECT MAX(display_order)+1 as new_order
869
                FROM $table
870
                WHERE c_id = $course_id ";
871
        $res = Database::query($sql);
872
        $obj = Database::fetch_object($res);
873
        if (!isset($obj->new_order)) {
874
            $obj->new_order = 1;
875
        }
876
877
        $params = [
878
            'c_id' => $course_id,
879
            'title' => $title,
880
            'display_order' => $obj->new_order,
881
            'description' => $description,
882
            'doc_state' => $doc_state,
883
            'work_state' => $work_state,
884
            'calendar_state' => $calendar_state,
885
            'announcements_state' => $announcements_state,
886
            'forum_state' => $forum_state,
887
            'wiki_state' => $wiki_state,
888
            'chat_state' => $chat_state,
889
            'groups_per_user' => $groups_per_user,
890
            'self_reg_allowed' => $self_registration_allowed,
891
            'self_unreg_allowed' => $self_unregistration_allowed,
892
            'max_student' => $maximum_number_of_students
893
        ];
894
895
        $categoryId = Database::insert($table, $params);
896
        if ($categoryId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $categoryId of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
897
            $sql = "UPDATE $table SET id = iid
898
                    WHERE iid = $categoryId";
899
            Database::query($sql);
900
901
            return $categoryId;
902
        }
903
904
        return false;
905
    }
906
907
    /**
908
     * Update group category
909
     *
910
     * @param int $id
911
     * @param string $title
912
     * @param string $description
913
     * @param $doc_state
914
     * @param $work_state
915
     * @param $calendar_state
916
     * @param $announcements_state
917
     * @param $forum_state
918
     * @param $wiki_state
919
     * @param $chat_state
920
     * @param $self_registration_allowed
921
     * @param $self_unregistration_allowed
922
     * @param $maximum_number_of_students
923
     * @param $groups_per_user
924
     */
925
    public static function update_category(
926
        $id,
927
        $title,
928
        $description,
929
        $doc_state,
930
        $work_state,
931
        $calendar_state,
932
        $announcements_state,
933
        $forum_state,
934
        $wiki_state,
935
        $chat_state,
936
        $self_registration_allowed,
937
        $self_unregistration_allowed,
938
        $maximum_number_of_students,
939
        $groups_per_user
940
    ) {
941
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
942
        $id = intval($id);
943
944
        $course_id = api_get_course_int_id();
945
946
        $sql = "UPDATE ".$table." SET
947
                    title='".Database::escape_string($title)."',
948
                    description='".Database::escape_string($description)."',
949
                    doc_state = '".Database::escape_string($doc_state)."',
950
                    work_state = '".Database::escape_string($work_state)."',
951
                    calendar_state = '".Database::escape_string($calendar_state)."',
952
                    announcements_state = '".Database::escape_string($announcements_state)."',
953
                    forum_state = '".Database::escape_string($forum_state)."',
954
                    wiki_state = '".Database::escape_string($wiki_state)."',
955
                    chat_state = '".Database::escape_string($chat_state)."',
956
                    groups_per_user   = '".Database::escape_string($groups_per_user)."',
957
                    self_reg_allowed = '".Database::escape_string($self_registration_allowed)."',
958
                    self_unreg_allowed = '".Database::escape_string($self_unregistration_allowed)."',
959
                    max_student = ".intval($maximum_number_of_students)."
960
                WHERE c_id = $course_id AND id = $id";
961
962
        Database::query($sql);
963
964
        // Updating all groups inside this category
965
        $groups = self::get_group_list($id);
966
967
        if (!empty($groups)) {
968
            foreach ($groups as $group) {
969
                self::set_group_properties(
970
                    $group['id'],
971
                    $group['name'],
972
                    $group['description'],
973
                    $maximum_number_of_students,
974
                    $doc_state,
975
                    $work_state,
976
                    $calendar_state,
977
                    $announcements_state,
978
                    $forum_state,
979
                    $wiki_state,
980
                    $chat_state,
981
                    $self_registration_allowed,
982
                    $self_unregistration_allowed,
983
                    $id
984
                );
985
            }
986
        }
987
    }
988
989
    /**
990
     * Returns the number of groups of the user with the greatest number of
991
     * subscriptions in the given category
992
     */
993
    public static function get_current_max_groups_per_user(
994
        $category_id = null,
995
        $course_code = null
996
    ) {
997
        $course_info = api_get_course_info($course_code);
998
        $group_table = Database::get_course_table(TABLE_GROUP);
999
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1000
        $sql = 'SELECT COUNT(gu.group_id) AS current_max
1001
                FROM '.$group_user_table.' gu, '.$group_table.' g
1002
				WHERE g.c_id = '.$course_info['real_id'].'
1003
				AND gu.c_id = g.c_id
1004
				AND gu.group_id = g.iid ';
1005
        if ($category_id != null) {
1006
            $category_id = intval($category_id);
1007
            $sql .= ' AND g.category_id = '.$category_id;
1008
        }
1009
        $sql .= ' GROUP BY gu.user_id ORDER BY current_max DESC LIMIT 1';
1010
        $res = Database::query($sql);
1011
        $obj = Database::fetch_object($res);
1012
1013
        return $obj->current_max;
1014
    }
1015
1016
    /**
1017
     * Swaps the display-order of two categories
1018
     * @param int $id1 The id of the first category
1019
     * @param int $id2 The id of the second category
1020
     */
1021
    public static function swap_category_order($id1, $id2)
1022
    {
1023
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
1024
        $id1 = intval($id1);
1025
        $id2 = intval($id2);
1026
        $course_id = api_get_course_int_id();
1027
1028
        $sql = "SELECT id, display_order FROM $table
1029
                WHERE id IN ($id1,$id2) AND c_id = $course_id ";
1030
        $res = Database::query($sql);
1031
        $cat1 = Database::fetch_object($res);
1032
        $cat2 = Database::fetch_object($res);
1033
        if ($cat1 && $cat2) {
1034
            $sql = "UPDATE $table SET display_order=$cat2->display_order
1035
                    WHERE id = $cat1->id AND c_id = $course_id ";
1036
            Database::query($sql);
1037
1038
            $sql = "UPDATE $table SET display_order=$cat1->display_order
1039
                    WHERE id = $cat2->id AND c_id = $course_id ";
1040
            Database::query($sql);
1041
        }
1042
    }
1043
1044
    /**
1045
     * Get all users from a given group
1046
     * @param int $group_id The group
1047
     * @param bool $load_extra_info
1048
     * @param int $start
1049
     * @param int $limit
1050
     * @param bool $getCount
1051
     * @param int $courseId
1052
     * @param $column
1053
     * @param $direction
1054
     * @return array list of user id
1055
     */
1056
    public static function get_users(
1057
        $group_id,
1058
        $load_extra_info = false,
1059
        $start = null,
1060
        $limit = null,
1061
        $getCount = false,
1062
        $courseId = null,
1063
        $column = null,
1064
        $direction = null
1065
    ) {
1066
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1067
        $groupTable = Database::get_course_table(TABLE_GROUP);
1068
        $user_table = Database::get_main_table(TABLE_MAIN_USER);
1069
        $group_id = intval($group_id);
1070
1071
        if (empty($courseId)) {
1072
            $courseId = api_get_course_int_id();
1073
        } else {
1074
            $courseId = intval($courseId);
1075
        }
1076
1077
        $select = " SELECT u.id, firstname, lastname ";
1078
        if ($getCount) {
1079
            $select = " SELECT count(u.id) count";
1080
        }
1081
        $sql = "$select
1082
                FROM $group_user_table gu
1083
                INNER JOIN $groupTable g
1084
                ON (gu.group_id = g.id and g.c_id = gu.c_id)
1085
                INNER JOIN $user_table u
1086
                ON (u.id = gu.user_id)
1087
                WHERE 
1088
                    gu.c_id = $courseId AND 
1089
                    g.id = $group_id";
1090
1091
        if (!empty($column) && !empty($direction)) {
1092
            $column = Database::escape_string($column, null, false);
1093
            $direction = ($direction == 'ASC' ? 'ASC' : 'DESC');
1094
            $sql .= " ORDER BY $column $direction";
1095
        }
1096
1097
        if (!empty($start) && !empty($limit)) {
1098
            $start = intval($start);
1099
            $limit = intval($limit);
1100
            $sql .= " LIMIT $start, $limit";
1101
        }
1102
        $res = Database::query($sql);
1103
        $users = [];
1104
        while ($obj = Database::fetch_object($res)) {
1105
            if ($getCount) {
1106
                return $obj->count;
1107
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

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

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

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

Loading history...
1108
            }
1109
            if ($load_extra_info) {
1110
                $users[] = api_get_user_info($obj->id);
1111
            } else {
1112
                $users[] = $obj->id;
1113
            }
1114
        }
1115
1116
        return $users;
1117
    }
1118
1119
    /**
1120
     * @param int $group_id id
1121
     * @return array
1122
     */
1123
    public static function getStudentsAndTutors($group_id)
1124
    {
1125
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1126
        $tutor_user_table = Database::get_course_table(TABLE_GROUP_TUTOR);
1127
        $groupTable = Database::get_course_table(TABLE_GROUP);
1128
1129
        $course_id = api_get_course_int_id();
1130
        $group_id = intval($group_id);
1131
        $sql = "SELECT user_id 
1132
                FROM $group_user_table gu
1133
                INNER JOIN $groupTable g
1134
                ON (gu.group_id = g.iid and g.c_id = gu.c_id)
1135
                WHERE gu.c_id = $course_id AND g.id = $group_id";
1136
        $res = Database::query($sql);
1137
        $users = [];
1138
1139
        while ($obj = Database::fetch_object($res)) {
1140
            $users[] = api_get_user_info($obj->user_id);
1141
        }
1142
1143
        $sql = "SELECT user_id 
1144
                FROM $tutor_user_table gu
1145
                INNER JOIN $groupTable g
1146
                ON (gu.group_id = g.id and g.c_id = gu.c_id)
1147
                WHERE gu.c_id = $course_id AND g.id = $group_id";
1148
        $res = Database::query($sql);
1149
        while ($obj = Database::fetch_object($res)) {
1150
            $users[] = api_get_user_info($obj->user_id);
1151
        }
1152
1153
        return $users;
1154
    }
1155
1156
    /**
1157
     * Get only tutors from a group
1158
     * @param array $groupInfo
1159
     * @return array
1160
     */
1161
    public static function getTutors($groupInfo)
1162
    {
1163
        $groupTable = Database::get_course_table(TABLE_GROUP);
1164
        $tutor_user_table = Database::get_course_table(TABLE_GROUP_TUTOR);
1165
        $course_id = api_get_course_int_id();
1166
        $group_id = intval($groupInfo['iid']);
1167
1168
        $sql = "SELECT user_id 
1169
                FROM $tutor_user_table gu
1170
                INNER JOIN $groupTable g
1171
                ON (gu.group_id = g.id and g.c_id = gu.c_id)
1172
                WHERE gu.c_id = $course_id AND g.iid = $group_id";
1173
        $res = Database::query($sql);
1174
1175
        $users = [];
1176
        while ($obj = Database::fetch_object($res)) {
1177
            $users[] = api_get_user_info($obj->user_id);
1178
        }
1179
1180
        return $users;
1181
    }
1182
1183
    /**
1184
     * Get only students from a group (not tutors)
1185
     * @param int $group_id iid
1186
     * @return array
1187
     */
1188
    public static function getStudents($group_id)
1189
    {
1190
        $em = Database::getManager();
1191
        $subscriptions = $em
1192
            ->createQuery('
1193
                SELECT gu
1194
                FROM ChamiloCourseBundle:CGroupRelUser gu
1195
                INNER JOIN ChamiloCourseBundle:CGroupInfo g
1196
                WITH gu.groupId = g.id AND g.cId = gu.cId
1197
                WHERE gu.cId = :course AND g.id = :group
1198
            ')
1199
            ->setParameters([
1200
                'course' => api_get_course_int_id(),
1201
                'group' => intval($group_id)
1202
            ])
1203
            ->getResult();
1204
1205
        $users = [];
1206
1207
        /** @var CGroupRelUser $subscription */
1208
        foreach ($subscriptions as $subscription) {
1209
            $users[] = api_get_user_info($subscription->getUserId());
1210
        }
1211
1212
        return $users;
1213
    }
1214
1215
    /**
1216
     * Returns users belonging to any of the group
1217
     *
1218
     * @param array $groups list of group ids
1219
     * @return array list of user ids
1220
     */
1221
    public static function get_groups_users($groups = [])
1222
    {
1223
        $result = [];
1224
        $table = Database::get_course_table(TABLE_GROUP_USER);
1225
        $course_id = api_get_course_int_id();
1226
1227
        $groups = array_map('intval', $groups);
1228
        // protect individual elements with surrounding quotes
1229
        $groups = implode(', ', $groups);
1230
        $sql = "SELECT DISTINCT user_id
1231
                FROM $table gu
1232
                WHERE c_id = $course_id AND gu.group_id IN ($groups)";
1233
        $rs = Database::query($sql);
1234
        while ($row = Database::fetch_array($rs)) {
1235
            $result[] = $row['user_id'];
1236
        }
1237
1238
        return $result;
1239
    }
1240
1241
    /**
1242
     * Fill the groups with students.
1243
     * The algorithm takes care to first fill the groups with the least # of users.
1244
     * Analysis
1245
     * There was a problem with the "ALL" setting.
1246
     * When max # of groups is set to all, the value is sometimes NULL and sometimes ALL
1247
     * and in both cased the query does not work as expected.
1248
     * Stupid solution (currently implemented: set ALL to a big number (INFINITE) and things are solved :)
1249
     * Better solution: that's up to you.
1250
     *
1251
     * Note
1252
     * Throughout Dokeos there is some confusion about "course id" and "course code"
1253
     * The code is e.g. TEST101, but sometimes a variable that is called courseID also contains a course code string.
1254
     * However, there is also a integer course_id that uniquely identifies the course.
1255
     * ywarnier:> Now the course_id has been removed (25/1/2005)
1256
     * The databases are als very inconsistent in this.
1257
     *
1258
     * @param array $groupInfo
1259
     * @author Chrisptophe Gesche <[email protected]>,
1260
     *         Hugues Peeters     <[email protected]> - original version
1261
     * @author Roan Embrechts - virtual course support, code cleaning
1262
     * @author Bart Mollet - code cleaning, use other GroupManager-functions
1263
     * @return bool
1264
     */
1265
    public static function fillGroupWithUsers($groupInfo)
1266
    {
1267
        $_course = api_get_course_info();
1268
        if (empty($_course) || empty($groupInfo)) {
1269
            return false;
1270
        }
1271
        $session_id = api_get_session_id();
1272
        $complete_user_list = CourseManager::get_user_list_from_course_code(
1273
            $_course['code'],
1274
            $session_id
1275
        );
1276
        $groupIid = $groupInfo['iid'];
1277
        $category = self::get_category_from_group($groupIid);
1278
1279
        // Getting max numbers of user from group
1280
        $maxNumberStudents = empty($groupInfo['maximum_number_of_students']) ? self::INFINITE : $groupInfo['maximum_number_of_students'];
1281
        $groupsPerUser = self::INFINITE;
1282
        $categoryId = 0;
1283
        if ($category) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $category of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1284
            $groupsPerUser = empty($category['groups_per_user']) ? self::INFINITE : $category['groups_per_user'];
1285
            $maxNumberStudentsCategory = empty($category['max_student']) ? self::INFINITE : $category['max_student'];
1286
            $categoryId = $category['id'];
1287
            if ($maxNumberStudentsCategory < $maxNumberStudents) {
1288
                $maxNumberStudents = $maxNumberStudentsCategory;
1289
            }
1290
        }
1291
1292
        $usersToAdd = [];
1293
        foreach ($complete_user_list as $userInfo) {
1294
            $isSubscribed = self::is_subscribed($userInfo['user_id'], $groupInfo);
1295
            if ($isSubscribed) {
1296
                continue;
1297
            }
1298
            $numberOfGroups = self::user_in_number_of_groups(
1299
                $userInfo['user_id'],
1300
                $categoryId
1301
            );
1302
            if ($groupsPerUser > $numberOfGroups) {
1303
                $usersToAdd[] = $userInfo['user_id'];
1304
            }
1305
            if (count($usersToAdd) == $maxNumberStudents) {
1306
                break;
1307
            }
1308
        }
1309
1310
        foreach ($usersToAdd as $userId) {
1311
            self::subscribe_users($userId, $groupInfo);
1312
        }
1313
    }
1314
1315
    /**
1316
     * Get the number of students in a group.
1317
     * @param int $group_id id
1318
     * @return int Number of students in the given group.
1319
     */
1320
    public static function number_of_students($group_id, $course_id = null)
1321
    {
1322
        $table = Database::get_course_table(TABLE_GROUP_USER);
1323
        $group_id = intval($group_id);
1324
        if (empty($course_id)) {
1325
            $course_id = api_get_course_int_id();
1326
        } else {
1327
            $course_id = intval($course_id);
1328
        }
1329
        $sql = "SELECT COUNT(*) AS number_of_students
1330
                FROM $table
1331
                WHERE c_id = $course_id AND group_id = $group_id";
1332
        $result = Database::query($sql);
1333
        $db_object = Database::fetch_object($result);
1334
1335
        return $db_object->number_of_students;
1336
    }
1337
1338
    /**
1339
     * Maximum number of students in a group
1340
     * @param int $group_id iid
1341
     * @return int Maximum number of students in the given group.
1342
     */
1343
    public static function maximum_number_of_students($group_id)
1344
    {
1345
        $table = Database::get_course_table(TABLE_GROUP);
1346
        $group_id = intval($group_id);
1347
        $course_id = api_get_course_int_id();
1348
        $sql = "SELECT max_student FROM $table 
1349
                WHERE c_id = $course_id AND iid = $group_id";
1350
        $db_result = Database::query($sql);
1351
        $db_object = Database::fetch_object($db_result);
1352
        if ($db_object->max_student == 0) {
1353
            return self::INFINITE;
1354
        }
1355
        return $db_object->max_student;
1356
    }
1357
1358
    /**
1359
     * Number of groups of a user
1360
     * @param int $user_id
1361
     * @param int $cat_id
1362
     * @return int The number of groups the user is subscribed in.
1363
     */
1364
    public static function user_in_number_of_groups($user_id, $cat_id = 0)
1365
    {
1366
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1367
        $table_group = Database::get_course_table(TABLE_GROUP);
1368
        $user_id = (int) $user_id;
1369
        $cat_id = (int) $cat_id;
1370
1371
        $course_id = api_get_course_int_id();
1372
        $cat_condition = '';
1373
        if (!empty($cat_id)) {
1374
            $cat_condition = " AND g.category_id =  $cat_id ";
1375
        }
1376
1377
        $sql = "SELECT COUNT(*) AS number_of_groups
1378
                FROM $table_group_user gu 
1379
                INNER JOIN $table_group g
1380
                ON (g.iid = gu.group_id AND gu.c_id = g.c_id)
1381
                WHERE
1382
                    gu.c_id = $course_id AND
1383
                    g.c_id = $course_id AND
1384
                    gu.user_id = $user_id                       
1385
                    $cat_condition";
1386
1387
        $result = Database::query($sql);
1388
        $db_object = Database::fetch_object($result);
1389
1390
        return $db_object->number_of_groups;
1391
    }
1392
1393
    /**
1394
     * Is sef-registration allowed?
1395
     * @param int $user_id
1396
     * @param array $groupInfo
1397
     * @return bool TRUE if self-registration is allowed in the given group.
1398
     */
1399
    public static function is_self_registration_allowed($user_id, $groupInfo)
1400
    {
1401
        $course_id = api_get_course_int_id();
1402
        if (!$user_id > 0) {
1403
            return false;
1404
        }
1405
        $groupIid = $groupInfo['iid'];
1406
        $table = Database::get_course_table(TABLE_GROUP);
1407
        if (isset($groupIid)) {
1408
            $sql = "SELECT status, self_registration_allowed
1409
                    FROM $table
1410
                    WHERE c_id = $course_id AND iid = $groupIid";
1411
            $result = Database::query($sql);
1412
            $group = Database::fetch_object($result);
1413
1414
            if ($group->status == 0 || $group->self_registration_allowed != 1) {
1415
                return false;
1416
            }
1417
1418
            return self::canUserSubscribe($user_id, $groupInfo);
1419
        } else {
1420
            return false;
1421
        }
1422
    }
1423
1424
    /**
1425
     * Is sef-unregistration allowed?
1426
     * @param int $user_id
1427
     * @param array $groupInfo
1428
     * @return bool TRUE if self-unregistration is allowed in the given group.
1429
     */
1430
    public static function is_self_unregistration_allowed($user_id, $groupInfo)
1431
    {
1432
        if (!$user_id > 0 || empty($groupInfo)) {
1433
            return false;
1434
        }
1435
        $groupIid = $groupInfo['iid'];
1436
        $table = Database::get_course_table(TABLE_GROUP);
1437
        $course_id = api_get_course_int_id();
1438
1439
        $sql = "SELECT status, self_unregistration_allowed
1440
                FROM $table
1441
                WHERE c_id = $course_id AND iid = $groupIid";
1442
        $result = Database::query($sql);
1443
        $group = Database::fetch_object($result);
1444
1445
        if ($group->status == 0 || $group->self_unregistration_allowed != 1) {
1446
            return false;
1447
        }
1448
1449
        return self::is_subscribed($user_id, $groupInfo);
1450
    }
1451
1452
    /**
1453
     * Is user subscribed in group?
1454
     * @param int $user_id
1455
     * @param array $groupInfo
1456
     * @return bool TRUE if given user is subscribed in given group
1457
     */
1458
    public static function is_subscribed($user_id, $groupInfo)
1459
    {
1460
        $course_id = api_get_course_int_id();
1461
        if (empty($user_id) || empty($groupInfo) || empty($course_id)) {
1462
            return false;
1463
        }
1464
        $table = Database::get_course_table(TABLE_GROUP_USER);
1465
        $group_id = intval($groupInfo['id']);
1466
        $user_id = intval($user_id);
1467
1468
        $sql = "SELECT 1 FROM $table
1469
                WHERE
1470
                    c_id = $course_id AND
1471
                    group_id = $group_id AND
1472
                    user_id = $user_id
1473
                ";
1474
        $result = Database::query($sql);
1475
1476
        return Database::num_rows($result) > 0;
1477
    }
1478
1479
    /**
1480
     * Can a user subscribe to a specified group in a course
1481
     * @param int $user_id
1482
     * @param array $groupInfo
1483
     * @param bool $checkMaxNumberStudents
1484
     *
1485
     * @return bool TRUE if given user  can be subscribed in given group
1486
     */
1487
    public static function canUserSubscribe(
1488
        $user_id,
1489
        $groupInfo,
1490
        $checkMaxNumberStudents = true
1491
    ) {
1492
        $group_id = $groupInfo['id'];
1493
        $groupIid = $groupInfo['iid'];
1494
        if ($checkMaxNumberStudents) {
1495
            $category = self::get_category_from_group($groupIid);
1496
            if ($category) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $category of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1497
                if ($category['groups_per_user'] == self::GROUP_PER_MEMBER_NO_LIMIT) {
1498
                    $category['groups_per_user'] = self::INFINITE;
1499
                }
1500
                $result = self::user_in_number_of_groups($user_id, $category['id']) < $category['groups_per_user'];
1501
                if ($result == false) {
1502
                    return false;
1503
                }
1504
            }
1505
1506
            $result = self::number_of_students($group_id) < self::maximum_number_of_students($groupIid);
1507
1508
            if ($result == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
1509
                return false;
1510
            }
1511
        }
1512
1513
        $result = self::is_tutor_of_group($user_id, $groupInfo);
1514
1515
        if ($result) {
1516
            return false;
1517
        }
1518
1519
        $result = self::is_subscribed($user_id, $groupInfo);
1520
1521
        if ($result) {
1522
            return false;
1523
        }
1524
1525
        return true;
1526
    }
1527
1528
    /**
1529
     * Get all subscribed users (members) from a group
1530
     * @param array $groupInfo
1531
     * @return array An array with information of all users from the given group.
1532
     *               (user_id, firstname, lastname, email)
1533
     */
1534
    public static function get_subscribed_users($groupInfo)
1535
    {
1536
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
1537
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1538
        $order_clause = api_sort_by_first_name() ? ' ORDER BY u.firstname, u.lastname' : ' ORDER BY u.lastname, u.firstname';
1539
        $orderListByOfficialCode = api_get_setting('order_user_list_by_official_code');
1540
        if ($orderListByOfficialCode === 'true') {
1541
            $order_clause = " ORDER BY u.official_code, u.firstname, u.lastname";
1542
        }
1543
1544
        $group_id = intval($groupInfo['id']);
1545
1546
        if (empty($group_id)) {
1547
            return [];
1548
        }
1549
1550
        $course_id = api_get_course_int_id();
1551
1552
        $sql = "SELECT 
1553
                    ug.id, 
1554
                    u.user_id, 
1555
                    u.lastname, 
1556
                    u.firstname, 
1557
                    u.email, 
1558
                    u.username
1559
                FROM $table_user u 
1560
                INNER JOIN $table_group_user ug
1561
                ON (ug.user_id = u.user_id)
1562
                WHERE ug.c_id = $course_id AND
1563
                      ug.group_id = $group_id
1564
                $order_clause";
1565
1566
        $db_result = Database::query($sql);
1567
        $users = [];
1568
        while ($user = Database::fetch_object($db_result)) {
1569
            $users[$user->user_id] = [
1570
                'user_id'   => $user->user_id,
1571
                'firstname' => $user->firstname,
1572
                'lastname'  => $user->lastname,
1573
                'email'     => $user->email,
1574
                'username'  => $user->username
1575
            ];
1576
        }
1577
1578
        return $users;
1579
    }
1580
1581
    /**
1582
     * @author Patrick Cool <[email protected]>, Ghent University
1583
     * Get all subscribed tutors of a group
1584
     * @param array $groupInfo
1585
     * @return array An array with information of all users from the given group.
1586
     *               (user_id, firstname, lastname, email)
1587
     */
1588
    public static function get_subscribed_tutors($groupInfo, $id_only = false)
1589
    {
1590
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
1591
        $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1592
        $order_clause = api_sort_by_first_name() ? ' ORDER BY u.firstname, u.lastname' : ' ORDER BY u.lastname, u.firstname';
1593
1594
        $orderListByOfficialCode = api_get_setting('order_user_list_by_official_code');
1595
        if ($orderListByOfficialCode === 'true') {
1596
            $order_clause = " ORDER BY u.official_code, u.firstname, u.lastname";
1597
        }
1598
1599
        $group_id = intval($groupInfo['id']);
1600
        $course_id = api_get_course_int_id();
1601
1602
        $sql = "SELECT tg.id, u.user_id, u.lastname, u.firstname, u.email
1603
                FROM $table_user u, $table_group_tutor tg
1604
                WHERE
1605
                    tg.c_id = $course_id AND
1606
                    tg.group_id = $group_id AND
1607
                    tg.user_id = u.user_id 
1608
                $order_clause
1609
                ";
1610
        $db_result = Database::query($sql);
1611
        $users = [];
1612
        while ($user = Database::fetch_object($db_result)) {
1613
            if (!$id_only) {
1614
                $member['user_id'] = $user->user_id;
1615
                $member['firstname'] = $user->firstname;
1616
                $member['lastname'] = $user->lastname;
1617
                $member['email'] = $user->email;
1618
                $users[] = $member;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $member does not seem to be defined for all execution paths leading up to this point.
Loading history...
1619
            } else {
1620
                $users[] = $user->user_id;
1621
            }
1622
        }
1623
1624
        return $users;
1625
    }
1626
1627
    /**
1628
     * Subscribe user(s) to a specified group in current course (as a student)
1629
     * @param mixed $user_ids Can be an array with user-id's or a single user-id
1630
     * @param array $groupInfo
1631
     * @param int $course_id
1632
     * @return bool TRUE if successful
1633
     */
1634
    public static function subscribe_users($user_ids, $groupInfo, $course_id = null)
1635
    {
1636
        $user_ids = is_array($user_ids) ? $user_ids : [$user_ids];
1637
        $course_id = empty($course_id) ? api_get_course_int_id() : (int) $course_id;
1638
        $group_id = $groupInfo['id'];
1639
1640
        $table = Database::get_course_table(TABLE_GROUP_USER);
1641
        if (!empty($user_ids)) {
1642
            foreach ($user_ids as $user_id) {
1643
                if (self::canUserSubscribe($user_id, $groupInfo)) {
1644
                    $user_id = intval($user_id);
1645
                    $sql = "INSERT INTO ".$table." (c_id, user_id, group_id)
1646
                            VALUES ('$course_id', '".$user_id."', '".$group_id."')";
1647
                    Database::query($sql);
1648
                }
1649
            }
1650
        }
1651
1652
        return true;
1653
    }
1654
1655
    /**
1656
     * Subscribe tutor(s) to a specified group in current course
1657
     * @param mixed $user_ids Can be an array with user-id's or a single user-id
1658
     * @param array $groupInfo
1659
     * @param int $course_id
1660
     *
1661
     * @author Patrick Cool <[email protected]>, Ghent University
1662
     * @see subscribe_users. This function is almost an exact copy of that function.
1663
     * @return bool TRUE if successful
1664
     */
1665
    public static function subscribe_tutors($user_ids, $groupInfo, $course_id = 0)
1666
    {
1667
        $user_ids = is_array($user_ids) ? $user_ids : [$user_ids];
1668
        $result = true;
1669
        $course_id = isset($course_id) && !empty($course_id) ? intval($course_id) : api_get_course_int_id();
1670
        $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1671
        $groupId = (int) $groupInfo['id'];
1672
1673
        foreach ($user_ids as $user_id) {
1674
            $user_id = intval($user_id);
1675
            if (self::canUserSubscribe($user_id, $groupInfo, false)) {
1676
                $sql = "INSERT INTO ".$table_group_tutor." (c_id, user_id, group_id)
1677
                        VALUES ('$course_id', '".$user_id."', '".$groupId."')";
1678
                $result = Database::query($sql);
1679
            }
1680
        }
1681
1682
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result also could return the type Doctrine\DBAL\Driver\Statement which is incompatible with the documented return type boolean.
Loading history...
1683
    }
1684
1685
    /**
1686
     * Unsubscribe user(s) from a specified group in current course
1687
     * @param mixed $user_ids Can be an array with user-id's or a single user-id
1688
     * @param array $groupInfo
1689
     * @return bool TRUE if successful
1690
     */
1691
    public static function unsubscribe_users($user_ids, $groupInfo)
1692
    {
1693
        $user_ids = is_array($user_ids) ? $user_ids : [$user_ids];
1694
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1695
        $group_id = intval($groupInfo['id']);
1696
        $course_id = api_get_course_int_id();
1697
        $sql = 'DELETE FROM '.$table_group_user.'
1698
                WHERE
1699
                    c_id = '.$course_id.' AND
1700
                    group_id = '.$group_id.' AND
1701
                    user_id IN ('.implode(',', $user_ids).')
1702
                ';
1703
        Database::query($sql);
1704
    }
1705
1706
    /**
1707
     * Unsubscribe all users from one or more groups
1708
     * @param array $groupInfo
1709
     * @return bool TRUE if successful
1710
     */
1711
    public static function unsubscribe_all_users($groupInfo)
1712
    {
1713
        $course_id = api_get_course_int_id();
1714
        $groupId = (int) $groupInfo['id'];
1715
        if (empty($course_id) || empty($groupId)) {
1716
            return false;
1717
        }
1718
1719
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1720
        $sql = "DELETE FROM $table_group_user
1721
                WHERE 
1722
                    group_id = $groupId AND 
1723
                    c_id = $course_id";
1724
        $result = Database::query($sql);
1725
1726
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result returns the type Doctrine\DBAL\Driver\Statement which is incompatible with the documented return type boolean.
Loading history...
1727
    }
1728
1729
    /**
1730
     * Unsubscribe all tutors from one or more groups
1731
     * @param int $groupId iid
1732
     * @see unsubscribe_all_users. This function is almost an exact copy of that function.
1733
     * @return bool TRUE if successful
1734
     * @author Patrick Cool <[email protected]>, Ghent University
1735
     */
1736
    public static function unsubscribe_all_tutors($groupId)
1737
    {
1738
        $courseId = api_get_course_int_id();
1739
        $groupId = (int) $groupId;
1740
1741
        if (empty($courseId) || empty($groupId)) {
1742
            return false;
1743
        }
1744
1745
        if (!empty($groupId) > 0) {
1746
            $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1747
            $sql = "DELETE FROM $table_group_tutor
1748
                    WHERE group_id = $groupId AND c_id = $courseId";
1749
            $result = Database::query($sql);
1750
            return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result returns the type Doctrine\DBAL\Driver\Statement which is incompatible with the documented return type boolean.
Loading history...
1751
        }
1752
        return true;
1753
    }
1754
1755
    /**
1756
     * Is the user a tutor of this group?
1757
     * @param int $user_id the id of the user
1758
     * @param array $groupInfo
1759
     * @param int $courseId
1760
     * @return boolean true/false
1761
     * @todo use the function user_has_access that includes this function
1762
     * @author Patrick Cool <[email protected]>, Ghent University
1763
     */
1764
    public static function is_tutor_of_group($user_id, $groupInfo, $courseId = 0)
1765
    {
1766
        if (empty($groupInfo)) {
1767
            return false;
1768
        }
1769
1770
        $courseId = empty($courseId) ? api_get_course_int_id() : (int) $courseId;
1771
        if (empty($courseId)) {
1772
            return false;
1773
        }
1774
1775
        $user_id = intval($user_id);
1776
        $group_id = intval($groupInfo['id']);
1777
1778
        $table = Database::get_course_table(TABLE_GROUP_TUTOR);
1779
1780
        $sql = "SELECT * FROM $table
1781
                WHERE 
1782
                    c_id = $courseId AND 
1783
                    user_id = $user_id AND 
1784
                    group_id = $group_id";
1785
        $result = Database::query($sql);
1786
        if (Database::num_rows($result) > 0) {
1787
            return true;
1788
        } else {
1789
            return false;
1790
        }
1791
    }
1792
1793
    /**
1794
     * Is the user part of this group? This can be a tutor or a normal member
1795
     * you should use this function if the access to a tool or functionality is
1796
     * restricted to the people who are actually in the group
1797
     * before you had to check if the user was
1798
     * 1. a member of the group OR
1799
     * 2. a tutor of the group. This function combines both
1800
     * @param int $user_id the id of the user
1801
     * @param array $groupInfo
1802
     * @return boolean true/false
1803
     * @author Patrick Cool <[email protected]>, Ghent University
1804
     */
1805
    public static function is_user_in_group($user_id, $groupInfo)
1806
    {
1807
        $member = self::is_subscribed($user_id, $groupInfo);
1808
        $tutor = self::is_tutor_of_group($user_id, $groupInfo);
1809
        if ($member || $tutor) {
1810
            return true;
1811
        } else {
1812
            return false;
1813
        }
1814
    }
1815
1816
    /**
1817
     * Get all group's from a given course in which a given user is unsubscribed
1818
     * @author  Patrick Cool
1819
     * @param int  $course_id retrieve the groups for
1820
     * @param int $user_id the ID of the user you want to know all its group memberships
1821
     * @return array
1822
     */
1823
    public static function get_group_ids($course_id, $user_id)
1824
    {
1825
        $groups = [];
1826
        $tbl_group = Database::get_course_table(TABLE_GROUP_USER);
1827
        $tbl_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1828
        $user_id = intval($user_id);
1829
        $course_id = intval($course_id);
1830
1831
        $sql = "SELECT group_id FROM $tbl_group
1832
                WHERE c_id = $course_id AND user_id = '$user_id'";
1833
        $result = Database::query($sql);
1834
1835
        if ($result) {
1836
            while ($row = Database::fetch_array($result)) {
1837
                $groups[] = $row['group_id'];
1838
            }
1839
        }
1840
1841
        //Also loading if i'm the tutor
1842
        $sql = "SELECT group_id FROM $tbl_group_tutor
1843
                WHERE c_id = $course_id AND user_id = '$user_id'";
1844
        $result = Database::query($sql);
1845
        if ($result) {
1846
            while ($row = Database::fetch_array($result)) {
1847
                $groups[] = $row['group_id'];
1848
            }
1849
        }
1850
        if (!empty($groups)) {
1851
            array_filter($groups);
1852
        }
1853
1854
        return $groups;
1855
    }
1856
1857
    /**
1858
     * Remove all users that are not students and all users who have tutor status
1859
     * from  the list.
1860
     * @param array $user_array_in
1861
     * @return array
1862
     */
1863
    public static function filter_only_students($user_array_in)
1864
    {
1865
        $user_array_out = [];
1866
        foreach ($user_array_in as $this_user) {
1867
            if (api_get_session_id()) {
1868
                if ($this_user['status_session'] == 0) {
1869
                    $user_array_out[] = $this_user;
1870
                }
1871
            } else {
1872
                if ($this_user['status_rel'] == STUDENT) {
1873
                    $user_array_out[] = $this_user;
1874
                }
1875
            }
1876
        }
1877
        return $user_array_out;
1878
    }
1879
1880
    /**
1881
     * Check if a user has access to a certain group tool
1882
     * @param int $user_id The user id
1883
     * @param int $group_id The group iid
1884
     * @param string $tool The tool to check the access rights. This should be
1885
     * one of constants: GROUP_TOOL_DOCUMENTS
1886
     * @return bool True if the given user has access to the given tool in the
1887
     * given course.
1888
     */
1889
    public static function user_has_access($user_id, $group_id, $tool)
1890
    {
1891
        // Admin have access everywhere
1892
        if (api_is_platform_admin()) {
1893
            return true;
1894
        }
1895
1896
        // Course admin also have access to everything
1897
        if (api_is_allowed_to_edit()) {
1898
            return true;
1899
        }
1900
1901
        switch ($tool) {
1902
            case self::GROUP_TOOL_FORUM:
1903
                $key = 'forum_state';
1904
                break;
1905
            case self::GROUP_TOOL_DOCUMENTS:
1906
                $key = 'doc_state';
1907
                break;
1908
            case self::GROUP_TOOL_CALENDAR:
1909
                $key = 'calendar_state';
1910
                break;
1911
            case self::GROUP_TOOL_ANNOUNCEMENT:
1912
                $key = 'announcements_state';
1913
                break;
1914
            case self::GROUP_TOOL_WORK:
1915
                $key = 'work_state';
1916
                break;
1917
            case self::GROUP_TOOL_WIKI:
1918
                $key = 'wiki_state';
1919
                break;
1920
            case self::GROUP_TOOL_CHAT:
1921
                $key = 'chat_state';
1922
                break;
1923
            default:
1924
                return false;
1925
        }
1926
1927
        // Check group properties
1928
        $groupInfo = self::get_group_properties($group_id, true);
1929
1930
        if (empty($groupInfo)) {
1931
            return false;
1932
        }
1933
1934
        if ($groupInfo['status'] == 0) {
1935
            return false;
1936
        }
1937
1938
        if (!isset($groupInfo[$key])) {
1939
            return false;
1940
        }
1941
1942
        if (api_is_allowed_to_edit(false, true)) {
1943
            return true;
1944
        }
1945
1946
        $status = $groupInfo[$key];
1947
1948
        switch ($status) {
1949
            case self::TOOL_NOT_AVAILABLE:
1950
                return false;
1951
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

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

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

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

Loading history...
1952
            case self::TOOL_PUBLIC:
1953
                return true;
1954
                break;
1955
            case self::TOOL_PRIVATE:
1956
                $userIsInGroup = self::is_user_in_group($user_id, $groupInfo);
1957
                if ($userIsInGroup) {
1958
                    return true;
1959
                }
1960
                break;
1961
        }
1962
1963
        return false;
1964
    }
1965
1966
    /**
1967
     * @param int $userId
1968
     * @param array $groupInfo
1969
     * @param int $sessionId
1970
     *
1971
     * @return bool
1972
     */
1973
    public static function userHasAccessToBrowse($userId, $groupInfo, $sessionId = 0)
1974
    {
1975
        if (empty($groupInfo)) {
1976
            return false;
1977
        }
1978
1979
        if (api_is_platform_admin()) {
1980
            return true;
1981
        }
1982
1983
        if (api_is_allowed_to_edit(false, true)) {
1984
            return true;
1985
        }
1986
1987
        $groupId = $groupInfo['iid'];
1988
        $tutors = self::get_subscribed_tutors($groupInfo, true);
1989
1990
        if (in_array($userId, $tutors)) {
1991
            return true;
1992
        }
1993
1994
        if ($groupInfo['status'] == 0) {
1995
            return false;
1996
        }
1997
1998
        if (self::user_has_access($userId, $groupId, self::GROUP_TOOL_FORUM) ||
1999
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_DOCUMENTS) ||
2000
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_CALENDAR) ||
2001
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_ANNOUNCEMENT) ||
2002
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_WORK) ||
2003
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_WIKI) ||
2004
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_CHAT)
2005
        ) {
2006
            return true;
2007
        }
2008
2009
        if (api_is_session_general_coach() && $groupInfo['session_id'] == $sessionId) {
2010
            return true;
2011
        }
2012
2013
        return false;
2014
    }
2015
2016
2017
    /**
2018
     * Get all groups where a specific user is subscribed
2019
     * @param int $user_id
2020
     * @return array
2021
     */
2022
    public static function get_user_group_name($user_id)
2023
    {
2024
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
2025
        $table_group = Database::get_course_table(TABLE_GROUP);
2026
        $user_id = intval($user_id);
2027
        $course_id = api_get_course_int_id();
2028
        $sql = "SELECT name
2029
                FROM $table_group g 
2030
                INNER JOIN $table_group_user gu
2031
                ON (gu.group_id = g.iid)
2032
                WHERE
2033
                  gu.c_id= $course_id AND
2034
                  g.c_id= $course_id AND
2035
                  gu.user_id = $user_id";
2036
        $res = Database::query($sql);
2037
        $groups = [];
2038
        while ($group = Database::fetch_array($res)) {
2039
            $groups[] .= $group['name'];
2040
        }
2041
        return $groups;
2042
    }
2043
2044
    /**
2045
     * Get all groups where a specific user is subscribed
2046
     * @param int $user_id
2047
     * @return array
2048
     */
2049
    public static function getAllGroupPerUserSubscription($user_id)
2050
    {
2051
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
2052
        $table_tutor_user = Database::get_course_table(TABLE_GROUP_TUTOR);
2053
        $table_group = Database::get_course_table(TABLE_GROUP);
2054
        $user_id = intval($user_id);
2055
        $course_id = api_get_course_int_id();
2056
        $sql = "SELECT DISTINCT g.*
2057
               FROM $table_group g
2058
               LEFT JOIN $table_group_user gu
2059
               ON (gu.group_id = g.iid AND g.c_id = gu.c_id)
2060
               LEFT JOIN $table_tutor_user tu
2061
               ON (tu.group_id = g.iid AND g.c_id = tu.c_id)
2062
               WHERE
2063
                  g.c_id = $course_id AND
2064
                  (gu.user_id = $user_id OR tu.user_id = $user_id) ";
2065
        $res = Database::query($sql);
2066
        $groups = [];
2067
        while ($group = Database::fetch_array($res, 'ASSOC')) {
2068
            $groups[] = $group;
2069
        }
2070
2071
        return $groups;
2072
    }
2073
2074
    /**
2075
     * @param array $userList
2076
     * @param array $groupInfo
2077
     * @return mixed
2078
     */
2079
    public static function getNumberLeftFromGroupFromUserList($userList, $groupInfo)
2080
    {
2081
        $groupIid = (int) $groupInfo['iid'];
2082
        $category = self::get_category_from_group($groupIid);
2083
        $number_groups_per_user = $groupInfo['maximum_number_of_students'];
2084
        $categoryId = 0;
2085
        if ($category) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $category of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
2086
            $groups_per_user = $category['groups_per_user'];
2087
            $number_groups_per_user = $groups_per_user == self::GROUP_PER_MEMBER_NO_LIMIT ? self::INFINITE : $groups_per_user;
2088
            $categoryId = $category['id'];
2089
        }
2090
2091
        $usersAdded = [];
2092
        foreach ($userList as &$userInfo) {
2093
            // find # of groups the user is enrolled in
2094
            $numberOfGroups = self::user_in_number_of_groups(
2095
                $userInfo['user_id'],
2096
                $categoryId
2097
            );
2098
2099
            if (in_array($userInfo['user_id'], $usersAdded)) {
2100
                continue;
2101
            }
2102
2103
            $usersAdded[] = $userInfo['user_id'];
2104
2105
            // add # of groups to user list
2106
            $userInfo['number_groups_left'] = $number_groups_per_user - $numberOfGroups;
2107
        }
2108
2109
        return $userList;
2110
    }
2111
2112
    /**
2113
     * @param array $group_list
2114
     * @param int $category_id
2115
     *
2116
     * @return string
2117
     */
2118
    public static function process_groups($group_list, $category_id = 0)
2119
    {
2120
        global $charset;
2121
        $category_id = (int) $category_id;
2122
        $totalRegistered = 0;
2123
        $group_data = [];
2124
        $user_info = api_get_user_info();
2125
        $session_id = api_get_session_id();
2126
        $user_id = $user_info['user_id'];
2127
        $hideGroup = api_get_setting('hide_course_group_if_no_tools_available');
2128
2129
        foreach ($group_list as $this_group) {
2130
            // Validation when belongs to a session
2131
            $session_img = api_get_session_image($this_group['session_id'], $user_info['status']);
2132
2133
            // All the tutors of this group
2134
            $tutorsids_of_group = self::get_subscribed_tutors($this_group, true);
2135
            $isMember = self::is_subscribed($user_id, $this_group);
2136
2137
            // Create a new table-row
2138
            $row = [];
2139
            // Checkbox
2140
            if (api_is_allowed_to_edit(false, true) && count($group_list) > 1) {
2141
                $row[] = $this_group['id'];
2142
            }
2143
2144
            if (self::userHasAccessToBrowse($user_id, $this_group, $session_id)) {
2145
                // Group name
2146
                $groupNameClass = null;
2147
                if ($this_group['status'] == 0) {
2148
                    $groupNameClass = 'muted';
2149
                }
2150
2151
                $group_name = '<a class="'.$groupNameClass.'" href="group_space.php?'.api_get_cidreq(true, false).'&gidReq='.$this_group['id'].'">'.
2152
                    Security::remove_XSS($this_group['name']).'</a> ';
2153
                if (!empty($user_id) && !empty($this_group['id_tutor']) && $user_id == $this_group['id_tutor']) {
2154
                    $group_name .= Display::label(get_lang('OneMyGroups'), 'success');
2155
                } elseif ($isMember) {
2156
                    $group_name .= Display::label(get_lang('MyGroup'), 'success');
2157
                }
2158
2159
                if (api_is_allowed_to_edit() && !empty($this_group['session_name'])) {
2160
                    $group_name .= ' ('.$this_group['session_name'].')';
2161
                }
2162
                $group_name .= $session_img;
2163
                $row[] = $group_name.'<br />'.stripslashes(trim($this_group['description']));
2164
            } else {
2165
                if ($hideGroup === 'true') {
2166
                    continue;
2167
                }
2168
                $row[] = $this_group['name'].'<br />'.stripslashes(trim($this_group['description']));
2169
            }
2170
2171
            // Tutor name
2172
            $tutor_info = '';
2173
            if (count($tutorsids_of_group) > 0) {
2174
                foreach ($tutorsids_of_group as $tutor_id) {
2175
                    $tutor = api_get_user_info($tutor_id);
2176
                    $username = api_htmlentities(
2177
                        sprintf(get_lang('LoginX'), $tutor['username']),
2178
                        ENT_QUOTES
2179
                    );
2180
                    if (api_get_setting('show_email_addresses') === 'true') {
2181
                        $tutor_info .= Display::tag(
2182
                            'span',
2183
                            Display::encrypted_mailto_link(
2184
                                $tutor['mail'],
2185
                                $tutor['complete_name']
2186
                            ),
2187
                            ['title' => $username]
2188
                        ).', ';
2189
                    } else {
2190
                        if (api_is_allowed_to_edit()) {
2191
                            $tutor_info .= Display::tag(
2192
                            'span',
2193
                                Display::encrypted_mailto_link(
2194
                                    $tutor['mail'],
2195
                                    $tutor['complete_name_with_username']
2196
                                ),
2197
                                ['title'=>$username]
2198
                            ).', ';
2199
                        } else {
2200
                            $tutor_info .= Display::tag(
2201
                                'span',
2202
                                $tutor['complete_name'],
2203
                                ['title' => $username]
2204
                            ).', ';
2205
                        }
2206
                    }
2207
                }
2208
            }
2209
2210
            $tutor_info = api_substr(
2211
                $tutor_info,
2212
                0,
2213
                api_strlen($tutor_info) - 2
2214
            );
2215
            $row[] = $tutor_info;
2216
2217
            // Max number of members in group
2218
            $max_members = $this_group['maximum_number_of_members'] == self::MEMBER_PER_GROUP_NO_LIMIT ? ' ' : ' / '.$this_group['maximum_number_of_members'];
2219
2220
            // Number of members in group
2221
            $row[] = $this_group['number_of_members'].$max_members;
2222
2223
            // Self-registration / unregistration
2224
            if (!api_is_allowed_to_edit(false, true)) {
2225
                if (self::is_self_registration_allowed($user_id, $this_group)) {
2226
                    $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>';
2227
                } elseif (self::is_self_unregistration_allowed($user_id, $this_group)) {
2228
                    $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>';
2229
                } else {
2230
                    $row[] = '-';
2231
                }
2232
            }
2233
2234
            $url = api_get_path(WEB_CODE_PATH).'group/';
2235
            // Edit-links
2236
            if (api_is_allowed_to_edit(false, true) &&
2237
                !(api_is_session_general_coach() && intval($this_group['session_id']) != $session_id)
2238
            ) {
2239
                $edit_actions = '<a href="'.$url.'settings.php?'.api_get_cidreq(true, false).'&gidReq='.$this_group['id'].'"  title="'.get_lang('Edit').'">'.
2240
                    Display::return_icon('edit.png', get_lang('EditGroup'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2241
2242
                if ($this_group['status'] == 1) {
2243
                    $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').'">'.
2244
                        Display::return_icon('visible.png', get_lang('Hide'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2245
                } else {
2246
                    $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').'">'.
2247
                        Display::return_icon('invisible.png', get_lang('Show'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2248
                }
2249
2250
                $edit_actions .= '<a href="'.$url.'member_settings.php?'.api_get_cidreq(true, false).'&gidReq='.$this_group['id'].'"  title="'.get_lang('GroupMembers').'">'.
2251
                    Display::return_icon('user.png', get_lang('GroupMembers'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2252
2253
                $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').'">'.
2254
                    Display::return_icon('export_excel.png', get_lang('Export'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2255
2256
                $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').'">'.
2257
                    Display::return_icon('fill.png', get_lang('FillGroup'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2258
2259
                $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').'">'.
2260
                    Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2261
2262
                $row[] = $edit_actions;
2263
            }
2264
            if (!empty($this_group['nbMember'])) {
2265
                $totalRegistered = $totalRegistered + $this_group['nbMember'];
2266
            }
2267
            $group_data[] = $row;
2268
        } // end loop
2269
2270
        // If no groups then don't show the table (only for students)
2271
        if (!api_is_allowed_to_edit(true, false)) {
2272
            if (empty($group_data)) {
2273
                return '';
2274
            }
2275
        }
2276
2277
        $table = new SortableTableFromArrayConfig(
2278
            $group_data,
2279
            1,
2280
            20,
2281
            'group_category_'.$category_id
2282
        );
2283
        $table->set_additional_parameters(['category' => $category_id]);
2284
        $column = 0;
2285
        if (api_is_allowed_to_edit(false, true) and count($group_list) > 1) {
2286
            $table->set_header($column++, '', false);
2287
        }
2288
        $table->set_header($column++, get_lang('Groups'));
2289
        $table->set_header($column++, get_lang('GroupTutor'));
2290
        $table->set_header($column++, get_lang('Registered'), false);
2291
2292
        if (!api_is_allowed_to_edit(false, true)) {
2293
            // If self-registration allowed
2294
            $table->set_header($column++, get_lang('GroupSelfRegistration'), false);
2295
        }
2296
2297
        if (api_is_allowed_to_edit(false, true)) {
2298
            // Only for course administrator
2299
            $table->set_header($column++, get_lang('Modify'), false);
2300
            $form_actions = [];
2301
            $form_actions['fill_selected'] = get_lang('FillGroup');
2302
            $form_actions['empty_selected'] = get_lang('EmptyGroup');
2303
            $form_actions['delete_selected'] = get_lang('Delete');
2304
            if (count($group_list) > 1) {
2305
                $table->set_form_actions($form_actions, 'group');
2306
            }
2307
        }
2308
2309
        return $table->return_table();
2310
    }
2311
2312
    /**
2313
     * @param array $groupData
2314
     * @param bool $deleteNotInArray
2315
     * @return array
2316
     */
2317
    public static function importCategoriesAndGroupsFromArray(
2318
        $groupData,
2319
        $deleteNotInArray = false
2320
    ) {
2321
        $result = [];
2322
        $elementsFound = [
2323
            'categories' => [],
2324
            'groups' => []
2325
        ];
2326
2327
        $courseCode = api_get_course_id();
2328
        $sessionId = api_get_session_id();
2329
        $groupCategories = self::get_categories();
2330
2331
        if (empty($groupCategories)) {
2332
            $result['error'][] = get_lang('CreateACategory');
2333
            return $result;
2334
        }
2335
2336
        foreach ($groupData as $data) {
2337
            $isCategory = empty($data['group']) ? true : false;
2338
            if ($isCategory) {
2339
                $categoryInfo = self::getCategoryByTitle($data['category']);
2340
                $categoryId = $categoryInfo['id'];
2341
2342
                if (!empty($categoryInfo)) {
2343
                    // Update
2344
                    self::update_category(
2345
                        $categoryId,
2346
                        $data['category'],
2347
                        $data['description'],
2348
                        $data['doc_state'],
2349
                        $data['work_state'],
2350
                        $data['calendar_state'],
2351
                        $data['announcements_state'],
2352
                        $data['forum_state'],
2353
                        $data['wiki_state'],
2354
                        $data['chat_state'],
2355
                        $data['self_reg_allowed'],
2356
                        $data['self_unreg_allowed'],
2357
                        $data['max_student'],
2358
                        $data['groups_per_user']
2359
                    );
2360
                    $data['category_id'] = $categoryId;
2361
                    $result['updated']['category'][] = $data;
2362
                } else {
2363
                    // Add
2364
                    $categoryId = self::create_category(
2365
                        $data['category'],
2366
                        $data['description'],
2367
                        $data['doc_state'],
2368
                        $data['work_state'],
2369
                        $data['calendar_state'],
2370
                        $data['announcements_state'],
2371
                        $data['forum_state'],
2372
                        $data['wiki_state'],
2373
                        $data['chat_state'],
2374
                        $data['self_reg_allowed'],
2375
                        $data['self_unreg_allowed'],
2376
                        $data['max_student'],
2377
                        $data['groups_per_user']
2378
                    );
2379
2380
                    if ($categoryId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $categoryId of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
2381
                        $data['category_id'] = $categoryId;
2382
                        $result['added']['category'][] = $data;
2383
                    }
2384
                }
2385
                $elementsFound['categories'][] = $categoryId;
2386
            } else {
2387
                $groupInfo = self::getGroupByName($data['group']);
2388
                $categoryInfo = [];
2389
                if (isset($data['category'])) {
2390
                    $categoryInfo = self::getCategoryByTitle($data['category']);
2391
                }
2392
                $categoryId = null;
2393
                if (!empty($categoryInfo)) {
2394
                    $categoryId = $categoryInfo['id'];
2395
                } else {
2396
                    if (!empty($groupCategories) && isset($groupCategories[0])) {
2397
                        $defaultGroupCategory = $groupCategories[0];
2398
                        $categoryId = $defaultGroupCategory['id'];
2399
                    }
2400
                }
2401
2402
                if (empty($groupInfo)) {
2403
                    // Add
2404
                    $groupId = self::create_group(
2405
                        $data['group'],
2406
                        $categoryId,
2407
                        null,
2408
                        $data['max_student']
2409
                    );
2410
2411
                    if ($groupId) {
2412
                        self::set_group_properties(
2413
                            $groupId,
2414
                            $data['group'],
2415
                            $data['description'],
2416
                            $data['max_student'],
2417
                            $data['doc_state'],
2418
                            $data['work_state'],
2419
                            $data['calendar_state'],
2420
                            $data['announcements_state'],
2421
                            $data['forum_state'],
2422
                            $data['wiki_state'],
2423
                            $data['chat_state'],
2424
                            $data['self_reg_allowed'],
2425
                            $data['self_unreg_allowed'],
2426
                            $categoryId
2427
                        );
2428
                        $data['group_id'] = $groupId;
2429
                        $result['added']['group'][] = $data;
2430
                    }
2431
                    $groupInfo = self::get_group_properties($groupId, true);
2432
                } else {
2433
                    // Update
2434
                    $groupId = $groupInfo['id'];
2435
                    self::set_group_properties(
2436
                        $groupId,
2437
                        $data['group'],
2438
                        $data['description'],
2439
                        $data['max_student'],
2440
                        $data['doc_state'],
2441
                        $data['work_state'],
2442
                        $data['calendar_state'],
2443
                        $data['announcements_state'],
2444
                        $data['forum_state'],
2445
                        $data['wiki_state'],
2446
                        $data['chat_state'],
2447
                        $data['self_reg_allowed'],
2448
                        $data['self_unreg_allowed'],
2449
                        $categoryId
2450
                    );
2451
2452
                    $data['group_id'] = $groupId;
2453
                    $result['updated']['group'][] = $data;
2454
                    $groupInfo = self::get_group_properties($groupId);
2455
                }
2456
2457
                $students = isset($data['students']) ? explode(',', $data['students']) : [];
2458
                if (!empty($students)) {
2459
                    $studentUserIdList = [];
2460
                    foreach ($students as $student) {
2461
                        $userInfo = api_get_user_info_from_username($student);
2462
2463
                        if (!$userInfo) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $userInfo of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
2464
                            continue;
2465
                        }
2466
2467
                        if (!CourseManager::is_user_subscribed_in_course(
2468
                                $userInfo['user_id'],
2469
                                $courseCode,
2470
                                !empty($sessionId),
2471
                                $sessionId
2472
                            )
2473
                        ) {
2474
                            Display::addFlash(
2475
                                Display::return_message(
2476
                                    sprintf(
2477
                                        get_lang('StudentXIsNotSubscribedToCourse'),
2478
                                        $userInfo['complete_name']
2479
                                    ),
2480
                                    'warning'
2481
                                )
2482
                            );
2483
                            continue;
2484
                        }
2485
2486
                        $studentUserIdList[] = $userInfo['user_id'];
2487
                    }
2488
                    self::subscribe_users($studentUserIdList, $groupInfo);
2489
                }
2490
2491
                $tutors = isset($data['tutors']) ? explode(',', $data['tutors']) : [];
2492
                if (!empty($tutors)) {
2493
                    $tutorIdList = [];
2494
                    foreach ($tutors as $tutor) {
2495
                        $userInfo = api_get_user_info_from_username($tutor);
2496
2497
                        if (!$userInfo) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $userInfo of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
2498
                            continue;
2499
                        }
2500
2501
                        if (!CourseManager::is_user_subscribed_in_course(
2502
                                $userInfo['user_id'],
2503
                                $courseCode,
2504
                                !empty($sessionId),
2505
                                $sessionId
2506
                            )
2507
                        ) {
2508
                            Display::addFlash(
2509
                                Display::return_message(
2510
                                    sprintf(get_lang('TutorXIsNotSubscribedToCourse'), $userInfo['complete_name']),
2511
                                    'warning'
2512
                                )
2513
                            );
2514
2515
                            continue;
2516
                        }
2517
2518
                        $tutorIdList[] = $userInfo['user_id'];
2519
                    }
2520
                    self::subscribe_tutors($tutorIdList, $groupInfo);
2521
                }
2522
2523
                $elementsFound['groups'][] = $groupId;
2524
            }
2525
        }
2526
2527
        if ($deleteNotInArray) {
2528
            // Check categories
2529
            $categories = self::get_categories();
2530
            foreach ($categories as $category) {
2531
                if (!in_array($category['id'], $elementsFound['categories'])) {
2532
                    self::delete_category($category['id']);
2533
                    $category['category'] = $category['title'];
2534
                    $result['deleted']['category'][] = $category;
2535
                }
2536
            }
2537
2538
            $groups = self::get_groups();
2539
            foreach ($groups as $group) {
2540
                if (!in_array($group['iid'], $elementsFound['groups'])) {
2541
                    self::delete_groups($group);
2542
                    $group['group'] = $group['name'];
2543
                    $result['deleted']['group'][] = $group;
2544
                }
2545
            }
2546
        }
2547
2548
        return $result;
2549
    }
2550
2551
    /**
2552
     * Export all categories/group from a course to an array.
2553
     * This function works only in a context of a course.
2554
     * @param int $groupId
2555
     * @param bool $loadUsers
2556
     * @return array
2557
     */
2558
    public static function exportCategoriesAndGroupsToArray($groupId = null, $loadUsers = false)
2559
    {
2560
        $data = [];
2561
        $data[] = [
2562
            'category',
2563
            'group',
2564
            'description',
2565
            'announcements_state',
2566
            'calendar_state',
2567
            'chat_state',
2568
            'doc_state',
2569
            'forum_state',
2570
            'work_state',
2571
            'wiki_state',
2572
            'max_student',
2573
            'self_reg_allowed',
2574
            'self_unreg_allowed',
2575
            'groups_per_user'
2576
        ];
2577
2578
        $count = 1;
2579
2580
        if ($loadUsers) {
2581
            $data[0][] = 'students';
2582
            $data[0][] = 'tutors';
2583
        }
2584
2585
        if ($loadUsers == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

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