Completed
Push — master ( 9b8b24...6e1754 )
by Julito
58:58
created

GroupManager::set_group_properties()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 53
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 32
nc 4
nop 14
dl 0
loc 53
rs 8.9849
c 0
b 0
f 0

How to fix   Long Method    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CourseBundle\Entity\CGroupRelUser;
5
6
/**
7
 * This library contains some functions for group-management.
8
 * @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 = array();
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
203
        } else {
204
            $docState = self::TOOL_PRIVATE;
205
            $calendarState = self::TOOL_PRIVATE;
206
            $workState = self::TOOL_PRIVATE;
207
            $anonuncementState = self::TOOL_PRIVATE;
208
            $forumState = self::TOOL_PRIVATE;
209
            $wikiState = self::TOOL_PRIVATE;
210
            $chatState = self::TOOL_PRIVATE;
211
            $selfRegAllowed = 0;
212
            $selfUnregAllwoed = 0;
213
        }
214
215
        $table_group = Database::get_course_table(TABLE_GROUP);
216
        $sql = "INSERT INTO $table_group SET
217
                c_id = $course_id,
218
                status = 1,
219
                category_id='".Database::escape_string($category_id)."',
220
                max_student = '".$places."',
221
                doc_state = '".$docState."',
222
                calendar_state = '".$calendarState."',
223
                work_state = '".$workState."',
224
                announcements_state = '".$anonuncementState."',
225
                forum_state = '".$forumState."',
226
                wiki_state = '".$wikiState."',
227
                chat_state = '".$chatState."',
228
                self_registration_allowed = '".$selfRegAllowed."',
229
                self_unregistration_allowed = '".$selfUnregAllwoed."',
230
                session_id='".intval($session_id)."'";
231
232
        Database::query($sql);
233
        $lastId = Database::insert_id();
234
235
        if ($lastId) {
236
            $sql = "UPDATE $table_group SET id = iid WHERE iid = $lastId";
237
            Database::query($sql);
238
239
            $desired_dir_name = '/'.api_replace_dangerous_char($name).'_groupdocs';
240
            $my_path = api_get_path(SYS_COURSE_PATH).$currentCourseRepository.'/document';
241
242
            $newFolderData = create_unexisting_directory(
243
                $_course,
244
                api_get_user_id(),
245
                $session_id,
246
                $lastId,
247
                null,
248
                $my_path,
249
                $desired_dir_name,
250
                null,
251
                1
252
            );
253
254
            $unique_name = $newFolderData['path'];
255
256
            /* Stores the directory path into the group table */
257
            $sql = "UPDATE $table_group SET
258
                        name = '".Database::escape_string($name)."',
259
                        secret_directory = '".$unique_name."'
260
                    WHERE c_id = $course_id AND id ='".$lastId."'";
261
262
            Database::query($sql);
263
264
            // create a forum if needed
265
            if ($forumState >= 0) {
266
                require_once api_get_path(SYS_CODE_PATH).'forum/forumconfig.inc.php';
267
                require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
268
269
                $forum_categories = get_forum_categories();
270
                if (empty($forum_categories)) {
271
                    $categoryParam = array(
272
                        'forum_category_title' => get_lang('GroupForums'),
273
                    );
274
                    store_forumcategory($categoryParam);
275
276
                    $forum_categories = get_forum_categories();
277
                }
278
279
                $counter = 0;
280
                foreach ($forum_categories as $key => $value) {
281
                    if ($counter == 0) {
282
                        $forum_category_id = $key;
283
                    }
284
                    $counter++;
285
                }
286
                // A sanity check.
287
                if (empty($forum_category_id)) {
288
                    $forum_category_id = 0;
289
                }
290
291
                $values = array();
292
                $values['forum_title'] = $name;
293
                $values['group_id'] = $lastId;
294
                $values['forum_category'] = $forum_category_id;
295
                $values['allow_anonymous_group']['allow_anonymous'] = 0;
296
                $values['students_can_edit_group']['students_can_edit'] = 0;
297
                $values['approval_direct_group']['approval_direct'] = 0;
298
                $values['allow_attachments_group']['allow_attachments'] = 1;
299
                $values['allow_new_threads_group']['allow_new_threads'] = 1;
300
                $values['default_view_type_group']['default_view_type'] = api_get_setting('default_forum_view');
301
                $values['group_forum'] = $lastId;
302
                if ($forumState == '1') {
303
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'public';
304
                } elseif ($forumState == '2') {
305
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'private';
306
                } elseif ($forumState == '0') {
307
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'unavailable';
308
                }
309
                store_forum($values);
310
            }
311
        }
312
313
        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...
314
    }
315
316
    /**
317
     * Create subgroups.
318
     * This function creates new groups based on an existing group. It will
319
     * create the specified number of groups and fill those groups with users
320
     * from the base group
321
     * @param int $group_id The group from which subgroups have to be created.
322
     * @param int $number_of_groups The number of groups that have to be created
323
     */
324
    public static function create_subgroups($group_id, $number_of_groups)
325
    {
326
        $course_id = api_get_course_int_id();
327
        $table_group = Database::get_course_table(TABLE_GROUP);
328
        $category_id = self::create_category(
329
            get_lang('Subgroups'),
330
            '',
331
            self::TOOL_PRIVATE,
332
            self::TOOL_PRIVATE,
333
            0,
334
            0,
335
            1,
336
            1
337
        );
338
        $users = self::get_users($group_id);
339
        $group_ids = array();
340
341
        for ($group_nr = 1; $group_nr <= $number_of_groups; $group_nr++) {
342
            $group_ids[] = self::create_group(
343
                get_lang('Subgroup').' '.$group_nr,
344
                $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

344
                /** @scrutinizer ignore-type */ $category_id,
Loading history...
345
                0,
346
                0
347
            );
348
        }
349
350
        $members = array();
351
        foreach ($users as $index => $user_id) {
352
            $groupId = $group_ids[$index % $number_of_groups];
353
            $groupInfo = self::get_group_properties($groupId);
354
            self::subscribe_users(
355
                $user_id,
356
                $groupInfo
357
            );
358
            $members[$group_ids[$groupId]]++;
359
        }
360
361
        foreach ($members as $group_id => $places) {
362
            $sql = "UPDATE $table_group SET max_student = $places
363
                    WHERE c_id = $course_id  AND id = $group_id";
364
            Database::query($sql);
365
        }
366
    }
367
368
    /**
369
     * Create a group for every class subscribed to the current course
370
     * @param int $category_id The category in which the groups should be created
371
     * @return array
372
     */
373
    public static function create_class_groups($category_id)
374
    {
375
        $options['where'] = array(" 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...
376
        $obj = new UserGroup();
377
        $classes = $obj->getUserGroupInCourse($options);
378
        $group_ids = array();
379
        foreach ($classes as $class) {
380
            $users_ids = $obj->get_users_by_usergroup($class['id']);
381
            $group_id = self::create_group(
382
                $class['name'],
383
                $category_id,
384
                0,
385
                count($users_ids)
386
            );
387
            $groupInfo = self::get_group_properties($group_id);
388
            self::subscribe_users($users_ids, $groupInfo);
389
            $group_ids[] = $group_id;
390
        }
391
        return $group_ids;
392
    }
393
394
    /**
395
     * Deletes groups and their data.
396
     * @author Christophe Gesche <[email protected]>
397
     * @author Hugues Peeters <[email protected]>
398
     * @author Bart Mollet
399
     * @param  array  $groupInfo iid
400
     * @param string $course_code Default is current course
401
     * @return integer              - number of groups deleted.
402
     */
403
    public static function delete_groups($groupInfo, $course_code = null)
404
    {
405
        if (empty($groupInfo['iid'])) {
406
            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...
407
        }
408
        $course_info = api_get_course_info($course_code);
409
        $course_id = $course_info['real_id'];
410
411
        // Database table definitions
412
        $group_table = Database::get_course_table(TABLE_GROUP);
413
        $forum_table = Database::get_course_table(TABLE_FORUM);
414
        $groupInfo = self::get_group_properties($groupInfo['iid'], true);
415
        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...
416
            $groupIid = $groupInfo['iid'];
417
            $groupId = $groupInfo['id'];
418
            // Unsubscribe all users
419
            self::unsubscribe_all_users($groupInfo);
420
            self::unsubscribe_all_tutors($groupInfo);
421
422
            if (!empty($groupInfo['secret_directory'])) {
423
                $directory = $groupInfo['secret_directory'];
424
                // move group-documents to garbage
425
                $source_directory = api_get_path(SYS_COURSE_PATH).$course_info['path']."/document".$directory;
426
                // File to renamed
427
                $destination_dir = api_get_path(SYS_COURSE_PATH).$course_info['path']."/document".$directory.'_DELETED_'.$groupInfo['id'];
428
                //Deleting from document tool
429
                DocumentManager::delete_document(
430
                    $course_info,
431
                    $directory,
432
                    $source_directory
433
                );
434
435
                if (file_exists($source_directory)) {
436
                    if (api_get_setting('permanently_remove_deleted_files') === 'true') {
437
                        // Delete
438
                        my_delete($source_directory);
439
                    } else {
440
                        // Rename
441
                        rename($source_directory, $destination_dir);
442
                    }
443
                }
444
            }
445
446
            $sql = "DELETE FROM $forum_table
447
                    WHERE c_id = $course_id AND forum_of_group = $groupId ";
448
            Database::query($sql);
449
450
            // Delete item properties of this group.
451
            // to_group_id is related to c_group_info.iid
452
            $itemPropertyTable = Database::get_course_table(TABLE_ITEM_PROPERTY);
453
            $sql = "DELETE FROM $itemPropertyTable
454
                    WHERE c_id = $course_id AND to_group_id = $groupIid ";
455
            Database::query($sql);
456
457
            // delete the groups
458
            $sql = "DELETE FROM $group_table
459
                    WHERE c_id = $course_id AND iid = $groupIid ";
460
            Database::query($sql);
461
        }
462
463
        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...
464
    }
465
466
    /**
467
     * Get group properties
468
     * @param int $group_id The group from which properties are requested.
469
     * @param bool $useIid
470
     * @return array All properties. Array-keys are:
471
     * name, tutor_id, description, maximum_number_of_students,
472
     * directory and visibility of tools
473
     */
474
    public static function get_group_properties($group_id, $useIid = false)
475
    {
476
        $course_id = api_get_course_int_id();
477
        if (empty($group_id) || !is_integer(intval($group_id))) {
478
            return null;
479
        }
480
481
        $table_group = Database::get_course_table(TABLE_GROUP);
482
        $sql = "SELECT * FROM $table_group
483
                WHERE c_id = $course_id AND id = ".intval($group_id);
484
485
        if ($useIid) {
486
            $sql = "SELECT * FROM $table_group
487
                    WHERE c_id = $course_id AND iid = ".intval($group_id);
488
        }
489
        $db_result = Database::query($sql);
490
        $db_object = Database::fetch_object($db_result);
491
492
        $result = array();
493
        if ($db_object) {
494
            $result['id'] = $db_object->id;
495
            $result['iid'] = $db_object->iid;
496
            $result['name'] = $db_object->name;
497
            $result['status'] = $db_object->status;
498
            $result['description'] = $db_object->description;
499
            $result['maximum_number_of_students'] = $db_object->max_student;
500
            $result['max_student'] = $db_object->max_student;
501
            $result['doc_state'] = $db_object->doc_state;
502
            $result['work_state'] = $db_object->work_state;
503
            $result['calendar_state'] = $db_object->calendar_state;
504
            $result['announcements_state'] = $db_object->announcements_state;
505
            $result['forum_state'] = $db_object->forum_state;
506
            $result['wiki_state'] = $db_object->wiki_state;
507
            $result['chat_state'] = $db_object->chat_state;
508
            $result['directory'] = $db_object->secret_directory;
509
            $result['self_registration_allowed'] = $db_object->self_registration_allowed;
510
            $result['self_unregistration_allowed'] = $db_object->self_unregistration_allowed;
511
            $result['count_users'] = count(
512
                self::get_subscribed_users($result)
513
            );
514
            $result['count_tutor'] = count(
515
                self::get_subscribed_tutors($result)
516
            );
517
            $result['count_all'] = $result['count_users'] + $result['count_tutor'];
518
        }
519
520
        return $result;
521
    }
