Passed
Push — master ( 48aeb9...852133 )
by Julito
09:44
created

GroupManager::deleteGroup()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 70
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 19
nc 4
nop 2
dl 0
loc 70
rs 9.6333
c 0
b 0
f 0

How to fix   Long Method   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\Course;
6
use Chamilo\CoreBundle\Framework\Container;
7
use Chamilo\CourseBundle\Entity\CGroup;
8
use Chamilo\CourseBundle\Entity\CGroupCategory;
9
10
/**
11
 * This library contains some functions for group-management.
12
 *
13
 * @author Bart Mollet
14
 *
15
 * @todo Add $course_code parameter to all functions. So this GroupManager can
16
 * be used outside a session.
17
 */
18
class GroupManager
19
{
20
    /* DEFAULT_GROUP_CATEGORY:
21
    When group categories aren't available (platform-setting),
22
    all groups are created in this 'dummy'-category*/
23
    public const DEFAULT_GROUP_CATEGORY = 2;
24
25
    /**
26
     * infinite.
27
     */
28
    public const INFINITE = 99999;
29
    /**
30
     * No limit on the number of users in a group.
31
     */
32
    public const MEMBER_PER_GROUP_NO_LIMIT = 0;
33
    /**
34
     * No limit on the number of groups per user.
35
     */
36
    public const GROUP_PER_MEMBER_NO_LIMIT = 0;
37
    /**
38
     * The tools of a group can have 3 states
39
     * - not available
40
     * - public
41
     * - private.
42
     */
43
    public const TOOL_NOT_AVAILABLE = 0;
44
    public const TOOL_PUBLIC = 1;
45
    public const TOOL_PRIVATE = 2;
46
    public const TOOL_PRIVATE_BETWEEN_USERS = 3;
47
48
    /**
49
     * Constants for the available group tools.
50
     */
51
    public const GROUP_TOOL_FORUM = 0;
52
    public const GROUP_TOOL_DOCUMENTS = 1;
53
    public const GROUP_TOOL_CALENDAR = 2;
54
    public const GROUP_TOOL_ANNOUNCEMENT = 3;
55
    public const GROUP_TOOL_WORK = 4;
56
    public const GROUP_TOOL_WIKI = 5;
57
    public const GROUP_TOOL_CHAT = 6;
58
59
    public const DOCUMENT_MODE_SHARE = 0; // By default
60
    public const DOCUMENT_MODE_READ_ONLY = 1;
61
    public const DOCUMENT_MODE_COLLABORATION = 2;
62
63
    /**
64
     * GroupManager constructor.
65
     */
66
    public function __construct()
67
    {
68
    }
69
70
    /**
71
     * @param int $courseId
72
     *
73
     * @return array
74
     */
75
    public static function get_groups($courseId = 0)
76
    {
77
        $repo = Container::getGroupRepository();
78
        $course = api_get_course_entity($courseId);
79
80
        $qb = $repo->getResourcesByCourse($course);
81
82
        return $qb->getQuery()->getArrayResult();
83
84
        $table_group = Database::get_course_table(TABLE_GROUP);
0 ignored issues
show
Unused Code introduced by
$table_group = Database:...urse_table(TABLE_GROUP) is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
85
        $courseId = !empty($courseId) ? (int) $courseId : api_get_course_int_id();
86
87
        $sql = "SELECT * FROM $table_group WHERE c_id = $courseId  ";
88
        $result = Database::query($sql);
89
90
        return Database::store_result($result, 'ASSOC');
91
    }
92
93
    /**
94
     * Get list of groups for current course.
95
     *
96
     * @param int   $categoryId  The id of the category from which the groups are
97
     *                           requested
98
     * @param array $course_info Default is current course
99
     * @param int   $status      group status
100
     * @param int   $sessionId
101
     * @param bool  $getCount
102
     * @param bool  $notInGroup  Get groups not in a category
103
     *
104
     * @return array an array with all information about the groups
105
     */
106
    public static function get_group_list(
107
        $categoryId = null,
108
        $course_info = [],
109
        $status = null,
110
        $sessionId = 0,
111
        $getCount = false,
112
        $filterByKeyword = ''
113
    ) {
114
        $course_info = empty($course_info) ? api_get_course_info() : $course_info;
115
116
        if (empty($course_info)) {
117
            return [];
118
        }
119
120
        $sessionId = empty($sessionId) ? api_get_session_id() : (int) $sessionId;
121
        $course_id = $course_info['real_id'];
122
123
        $repo = Container::getGroupRepository();
124
        $course = api_get_course_entity($course_id);
125
        $session = api_get_session_entity($sessionId);
126
        //$group = api_get_group_entity(api_get_group_id());
127
        $group = null;
128
        $qb = $repo->getResourcesByCourse($course, $session, $group);
129
130
        if (null === $categoryId) {
131
            $qb
132
                ->andWhere('resource.category is NULL');
133
        } else {
134
            $qb
135
                ->andWhere('resource.category = :category')
136
                ->setParameter('category', $categoryId);
137
        }
138
139
        if (!empty($filterByKeyword)) {
140
            $qb->andWhere($qb->expr()->like('resource.name', ':keyword'));
141
            $qb->setParameter('keyword', "%$filterByKeyword%");
142
        }
143
144
        if ($getCount) {
145
            $qb->select('count(resource)');
146
147
            return $qb->getQuery()->getSingleScalarResult();
148
        }
149
150
        return $qb->getQuery()->getArrayResult();
151
152
        $table_group = Database::get_course_table(TABLE_GROUP);
0 ignored issues
show
Unused Code introduced by
$table_group = Database:...urse_table(TABLE_GROUP) is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
153
154
        $select = ' g.iid,
155
                    g.name,
156
                    g.description,
157
                    g.category_id,
158
                    g.max_student maximum_number_of_members,
159
                    g.secret_directory,
160
                    g.self_registration_allowed,
161
                    g.self_unregistration_allowed,
162
                    g.status
163
                    ';
164
        if ($getCount) {
165
            $select = ' DISTINCT count(g.iid) as count ';
166
        }
167
168
        $sql = "SELECT
169
                $select
170
                FROM $table_group g
171
                WHERE 1 = 1 ";
172
173
        if (!is_null($categoryId)) {
174
            $sql .= " AND g.category_id = '".intval($categoryId)."' ";
175
            $session_condition = api_get_session_condition($sessionId);
176
            if (!empty($session_condition)) {
177
                //$sql .= $session_condition;
178
            }
179
        } else {
180
            $session_condition = api_get_session_condition($sessionId, true);
181
        }
182
183
        $session_condition = '';
184
185
        if (!is_null($status)) {
186
            $sql .= " AND g.status = '".intval($status)."' ";
187
        }
188
189
        //$sql .= " AND g.c_id = $course_id ";
190
        if ($notInGroup) {
191
            $sql .= "  AND (g.category_id IS NULL OR g.category_id = 0) ";
192
        }
193
194
        if (!empty($session_condition)) {
195
            $sql .= $session_condition;
196
        }
197
        $sql .= ' ORDER BY UPPER(g.name)';
198
199
        $result = Database::query($sql);
200
201
        if ($getCount) {
202
            $row = Database::fetch_array($result);
203
204
            return $row['count'];
205
        }
206
207
        $groups = [];
208
        while ($thisGroup = Database::fetch_array($result)) {
209
            $thisGroup['number_of_members'] = count(self::get_subscribed_users($thisGroup));
210
            if (0 != $thisGroup['session_id']) {
211
                $sql = 'SELECT name FROM '.Database::get_main_table(TABLE_MAIN_SESSION).'
212
                        WHERE id='.$thisGroup['session_id'];
213
                $rs_session = Database::query($sql);
214
                if (Database::num_rows($rs_session) > 0) {
215
                    $thisGroup['session_name'] = Database::result($rs_session, 0, 0);
216
                }
217
            }
218
            $groups[] = $thisGroup;
219
        }
220
221
        return $groups;
222
    }
223
224
    /**
225
     * Create a group.
226
     *
227
     * @param string $name        The name for this group
228
     * @param int    $category_id
229
     * @param int    $tutor       The user-id of the group's tutor
230
     * @param int    $places      How many people can subscribe to the new group
231
     *
232
     * @return int
233
     */
234
    public static function create_group($name, $category_id, $tutor, $places)
235
    {
236
        $_course = api_get_course_info();
237
        $session_id = api_get_session_id();
238
        $course_id = $_course['real_id'];
239
        $category = self::get_category($category_id);
240
        $places = (int) $places;
241
242
        // Default values
243
        $docState = self::TOOL_PRIVATE;
244
        $calendarState = self::TOOL_PRIVATE;
245
        $workState = self::TOOL_PRIVATE;
246
        $anonuncementState = self::TOOL_PRIVATE;
247
        $forumState = self::TOOL_PRIVATE;
248
        $wikiState = self::TOOL_PRIVATE;
249
        $chatState = self::TOOL_PRIVATE;
250
        $selfRegAllowed = 0;
251
        $selfUnregAllwoed = 0;
252
        $documentAccess = 0;
253
254
        if ($category) {
255
            if (0 == $places) {
256
                //if the amount of users per group is not filled in, use the setting from the category
257
                $places = $category['max_student'];
258
            } else {
259
                if ($places > $category['max_student'] && 0 != $category['max_student']) {
260
                    $places = $category['max_student'];
261
                }
262
            }
263
            $docState = $category['doc_state'];
264
            $calendarState = $category['calendar_state'];
265
            $workState = $category['work_state'];
266
            $anonuncementState = $category['announcements_state'];
267
            $forumState = $category['forum_state'];
268
            $wikiState = $category['wiki_state'];
269
            $chatState = $category['chat_state'];
270
            $selfRegAllowed = $category['self_reg_allowed'];
271
            $selfUnregAllwoed = $category['self_unreg_allowed'];
272
            $documentAccess = isset($category['document_access']) ? $category['document_access'] : 0;
273
        }
274
275
        $course = api_get_course_entity($course_id);
276
        $session = api_get_session_entity($session_id);
277
278
        $category = null;
279
        if (!empty($category_id)) {
280
            $category = Container::getGroupCategoryRepository()->find($category_id);
281
        }
282
283
        $group = new CGroup();
284
        $group
285
            ->setName($name)
286
            ->setCategory($category)
287
            ->setMaxStudent($places)
288
            ->setDocState($docState)
289
            ->setCalendarState($calendarState)
290
            ->setWorkState($workState)
291
            ->setForumState($forumState)
292
            ->setWikiState($wikiState)
293
            ->setAnnouncementsState($anonuncementState)
294
            ->setChatState($chatState)
295
            ->setSelfRegistrationAllowed($selfRegAllowed)
296
            ->setSelfUnregistrationAllowed($selfUnregAllwoed)
297
            ->setDocumentAccess($documentAccess)
298
            ->setParent($course)
299
            ->addCourseLink($course, $session)
300
        ;
301
302
        $repo = Container::getGroupRepository();
303
        $repo->create($group);
304
        $lastId = $group->getIid();
305
306
        if ($lastId) {
307
            /*$desired_dir_name = '/'.api_replace_dangerous_char($name).'_groupdocs';
308
309
            $newFolderData = create_unexisting_directory(
310
                $_course,
311
                api_get_user_id(),
312
                $session_id,
313
                $lastId,
314
                null,
315
                null,
316
                    $desired_dir_name,
317
                $desired_dir_name,
318
                1
319
            );*/
320
321
            //$unique_name = $newFolderData->getPath();
322
323
            /* Stores the directory path into the group table */
324
            /*$sql = "UPDATE $table_group SET
325
                        name = '".Database::escape_string($name)."',
326
                        secret_directory = '".$unique_name."'
327
                    WHERE c_id = $course_id AND id ='".$lastId."'";
328
329
            Database::query($sql);*/
330
331
            // create a forum if needed
332
            if ($forumState >= 0) {
333
                require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
334
335
                $forumName = get_lang('Group forums');
336
                $repo = Container::getForumCategoryRepository();
337
                $criteria = ['cId' => $course_id, 'catTitle' => $forumName];
338
                $category = $repo->findOneBy($criteria);
339
340
                if (empty($category)) {
341
                    $categoryParam = [
342
                        'forum_category_title' => $forumName,
343
                    ];
344
                    $categoryId = store_forumcategory($categoryParam);
345
                } else {
346
                    $categoryId = $category->getIid();
347
                }
348
349
                $values = [];
350
                $values['forum_title'] = $name;
351
                $values['group_id'] = $lastId;
352
                $values['forum_category'] = $categoryId;
353
                $values['allow_anonymous_group']['allow_anonymous'] = 0;
354
                $values['students_can_edit_group']['students_can_edit'] = 0;
355
                $values['approval_direct_group']['approval_direct'] = 0;
356
                $values['allow_attachments_group']['allow_attachments'] = 1;
357
                $values['allow_new_threads_group']['allow_new_threads'] = 1;
358
                $values['default_view_type_group']['default_view_type'] = api_get_setting('default_forum_view');
359
                $values['group_forum'] = $lastId;
360
                if ('1' == $forumState) {
361
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'public';
362
                } elseif ('2' == $forumState) {
363
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'private';
364
                } elseif ('0' == $forumState) {
365
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'unavailable';
366
                }
367
                store_forum($values);
368
            }
369
        }
370
371
        return $lastId;
372
    }
373
374
    /**
375
     * Create subgroups.
376
     * This function creates new groups based on an existing group. It will
377
     * create the specified number of groups and fill those groups with users
378
     * from the base group.
379
     *
380
     * @param int $group_id         the group from which subgroups have to be created
381
     * @param int $number_of_groups The number of groups that have to be created
382
     */
383
    public static function create_subgroups($group_id, $number_of_groups)
384
    {
385
        $courseId = api_get_course_int_id();
386
        $table_group = Database::get_course_table(TABLE_GROUP);
387
        $category_id = self::create_category(
388
            get_lang('Subgroups'),
389
            '',
390
            self::TOOL_PRIVATE,
391
            self::TOOL_PRIVATE,
392
            0,
393
            0,
394
            1,
395
            1
396
        );
397
        $users = self::get_users($group_id);
398
        $group_ids = [];
399
400
        for ($group_nr = 1; $group_nr <= $number_of_groups; $group_nr++) {
401
            $group_ids[] = self::create_group(
402
                get_lang('Subgroup').' '.$group_nr,
403
                $category_id,
404
                0,
405
                0
406
            );
407
        }
408
409
        $members = [];
410
        foreach ($users as $index => $user_id) {
411
            $groupId = $group_ids[$index % $number_of_groups];
412
            $groupInfo = self::get_group_properties($groupId);
413
            self::subscribe_users(
414
                $user_id,
415
                $groupInfo
416
            );
417
            $members[$group_ids[$groupId]]++;
418
        }
419
420
        foreach ($members as $group_id => $places) {
421
            $sql = "UPDATE $table_group SET max_student = $places
422
                    WHERE c_id = $courseId  AND id = $group_id";
423
            Database::query($sql);
424
        }
425
    }
426
427
    /**
428
     * Create a group for every class subscribed to the current course.
429
     *
430
     * @param int $categoryId The category in which the groups should be created
431
     *
432
     * @return array
433
     */
434
    public static function create_class_groups($categoryId)
435
    {
436
        $options['where'] = [' usergroup.course_id = ? ' => api_get_course_int_id()];
437
        $obj = new UserGroup();
438
        $classes = $obj->getUserGroupInCourse($options);
439
        $group_ids = [];
440
441
        foreach ($classes as $class) {
442
            $userList = $obj->get_users_by_usergroup($class['id']);
443
            $groupId = self::create_group(
444
                $class['name'],
445
                $categoryId,
446
                0,
447
                null
448
            );
449
450
            if ($groupId) {
451
                $groupInfo = self::get_group_properties($groupId);
452
                self::subscribe_users($userList, $groupInfo);
453
                $group_ids[] = $groupId;
454
            }
455
        }
456
457
        return $group_ids;
458
    }
459
460
    /**
461
     * Deletes groups and their data.
462
     *
463
     * @author Christophe Gesche <[email protected]>
464
     * @author Hugues Peeters <[email protected]>
465
     * @author Bart Mollet
466
     *
467
     * @param string $course_code Default is current course
468
     *
469
     * @return int - number of groups deleted
470
     */
471
    public static function deleteGroup(CGroup $group, $course_code = null)
472
    {
473
        if (empty($group)) {
474
            return false;
475
        }
476
        $course_info = api_get_course_info($course_code);
477
        if (empty($course_info)) {
478
            return false;
479
        }
480
481
        $course_id = $course_info['real_id'];
482
        $em = Database::getManager();
483
        $groupIid = $group->getIid();
484
485
        // Unsubscribe all users
486
        self::unsubscribe_all_users($groupInfo);
487
        self::unsubscribe_all_tutors($groupInfo);
488
489
        if (!empty($groupInfo['secret_directory'])) {
490
            /*
491
            $directory = $groupInfo['secret_directory'];
492
            // move group-documents to garbage
493
            $source_directory = api_get_path(SYS_COURSE_PATH).$course_info['path']."/document".$directory;
494
            // File to renamed
495
            $destination_dir = api_get_path(SYS_COURSE_PATH).$course_info['path']."/document".$directory.'_DELETED_'.$groupInfo['id'];
496
            //Deleting from document tool
497
            DocumentManager::delete_document(
498
                $course_info,
499
                $directory,
500
                $source_directory
501
            );
502
503
            if (file_exists($source_directory)) {
504
                if ('true' === api_get_setting('permanently_remove_deleted_files')) {
505
                    // Delete
506
                    my_delete($source_directory);
507
                } else {
508
                    // Rename
509
                    rename($source_directory, $destination_dir);
510
                }
511
            }*/
512
        }
513
514
        $em
515
            ->createQuery(
516
                'DELETE FROM ChamiloCourseBundle:CForumForum f WHERE f.forumOfGroup = :group'
517
            )
518
            ->execute(['group' => $groupIid]);
519
520
        // Delete item properties of this group.
521
        // to_group_id is related to c_group_info.iid
522
        /*$em
523
            ->createQuery(
524
                'DELETE FROM ChamiloCourseBundle:CItemProperty ci WHERE ci.course = :course AND ci.group = :group'
525
            )
526
            ->execute(['course' => $course_id, 'group' => $groupId]);
527
        */
528
        // delete the groups
529
        $repo = Container::getGroupRepository();
530
        $em->remove($group);
531
        $em->flush();
532
533
        /*$em
534
            ->createQuery(
535
                'DELETE FROM ChamiloCourseBundle:CGroup g WHERE g.course = :course AND g.iid = :id'
536
            )
537
            ->execute(['course' => $course_id, 'id' => $groupIid]);*/
538
539
540
        return true;
541
    }
542
543
    /**
544
     * @deprecated Should be deleted by the resources.
545
     *
546
     * Function needed only when deleting a course, in order to be sure that all group ids are deleted.
547
     *
548
     * @param int $courseId
549
     *
550
     * @return bool
551
     */
552
    public static function deleteAllGroupsFromCourse($courseId)
553
    {
554
        $courseId = (int) $courseId;
555
556
        if (empty($courseId)) {
557
            return false;
558
        }
559
560
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
561
        $sql = "SELECT iid FROM $table
562
                WHERE c_id = $courseId ";
563
        Database::query($sql);
564
565
        // Database table definitions
566
        $table = Database::get_course_table(TABLE_GROUP_USER);
567
        $sql = "DELETE FROM $table
568
                WHERE c_id = $courseId";
569
        Database::query($sql);
570
571
        $table = Database::get_course_table(TABLE_GROUP_TUTOR);
572
        $sql = "DELETE FROM $table
573
                WHERE c_id = $courseId";
574
        Database::query($sql);
575
576
        $groupTable = Database::get_course_table(TABLE_GROUP);
577
        $sql = "DELETE FROM $groupTable
578
                WHERE c_id = $courseId";
579
        Database::query($sql);
580
581
        return true;
582
    }
583
584
    /**
585
     * Get group properties.
586
     *
587
     * @param int $group_id the group from which properties are requested
588
     *
589
     * @return array All properties. Array-keys are:
590
     *               name, tutor_id, description, maximum_number_of_students,
591
     *               directory and visibility of tools
592
     */
593
    public static function get_group_properties($group_id)
594
    {
595
        $group_id = (int) $group_id;
596
597
        if (empty($group_id)) {
598
            return null;
599
        }
600
601
        $table_group = Database::get_course_table(TABLE_GROUP);
602
603
        $sql = "SELECT * FROM $table_group
604
                WHERE iid = ".$group_id;
605
606
        $db_result = Database::query($sql);
607
        $db_object = Database::fetch_object($db_result);
608
609
        $result = [];
610
        if ($db_object) {
611
            $result['id'] = $db_object->iid;
612
            $result['iid'] = $db_object->iid;
613
            $result['name'] = $db_object->name;
614
            $result['status'] = $db_object->status;
615
            $result['description'] = $db_object->description;
616
            $result['maximum_number_of_students'] = $db_object->max_student;
617
            $result['max_student'] = $db_object->max_student;
618
            $result['doc_state'] = $db_object->doc_state;
619
            $result['work_state'] = $db_object->work_state;
620
            $result['calendar_state'] = $db_object->calendar_state;
621
            $result['announcements_state'] = $db_object->announcements_state;
622
            $result['forum_state'] = $db_object->forum_state;
623
            $result['wiki_state'] = $db_object->wiki_state;
624
            $result['chat_state'] = $db_object->chat_state;
625
            $result['directory'] = $db_object->secret_directory;
626
            $result['self_registration_allowed'] = $db_object->self_registration_allowed;
627
            $result['self_unregistration_allowed'] = $db_object->self_unregistration_allowed;
628
            $result['count_users'] = count(
629
                self::get_subscribed_users($result)
630
            );
631
            $result['count_tutor'] = count(
632
                self::get_subscribed_tutors($result)
633
            );
634
            $result['count_all'] = $result['count_users'] + $result['count_tutor'];
635
            $result['document_access'] = isset($db_object->document_access) ? $db_object->document_access : self::DOCUMENT_MODE_SHARE;
636
        }
637
638
        return $result;
639
    }
640
641
    /**
642
     * @param string $name
643
     * @param string $courseCode
644
     * @param int    $sessionId
645
     *
646
     * @return array
647
     */
648
    public static function getGroupByName($name, $courseCode = null, $sessionId = 0)
649
    {
650
        $name = trim($name);
651
652
        if (empty($name)) {
653
            return [];
654
        }
655
656
        $course_info = api_get_course_info($courseCode);
657
        $course_id = $course_info['real_id'];
658
        $name = Database::escape_string($name);
659
        $sessionId = empty($sessionId) ? api_get_session_id() : (int) $sessionId;
660
        $sessionCondition = api_get_session_condition($sessionId);
661
662
        $table = Database::get_course_table(TABLE_GROUP);
663
        $sql = "SELECT * FROM $table
664
                WHERE
665
                  c_id = $course_id AND
666
                  name = '$name'
667
                  $sessionCondition
668
                LIMIT 1";
669
        $res = Database::query($sql);
670
        $group = [];
671
        if (Database::num_rows($res)) {
672
            $group = Database::fetch_array($res, 'ASSOC');
673
        }
674
675
        return $group;
676
    }
677
678
    /**
679
     * Set group properties
680
     * Changes the group's properties.
681
     *
682
     * @param int       Group Id
683
     * @param string    Group name
684
     * @param string    Group description
685
     * @param int       Max number of students in group
686
     * @param int       Document tool's visibility (0=none,1=private,2=public)
687
     * @param int       Work tool's visibility (0=none,1=private,2=public)
688
     * @param int       Calendar tool's visibility (0=none,1=private,2=public)
689
     * @param int       Announcement tool's visibility (0=none,1=private,2=public)
690
     * @param int       Forum tool's visibility (0=none,1=private,2=public)
691
     * @param int       Wiki tool's visibility (0=none,1=private,2=public)
692
     * @param int       Chat tool's visibility (0=none,1=private,2=public)
693
     * @param bool Whether self registration is allowed or not
694
     * @param bool Whether self unregistration is allowed or not
695
     * @param int $categoryId
696
     * @param int $documentAccess
697
     *
698
     * @return bool TRUE if properties are successfully changed, false otherwise
699
     */
700
    public static function set_group_properties(
701
        $group_id,
702
        $name,
703
        $description,
704
        $maxStudent,
705
        $docState,
706
        $workState,
707
        $calendarState,
708
        $anonuncementState,
709
        $forumState,
710
        $wikiState,
711
        $chatState,
712
        $selfRegistrationAllowed,
713
        $selfUnRegistrationAllowed,
714
        $categoryId = null,
715
        $documentAccess = 0
716
    ) {
717
        $table_group = Database::get_course_table(TABLE_GROUP);
718
        $table_forum = Database::get_course_table(TABLE_FORUM);
719
        $categoryId = (int) $categoryId;
720
        $group_id = (int) $group_id;
721
        $repo = Container::getGroupRepository();
722
723
        /** @var CGroup $group */
724
        $group = $repo->find($group_id);
725
726
        $category = null;
727
        if (!empty($categoryId)) {
728
            $category = Container::getGroupCategoryRepository()->find($categoryId);
729
        }
730
731
        $group
732
            ->setName($name)
733
            ->setCategory($category)
734
            ->setMaxStudent($maxStudent)
735
            ->setDocState($docState)
736
            ->setCalendarState($calendarState)
737
            ->setWorkState($workState)
738
            ->setForumState($forumState)
739
            ->setWikiState($wikiState)
740
            ->setAnnouncementsState($anonuncementState)
741
            ->setChatState($chatState)
742
            ->setSelfRegistrationAllowed($selfRegistrationAllowed)
743
            ->setSelfUnregistrationAllowed($selfUnRegistrationAllowed)
744
            ->setDocumentAccess($documentAccess)
745
        ;
746
747
        $repo->update($group);
748
749
        /* Here we are updating a field in the table forum_forum that perhaps
750
        duplicates the table group_info.forum_state cvargas*/
751
        $forumState = (int) $forumState;
752
        $sql2 = "UPDATE $table_forum SET ";
753
        if (1 === $forumState) {
754
            $sql2 .= " forum_group_public_private='public' ";
755
        } elseif (2 === $forumState) {
756
            $sql2 .= " forum_group_public_private='private' ";
757
        } elseif (0 === $forumState) {
758
            $sql2 .= " forum_group_public_private='unavailable' ";
759
        }
760
        $sql2 .= ' WHERE forum_of_group='.$group_id;
761
        Database::query($sql2);
762
763
        return true;
764
    }
765
766
    /**
767
     * Get the total number of groups for the current course.
768
     *
769
     * @return int the number of groups for the current course
770
     */
771
    public static function get_number_of_groups()
772
    {
773
        $repo = Container::getGroupRepository();
774
775
        $course = api_get_course_entity(api_get_course_int_id());
776
        $session = api_get_session_entity(api_get_session_id());
777
        $group = api_get_group_entity(api_get_group_id());
778
779
        $qb = $repo->getResourcesByCourse($course, $session, $group);
780
        $qb->select('count(resource)');
781
782
        return $qb->getQuery()->getSingleScalarResult();
783
784
        $courseId = api_get_course_int_id();
0 ignored issues
show
Unused Code introduced by
$courseId = api_get_course_int_id() is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
785
        $table = Database::get_course_table(TABLE_GROUP);
786
        $sql = "SELECT COUNT(id) AS number_of_groups
787
                FROM $table
788
                WHERE c_id = $courseId ";
789
        $res = Database::query($sql);
790
        $obj = Database::fetch_object($res);
791
792
        return $obj->number_of_groups;
793
    }
794
795
    /**
796
     * Get all categories.
797
     */
798
    public static function get_categories(Course $course = null): array
799
    {
800
        $repo = Container::getGroupCategoryRepository();
801
802
        if (null === $course) {
803
            $course = api_get_course_entity(api_get_course_int_id());
804
        }
805
806
        $session = api_get_session_entity(api_get_session_id());
807
        //$group = api_get_group_entity(api_get_group_id());
808
        $group = null;
809
810
        $qb = $repo->getResourcesByCourse($course, $session, $group);
811
812
        return $qb->getQuery()->getArrayResult();
813
814
        $course_info = api_get_course_info($course_code);
0 ignored issues
show
Unused Code introduced by
$course_info = api_get_course_info($course_code) is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
815
        $courseId = $course_info['real_id'];
816
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
817
        $sql = "SELECT * FROM $table
818
                WHERE c_id = $courseId
819
                ORDER BY display_order";
820
        $res = Database::query($sql);
821
        $cats = [];
822
        while ($cat = Database::fetch_array($res)) {
823
            $cats[] = $cat;
824
        }
825
826
        return $cats;
827
    }
828
829
    /**
830
     * Get a group category.
831
     *
832
     * @param int    $id          The category id
833
     * @param string $course_code The course (default = current course)
834
     *
835
     * @return array
836
     */
837
    public static function get_category($id, $course_code = null)
838
    {
839
        if (empty($id)) {
840
            return [];
841
        }
842
843
        $courseInfo = api_get_course_info($course_code);
844
        $courseId = $courseInfo['real_id'];
845
        $id = intval($id);
846
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
847
        $sql = "SELECT * FROM $table
848
                WHERE  iid = $id
849
                LIMIT 1";
850
        $res = Database::query($sql);
851
852
        return Database::fetch_array($res);
853
    }
854
855
    /**
856
     * Get a group category.
857
     *
858
     * @param string $title
859
     * @param string $course_code The course (default = current course)
860
     *
861
     * @return array
862
     */
863
    public static function getCategoryByTitle($title, $course_code = null)
864
    {
865
        $title = trim($title);
866
867
        if (empty($title)) {
868
            return [];
869
        }
870
871
        $course_info = api_get_course_info($course_code);
872
        $courseId = $course_info['real_id'];
873
        $title = Database::escape_string($title);
874
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
875
        $sql = "SELECT * FROM $table
876
                WHERE c_id = $courseId AND title = '$title'
877
                LIMIT 1";
878
        $res = Database::query($sql);
879
        $category = [];
880
        if (Database::num_rows($res)) {
881
            $category = Database::fetch_array($res, 'ASSOC');
882
        }
883
884
        return $category;
885
    }
886
887
    /**
888
     * Get the unique category of a given group.
889
     *
890
     * @param int    $group_id    The iid of the group
891
     * @param string $course_code The course in which the group is (default =
892
     *                            current course)
893
     *
894
     * @return array The category
895
     */
896
    public static function get_category_from_group($group_id, $course_code = '')
897
    {
898
        $table_group = Database::get_course_table(TABLE_GROUP);
899
        $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
900
901
        $group_id = (int) $group_id;
902
903
        if (empty($group_id)) {
904
            return [];
905
        }
906
907
        $course_info = api_get_course_info($course_code);
908
909
        if (empty($course_info)) {
910
            return false;
911
        }
912
913
        $courseId = $course_info['real_id'];
914
        $sql = "SELECT gc.* FROM $table_group_cat gc
915
                INNER JOIN $table_group g
916
                ON (gc.iid = g.category_id)
917
                WHERE
918
                    g.iid = $group_id
919
                LIMIT 1";
920
        $res = Database::query($sql);
921
        $cat = [];
922
        if (Database::num_rows($res)) {
923
            $cat = Database::fetch_array($res);
924
        }
925
926
        return $cat;
927
    }
928
929
    /**
930
     * Delete a group category.
931
     *
932
     * @param int    $cat_id      The id of the category to delete
933
     * @param string $course_code The code in which the category should be
934
     *                            deleted (default = current course)
935
     *
936
     * @return bool
937
     */
938
    public static function delete_category($cat_id, $course_code = '')
939
    {
940
        $course_info = api_get_course_info($course_code);
941
        if (empty($course_info)) {
942
            return false;
943
        }
944
        $course_id = $course_info['real_id'];
945
946
        $table_group = Database::get_course_table(TABLE_GROUP);
947
        $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
948
        $cat_id = (int) $cat_id;
949
        $sql = "SELECT iid FROM $table_group
950
                WHERE category_id='".$cat_id."'";
951
        $res = Database::query($sql);
952
        if (Database::num_rows($res) > 0) {
953
            while ($group = Database::fetch_object($res)) {
954
                // Delete all groups in category
955
                /*$groupInfo = self::get_group_properties($group->iid, true);
956
                self::deleteGroup($groupInfo, $course_code);
957
                */
958
                // Set the category to NULL to avoid losing groups in sessions.
959
                $sql = "UPDATE $table_group SET category_id = NULL WHERE iid = ".$group->iid;
960
                Database::query($sql);
961
            }
962
        }
963
964
        $category = Database::getManager()->getRepository(CGroupCategory::class)->find($cat_id);
965
        if ($category) {
966
            Database::getManager()->remove($category);
967
            Database::getManager()->flush();
968
        }
969
970
        /*$sql = "DELETE FROM $table_group_cat
971
                WHERE iid='".$cat_id."'";
972
        Database::query($sql);*/
973
974
        return true;
975
    }
976
977
    /**
978
     * Create group category.
979
     *
980
     * @param string $title                     The title of the new category
981
     * @param string $description               The description of the new category
982
     * @param int    $selfRegistrationAllowed   allow users to self register
983
     * @param int    $selfUnRegistrationAllowed allow user to self unregister
984
     * @param int    $documentAccess            document access
985
     *
986
     * @return mixed
987
     */
988
    public static function create_category(
989
        $title,
990
        $description,
991
        $docState,
992
        $workState,
993
        $calendarState,
994
        $anonuncementState,
995
        $forumState,
996
        $wikiState,
997
        $chatState = 1,
998
        $selfRegistrationAllowed = 0,
999
        $selfUnRegistrationAllowed = 0,
1000
        $maxStudent = 8,
1001
        $groupsPerUser = 0,
1002
        $documentAccess = 0
1003
    ) {
1004
        if (empty($title)) {
1005
            return false;
1006
        }
1007
        /*$sql = "SELECT MAX(display_order)+1 as new_order
1008
                FROM $table
1009
                WHERE c_id = $course_id ";
1010
        $res = Database::query($sql);
1011
        $obj = Database::fetch_object($res);
1012
        if (!isset($obj->new_order)) {
1013
            $obj->new_order = 1;
1014
        }*/
1015
1016
        $course = api_get_course_entity(api_get_course_int_id());
1017
        $session = api_get_session_entity(api_get_session_id());
1018
1019
        $category = new CGroupCategory();
1020
        $category
1021
            ->setTitle($title)
1022
            ->setDescription($description)
1023
            ->setMaxStudent($maxStudent)
1024
            ->setDocState($docState)
1025
            ->setCalendarState($calendarState)
1026
            ->setWorkState($workState)
1027
            ->setForumState($forumState)
1028
            ->setWikiState($wikiState)
1029
            ->setAnnouncementsState($anonuncementState)
1030
            ->setChatState($chatState)
1031
            ->setSelfRegAllowed($selfRegistrationAllowed)
1032
            ->setSelfUnregAllowed($selfUnRegistrationAllowed)
1033
            ->setDocumentAccess($documentAccess)
1034
            ->setGroupsPerUser($groupsPerUser)
1035
            ->setParent($course)
1036
            ->addCourseLink($course, $session)
1037
        ;
1038
1039
        $repo = Container::getGroupCategoryRepository();
1040
        $repo->create($category);
1041
1042
        return $category->getIid();
1043
    }
1044
1045
    /**
1046
     * Update group category.
1047
     *
1048
     * @param int    $id
1049
     * @param string $title
1050
     * @param string $description
1051
     * @param $doc_state
1052
     * @param $work_state
1053
     * @param $calendar_state
1054
     * @param $announcements_state
1055
     * @param $forum_state
1056
     * @param $wiki_state
1057
     * @param $chat_state
1058
     * @param $selfRegistrationAllowed
1059
     * @param $selfUnRegistrationAllowed
1060
     * @param $maximum_number_of_students
1061
     * @param $groups_per_user
1062
     * @param $documentAccess
1063
     */
1064
    public static function update_category(
1065
        $id,
1066
        $title,
1067
        $description,
1068
        $doc_state,
1069
        $work_state,
1070
        $calendar_state,
1071
        $announcements_state,
1072
        $forum_state,
1073
        $wiki_state,
1074
        $chat_state,
1075
        $selfRegistrationAllowed,
1076
        $selfUnRegistrationAllowed,
1077
        $maximum_number_of_students,
1078
        $groups_per_user,
1079
        $documentAccess
1080
    ) {
1081
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
1082
        $id = (int) $id;
1083
1084
        $courseId = api_get_course_int_id();
1085
1086
        $allowDocumentAccess = api_get_configuration_value('group_category_document_access');
1087
        $documentCondition = '';
1088
        if ($allowDocumentAccess) {
1089
            $documentAccess = (int) $documentAccess;
1090
            $documentCondition = " document_access = $documentAccess, ";
1091
        }
1092
1093
        $sql = 'UPDATE '.$table." SET
1094
                    title='".Database::escape_string($title)."',
1095
                    description='".Database::escape_string($description)."',
1096
                    doc_state = '".Database::escape_string($doc_state)."',
1097
                    work_state = '".Database::escape_string($work_state)."',
1098
                    calendar_state = '".Database::escape_string($calendar_state)."',
1099
                    announcements_state = '".Database::escape_string($announcements_state)."',
1100
                    forum_state = '".Database::escape_string($forum_state)."',
1101
                    wiki_state = '".Database::escape_string($wiki_state)."',
1102
                    chat_state = '".Database::escape_string($chat_state)."',
1103
                    groups_per_user   = '".Database::escape_string($groups_per_user)."',
1104
                    self_reg_allowed = '".Database::escape_string($selfRegistrationAllowed)."',
1105
                    self_unreg_allowed = '".Database::escape_string($selfUnRegistrationAllowed)."',
1106
                    $documentCondition
1107
                    max_student = ".intval($maximum_number_of_students)."
1108
                WHERE iid = $id";
1109
1110
        Database::query($sql);
1111
1112
        // Updating all groups inside this category
1113
        $groups = self::get_group_list($id);
1114
1115
        if (!empty($groups)) {
1116
            foreach ($groups as $group) {
1117
                self::set_group_properties(
1118
                    $group['iid'],
1119
                    $group['name'],
1120
                    $group['description'],
1121
                    $maximum_number_of_students,
1122
                    $doc_state,
1123
                    $work_state,
1124
                    $calendar_state,
1125
                    $announcements_state,
1126
                    $forum_state,
1127
                    $wiki_state,
1128
                    $chat_state,
1129
                    $selfRegistrationAllowed,
1130
                    $selfUnRegistrationAllowed,
1131
                    $id,
1132
                    $documentAccess
1133
                );
1134
            }
1135
        }
1136
    }
1137
1138
    /**
1139
     * Returns the number of groups of the user with the greatest number of
1140
     * subscriptions in the given category.
1141
     */
1142
    public static function get_current_max_groups_per_user($category_id = null, $course_code = null)
1143
    {
1144
        $course_info = api_get_course_info($course_code);
1145
        $group_table = Database::get_course_table(TABLE_GROUP);
1146
1147
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1148
        $sql = "SELECT COUNT(gu.group_id) AS current_max
1149
                FROM $group_user_table gu
1150
                INNER JOIN $group_table g
1151
                ON (gu.group_id = g.iid)
1152
                WHERE 1= 1 ";
1153
        if (null != $category_id) {
1154
            $category_id = intval($category_id);
1155
            $sql .= ' AND g.category_id = '.$category_id;
1156
        }
1157
        $sql .= ' GROUP BY gu.user_id
1158
                  ORDER BY current_max DESC LIMIT 1';
1159
1160
        $res = Database::query($sql);
1161
        $obj = Database::fetch_object($res);
1162
1163
        if ($obj) {
1164
            return $obj->current_max;
1165
        }
1166
1167
        return 0;
1168
    }
1169
1170
    /**
1171
     * Swaps the display-order of two categories.
1172
     *
1173
     * @param int $id1 The id of the first category
1174
     * @param int $id2 The id of the second category
1175
     */
1176
    public static function swap_category_order($id1, $id2)
1177
    {
1178
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
1179
        $id1 = intval($id1);
1180
        $id2 = intval($id2);
1181
        $course_id = api_get_course_int_id();
1182
1183
        $sql = "SELECT id, display_order FROM $table
1184
                WHERE id IN ($id1,$id2) AND c_id = $course_id ";
1185
        $res = Database::query($sql);
1186
        $cat1 = Database::fetch_object($res);
1187
        $cat2 = Database::fetch_object($res);
1188
        if ($cat1 && $cat2) {
1189
            $sql = "UPDATE $table SET display_order=$cat2->display_order
1190
                    WHERE id = $cat1->id AND c_id = $course_id ";
1191
            Database::query($sql);
1192
1193
            $sql = "UPDATE $table SET display_order=$cat1->display_order
1194
                    WHERE id = $cat2->id AND c_id = $course_id ";
1195
            Database::query($sql);
1196
        }
1197
    }
1198
1199
    /**
1200
     * Get all users from a given group.
1201
     *
1202
     * @param int  $group_id        The group
1203
     * @param bool $load_extra_info
1204
     * @param int  $start
1205
     * @param int  $limit
1206
     * @param bool $getCount
1207
     * @param int  $courseId
1208
     * @param $column
1209
     * @param $direction
1210
     *
1211
     * @return array list of user id
1212
     */
1213
    public static function get_users(
1214
        $group_id,
1215
        $load_extra_info = false,
1216
        $start = null,
1217
        $limit = null,
1218
        $getCount = false,
1219
        $courseId = null,
1220
        $column = null,
1221
        $direction = null
1222
    ) {
1223
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1224
        $groupTable = Database::get_course_table(TABLE_GROUP);
1225
        $user_table = Database::get_main_table(TABLE_MAIN_USER);
1226
        $group_id = (int) $group_id;
1227
1228
        if (empty($courseId)) {
1229
            $courseId = api_get_course_int_id();
1230
        } else {
1231
            $courseId = (int) $courseId;
1232
        }
1233
1234
        $select = ' SELECT u.id, firstname, lastname ';
1235
        if ($getCount) {
1236
            $select = ' SELECT count(u.id) count';
1237
        }
1238
        $sql = "$select
1239
                FROM $group_user_table gu
1240
                INNER JOIN $groupTable g
1241
                ON (gu.group_id = g.iid and g.c_id = gu.c_id)
1242
                INNER JOIN $user_table u
1243
                ON (u.id = gu.user_id)
1244
                WHERE
1245
                    gu.c_id = $courseId AND
1246
                    g.iid = $group_id";
1247
1248
        if (!empty($column) && !empty($direction)) {
1249
            $column = Database::escape_string($column, null, false);
1250
            $direction = ('ASC' == $direction ? 'ASC' : 'DESC');
1251
            $sql .= " ORDER BY $column $direction";
1252
        }
1253
1254
        if (!empty($start) && !empty($limit)) {
1255
            $start = (int) $start;
1256
            $limit = (int) $limit;
1257
            $sql .= " LIMIT $start, $limit";
1258
        }
1259
        $res = Database::query($sql);
1260
        $users = [];
1261
        while ($obj = Database::fetch_object($res)) {
1262
            if ($getCount) {
1263
                return $obj->count;
1264
                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...
1265
            }
1266
            if ($load_extra_info) {
1267
                $users[] = api_get_user_info($obj->id);
1268
            } else {
1269
                $users[] = $obj->id;
1270
            }
1271
        }
1272
1273
        return $users;
1274
    }
1275
1276
    /**
1277
     * @param int $group_id id
1278
     *
1279
     * @return array
1280
     */
1281
    public static function getStudentsAndTutors($group_id)
1282
    {
1283
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1284
        $tutor_user_table = Database::get_course_table(TABLE_GROUP_TUTOR);
1285
        $groupTable = Database::get_course_table(TABLE_GROUP);
1286
1287
        $course_id = api_get_course_int_id();
1288
        $group_id = (int) $group_id;
1289
1290
        $sql = "SELECT user_id
1291
                FROM $group_user_table gu
1292
                INNER JOIN $groupTable g
1293
                ON (gu.group_id = g.iid)
1294
                WHERE g.iid = $group_id";
1295
        $res = Database::query($sql);
1296
        $users = [];
1297
1298
        while ($obj = Database::fetch_object($res)) {
1299
            $users[] = api_get_user_info($obj->user_id);
1300
        }
1301
1302
        $sql = "SELECT user_id
1303
                FROM $tutor_user_table gu
1304
                INNER JOIN $groupTable g
1305
                ON (gu.group_id = g.iid)
1306
                WHERE g.iid = $group_id";
1307
        $res = Database::query($sql);
1308
        while ($obj = Database::fetch_object($res)) {
1309
            $users[] = api_get_user_info($obj->user_id);
1310
        }
1311
1312
        return $users;
1313
    }
1314
1315
    /**
1316
     * Get only tutors from a group.
1317
     *
1318
     * @param array $groupInfo
1319
     *
1320
     * @return array
1321
     */
1322
    public static function getTutors($groupInfo)
1323
    {
1324
        $groupTable = Database::get_course_table(TABLE_GROUP);
1325
        $tutor_user_table = Database::get_course_table(TABLE_GROUP_TUTOR);
1326
        $course_id = api_get_course_int_id();
1327
        $group_id = (int) $groupInfo['iid'];
1328
1329
        $sql = "SELECT user_id
1330
                FROM $tutor_user_table gu
1331
                INNER JOIN $groupTable g
1332
                ON (gu.group_id = g.iid)
1333
                WHERE g.iid = $group_id";
1334
        $res = Database::query($sql);
1335
1336
        $users = [];
1337
        while ($obj = Database::fetch_object($res)) {
1338
            $users[] = api_get_user_info($obj->user_id);
1339
        }
1340
1341
        return $users;
1342
    }
1343
1344
    /**
1345
     * Get only students from a group (not tutors).
1346
     *
1347
     * @param bool $filterOnlyActive
1348
     *
1349
     * @return array
1350
     */
1351
    public static function getStudents($groupId, $filterOnlyActive = false)
1352
    {
1353
        $groupId = (int) $groupId;
1354
        $activeCondition = $filterOnlyActive ? 'AND u.active = 1' : '';
1355
1356
        $em = Database::getManager();
1357
        $subscriptions = $em
1358
            ->createQuery("
1359
                SELECT u.id FROM ChamiloCoreBundle:User u
1360
                INNER JOIN ChamiloCourseBundle:CGroupRelUser gu
1361
                WITH u.id = gu.user
1362
                INNER JOIN ChamiloCourseBundle:CGroup g
1363
                WITH gu.group = g.iid
1364
                WHERE g.iid = :group
1365
                    $activeCondition
1366
            ")
1367
            ->setParameters([
1368
                'group' => $groupId,
1369
            ])
1370
            ->getResult();
1371
1372
        $users = [];
1373
        foreach ($subscriptions as $subscription) {
1374
            $users[] = api_get_user_info($subscription['id']);
1375
        }
1376
1377
        return $users;
1378
    }
1379
1380
    public static function getStudentsCount($groupId, $filterOnlyActive = false)
1381
    {
1382
        $groupId = (int) $groupId;
1383
        $activeCondition = $filterOnlyActive ? 'AND u.active = 1' : '';
1384
1385
        $em = Database::getManager();
1386
        return $em
1387
            ->createQuery("
1388
                SELECT COUNT(u.id) FROM ChamiloCoreBundle:User u
1389
                INNER JOIN ChamiloCourseBundle:CGroupRelUser gu
1390
                WITH u.id = gu.user
1391
                INNER JOIN ChamiloCourseBundle:CGroup g
1392
                WITH gu.group = g.iid
1393
                WHERE g.iid = :group
1394
                    $activeCondition
1395
            ")
1396
            ->setParameters([
1397
                'group' => $groupId,
1398
            ])
1399
            ->getSingleScalarResult();
1400
    }
1401
1402
    /**
1403
     * Returns users belonging to any of the group.
1404
     *
1405
     * @param array $groups list of group ids
1406
     *
1407
     * @return array list of user ids
1408
     */
1409
    public static function get_groups_users($groups = [])
1410
    {
1411
        $result = [];
1412
        $table = Database::get_course_table(TABLE_GROUP_USER);
1413
        $course_id = api_get_course_int_id();
1414
1415
        $groups = array_map('intval', $groups);
1416
        // protect individual elements with surrounding quotes
1417
        $groups = implode(', ', $groups);
1418
        $sql = "SELECT DISTINCT user_id
1419
                FROM $table gu
1420
                WHERE gu.group_id IN ($groups)";
1421
        $rs = Database::query($sql);
1422
        while ($row = Database::fetch_array($rs)) {
1423
            $result[] = $row['user_id'];
1424
        }
1425
1426
        return $result;
1427
    }
1428
1429
    /**
1430
     * Fill the groups with students.
1431
     * The algorithm takes care to first fill the groups with the least # of users.
1432
     * Analysis
1433
     * There was a problem with the "ALL" setting.
1434
     * When max # of groups is set to all, the value is sometimes NULL and sometimes ALL
1435
     * and in both cased the query does not work as expected.
1436
     * Stupid solution (currently implemented: set ALL to a big number (INFINITE) and things are solved :)
1437
     * Better solution: that's up to you.
1438
     *
1439
     * Note
1440
     * Throughout Dokeos there is some confusion about "course id" and "course code"
1441
     * The code is e.g. TEST101, but sometimes a variable that is called courseID also contains a course code string.
1442
     * However, there is also a integer course_id that uniquely identifies the course.
1443
     * ywarnier:> Now the course_id has been removed (25/1/2005)
1444
     * The databases are als very inconsistent in this.
1445
     *
1446
     * @author Chrisptophe Gesche <[email protected]>,
1447
     *         Hugues Peeters     <[email protected]> - original version
1448
     * @author Roan Embrechts - virtual course support, code cleaning
1449
     * @author Bart Mollet - code cleaning, use other GroupManager-functions
1450
     *
1451
     * @return bool
1452
     */
1453
    public static function fillGroupWithUsers(CGroup $group)
1454
    {
1455
        $_course = api_get_course_info();
1456
        if (empty($_course) || empty($group)) {
1457
            return false;
1458
        }
1459
        $session_id = api_get_session_id();
1460
        $complete_user_list = CourseManager::get_user_list_from_course_code(
1461
            $_course['code'],
1462
            $session_id
1463
        );
1464
        $groupIid = $group->getIid();
1465
        $category = self::get_category_from_group($groupIid);
1466
1467
        // Getting max numbers of user from group
1468
        $maxNumberStudents = empty($groupInfo['maximum_number_of_students']) ? self::INFINITE : $groupInfo['maximum_number_of_students'];
1469
        $groupsPerUser = self::INFINITE;
1470
        $categoryId = 0;
1471
        if ($category) {
1472
            $groupsPerUser = empty($category['groups_per_user']) ? self::INFINITE : $category['groups_per_user'];
1473
            $maxNumberStudentsCategory = empty($category['max_student']) ? self::INFINITE : $category['max_student'];
1474
            $categoryId = $category['id'];
1475
            if ($maxNumberStudentsCategory < $maxNumberStudents) {
1476
                $maxNumberStudents = $maxNumberStudentsCategory;
1477
            }
1478
        }
1479
1480
        $usersToAdd = [];
1481
        foreach ($complete_user_list as $userInfo) {
1482
            $isSubscribed = self::is_subscribed($userInfo['user_id'], $groupInfo);
1483
            if ($isSubscribed) {
1484
                continue;
1485
            }
1486
            $numberOfGroups = self::user_in_number_of_groups(
1487
                $userInfo['user_id'],
1488
                $categoryId
1489
            );
1490
            if ($groupsPerUser > $numberOfGroups) {
1491
                $usersToAdd[] = $userInfo['user_id'];
1492
            }
1493
            if (count($usersToAdd) == $maxNumberStudents) {
1494
                break;
1495
            }
1496
        }
1497
1498
        foreach ($usersToAdd as $userId) {
1499
            self::subscribe_users($userId, $groupInfo);
1500
        }
1501
    }
1502
1503
    /**
1504
     * Get the number of students in a group.
1505
     *
1506
     * @param int $group_id id
1507
     *
1508
     * @return int number of students in the given group
1509
     */
1510
    public static function number_of_students($group_id, $course_id = null)
1511
    {
1512
        $table = Database::get_course_table(TABLE_GROUP_USER);
1513
        $group_id = (int) $group_id;
1514
        $course_id = (int) $course_id;
1515
1516
        if (empty($course_id)) {
1517
            $course_id = api_get_course_int_id();
1518
        }
1519
        $sql = "SELECT COUNT(*) AS number_of_students
1520
                FROM $table
1521
                WHERE c_id = $course_id AND group_id = $group_id";
1522
        $result = Database::query($sql);
1523
        $db_object = Database::fetch_object($result);
1524
1525
        return $db_object->number_of_students;
1526
    }
1527
1528
    /**
1529
     * Maximum number of students in a group.
1530
     *
1531
     * @param int $group_id iid
1532
     *
1533
     * @return int maximum number of students in the given group
1534
     */
1535
    public static function maximum_number_of_students($group_id)
1536
    {
1537
        $table = Database::get_course_table(TABLE_GROUP);
1538
        $group_id = (int) $group_id;
1539
        $course_id = api_get_course_int_id();
1540
        $sql = "SELECT max_student FROM $table
1541
                WHERE iid = $group_id";
1542
        $db_result = Database::query($sql);
1543
        $db_object = Database::fetch_object($db_result);
1544
        if (0 == $db_object->max_student) {
1545
            return self::INFINITE;
1546
        }
1547
1548
        return $db_object->max_student;
1549
    }
1550
1551
    /**
1552
     * Number of groups of a user.
1553
     *
1554
     * @param int $user_id
1555
     * @param int $cat_id
1556
     *
1557
     * @return int the number of groups the user is subscribed in
1558
     */
1559
    public static function user_in_number_of_groups($user_id, $cat_id = 0)
1560
    {
1561
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1562
        $table_group = Database::get_course_table(TABLE_GROUP);
1563
        $user_id = (int) $user_id;
1564
        $cat_id = (int) $cat_id;
1565
1566
        $course_id = api_get_course_int_id();
1567
        $cat_condition = '';
1568
        if (!empty($cat_id)) {
1569
            $cat_condition = " AND g.category_id =  $cat_id ";
1570
        }
1571
1572
        $sql = "SELECT COUNT(*) AS number_of_groups
1573
                FROM $table_group_user gu
1574
                INNER JOIN $table_group g
1575
                ON (g.iid = gu.group_id)
1576
                WHERE
1577
                    gu.user_id = $user_id
1578
                    $cat_condition";
1579
1580
        $result = Database::query($sql);
1581
        $db_object = Database::fetch_object($result);
1582
1583
        return $db_object->number_of_groups;
1584
    }
1585
1586
    /**
1587
     * Is sef-registration allowed?
1588
     *
1589
     * @param int   $user_id
1590
     * @param array $groupInfo
1591
     *
1592
     * @return bool TRUE if self-registration is allowed in the given group
1593
     */
1594
    public static function is_self_registration_allowed($user_id, $groupInfo)
1595
    {
1596
        $course_id = api_get_course_int_id();
1597
        if (empty($user_id)) {
1598
            return false;
1599
        }
1600
1601
        $groupIid = $groupInfo['iid'];
1602
        $table = Database::get_course_table(TABLE_GROUP);
1603
        if (isset($groupIid)) {
1604
            $sql = "SELECT status, self_registration_allowed
1605
                    FROM $table
1606
                    WHERE iid = $groupIid";
1607
            $result = Database::query($sql);
1608
            $group = Database::fetch_object($result);
1609
1610
            if (0 == $group->status || 1 != $group->self_registration_allowed) {
1611
                return false;
1612
            }
1613
1614
            return self::canUserSubscribe($user_id, $groupInfo);
1615
        }
1616
1617
        return false;
1618
    }
1619
1620
    /**
1621
     * Is sef-unregistration allowed?
1622
     *
1623
     * @param int   $user_id
1624
     * @param array $groupInfo
1625
     *
1626
     * @return bool TRUE if self-unregistration is allowed in the given group
1627
     */
1628
    public static function is_self_unregistration_allowed($user_id, $groupInfo)
1629
    {
1630
        if (empty($user_id) || empty($groupInfo)) {
1631
            return false;
1632
        }
1633
        $groupIid = $groupInfo['iid'];
1634
        $table = Database::get_course_table(TABLE_GROUP);
1635
        $course_id = api_get_course_int_id();
1636
1637
        $sql = "SELECT status, self_unregistration_allowed
1638
                FROM $table
1639
                WHERE iid = $groupIid";
1640
        $result = Database::query($sql);
1641
        $group = Database::fetch_object($result);
1642
1643
        if (0 == $group->status || 1 != $group->self_unregistration_allowed) {
1644
            return false;
1645
        }
1646
1647
        return self::is_subscribed($user_id, $groupInfo);
1648
    }
1649
1650
    /**
1651
     * Is user subscribed in group?
1652
     *
1653
     * @param int   $user_id
1654
     * @param array $groupInfo
1655
     *
1656
     * @return bool TRUE if given user is subscribed in given group
1657
     */
1658
    public static function is_subscribed($user_id, $groupInfo)
1659
    {
1660
        $course_id = api_get_course_int_id();
1661
        if (empty($user_id) || empty($groupInfo) || empty($course_id)) {
1662
            return false;
1663
        }
1664
        $table = Database::get_course_table(TABLE_GROUP_USER);
1665
        $group_id = intval($groupInfo['iid']);
1666
        $user_id = intval($user_id);
1667
1668
        $sql = "SELECT 1 FROM $table
1669
                WHERE
1670
                    group_id = $group_id AND
1671
                    user_id = $user_id
1672
                ";
1673
        $result = Database::query($sql);
1674
1675
        return Database::num_rows($result) > 0;
1676
    }
1677
1678
    /**
1679
     * Can a user subscribe to a specified group in a course.
1680
     *
1681
     * @param int   $user_id
1682
     * @param array $groupInfo
1683
     * @param bool  $checkMaxNumberStudents
1684
     *
1685
     * @return bool TRUE if given user  can be subscribed in given group
1686
     */
1687
    public static function canUserSubscribe(
1688
        $user_id,
1689
        $groupInfo,
1690
        $checkMaxNumberStudents = true
1691
    ) {
1692
        $groupIid = $groupInfo['iid'];
1693
        if ($checkMaxNumberStudents) {
1694
            $category = self::get_category_from_group($groupIid);
1695
            if ($category) {
1696
                if (self::GROUP_PER_MEMBER_NO_LIMIT == $category['groups_per_user']) {
1697
                    $category['groups_per_user'] = self::INFINITE;
1698
                }
1699
                $result = self::user_in_number_of_groups($user_id, $category['iid']) < $category['groups_per_user'];
1700
                if (false == $result) {
1701
                    return false;
1702
                }
1703
            }
1704
1705
            $result = self::number_of_students($groupIid) < self::maximum_number_of_students($groupIid);
1706
1707
            if (false == $result) {
1708
                return false;
1709
            }
1710
        }
1711
1712
        $result = self::is_tutor_of_group($user_id, $groupInfo);
1713
1714
        if ($result) {
1715
            return false;
1716
        }
1717
1718
        $result = self::is_subscribed($user_id, $groupInfo);
1719
1720
        if ($result) {
1721
            return false;
1722
        }
1723
1724
        return true;
1725
    }
1726
1727
    /**
1728
     * Get all subscribed users (members) from a group.
1729
     *
1730
     * @param array $groupInfo
1731
     *
1732
     * @return array An array with information of all users from the given group.
1733
     *               (user_id, firstname, lastname, email)
1734
     */
1735
    public static function get_subscribed_users($groupInfo)
1736
    {
1737
        if (empty($groupInfo)) {
1738
            return [];
1739
        }
1740
1741
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
1742
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1743
        $order_clause = api_sort_by_first_name() ? ' ORDER BY u.firstname, u.lastname' : ' ORDER BY u.lastname, u.firstname';
1744
        $orderListByOfficialCode = api_get_setting('order_user_list_by_official_code');
1745
        if ('true' === $orderListByOfficialCode) {
1746
            $order_clause = ' ORDER BY u.official_code, u.firstname, u.lastname';
1747
        }
1748
1749
        $group_id = (int) $groupInfo['iid'];
1750
1751
        if (empty($group_id)) {
1752
            return [];
1753
        }
1754
1755
        $course_id = api_get_course_int_id();
1756
1757
        $sql = "SELECT
1758
                    ug.iid,
1759
                    u.id as user_id,
1760
                    u.lastname,
1761
                    u.firstname,
1762
                    u.email,
1763
                    u.username
1764
                FROM $table_user u
1765
                INNER JOIN $table_group_user ug
1766
                ON (ug.user_id = u.id)
1767
                WHERE
1768
                      ug.group_id = $group_id
1769
                $order_clause";
1770
1771
        $db_result = Database::query($sql);
1772
        $users = [];
1773
        while ($user = Database::fetch_object($db_result)) {
1774
            $users[$user->user_id] = [
1775
                'user_id' => $user->user_id,
1776
                'firstname' => $user->firstname,
1777
                'lastname' => $user->lastname,
1778
                'email' => $user->email,
1779
                'username' => $user->username,
1780
            ];
1781
        }
1782
1783
        return $users;
1784
    }
1785
1786
    /**
1787
     * @author Patrick Cool <[email protected]>, Ghent University
1788
     * Get all subscribed tutors of a group
1789
     *
1790
     * @param array $groupInfo
1791
     *
1792
     * @return array An array with information of all users from the given group.
1793
     *               (user_id, firstname, lastname, email)
1794
     */
1795
    public static function get_subscribed_tutors($groupInfo, $id_only = false)
1796
    {
1797
        if (empty($groupInfo)) {
1798
            return [];
1799
        }
1800
1801
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
1802
        $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1803
        $order_clause = api_sort_by_first_name() ? ' ORDER BY u.firstname, u.lastname' : ' ORDER BY u.lastname, u.firstname';
1804
1805
        $orderListByOfficialCode = api_get_setting('order_user_list_by_official_code');
1806
        if ('true' === $orderListByOfficialCode) {
1807
            $order_clause = ' ORDER BY u.official_code, u.firstname, u.lastname';
1808
        }
1809
1810
        $group_id = (int) $groupInfo['iid'];
1811
        $course_id = api_get_course_int_id();
1812
1813
        $sql = "SELECT u.id, u.lastname, u.firstname, u.email
1814
                FROM $table_user u
1815
                INNER JOIN $table_group_tutor tg
1816
                ON (tg.user_id = u.id)
1817
                WHERE
1818
                    tg.group_id = $group_id
1819
                    $order_clause
1820
                ";
1821
        $db_result = Database::query($sql);
1822
        $users = [];
1823
        while ($user = Database::fetch_object($db_result)) {
1824
            if (!$id_only) {
1825
                $member['user_id'] = $user->id;
1826
                $member['firstname'] = $user->firstname;
1827
                $member['lastname'] = $user->lastname;
1828
                $member['email'] = $user->email;
1829
                $users[] = $member;
1830
            } else {
1831
                $users[] = $user->id;
1832
            }
1833
        }
1834
1835
        return $users;
1836
    }
1837
1838
    /**
1839
     * Subscribe user(s) to a specified group in current course (as a student).
1840
     *
1841
     * @param mixed $user_ids  Can be an array with user-id's or a single user-id
1842
     * @param array $groupInfo
1843
     * @param int   $course_id
1844
     *
1845
     * @return bool TRUE if successful
1846
     */
1847
    public static function subscribe_users($user_ids, $groupInfo, $course_id = null)
1848
    {
1849
        $user_ids = is_array($user_ids) ? $user_ids : [$user_ids];
1850
        $course_id = empty($course_id) ? api_get_course_int_id() : (int) $course_id;
1851
        $group_id = $groupInfo['iid'];
1852
1853
        if (!empty($user_ids)) {
1854
            $table = Database::get_course_table(TABLE_GROUP_USER);
1855
            foreach ($user_ids as $user_id) {
1856
                if (self::canUserSubscribe($user_id, $groupInfo)) {
1857
                    $user_id = (int) $user_id;
1858
                    $sql = "INSERT INTO $table (c_id, user_id, group_id, status, role)
1859
                            VALUES ('$course_id', '".$user_id."', '".$group_id."', 0, '')";
1860
                    Database::query($sql);
1861
                }
1862
            }
1863
        }
1864
1865
        return true;
1866
    }
1867
1868
    /**
1869
     * Subscribe tutor(s) to a specified group in current course.
1870
     *
1871
     * @param mixed $user_ids  Can be an array with user-id's or a single user-id
1872
     * @param array $groupInfo
1873
     * @param int   $course_id
1874
     *
1875
     * @author Patrick Cool <[email protected]>, Ghent University
1876
     *
1877
     * @see subscribe_users. This function is almost an exact copy of that function.
1878
     *
1879
     * @return bool TRUE if successful
1880
     */
1881
    public static function subscribe_tutors($user_ids, $groupInfo, $course_id = 0)
1882
    {
1883
        $user_ids = is_array($user_ids) ? $user_ids : [$user_ids];
1884
        $result = true;
1885
        $course_id = isset($course_id) && !empty($course_id) ? intval($course_id) : api_get_course_int_id();
1886
        $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1887
        $groupId = (int) $groupInfo['iid'];
1888
1889
        foreach ($user_ids as $user_id) {
1890
            $user_id = intval($user_id);
1891
            if (self::canUserSubscribe($user_id, $groupInfo, false)) {
1892
                $sql = 'INSERT INTO '.$table_group_tutor." (c_id, user_id, group_id)
1893
                        VALUES ('$course_id', '".$user_id."', '".$groupId."')";
1894
                $result = Database::query($sql);
1895
            }
1896
        }
1897
1898
        return $result;
1899
    }
1900
1901
    /**
1902
     * Unsubscribe user(s) from a specified group in current course.
1903
     *
1904
     * @param mixed $user_ids  Can be an array with user-id's or a single user-id
1905
     * @param array $groupInfo
1906
     *
1907
     * @return bool TRUE if successful
1908
     */
1909
    public static function unsubscribe_users($user_ids, $groupInfo)
1910
    {
1911
        $user_ids = is_array($user_ids) ? $user_ids : [$user_ids];
1912
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1913
        $group_id = intval($groupInfo['iid']);
1914
        $course_id = api_get_course_int_id();
1915
        $sql = 'DELETE FROM '.$table_group_user.'
1916
                WHERE
1917
                    group_id = '.$group_id.' AND
1918
                    user_id IN ('.implode(',', $user_ids).')
1919
                ';
1920
        Database::query($sql);
1921
    }
1922
1923
    /**
1924
     * Unsubscribe all users from one or more groups.
1925
     *
1926
     * @param int $groupId
1927
     *
1928
     * @return bool TRUE if successful
1929
     */
1930
    public static function unsubscribe_all_users($groupId)
1931
    {
1932
        $groupId = (int) $groupId;
1933
        if (empty($groupId)) {
1934
            return false;
1935
        }
1936
1937
        $table = Database::get_course_table(TABLE_GROUP_USER);
1938
        $sql = "DELETE FROM $table
1939
                WHERE
1940
                    group_id = $groupId ";
1941
1942
        return Database::query($sql);
1943
    }
1944
1945
    /**
1946
     * Unsubscribe all tutors from one or more groups.
1947
     *
1948
     * @param int $groupId iid
1949
     *
1950
     * @see unsubscribe_all_users. This function is almost an exact copy of that function.
1951
     *
1952
     * @return bool TRUE if successful
1953
     *
1954
     * @author Patrick Cool <[email protected]>, Ghent University
1955
     */
1956
    public static function unsubscribe_all_tutors($groupId)
1957
    {
1958
        $courseId = api_get_course_int_id();
1959
        $groupId = (int) $groupId;
1960
1961
        if (empty($courseId) || empty($groupId)) {
1962
            return false;
1963
        }
1964
1965
        if (!empty($groupId)) {
1966
            $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1967
            $sql = "DELETE FROM $table_group_tutor
1968
                    WHERE group_id = $groupId ";
1969
            $result = Database::query($sql);
1970
1971
            return $result;
1972
        }
1973
1974
        return true;
1975
    }
1976
1977
    /**
1978
     * Is the user a tutor of this group?
1979
     *
1980
     * @param int   $user_id   the id of the user
1981
     * @param array $groupInfo
1982
     * @param int   $courseId
1983
     *
1984
     * @return bool true/false
1985
     *
1986
     * @todo use the function user_has_access that includes this function
1987
     *
1988
     * @author Patrick Cool <[email protected]>, Ghent University
1989
     */
1990
    public static function is_tutor_of_group($user_id, $groupInfo, $courseId = 0)
1991
    {
1992
        if (empty($groupInfo)) {
1993
            return false;
1994
        }
1995
1996
        $courseId = empty($courseId) ? api_get_course_int_id() : (int) $courseId;
1997
        if (empty($courseId)) {
1998
            return false;
1999
        }
2000
2001
        $user_id = (int) $user_id;
2002
        $group_id = (int) $groupInfo['iid'];
2003
2004
        $table = Database::get_course_table(TABLE_GROUP_TUTOR);
2005
2006
        $sql = "SELECT * FROM $table
2007
                WHERE
2008
                    user_id = $user_id AND
2009
                    group_id = $group_id";
2010
        $result = Database::query($sql);
2011
        if (Database::num_rows($result) > 0) {
2012
            return true;
2013
        }
2014
2015
        return false;
2016
    }
2017
2018
    /**
2019
     * Is the user part of this group? This can be a tutor or a normal member
2020
     * you should use this function if the access to a tool or functionality is
2021
     * restricted to the people who are actually in the group
2022
     * before you had to check if the user was
2023
     * 1. a member of the group OR
2024
     * 2. a tutor of the group. This function combines both.
2025
     *
2026
     * @param int   $user_id   the id of the user
2027
     * @param array $groupInfo
2028
     *
2029
     * @return bool true/false
2030
     *
2031
     * @author Patrick Cool <[email protected]>, Ghent University
2032
     */
2033
    public static function is_user_in_group($user_id, $groupInfo)
2034
    {
2035
        $member = self::is_subscribed($user_id, $groupInfo);
2036
        if ($member) {
2037
            return true;
2038
        }
2039
2040
        $tutor = self::is_tutor_of_group($user_id, $groupInfo);
2041
        if ($tutor) {
2042
            return true;
2043
        }
2044
2045
        return false;
2046
    }
2047
2048
    /**
2049
     * Get all group's from a given course in which a given user is unsubscribed.
2050
     *
2051
     * @author  Patrick Cool
2052
     *
2053
     * @param int $course_id retrieve the groups for
2054
     * @param int $user_id   the ID of the user you want to know all its group memberships
2055
     *
2056
     * @return array
2057
     */
2058
    public static function get_group_ids($course_id, $user_id)
2059
    {
2060
        $groups = [];
2061
        $tbl_group = Database::get_course_table(TABLE_GROUP_USER);
2062
        $tbl_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
2063
        $user_id = intval($user_id);
2064
        $course_id = intval($course_id);
2065
2066
        $sql = "SELECT group_id FROM $tbl_group
2067
                WHERE user_id = '$user_id'";
2068
        $result = Database::query($sql);
2069
2070
        if ($result) {
2071
            while ($row = Database::fetch_array($result)) {
2072
                $groups[] = $row['group_id'];
2073
            }
2074
        }
2075
2076
        //Also loading if i'm the tutor
2077
        $sql = "SELECT group_id FROM $tbl_group_tutor
2078
                WHERE user_id = '$user_id'";
2079
        $result = Database::query($sql);
2080
        if ($result) {
2081
            while ($row = Database::fetch_array($result)) {
2082
                $groups[] = $row['group_id'];
2083
            }
2084
        }
2085
        if (!empty($groups)) {
2086
            array_filter($groups);
2087
        }
2088
2089
        return $groups;
2090
    }
2091
2092
    /**
2093
     * Check if a user has access to a certain group tool.
2094
     *
2095
     * @param int    $user_id  The user id
2096
     * @param int    $group_id The group iid
2097
     * @param string $tool     The tool to check the access rights. This should be
2098
     *                         one of constants: GROUP_TOOL_DOCUMENTS
2099
     *
2100
     * @return bool true if the given user has access to the given tool in the
2101
     *              given course
2102
     */
2103
    public static function user_has_access($user_id, $group_id, $tool)
2104
    {
2105
        // Admin have access everywhere
2106
        if (api_is_platform_admin()) {
2107
            return true;
2108
        }
2109
2110
        // Course admin also have access to everything
2111
        if (api_is_allowed_to_edit(false, true, true)) {
2112
            return true;
2113
        }
2114
2115
        switch ($tool) {
2116
            case self::GROUP_TOOL_FORUM:
2117
                $key = 'forum_state';
2118
                break;
2119
            case self::GROUP_TOOL_DOCUMENTS:
2120
                $key = 'doc_state';
2121
                break;
2122
            case self::GROUP_TOOL_CALENDAR:
2123
                $key = 'calendar_state';
2124
                break;
2125
            case self::GROUP_TOOL_ANNOUNCEMENT:
2126
                $key = 'announcements_state';
2127
                break;
2128
            case self::GROUP_TOOL_WORK:
2129
                $key = 'work_state';
2130
                break;
2131
            case self::GROUP_TOOL_WIKI:
2132
                $key = 'wiki_state';
2133
                break;
2134
            case self::GROUP_TOOL_CHAT:
2135
                $key = 'chat_state';
2136
                break;
2137
            default:
2138
                return false;
2139
        }
2140
2141
        // Check group properties
2142
        $groupInfo = self::get_group_properties($group_id, true);
2143
2144
        if (empty($groupInfo)) {
2145
            return false;
2146
        }
2147
2148
        if (0 == $groupInfo['status']) {
2149
            return false;
2150
        }
2151
2152
        if (!isset($groupInfo[$key])) {
2153
            return false;
2154
        }
2155
2156
        $status = $groupInfo[$key];
2157
2158
        switch ($status) {
2159
            case self::TOOL_NOT_AVAILABLE:
2160
                return false;
2161
                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...
2162
            case self::TOOL_PUBLIC:
2163
                return true;
2164
                break;
2165
            case self::TOOL_PRIVATE:
2166
                $userIsInGroup = self::is_user_in_group($user_id, $groupInfo);
2167
                if ($userIsInGroup) {
2168
                    return true;
2169
                }
2170
                break;
2171
            case self::TOOL_PRIVATE_BETWEEN_USERS:
2172
                // Only works for announcements for now
2173
                $userIsInGroup = self::is_user_in_group($user_id, $groupInfo);
2174
                if ($userIsInGroup && self::GROUP_TOOL_ANNOUNCEMENT == $tool) {
2175
                    return true;
2176
                }
2177
                break;
2178
        }
2179
2180
        return false;
2181
    }
2182
2183
    /**
2184
     * @param int   $userId
2185
     * @param array $groupInfo
2186
     * @param int   $sessionId
2187
     *
2188
     * @return bool
2189
     */
2190
    public static function userHasAccessToBrowse($userId, $groupInfo, $sessionId = 0)
2191
    {
2192
        if (empty($groupInfo)) {
2193
            return false;
2194
        }
2195
2196
        if (api_is_platform_admin()) {
2197
            return true;
2198
        }
2199
2200
        if (api_is_allowed_to_edit(false, true, true)) {
2201
            return true;
2202
        }
2203
2204
        if (!empty($sessionId)) {
2205
            if (api_is_coach($sessionId, api_get_course_int_id())) {
2206
                return true;
2207
            }
2208
2209
            if (api_is_drh()) {
2210
                if (SessionManager::isUserSubscribedAsHRM($sessionId, $userId)) {
2211
                    return true;
2212
                }
2213
            }
2214
        }
2215
2216
        $groupId = $groupInfo['iid'];
2217
        if (self::is_tutor_of_group($userId, $groupInfo)) {
2218
            return true;
2219
        }
2220
2221
        if (0 == $groupInfo['status']) {
2222
            return false;
2223
        }
2224
2225
        if (self::user_has_access($userId, $groupId, self::GROUP_TOOL_FORUM) ||
2226
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_DOCUMENTS) ||
2227
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_CALENDAR) ||
2228
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_ANNOUNCEMENT) ||
2229
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_WORK) ||
2230
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_WIKI) ||
2231
            self::user_has_access($userId, $groupId, self::GROUP_TOOL_CHAT)
