Passed
Push — master ( f1b610...33f510 )
by Julito
10:14
created

GroupManager::getStudents()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 27
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 13
nc 4
nop 2
dl 0
loc 27
rs 9.8333
c 0
b 0
f 0
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 CGroup[]
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()->getResult();
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
        $returnEntityList = false
114
    ) {
115
        $course_info = empty($course_info) ? api_get_course_info() : $course_info;
116
117
        if (empty($course_info)) {
118
            return [];
119
        }
120
121
        $sessionId = empty($sessionId) ? api_get_session_id() : (int) $sessionId;
122
        $course_id = $course_info['real_id'];
123
124
        $repo = Container::getGroupRepository();
125
        $course = api_get_course_entity($course_id);
126
        $session = api_get_session_entity($sessionId);
127
        //$group = api_get_group_entity(api_get_group_id());
128
        $group = null;
129
        $qb = $repo->getResourcesByCourse($course, $session, $group);
130
131
        if (null === $categoryId) {
132
            $qb
133
                ->andWhere('resource.category is NULL');
134
        } else {
135
            $qb
136
                ->andWhere('resource.category = :category')
137
                ->setParameter('category', $categoryId);
138
        }
139
140
        if (!empty($filterByKeyword)) {
141
            $qb->andWhere($qb->expr()->like('resource.name', ':keyword'));
142
            $qb->setParameter('keyword', "%$filterByKeyword%");
143
        }
144
145
        if ($getCount) {
146
            $qb->select('count(resource)');
147
148
            return $qb->getQuery()->getSingleScalarResult();
149
        }
150
151
        if ($returnEntityList) {
152
            return $qb->getQuery()->getResult();
153
        }
154
155
        return $qb->getQuery()->getArrayResult();
156
157
        $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...
158
159
        $select = ' g.iid,
160
                    g.name,
161
                    g.description,
162
                    g.category_id,
163
                    g.max_student maximum_number_of_members,
164
                    g.secret_directory,
165
                    g.self_registration_allowed,
166
                    g.self_unregistration_allowed,
167
                    g.status
168
                    ';
169
        if ($getCount) {
170
            $select = ' DISTINCT count(g.iid) as count ';
171
        }
172
173
        $sql = "SELECT
174
                $select
175
                FROM $table_group g
176
                WHERE 1 = 1 ";
177
178
        if (!is_null($categoryId)) {
179
            $sql .= " AND g.category_id = '".intval($categoryId)."' ";
180
            $session_condition = api_get_session_condition($sessionId);
181
            if (!empty($session_condition)) {
182
                //$sql .= $session_condition;
183
            }
184
        } else {
185
            $session_condition = api_get_session_condition($sessionId, true);
186
        }
187
188
        $session_condition = '';
189
190
        if (!is_null($status)) {
191
            $sql .= " AND g.status = '".intval($status)."' ";
192
        }
193
194
        //$sql .= " AND g.c_id = $course_id ";
195
        if ($notInGroup) {
196
            $sql .= "  AND (g.category_id IS NULL OR g.category_id = 0) ";
197
        }
198
199
        if (!empty($session_condition)) {
200
            $sql .= $session_condition;
201
        }
202
        $sql .= ' ORDER BY UPPER(g.name)';
203
204
        $result = Database::query($sql);
205
206
        if ($getCount) {
207
            $row = Database::fetch_array($result);
208
209
            return $row['count'];
210
        }
211
212
        $groups = [];
213
        while ($thisGroup = Database::fetch_array($result)) {
214
            $thisGroup['number_of_members'] = count(self::get_subscribed_users($thisGroup));
215
            if (0 != $thisGroup['session_id']) {
216
                $sql = 'SELECT name FROM '.Database::get_main_table(TABLE_MAIN_SESSION).'
217
                        WHERE id='.$thisGroup['session_id'];
218
                $rs_session = Database::query($sql);
219
                if (Database::num_rows($rs_session) > 0) {
220
                    $thisGroup['session_name'] = Database::result($rs_session, 0, 0);
221
                }
222
            }
223
            $groups[] = $thisGroup;
224
        }
225
226
        return $groups;
227
    }
228
229
    /**
230
     * Create a group.
231
     *
232
     * @param string $name        The name for this group
233
     * @param int    $category_id
234
     * @param int    $tutor       The user-id of the group's tutor
235
     * @param int    $places      How many people can subscribe to the new group
236
     *
237
     * @return int
238
     */
239
    public static function create_group($name, $category_id, $tutor, $places)
240
    {
241
        $_course = api_get_course_info();
242
        $session_id = api_get_session_id();
243
        $course_id = $_course['real_id'];
244
        $category = self::get_category($category_id);
245
        $places = (int) $places;
246
247
        // Default values
248
        $docState = self::TOOL_PRIVATE;
249
        $calendarState = self::TOOL_PRIVATE;
250
        $workState = self::TOOL_PRIVATE;
251
        $anonuncementState = self::TOOL_PRIVATE;
252
        $forumState = self::TOOL_PRIVATE;
253
        $wikiState = self::TOOL_PRIVATE;
254
        $chatState = self::TOOL_PRIVATE;
255
        $selfRegAllowed = 0;
256
        $selfUnregAllwoed = 0;
257
        $documentAccess = 0;
258
259
        if ($category) {
260
            if (0 == $places) {
261
                //if the amount of users per group is not filled in, use the setting from the category
262
                $places = $category['max_student'];
263
            } else {
264
                if ($places > $category['max_student'] && 0 != $category['max_student']) {
265
                    $places = $category['max_student'];
266
                }
267
            }
268
            $docState = $category['doc_state'];
269
            $calendarState = $category['calendar_state'];
270
            $workState = $category['work_state'];
271
            $anonuncementState = $category['announcements_state'];
272
            $forumState = $category['forum_state'];
273
            $wikiState = $category['wiki_state'];
274
            $chatState = $category['chat_state'];
275
            $selfRegAllowed = $category['self_reg_allowed'];
276
            $selfUnregAllwoed = $category['self_unreg_allowed'];
277
            $documentAccess = isset($category['document_access']) ? $category['document_access'] : 0;
278
        }
279
280
        $course = api_get_course_entity($course_id);
281
        $session = api_get_session_entity($session_id);
282
283
        $category = null;
284
        if (!empty($category_id)) {
285
            $category = Container::getGroupCategoryRepository()->find($category_id);
286
        }
287
288
        $group = new CGroup();
289
        $group
290
            ->setName($name)
291
            ->setCategory($category)
292
            ->setMaxStudent($places)
293
            ->setDocState($docState)
294
            ->setCalendarState($calendarState)
295
            ->setWorkState($workState)
296
            ->setForumState($forumState)
297
            ->setWikiState($wikiState)
298
            ->setAnnouncementsState($anonuncementState)
299
            ->setChatState($chatState)
300
            ->setSelfRegistrationAllowed($selfRegAllowed)
301
            ->setSelfUnregistrationAllowed($selfUnregAllwoed)
302
            ->setDocumentAccess($documentAccess)
303
            ->setParent($course)
304
            ->addCourseLink($course, $session)
305
        ;
306
307
        $repo = Container::getGroupRepository();
308
        $repo->create($group);
309
        $lastId = $group->getIid();
310
311
        if ($lastId) {
312
            /*$desired_dir_name = '/'.api_replace_dangerous_char($name).'_groupdocs';
313
314
            $newFolderData = create_unexisting_directory(
315
                $_course,
316
                api_get_user_id(),
317
                $session_id,
318
                $lastId,
319
                null,
320
                null,
321
                    $desired_dir_name,
322
                $desired_dir_name,
323
                1
324
            );*/
325
326
            //$unique_name = $newFolderData->getPath();
327
328
            /* Stores the directory path into the group table */
329
            /*$sql = "UPDATE $table_group SET
330
                        name = '".Database::escape_string($name)."',
331
                        secret_directory = '".$unique_name."'
332
                    WHERE c_id = $course_id AND id ='".$lastId."'";
333
334
            Database::query($sql);*/
335
336
            // create a forum if needed
337
            if ($forumState >= 0) {
338
                require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
339
340
                $forumName = get_lang('Group forums');
341
                $repo = Container::getForumCategoryRepository();
342
                $criteria = ['cId' => $course_id, 'catTitle' => $forumName];
343
                $category = $repo->findOneBy($criteria);
344
345
                if (empty($category)) {
346
                    $categoryParam = [
347
                        'forum_category_title' => $forumName,
348
                    ];
349
                    $categoryId = store_forumcategory($categoryParam);
350
                } else {
351
                    $categoryId = $category->getIid();
352
                }
353
354
                $values = [];
355
                $values['forum_title'] = $name;
356
                $values['group_id'] = $lastId;
357
                $values['forum_category'] = $categoryId;
358
                $values['allow_anonymous_group']['allow_anonymous'] = 0;
359
                $values['students_can_edit_group']['students_can_edit'] = 0;
360
                $values['approval_direct_group']['approval_direct'] = 0;
361
                $values['allow_attachments_group']['allow_attachments'] = 1;
362
                $values['allow_new_threads_group']['allow_new_threads'] = 1;
363
                $values['default_view_type_group']['default_view_type'] = api_get_setting('default_forum_view');
364
                $values['group_forum'] = $lastId;
365
                if ('1' == $forumState) {
366
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'public';
367
                } elseif ('2' == $forumState) {
368
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'private';
369
                } elseif ('0' == $forumState) {
370
                    $values['public_private_group_forum_group']['public_private_group_forum'] = 'unavailable';
371
                }
372
                store_forum($values);
373
            }
374
        }
375
376
        return $lastId;
377
    }
378
379
    /**
380
     * Create subgroups.
381
     * This function creates new groups based on an existing group. It will
382
     * create the specified number of groups and fill those groups with users
383
     * from the base group.
384
     *
385
     * @param int $group_id         the group from which subgroups have to be created
386
     * @param int $number_of_groups The number of groups that have to be created
387
     */
388
    public static function create_subgroups($group_id, $number_of_groups)
389
    {
390
        $courseId = api_get_course_int_id();
391
        $table_group = Database::get_course_table(TABLE_GROUP);
392
        $category_id = self::create_category(
393
            get_lang('Subgroups'),
394
            '',
395
            self::TOOL_PRIVATE,
396
            self::TOOL_PRIVATE,
397
            0,
398
            0,
399
            1,
400
            1
401
        );
402
        $users = self::get_users($group_id);
403
        $group_ids = [];
404
405
        for ($group_nr = 1; $group_nr <= $number_of_groups; $group_nr++) {
406
            $group_ids[] = self::create_group(
407
                get_lang('Subgroup').' '.$group_nr,
408
                $category_id,
409
                0,
410
                0
411
            );
412
        }
413
414
        $members = [];
415
        foreach ($users as $index => $user_id) {
416
            $groupId = $group_ids[$index % $number_of_groups];
417
            self::subscribeUsers(
418
                $user_id,
419
                api_get_group_entity($groupId)
420
            );
421
            $members[$group_ids[$groupId]]++;
422
        }
423
424
        foreach ($members as $group_id => $places) {
425
            $sql = "UPDATE $table_group SET max_student = $places
426
                    WHERE c_id = $courseId  AND id = $group_id";
427
            Database::query($sql);
428
        }
429
    }
430
431
    /**
432
     * Create a group for every class subscribed to the current course.
433
     *
434
     * @param int $categoryId The category in which the groups should be created
435
     *
436
     * @return array
437
     */
438
    public static function create_class_groups($categoryId)
439
    {
440
        $options['where'] = [' usergroup.course_id = ? ' => api_get_course_int_id()];
441
        $obj = new UserGroup();
442
        $classes = $obj->getUserGroupInCourse($options);
443
        $group_ids = [];
444
445
        foreach ($classes as $class) {
446
            $userList = $obj->get_users_by_usergroup($class['id']);
447
            $groupId = self::create_group(
448
                $class['name'],
449
                $categoryId,
450
                0,
451
                null
452
            );
453
454
            if ($groupId) {
455
                self::subscribeUsers($userList, api_get_group_entity($groupId));
456
                $group_ids[] = $groupId;
457
            }
458
        }
459
460
        return $group_ids;
461
    }
462
463
    /**
464
     * Deletes groups and their data.
465
     *
466
     * @author Christophe Gesche <[email protected]>
467
     * @author Hugues Peeters <[email protected]>
468
     * @author Bart Mollet
469
     *
470
     * @param string $course_code Default is current course
471
     *
472
     * @return int - number of groups deleted
473
     */
474
    public static function deleteGroup(CGroup $group, $course_code = null)
475
    {
476
        if (empty($group)) {
477
            return false;
478
        }
479
        $course_info = api_get_course_info($course_code);
480
        if (empty($course_info)) {
481
            return false;
482
        }
483
484
        $em = Database::getManager();
485
        $groupIid = $group->getIid();
486
487
        // Unsubscribe all users
488
        self::unsubscribeAllUsers($groupIid);
489
        self::unsubscribe_all_tutors($groupIid);
490
491
        $em
492
            ->createQuery(
493
                'DELETE FROM ChamiloCourseBundle:CForumForum f WHERE f.forumOfGroup = :group'
494
            )
495
            ->execute(['group' => $groupIid]);
496
497
        // delete the groups
498
        $repo = Container::getGroupRepository();
499
        $em->remove($group);
500
        $em->flush();
501
502
        return true;
503
    }