522
523
    /**
524
     * @param string $name
525
     * @param string $courseCode
526
     * @param int $sessionId
527
     * @return array
528
     */
529
    public static function getGroupByName($name, $courseCode = null, $sessionId = 0)
530
    {
531
        $name = trim($name);
532
533
        if (empty($name)) {
534
            return array();
535
        }
536
537
        $course_info = api_get_course_info($courseCode);
538
        $course_id = $course_info['real_id'];
539
        $name = Database::escape_string($name);
540
        $sessionId = empty($sessionId) ? api_get_session_id() : (int) $sessionId;
541
        $sessionCondition = api_get_session_condition($sessionId);
542
543
        $table = Database::get_course_table(TABLE_GROUP);
544
        $sql = "SELECT * FROM $table
545
                WHERE 
546
                  c_id = $course_id AND 
547
                  name = '$name'
548
                  $sessionCondition
549
                LIMIT 1";
550
        $res = Database::query($sql);
551
        $group = array();
552
        if (Database::num_rows($res)) {
553
            $group = Database::fetch_array($res, 'ASSOC');
554
        }
555
556
        return $group;
557
    }
558
559
    /**
560
     * @param int $courseId
561
     * @param int $categoryId
562
     * @param string $name
563
     * @return array
564
     */
565
    public static function getGroupListFilterByName($name, $categoryId, $courseId)
566
    {
567
        $name = trim($name);
568
        if (empty($name)) {
569
            return array();
570
        }
571
        $name = Database::escape_string($name);
572
        $courseId = intval($courseId);
573
        $table_group = Database::get_course_table(TABLE_GROUP);
574
        $sql = "SELECT * FROM $table_group
575
                WHERE c_id = $courseId AND name LIKE '%$name%'";
576
577
        if (!empty($categoryId)) {
578
            $categoryId = intval($categoryId);
579
            $sql .= " AND category_id = $categoryId";
580
        }
581
        $sql .= " ORDER BY name";
582
        $result = Database::query($sql);
583
584
        return Database::store_result($result, 'ASSOC');
585
    }
586
587
    /**
588
     * Set group properties
589
     * Changes the group's properties.
590
     * @param int       Group Id
591
     * @param string    Group name
592
     * @param string    Group description
593
     * @param int       Max number of students in group
594
     * @param int       Document tool's visibility (0=none,1=private,2=public)
595
     * @param int       Work tool's visibility (0=none,1=private,2=public)
596
     * @param int       Calendar tool's visibility (0=none,1=private,2=public)
597
     * @param int       Announcement tool's visibility (0=none,1=private,2=public)
598
     * @param int       Forum tool's visibility (0=none,1=private,2=public)
599
     * @param int       Wiki tool's visibility (0=none,1=private,2=public)
600
     * @param int       Chat tool's visibility (0=none,1=private,2=public)
601
     * @param bool Whether self registration is allowed or not
602
     * @param bool Whether self unregistration is allowed or not
603
     * @param int $categoryId
604
     * @return bool TRUE if properties are successfully changed, false otherwise
605
     */
606
    public static function set_group_properties(
607
        $group_id,
608
        $name,
609
        $description,
610
        $maximum_number_of_students,
611
        $doc_state,
612
        $work_state,
613
        $calendar_state,
614
        $announcements_state,
615
        $forum_state,
616
        $wiki_state,
617
        $chat_state,
618
        $self_registration_allowed,
619
        $self_unregistration_allowed,
620
        $categoryId = null
621
    ) {
622
        $table_group = Database::get_course_table(TABLE_GROUP);
623
        $table_forum = Database::get_course_table(TABLE_FORUM);
624
        $categoryId = intval($categoryId);
625
        $group_id = intval($group_id);
626
        $course_id = api_get_course_int_id();
627
628
        $sql = "UPDATE ".$table_group." SET
629
                    name='".Database::escape_string(trim($name))."',
630
                    doc_state = '".Database::escape_string($doc_state)."',
631
                    work_state = '".Database::escape_string($work_state)."',
632
                    calendar_state = '".Database::escape_string($calendar_state)."',
633
                    announcements_state = '".Database::escape_string($announcements_state)."',
634
                    forum_state = '".Database::escape_string($forum_state)."',
635
                    wiki_state = '".Database::escape_string($wiki_state)."',
636
                    chat_state = '".Database::escape_string($chat_state)."',
637
                    description ='".Database::escape_string(trim($description))."',
638
                    max_student = '".Database::escape_string($maximum_number_of_students)."',
639
                    self_registration_allowed = '".Database::escape_string($self_registration_allowed)."',
640
                    self_unregistration_allowed = '".Database::escape_string($self_unregistration_allowed)."',
641
                    category_id = ".intval($categoryId)."
642
                WHERE c_id = $course_id AND id=".$group_id;
643
        $result = Database::query($sql);
644
645
        /* Here we are updating a field in the table forum_forum that perhaps
646
        duplicates the table group_info.forum_state cvargas*/
647
        $forum_state = (int) $forum_state;
648
        $sql2 = "UPDATE ".$table_forum." SET ";
649
        if ($forum_state === 1) {
650
            $sql2 .= " forum_group_public_private='public' ";
651
        } elseif ($forum_state === 2) {
652
            $sql2 .= " forum_group_public_private='private' ";
653
        } elseif ($forum_state === 0) {
654
            $sql2 .= " forum_group_public_private='unavailable' ";
655
        }
656
        $sql2 .= " WHERE c_id = $course_id AND forum_of_group=".$group_id;
657
        Database::query($sql2);
658
        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...
659
    }
660
661
    /**
662
     * Get the total number of groups for the current course.
663
     * @return int The number of groups for the current course.
664
     */
665
    public static function get_number_of_groups()
666
    {
667
        $course_id = api_get_course_int_id();
668
        $table = Database::get_course_table(TABLE_GROUP);
669
        $sql = "SELECT COUNT(id) AS number_of_groups
670
                FROM $table
671
                WHERE c_id = $course_id ";
672
        $res = Database::query($sql);
673
        $obj = Database::fetch_object($res);
674
675
        return $obj->number_of_groups;
676
    }
677
678
    /**
679
     * Get all categories
680
     * @param string $course_code The course (default = current course)
681
     * @return array
682
     */
683
    public static function get_categories($course_code = null)
684
    {
685
        $course_info = api_get_course_info($course_code);
686
        $course_id = $course_info['real_id'];
687
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
688
        $sql = "SELECT * FROM $table
689
                WHERE c_id = $course_id
690
                ORDER BY display_order";
691
        $res = Database::query($sql);
692
        $cats = array();
693
        while ($cat = Database::fetch_array($res)) {
694
            $cats[] = $cat;
695
        }
696
        return $cats;
697
    }
698
699
    /**
700
     * Get a group category
701
     * @param int $id The category id
702
     * @param string $course_code The course (default = current course)
703
     * @return array
704
     */
705
    public static function get_category($id, $course_code = null)
706
    {
707
        if (empty($id)) {
708
            return array();
709
        }
710
711
        $course_info = api_get_course_info($course_code);
712
        $course_id = $course_info['real_id'];
713
        $id = intval($id);
714
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
715
        $sql = "SELECT * FROM $table
716
                WHERE c_id = $course_id AND id = $id
717
                LIMIT 1";
718
        $res = Database::query($sql);
719
720
        return Database::fetch_array($res);
721
    }
722
723
    /**
724
     * Get a group category
725
     * @param string $title
726
     * @param string $course_code The course (default = current course)
727
     * @return array
728
     */
729
    public static function getCategoryByTitle($title, $course_code = null)
730
    {
731
        $title = trim($title);
732
733
        if (empty($title)) {
734
            return array();
735
        }
736
737
        $course_info = api_get_course_info($course_code);
738
        $course_id = $course_info['real_id'];
739
        $title = Database::escape_string($title);
740
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
741
        $sql = "SELECT * FROM $table
742
                WHERE c_id = $course_id AND title = '$title'
743
                LIMIT 1";
744
        $res = Database::query($sql);
745
        $category = array();
746
        if (Database::num_rows($res)) {
747
            $category = Database::fetch_array($res, 'ASSOC');
748
        }
749
        return $category;
750
    }
751
752
    /**
753
     * Get the unique category of a given group
754
     * @param int $group_id The iid of the group
755
     * @param string $course_code The course in which the group is (default =
756
     * current course)
757
     * @return array The category
758
     */
759
    public static function get_category_from_group($group_id, $course_code = '')
760
    {
761
        $table_group = Database::get_course_table(TABLE_GROUP);
762
        $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
763
764
        $group_id = intval($group_id);
765
766
        if (empty($group_id)) {
767
            return array();
768
        }
769
770
        $course_info = api_get_course_info($course_code);
771
772
        if (empty($course_info)) {
773
            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...
774
        }
775
776
        $course_id = $course_info['real_id'];
777
        $sql = "SELECT gc.* FROM $table_group_cat gc, $table_group g
778
                WHERE
779
                    gc.c_id = $course_id AND
780
                    g.c_id = $course_id AND
781
                    gc.id = g.category_id AND 
782
                    g.iid = $group_id
783
                LIMIT 1";
784
        $res = Database::query($sql);
785
        $cat = array();
786
        if (Database::num_rows($res)) {
787
            $cat = Database::fetch_array($res);
788
        }
789
        return $cat;
790
    }
791
792
    /**
793
     * Delete a group category
794
     * @param int $cat_id The id of the category to delete
795
     * @param string $course_code The code in which the category should be
796
     * deleted (default = current course)
797
     * @return bool
798
     */
799
    public static function delete_category($cat_id, $course_code = '')
800
    {
801
        $course_info = api_get_course_info($course_code);
802
        if (empty($course_info)) {
803
            return false;
804
        }
805
        $course_id = $course_info['real_id'];
806
807
        $table_group = Database::get_course_table(TABLE_GROUP);
808
        $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
809
        $cat_id = intval($cat_id);
810
        $sql = "SELECT iid FROM $table_group
811
                WHERE c_id = $course_id AND category_id='".$cat_id."'";
812
        $res = Database::query($sql);
813
        if (Database::num_rows($res) > 0) {
814
            while ($group = Database::fetch_object($res)) {
815
                // Delete all groups in category
816
                /*$groupInfo = self::get_group_properties($group->iid, true);
817
                self::delete_groups($groupInfo, $course_code);
818
                */
819
                // Set the category to NULL to avoid losing groups in sessions.
820
                $sql = "UPDATE $table_group SET category_id = NULL WHERE iid = ".$group->iid;
821
                Database::query($sql);
822
823
            }
824
        }
825
        $sql = "DELETE FROM $table_group_cat
826
                WHERE c_id = $course_id  AND id='".$cat_id."'";
827
        Database::query($sql);
828
829
        return true;
830
    }
831
832
    /**
833
     * Create group category
834
     * @param string $title The title of the new category
835
     * @param string $description The description of the new category
836
     * @param int $doc_state
837
     * @param int $work_state
838
     * @param int $calendar_state
839
     * @param int $announcements_state
840
     * @param int $forum_state
841
     * @param int $wiki_state
842
     * @param int $chat_state
843
     * @param int $self_registration_allowed
844
     * @param int $self_unregistration_allowed
845
     * @param int $maximum_number_of_students
846
     * @param int $groups_per_user
847
     * @return mixed
848
     */