2232
        ) {
2233
            return true;
2234
        }
2235
2236
        if (api_is_session_general_coach() && $groupInfo['session_id'] == $sessionId) {
2237
            return true;
2238
        }
2239
2240
        return false;
2241
    }
2242
2243
    /**
2244
     * Get all groups where a specific user is subscribed.
2245
     *
2246
     * @param int $user_id
2247
     *
2248
     * @return array
2249
     */
2250
    public static function get_user_group_name($user_id)
2251
    {
2252
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
2253
        $table_group = Database::get_course_table(TABLE_GROUP);
2254
        $user_id = intval($user_id);
2255
        $course_id = api_get_course_int_id();
2256
        $sql = "SELECT name
2257
                FROM $table_group g
2258
                INNER JOIN $table_group_user gu
2259
                ON (gu.group_id = g.iid)
2260
                WHERE
2261
                  gu.user_id = $user_id";
2262
        $res = Database::query($sql);
2263
        $groups = [];
2264
        while ($group = Database::fetch_array($res)) {
2265
            $groups[] .= $group['name'];
2266
        }
2267
2268
        return $groups;
2269
    }
2270
2271
    /**
2272
     * Get all groups where a specific user is subscribed.
2273
     *
2274
     * @param int      $user_id
2275
     * @param int      $courseId
2276
     * @param int|null $sessionId
2277
     *
2278
     * @return array
2279
     */