504
505
    /**
506
     * @deprecated Should be deleted by the resources.
507
     *
508
     * Function needed only when deleting a course, in order to be sure that all group ids are deleted.
509
     *
510
     * @param int $courseId
511
     *
512
     * @return bool
513
     */
514
    public static function deleteAllGroupsFromCourse($courseId)
515
    {
516
        $courseId = (int) $courseId;
517
518
        if (empty($courseId)) {
519
            return false;
520
        }
521
522
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
523
        $sql = "SELECT iid FROM $table
524
                WHERE c_id = $courseId ";
525
        Database::query($sql);
526
527
        // Database table definitions
528
        $table = Database::get_course_table(TABLE_GROUP_USER);
529
        $sql = "DELETE FROM $table
530
                WHERE c_id = $courseId";
531
        Database::query($sql);
532
533
        $table = Database::get_course_table(TABLE_GROUP_TUTOR);
534
        $sql = "DELETE FROM $table
535
                WHERE c_id = $courseId";
536
        Database::query($sql);
537
538
        $groupTable = Database::get_course_table(TABLE_GROUP);
539
        $sql = "DELETE FROM $groupTable
540
                WHERE c_id = $courseId";
541
        Database::query($sql);
542
543
        return true;
544
    }
545
546
    /**
547
     * Get group properties.
548
     *
549
     * @param int $group_id the group from which properties are requested
550
     *
551
     * @return array All properties. Array-keys are:
552
     *               name, tutor_id, description, maximum_number_of_students,
553
     *               directory and visibility of tools
554
     */
555
    public static function get_group_properties($group_id)
556
    {
557
        $group_id = (int) $group_id;
558
559
        if (empty($group_id)) {
560
            return null;
561
        }
562
563
        $table_group = Database::get_course_table(TABLE_GROUP);
564
565
        $sql = "SELECT * FROM $table_group
566
                WHERE iid = ".$group_id;
567
568
        $db_result = Database::query($sql);
569
        $db_object = Database::fetch_object($db_result);
570
571
        $result = [];
572
        if ($db_object) {
573
            $result['id'] = $db_object->iid;
574
            $result['iid'] = $db_object->iid;
575
            $result['name'] = $db_object->name;
576
            $result['status'] = $db_object->status;
577
            $result['description'] = $db_object->description;
578
            $result['maximum_number_of_students'] = $db_object->max_student;
579
            $result['max_student'] = $db_object->max_student;
580
            $result['doc_state'] = $db_object->doc_state;
581
            $result['work_state'] = $db_object->work_state;
582
            $result['calendar_state'] = $db_object->calendar_state;
583
            $result['announcements_state'] = $db_object->announcements_state;
584
            $result['forum_state'] = $db_object->forum_state;
585
            $result['wiki_state'] = $db_object->wiki_state;
586
            $result['chat_state'] = $db_object->chat_state;
587
            $result['directory'] = $db_object->secret_directory;
588
            $result['self_registration_allowed'] = $db_object->self_registration_allowed;
589
            $result['self_unregistration_allowed'] = $db_object->self_unregistration_allowed;
590
            $result['count_users'] = count(
591
                self::get_subscribed_users($result)
592
            );
593
            /*$result['count_tutor'] = count(
594
                self::get_subscribed_tutors($result)
595
            );*/
596
            //$result['count_all'] = $result['count_users'] + $result['count_tutor'];
597
            $result['count_all'] = null;
598
            $result['document_access'] = isset($db_object->document_access) ? $db_object->document_access : self::DOCUMENT_MODE_SHARE;
599
        }
600
601
        return $result;
602
    }
603
604
    /**
605
     * @param string $name
606
     * @param string $courseCode
607
     * @param int    $sessionId
608
     *
609
     * @return array
610
     */
611
    public static function getGroupByName($name, $courseCode = null, $sessionId = 0)
612
    {
613
        $name = trim($name);
614
615
        if (empty($name)) {
616
            return [];
617
        }
618
619
        $course_info = api_get_course_info($courseCode);
620
        $course_id = $course_info['real_id'];
621
        $name = Database::escape_string($name);
622
        $sessionId = empty($sessionId) ? api_get_session_id() : (int) $sessionId;
623
        $sessionCondition = api_get_session_condition($sessionId);
624
625
        $table = Database::get_course_table(TABLE_GROUP);
626
        $sql = "SELECT * FROM $table
627
                WHERE
628
                  c_id = $course_id AND
629
                  name = '$name'
630
                  $sessionCondition
631
                LIMIT 1";
632
        $res = Database::query($sql);
633
        $group = [];
634
        if (Database::num_rows($res)) {
635
            $group = Database::fetch_array($res, 'ASSOC');
636
        }
637
638
        return $group;
639
    }
640
641
    /**
642
     * Set group properties
643
     * Changes the group's properties.
644
     *
645
     * @param int       Group Id
646
     * @param string    Group name
647
     * @param string    Group description
648
     * @param int       Max number of students in group
649
     * @param int       Document tool's visibility (0=none,1=private,2=public)
650
     * @param int       Work tool's visibility (0=none,1=private,2=public)
651
     * @param int       Calendar tool's visibility (0=none,1=private,2=public)
652
     * @param int       Announcement tool's visibility (0=none,1=private,2=public)
653
     * @param int       Forum tool's visibility (0=none,1=private,2=public)
654
     * @param int       Wiki tool's visibility (0=none,1=private,2=public)
655
     * @param int       Chat tool's visibility (0=none,1=private,2=public)
656
     * @param bool Whether self registration is allowed or not
657
     * @param bool Whether self unregistration is allowed or not
658
     * @param int $categoryId
659
     * @param int $documentAccess
660
     *
661
     * @return bool TRUE if properties are successfully changed, false otherwise
662
     */
663
    public static function set_group_properties(
664
        $group_id,
665
        $name,
666
        $description,
667
        $maxStudent,
668
        $docState,
669
        $workState,
670
        $calendarState,
671
        $anonuncementState,
672
        $forumState,
673
        $wikiState,
674
        $chatState,
675
        $selfRegistrationAllowed,
676
        $selfUnRegistrationAllowed,
677
        $categoryId = null,
678
        $documentAccess = 0
679
    ) {
680
        $table_forum = Database::get_course_table(TABLE_FORUM);
681
        $categoryId = (int) $categoryId;
682
        $group_id = (int) $group_id;
683
        $repo = Container::getGroupRepository();
684
685
        /** @var CGroup $group */
686
        $group = $repo->find($group_id);
687
688
        $category = null;
689
        if (!empty($categoryId)) {
690
            $category = Container::getGroupCategoryRepository()->find($categoryId);
691
        }
692
693
        $group
694
            ->setName($name)
695
            ->setCategory($category)
696
            ->setMaxStudent($maxStudent)
697
            ->setDocState($docState)
698
            ->setCalendarState($calendarState)
699
            ->setWorkState($workState)
700
            ->setForumState($forumState)
701
            ->setWikiState($wikiState)
702
            ->setAnnouncementsState($anonuncementState)
703
            ->setChatState($chatState)
704
            ->setSelfRegistrationAllowed($selfRegistrationAllowed)
705
            ->setSelfUnregistrationAllowed($selfUnRegistrationAllowed)
706
            ->setDocumentAccess($documentAccess)
707
        ;
708
709
        $repo->update($group);
710
711
        /* Here we are updating a field in the table forum_forum that perhaps
712
        duplicates the table group_info.forum_state cvargas*/
713
        $forumState = (int) $forumState;
714
        $sql2 = "UPDATE $table_forum SET ";
715
        if (1 === $forumState) {
716
            $sql2 .= " forum_group_public_private='public' ";
717
        } elseif (2 === $forumState) {
718
            $sql2 .= " forum_group_public_private='private' ";
719
        } elseif (0 === $forumState) {
720
            $sql2 .= " forum_group_public_private='unavailable' ";
721
        }
722
        $sql2 .= ' WHERE forum_of_group='.$group_id;
723
        Database::query($sql2);
724
725
        return true;
726
    }
727
728
    /**
729
     * Get the total number of groups for the current course.
730
     *
731
     * @return int the number of groups for the current course
732
     */
733
    public static function get_number_of_groups()
734
    {
735
        $repo = Container::getGroupRepository();
736
737
        $course = api_get_course_entity(api_get_course_int_id());
738
        $session = api_get_session_entity(api_get_session_id());
739
        $group = api_get_group_entity(api_get_group_id());
740
741
        $qb = $repo->getResourcesByCourse($course, $session, $group);
742
        $qb->select('count(resource)');
743
744
        return $qb->getQuery()->getSingleScalarResult();
745
746
        $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...
747
        $table = Database::get_course_table(TABLE_GROUP);
748
        $sql = "SELECT COUNT(id) AS number_of_groups
749
                FROM $table
750
                WHERE c_id = $courseId ";
751
        $res = Database::query($sql);
752
        $obj = Database::fetch_object($res);
753
754
        return $obj->number_of_groups;
755
    }
756
757
    /**
758
     * Get all categories.
759
     */
760
    public static function get_categories(Course $course = null): array
761
    {
762
        $repo = Container::getGroupCategoryRepository();
763
764
        if (null === $course) {
765
            $course = api_get_course_entity(api_get_course_int_id());
766
        }
767
768
        $session = api_get_session_entity(api_get_session_id());
769
        //$group = api_get_group_entity(api_get_group_id());
770
        $group = null;
771
772
        $qb = $repo->getResourcesByCourse($course, $session, $group);
773
774
        return $qb->getQuery()->getArrayResult();
775
776
        $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...
777
        $courseId = $course_info['real_id'];
778
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
779
        $sql = "SELECT * FROM $table
780
                WHERE c_id = $courseId
781
                ORDER BY display_order";
782
        $res = Database::query($sql);
783
        $cats = [];
784
        while ($cat = Database::fetch_array($res)) {
785
            $cats[] = $cat;
786
        }
787
788
        return $cats;
789
    }
790
791
    /**
792
     * Get a group category.
793
     *
794
     * @param int    $id          The category id
795
     * @param string $course_code The course (default = current course)
796
     *
797
     * @return array
798
     */
799
    public static function get_category($id, $course_code = null)
800
    {
801
        if (empty($id)) {
802
            return [];
803
        }
804
805
        $courseInfo = api_get_course_info($course_code);
806
        $courseId = $courseInfo['real_id'];
807
        $id = intval($id);
808
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
809
        $sql = "SELECT * FROM $table
810
                WHERE  iid = $id
811
                LIMIT 1";
812
        $res = Database::query($sql);
813
814
        return Database::fetch_array($res);
815
    }
816
817
    /**
818
     * Get a group category.
819
     *
820
     * @param string $title
821
     * @param string $course_code The course (default = current course)
822
     *
823
     * @return array
824
     */
825
    public static function getCategoryByTitle($title, $course_code = null)
826
    {
827
        $title = trim($title);
828
829
        if (empty($title)) {
830
            return [];
831
        }
832
833
        $course_info = api_get_course_info($course_code);
834
        $courseId = $course_info['real_id'];
835
        $title = Database::escape_string($title);
836
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
837
        $sql = "SELECT * FROM $table
838
                WHERE c_id = $courseId AND title = '$title'
839
                LIMIT 1";
840
        $res = Database::query($sql);
841
        $category = [];
842
        if (Database::num_rows($res)) {
843
            $category = Database::fetch_array($res, 'ASSOC');
844
        }
845
846
        return $category;
847
    }
848
849
    /**
850
     * Get the unique category of a given group.
851
     *
852
     * @param int    $group_id    The iid of the group
853
     * @param string $course_code The course in which the group is (default =
854
     *                            current course)
855
     *
856
     * @return array The category
857
     */
858
    public static function get_category_from_group($group_id, $course_code = '')
859
    {
860
        $table_group = Database::get_course_table(TABLE_GROUP);
861
        $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
862
863
        $group_id = (int) $group_id;
864
865
        if (empty($group_id)) {
866
            return [];
867
        }
868
869
        $course_info = api_get_course_info($course_code);
870
871
        if (empty($course_info)) {
872
            return false;
873
        }
874
875
        $sql = "SELECT gc.* FROM $table_group_cat gc
876
                INNER JOIN $table_group g
877
                ON (gc.iid = g.category_id)
878
                WHERE
879
                    g.iid = $group_id
880
                LIMIT 1";
881
        $res = Database::query($sql);
882
        $cat = [];
883
        if (Database::num_rows($res)) {
884
            $cat = Database::fetch_array($res);
885
        }
886
887
        return $cat;
888
    }
889
890
    /**
891
     * Delete a group category.
892
     *
893
     * @param int    $cat_id      The id of the category to delete
894
     * @param string $course_code The code in which the category should be
895
     *                            deleted (default = current course)
896
     *
897
     * @return bool
898
     */
899
    public static function delete_category($cat_id, $course_code = '')