849
    public static function create_category(
850
        $title,
851
        $description,
852
        $doc_state,
853
        $work_state,
854
        $calendar_state,
855
        $announcements_state,
856
        $forum_state,
857
        $wiki_state,
858
        $chat_state = 1,
859
        $self_registration_allowed = 0,
860
        $self_unregistration_allowed = 0,
861
        $maximum_number_of_students = 8,
862
        $groups_per_user = 0
863
    ) {
864
        if (empty($title)) {
865
            return false;
866
        }
867
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
868
        $course_id = api_get_course_int_id();
869
870
        $sql = "SELECT MAX(display_order)+1 as new_order
871
                FROM $table
872
                WHERE c_id = $course_id ";
873
        $res = Database::query($sql);
874
        $obj = Database::fetch_object($res);
875
        if (!isset($obj->new_order)) {
876
            $obj->new_order = 1;
877
        }
878
879
        $params = [
880
            'c_id' => $course_id,
881
            'title' => $title,
882
            'display_order' => $obj->new_order,
883
            'description' => $description,
884
            'doc_state' => $doc_state,
885
            'work_state' => $work_state,
886
            'calendar_state' => $calendar_state,
887
            'announcements_state' => $announcements_state,
888
            'forum_state' => $forum_state,
889
            'wiki_state' => $wiki_state,
890
            'chat_state' => $chat_state,
891
            'groups_per_user' => $groups_per_user,
892
            'self_reg_allowed' => $self_registration_allowed,
893
            'self_unreg_allowed' => $self_unregistration_allowed,
894
            'max_student' => $maximum_number_of_students
895
        ];
896
897
        $categoryId = Database::insert($table, $params);
898
        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...
899
            $sql = "UPDATE $table SET id = iid
900
                    WHERE iid = $categoryId";
901
            Database::query($sql);
902
903
            return $categoryId;
904
        }
905
906
        return false;
907
    }
908
909
    /**
910
     * Update group category
911
     *
912
     * @param int $id
913
     * @param string $title
914
     * @param string $description
915
     * @param $doc_state
916
     * @param $work_state
917
     * @param $calendar_state
918
     * @param $announcements_state
919
     * @param $forum_state
920
     * @param $wiki_state
921
     * @param $chat_state
922
     * @param $self_registration_allowed
923
     * @param $self_unregistration_allowed
924
     * @param $maximum_number_of_students
925
     * @param $groups_per_user
926
     */
927
    public static function update_category(
928
        $id,
929
        $title,
930
        $description,
931
        $doc_state,
932
        $work_state,
933
        $calendar_state,
934
        $announcements_state,
935
        $forum_state,
936
        $wiki_state,
937
        $chat_state,
938
        $self_registration_allowed,
939
        $self_unregistration_allowed,
940
        $maximum_number_of_students,
941
        $groups_per_user
942
    ) {
943
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
944
        $id = intval($id);
945
946
        $course_id = api_get_course_int_id();
947
948
        $sql = "UPDATE ".$table." SET
949
                    title='".Database::escape_string($title)."',
950
                    description='".Database::escape_string($description)."',
951
                    doc_state = '".Database::escape_string($doc_state)."',
952
                    work_state = '".Database::escape_string($work_state)."',
953
                    calendar_state = '".Database::escape_string($calendar_state)."',
954
                    announcements_state = '".Database::escape_string($announcements_state)."',
955
                    forum_state = '".Database::escape_string($forum_state)."',
956
                    wiki_state = '".Database::escape_string($wiki_state)."',
957
                    chat_state = '".Database::escape_string($chat_state)."',
958
                    groups_per_user   = '".Database::escape_string($groups_per_user)."',
959
                    self_reg_allowed = '".Database::escape_string($self_registration_allowed)."',
960
                    self_unreg_allowed = '".Database::escape_string($self_unregistration_allowed)."',
961
                    max_student = ".intval($maximum_number_of_students)."
962
                WHERE c_id = $course_id AND id = $id";
963
964
        Database::query($sql);
965
966
        // Updating all groups inside this category
967
        $groups = self::get_group_list($id);
968
969
        if (!empty($groups)) {
970
            foreach ($groups as $group) {
971
                self::set_group_properties(
972
                    $group['id'],
973
                    $group['name'],
974
                    $group['description'],
975
                    $maximum_number_of_students,
976
                    $doc_state,
977
                    $work_state,
978
                    $calendar_state,
979
                    $announcements_state,
980
                    $forum_state,
981
                    $wiki_state,
982
                    $chat_state,
983
                    $self_registration_allowed,
984
                    $self_unregistration_allowed,
985
                    $id
986
                );
987
            }
988
        }
989
    }
990
991
    /**
992
     * Returns the number of groups of the user with the greatest number of
993
     * subscriptions in the given category
994
     */
995
    public static function get_current_max_groups_per_user(
996
        $category_id = null,
997
        $course_code = null
998
    ) {
999
        $course_info = api_get_course_info($course_code);
1000
        $group_table = Database::get_course_table(TABLE_GROUP);
1001
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1002
        $sql = 'SELECT COUNT(gu.group_id) AS current_max
1003
                FROM '.$group_user_table.' gu, '.$group_table.' g
1004
				WHERE g.c_id = '.$course_info['real_id'].'
1005
				AND gu.c_id = g.c_id
1006
				AND gu.group_id = g.iid ';
1007
        if ($category_id != null) {
1008
            $category_id = intval($category_id);
1009
            $sql .= ' AND g.category_id = '.$category_id;
1010
        }
1011
        $sql .= ' GROUP BY gu.user_id ORDER BY current_max DESC LIMIT 1';
1012
        $res = Database::query($sql);
1013
        $obj = Database::fetch_object($res);
1014
1015
        return $obj->current_max;
1016
    }
1017
1018
    /**
1019
     * Swaps the display-order of two categories
1020
     * @param int $id1 The id of the first category
1021
     * @param int $id2 The id of the second category
1022
     */
1023
    public static function swap_category_order($id1, $id2)
1024
    {
1025
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
1026
        $id1 = intval($id1);
1027
        $id2 = intval($id2);
1028
        $course_id = api_get_course_int_id();
1029
1030
        $sql = "SELECT id, display_order FROM $table
1031
                WHERE id IN ($id1,$id2) AND c_id = $course_id ";
1032
        $res = Database::query($sql);
1033
        $cat1 = Database::fetch_object($res);
1034
        $cat2 = Database::fetch_object($res);
1035
        if ($cat1 && $cat2) {
1036
            $sql = "UPDATE $table SET display_order=$cat2->display_order
1037
                    WHERE id = $cat1->id AND c_id = $course_id ";
1038
            Database::query($sql);
1039
1040
            $sql = "UPDATE $table SET display_order=$cat1->display_order
1041
                    WHERE id = $cat2->id AND c_id = $course_id ";
1042
            Database::query($sql);
1043
        }
1044
    }
1045
1046
    /**
1047
     * Get all users from a given group
1048
     * @param int $group_id The group
1049
     * @param bool $load_extra_info
1050
     * @param int $start
1051
     * @param int $limit
1052
     * @param bool $getCount
1053
     * @param int $courseId
1054
     * @param $column
1055
     * @param $direction
1056
     * @return array list of user id
1057
     */
1058
    public static function get_users(
1059
        $group_id,
1060
        $load_extra_info = false,
1061
        $start = null,
1062
        $limit = null,
1063
        $getCount = false,
1064
        $courseId = null,
1065
        $column = null,
1066
        $direction = null
1067
    ) {
1068
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1069
        $groupTable = Database::get_course_table(TABLE_GROUP);
1070
        $user_table = Database::get_main_table(TABLE_MAIN_USER);
1071
        $group_id = intval($group_id);
1072
1073
        if (empty($courseId)) {
1074
            $courseId = api_get_course_int_id();
1075
        } else {
1076
            $courseId = intval($courseId);
1077
        }
1078
1079
        $select = " SELECT u.id, firstname, lastname ";
1080
        if ($getCount) {
1081
            $select = " SELECT count(u.id) count";
1082
        }
1083
        $sql = "$select
1084
                FROM $group_user_table gu
1085
                INNER JOIN $groupTable g
1086
                ON (gu.group_id = g.id and g.c_id = gu.c_id)
1087
                INNER JOIN $user_table u
1088
                ON (u.id = gu.user_id)
1089
                WHERE 
1090
                    gu.c_id = $courseId AND 
1091
                    g.id = $group_id";
1092
1093
        if (!empty($column) && !empty($direction)) {
1094
            $column = Database::escape_string($column, null, false);
1095
            $direction = ($direction == 'ASC' ? 'ASC' : 'DESC');
1096
            $sql .= " ORDER BY $column $direction";
1097
        }
1098
1099
        if (!empty($start) && !empty($limit)) {
1100
            $start = intval($start);
1101
            $limit = intval($limit);
1102
            $sql .= " LIMIT $start, $limit";
1103
        }
1104
        $res = Database::query($sql);
1105
        $users = array();
1106
        while ($obj = Database::fetch_object($res)) {
1107
            if ($getCount) {
1108
                return $obj->count;
1109
                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...
1110
            }
1111
            if ($load_extra_info) {
1112
                $users[] = api_get_user_info($obj->id);
1113
            } else {
1114
                $users[] = $obj->id;
1115
            }
1116
        }
1117
1118
        return $users;
1119
    }
1120
1121
    /**
1122
     * @param int $group_id id
1123
     * @return array
1124
     */
1125
    public static function getStudentsAndTutors($group_id)
1126
    {
1127
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1128
        $tutor_user_table = Database::get_course_table(TABLE_GROUP_TUTOR);
1129
        $groupTable = Database::get_course_table(TABLE_GROUP);
1130
1131
        $course_id = api_get_course_int_id();
1132
        $group_id = intval($group_id);
1133
        $sql = "SELECT user_id 
1134
                FROM $group_user_table gu
1135
                INNER JOIN $groupTable g
1136
                ON (gu.group_id = g.iid and g.c_id = gu.c_id)
1137
                WHERE gu.c_id = $course_id AND g.id = $group_id";
1138
        $res = Database::query($sql);
1139
        $users = array();
1140
1141
        while ($obj = Database::fetch_object($res)) {
1142
            $users[] = api_get_user_info($obj->user_id);
1143
        }
1144
1145
        $sql = "SELECT user_id 
1146
                FROM $tutor_user_table gu
1147
                INNER JOIN $groupTable g
1148
                ON (gu.group_id = g.id and g.c_id = gu.c_id)
1149
                WHERE gu.c_id = $course_id AND g.id = $group_id";
1150
        $res = Database::query($sql);
1151
        while ($obj = Database::fetch_object($res)) {
1152
            $users[] = api_get_user_info($obj->user_id);
1153
        }
1154
1155
        return $users;
1156
    }
1157
1158
    /**
1159
     * Get only tutors from a group
1160
     * @param array $groupInfo
1161
     * @return array
1162
     */
1163
    public static function getTutors($groupInfo)
1164
    {
1165
        $groupTable = Database::get_course_table(TABLE_GROUP);
1166
        $tutor_user_table = Database::get_course_table(TABLE_GROUP_TUTOR);
1167
        $course_id = api_get_course_int_id();
1168
        $group_id = intval($groupInfo['iid']);
1169
1170
        $sql = "SELECT user_id 
1171
                FROM $tutor_user_table gu
1172
                INNER JOIN $groupTable g
1173
                ON (gu.group_id = g.id and g.c_id = gu.c_id)
1174
                WHERE gu.c_id = $course_id AND g.iid = $group_id";
1175
        $res = Database::query($sql);
1176
1177
        $users = array();
1178
        while ($obj = Database::fetch_object($res)) {
1179
            $users[] = api_get_user_info($obj->user_id);
1180
        }
1181
1182
        return $users;
1183
    }
1184
1185
    /**
1186
     * Get only students from a group (not tutors)
1187
     * @param int $group_id iid
1188
     * @return array
1189
     */
1190
    public static function getStudents($group_id)