2280
    public static function getAllGroupPerUserSubscription($user_id, $courseId = 0, $sessionId = null)
2281
    {
2282
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
2283
        $table_tutor_user = Database::get_course_table(TABLE_GROUP_TUTOR);
2284
        $table_group = Database::get_course_table(TABLE_GROUP);
2285
        $user_id = (int) $user_id;
2286
        $courseId = empty($courseId) ? api_get_course_int_id() : (int) $courseId;
2287
2288
        $sql = "SELECT DISTINCT g.*
2289
               FROM $table_group g
2290
               LEFT JOIN $table_group_user gu
2291
               ON (gu.group_id = g.iid)
2292
               LEFT JOIN $table_tutor_user tu
2293
               ON (tu.group_id = g.iid)
2294
               WHERE
2295
                  (gu.user_id = $user_id OR tu.user_id = $user_id) ";
2296
2297
        if (null !== $sessionId) {
2298
            $sessionId = (int) $sessionId;
2299
            $sql .= " AND g.session_id = $sessionId ";
2300
        }
2301
2302
        $res = Database::query($sql);
2303
        $groups = [];
2304
        while ($group = Database::fetch_array($res, 'ASSOC')) {
2305
            $groups[] = $group;
2306
        }
2307
2308
        return $groups;
2309
    }