900
    {
901
        $course_info = api_get_course_info($course_code);
902
        if (empty($course_info)) {
903
            return false;
904
        }
905
        $course_id = $course_info['real_id'];
906
907
        $table_group = Database::get_course_table(TABLE_GROUP);
908
        $table_group_cat = Database::get_course_table(TABLE_GROUP_CATEGORY);
909
        $cat_id = (int) $cat_id;
910
        $sql = "SELECT iid FROM $table_group
911
                WHERE category_id='".$cat_id."'";
912
        $res = Database::query($sql);
913
        if (Database::num_rows($res) > 0) {
914
            while ($group = Database::fetch_object($res)) {
915
                // Delete all groups in category
916
                /*$groupInfo = self::get_group_properties($group->iid, true);
917
                self::deleteGroup($groupInfo, $course_code);
918
                */
919
                // Set the category to NULL to avoid losing groups in sessions.
920
                $sql = "UPDATE $table_group SET category_id = NULL WHERE iid = ".$group->iid;
921
                Database::query($sql);
922
            }
923
        }
924
925
        $category = Database::getManager()->getRepository(CGroupCategory::class)->find($cat_id);
926
        if ($category) {
927
            Database::getManager()->remove($category);
928
            Database::getManager()->flush();
929
        }
930
931
        /*$sql = "DELETE FROM $table_group_cat
932
                WHERE iid='".$cat_id."'";
933
        Database::query($sql);*/
934
935
        return true;
936
    }
937
938
    /**
939
     * Create group category.
940
     *
941
     * @param string $title                     The title of the new category
942
     * @param string $description               The description of the new category
943
     * @param int    $selfRegistrationAllowed   allow users to self register
944
     * @param int    $selfUnRegistrationAllowed allow user to self unregister
945
     * @param int    $documentAccess            document access
946
     *
947
     * @return mixed
948
     */
949
    public static function create_category(
950
        $title,
951
        $description,
952
        $docState,
953
        $workState,
954
        $calendarState,
955
        $anonuncementState,
956
        $forumState,
957
        $wikiState,
958
        $chatState = 1,
959
        $selfRegistrationAllowed = 0,
960
        $selfUnRegistrationAllowed = 0,
961
        $maxStudent = 8,
962
        $groupsPerUser = 0,
963
        $documentAccess = 0
964
    ) {
965
        if (empty($title)) {
966
            return false;
967
        }
968
        /*$sql = "SELECT MAX(display_order)+1 as new_order
969
                FROM $table
970
                WHERE c_id = $course_id ";
971
        $res = Database::query($sql);
972
        $obj = Database::fetch_object($res);
973
        if (!isset($obj->new_order)) {
974
            $obj->new_order = 1;
975
        }*/
976
977
        $course = api_get_course_entity(api_get_course_int_id());
978
        $session = api_get_session_entity(api_get_session_id());
979
980
        $category = new CGroupCategory();
981
        $category
982
            ->setTitle($title)
983
            ->setDescription($description)
984
            ->setMaxStudent($maxStudent)
985
            ->setDocState($docState)
986
            ->setCalendarState($calendarState)
987
            ->setWorkState($workState)
988
            ->setForumState($forumState)
989
            ->setWikiState($wikiState)
990
            ->setAnnouncementsState($anonuncementState)
991
            ->setChatState($chatState)
992
            ->setSelfRegAllowed($selfRegistrationAllowed)
993
            ->setSelfUnregAllowed($selfUnRegistrationAllowed)
994
            ->setDocumentAccess($documentAccess)
995
            ->setGroupsPerUser($groupsPerUser)
996
            ->setParent($course)
997
            ->addCourseLink($course, $session)
998
        ;
999
1000
        $repo = Container::getGroupCategoryRepository();
1001
        $repo->create($category);
1002
1003
        return $category->getIid();
1004
    }
1005
1006
    /**
1007
     * Update group category.
1008
     *
1009
     * @param int    $id
1010
     * @param string $title
1011
     * @param string $description
1012
     * @param $doc_state
1013
     * @param $work_state
1014
     * @param $calendar_state
1015
     * @param $announcements_state
1016
     * @param $forum_state
1017
     * @param $wiki_state
1018
     * @param $chat_state
1019
     * @param $selfRegistrationAllowed
1020
     * @param $selfUnRegistrationAllowed
1021
     * @param $maximum_number_of_students
1022
     * @param $groups_per_user
1023
     * @param $documentAccess
1024
     */
1025
    public static function update_category(
1026
        $id,
1027
        $title,
1028
        $description,
1029
        $doc_state,
1030
        $work_state,
1031
        $calendar_state,
1032
        $announcements_state,
1033
        $forum_state,
1034
        $wiki_state,
1035
        $chat_state,
1036
        $selfRegistrationAllowed,
1037
        $selfUnRegistrationAllowed,
1038
        $maximum_number_of_students,
1039
        $groups_per_user,
1040
        $documentAccess
1041
    ) {
1042
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
1043
        $id = (int) $id;
1044
1045
        $allowDocumentAccess = api_get_configuration_value('group_category_document_access');
1046
        $documentCondition = '';
1047
        if ($allowDocumentAccess) {
1048
            $documentAccess = (int) $documentAccess;
1049
            $documentCondition = " document_access = $documentAccess, ";
1050
        }
1051
1052
        $sql = 'UPDATE '.$table." SET
1053
                    title='".Database::escape_string($title)."',
1054
                    description='".Database::escape_string($description)."',
1055
                    doc_state = '".Database::escape_string($doc_state)."',
1056
                    work_state = '".Database::escape_string($work_state)."',
1057
                    calendar_state = '".Database::escape_string($calendar_state)."',
1058
                    announcements_state = '".Database::escape_string($announcements_state)."',
1059
                    forum_state = '".Database::escape_string($forum_state)."',
1060
                    wiki_state = '".Database::escape_string($wiki_state)."',
1061
                    chat_state = '".Database::escape_string($chat_state)."',
1062
                    groups_per_user   = '".Database::escape_string($groups_per_user)."',
1063
                    self_reg_allowed = '".Database::escape_string($selfRegistrationAllowed)."',
1064
                    self_unreg_allowed = '".Database::escape_string($selfUnRegistrationAllowed)."',
1065
                    $documentCondition
1066
                    max_student = ".intval($maximum_number_of_students)."
1067
                WHERE iid = $id";
1068
        Database::query($sql);
1069
1070
        // Updating all groups inside this category
1071
        $groups = self::get_group_list($id);
1072
1073
        if (!empty($groups)) {
1074
            foreach ($groups as $group) {
1075
                self::set_group_properties(
1076
                    $group['iid'],
1077
                    $group['name'],
1078
                    $group['description'],
1079
                    $maximum_number_of_students,
1080
                    $doc_state,
1081
                    $work_state,
1082
                    $calendar_state,
1083
                    $announcements_state,
1084
                    $forum_state,
1085
                    $wiki_state,
1086
                    $chat_state,
1087
                    $selfRegistrationAllowed,
1088
                    $selfUnRegistrationAllowed,
1089
                    $id,
1090
                    $documentAccess
1091
                );
1092
            }
1093
        }
1094
    }
1095
1096
    /**
1097
     * Returns the number of groups of the user with the greatest number of
1098
     * subscriptions in the given category.
1099
     */
1100
    public static function get_current_max_groups_per_user($category_id = null, $course_code = null)
1101
    {
1102
        $course_info = api_get_course_info($course_code);
1103
        $group_table = Database::get_course_table(TABLE_GROUP);
1104
1105
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1106
        $sql = "SELECT COUNT(gu.group_id) AS current_max
1107
                FROM $group_user_table gu
1108
                INNER JOIN $group_table g
1109
                ON (gu.group_id = g.iid)
1110
                WHERE 1= 1 ";
1111
        if (null != $category_id) {
1112
            $category_id = intval($category_id);
1113
            $sql .= ' AND g.category_id = '.$category_id;
1114
        }
1115
        $sql .= ' GROUP BY gu.user_id
1116
                  ORDER BY current_max DESC LIMIT 1';
1117
1118
        $res = Database::query($sql);
1119
        $obj = Database::fetch_object($res);
1120
1121
        if ($obj) {
1122
            return $obj->current_max;
1123
        }
1124
1125
        return 0;
1126
    }
1127
1128
    /**
1129
     * Swaps the display-order of two categories.
1130
     *
1131
     * @param int $id1 The id of the first category
1132
     * @param int $id2 The id of the second category
1133
     */
1134
    public static function swap_category_order($id1, $id2)
1135
    {
1136
        $table = Database::get_course_table(TABLE_GROUP_CATEGORY);
1137
        $id1 = intval($id1);
1138
        $id2 = intval($id2);
1139
        $course_id = api_get_course_int_id();
1140
1141
        $sql = "SELECT id, display_order FROM $table
1142
                WHERE id IN ($id1,$id2) AND c_id = $course_id ";
1143
        $res = Database::query($sql);
1144
        $cat1 = Database::fetch_object($res);
1145
        $cat2 = Database::fetch_object($res);
1146
        if ($cat1 && $cat2) {
1147
            $sql = "UPDATE $table SET display_order=$cat2->display_order
1148
                    WHERE id = $cat1->id AND c_id = $course_id ";
1149
            Database::query($sql);
1150
1151
            $sql = "UPDATE $table SET display_order=$cat1->display_order
1152
                    WHERE id = $cat2->id AND c_id = $course_id ";
1153
            Database::query($sql);
1154
        }
1155
    }
1156
1157
    /**
1158
     * Get all users from a given group.
1159
     *
1160
     * @param int  $group_id        The group
1161
     * @param bool $load_extra_info
1162
     * @param int  $start
1163
     * @param int  $limit
1164
     * @param bool $getCount
1165
     * @param int  $courseId
1166
     * @param $column
1167
     * @param $direction
1168
     *
1169
     * @return array list of user id
1170
     */
1171
    public static function get_users(
1172
        $group_id,
1173
        $load_extra_info = false,
1174
        $start = null,
1175
        $limit = null,
1176
        $getCount = false,
1177
        $courseId = null,
1178
        $column = null,
1179
        $direction = null
1180
    ) {
1181
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1182
        $groupTable = Database::get_course_table(TABLE_GROUP);
1183
        $user_table = Database::get_main_table(TABLE_MAIN_USER);
1184
        $group_id = (int) $group_id;
1185
1186
        if (empty($courseId)) {
1187
            $courseId = api_get_course_int_id();
1188
        } else {
1189
            $courseId = (int) $courseId;
1190
        }
1191
1192
        $select = ' SELECT u.id, firstname, lastname ';
1193
        if ($getCount) {
1194
            $select = ' SELECT count(u.id) count';
1195
        }
1196
        $sql = "$select
1197
                FROM $group_user_table gu
1198
                INNER JOIN $groupTable g
1199
                ON (gu.group_id = g.iid and g.c_id = gu.c_id)
1200
                INNER JOIN $user_table u
1201
                ON (u.id = gu.user_id)
1202
                WHERE
1203
                    gu.c_id = $courseId AND
1204
                    g.iid = $group_id";
1205
1206
        if (!empty($column) && !empty($direction)) {
1207
            $column = Database::escape_string($column, null, false);
1208
            $direction = ('ASC' == $direction ? 'ASC' : 'DESC');
1209
            $sql .= " ORDER BY $column $direction";
1210
        }
1211
1212
        if (!empty($start) && !empty($limit)) {
1213
            $start = (int) $start;
1214
            $limit = (int) $limit;
1215
            $sql .= " LIMIT $start, $limit";
1216
        }
1217
        $res = Database::query($sql);
1218
        $users = [];
1219
        while ($obj = Database::fetch_object($res)) {
1220
            if ($getCount) {
1221
                return $obj->count;
1222
                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...
1223
            }
1224
            if ($load_extra_info) {
1225
                $users[] = api_get_user_info($obj->id);
1226
            } else {
1227
                $users[] = $obj->id;
1228
            }
1229
        }
1230
1231
        return $users;
1232
    }
1233
1234
    /**
1235
     * @param int $group_id id
1236
     *
1237
     * @return array
1238
     */
1239
    public static function getStudentsAndTutors($group_id)
1240
    {
1241
        $group_user_table = Database::get_course_table(TABLE_GROUP_USER);
1242
        $tutor_user_table = Database::get_course_table(TABLE_GROUP_TUTOR);
1243
        $groupTable = Database::get_course_table(TABLE_GROUP);
1244
1245
        $course_id = api_get_course_int_id();
1246
        $group_id = (int) $group_id;
1247
1248
        $sql = "SELECT user_id
1249
                FROM $group_user_table gu
1250
                INNER JOIN $groupTable g
1251
                ON (gu.group_id = g.iid)
1252
                WHERE g.iid = $group_id";
1253
        $res = Database::query($sql);
1254
        $users = [];
1255
1256
        while ($obj = Database::fetch_object($res)) {
1257
            $users[] = api_get_user_info($obj->user_id);
1258
        }
1259
1260
        $sql = "SELECT user_id
1261
                FROM $tutor_user_table gu
1262
                INNER JOIN $groupTable g
1263
                ON (gu.group_id = g.iid)
1264
                WHERE g.iid = $group_id";
1265
        $res = Database::query($sql);
1266
        while ($obj = Database::fetch_object($res)) {
1267
            $users[] = api_get_user_info($obj->user_id);
1268
        }
1269
1270
        return $users;
1271
    }