1191
    {
1192
        $em = Database::getManager();
1193
        $subscriptions = $em
1194
            ->createQuery('
1195
                SELECT gu
1196
                FROM ChamiloCourseBundle:CGroupRelUser gu
1197
                INNER JOIN ChamiloCourseBundle:CGroupInfo g
1198
                WITH gu.groupId = g.id AND g.cId = gu.cId
1199
                WHERE gu.cId = :course AND g.id = :group
1200
            ')
1201
            ->setParameters([
1202
                'course' => api_get_course_int_id(),
1203
                'group' => intval($group_id)
1204
            ])
1205
            ->getResult();
1206
1207
        $users = [];
1208
1209
        /** @var CGroupRelUser $subscription */
1210
        foreach ($subscriptions as $subscription) {
1211
            $users[] = api_get_user_info($subscription->getUserId());
1212
        }
1213
1214
        return $users;
1215
    }
1216
1217
    /**
1218
     * Returns users belonging to any of the group
1219
     *
1220
     * @param array $groups list of group ids
1221
     * @return array list of user ids
1222
     */
1223
    public static function get_groups_users($groups = [])
1224
    {
1225
        $result = array();
1226
        $table = Database::get_course_table(TABLE_GROUP_USER);
1227
        $course_id = api_get_course_int_id();
1228
1229
        $groups = array_map('intval', $groups);
1230
        // protect individual elements with surrounding quotes
1231
        $groups = implode(', ', $groups);
1232
        $sql = "SELECT DISTINCT user_id
1233
                FROM $table gu
1234
                WHERE c_id = $course_id AND gu.group_id IN ($groups)";
1235
        $rs = Database::query($sql);
1236
        while ($row = Database::fetch_array($rs)) {
1237
            $result[] = $row['user_id'];
1238
        }
1239
1240
        return $result;
1241
    }
1242
1243
    /**
1244
     * Fill the groups with students.
1245
     * The algorithm takes care to first fill the groups with the least # of users.
1246
     * Analysis
1247
     * There was a problem with the "ALL" setting.
1248
     * When max # of groups is set to all, the value is sometimes NULL and sometimes ALL
1249
     * and in both cased the query does not work as expected.
1250
     * Stupid solution (currently implemented: set ALL to a big number (INFINITE) and things are solved :)
1251
     * Better solution: that's up to you.
1252
     *
1253
     * Note
1254
     * Throughout Dokeos there is some confusion about "course id" and "course code"
1255
     * The code is e.g. TEST101, but sometimes a variable that is called courseID also contains a course code string.
1256
     * However, there is also a integer course_id that uniquely identifies the course.
1257
     * ywarnier:> Now the course_id has been removed (25/1/2005)
1258
     * The databases are als very inconsistent in this.
1259
     *
1260
     * @param array $groupInfo
1261
     * @author Chrisptophe Gesche <[email protected]>,
1262
     *         Hugues Peeters     <[email protected]> - original version
1263
     * @author Roan Embrechts - virtual course support, code cleaning
1264
     * @author Bart Mollet - code cleaning, use other GroupManager-functions
1265
     * @return bool
1266
     */
1267
    public static function fillGroupWithUsers($groupInfo)
1268
    {
1269
        $_course = api_get_course_info();
1270
        if (empty($_course) || empty($groupInfo)) {
1271
            return false;
1272
        }
1273
        $session_id = api_get_session_id();
1274
        $complete_user_list = CourseManager::get_user_list_from_course_code(
1275
            $_course['code'],
1276
            $session_id
1277
        );
1278
        $groupIid = $groupInfo['iid'];
1279
        $category = self::get_category_from_group($groupIid);
1280
1281
        // Getting max numbers of user from group
1282
        $maxNumberStudents = empty($groupInfo['maximum_number_of_students']) ? self::INFINITE : $groupInfo['maximum_number_of_students'];
1283
        $groupsPerUser = self::INFINITE;
1284
        $categoryId = 0;
1285
        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...
1286
            $groupsPerUser = empty($category['groups_per_user']) ? self::INFINITE : $category['groups_per_user'];
1287
            $maxNumberStudentsCategory = empty($category['max_student']) ? self::INFINITE : $category['max_student'];
1288
            $categoryId = $category['id'];
1289
            if ($maxNumberStudentsCategory < $maxNumberStudents) {
1290
                $maxNumberStudents = $maxNumberStudentsCategory;
1291
            }
1292
        }
1293
1294
        $usersToAdd = [];
1295
        foreach ($complete_user_list as $userInfo) {
1296
            $isSubscribed = self::is_subscribed($userInfo['user_id'], $groupInfo);
1297
            if ($isSubscribed) {
1298
                continue;
1299
            }
1300
            $numberOfGroups = self::user_in_number_of_groups(
1301
                $userInfo['user_id'],
1302
                $categoryId
1303
            );
1304
            if ($groupsPerUser > $numberOfGroups) {
1305
                $usersToAdd[] = $userInfo['user_id'];
1306
            }
1307
            if (count($usersToAdd) == $maxNumberStudents) {
1308
                break;
1309
            }
1310
        }
1311
1312
        foreach ($usersToAdd as $userId) {
1313
            self::subscribe_users($userId, $groupInfo);
1314
        }
1315
    }
1316
1317
    /**
1318
     * Get the number of students in a group.
1319
     * @param int $group_id id
1320
     * @return int Number of students in the given group.
1321
     */
1322
    public static function number_of_students($group_id, $course_id = null)
1323
    {
1324
        $table = Database::get_course_table(TABLE_GROUP_USER);
1325
        $group_id = intval($group_id);
1326
        if (empty($course_id)) {
1327
            $course_id = api_get_course_int_id();
1328
        } else {
1329
            $course_id = intval($course_id);
1330
        }
1331
        $sql = "SELECT COUNT(*) AS number_of_students
1332
                FROM $table
1333
                WHERE c_id = $course_id AND group_id = $group_id";
1334
        $result = Database::query($sql);
1335
        $db_object = Database::fetch_object($result);
1336
1337
        return $db_object->number_of_students;
1338
    }
1339
1340
    /**
1341
     * Maximum number of students in a group
1342
     * @param int $group_id iid
1343
     * @return int Maximum number of students in the given group.
1344
     */
1345
    public static function maximum_number_of_students($group_id)
1346
    {
1347
        $table = Database::get_course_table(TABLE_GROUP);
1348
        $group_id = intval($group_id);
1349
        $course_id = api_get_course_int_id();
1350
        $sql = "SELECT max_student FROM $table 
1351
                WHERE c_id = $course_id AND iid = $group_id";
1352
        $db_result = Database::query($sql);
1353
        $db_object = Database::fetch_object($db_result);
1354
        if ($db_object->max_student == 0) {
1355
            return self::INFINITE;
1356
        }
1357
        return $db_object->max_student;
1358
    }
1359
1360
    /**
1361
     * Number of groups of a user
1362
     * @param int $user_id
1363
     * @param int $cat_id
1364
     * @return int The number of groups the user is subscribed in.
1365
     */
1366
    public static function user_in_number_of_groups($user_id, $cat_id = 0)
1367
    {
1368
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1369
        $table_group = Database::get_course_table(TABLE_GROUP);
1370
        $user_id = (int) $user_id;
1371
        $cat_id = (int) $cat_id;
1372
1373
        $course_id = api_get_course_int_id();
1374
        $cat_condition = '';
1375
        if (!empty($cat_id)) {
1376
            $cat_condition = " AND g.category_id =  $cat_id ";
1377
        }
1378
1379
        $sql = "SELECT COUNT(*) AS number_of_groups
1380
                FROM $table_group_user gu 
1381
                INNER JOIN $table_group g
1382
                ON (g.iid = gu.group_id AND gu.c_id = g.c_id)
1383
                WHERE
1384
                    gu.c_id = $course_id AND
1385
                    g.c_id = $course_id AND
1386
                    gu.user_id = $user_id                       
1387
                    $cat_condition";
1388
1389
        $result = Database::query($sql);
1390
        $db_object = Database::fetch_object($result);
1391
1392
        return $db_object->number_of_groups;
1393
    }
1394
1395
    /**
1396
     * Is sef-registration allowed?
1397
     * @param int $user_id
1398
     * @param array $groupInfo
1399
     * @return bool TRUE if self-registration is allowed in the given group.
1400
     */
1401
    public static function is_self_registration_allowed($user_id, $groupInfo)
1402
    {
1403
        $course_id = api_get_course_int_id();
1404
        if (!$user_id > 0) {
1405
            return false;
1406
        }
1407
        $groupIid = $groupInfo['iid'];
1408
        $table = Database::get_course_table(TABLE_GROUP);
1409
        if (isset($groupIid)) {
1410
            $sql = "SELECT status, self_registration_allowed
1411
                    FROM $table
1412
                    WHERE c_id = $course_id AND iid = $groupIid";
1413
            $result = Database::query($sql);
1414
            $group = Database::fetch_object($result);
1415
1416
            if ($group->status == 0 || $group->self_registration_allowed != 1) {
1417
                return false;
1418
            }
1419
1420
            return self::canUserSubscribe($user_id, $groupInfo);
1421
        } else {
1422
            return false;
1423
        }
1424
    }
1425
1426
    /**
1427
     * Is sef-unregistration allowed?
1428
     * @param int $user_id
1429
     * @param array $groupInfo
1430
     * @return bool TRUE if self-unregistration is allowed in the given group.
1431
     */
1432
    public static function is_self_unregistration_allowed($user_id, $groupInfo)
1433
    {
1434
        if (!$user_id > 0 || empty($groupInfo)) {
1435
            return false;
1436
        }
1437
        $groupIid = $groupInfo['iid'];
1438
        $table = Database::get_course_table(TABLE_GROUP);
1439
        $course_id = api_get_course_int_id();
1440
1441
        $sql = "SELECT status, self_unregistration_allowed
1442
                FROM $table
1443
                WHERE c_id = $course_id AND iid = $groupIid";
1444
        $result = Database::query($sql);
1445
        $group = Database::fetch_object($result);
1446
1447
        if ($group->status == 0 || $group->self_unregistration_allowed != 1) {
1448
            return false;
1449
        }
1450
1451
        return self::is_subscribed($user_id, $groupInfo);
1452
    }
1453
1454
    /**
1455
     * Is user subscribed in group?
1456
     * @param int $user_id
1457
     * @param array $groupInfo
1458
     * @return bool TRUE if given user is subscribed in given group
1459
     */
1460
    public static function is_subscribed($user_id, $groupInfo)
1461
    {
1462
        $course_id = api_get_course_int_id();
1463
        if (empty($user_id) || empty($groupInfo) || empty($course_id)) {
1464
            return false;
1465
        }
1466
        $table = Database::get_course_table(TABLE_GROUP_USER);
1467
        $group_id = intval($groupInfo['id']);
1468
        $user_id = intval($user_id);
1469
1470
        $sql = "SELECT 1 FROM $table
1471
                WHERE
1472
                    c_id = $course_id AND
1473
                    group_id = $group_id AND
1474
                    user_id = $user_id
1475
                ";
1476
        $result = Database::query($sql);
1477
1478
        return Database::num_rows($result) > 0;
1479
    }
1480
1481
    /**
1482
     * Can a user subscribe to a specified group in a course
1483
     * @param int $user_id
1484
     * @param array $groupInfo
1485
     * @param bool $checkMaxNumberStudents
1486
     *
1487
     * @return bool TRUE if given user  can be subscribed in given group
1488
     */
1489
    public static function canUserSubscribe(
1490
        $user_id,
1491
        $groupInfo,
1492
        $checkMaxNumberStudents = true
1493
    ) {
1494
        $group_id = $groupInfo['id'];
1495
        $groupIid = $groupInfo['iid'];
1496
        if ($checkMaxNumberStudents) {
1497
            $category = self::get_category_from_group($groupIid);
1498
            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...
1499
                if ($category['groups_per_user'] == self::GROUP_PER_MEMBER_NO_LIMIT) {
1500
                    $category['groups_per_user'] = self::INFINITE;
1501
                }
1502
                $result = self::user_in_number_of_groups($user_id, $category['id']) < $category['groups_per_user'];
1503
                if ($result == false) {
1504
                    return false;
1505
                }
1506
            }
1507
1508
            $result = self::number_of_students($group_id) < self::maximum_number_of_students($groupIid);
1509
1510
            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...
1511
                return false;
1512
            }