2310
2311
    /**
2312
     * @param array $group_list
2313
     * @param int   $category_id
2314
     *
2315
     * @return string
2316
     */
2317
    public static function process_groups($group_list, $category_id = 0)
2318
    {
2319
        $charset = 'UTF-8';
2320
        $category_id = (int) $category_id;
2321
        $totalRegistered = 0;
2322
        $group_data = [];
2323
        $user_info = api_get_user_info();
2324
        $session_id = api_get_session_id();
2325
        $user_id = $user_info['user_id'];
2326
        $hideGroup = api_get_setting('hide_course_group_if_no_tools_available');
2327
        $extraField = new ExtraField('survey');
2328
        $surveyGroupExists = $extraField->get_handler_field_info_by_field_variable('group_id') ? true : false;
2329
        $url = api_get_path(WEB_CODE_PATH).'group/';
2330
2331
        foreach ($group_list as $this_group) {
2332
            $groupId = $this_group['iid'];
2333
            // Validation when belongs to a session
2334
            $session_img = '';
2335
            //$session_img = api_get_session_image($this_group['session_id'], $user_info['status']);
2336
2337
            // All the tutors of this group
2338
            $tutors = self::get_subscribed_tutors($this_group, true);
2339
            $isMember = self::is_subscribed($user_id, $this_group);
2340
2341
            // Create a new table-row
2342
            $row = [];
2343
            // Checkbox
2344
            if (api_is_allowed_to_edit(false, true) && count($group_list) > 1) {
2345
                $row[] = $this_group['iid'];
2346
            }
2347
2348
            if (self::userHasAccessToBrowse($user_id, $this_group, $session_id)) {
2349
                // Group name
2350
                $groupNameClass = null;
2351
                if (0 == $this_group['status']) {
2352
                    $groupNameClass = 'muted';
2353
                }
2354
2355
                $group_name = '<a
2356
                    class="'.$groupNameClass.'"
2357
                    href="group_space.php?'.api_get_cidreq(true, false).'&gid='.$groupId.'">'.
2358
                    Security::remove_XSS($this_group['name']).'</a> ';
2359
2360
                $group_name2 = '';
2361
                if (api_get_configuration_value('extra')) {
2362
                    $group_name2 = '<a
2363
                        href="group_space_tracking.php?cid='.api_get_course_int_id().'&gid='.$groupId.'">'.
2364
                        get_lang('suivi_de').''.stripslashes($this_group['name']).'</a>';
2365
                }
2366
2367
                if (!empty($user_id) && !empty($this_group['id_tutor']) && $user_id == $this_group['id_tutor']) {
2368
                    $group_name .= Display::label(get_lang('my supervision'), 'success');
2369
                } elseif ($isMember) {
2370
                    $group_name .= Display::label(get_lang('my group'), 'success');
2371
                }
2372
2373
                if (api_is_allowed_to_edit() && !empty($this_group['session_name'])) {
2374
                    $group_name .= ' ('.$this_group['session_name'].')';
2375
                }
2376
                $group_name .= $session_img;
2377
                $row[] = $group_name.$group_name2.'<br />'.stripslashes(trim($this_group['description']));
2378
            } else {
2379
                if ('true' === $hideGroup) {
2380
                    continue;
2381
                }
2382
                $row[] = $this_group['name'].'<br />'.stripslashes(trim($this_group['description']));
2383
            }
2384
2385
            // Tutor name
2386
            $tutor_info = '';
2387
            if (count($tutors) > 0) {
2388
                foreach ($tutors as $tutor_id) {
2389
                    $tutor = api_get_user_info($tutor_id);
2390
                    $username = api_htmlentities(
2391
                        sprintf(get_lang('Login: %s'), $tutor['username']),
2392
                        ENT_QUOTES
2393
                    );
2394
                    if ('true' === api_get_setting('show_email_addresses')) {
2395
                        $tutor_info .= Display::tag(
2396
                            'span',
2397
                            Display::encrypted_mailto_link(
2398
                                $tutor['mail'],
2399
                                $tutor['complete_name']
2400
                            ),
2401
                            ['title' => $username]
2402
                        ).', ';
2403
                    } else {
2404
                        if (api_is_allowed_to_edit()) {
2405
                            $tutor_info .= Display::tag(
2406
                            'span',
2407
                                Display::encrypted_mailto_link(
2408
                                    $tutor['mail'],
2409
                                    $tutor['complete_name_with_username']
2410
                                ),
2411
                                ['title' => $username]
2412
                            ).', ';
2413
                        } else {
2414
                            $tutor_info .= Display::tag(
2415
                                'span',
2416
                                $tutor['complete_name'],
2417
                                ['title' => $username]
2418
                            ).', ';
2419
                        }
2420
                    }
2421
                }
2422
            }
2423
2424
            $tutor_info = api_substr(
2425
                $tutor_info,
2426
                0,
2427
                api_strlen($tutor_info) - 2
2428
            );
2429
            $row[] = $tutor_info;
2430
2431
            // Max number of members in group
2432
            $max_members = self::MEMBER_PER_GROUP_NO_LIMIT == $this_group['maxStudent'] ? ' ' : ' / '.$this_group['maxStudent'];
2433
            $registeredUsers = self::getStudentsCount($groupId);
2434
            // Number of members in group
2435
            $row[] = $registeredUsers.$max_members;
2436
            $confirmMessage = addslashes(api_htmlentities(get_lang('Please confirm your choice'), ENT_QUOTES, $charset));
2437
            // Self-registration / unregistration
2438
            if (!api_is_allowed_to_edit(false, true)) {
2439
                if (self::is_self_registration_allowed($user_id, $this_group)) {
2440
                    $row[] = '<a
2441
                        class = "btn btn-default"
2442
                        href="group.php?'.api_get_cidreq().'&category='.$category_id.'&action=self_reg&group_id='.$groupId.'"
2443
                        onclick="javascript:if(!confirm('."'".$confirmMessage."'".')) return false;">'.get_lang('register').'</a>';
2444
                } elseif (self::is_self_unregistration_allowed($user_id, $this_group)) {
2445
                    $row[] = '<a
2446
                        class = "btn btn-default"
2447
                        href="group.php?'.api_get_cidreq().'&category='.$category_id.'&action=self_unreg&group_id='.$groupId.'"
2448
                        onclick="javascript:if(!confirm('."'".$confirmMessage."'".')) return false;">'.get_lang('unregister').'</a>';
2449
                } else {
2450
                    $row[] = '-';
2451
                }
2452
            }
2453
2454
            // Edit-links
2455
            if (api_is_allowed_to_edit(false, true) &&
2456
                !(api_is_session_general_coach() && intval($this_group['session_id']) != $session_id)
2457
            ) {
2458
                $edit_actions = '<a
2459
                    href="'.$url.'settings.php?'.api_get_cidreq(true, false).'&gid='.$groupId.'"
2460
                    title="'.get_lang('Edit').'">'.
2461
                    Display::return_icon('edit.png', get_lang('Edit this group'), '', ICON_SIZE_SMALL).
2462
                    '</a>&nbsp;';
2463
2464
                if (1 == $this_group['status']) {
2465
                    $edit_actions .= '<a
2466
                        href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=set_invisible&group_id='.$groupId.'"
2467
                        title="'.get_lang('Hide').'">'.
2468
                        Display::return_icon('visible.png', get_lang('Hide'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2469
                } else {
2470
                    $edit_actions .= '<a
2471
                        href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=set_visible&group_id='.$groupId.'"
2472
                        title="'.get_lang('Show').'">'.
2473
                        Display::return_icon('invisible.png', get_lang('Show'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2474
                }
2475
2476
                $edit_actions .= '<a
2477
                    href="'.$url.'member_settings.php?'.api_get_cidreq(true, false).'&gid='.$groupId.'"
2478
                    title="'.get_lang('Group members').'">'.
2479
                    Display::return_icon('user.png', get_lang('Group members'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2480
2481
                $edit_actions .= '<a
2482
                    href="'.$url.'group_overview.php?action=export&type=xls&'.api_get_cidreq(true, false).'&id='.$groupId.'"
2483
                    title="'.get_lang('Export users list').'">'.
2484
                    Display::return_icon('export_excel.png', get_lang('Export'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2485
2486
                if ($surveyGroupExists) {
2487
                    $edit_actions .= Display::url(
2488
                        Display::return_icon('survey.png', get_lang('ExportSurveyResults'), '', ICON_SIZE_SMALL),
2489
                        $url.'group_overview.php?action=export_surveys&'.api_get_cidreq(true, false).'&id='.$groupId
2490
                    ).'&nbsp;';
2491
                }
2492
                $edit_actions .= '<a
2493
                    href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=fill_one&group_id='.$groupId.'"
2494
                    onclick="javascript: if(!confirm('."'".$confirmMessage."'".')) return false;" title="'.get_lang('FillGroup').'">'.
2495
                    Display::return_icon('fill.png', get_lang('FillGroup'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2496
2497
                $edit_actions .= '<a
2498
                    href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=delete_one&group_id='.$groupId.'"
2499
                    onclick="javascript: if(!confirm('."'".$confirmMessage."'".')) return false;" title="'.get_lang('Delete').'">'.
2500
                    Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2501
2502
                $row[] = $edit_actions;
2503
            }
2504
            if (!empty($this_group['nbMember'])) {
2505
                $totalRegistered = $totalRegistered + $this_group['nbMember'];
2506
            }
2507
            $group_data[] = $row;
2508
        }
2509
2510
        // If no groups then don't show the table (only for students)
2511
        if (!api_is_allowed_to_edit(true, false)) {
2512
            if (empty($group_data)) {
2513
                return '';
2514
            }
2515
        }
2516
2517
        $table = new SortableTableFromArrayConfig(
2518
            $group_data,
2519
            1,
2520
            20,
2521
            'group_category_'.$category_id
2522
        );
2523
        $table->set_additional_parameters(['category' => $category_id]);
2524
        $column = 0;
2525
        if (api_is_allowed_to_edit(false, true) and count($group_list) > 1) {
2526
            $table->set_header($column++, '', false);
2527
        }
2528
        $table->set_header($column++, get_lang('Groups'));
2529
        $table->set_header($column++, get_lang('Group tutor'));
2530
        $table->set_header($column++, get_lang('Registered'), false);
2531
2532
        if (!api_is_allowed_to_edit(false, true)) {
2533
            // If self-registration allowed
2534
            $table->set_header($column++, get_lang('Registration'), false);
2535
        }
2536
2537
        if (api_is_allowed_to_edit(false, true)) {
2538
            // Only for course administrator
2539
            $table->set_header($column++, get_lang('Edit'), false);
2540
            $form_actions = [];
2541
            $form_actions['fill_selected'] = get_lang('Fill the group randomly with course students');
2542
            $form_actions['empty_selected'] = get_lang('unsubscribe all users');
2543
            $form_actions['delete_selected'] = get_lang('Delete');
2544
            if (count($group_list) > 1) {
2545
                $table->set_form_actions($form_actions, 'group');
2546
            }
2547
        }
2548
2549
        return $table->return_table();
2550
    }
2551
2552
    /**
2553
     * @param array $groupData
2554
     * @param bool  $deleteNotInArray
2555
     *
2556
     * @return array
2557
     */
2558
    public static function importCategoriesAndGroupsFromArray($groupData, $deleteNotInArray = false)
2559
    {
2560
        $result = [];
2561
        $elementsFound = [
2562
            'categories' => [],
2563
            'groups' => [],
2564
        ];
2565
2566
        $courseCode = api_get_course_id();
2567
        $sessionId = api_get_session_id();
2568
        $groupCategories = self::get_categories();
2569
2570
        if (empty($groupCategories)) {
2571
            $result['error'][] = get_lang('Create a category');
2572
2573
            return $result;
2574
        }
2575
2576
        foreach ($groupData as $data) {
2577
            $isCategory = empty($data['group']) ? true : false;
2578
            if ($isCategory) {
2579
                $categoryInfo = self::getCategoryByTitle($data['category']);
2580
                $categoryId = $categoryInfo['iid'];
2581
2582
                if (!empty($categoryInfo)) {
2583
                    // Update
2584
                    self::update_category(
2585
                        $categoryId,
2586
                        $data['category'],
2587
                        $data['description'],
2588
                        $data['doc_state'],
2589
                        $data['work_state'],
2590
                        $data['calendar_state'],
2591
                        $data['announcements_state'],
2592
                        $data['forum_state'],
2593
                        $data['wiki_state'],
2594
                        $data['chat_state'],
2595
                        $data['self_reg_allowed'],
2596
                        $data['self_unreg_allowed'],
2597
                        $data['max_student'],
2598
                        $data['groups_per_user'],
2599
                        $data['document_access']
2600
                    );
2601
                    $data['category_id'] = $categoryId;
2602
                    $result['updated']['category'][] = $data;
2603
                } else {
2604
                    // Add
2605
                    $categoryId = self::create_category(
2606
                        $data['category'],
2607
                        $data['description'],
2608
                        $data['doc_state'],
2609
                        $data['work_state'],
2610
                        $data['calendar_state'],
2611
                        $data['announcements_state'],
2612
                        $data['forum_state'],
2613
                        $data['wiki_state'],
2614
                        $data['chat_state'],
2615
                        $data['self_reg_allowed'],
2616
                        $data['self_unreg_allowed'],
2617
                        $data['max_student'],
2618
                        $data['groups_per_user']
2619
                    );
2620
2621
                    if ($categoryId) {
2622
                        $data['category_id'] = $categoryId;
2623
                        $result['added']['category'][] = $data;
2624
                    }
2625
                }
2626
                $elementsFound['categories'][] = $categoryId;
2627
            } else {
2628
                $groupInfo = self::getGroupByName($data['group']);
2629
                $categoryInfo = [];
2630
                if (isset($data['category'])) {
2631
                    $categoryInfo = self::getCategoryByTitle($data['category']);
2632
                }
2633
                $categoryId = null;
2634
                if (!empty($categoryInfo)) {
2635
                    $categoryId = $categoryInfo['iid'];
2636
                } else {
2637
                    if (!empty($groupCategories) && isset($groupCategories[0])) {
2638
                        $defaultGroupCategory = $groupCategories[0];
2639
                        $categoryId = $defaultGroupCategory['iid'];
2640
                    }
2641
                }
2642
2643
                if (empty($groupInfo)) {
2644
                    // Add
2645
                    $groupId = self::create_group(
2646
                        $data['group'],
2647
                        $categoryId,
2648
                        null,
2649
                        $data['max_student']
2650
                    );
2651
2652
                    if ($groupId) {
2653
                        self::set_group_properties(
2654
                            $groupId,
2655
                            $data['group'],
2656
                            $data['description'],
2657
                            $data['max_student'],
2658
                            $data['doc_state'],
2659
                            $data['work_state'],
2660
                            $data['calendar_state'],
2661
                            $data['announcements_state'],
2662
                            $data['forum_state'],
2663
                            $data['wiki_state'],
2664
                            $data['chat_state'],
2665
                            $data['self_reg_allowed'],
2666
                            $data['self_unreg_allowed'],
2667
                            $categoryId
2668
                        );
2669
                        $data['group_id'] = $groupId;
2670
                        $result['added']['group'][] = $data;
2671
                    }
2672
                    $groupInfo = self::get_group_properties($groupId, true);
2673
                } else {
2674
                    // Update
2675
                    $groupId = $groupInfo['iid'];
2676
                    self::set_group_properties(
2677
                        $groupId,
2678
                        $data['group'],
2679
                        $data['description'],
2680
                        $data['max_student'],
2681
                        $data['doc_state'],
2682
                        $data['work_state'],
2683
                        $data['calendar_state'],
2684
                        $data['announcements_state'],
2685
                        $data['forum_state'],
2686
                        $data['wiki_state'],
2687
                        $data['chat_state'],
2688
                        $data['self_reg_allowed'],
2689
                        $data['self_unreg_allowed'],
2690
                        $categoryId
2691
                    );
2692
2693
                    $data['group_id'] = $groupId;
2694
                    $result['updated']['group'][] = $data;
2695
                    $groupInfo = self::get_group_properties($groupId);
2696
                }
2697
2698
                $students = isset($data['students']) ? explode(',', $data['students']) : [];
2699
                if (!empty($students)) {
2700
                    $studentUserIdList = [];
2701
                    foreach ($students as $student) {
2702
                        $userInfo = api_get_user_info_from_username($student);
2703
2704
                        if (!$userInfo) {
2705
                            continue;
2706
                        }
2707
2708
                        if (!CourseManager::is_user_subscribed_in_course(
2709
                                $userInfo['user_id'],
2710
                                $courseCode,
2711
                                !empty($sessionId),
2712
                                $sessionId
2713
                            )
2714
                        ) {
2715
                            Display::addFlash(
2716
                                Display::return_message(
2717
                                    sprintf(
2718
                                        get_lang('Student %s is no subscribed to this course'),
2719
                                        $userInfo['complete_name']
2720
                                    ),
2721
                                    'warning'
2722
                                )
2723
                            );
2724
                            continue;
2725
                        }
2726
2727
                        $studentUserIdList[] = $userInfo['user_id'];
2728
                    }
2729
                    self::subscribe_users($studentUserIdList, $groupInfo);
2730
                }
2731
2732
                $tutors = isset($data['tutors']) ? explode(',', $data['tutors']) : [];
2733
                if (!empty($tutors)) {
2734
                    $tutorIdList = [];
2735
                    foreach ($tutors as $tutor) {
2736
                        $userInfo = api_get_user_info_from_username($tutor);
2737
2738
                        if (!$userInfo) {
2739
                            continue;
2740
                        }
2741
2742
                        if (!CourseManager::is_user_subscribed_in_course(
2743
                                $userInfo['user_id'],
2744
                                $courseCode,
2745
                                !empty($sessionId),
2746
                                $sessionId
2747
                            )
2748
                        ) {
2749
                            Display::addFlash(
2750
                                Display::return_message(
2751
                                    sprintf(get_lang('Tutor %s is no subscribed to this course'), $userInfo['complete_name']),
2752
                                    'warning'
2753
                                )
2754
                            );
2755
2756
                            continue;
2757
                        }
2758
2759
                        $tutorIdList[] = $userInfo['user_id'];
2760
                    }
2761
                    self::subscribe_tutors($tutorIdList, $groupInfo);
2762
                }
2763
2764
                $elementsFound['groups'][] = $groupId;
2765
            }
2766
        }
2767
2768
        if ($deleteNotInArray) {
2769
            // Check categories
2770
            $categories = self::get_categories();
2771
            foreach ($categories as $category) {
2772
                if (!in_array($category['iid'], $elementsFound['categories'])) {
2773
                    self::delete_category($category['iid']);
2774
                    $category['category'] = $category['title'];
2775
                    $result['deleted']['category'][] = $category;
2776
                }
2777
            }
2778
2779
            $groups = self::get_groups();
2780
            foreach ($groups as $group) {
2781
                if (!in_array($group['iid'], $elementsFound['groups'])) {
2782
                    self::deleteGroup($group);
2783
                    $group['group'] = $group['name'];
2784
                    $result['deleted']['group'][] = $group;
2785
                }
2786
            }
2787
        }
2788
2789
        return $result;
2790
    }
2791
2792
    /**
2793
     * Export all categories/group from a course to an array.
2794
     * This function works only in a context of a course.
2795
     *
2796
     * @param int  $groupId
2797
     * @param bool $loadUsers
2798
     *
2799
     * @return array
2800
     */
2801
    public static function exportCategoriesAndGroupsToArray($groupId = null, $loadUsers = false)
2802
    {
2803
        $data = [];
2804
        $data[] = [
2805
            'category',
2806
            'group',
2807
            'description',
2808
            'announcements_state',
2809
            'calendar_state',
2810
            'chat_state',
2811
            'doc_state',
2812
            'forum_state',
2813
            'work_state',
2814
            'wiki_state',
2815
            'max_student',
2816
            'self_reg_allowed',
2817
            'self_unreg_allowed',
2818
            'groups_per_user',
2819
        ];
2820
2821
        $count = 1;
2822
2823
        if ($loadUsers) {
2824
            $data[0][] = 'students';
2825
            $data[0][] = 'tutors';
2826
        }
2827
2828
        if (false == $loadUsers) {
2829
            $categories = self::get_categories();
2830
2831
            foreach ($categories as $categoryInfo) {
2832
                $data[$count] = [
2833
                    $categoryInfo['title'],
2834
                    null,
2835
                    $categoryInfo['description'],
2836
                    $categoryInfo['announcements_state'],
2837
                    $categoryInfo['calendar_state'],
2838
                    $categoryInfo['chat_state'],
2839
                    $categoryInfo['doc_state'],
2840
                    $categoryInfo['forum_state'],
2841
                    $categoryInfo['work_state'],
2842
                    $categoryInfo['wiki_state'],
2843
                    $categoryInfo['max_student'],
2844
                    $categoryInfo['self_reg_allowed'],
2845
                    $categoryInfo['self_unreg_allowed'],
2846
                    $categoryInfo['groups_per_user'],
2847
                ];
2848
                $count++;
2849
            }
2850
        }
2851
2852
        $groups = self::get_group_list();
2853
        foreach ($groups as $groupInfo) {
2854
            $groupId = $groupInfo['iid'];
2855
            $categoryTitle = null;
2856
            $categoryInfo = [];
2857
            if (isset($groupInfo['category'])) {
2858
                $categoryInfo = self::get_category($groupInfo['category']);
2859
            }
2860
2861
            $groupSettings = self::get_group_properties($groupId);
2862
            if (!empty($categoryInfo)) {
2863
                $categoryTitle = $categoryInfo['title'];
2864
            }
2865
2866
            $users = self::getStudents($groupId);
2867
            $userList = [];
2868
            foreach ($users as $user) {
2869
                $user = api_get_user_info($user['user_id']);
2870
                $userList[] = $user['username'];
2871
            }
2872
2873
            $tutors = self::getTutors($groupInfo);
2874
            $tutorList = [];
2875
            foreach ($tutors as $user) {
2876
                $user = api_get_user_info($user['user_id']);
2877
                $tutorList[] = $user['username'];
2878
            }
2879
2880
            $userListToString = null;
2881
            if (!empty($userList)) {
2882
                $userListToString = implode(',', $userList);
2883
            }
2884
2885
            $tutorListToString = null;
2886
            if (!empty($tutorList)) {
2887
                $tutorListToString = implode(',', $tutorList);
2888
            }
2889
2890
            $data[$count] = [
2891
                $categoryTitle,
2892
                $groupSettings['name'],
2893
                $groupSettings['description'],
2894
                $groupSettings['announcements_state'],
2895
                $groupSettings['calendar_state'],
2896
                $groupSettings['chat_state'],
2897
                $groupSettings['doc_state'],
2898
                $groupSettings['forum_state'],
2899
                $groupSettings['work_state'],
2900
                $groupSettings['wiki_state'],
2901
                $groupSettings['maximum_number_of_students'],
2902
                $groupSettings['self_registration_allowed'],
2903
                $groupSettings['self_unregistration_allowed'],
2904
                null,
2905
            ];
2906
2907
            if ($loadUsers) {
2908
                $data[$count][] = $userListToString;
2909
                $data[$count][] = $tutorListToString;
2910
            }
2911
2912
            if (!empty($groupId)) {
2913
                if ($groupId == $groupInfo['iid']) {
2914
                    break;
2915
                }
2916
            }
2917
            $count++;
2918
        }
2919
2920
        return $data;
2921
    }
2922
2923
    /**
2924
     * @param string $default
2925
     */
2926
    public static function getSettingBar($default)
2927
    {
2928
        $activeSettings = null;
2929
        $activeTutor = null;
2930
        $activeMember = null;
2931
2932
        switch ($default) {
2933
            case 'settings':
2934
                $activeSettings = 'active';
2935
                break;
2936
            case 'tutor':
2937
                $activeTutor = 'active';
2938
                break;
2939
            case 'member':
2940
                $activeMember = 'active';
2941
                break;
2942
        }
2943
2944
        $url = api_get_path(WEB_CODE_PATH).'group/%s?'.api_get_cidreq();
2945
2946
        echo '
2947
            <ul class="nav nav-tabs">
2948
                <li class="nav-item">
2949
                    <a class="nav-link '.$activeSettings.'" id="group_settings_tab" href="'.sprintf($url, 'settings.php').'">
2950
                    '.Display::return_icon('settings.png').' '.get_lang('Settings').'
2951
                    </a>
2952
                </li>
2953
                <li class="nav-item">
2954
                    <a class="nav-link '.$activeMember.'" id="group_members_tab" href="'.sprintf($url, 'member_settings.php').'">
2955
                    '.Display::return_icon('user.png').' '.get_lang('Group members').'</a>
2956
                </li>
2957
                <li class="nav-item">
2958
                    <a class="nav-link  '.$activeTutor.'" id="group_tutors_tab" href="'.sprintf($url, 'tutor_settings.php').'">
2959
                    '.Display::return_icon('teacher.png').' '.get_lang('Group tutors').'
2960
                    </a>
2961
                </li>
2962
            </ul>';
2963
    }
2964
2965
    public static function groupOverview($group, $url)
2966
    {
2967
        $groupId = $group['iid'];
2968
        $content = '<li>';
2969
        $content .= Display::tag(
2970
            'h3',
2971
            Display::url(
2972
                Security::remove_XSS($group['name']),
2973
                $url.'&gidReq='.$groupId
2974
            )
2975
        );
2976
        $users = self::getTutors($group);
2977
        if (!empty($users)) {
2978
            $content .= '<ul>';
2979
            $content .= "<li>".Display::tag('h4', get_lang('Tutors'))."</li><ul>";
2980
            foreach ($users as $user) {
2981
                $userInfo = api_get_user_info($user['user_id']);
2982
                $content .= '<li title="'.$userInfo['username'].'">'.
2983
                    $userInfo['complete_name_with_username'].
2984
                    '</li>';
2985
            }
2986
            $content .= '</ul>';
2987
            $content .= '</ul>';
2988
        }
2989
2990
        $users = self::getStudents($group['iid']);
2991
        if (!empty($users)) {
2992
            $content .= '<ul>';
2993
            $content .= "<li>".Display::tag('h4', get_lang('Students'))."</li><ul>";
2994
            foreach ($users as $user) {
2995
                $userInfo = api_get_user_info($user['user_id']);
2996
                $content .= '<li title="'.$userInfo['username'].'">'.
2997
                    $userInfo['complete_name_with_username'].
2998
                    '</li>';
2999
            }
3000
            $content .= '</ul>';
3001
            $content .= '</ul>';
3002
        }
3003
        $content .= '</li>';
3004
3005
        return $content;
3006
    }
3007
    /**
3008
     * @param array  $courseInfo
3009
     * @param string $keyword
3010
     *
3011
     * @return string
3012
     */
3013
    public static function getOverview($courseInfo, $keyword = '')
3014
    {
3015
        $content = null;
3016
        $categories = self::get_categories();
3017
        $url = api_get_path(WEB_CODE_PATH).'group/group_space.php?'.api_get_cidreq(true, false);
3018
        if (!empty($categories)) {
3019
            foreach ($categories as $category) {
3020
                if ('true' === api_get_setting('allow_group_categories')) {
3021
                    $content .= '<h2>'.$category['title'].'</h2>';
3022
                }
3023
                $groups = self::get_group_list($category['iid'], $courseInfo, null, 0, false, $keyword);
3024
                $content .= '<ul>';
3025
                if (!empty($groups)) {
3026
                    foreach ($groups as $group) {
3027
                        $content .= self::groupOverview($group, $url);
3028
                    }
3029
                }
3030
                $content .= '</ul>';
3031
            }
3032
        }
3033
3034
        // Check groups with no categories.
3035
        $groups = self::get_group_list(null, api_get_course_info(), null, api_get_session_id(), false, true);
3036
        if (!empty($groups)) {
3037
            $content .= '<h2>'.get_lang('NoCategorySelected').'</h2>';
3038
            $content .= '<ul>';
3039
            foreach ($groups as $group) {
3040
                if (!empty($group['category_id'])) {
3041
                    continue;
3042
                }
3043
                $content .= self::groupOverview($group, $url);
3044
            }
3045
            $content .= '</ul>';
3046
        }
3047
3048
        return $content;
3049
    }
3050
3051
    /**
3052
     * Returns the search form.
3053
     *
3054
     * @return string
3055
     */
3056
    public static function getSearchForm()
3057
    {
3058
        $url = api_get_path(WEB_CODE_PATH).'group/group_overview.php?'.api_get_cidreq();
3059
        $form = new FormValidator(
3060
            'search_groups',
3061
            'get',
3062
            $url,
3063
            null,
3064
            ['class' => 'form-search'],
3065
            FormValidator::LAYOUT_INLINE
3066
        );
3067
        $form->addElement('text', 'keyword');
3068
        $form->addCourseHiddenParams();
3069
        $form->addButtonSearch();
3070
3071
        return $form->toHtml();
3072
    }
3073
3074
    public static function setStatus(CGroup $group, $status)
3075
    {
3076
        $group->setStatus($status);
3077
        $em = Database::getManager();
3078
        $em->persist($group);
3079
        $em->flush();
3080
    }
3081
3082
    public static function setVisible(CGroup $group)
3083
    {
3084
        self::setStatus($group, true);
3085
    }
3086
3087
    public static function setInvisible(CGroup $group)
3088
    {
3089
        self::setStatus($group, false);
3090
    }
3091
3092
    /**
3093
     * @param int   $userId
3094
     * @param int   $courseId
3095
     * @param array $groupInfo
3096
     * @param array $documentInfoToBeCheck
3097
     * @param bool  $blockPage
3098
     *
3099
     * @return bool
3100
     */
3101
    public static function allowUploadEditDocument(
3102
        $userId,
3103
        $courseId,
3104
        $groupInfo,
3105
        $documentInfoToBeCheck = null,
3106
        $blockPage = false
3107
    ) {
3108
        // Admin and teachers can make any change no matter what
3109
        if (api_is_platform_admin() || api_is_allowed_to_edit(false, true)) {
3110
            return true;
3111
        }
3112
3113
        if (empty($groupInfo) || !isset($groupInfo['iid'])) {
3114
            if ($blockPage) {
3115
                api_not_allowed(true);
3116
            }
3117
3118
            return false;
3119
        }
3120
3121
        // Tutor can also make any change
3122
        $isTutor = self::is_tutor_of_group($userId, $groupInfo, $courseId);
3123
3124
        if ($isTutor) {
3125
            return true;
3126
        }
3127
3128
        // Just in case also check if document in group is available
3129
        if (0 == $groupInfo['doc_state']) {
3130
            if ($blockPage) {
3131
                api_not_allowed(true);
3132
            }
3133
3134
            return false;
3135
        }
3136
3137
        // Default behaviour
3138
        $documentAccess = self::DOCUMENT_MODE_SHARE;
3139
3140
        // Check category document access
3141
        /*$allowCategoryGroupDocumentAccess = api_get_configuration_value('group_category_document_access');
3142
        if ($allowCategoryGroupDocumentAccess) {
3143
            $category = GroupManager::get_category_from_group($groupInfo['iid']);
3144
            if (!empty($category) && isset($category['document_access'])) {
3145
                $documentAccess = (int) $category['document_access'];
3146
            }
3147
        }*/
3148
3149
        // Check group document access
3150
        $allow = api_get_configuration_value('group_document_access');
3151
        if ($allow) {
3152
            if (isset($groupInfo['document_access'])) {
3153
                $documentAccess = (int) $groupInfo['document_access'];
3154
            }
3155
        }
3156
3157
        // Check access for students
3158
        $result = false;
3159
        switch ($documentAccess) {
3160
            case self::DOCUMENT_MODE_SHARE:
3161
                // Default chamilo behaviour
3162
                // Student can upload his own content, cannot modify another content.
3163
                $isMember = self::is_subscribed($userId, $groupInfo);
3164
                if ($isMember) {
3165
                    // No document to check, allow access to document feature.
3166
                    if (empty($documentInfoToBeCheck)) {
3167
                        $result = true;
3168
                    } else {
3169
                        // Member can only edit his own document
3170
                        $authorId = isset($documentInfoToBeCheck['insert_user_id']) ? $documentInfoToBeCheck['insert_user_id'] : 0;
3171
                        // If "insert_user_id" is not set, check the author id from c_item_property
3172
                        if (empty($authorId) && isset($documentInfoToBeCheck['id'])) {
3173
                            // @todo use resources
3174
                            /*$documentInfo = api_get_item_property_info(
3175
                                $courseId,
3176
                                'document',
3177
                                $documentInfoToBeCheck['id'],
3178
                                0
3179
                            );
3180
                            // Try to find this document in the session
3181
                            if (!empty($sessionId)) {
3182
                                $documentInfo = api_get_item_property_info(
3183
                                    $courseId,
3184
                                    'document',
3185
                                    $documentInfoToBeCheck['id'],
3186
                                    api_get_session_id()
3187
                                );
3188
                            }
3189
3190
                            if (!empty($documentInfo) && isset($documentInfo['insert_user_id'])) {
3191
                                $authorId = $documentInfo['insert_user_id'];
3192
                            }*/
3193
                        }
3194
3195
                        if ($authorId == $userId) {
3196
                            $result = true;
3197
                        }
3198
                    }
3199
                }
3200
                break;
3201
            case self::DOCUMENT_MODE_READ_ONLY:
3202
                // Student cannot upload content, cannot modify another content.
3203
                $result = false;
3204
                break;
3205
            case self::DOCUMENT_MODE_COLLABORATION:
3206
                // Student can upload content, can modify another content.
3207
                $isMember = self::is_subscribed($userId, $groupInfo);
3208
                if ($isMember) {
3209
                    $result = true;
3210
                }
3211
                break;
3212
        }
3213
3214
        if ($blockPage && false == $result) {
3215
            api_not_allowed(true);
3216
        }
3217
3218
        return $result;
3219
    }
3220
}
3221