1272
1273
    /**
1274
     * Get only tutors from a group.
1275
     *
1276
     * @param array $groupInfo
1277
     *
1278
     * @return array
1279
     */
1280
    public static function getTutors($groupInfo)
1281
    {
1282
        $groupTable = Database::get_course_table(TABLE_GROUP);
1283
        $tutor_user_table = Database::get_course_table(TABLE_GROUP_TUTOR);
1284
        $course_id = api_get_course_int_id();
1285
        $group_id = (int) $groupInfo['iid'];
1286
1287
        $sql = "SELECT user_id
1288
                FROM $tutor_user_table gu
1289
                INNER JOIN $groupTable g
1290
                ON (gu.group_id = g.iid)
1291
                WHERE g.iid = $group_id";
1292
        $res = Database::query($sql);
1293
1294
        $users = [];
1295
        while ($obj = Database::fetch_object($res)) {
1296
            $users[] = api_get_user_info($obj->user_id);
1297
        }
1298
1299
        return $users;
1300
    }
1301
1302
    /**
1303
     * Get only students from a group (not tutors).
1304
     *
1305
     * @param bool $filterOnlyActive
1306
     *
1307
     * @return array
1308
     */
1309
    public static function getStudents($groupId, $filterOnlyActive = false)
1310
    {
1311
        $groupId = (int) $groupId;
1312
        $activeCondition = $filterOnlyActive ? 'AND u.active = 1' : '';
1313
1314
        $em = Database::getManager();
1315
        $subscriptions = $em
1316
            ->createQuery("
1317
                SELECT u.id FROM ChamiloCoreBundle:User u
1318
                INNER JOIN ChamiloCourseBundle:CGroupRelUser gu
1319
                WITH u.id = gu.user
1320
                INNER JOIN ChamiloCourseBundle:CGroup g
1321
                WITH gu.group = g.iid
1322
                WHERE g.iid = :group
1323
                    $activeCondition
1324
            ")
1325
            ->setParameters([
1326
                'group' => $groupId,
1327
            ])
1328
            ->getResult();
1329
1330
        $users = [];
1331
        foreach ($subscriptions as $subscription) {
1332
            $users[] = api_get_user_info($subscription['id']);
1333
        }
1334
1335
        return $users;
1336
    }
1337
1338
    public static function getStudentsCount($groupId, $filterOnlyActive = false)
1339
    {
1340
        $groupId = (int) $groupId;
1341
        $activeCondition = $filterOnlyActive ? 'AND u.active = 1' : '';
1342
1343
        $em = Database::getManager();
1344
1345
        return $em
1346
            ->createQuery("
1347
                SELECT COUNT(u.id) FROM ChamiloCoreBundle:User u
1348
                INNER JOIN ChamiloCourseBundle:CGroupRelUser gu
1349
                WITH u.id = gu.user
1350
                INNER JOIN ChamiloCourseBundle:CGroup g
1351
                WITH gu.group = g.iid
1352
                WHERE g.iid = :group
1353
                    $activeCondition
1354
            ")
1355
            ->setParameters([
1356
                'group' => $groupId,
1357
            ])
1358
            ->getSingleScalarResult();
1359
    }
1360
1361
    /**
1362
     * Returns users belonging to any of the group.
1363
     *
1364
     * @param array $groups list of group ids
1365
     *
1366
     * @return array list of user ids
1367
     */
1368
    public static function get_groups_users($groups = [])
1369
    {
1370
        $result = [];
1371
        $table = Database::get_course_table(TABLE_GROUP_USER);
1372
        $course_id = api_get_course_int_id();
1373
1374
        $groups = array_map('intval', $groups);
1375
        // protect individual elements with surrounding quotes
1376
        $groups = implode(', ', $groups);
1377
        $sql = "SELECT DISTINCT user_id
1378
                FROM $table gu
1379
                WHERE gu.group_id IN ($groups)";
1380
        $rs = Database::query($sql);
1381
        while ($row = Database::fetch_array($rs)) {
1382
            $result[] = $row['user_id'];
1383
        }
1384
1385
        return $result;
1386
    }
1387
1388
    /**
1389
     * Fill the groups with students.
1390
     * The algorithm takes care to first fill the groups with the least # of users.
1391
     * Analysis
1392
     * There was a problem with the "ALL" setting.
1393
     * When max # of groups is set to all, the value is sometimes NULL and sometimes ALL
1394
     * and in both cased the query does not work as expected.
1395
     * Stupid solution (currently implemented: set ALL to a big number (INFINITE) and things are solved :)
1396
     * Better solution: that's up to you.
1397
     *
1398
     * Note
1399
     * Throughout Dokeos there is some confusion about "course id" and "course code"
1400
     * The code is e.g. TEST101, but sometimes a variable that is called courseID also contains a course code string.
1401
     * However, there is also a integer course_id that uniquely identifies the course.
1402
     * ywarnier:> Now the course_id has been removed (25/1/2005)
1403
     * The databases are als very inconsistent in this.
1404
     *
1405
     * @author Chrisptophe Gesche <[email protected]>,
1406
     *         Hugues Peeters     <[email protected]> - original version
1407
     * @author Roan Embrechts - virtual course support, code cleaning
1408
     * @author Bart Mollet - code cleaning, use other GroupManager-functions
1409
     *
1410
     * @return bool
1411
     */
1412
    public static function fillGroupWithUsers(CGroup $group)
1413
    {
1414
        $_course = api_get_course_info();
1415
        if (empty($_course) || empty($group)) {
1416
            return false;
1417
        }
1418
        $session_id = api_get_session_id();
1419
        $complete_user_list = CourseManager::get_user_list_from_course_code(
1420
            $_course['code'],
1421
            $session_id
1422
        );
1423
        $groupIid = $group->getIid();
1424
        $category = self::get_category_from_group($groupIid);
1425
1426
        // Getting max numbers of user from group
1427
        $maxNumberStudents = empty($group->getMaxStudent()) ? self::INFINITE : $group->getMaxStudent();
1428
        $groupsPerUser = self::INFINITE;
1429
        $categoryId = 0;
1430
        if ($category) {
1431
            $groupsPerUser = empty($category['groups_per_user']) ? self::INFINITE : $category['groups_per_user'];
1432
            $maxNumberStudentsCategory = empty($category['max_student']) ? self::INFINITE : $category['max_student'];
1433
            $categoryId = $category['iid'];
1434
            if ($maxNumberStudentsCategory < $maxNumberStudents) {
1435
                $maxNumberStudents = $maxNumberStudentsCategory;
1436
            }
1437
        }
1438
1439
        $usersToAdd = [];
1440
        foreach ($complete_user_list as $userInfo) {
1441
            $isSubscribed = self::is_subscribed($userInfo['user_id'], $group);
1442
            if ($isSubscribed) {
1443
                continue;
1444
            }
1445
            $numberOfGroups = self::user_in_number_of_groups(
1446
                $userInfo['user_id'],
1447
                $categoryId
1448
            );
1449
            if ($groupsPerUser > $numberOfGroups) {
1450
                $usersToAdd[] = $userInfo['user_id'];
1451
            }
1452
            if (count($usersToAdd) == $maxNumberStudents) {
1453
                break;
1454
            }
1455
        }
1456
1457
        foreach ($usersToAdd as $userId) {
1458
            self::subscribeUsers($userId, $group);
1459
        }
1460
    }
1461
1462
    /**
1463
     * Get the number of students in a group.
1464
     *
1465
     * @param int $group_id id
1466
     *
1467
     * @return int number of students in the given group
1468
     */
1469
    public static function number_of_students($group_id, $course_id = null)
1470
    {
1471
        $table = Database::get_course_table(TABLE_GROUP_USER);
1472
        $group_id = (int) $group_id;
1473
        $course_id = (int) $course_id;
1474
1475
        if (empty($course_id)) {
1476
            $course_id = api_get_course_int_id();
1477
        }
1478
        $sql = "SELECT COUNT(*) AS number_of_students
1479
                FROM $table
1480
                WHERE c_id = $course_id AND group_id = $group_id";
1481
        $result = Database::query($sql);
1482
        $db_object = Database::fetch_object($result);
1483
1484
        return $db_object->number_of_students;
1485
    }
1486
1487
    /**
1488
     * Maximum number of students in a group.
1489
     *
1490
     * @param int $group_id iid
1491
     *
1492
     * @return int maximum number of students in the given group
1493
     */
1494
    public static function maximum_number_of_students($group_id)
1495
    {
1496
        $table = Database::get_course_table(TABLE_GROUP);
1497
        $group_id = (int) $group_id;
1498
        $course_id = api_get_course_int_id();
1499
        $sql = "SELECT max_student FROM $table
1500
                WHERE iid = $group_id";
1501
        $db_result = Database::query($sql);
1502
        $db_object = Database::fetch_object($db_result);
1503
        if (0 == $db_object->max_student) {
1504
            return self::INFINITE;
1505
        }
1506
1507
        return $db_object->max_student;
1508
    }
1509
1510
    /**
1511
     * Number of groups of a user.
1512
     *
1513
     * @param int $user_id
1514
     * @param int $cat_id
1515
     *
1516
     * @return int the number of groups the user is subscribed in
1517
     */
1518
    public static function user_in_number_of_groups($user_id, $cat_id = 0)
1519
    {
1520
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1521
        $table_group = Database::get_course_table(TABLE_GROUP);
1522
        $user_id = (int) $user_id;
1523
        $cat_id = (int) $cat_id;
1524
1525
        $course_id = api_get_course_int_id();
1526
        $cat_condition = '';
1527
        if (!empty($cat_id)) {
1528
            $cat_condition = " AND g.category_id =  $cat_id ";
1529
        }
1530
1531
        $sql = "SELECT COUNT(*) AS number_of_groups
1532
                FROM $table_group_user gu
1533
                INNER JOIN $table_group g
1534
                ON (g.iid = gu.group_id)
1535
                WHERE
1536
                    gu.user_id = $user_id
1537
                    $cat_condition";
1538
1539
        $result = Database::query($sql);
1540
        $db_object = Database::fetch_object($result);
1541
1542
        return $db_object->number_of_groups;
1543
    }
1544
1545
    /**
1546
     * Is sef-registration allowed?
1547
     *
1548
     * @param int $user_id
1549
     *
1550
     * @return bool TRUE if self-registration is allowed in the given group
1551
     */
1552
    public static function is_self_registration_allowed($user_id, CGroup $group)
1553
    {
1554
        if (empty($user_id)) {
1555
            return false;
1556
        }
1557
1558
        if ($group) {
1559
            if (0 == $group->getStatus() || 1 != $group->getSelfRegistrationAllowed()) {
1560
                return false;
1561
            }
1562
1563
            return self::canUserSubscribe($user_id, $group);
1564
        }
1565
1566
        return false;
1567
    }
1568
1569
    /**
1570
     * Is sef-unregistration allowed?
1571
     *
1572
     * @param int $user_id
1573
     *
1574
     * @return bool TRUE if self-unregistration is allowed in the given group
1575
     */
1576
    public static function is_self_unregistration_allowed($user_id, CGroup $group)
1577
    {
1578
        if (empty($user_id) || empty($group)) {
1579
            return false;
1580
        }
1581
        if (0 == $group->getStatus() || 1 != $group->getSelfUnregistrationAllowed()) {
1582
            return false;
1583
        }
1584
1585
        return self::is_subscribed($user_id, $group);
1586
    }
1587
1588
    /**
1589
     * Is user subscribed in group?
1590
     *
1591
     * @param int $user_id
1592
     *
1593
     * @return bool TRUE if given user is subscribed in given group
1594
     */
1595
    public static function is_subscribed($user_id, CGroup $group)
1596
    {
1597
        $course_id = api_get_course_int_id();
1598
        if (empty($user_id) || empty($group) || empty($course_id)) {
1599
            return false;
1600
        }
1601
        $table = Database::get_course_table(TABLE_GROUP_USER);
1602
        $group_id = $group->getIid();
1603
        $user_id = (int) $user_id;
1604
1605
        $sql = "SELECT 1 FROM $table
1606
                WHERE
1607
                    group_id = $group_id AND
1608
                    user_id = $user_id
1609
                ";
1610
        $result = Database::query($sql);
1611
1612
        return Database::num_rows($result) > 0;
1613
    }
1614
1615
    /**
1616
     * Can a user subscribe to a specified group in a course.
1617
     *
1618
     * @param int  $user_id
1619
     * @param bool $checkMaxNumberStudents
1620
     *
1621
     * @return bool true if success
1622
     */
1623
    public static function canUserSubscribe(
1624
        $user_id,
1625
        CGroup $group,
1626
        $checkMaxNumberStudents = true
1627
    ) {
1628
        $groupIid = $group->getIid();
1629
        if ($checkMaxNumberStudents) {
1630
            $category = self::get_category_from_group($group->getIid());
1631
            if ($category) {
1632
                if (self::GROUP_PER_MEMBER_NO_LIMIT == $category['groups_per_user']) {
1633
                    $category['groups_per_user'] = self::INFINITE;
1634
                }
1635
                $result = self::user_in_number_of_groups($user_id, $category['iid']) < $category['groups_per_user'];
1636
                if (false == $result) {
1637
                    return false;
1638
                }
1639
            }
1640
1641
            $result = self::number_of_students($groupIid) < self::maximum_number_of_students($groupIid);
1642
1643
            if (false == $result) {
1644
                return false;
1645
            }
1646
        }
1647
1648
        $result = self::isTutorOfGroup($user_id, $group);
1649
1650
        if ($result) {
1651
            return false;
1652
        }
1653
1654
        $result = self::is_subscribed($user_id, $group);
1655
1656
        if ($result) {
1657
            return false;
1658
        }
1659
1660
        return true;
1661
    }
1662
1663
    /**
1664
     * Get all subscribed users (members) from a group.
1665
     *
1666
     * @param array $groupInfo
1667
     *
1668
     * @return array An array with information of all users from the given group.
1669
     *               (user_id, firstname, lastname, email)
1670
     */
1671
    public static function get_subscribed_users($groupInfo)
1672
    {
1673
        if (empty($groupInfo)) {
1674
            return [];
1675
        }
1676
1677
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
1678
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1679
        $order_clause = api_sort_by_first_name() ? ' ORDER BY u.firstname, u.lastname' : ' ORDER BY u.lastname, u.firstname';
1680
        $orderListByOfficialCode = api_get_setting('order_user_list_by_official_code');
1681
        if ('true' === $orderListByOfficialCode) {
1682
            $order_clause = ' ORDER BY u.official_code, u.firstname, u.lastname';
1683
        }
1684
1685
        $group_id = (int) $groupInfo['iid'];
1686
1687
        if (empty($group_id)) {
1688
            return [];
1689
        }
1690
1691
        $course_id = api_get_course_int_id();
1692
1693
        $sql = "SELECT
1694
                    ug.iid,
1695
                    u.id as user_id,
1696
                    u.lastname,
1697
                    u.firstname,
1698
                    u.email,
1699
                    u.username
1700
                FROM $table_user u
1701
                INNER JOIN $table_group_user ug
1702
                ON (ug.user_id = u.id)
1703
                WHERE
1704
                      ug.group_id = $group_id
1705
                $order_clause";
1706
1707
        $db_result = Database::query($sql);
1708
        $users = [];
1709
        while ($user = Database::fetch_object($db_result)) {
1710
            $users[$user->user_id] = [
1711
                'user_id' => $user->user_id,
1712
                'firstname' => $user->firstname,
1713
                'lastname' => $user->lastname,
1714
                'email' => $user->email,
1715
                'username' => $user->username,
1716
            ];
1717
        }
1718
1719
        return $users;
1720
    }
1721
1722
    /**
1723
     * Subscribe user(s) to a specified group in current course (as a student).
1724
     *
1725
     * @param mixed  $userList  Can be an array with user-id's or a single user-id
1726
     * @param CGroup $group
1727
     * @param int    $course_id
1728
     *
1729
     * @return bool
1730
     */
1731
    public static function subscribeUsers($userList, CGroup $group = null, $course_id = null)
1732
    {
1733
        if (empty($group)) {
1734
            return false;
1735
        }
1736
        $userList = is_array($userList) ? $userList : [$userList];
1737
        $course_id = empty($course_id) ? api_get_course_int_id() : (int) $course_id;
1738
        $group_id = $group->getIid();
1739
1740
        if (!empty($userList)) {
1741
            $table = Database::get_course_table(TABLE_GROUP_USER);
1742
            foreach ($userList as $user_id) {
1743
                if (self::canUserSubscribe($user_id, $group)) {
1744
                    $user_id = (int) $user_id;
1745
                    $sql = "INSERT INTO $table (c_id, user_id, group_id, status, role)
1746
                            VALUES ('$course_id', '".$user_id."', '".$group_id."', 0, '')";
1747
                    Database::query($sql);
1748
                }
1749
            }
1750
        }
1751
1752
        return true;
1753
    }
1754
1755
    /**
1756
     * Subscribe tutor(s) to a specified group in current course.
1757
     *
1758
     * @param mixed $userList  Can be an array with user-id's or a single user-id
1759
     * @param array $groupInfo
1760
     * @param int   $course_id
1761
     */
1762
    public static function subscribeTutors($userList, CGroup $group = null, $course_id = 0)
1763
    {
1764
        if (empty($group)) {
1765
            return false;
1766
        }
1767
        $userList = is_array($userList) ? $userList : [$userList];
1768
        $result = true;
1769
        $course_id = isset($course_id) && !empty($course_id) ? intval($course_id) : api_get_course_int_id();
1770
        $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1771
        $groupId = (int) $group->getIid();
1772
1773
        foreach ($userList as $user_id) {
1774
            $user_id = intval($user_id);
1775
            if (self::canUserSubscribe($user_id, $group, false)) {
1776
                $sql = 'INSERT INTO '.$table_group_tutor." (c_id, user_id, group_id)
1777
                        VALUES ('$course_id', '".$user_id."', '".$groupId."')";
1778
                $result = Database::query($sql);
1779
            }
1780
        }
1781
1782
        return $result;
1783
    }
1784
1785
    /**
1786
     * Unsubscribe user(s) from a specified group in current course.
1787
     *
1788
     * @param mixed $userList Can be an array with user-id's or a single user-id
1789
     *
1790
     * @return bool
1791
     */
1792
    public static function unsubscribeUsers($userList, CGroup $group = null)
1793
    {
1794
        if (empty($group)) {
1795
            return false;
1796
        }
1797
        $userList = is_array($userList) ? $userList : [$userList];
1798
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
1799
        $group_id = $group->getIid();
1800
        $course_id = api_get_course_int_id();
1801
        $sql = 'DELETE FROM '.$table_group_user.'
1802
                WHERE
1803
                    group_id = '.$group_id.' AND
1804
                    user_id IN ('.implode(',', $userList).')
1805
                ';
1806
        Database::query($sql);
1807
    }
1808
1809
    /**
1810
     * Unsubscribe all users from one or more groups.
1811
     *
1812
     * @param int $groupId
1813
     *
1814
     * @return bool
1815
     */
1816
    public static function unsubscribeAllUsers($groupId)
1817
    {
1818
        $groupId = (int) $groupId;
1819
        if (empty($groupId)) {
1820
            return false;
1821
        }
1822
1823
        $table = Database::get_course_table(TABLE_GROUP_USER);
1824
        $sql = "DELETE FROM $table
1825
                WHERE
1826
                    group_id = $groupId ";
1827
1828
        return Database::query($sql);
1829
    }
1830
1831
    /**
1832
     * Unsubscribe all tutors from one or more groups.
1833
     *
1834
     * @param int $groupId iid
1835
     *
1836
     * @see unsubscribe_all_users. This function is almost an exact copy of that function.
1837
     *
1838
     * @return bool TRUE if successful
1839
     *
1840
     * @author Patrick Cool <[email protected]>, Ghent University
1841
     */
1842
    public static function unsubscribe_all_tutors($groupId)
1843
    {
1844
        $courseId = api_get_course_int_id();
1845
        $groupId = (int) $groupId;
1846
1847
        if (empty($courseId) || empty($groupId)) {
1848
            return false;
1849
        }
1850
1851
        if (!empty($groupId)) {
1852
            $table_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1853
            $sql = "DELETE FROM $table_group_tutor
1854
                    WHERE group_id = $groupId ";
1855
            Database::query($sql);
1856
        }
1857
1858
        return true;
1859
    }
1860
1861
    /**
1862
     * Is the user a tutor of this group?
1863
     *
1864
     * @todo replace this function with $group->isUserTutor
1865
     */
1866
    public static function isTutorOfGroup($userId, CGroup $group = null)
1867
    {
1868
        if (empty($group)) {
1869
            return false;
1870
        }
1871
1872
        $userId = (int) $userId;
1873
        $group_id = (int) $group->getIid();
1874
1875
        $table = Database::get_course_table(TABLE_GROUP_TUTOR);
1876
1877
        $sql = "SELECT * FROM $table
1878
                WHERE
1879
                    user_id = $userId AND
1880
                    group_id = $group_id";
1881
        $result = Database::query($sql);
1882
1883
        return Database::num_rows($result) > 0;
1884
    }
1885
1886
    /**
1887
     * Is the user part of this group? This can be a tutor or a normal member
1888
     * you should use this function if the access to a tool or functionality is
1889
     * restricted to the people who are actually in the group
1890
     * before you had to check if the user was
1891
     * 1. a member of the group OR
1892
     * 2. a tutor of the group. This function combines both.
1893
     */
1894
    public static function isUserInGroup($user_id, CGroup $group)
1895
    {
1896
        $member = self::is_subscribed($user_id, $group);
1897
        if ($member) {
1898
            return true;
1899
        }
1900
1901
        $tutor = self::isTutorOfGroup($user_id, $group);
1902
        if ($tutor) {
1903
            return true;
1904
        }
1905
1906
        return false;
1907
    }
1908
1909
    /**
1910
     * Get all group's from a given course in which a given user is unsubscribed.
1911
     *
1912
     * @author  Patrick Cool
1913
     *
1914
     * @param int $course_id retrieve the groups for
1915
     * @param int $user_id   the ID of the user you want to know all its group memberships
1916
     *
1917
     * @return array
1918
     */
1919
    public static function get_group_ids($course_id, $user_id)
1920
    {
1921
        $groups = [];
1922
        $tbl_group = Database::get_course_table(TABLE_GROUP_USER);
1923
        $tbl_group_tutor = Database::get_course_table(TABLE_GROUP_TUTOR);
1924
        $user_id = intval($user_id);
1925
        $course_id = intval($course_id);
1926
1927
        $sql = "SELECT group_id FROM $tbl_group
1928
                WHERE user_id = '$user_id'";
1929
        $result = Database::query($sql);
1930
1931
        if ($result) {
1932
            while ($row = Database::fetch_array($result)) {
1933
                $groups[] = $row['group_id'];
1934
            }
1935
        }
1936
1937
        //Also loading if i'm the tutor
1938
        $sql = "SELECT group_id FROM $tbl_group_tutor
1939
                WHERE user_id = '$user_id'";
1940
        $result = Database::query($sql);
1941
        if ($result) {
1942
            while ($row = Database::fetch_array($result)) {
1943
                $groups[] = $row['group_id'];
1944
            }
1945
        }
1946
        if (!empty($groups)) {
1947
            array_filter($groups);
1948
        }
1949
1950
        return $groups;
1951
    }
1952
1953
    /**
1954
     * Check if a user has access to a certain group tool.
1955
     *
1956
     * @param int    $user_id  The user id
1957
     * @param CGroup $group
1958
     * @param string $tool     The tool to check the access rights. This should be
1959
     *                         one of constants: GROUP_TOOL_DOCUMENTS
1960
     *
1961
     * @return bool true if the given user has access to the given tool in the
1962
     *              given course
1963
     */
1964
    public static function userHasAccess($user_id, CGroup $group = null, $tool)
1965
    {
1966
        if (null === $group) {
1967
            return false;
1968
        }
1969
1970
        // Admin have access everywhere
1971
        if (api_is_platform_admin()) {
1972
            return true;
1973
        }
1974
1975
        // Course admin also have access to everything
1976
        if (api_is_allowed_to_edit(false, true, true)) {
1977
            return true;
1978
        }
1979
1980
        if (0 == $group->getStatus()) {
1981
            return false;
1982
        }
1983
1984
        switch ($tool) {
1985
            case self::GROUP_TOOL_FORUM:
1986
                $toolStatus = $group->getForumState();
1987
                break;
1988
            case self::GROUP_TOOL_DOCUMENTS:
1989
                $toolStatus = $group->getDocState();
1990
                break;
1991
            case self::GROUP_TOOL_CALENDAR:
1992
                $toolStatus = $group->getCalendarState();
1993
                break;
1994
            case self::GROUP_TOOL_ANNOUNCEMENT:
1995
                $toolStatus = $group->getAnnouncementsState();
1996
                break;
1997
            case self::GROUP_TOOL_WORK:
1998
                $toolStatus = $group->getWorkState();
1999
                break;
2000
            case self::GROUP_TOOL_WIKI:
2001
                $toolStatus = $group->getWikiState();
2002
                break;
2003
            case self::GROUP_TOOL_CHAT:
2004
                $toolStatus = $group->getChatState();
2005
                break;
2006
            default:
2007
                return false;
2008
        }
2009
2010
        switch ($toolStatus) {
2011
            case self::TOOL_NOT_AVAILABLE:
2012
                return false;
2013
                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...
2014
            case self::TOOL_PUBLIC:
2015
                return true;
2016
                break;
2017
            case self::TOOL_PRIVATE:
2018
                $userIsInGroup = self::isUserInGroup($user_id, $group);
2019
                if ($userIsInGroup) {
2020
                    return true;
2021
                }
2022
                break;
2023
            case self::TOOL_PRIVATE_BETWEEN_USERS:
2024
                // Only works for announcements for now
2025
                $userIsInGroup = self::isUserInGroup($user_id, $group);
2026
                if ($userIsInGroup && self::GROUP_TOOL_ANNOUNCEMENT == $tool) {
2027
                    return true;
2028
                }
2029
                break;
2030
        }
2031
2032
        return false;
2033
    }
2034
2035
    /**
2036
     * @param int $userId
2037
     * @param int $sessionId
2038
     *
2039
     * @return bool
2040
     */
2041
    public static function userHasAccessToBrowse($userId, CGroup $group = null, $sessionId = 0)
2042
    {
2043
        if (null === $group) {
2044
            return false;
2045
        }
2046
2047
        if (api_is_platform_admin()) {
2048
            return true;
2049
        }
2050
2051
        if (api_is_allowed_to_edit(false, true, true)) {
2052
            return true;
2053
        }
2054
2055
        if (!empty($sessionId)) {
2056
            if (api_is_coach($sessionId, api_get_course_int_id())) {
2057
                return true;
2058
            }
2059
2060
            if (api_is_drh()) {
2061
                if (SessionManager::isUserSubscribedAsHRM($sessionId, $userId)) {
2062
                    return true;
2063
                }
2064
            }
2065
        }
2066
2067
        if (self::isTutorOfGroup($userId, $group)) {
2068
            return true;
2069
        }
2070
2071
        if (0 == $group->getStatus()) {
2072
            return false;
2073
        }
2074
2075
        if (self::userHasAccess($userId, $group, self::GROUP_TOOL_FORUM) ||
2076
            self::userHasAccess($userId, $group, self::GROUP_TOOL_DOCUMENTS) ||
2077
            self::userHasAccess($userId, $group, self::GROUP_TOOL_CALENDAR) ||
2078
            self::userHasAccess($userId, $group, self::GROUP_TOOL_ANNOUNCEMENT) ||
2079
            self::userHasAccess($userId, $group, self::GROUP_TOOL_WORK) ||
2080
            self::userHasAccess($userId, $group, self::GROUP_TOOL_WIKI) ||
2081
            self::userHasAccess($userId, $group, self::GROUP_TOOL_CHAT)
2082
        ) {
2083
            return true;
2084
        }
2085
        //@todo check group session id
2086
        $groupSessionId = null;
2087
2088
        if (api_is_session_general_coach() && $groupSessionId == $sessionId) {
2089
            return true;
2090
        }
2091
2092
        return false;
2093
    }
2094
2095
    /**
2096
     * Get all groups where a specific user is subscribed.
2097
     *
2098
     * @param int $user_id
2099
     *
2100
     * @return array
2101
     */
2102
    public static function get_user_group_name($user_id)
2103
    {
2104
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
2105
        $table_group = Database::get_course_table(TABLE_GROUP);
2106
        $user_id = intval($user_id);
2107
        $course_id = api_get_course_int_id();
2108
        $sql = "SELECT name
2109
                FROM $table_group g
2110
                INNER JOIN $table_group_user gu
2111
                ON (gu.group_id = g.iid)
2112
                WHERE
2113
                  gu.user_id = $user_id";
2114
        $res = Database::query($sql);
2115
        $groups = [];
2116
        while ($group = Database::fetch_array($res)) {
2117
            $groups[] .= $group['name'];
2118
        }
2119
2120
        return $groups;
2121
    }
2122
2123
    /**
2124
     * Get all groups where a specific user is subscribed.
2125
     *
2126
     * @param int      $user_id
2127
     * @param int      $courseId
2128
     * @param int|null $sessionId
2129
     *
2130
     * @return array
2131
     */
2132
    public static function getAllGroupPerUserSubscription($user_id, $courseId = 0, $sessionId = null)
2133
    {
2134
        $table_group_user = Database::get_course_table(TABLE_GROUP_USER);
2135
        $table_tutor_user = Database::get_course_table(TABLE_GROUP_TUTOR);
2136
        $table_group = Database::get_course_table(TABLE_GROUP);
2137
        $user_id = (int) $user_id;
2138
        $courseId = empty($courseId) ? api_get_course_int_id() : (int) $courseId;
2139
2140
        $sql = "SELECT DISTINCT g.*
2141
               FROM $table_group g
2142
               LEFT JOIN $table_group_user gu
2143
               ON (gu.group_id = g.iid)
2144
               LEFT JOIN $table_tutor_user tu
2145
               ON (tu.group_id = g.iid)
2146
               WHERE
2147
                  (gu.user_id = $user_id OR tu.user_id = $user_id) ";
2148
2149
        if (null !== $sessionId) {
2150
            $sessionId = (int) $sessionId;
2151
            $sql .= " AND g.session_id = $sessionId ";
2152
        }
2153
2154
        $res = Database::query($sql);
2155
        $groups = [];
2156
        while ($group = Database::fetch_array($res, 'ASSOC')) {
2157
            $groups[] = $group;
2158
        }
2159
2160
        return $groups;
2161
    }
2162
2163
    /**
2164
     * @param CGroup[] $groupList
2165
     * @param int      $category_id
2166
     *
2167
     * @return string
2168
     */
2169
    public static function processGroups($groupList, $category_id = 0)
2170
    {
2171
        $charset = 'UTF-8';
2172
        $category_id = (int) $category_id;
2173
        $totalRegistered = 0;
2174
        $group_data = [];
2175
        $user_info = api_get_user_info();
2176
        $session_id = api_get_session_id();
2177
        $user_id = $user_info['user_id'];
2178
        $hideGroup = api_get_setting('hide_course_group_if_no_tools_available');
2179
        $extraField = new ExtraField('survey');
2180
        $surveyGroupExists = $extraField->get_handler_field_info_by_field_variable('group_id') ? true : false;
2181
        $url = api_get_path(WEB_CODE_PATH).'group/';
2182
2183
        foreach ($groupList as $group) {
2184
            $groupId = $group->getIid();
2185
2186
            // Validation when belongs to a session
2187
            $session_img = '';
2188
            //$session_img = api_get_session_image($group['session_id'], $user_info['status']);
2189
2190
            // All the tutors of this group
2191
            $tutors = $group->getTutors();
2192
            $isMember = self::is_subscribed($user_id, $group);
2193
2194
            // Create a new table-row
2195
            $row = [];
2196
            // Checkbox
2197
            if (api_is_allowed_to_edit(false, true) && count($groupList) > 1) {
2198
                $row[] = $groupId;
2199
            }
2200
2201
            if (self::userHasAccessToBrowse($user_id, $group, $session_id)) {
2202
                // Group name
2203
                $groupNameClass = null;
2204
                if (0 == $group->getStatus()) {
2205
                    $groupNameClass = 'muted';
2206
                }
2207
2208
                $group_name = '<a
2209
                    class="'.$groupNameClass.'"
2210
                    href="group_space.php?'.api_get_cidreq(true, false).'&gid='.$groupId.'">'.
2211
                    Security::remove_XSS($group->getName()).'</a> ';
2212
2213
                $group_name2 = '';
2214
                if (api_get_configuration_value('extra')) {
2215
                    $group_name2 = '<a
2216
                        href="group_space_tracking.php?cid='.api_get_course_int_id().'&gid='.$groupId.'">'.
2217
                        get_lang('suivi_de').''.stripslashes($group->getName()).'</a>';
2218
                }
2219
2220
                /*
2221
                if (!empty($user_id) && !empty($this_group['id_tutor']) && $user_id == $this_group['id_tutor']) {
2222
                    $group_name .= Display::label(get_lang('my supervision'), 'success');
2223
                } elseif ($isMember) {
2224
                    $group_name .= Display::label(get_lang('my group'), 'success');
2225
                }*/
2226
2227
                /*if (api_is_allowed_to_edit() && !empty($this_group['session_name'])) {
2228
                    $group_name .= ' ('.$this_group['session_name'].')';
2229
                }
2230
                $group_name .= $session_img;*/
2231
2232
                $row[] = $group_name.$group_name2.'<br />'.stripslashes(trim($group->getDescription()));
2233
            } else {
2234
                if ('true' === $hideGroup) {
2235
                    continue;
2236
                }
2237
                $row[] = $group->getName().'<br />'.stripslashes(trim($group->getDescription()));
2238
            }
2239
2240
            // Tutor name
2241
            $tutor_info = '';
2242
            if (count($tutors) > 0) {
2243
                foreach ($tutors as $tutorGroup) {
2244
                    $tutor = $tutorGroup->getUser();
2245
                    $username = api_htmlentities(
2246
                        sprintf(get_lang('Login: %s'), $tutor->getUsername()),
2247
                        ENT_QUOTES
2248
                    );
2249
                    if ('true' === api_get_setting('show_email_addresses')) {
2250
                        $tutor_info .= Display::tag(
2251
                            'span',
2252
                            Display::encrypted_mailto_link(
2253
                                $tutor->getEmail(),
2254
                                UserManager::formatUserFullName($tutor)
2255
                            ),
2256
                            ['title' => $username]
2257
                        ).', ';
2258
                    } else {
2259
                        if (api_is_allowed_to_edit()) {
2260
                            $tutor_info .= Display::tag(
2261
                            'span',
2262
                                Display::encrypted_mailto_link(
2263
                                    $tutor->getEmail(),
2264
                                    UserManager::formatUserFullName($tutor)
2265
                                ),
2266
                                ['title' => $username]
2267
                            ).', ';
2268
                        } else {
2269
                            $tutor_info .= Display::tag(
2270
                                'span',
2271
                                    UserManager::formatUserFullName($tutor),
2272
                                ['title' => $username]
2273
                            ).', ';
2274
                        }
2275
                    }
2276
                }
2277
            }
2278
2279
            $tutor_info = api_substr(
2280
                $tutor_info,
2281
                0,
2282
                api_strlen($tutor_info) - 2
2283
            );
2284
            $row[] = $tutor_info;
2285
2286
            // Max number of members in group
2287
            $max_members = self::MEMBER_PER_GROUP_NO_LIMIT == $group->getMaxStudent() ? ' ' : ' / '.$group->getMaxStudent();
2288
            $registeredUsers = self::getStudentsCount($groupId);
2289
            // Number of members in group
2290
            $row[] = $registeredUsers.$max_members;
2291
            $confirmMessage = addslashes(
2292
                api_htmlentities(get_lang('Please confirm your choice'), ENT_QUOTES, $charset)
2293
            );
2294
            // Self-registration / unregistration
2295
            if (!api_is_allowed_to_edit(false, true)) {
2296
                if (self::is_self_registration_allowed($user_id, $group)) {
2297
                    $row[] = '<a
2298
                        class = "btn btn-default"
2299
                        href="group.php?'.api_get_cidreq().'&category='.$category_id.'&action=self_reg&group_id='.$groupId.'"
2300
                        onclick="javascript:if(!confirm('."'".$confirmMessage."'".')) return false;">'.get_lang('register').'</a>';
2301
                } elseif (self::is_self_unregistration_allowed($user_id, $group)) {
2302
                    $row[] = '<a
2303
                        class = "btn btn-default"
2304
                        href="group.php?'.api_get_cidreq().'&category='.$category_id.'&action=self_unreg&group_id='.$groupId.'"
2305
                        onclick="javascript:if(!confirm('."'".$confirmMessage."'".')) return false;">'.get_lang('unregister').'</a>';
2306
                } else {
2307
                    $row[] = '-';
2308
                }
2309
            }
2310
2311
            // @todo fix group session access.
2312
            $groupSessionId = null;
2313
2314
            // Edit-links
2315
            if (api_is_allowed_to_edit(false, true) &&
2316
                !(api_is_session_general_coach() && $groupSessionId != $session_id)
2317
            ) {
2318
                $edit_actions = '<a
2319
                    href="'.$url.'settings.php?'.api_get_cidreq(true, false).'&gid='.$groupId.'"
2320
                    title="'.get_lang('Edit').'">'.
2321
                    Display::return_icon('edit.png', get_lang('Edit this group'), '', ICON_SIZE_SMALL).
2322
                    '</a>&nbsp;';
2323
2324
                if (1 == $group->getStatus()) {
2325
                    $edit_actions .= '<a
2326
                        href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=set_invisible&group_id='.$groupId.'"
2327
                        title="'.get_lang('Hide').'">'.
2328
                        Display::return_icon('visible.png', get_lang('Hide'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2329
                } else {
2330
                    $edit_actions .= '<a
2331
                        href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=set_visible&group_id='.$groupId.'"
2332
                        title="'.get_lang('Show').'">'.
2333
                        Display::return_icon('invisible.png', get_lang('Show'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2334
                }
2335
2336
                $edit_actions .= '<a
2337
                    href="'.$url.'member_settings.php?'.api_get_cidreq(true, false).'&gid='.$groupId.'"
2338
                    title="'.get_lang('Group members').'">'.
2339
                    Display::return_icon('user.png', get_lang('Group members'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2340
2341
                $edit_actions .= '<a
2342
                    href="'.$url.'group_overview.php?action=export&type=xls&'.api_get_cidreq(true, false).'&id='.$groupId.'"
2343
                    title="'.get_lang('Export users list').'">'.
2344
                    Display::return_icon('export_excel.png', get_lang('Export'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2345
2346
                if ($surveyGroupExists) {
2347
                    $edit_actions .= Display::url(
2348
                        Display::return_icon('survey.png', get_lang('ExportSurveyResults'), '', ICON_SIZE_SMALL),
2349
                        $url.'group_overview.php?action=export_surveys&'.api_get_cidreq(true, false).'&id='.$groupId
2350
                    ).'&nbsp;';
2351
                }
2352
                $edit_actions .= '<a
2353
                    href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=fill_one&group_id='.$groupId.'"
2354
                    onclick="javascript: if(!confirm('."'".$confirmMessage."'".')) return false;" title="'.get_lang('FillGroup').'">'.
2355
                    Display::return_icon('fill.png', get_lang('FillGroup'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2356
2357
                $edit_actions .= '<a
2358
                    href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=delete_one&group_id='.$groupId.'"
2359
                    onclick="javascript: if(!confirm('."'".$confirmMessage."'".')) return false;" title="'.get_lang('Delete').'">'.
2360
                    Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
2361
2362
                $row[] = $edit_actions;
2363
            }
2364
2365
            /*if (!empty($this_group['nbMember'])) {
2366
                $totalRegistered = $totalRegistered + $this_group['nbMember'];
2367
            }*/
2368
            $group_data[] = $row;
2369
        }
2370
2371
        // If no groups then don't show the table (only for students)
2372
        if (!api_is_allowed_to_edit(true, false)) {
2373
            if (empty($group_data)) {
2374
                return '';
2375
            }
2376
        }
2377
2378
        $table = new SortableTableFromArrayConfig(
2379
            $group_data,
2380
            1,
2381
            20,
2382
            'group_category_'.$category_id
2383
        );
2384
        $table->set_additional_parameters(['category' => $category_id]);
2385
        $column = 0;
2386
        if (api_is_allowed_to_edit(false, true) && count($groupList) > 1) {
2387
            $table->set_header($column++, '', false);
2388
        }
2389
        $table->set_header($column++, get_lang('Groups'));
2390
        $table->set_header($column++, get_lang('Group tutor'));
2391
        $table->set_header($column++, get_lang('Registered'), false);
2392
2393
        if (!api_is_allowed_to_edit(false, true)) {
2394
            // If self-registration allowed
2395
            $table->set_header($column++, get_lang('Registration'), false);
2396
        }
2397
2398
        if (api_is_allowed_to_edit(false, true)) {
2399
            // Only for course administrator
2400
            $table->set_header($column++, get_lang('Edit'), false);
2401
            $form_actions = [];
2402
            $form_actions['fill_selected'] = get_lang('Fill the group randomly with course students');
2403
            $form_actions['empty_selected'] = get_lang('unsubscribe all users');
2404
            $form_actions['delete_selected'] = get_lang('Delete');
2405
            if (count($groupList) > 1) {
2406
                $table->set_form_actions($form_actions, 'group');
2407
            }
2408
        }
2409
2410
        return $table->return_table();
2411
    }
2412
2413
    /**
2414
     * @param array $groupData
2415
     * @param bool  $deleteNotInArray
2416
     *
2417
     * @return array
2418
     */
2419
    public static function importCategoriesAndGroupsFromArray($groupData, $deleteNotInArray = false)
2420
    {
2421
        $result = [];
2422
        $elementsFound = [
2423
            'categories' => [],
2424
            'groups' => [],
2425
        ];
2426
2427
        $courseCode = api_get_course_id();
2428
        $sessionId = api_get_session_id();
2429
        $groupCategories = self::get_categories();
2430
2431
        if (empty($groupCategories)) {
2432
            $result['error'][] = get_lang('Create a category');
2433
2434
            return $result;
2435
        }
2436
2437
        foreach ($groupData as $data) {
2438
            $isCategory = empty($data['group']) ? true : false;
2439
            if ($isCategory) {
2440
                $categoryInfo = self::getCategoryByTitle($data['category']);
2441
                $categoryId = $categoryInfo['iid'];
2442
2443
                if (!empty($categoryInfo)) {
2444
                    // Update
2445
                    self::update_category(
2446
                        $categoryId,
2447
                        $data['category'],
2448
                        $data['description'],
2449
                        $data['doc_state'],
2450
                        $data['work_state'],
2451
                        $data['calendar_state'],
2452
                        $data['announcements_state'],
2453
                        $data['forum_state'],
2454
                        $data['wiki_state'],
2455
                        $data['chat_state'],
2456
                        $data['self_reg_allowed'],
2457
                        $data['self_unreg_allowed'],
2458
                        $data['max_student'],
2459
                        $data['groups_per_user'],
2460
                        $data['document_access']
2461
                    );
2462
                    $data['category_id'] = $categoryId;
2463
                    $result['updated']['category'][] = $data;
2464
                } else {
2465
                    // Add
2466
                    $categoryId = self::create_category(
2467
                        $data['category'],
2468
                        $data['description'],
2469
                        $data['doc_state'],
2470
                        $data['work_state'],
2471
                        $data['calendar_state'],
2472
                        $data['announcements_state'],
2473
                        $data['forum_state'],
2474
                        $data['wiki_state'],
2475
                        $data['chat_state'],
2476
                        $data['self_reg_allowed'],
2477
                        $data['self_unreg_allowed'],
2478
                        $data['max_student'],
2479
                        $data['groups_per_user']
2480
                    );
2481
2482
                    if ($categoryId) {
2483
                        $data['category_id'] = $categoryId;
2484
                        $result['added']['category'][] = $data;
2485
                    }
2486
                }
2487
                $elementsFound['categories'][] = $categoryId;
2488
            } else {
2489
                $groupInfo = self::getGroupByName($data['group']);
2490
                $categoryInfo = [];
2491
                if (isset($data['category'])) {
2492
                    $categoryInfo = self::getCategoryByTitle($data['category']);
2493
                }
2494
                $categoryId = null;
2495
                if (!empty($categoryInfo)) {
2496
                    $categoryId = $categoryInfo['iid'];
2497
                } else {
2498
                    if (!empty($groupCategories) && isset($groupCategories[0])) {
2499
                        $defaultGroupCategory = $groupCategories[0];
2500
                        $categoryId = $defaultGroupCategory['iid'];
2501
                    }
2502
                }
2503
2504
                if (empty($groupInfo)) {
2505
                    // Add
2506
                    $groupId = self::create_group(
2507
                        $data['group'],
2508
                        $categoryId,
2509
                        null,
2510
                        $data['max_student']
2511
                    );
2512
2513
                    if ($groupId) {
2514
                        self::set_group_properties(
2515
                            $groupId,
2516
                            $data['group'],
2517
                            $data['description'],
2518
                            $data['max_student'],
2519
                            $data['doc_state'],
2520
                            $data['work_state'],
2521
                            $data['calendar_state'],
2522
                            $data['announcements_state'],
2523
                            $data['forum_state'],
2524
                            $data['wiki_state'],
2525
                            $data['chat_state'],
2526
                            $data['self_reg_allowed'],
2527
                            $data['self_unreg_allowed'],
2528
                            $categoryId
2529
                        );
2530
                        $data['group_id'] = $groupId;
2531
                        $result['added']['group'][] = $data;
2532
                    }
2533
                    $groupInfo = self::get_group_properties($groupId, true);
2534
                } else {
2535
                    // Update
2536
                    $groupId = $groupInfo['iid'];
2537
                    self::set_group_properties(
2538
                        $groupId,
2539
                        $data['group'],
2540
                        $data['description'],
2541
                        $data['max_student'],
2542
                        $data['doc_state'],
2543
                        $data['work_state'],
2544
                        $data['calendar_state'],
2545
                        $data['announcements_state'],
2546
                        $data['forum_state'],
2547
                        $data['wiki_state'],
2548
                        $data['chat_state'],
2549
                        $data['self_reg_allowed'],
2550
                        $data['self_unreg_allowed'],
2551
                        $categoryId
2552
                    );
2553
2554
                    $data['group_id'] = $groupId;
2555
                    $result['updated']['group'][] = $data;
2556
                    $groupInfo = self::get_group_properties($groupId);
2557
                }
2558
2559
                $students = isset($data['students']) ? explode(',', $data['students']) : [];
2560
                if (!empty($students)) {
2561
                    $studentUserIdList = [];
2562
                    foreach ($students as $student) {
2563
                        $userInfo = api_get_user_info_from_username($student);
2564
2565
                        if (!$userInfo) {
2566
                            continue;
2567
                        }
2568
2569
                        if (!CourseManager::is_user_subscribed_in_course(
2570
                                $userInfo['user_id'],
2571
                                $courseCode,
2572
                                !empty($sessionId),
2573
                                $sessionId
2574
                            )
2575
                        ) {
2576
                            Display::addFlash(
2577
                                Display::return_message(
2578
                                    sprintf(
2579
                                        get_lang('Student %s is no subscribed to this course'),
2580
                                        $userInfo['complete_name']
2581
                                    ),
2582
                                    'warning'
2583
                                )
2584
                            );
2585
                            continue;
2586
                        }
2587
2588
                        $studentUserIdList[] = $userInfo['user_id'];
2589
                    }
2590
                    self::subscribeUsers($studentUserIdList, api_get_group_entity($groupInfo['iid']));
2591
                }
2592
2593
                $tutors = isset($data['tutors']) ? explode(',', $data['tutors']) : [];
2594
                if (!empty($tutors)) {
2595
                    $tutorIdList = [];
2596
                    foreach ($tutors as $tutor) {
2597
                        $userInfo = api_get_user_info_from_username($tutor);
2598
2599
                        if (!$userInfo) {
2600
                            continue;
2601
                        }
2602
2603
                        if (!CourseManager::is_user_subscribed_in_course(
2604
                                $userInfo['user_id'],
2605
                                $courseCode,
2606
                                !empty($sessionId),
2607
                                $sessionId
2608
                            )
2609
                        ) {
2610
                            Display::addFlash(
2611
                                Display::return_message(
2612
                                    sprintf(get_lang('Tutor %s is no subscribed to this course'), $userInfo['complete_name']),
2613
                                    'warning'
2614
                                )
2615
                            );
2616
2617
                            continue;
2618
                        }
2619
2620
                        $tutorIdList[] = $userInfo['user_id'];
2621
                    }
2622
                    self::subscribeTutors($tutorIdList, api_get_group_entity($groupInfo['iid']));
2623
                }
2624
2625
                $elementsFound['groups'][] = $groupId;
2626
            }
2627
        }
2628
2629
        if ($deleteNotInArray) {
2630
            // Check categories
2631
            $categories = self::get_categories();
2632
            foreach ($categories as $category) {
2633
                if (!in_array($category['iid'], $elementsFound['categories'])) {
2634
                    self::delete_category($category['iid']);
2635
                    $category['category'] = $category['title'];
2636
                    $result['deleted']['category'][] = $category;
2637
                }
2638
            }
2639
2640
            $groups = self::get_groups();
2641
            foreach ($groups as $group) {
2642
                if (!in_array($group->getIid(), $elementsFound['groups'])) {
2643
                    self::deleteGroup($group);
2644
                    $result['deleted']['group'][] = $group;
2645
                }
2646
            }
2647
        }
2648
2649
        return $result;
2650
    }
2651
2652
    /**
2653
     * Export all categories/group from a course to an array.
2654
     * This function works only in a context of a course.
2655
     *
2656
     * @param int  $groupId
2657
     * @param bool $loadUsers
2658
     *
2659
     * @return array
2660
     */
2661
    public static function exportCategoriesAndGroupsToArray($groupId = null, $loadUsers = false)
2662
    {
2663
        $data = [];
2664
        $data[] = [
2665
            'category',
2666
            'group',
2667
            'description',
2668
            'announcements_state',
2669
            'calendar_state',
2670
            'chat_state',
2671
            'doc_state',
2672
            'forum_state',
2673
            'work_state',
2674
            'wiki_state',
2675
            'max_student',
2676
            'self_reg_allowed',
2677
            'self_unreg_allowed',
2678
            'groups_per_user',
2679
        ];
2680
2681
        $count = 1;
2682
2683
        if ($loadUsers) {
2684
            $data[0][] = 'students';
2685
            $data[0][] = 'tutors';
2686
        }
2687
2688
        if (false == $loadUsers) {
2689
            $categories = self::get_categories();
2690
2691
            foreach ($categories as $categoryInfo) {
2692
                $data[$count] = [
2693
                    $categoryInfo['title'],
2694
                    null,
2695
                    $categoryInfo['description'],
2696
                    $categoryInfo['announcements_state'],
2697
                    $categoryInfo['calendar_state'],
2698
                    $categoryInfo['chat_state'],
2699
                    $categoryInfo['doc_state'],
2700
                    $categoryInfo['forum_state'],
2701
                    $categoryInfo['work_state'],
2702
                    $categoryInfo['wiki_state'],
2703
                    $categoryInfo['max_student'],
2704
                    $categoryInfo['self_reg_allowed'],
2705
                    $categoryInfo['self_unreg_allowed'],
2706
                    $categoryInfo['groups_per_user'],
2707
                ];
2708
                $count++;
2709
            }
2710
        }
2711
2712
        $groups = self::get_group_list();
2713
        foreach ($groups as $groupInfo) {
2714
            $groupId = $groupInfo['iid'];
2715
            $categoryTitle = null;
2716
            $categoryInfo = [];
2717
            if (isset($groupInfo['category'])) {
2718
                $categoryInfo = self::get_category($groupInfo['category']);
2719
            }
2720
2721
            $groupSettings = self::get_group_properties($groupId);
2722
            if (!empty($categoryInfo)) {
2723
                $categoryTitle = $categoryInfo['title'];
2724
            }
2725
2726
            $users = self::getStudents($groupId);
2727
            $userList = [];
2728
            foreach ($users as $user) {
2729
                $user = api_get_user_info($user['user_id']);
2730
                $userList[] = $user['username'];
2731
            }
2732
2733
            $tutors = self::getTutors($groupInfo);
2734
            $tutorList = [];
2735
            foreach ($tutors as $user) {
2736
                $user = api_get_user_info($user['user_id']);
2737
                $tutorList[] = $user['username'];
2738
            }
2739
2740
            $userListToString = null;
2741
            if (!empty($userList)) {
2742
                $userListToString = implode(',', $userList);
2743
            }
2744
2745
            $tutorListToString = null;
2746
            if (!empty($tutorList)) {
2747
                $tutorListToString = implode(',', $tutorList);
2748
            }
2749
2750
            $data[$count] = [
2751
                $categoryTitle,
2752
                $groupSettings['name'],
2753
                $groupSettings['description'],
2754
                $groupSettings['announcements_state'],
2755
                $groupSettings['calendar_state'],
2756
                $groupSettings['chat_state'],
2757
                $groupSettings['doc_state'],
2758
                $groupSettings['forum_state'],
2759
                $groupSettings['work_state'],
2760
                $groupSettings['wiki_state'],
2761
                $groupSettings['maximum_number_of_students'],
2762
                $groupSettings['self_registration_allowed'],
2763
                $groupSettings['self_unregistration_allowed'],
2764
                null,
2765
            ];
2766
2767
            if ($loadUsers) {
2768
                $data[$count][] = $userListToString;
2769
                $data[$count][] = $tutorListToString;
2770
            }
2771
2772
            if (!empty($groupId)) {
2773
                if ($groupId == $groupInfo['iid']) {
2774
                    break;
2775
                }
2776
            }
2777
            $count++;
2778
        }
2779
2780
        return $data;
2781
    }
2782
2783
    /**
2784
     * @param string $default
2785
     */
2786
    public static function getSettingBar($default)
2787
    {
2788
        $activeSettings = null;
2789
        $activeTutor = null;
2790
        $activeMember = null;
2791
2792
        switch ($default) {
2793
            case 'settings':
2794
                $activeSettings = 'active';
2795
                break;
2796
            case 'tutor':
2797
                $activeTutor = 'active';
2798
                break;
2799
            case 'member':
2800
                $activeMember = 'active';
2801
                break;
2802
        }
2803
2804
        $url = api_get_path(WEB_CODE_PATH).'group/%s?'.api_get_cidreq();
2805
2806
        echo '
2807
            <ul class="nav nav-tabs">
2808
                <li class="nav-item">
2809
                    <a class="nav-link '.$activeSettings.'" id="group_settings_tab" href="'.sprintf($url, 'settings.php').'">
2810
                    '.Display::return_icon('settings.png').' '.get_lang('Settings').'
2811
                    </a>
2812
                </li>
2813
                <li class="nav-item">
2814
                    <a class="nav-link '.$activeMember.'" id="group_members_tab" href="'.sprintf($url, 'member_settings.php').'">
2815
                    '.Display::return_icon('user.png').' '.get_lang('Group members').'</a>
2816
                </li>
2817
                <li class="nav-item">
2818
                    <a class="nav-link  '.$activeTutor.'" id="group_tutors_tab" href="'.sprintf($url, 'tutor_settings.php').'">
2819
                    '.Display::return_icon('teacher.png').' '.get_lang('Group tutors').'
2820
                    </a>
2821
                </li>
2822
            </ul>';
2823
    }
2824
2825
    public static function groupOverview($group, $url)
2826
    {
2827
        $groupId = $group['iid'];
2828
        $content = '<li>';
2829
        $content .= Display::tag(
2830
            'h3',
2831
            Display::url(
2832
                Security::remove_XSS($group['name']),
2833
                $url.'&gidReq='.$groupId
2834
            )
2835
        );
2836
        $users = self::getTutors($group);
2837
        if (!empty($users)) {
2838
            $content .= '<ul>';
2839
            $content .= "<li>".Display::tag('h4', get_lang('Tutors'))."</li><ul>";
2840
            foreach ($users as $user) {
2841
                $userInfo = api_get_user_info($user['user_id']);
2842
                $content .= '<li title="'.$userInfo['username'].'">'.
2843
                    $userInfo['complete_name_with_username'].
2844
                    '</li>';
2845
            }
2846
            $content .= '</ul>';
2847
            $content .= '</ul>';
2848
        }
2849
2850
        $users = self::getStudents($group['iid']);
2851
        if (!empty($users)) {
2852
            $content .= '<ul>';
2853
            $content .= "<li>".Display::tag('h4', get_lang('Students'))."</li><ul>";
2854
            foreach ($users as $user) {
2855
                $userInfo = api_get_user_info($user['user_id']);
2856
                $content .= '<li title="'.$userInfo['username'].'">'.
2857
                    $userInfo['complete_name_with_username'].
2858
                    '</li>';
2859
            }
2860
            $content .= '</ul>';
2861
            $content .= '</ul>';
2862
        }
2863
        $content .= '</li>';
2864
2865
        return $content;
2866
    }
2867
2868
    /**
2869
     * @param array  $courseInfo
2870
     * @param string $keyword
2871
     *
2872
     * @return string
2873
     */
2874
    public static function getOverview($courseInfo, $keyword = '')
2875
    {
2876
        $content = null;
2877
        $categories = self::get_categories();
2878
        $url = api_get_path(WEB_CODE_PATH).'group/group_space.php?'.api_get_cidreq(true, false);
2879
        if (!empty($categories)) {
2880
            foreach ($categories as $category) {
2881
                if ('true' === api_get_setting('allow_group_categories')) {
2882
                    $content .= '<h2>'.$category['title'].'</h2>';
2883
                }
2884
                $groups = self::get_group_list($category['iid'], $courseInfo, null, 0, false, $keyword);
2885
                $content .= '<ul>';
2886
                if (!empty($groups)) {
2887
                    foreach ($groups as $group) {
2888
                        $content .= self::groupOverview($group, $url);
2889
                    }
2890
                }
2891
                $content .= '</ul>';
2892
            }
2893
        }
2894
2895
        // Check groups with no categories.
2896
        $groups = self::get_group_list(null, api_get_course_info(), null, api_get_session_id(), false, true);
2897
        if (!empty($groups)) {
2898
            $content .= '<h2>'.get_lang('NoCategorySelected').'</h2>';
2899
            $content .= '<ul>';
2900
            foreach ($groups as $group) {
2901
                if (!empty($group['category_id'])) {
2902
                    continue;
2903
                }
2904
                $content .= self::groupOverview($group, $url);
2905
            }
2906
            $content .= '</ul>';
2907
        }
2908
2909
        return $content;
2910
    }
2911
2912
    /**
2913
     * Returns the search form.
2914
     *
2915
     * @return string
2916
     */
2917
    public static function getSearchForm()
2918
    {
2919
        $url = api_get_path(WEB_CODE_PATH).'group/group_overview.php?'.api_get_cidreq();
2920
        $form = new FormValidator(
2921
            'search_groups',
2922
            'get',
2923
            $url,
2924
            null,
2925
            ['class' => 'form-search'],
2926
            FormValidator::LAYOUT_INLINE
2927
        );
2928
        $form->addElement('text', 'keyword');
2929
        $form->addCourseHiddenParams();
2930
        $form->addButtonSearch();
2931
2932
        return $form->toHtml();
2933
    }
2934
2935
    public static function setStatus(CGroup $group, $status)
2936
    {
2937
        $group->setStatus($status);
2938
        $em = Database::getManager();
2939
        $em->persist($group);
2940
        $em->flush();
2941
    }
2942
2943
    public static function setVisible(CGroup $group)
2944
    {
2945
        self::setStatus($group, true);
2946
    }
2947
2948
    public static function setInvisible(CGroup $group)
2949
    {
2950
        self::setStatus($group, false);
2951
    }
2952
2953
    /**
2954
     * @param int   $userId
2955
     * @param int   $courseId
2956
     * @param array $documentInfoToBeCheck
2957
     * @param bool  $blockPage
2958
     *
2959
     * @return bool
2960
     */
2961
    public static function allowUploadEditDocument(
2962
        $userId,
2963
        $courseId,
2964
        CGroup $group,
2965
        $documentInfoToBeCheck = null,
2966
        $blockPage = false
2967
    ) {
2968
        // Admin and teachers can make any change no matter what
2969
        if (api_is_platform_admin() || api_is_allowed_to_edit(false, true)) {
2970
            return true;
2971
        }
2972
2973
        if (empty($group)) {
2974
            if ($blockPage) {
2975
                api_not_allowed(true);
2976
            }
2977
2978
            return false;
2979
        }
2980
2981
        // Tutor can also make any change
2982
        $isTutor = self::isTutorOfGroup($userId, $group);
2983
2984
        if ($isTutor) {
2985
            return true;
2986
        }
2987
2988
        // Just in case also check if document in group is available
2989
        if (0 == $group->getDocState()) {
2990
            if ($blockPage) {
2991
                api_not_allowed(true);
2992
            }
2993
2994
            return false;
2995
        }
2996
2997
        // Default behaviour
2998
        $documentAccess = self::DOCUMENT_MODE_SHARE;
2999
3000
        // Check category document access
3001
        /*$allowCategoryGroupDocumentAccess = api_get_configuration_value('group_category_document_access');
3002
        if ($allowCategoryGroupDocumentAccess) {
3003
            $category = GroupManager::get_category_from_group($groupInfo['iid']);
3004
            if (!empty($category) && isset($category['document_access'])) {
3005
                $documentAccess = (int) $category['document_access'];
3006
            }
3007
        }*/
3008
3009
        // Check group document access
3010
        $allow = api_get_configuration_value('group_document_access');
3011
        if ($allow) {
3012
            $documentAccess = $group->getDocumentAccess();
3013
        }
3014
3015
        // Check access for students
3016
        $result = false;
3017
        switch ($documentAccess) {
3018
            case self::DOCUMENT_MODE_SHARE:
3019
                // Default chamilo behaviour
3020
                // Student can upload his own content, cannot modify another content.
3021
                $isMember = self::is_subscribed($userId, $group);
3022
                if ($isMember) {
3023
                    // No document to check, allow access to document feature.
3024
                    if (empty($documentInfoToBeCheck)) {
3025
                        $result = true;
3026
                    } else {
3027
                        // Member can only edit his own document
3028
                        $authorId = isset($documentInfoToBeCheck['insert_user_id']) ? $documentInfoToBeCheck['insert_user_id'] : 0;
3029
                        // If "insert_user_id" is not set, check the author id from c_item_property
3030
                        if (empty($authorId) && isset($documentInfoToBeCheck['id'])) {
3031
                            // @todo use resources
3032
                            /*$documentInfo = api_get_item_property_info(
3033
                                $courseId,
3034
                                'document',
3035
                                $documentInfoToBeCheck['id'],
3036
                                0
3037
                            );
3038
                            // Try to find this document in the session
3039
                            if (!empty($sessionId)) {
3040
                                $documentInfo = api_get_item_property_info(
3041
                                    $courseId,
3042
                                    'document',
3043
                                    $documentInfoToBeCheck['id'],
3044
                                    api_get_session_id()
3045
                                );
3046
                            }
3047
3048
                            if (!empty($documentInfo) && isset($documentInfo['insert_user_id'])) {
3049
                                $authorId = $documentInfo['insert_user_id'];
3050
                            }*/
3051
                        }
3052
3053
                        if ($authorId == $userId) {
3054
                            $result = true;
3055
                        }
3056
                    }
3057
                }
3058
                break;
3059
            case self::DOCUMENT_MODE_READ_ONLY:
3060
                // Student cannot upload content, cannot modify another content.
3061
                $result = false;
3062
                break;
3063
            case self::DOCUMENT_MODE_COLLABORATION:
3064
                // Student can upload content, can modify another content.
3065
                $isMember = self::is_subscribed($userId, $group);
3066
                if ($isMember) {
3067
                    $result = true;
3068
                }
3069
                break;
3070
        }
3071
3072
        if ($blockPage && false == $result) {
3073
            api_not_allowed(true);
3074
        }
3075
3076
        return $result;
3077
    }
3078
}
3079