1513
        }
1514
1515
        $result = self::is_tutor_of_group($user_id, $groupInfo);
1516
1517
        if ($result) {
1518
            return false;
1519
        }
1520
1521
        $result = self::is_subscribed($user_id, $groupInfo);
1522
1523
        if ($result) {
1524
            return false;
1525
        }
1526
1527
        return true;
1528
    }
1529
1530
    /**
1531
     * Get all subscribed users (members) from a group
1532
     * @param array $groupInfo
1533
     * @return array An array with information of all users from the given group.
1534
     *               (user_id, firstname, lastname, email)
1535
     */
1536
    public static function get_subscribed_users($groupInfo)
1537
    {
1538
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
1539
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1540
        $order_clause = api_sort_by_first_name() ? ' ORDER BY u.firstname, u.lastname' : ' ORDER BY u.lastname, u.firstname';
1541
        $orderListByOfficialCode = api_get_setting('order_user_list_by_official_code');
1542
        if ($orderListByOfficialCode === 'true') {
1543
            $order_clause = " ORDER BY u.official_code, u.firstname, u.lastname";
1544
        }
1545
1546
        $group_id = intval($groupInfo['id']);
1547
1548
        if (empty($group_id)) {
1549
            return array();
1550
        }
1551
1552
        $course_id = api_get_course_int_id();
1553
1554
        $sql = "SELECT 
1555
                    ug.id, 
1556
                    u.user_id, 
1557
                    u.lastname, 
1558
                    u.firstname, 
1559
                    u.email, 
1560
                    u.username
1561
                FROM $table_user u 
1562
                INNER JOIN $table_group_user ug
1563
                ON (ug.user_id = u.user_id)
1564
                WHERE ug.c_id = $course_id AND
1565
                      ug.group_id = $group_id
1566
                $order_clause";
1567
1568
        $db_result = Database::query($sql);
1569
        $users = array();
1570
        while ($user = Database::fetch_object($db_result)) {
1571
            $users[$user->user_id] = array(
1572
                'user_id'   => $user->user_id,
1573
                'firstname' => $user->firstname,
1574
                'lastname'  => $user->lastname,
1575
                'email'     => $user->email,
1576
                'username'  => $user->username
1577
            );
1578
        }
1579
1580
        return $users;
1581
    }
1582
1583
    /**
1584
     * @author Patrick Cool <[email protected]>, Ghent University
1585
     * Get all subscribed tutors of a group
1586
     * @param array $groupInfo
1587
     * @return array An array with information of all users from the given group.
1588
     *               (user_id, firstname, lastname, email)
1589
     */
1590
    public static function get_subscribed_tutors($groupInfo, $id_only = false)
1591
    {
1592
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
1593
        $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1594
        $order_clause = api_sort_by_first_name() ? ' ORDER BY u.firstname, u.lastname' : ' ORDER BY u.lastname, u.firstname';
1595
1596
        $orderListByOfficialCode = api_get_setting('order_user_list_by_official_code');
1597
        if ($orderListByOfficialCode === 'true') {
1598
            $order_clause = " ORDER BY u.official_code, u.firstname, u.lastname";
1599
        }
1600
1601
        $group_id = intval($groupInfo['id']);
1602
        $course_id = api_get_course_int_id();
1603
1604
        $sql = "SELECT tg.id, u.user_id, u.lastname, u.firstname, u.email
1605
                FROM $table_user u, $table_group_tutor tg
1606
                WHERE
1607
                    tg.c_id = $course_id AND
1608
                    tg.group_id = $group_id AND
1609
                    tg.user_id = u.user_id 
1610
                $order_clause
1611
                ";
1612
        $db_result = Database::query($sql);
1613
        $users = array();
1614
        while ($user = Database::fetch_object($db_result)) {
1615
            if (!$id_only) {
1616
                $member['user_id'] = $user->user_id;
1617
                $member['firstname'] = $user->firstname;
1618
                $member['lastname'] = $user->lastname;
1619
                $member['email'] = $user->email;
1620
                $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...
1621
            } else {
1622
                $users[] = $user->user_id;
1623
            }
1624
        }
1625
1626
        return $users;
1627
    }
1628
1629
    /**
1630
     * Subscribe user(s) to a specified group in current course (as a student)
1631
     * @param mixed $user_ids Can be an array with user-id's or a single user-id
1632
     * @param array $groupInfo
1633
     * @param int $course_id
1634
     * @return bool TRUE if successful
1635
     */
1636
    public static function subscribe_users($user_ids, $groupInfo, $course_id = null)
1637
    {
1638
        $user_ids = is_array($user_ids) ? $user_ids : array($user_ids);
1639
        $course_id = empty($course_id) ? api_get_course_int_id() : (int) $course_id;
1640
        $group_id = $groupInfo['id'];
1641
1642
        $table = Database::get_course_table(TABLE_GROUP_USER);
1643
        if (!empty($user_ids)) {
1644
            foreach ($user_ids as $user_id) {
1645
                if (self::canUserSubscribe($user_id, $groupInfo)) {
1646
                    $user_id = intval($user_id);
1647
                    $sql = "INSERT INTO ".$table." (c_id, user_id, group_id)
1648
                            VALUES ('$course_id', '".$user_id."', '".$group_id."')";
1649
                    Database::query($sql);
1650
                }
1651
            }
1652
        }
1653
1654
        return true;
1655
    }
1656
1657
    /**
1658
     * Subscribe tutor(s) to a specified group in current course
1659
     * @param mixed $user_ids Can be an array with user-id's or a single user-id
1660
     * @param array $groupInfo
1661
     * @param int $course_id
1662
     *
1663
     * @author Patrick Cool <[email protected]>, Ghent University
1664
     * @see subscribe_users. This function is almost an exact copy of that function.
1665
     * @return bool TRUE if successful
1666
     */
1667
    public static function subscribe_tutors($user_ids, $groupInfo, $course_id = 0)
1668
    {
1669
        $user_ids = is_array($user_ids) ? $user_ids : array($user_ids);
1670
        $result = true;
1671
        $course_id = isset($course_id) && !empty($course_id) ? intval($course_id) : api_get_course_int_id();
1672
        $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1673
        $groupId = (int) $groupInfo['id'];
1674
1675
        foreach ($user_ids as $user_id) {
1676
            $user_id = intval($user_id);
1677
            if (self::canUserSubscribe($user_id, $groupInfo, false)) {
1678
                $sql = "INSERT INTO ".$table_group_tutor." (c_id, user_id, group_id)
1679
                        VALUES ('$course_id', '".$user_id."', '".$groupId."')";
1680
                $result = Database::query($sql);
1681
            }
1682
        }
1683
1684
        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...
1685
    }
1686
1687
    /**
1688
     * Unsubscribe user(s) from a specified group in current course
1689
     * @param mixed $user_ids Can be an array with user-id's or a single user-id
1690
     * @param array $groupInfo
1691
     * @return bool TRUE if successful
1692
     */
1693
    public static function unsubscribe_users($user_ids, $groupInfo)
1694
    {
1695
        $user_ids = is_array($user_ids) ? $user_ids : array($user_ids);
1696
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1697
        $group_id = intval($groupInfo['id']);
1698
        $course_id = api_get_course_int_id();
1699
        $sql = 'DELETE FROM '.$table_group_user.'
1700
                WHERE
1701
                    c_id = '.$course_id.' AND
1702
                    group_id = '.$group_id.' AND
1703
                    user_id IN ('.implode(',', $user_ids).')
1704
                ';
1705
        Database::query($sql);
1706
    }
1707
1708
    /**
1709
     * Unsubscribe all users from one or more groups
1710
     * @param array $groupInfo
1711
     * @return bool TRUE if successful
1712
     */
1713
    public static function unsubscribe_all_users($groupInfo)
1714
    {
1715
        $course_id = api_get_course_int_id();
1716
        $groupId = (int) $groupInfo['id'];
1717
        if (empty($course_id) || empty($groupId)) {
1718
            return false;
1719
        }
1720
1721
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1722
        $sql = "DELETE FROM $table_group_user
1723
                WHERE 
1724
                    group_id = $groupId AND 
1725
                    c_id = $course_id";
1726
        $result = Database::query($sql);
1727
1728
        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...
1729
    }
1730
1731
    /**
1732
     * Unsubscribe all tutors from one or more groups
1733
     * @param int $groupId iid
1734
     * @see unsubscribe_all_users. This function is almost an exact copy of that function.
1735
     * @return bool TRUE if successful
1736
     * @author Patrick Cool <[email protected]>, Ghent University
1737
     */
1738
    public static function unsubscribe_all_tutors($groupId)
1739
    {
1740
        $courseId = api_get_course_int_id();
1741
        $groupId = (int) $groupId;
1742
1743
        if (empty($courseId) || empty($groupId)) {
1744
            return false;
1745
        }
1746
1747
        if (!empty($groupId) > 0) {
1748
            $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1749
            $sql = "DELETE FROM $table_group_tutor
1750
                    WHERE group_id = $groupId AND c_id = $courseId";
1751
            $result = Database::query($sql);
1752
            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...
1753
        }
1754
        return true;
1755
    }
1756
1757
    /**
1758
     * Is the user a tutor of this group?
1759
     * @param int $user_id the id of the user
1760
     * @param array $groupInfo
1761
     * @param int $courseId
1762
     * @return boolean true/false
1763
     * @todo use the function user_has_access that includes this function
1764
     * @author Patrick Cool <[email protected]>, Ghent University
1765
     */
1766
    public static function is_tutor_of_group($user_id, $groupInfo, $courseId = 0)
1767
    {
1768
        if (empty($groupInfo)) {
1769
            return false;
1770
        }
1771
1772
        $courseId = empty($courseId) ? api_get_course_int_id() : (int) $courseId;
1773
        if (empty($courseId)) {
1774
            return false;
1775
        }
1776
1777
        $user_id = intval($user_id);
1778
        $group_id = intval($groupInfo['id']);
1779
1780
        $table = Database::get_course_table(TABLE_GROUP_TUTOR);
1781
1782
        $sql = "SELECT * FROM $table
1783
                WHERE 
1784
                    c_id = $courseId AND 
1785
                    user_id = $user_id AND 
1786
                    group_id = $group_id";
1787
        $result = Database::query($sql);
1788
        if (Database::num_rows($result) > 0) {
1789
            return true;
1790
        } else {
1791
            return false;
1792
        }
1793
    }
1794
1795
    /**
1796
     * Is the user part of this group? This can be a tutor or a normal member
1797
     * you should use this function if the access to a tool or functionality is
1798
     * restricted to the people who are actually in the group
1799
     * before you had to check if the user was
1800
     * 1. a member of the group OR
1801
     * 2. a tutor of the group. This function combines both
1802
     * @param int $user_id the id of the user
1803
     * @param array $groupInfo
1804
     * @return boolean true/false
1805
     * @author Patrick Cool <[email protected]>, Ghent University
1806
     */
1807
    public static function is_user_in_group($user_id, $groupInfo)
1808
    {
1809
        $member = self::is_subscribed($user_id, $groupInfo);
1810
        $tutor = self::is_tutor_of_group($user_id, $groupInfo);
1811
        if ($member || $tutor) {
1812
            return true;
1813
        } else {
1814
            return false;
1815
        }
1816
    }
1817
1818
    /**
1819
     * Get all group's from a given course in which a given user is unsubscribed
1820
     * @author  Patrick Cool
1821
     * @param int  $course_id retrieve the groups for
1822
     * @param int $user_id the ID of the user you want to know all its group memberships
1823
     * @return array
1824
     */
1825
    public static function get_group_ids($course_id, $user_id)
1826
    {
1827
        $groups = array();
1828
        $tbl_group = Database::get_course_table(TABLE_GROUP_USER);
1829
        $tbl_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1830
        $user_id = intval($user_id);
1831
        $course_id = intval($course_id);
1832
1833
        $sql = "SELECT group_id FROM $tbl_group
1834
                WHERE c_id = $course_id AND user_id = '$user_id'";
1835
        $result = Database::query($sql);
1836
1837
        if ($result) {
1838
            while ($row = Database::fetch_array($result)) {
1839
                $groups[] = $row['group_id'];
1840
            }
1841
        }
1842
1843
        //Also loading if i'm the tutor
1844
        $sql = "SELECT group_id FROM $tbl_group_tutor
1845
                WHERE c_id = $course_id AND user_id = '$user_id'";
1846
        $result = Database::query($sql);
1847
        if ($result) {
1848
            while ($row = Database::fetch_array($result)) {
1849
                $groups[] = $row['group_id'];
1850
            }
1851
        }
1852
        if (!empty($groups)) {
1853
            array_filter($groups);
1854
        }
1855
1856
        return $groups;
1857
    }
1858
1859
    /**
1860
     * Remove all users that are not students and all users who have tutor status
1861
     * from  the list.
1862
     * @param array $user_array_in
1863
     * @return array
1864
     */
1865
    public static function filter_only_students($user_array_in)
1866
    {
1867
        $user_array_out = array();
1868
        foreach ($user_array_in as $this_user) {
1869
            if (api_get_session_id()) {
1870
                if ($this_user['status_session'] == 0) {
1871
                    $user_array_out[] = $this_user;
1872
                }
1873
            } else {
1874
                if ($this_user['status_rel'] == STUDENT) {
1875
                    $user_array_out[] = $this_user;
1876
                }
1877
            }
1878
        }
1879
        return $user_array_out;
1880
    }
1881
1882
    /**
1883
     * Check if a user has access to a certain group tool
1884
     * @param int $user_id The user id
1885
     * @param int $group_id The group iid
1886
     * @param string $tool The tool to check the access rights. This should be
1887
     * one of constants: GROUP_TOOL_DOCUMENTS
1888
     * @return bool True if the given user has access to the given tool in the
1889
     * given course.
1890
     */
1891
    public static function user_has_access($user_id, $group_id, $tool)
1892
    {
1893
        // Admin have access everywhere
1894
        if (api_is_platform_admin()) {
1895
            return true;
1896
        }
1897
1898
        // Course admin also have access to everything
1899
        if (api_is_allowed_to_edit()) {
1900
            return true;
1901
        }
1902
1903
        switch ($tool) {
1904
            case self::GROUP_TOOL_FORUM:
1905
                $key = 'forum_state';
1906
                break;
1907
            case self::GROUP_TOOL_DOCUMENTS:
1908
                $key = 'doc_state';
1909
                break;
1910
            case self::GROUP_TOOL_CALENDAR:
1911
                $key = 'calendar_state';
1912
                break;
1913
            case self::GROUP_TOOL_ANNOUNCEMENT:
1914
                $key = 'announcements_state';
1915
                break;
1916
            case self::GROUP_TOOL_WORK:
1917
                $key = 'work_state';
1918
                break;
1919
            case self::GROUP_TOOL_WIKI:
1920
                $key = 'wiki_state';
1921
                break;
1922
            case self::GROUP_TOOL_CHAT:
1923
                $key = 'chat_state';
1924
                break;
1925
            default:
1926
                return false;
1927
        }
1928
1929
        // Check group properties
1930
        $groupInfo = self::get_group_properties($group_id, true);
1931
1932
        if (empty($groupInfo)) {
1933
            return false;
1934
        }
1935
1936
        if ($groupInfo['status'] == 0) {
1937
            return false;
1938
        }
1939
1940
        if (!isset($groupInfo[$key])) {
1941
            return false;
1942
        }
1943
1944
        if (api_is_allowed_to_edit(false, true)) {
1945
            return true;
1946
        }
1947
1948
        $status = $groupInfo[$key];
1949
1950
        switch ($status) {
1951
            case self::TOOL_NOT_AVAILABLE:
1952
                return false;
1953
                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...
1954
            case self::TOOL_PUBLIC:
1955
                return true;
1956
                break;
1957
            case self::TOOL_PRIVATE:
1958
                $userIsInGroup = self::is_user_in_group($user_id, $groupInfo);
1959
                if ($userIsInGroup) {
1960
                    return true;
1961
                }
1962
                break;
1963
        }
1964
1965
        return false;
1966
    }
1967
1968
    /**
1969
     * @param int $userId
1970
     * @param array $groupInfo
1971
     * @param int $sessionId
1972
     *
1973
     * @return bool
1974
     */
1975
    public static function userHasAccessToBrowse($userId, $groupInfo, $sessionId = 0)
1976
    {
1977
        if (empty($groupInfo)) {
1978
            return false;
1979
        }
1980
1981
        if (api_is_platform_admin()) {
1982
            return true;
1983
        }
1984
1985
        if (api_is_allowed_to_edit(false, true)) {
1986
            return true;
1987
        }
1988
1989
        $groupId = $groupInfo['iid'];
1990
        $tutors = self::get_subscribed_tutors($groupInfo, true);
1991
1992
        if (in_array($userId, $tutors)) {
1993
            return true;
1994
        }
1995
1996
        if ($groupInfo['status'] == 0) {
1997
            return false;
1998
        }
1999
2000
        if (self::user_has_access($userId, $groupId, self::GROUP_TOOL_FORUM) ||
2001
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_DOCUMENTS) ||
2002
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_CALENDAR) ||
2003
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_ANNOUNCEMENT) ||
2004
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_WORK) ||
2005
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_WIKI) ||
2006
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_CHAT)
2007
        ) {
2008
            return true;
2009
        }
2010
2011
        if (api_is_session_general_coach() && $groupInfo['session_id'] == $sessionId) {
2012
            return true;
2013
        }
2014
2015
        return false;
2016
    }
2017
2018
2019
    /**
2020
     * Get all groups where a specific user is subscribed
2021
     * @param int $user_id
2022
     * @return array
2023
     */
2024
    public static function get_user_group_name($user_id)
2025
    {
2026
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
2027
        $table_group = Database::get_course_table(TABLE_GROUP);
2028
        $user_id = intval($user_id);
2029
        $course_id = api_get_course_int_id();
2030
        $sql = "SELECT name
2031
                FROM $table_group g 
2032
                INNER JOIN $table_group_user gu
2033
                ON (gu.group_id = g.iid)
2034
                WHERE
2035
                  gu.c_id= $course_id AND
2036
                  g.c_id= $course_id AND
2037
                  gu.user_id = $user_id";
2038
        $res = Database::query($sql);
2039
        $groups = array();
2040
        while ($group = Database::fetch_array($res)) {
2041
            $groups[] .= $group['name'];
2042
        }
2043
        return $groups;
2044
    }
2045
2046
    /**
2047
     * Get all groups where a specific user is subscribed
2048
     * @param int $user_id
2049
     * @return array
2050
     */
2051
    public static function getAllGroupPerUserSubscription($user_id)
2052
    {
2053
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
2054
        $table_tutor_user = Database::get_course_table(TABLE_GROUP_TUTOR);
2055
        $table_group = Database::get_course_table(TABLE_GROUP);
2056
        $user_id = intval($user_id);
2057
        $course_id = api_get_course_int_id();
2058
        $sql = "SELECT DISTINCT g.*
2059
               FROM $table_group g
2060
               LEFT JOIN $table_group_user gu
2061
               ON (gu.group_id = g.iid AND g.c_id = gu.c_id)
2062
               LEFT JOIN $table_tutor_user tu
2063
               ON (tu.group_id = g.iid AND g.c_id = tu.c_id)
2064
               WHERE
2065
                  g.c_id = $course_id AND
2066
                  (gu.user_id = $user_id OR tu.user_id = $user_id) ";
2067
        $res = Database::query($sql);
2068
        $groups = array();
2069
        while ($group = Database::fetch_array($res, 'ASSOC')) {
2070
            $groups[] = $group;
2071
        }
2072
2073
        return $groups;
2074
    }
2075
2076
    /**
2077
     * @param array $userList
2078
     * @param array $groupInfo
2079
     * @return mixed
2080
     */
2081
    public static function getNumberLeftFromGroupFromUserList($userList, $groupInfo)
2082
    {
2083
        $groupIid = (int) $groupInfo['iid'];
2084
        $category = self::get_category_from_group($groupIid);
2085
        $number_groups_per_user = $groupInfo['maximum_number_of_students'];
2086
        $categoryId = 0;
2087
        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...
2088
            $groups_per_user = $category['groups_per_user'];
2089
            $number_groups_per_user = $groups_per_user == self::GROUP_PER_MEMBER_NO_LIMIT ? self::INFINITE : $groups_per_user;
2090
            $categoryId = $category['id'];
2091
        }
2092
2093
        $usersAdded = [];
2094
        foreach ($userList as &$userInfo) {
2095
            // find # of groups the user is enrolled in
2096
            $numberOfGroups = self::user_in_number_of_groups(
2097
                $userInfo['user_id'],
2098
                $categoryId
2099
            );
2100
2101
            if (in_array($userInfo['user_id'], $usersAdded)) {
2102
                continue;
2103
            }
2104
2105
            $usersAdded[] = $userInfo['user_id'];
2106
2107
            // add # of groups to user list
2108
            $userInfo['number_groups_left'] = $number_groups_per_user - $numberOfGroups;
2109
        }
2110
2111
        return $userList;
2112
    }
2113
2114
    /**
2115
     * @param array $group_list
2116
     * @param int $category_id
2117
     *
2118
     * @return string
2119
     */
2120
    public static function process_groups($group_list, $category_id = 0)
2121
    {
2122
        global $charset;
2123
        $category_id = (int) $category_id;
2124
        $totalRegistered = 0;
2125
        $group_data = array();
2126
        $user_info = api_get_user_info();
2127
        $session_id = api_get_session_id();
2128
        $user_id = $user_info['user_id'];
2129
        $hideGroup = api_get_setting('hide_course_group_if_no_tools_available');
2130
2131
        foreach ($group_list as $this_group) {
2132
            // Validation when belongs to a session
2133
            $session_img = api_get_session_image($this_group['session_id'], $user_info['status']);
2134
2135
            // All the tutors of this group
2136
            $tutorsids_of_group = self::get_subscribed_tutors($this_group, true);
2137
            $isMember = self::is_subscribed($user_id, $this_group);
2138
2139
            // Create a new table-row
2140
            $row = [];
2141
            // Checkbox
2142
            if (api_is_allowed_to_edit(false, true) && count($group_list) > 1) {
2143
                $row[] = $this_group['id'];
2144
            }
2145
2146
            if (self::userHasAccessToBrowse($user_id, $this_group, $session_id)) {
2147
                // Group name
2148
                $groupNameClass = null;
2149
                if ($this_group['status'] == 0) {
2150
                    $groupNameClass = 'muted';
2151
                }
2152
2153
                $group_name = '<a class="'.$groupNameClass.'" href="group_space.php?'.api_get_cidreq(true, false).'&gidReq='.$this_group['id'].'">'.
2154
                    Security::remove_XSS($this_group['name']).'</a> ';
2155
                if (!empty($user_id) && !empty($this_group['id_tutor']) && $user_id == $this_group['id_tutor']) {
2156
                    $group_name .= Display::label(get_lang('OneMyGroups'), 'success');
2157
                } elseif ($isMember) {
2158
                    $group_name .= Display::label(get_lang('MyGroup'), 'success');
2159
                }
2160
2161
                if (api_is_allowed_to_edit() && !empty($this_group['session_name'])) {
2162
                    $group_name .= ' ('.$this_group['session_name'].')';
2163
                }
2164
                $group_name .= $session_img;
2165
                $row[] = $group_name.'<br />'.stripslashes(trim($this_group['description']));
2166
            } else {
2167
                if ($hideGroup === 'true') {
2168
                    continue;
2169
                }
2170
                $row[] = $this_group['name'].'<br />'.stripslashes(trim($this_group['description']));
2171
            }
2172
2173
            // Tutor name
2174
            $tutor_info = '';
2175
            if (count($tutorsids_of_group) > 0) {
2176
                foreach ($tutorsids_of_group as $tutor_id) {
2177
                    $tutor = api_get_user_info($tutor_id);
2178
                    $username = api_htmlentities(
2179
                        sprintf(get_lang('LoginX'), $tutor['username']),
2180
                        ENT_QUOTES
2181
                    );
2182
                    if (api_get_setting('show_email_addresses') === 'true') {
2183
                        $tutor_info .= Display::tag(
2184
                            'span',
2185
                            Display::encrypted_mailto_link(
2186
                                $tutor['mail'],
2187
                                $tutor['complete_name']
2188
                            ),
2189
                            array('title' => $username)
2190
                        ).', ';
2191
                    } else {
2192
                        if (api_is_allowed_to_edit()) {
2193
                            $tutor_info .= Display::tag(
2194
                            'span',
2195
                                Display::encrypted_mailto_link(
2196
                                    $tutor['mail'],
2197
                                    $tutor['complete_name_with_username']
2198
                                ),
2199
                                array('title'=>$username)
2200
                            ).', ';
2201
                        } else {
2202
                            $tutor_info .= Display::tag(
2203
                                'span',
2204
                                $tutor['complete_name'],
2205
                                array('title' => $username)
2206
                            ).', ';
2207
                        }
2208
                    }
2209
                }
2210
            }
2211
2212
            $tutor_info = api_substr(
2213
                $tutor_info,
2214
                0,
2215
                api_strlen($tutor_info) - 2
2216
            );
2217
            $row[] = $tutor_info;
2218
2219
            // Max number of members in group
2220
            $max_members = $this_group['maximum_number_of_members'] == self::MEMBER_PER_GROUP_NO_LIMIT ? ' ' : ' / '.$this_group['maximum_number_of_members'];
2221
2222
            // Number of members in group
2223
            $row[] = $this_group['number_of_members'].$max_members;
2224
2225
            // Self-registration / unregistration
2226
            if (!api_is_allowed_to_edit(false, true)) {
2227
                if (self::is_self_registration_allowed($user_id, $this_group)) {
2228
                    $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>';
2229
                } elseif (self::is_self_unregistration_allowed($user_id, $this_group)) {
2230
                    $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>';
2231
                } else {
2232
                    $row[] = '-';
2233
                }
2234
            }
2235
2236
            $url = api_get_path(WEB_CODE_PATH).'group/';
2237
            // Edit-links
2238
            if (api_is_allowed_to_edit(false, true) &&
2239
                !(api_is_session_general_coach() && intval($this_group['session_id']) != $session_id)
2240
            ) {
2241
                $edit_actions = '<a href="'.$url.'settings.php?'.api_get_cidreq(true, false).'&gidReq='.$this_group['id'].'"  title="'.get_lang('Edit').'">'.
2242
                    Display::return_icon('edit.png', get_lang('EditGroup'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2243
2244
                if ($this_group['status'] == 1) {
2245
                    $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').'">'.
2246
                        Display::return_icon('visible.png', get_lang('Hide'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2247
                } else {
2248
                    $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').'">'.
2249
                        Display::return_icon('invisible.png', get_lang('Show'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2250
                }
2251
2252
                $edit_actions .= '<a href="'.$url.'member_settings.php?'.api_get_cidreq(true, false).'&gidReq='.$this_group['id'].'"  title="'.get_lang('GroupMembers').'">'.
2253
                    Display::return_icon('user.png', get_lang('GroupMembers'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2254
2255
                $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').'">'.
2256
                    Display::return_icon('export_excel.png', get_lang('Export'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2257
2258
                $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').'">'.
2259
                    Display::return_icon('fill.png', get_lang('FillGroup'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2260
2261
                $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').'">'.
2262
                    Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2263
2264
                $row[] = $edit_actions;
2265
            }
2266
            if (!empty($this_group['nbMember'])) {
2267
                $totalRegistered = $totalRegistered + $this_group['nbMember'];
2268
            }
2269
            $group_data[] = $row;
2270
        } // end loop
2271
2272
        // If no groups then don't show the table (only for students)
2273
        if (!api_is_allowed_to_edit(true, false)) {
2274
            if (empty($group_data)) {
2275
                return '';
2276
            }
2277
        }
2278
2279
        $table = new SortableTableFromArrayConfig(
2280
            $group_data,
2281
            1,
2282
            20,
2283
            'group_category_'.$category_id
2284
        );
2285
        $table->set_additional_parameters(array('category' => $category_id));
2286
        $column = 0;
2287
        if (api_is_allowed_to_edit(false, true) and count($group_list) > 1) {
2288
            $table->set_header($column++, '', false);
2289
        }
2290
        $table->set_header($column++, get_lang('Groups'));
2291
        $table->set_header($column++, get_lang('GroupTutor'));
2292
        $table->set_header($column++, get_lang('Registered'), false);
2293
2294
        if (!api_is_allowed_to_edit(false, true)) {
2295
            // If self-registration allowed
2296
            $table->set_header($column++, get_lang('GroupSelfRegistration'), false);
2297
        }
2298
2299
        if (api_is_allowed_to_edit(false, true)) {
2300
            // Only for course administrator
2301
            $table->set_header($column++, get_lang('Modify'), false);
2302
            $form_actions = array();
2303
            $form_actions['fill_selected'] = get_lang('FillGroup');
2304
            $form_actions['empty_selected'] = get_lang('EmptyGroup');
2305
            $form_actions['delete_selected'] = get_lang('Delete');
2306
            if (count($group_list) > 1) {
2307
                $table->set_form_actions($form_actions, 'group');
2308
            }
2309
        }
2310
2311
        return $table->return_table();
2312
    }
2313
2314
    /**
2315
     * @param array $groupData
2316
     * @param bool $deleteNotInArray
2317
     * @return array
2318
     */
2319
    public static function importCategoriesAndGroupsFromArray(
2320
        $groupData,
2321
        $deleteNotInArray = false
2322
    ) {
2323
        $result = array();
2324
        $elementsFound = array(
2325
            'categories' => array(),
2326
            'groups' => array()
2327
        );
2328
2329
        $courseCode = api_get_course_id();
2330
        $sessionId = api_get_session_id();
2331
        $groupCategories = self::get_categories();
2332
2333
        if (empty($groupCategories)) {
2334
            $result['error'][] = get_lang('CreateACategory');
2335
            return $result;
2336
        }
2337
2338
        foreach ($groupData as $data) {
2339
            $isCategory = empty($data['group']) ? true : false;
2340
            if ($isCategory) {
2341
                $categoryInfo = self::getCategoryByTitle($data['category']);
2342
                $categoryId = $categoryInfo['id'];
2343
2344
                if (!empty($categoryInfo)) {
2345
                    // Update
2346
                    self::update_category(
2347
                        $categoryId,
2348
                        $data['category'],
2349
                        $data['description'],
2350
                        $data['doc_state'],
2351
                        $data['work_state'],
2352
                        $data['calendar_state'],
2353
                        $data['announcements_state'],
2354
                        $data['forum_state'],
2355
                        $data['wiki_state'],
2356
                        $data['chat_state'],
2357
                        $data['self_reg_allowed'],
2358
                        $data['self_unreg_allowed'],
2359
                        $data['max_student'],
2360
                        $data['groups_per_user']
2361
                    );
2362
                    $data['category_id'] = $categoryId;
2363
                    $result['updated']['category'][] = $data;
2364
                } else {
2365
                    // Add
2366
                    $categoryId = self::create_category(
2367
                        $data['category'],
2368
                        $data['description'],
2369
                        $data['doc_state'],
2370
                        $data['work_state'],
2371
                        $data['calendar_state'],
2372
                        $data['announcements_state'],
2373
                        $data['forum_state'],
2374
                        $data['wiki_state'],
2375
                        $data['chat_state'],
2376
                        $data['self_reg_allowed'],
2377
                        $data['self_unreg_allowed'],
2378
                        $data['max_student'],
2379
                        $data['groups_per_user']
2380
                    );
2381
2382
                    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...
2383
                        $data['category_id'] = $categoryId;
2384
                        $result['added']['category'][] = $data;
2385
                    }
2386
                }
2387
                $elementsFound['categories'][] = $categoryId;
2388
            } else {
2389
                $groupInfo = self::getGroupByName($data['group']);
2390
                $categoryInfo = [];
2391
                if (isset($data['category'])) {
2392
                    $categoryInfo = self::getCategoryByTitle($data['category']);
2393
                }
2394
                $categoryId = null;
2395
                if (!empty($categoryInfo)) {
2396
                    $categoryId = $categoryInfo['id'];
2397
                } else {
2398
                    if (!empty($groupCategories) && isset($groupCategories[0])) {
2399
                        $defaultGroupCategory = $groupCategories[0];
2400
                        $categoryId = $defaultGroupCategory['id'];
2401
                    }
2402
                }
2403
2404
                if (empty($groupInfo)) {
2405
                    // Add
2406
                    $groupId = self::create_group(
2407
                        $data['group'],
2408
                        $categoryId,
2409
                        null,
2410
                        $data['max_student']
2411
                    );
2412
2413
                    if ($groupId) {
2414
                        self::set_group_properties(
2415
                            $groupId,
2416
                            $data['group'],
2417
                            $data['description'],
2418
                            $data['max_student'],
2419
                            $data['doc_state'],
2420
                            $data['work_state'],
2421
                            $data['calendar_state'],
2422
                            $data['announcements_state'],
2423
                            $data['forum_state'],
2424
                            $data['wiki_state'],
2425
                            $data['chat_state'],
2426
                            $data['self_reg_allowed'],
2427
                            $data['self_unreg_allowed'],
2428
                            $categoryId
2429
                        );
2430
                        $data['group_id'] = $groupId;
2431
                        $result['added']['group'][] = $data;
2432
                    }
2433
                    $groupInfo = self::get_group_properties($groupId, true);
2434
                } else {
2435
                    // Update
2436
                    $groupId = $groupInfo['id'];
2437
                    self::set_group_properties(
2438
                        $groupId,
2439
                        $data['group'],
2440
                        $data['description'],
2441
                        $data['max_student'],
2442
                        $data['doc_state'],
2443
                        $data['work_state'],
2444
                        $data['calendar_state'],
2445
                        $data['announcements_state'],
2446
                        $data['forum_state'],
2447
                        $data['wiki_state'],
2448
                        $data['chat_state'],
2449
                        $data['self_reg_allowed'],
2450
                        $data['self_unreg_allowed'],
2451
                        $categoryId
2452
                    );
2453
2454
                    $data['group_id'] = $groupId;
2455
                    $result['updated']['group'][] = $data;
2456
                    $groupInfo = self::get_group_properties($groupId);
2457
                }
2458
2459
                $students = isset($data['students']) ? explode(',', $data['students']) : [];
2460
                if (!empty($students)) {
2461
                    $studentUserIdList = array();
2462
                    foreach ($students as $student) {
2463
                        $userInfo = api_get_user_info_from_username($student);
2464
2465
                        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...
2466
                            continue;
2467
                        }
2468
2469
                        if (!CourseManager::is_user_subscribed_in_course(
2470
                                $userInfo['user_id'],
2471
                                $courseCode,
2472
                                !empty($sessionId),
2473
                                $sessionId
2474
                            )
2475
                        ) {
2476
                            Display::addFlash(
2477
                                Display::return_message(
2478
                                    sprintf(
2479
                                        get_lang('StudentXIsNotSubscribedToCourse'),
2480
                                        $userInfo['complete_name']
2481
                                    ),
2482
                                    'warning'
2483
                                )
2484
                            );
2485
                            continue;
2486
                        }
2487
2488
                        $studentUserIdList[] = $userInfo['user_id'];
2489
                    }
2490
                    self::subscribe_users($studentUserIdList, $groupInfo);
2491
                }
2492
2493
                $tutors = isset($data['tutors']) ? explode(',', $data['tutors']) : [];
2494
                if (!empty($tutors)) {
2495
                    $tutorIdList = array();
2496
                    foreach ($tutors as $tutor) {
2497
                        $userInfo = api_get_user_info_from_username($tutor);
2498
2499
                        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...
2500
                            continue;
2501
                        }
2502
2503
                        if (!CourseManager::is_user_subscribed_in_course(
2504
                                $userInfo['user_id'],
2505
                                $courseCode,
2506
                                !empty($sessionId),
2507
                                $sessionId
2508
                            )
2509
                        ) {
2510
                            Display::addFlash(
2511
                                Display::return_message(
2512
                                    sprintf(get_lang('TutorXIsNotSubscribedToCourse'), $userInfo['complete_name']),
2513
                                    'warning'
2514
                                )
2515
                            );
2516
2517
                            continue;
2518
                        }
2519
2520
                        $tutorIdList[] = $userInfo['user_id'];
2521
                    }
2522
                    self::subscribe_tutors($tutorIdList, $groupInfo);
2523
                }
2524
2525
                $elementsFound['groups'][] = $groupId;
2526
            }
2527
        }
2528
2529
        if ($deleteNotInArray) {
2530
            // Check categories
2531
            $categories = self::get_categories();
2532
            foreach ($categories as $category) {
2533
                if (!in_array($category['id'], $elementsFound['categories'])) {
2534
                    self::delete_category($category['id']);
2535
                    $category['category'] = $category['title'];
2536
                    $result['deleted']['category'][] = $category;
2537
                }
2538
            }
2539
2540
            $groups = self::get_groups();
2541
            foreach ($groups as $group) {
2542
                if (!in_array($group['iid'], $elementsFound['groups'])) {
2543
                    self::delete_groups($group);
2544
                    $group['group'] = $group['name'];
2545
                    $result['deleted']['group'][] = $group;
2546
                }
2547
            }
2548
        }
2549
2550
        return $result;
2551
    }
2552
2553
    /**
2554
     * Export all categories/group from a course to an array.
2555
     * This function works only in a context of a course.
2556
     * @param int $groupId
2557
     * @param bool $loadUsers
2558
     * @return array
2559
     */
2560
    public static function exportCategoriesAndGroupsToArray($groupId = null, $loadUsers = false)
2561
    {
2562
        $data = array();
2563
        $data[] = array(
2564
            'category',
2565
            'group',
2566
            'description',
2567
            'announcements_state',
2568
            'calendar_state',
2569
            'chat_state',
2570
            'doc_state',
2571
            'forum_state',
2572
            'work_state',
2573
            'wiki_state',
2574
            'max_student',
2575
            'self_reg_allowed',
2576
            'self_unreg_allowed',
2577
            'groups_per_user'
2578
        );
2579
2580
        $count = 1;
2581
2582
        if ($loadUsers) {
2583
            $data[0][] = 'students';
2584
            $data[0][] = 'tutors';
2585
        }
2586
2587
        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...
2588
            $categories = self::get_categories();
2589
2590
            foreach ($categories as $categoryInfo) {
2591
                $data[$count] = array(
2592
                    $categoryInfo['title'],
2593
                    null,
2594
                    $categoryInfo['description'],
2595
                    $categoryInfo['announcements_state'],
2596
                    $categoryInfo['calendar_state'],
2597
                    $categoryInfo['chat_state'],
2598
                    $categoryInfo['doc_state'],
2599
                    $categoryInfo['forum_state'],
2600
                    $categoryInfo['work_state'],
2601
                    $categoryInfo['wiki_state'],
2602
                    $categoryInfo['max_student'],
2603
                    $categoryInfo['self_reg_allowed'],
2604
                    $categoryInfo['self_unreg_allowed'],
2605
                    $categoryInfo['groups_per_user']
2606
                );
2607
                $count++;
2608
            }
2609
        }
2610
2611
        $groups = self::get_group_list();
2612
2613
        foreach ($groups as $groupInfo) {
2614
            $categoryTitle = null;
2615
            $categoryInfo = self::get_category($groupInfo['category_id']);
2616
            $groupSettings = self::get_group_properties($groupInfo['id']);
2617
            if (!empty($categoryInfo)) {
2618
                $categoryTitle = $categoryInfo['title'];
2619
            }
2620
2621
            $users = self::getStudents($groupInfo['iid']);
2622
            $userList = array();
2623
            foreach ($users as $user) {
2624
                $user = api_get_user_info($user['user_id']);
2625
                $userList[] = $user['username'];
2626
            }
2627
2628
            $tutors = self::getTutors($groupInfo);
2629
            $tutorList = array();
2630
            foreach ($tutors as $user) {
2631
                $user = api_get_user_info($user['user_id']);
2632
                $tutorList[] = $user['username'];
2633
            }
2634
2635
            $userListToString = null;
2636
            if (!empty($userList)) {
2637
                $userListToString = implode(',', $userList);
2638
            }
2639
2640
            $tutorListToString = null;
2641
            if (!empty($tutorList)) {
2642
                $tutorListToString = implode(',', $tutorList);
2643
            }
2644
2645
            $data[$count] = array(
2646
                $categoryTitle,
2647
                $groupSettings['name'],
2648
                $groupSettings['description'],
2649
                $groupSettings['announcements_state'],
2650
                $groupSettings['calendar_state'],
2651
                $groupSettings['chat_state'],
2652
                $groupSettings['doc_state'],
2653
                $groupSettings['forum_state'],
2654
                $groupSettings['work_state'],
2655
                $groupSettings['wiki_state'],
2656
                $groupSettings['maximum_number_of_students'],
2657
                $groupSettings['self_registration_allowed'],
2658
                $groupSettings['self_unregistration_allowed'],
2659
                null
2660
            );
2661
2662
            if ($loadUsers) {
2663
                $data[$count][] = $userListToString;
2664
                $data[$count][] = $tutorListToString;
2665
            }
2666
2667
            if (!empty($groupId)) {
2668
                if ($groupId == $groupInfo['id']) {
2669
                    break;
2670
                }
2671
            }
2672
            $count++;
2673
        }
2674
2675
        return $data;
2676
    }
2677
2678
    /**
2679
     * @param string $default
2680
     */
2681
    public static function getSettingBar($default)
2682
    {
2683
        $activeSettings = null;
2684
        $activeTutor = null;
2685
        $activeMember = null;
2686
2687
        switch ($default) {
2688
            case 'settings':
2689
                $activeSettings = 'active';
2690
                break;
2691
            case'tutor':
2692
                $activeTutor = 'active';
2693
                break;
2694
            case 'member':
2695
                $activeMember = 'active';
2696
                break;
2697
        }
2698
2699
        $url = api_get_path(WEB_CODE_PATH).'group/%s?'.api_get_cidreq();
2700
2701
        echo '
2702
            <ul class="toolbar-groups nav nav-tabs">
2703
                <li class="'.$activeSettings.'">
2704
                    <a href="'.sprintf($url, 'settings.php').'">
2705
                    '.Display::return_icon('settings.png').' '.get_lang('Settings').'
2706
                    </a>
2707
                </li>
2708
                <li class="'.$activeMember.'">
2709
                    <a href="'.sprintf($url, 'member_settings.php').'">
2710
                    '.Display::return_icon('user.png').' '.get_lang('GroupMembers').'
2711
                    </a>
2712
                </li>
2713
                <li class="'.$activeTutor.'">
2714
                    <a href="'.sprintf($url, 'tutor_settings.php').'">
2715
                    '.Display::return_icon('teacher.png').' '.get_lang('GroupTutors').'
2716
                    </a>
2717
                </li>
2718
            </ul>';
2719
    }
2720
2721
    /**
2722
     * @param int $courseId
2723
     * @param string $keyword
2724
     * @return string
2725
     */
2726
    public static function getOverview($courseId, $keyword = null)
2727
    {
2728
        $content = null;
2729
        $categories = self::get_categories();
2730
        if (!empty($categories)) {
2731
2732
            foreach ($categories as $category) {
2733
                if (api_get_setting('allow_group_categories') == 'true') {
2734
                    $content .= '<h2>'.$category['title'].'</h2>';
2735
                }
2736
                if (!empty($keyword)) {
2737
                    $groups = self::getGroupListFilterByName(
2738
                        $keyword,
2739
                        $category['id'],
2740
                        $courseId
2741
                    );
2742
                } else {
2743
                    $groups = self::get_group_list($category['id']);
2744
                }
2745
2746
                if (empty($groups)) {
2747
                    $groups = self::get_group_list();
2748
                }
2749
2750
                $content .= '<ul>';
2751
                if (!empty($groups)) {
2752
                    foreach ($groups as $group) {
2753
                        $content .= '<li>';
2754
                        $content .= Display::tag(
2755
                            'h3',
2756
                            Security::remove_XSS($group['name'])
2757
                        );
2758
                        $users = self::getTutors($group);
2759
                        if (!empty($users)) {
2760
                            $content .= '<ul>';
2761
                            $content .= "<li>".Display::tag('h4', get_lang('Tutors'))."</li><ul>";
2762
                            foreach ($users as $user) {
2763
                                $user_info = api_get_user_info($user['user_id']);
2764
                                $content .= '<li title="'.$user_info['username'].'">'.
2765
                                    $user_info['complete_name_with_username'].
2766
                                '</li>';
2767
                            }
2768
                            $content .= '</ul>';
2769
                            $content .= '</ul>';
2770
                        }
2771
2772
                        $users = self::getStudents($group['id']);
2773
                        if (!empty($users)) {
2774
                            $content .= '<ul>';
2775
                            $content .= "<li>".Display::tag('h4', get_lang('Students'))."</li><ul>";
2776
                            foreach ($users as $user) {
2777
                                $user_info = api_get_user_info($user['user_id']);
2778
                                $content .= '<li title="'.$user_info['username'].'">'.
2779
                                    $user_info['complete_name_with_username'].
2780
                                    '</li>';
2781
                            }
2782
                            $content .= '</ul>';
2783
                            $content .= '</ul>';
2784
                        }
2785
                        $content .= '</li>';
2786
                    }
2787
                }
2788
                $content .= '</ul>';
2789
            }
2790
        }
2791
2792
        return $content;
2793
    }
2794
2795
    /**
2796
     * Returns the search form
2797
     * @return string
2798
     */
2799
    public static function getSearchForm()
2800
    {
2801
        $url = api_get_path(WEB_CODE_PATH).'group/group_overview.php?'.api_get_cidreq();
2802
        $form = new FormValidator(
2803
            'search_groups',
2804
            'get',
2805
            $url,
2806
            null,
2807
            array('class' => 'form-search'),
2808
            FormValidator::LAYOUT_INLINE
2809
        );
2810
        $form->addElement('text', 'keyword');
2811
        $form->addButtonSearch();
2812
        return $form->toHtml();
2813
    }
2814
2815
    /**
2816
     * @param int $groupId
2817
     * @param int $status
2818
     */
2819
    public static function setStatus($groupId, $status)
2820
    {
2821
        $groupInfo = self::get_group_properties($groupId);
2822
2823
        $courseId = api_get_course_int_id();
2824
        if (!empty($groupInfo)) {
2825
            $table = Database::get_course_table(TABLE_GROUP);
2826
            $params = array(
2827
                'status' => intval($status)
2828
            );
2829
            Database::update(
2830
                $table,
2831
                $params,
2832
                array('c_id = ? AND id = ?' => array($courseId, $groupId))
2833
            );
2834
        }
2835
    }
2836
2837
    /**
2838
     * @param int $groupId
2839
     */
2840
    public static function setVisible($groupId)
2841
    {
2842
        self::setStatus($groupId, 1);
2843
    }
2844
2845
    /**
2846
     * @param int $groupId
2847
     */
2848
    public static function setInvisible($groupId)
2849
    {
2850
        self::setStatus($groupId, 0);
2851
    }
2852
}
2853