Passed
Pull Request — master (#7195)
by
unknown
10:16
created

UserGroupModel::get_groups_by_user()   B

Complexity

Conditions 7
Paths 12

Size

Total Lines 61
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 39
c 0
b 0
f 0
nc 12
nop 3
dl 0
loc 61
rs 8.3626

How to fix   Long Method   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\ResourceFile;
6
use Chamilo\CoreBundle\Entity\Usergroup;
7
use Chamilo\CoreBundle\Enums\ActionIcon;
8
use Chamilo\CoreBundle\Enums\ObjectIcon;
9
use Chamilo\CoreBundle\Enums\ToolIcon;
10
use Chamilo\CoreBundle\Framework\Container;
11
use Symfony\Component\HttpFoundation\File\UploadedFile;
12
13
/**
14
 * Class UserGroup.
15
 *
16
 * This class provides methods for the UserGroup management.
17
 * Include/require it in your code to use its features.
18
 */
19
class UserGroupModel extends Model
20
{
21
    public const SOCIAL_CLASS = 1;
22
    public const NORMAL_CLASS = 0;
23
    public $columns = [
24
        'id',
25
        'title',
26
        'description',
27
        'group_type',
28
        'picture',
29
        'url',
30
        'allow_members_leave_group',
31
        'visibility',
32
        'updated_at',
33
        'created_at',
34
    ];
35
36
    public $useMultipleUrl = false;
37
    public $groupType = 0;
38
    public $showGroupTypeSetting = false;
39
    public $usergroup_rel_user_table;
40
    public $usergroup_rel_course_table;
41
    public $usergroup;
42
    public $usergroup_rel_session_table;
43
    public $session_table;
44
    public $access_url_rel_usergroup;
45
    public $session_rel_course_table;
46
    public $access_url_rel_user;
47
    public $table_course;
48
    public $table_user;
49
    private string $usergroup_table;
50
51
    public function __construct()
52
    {
53
        parent::__construct();
54
        $this->table = Database::get_main_table(TABLE_USERGROUP);
55
        $this->usergroup_rel_user_table = Database::get_main_table(TABLE_USERGROUP_REL_USER);
56
        $this->usergroup_rel_course_table = Database::get_main_table(TABLE_USERGROUP_REL_COURSE);
57
        $this->usergroup_rel_session_table = Database::get_main_table(TABLE_USERGROUP_REL_SESSION);
58
        $this->session_table = Database::get_main_table(TABLE_MAIN_SESSION);
59
        $this->usergroup_table = Database::get_main_table(TABLE_USERGROUP);
60
        $this->access_url_rel_usergroup = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USERGROUP);
61
        $this->session_rel_course_table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
62
        $this->access_url_rel_user = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
63
        $this->table_course = Database::get_main_table(TABLE_MAIN_COURSE);
64
        $this->table_user = Database::get_main_table(TABLE_MAIN_USER);
65
        $this->useMultipleUrl = api_get_multiple_access_url();
66
        if ($this->allowTeachers()) {
67
            $this->columns[] = 'author_id';
68
        }
69
    }
70
71
    /**
72
     * @return bool
73
     */
74
    public function getUseMultipleUrl()
75
    {
76
        return $this->useMultipleUrl;
77
    }
78
79
    /**
80
     * @return int
81
     */
82
    public function getTotalCount()
83
    {
84
        $options = [];
85
        $from = $this->table;
86
87
        if ($this->getUseMultipleUrl()) {
88
            $urlId = api_get_current_access_url_id();
89
            $options = [
90
                'where' => [
91
                    'access_url_id = ?' => [
92
                        $urlId,
93
                    ],
94
                ],
95
            ];
96
            $from = " $this->table u
97
                      INNER JOIN $this->access_url_rel_usergroup a
98
                      ON (u.id = a.usergroup_id) ";
99
        }
100
        $row = Database::select('count(*) as count', $from, $options, 'first');
101
102
        return $row['count'];
103
    }
104
105
    /**
106
     * @param int  $id       user group id
107
     * @param bool $getCount
108
     *
109
     * @return array|int
110
     */
111
    public function getUserGroupUsers($id, $getCount = false, $start = 0, $limit = 0)
112
    {
113
        $id = (int) $id;
114
        $start = (int) $start;
115
        $limit = (int) $limit;
116
117
        $select = ' u.* ';
118
        if ($getCount) {
119
            $select = 'COUNT(u.id) count ';
120
        }
121
122
        if ($this->getUseMultipleUrl()) {
123
            $urlId = api_get_current_access_url_id();
124
            $sql = "SELECT $select
125
                    FROM $this->usergroup_rel_user_table u
126
                    INNER JOIN $this->access_url_rel_user a
127
                    ON (u.user_id = a.user_id)
128
                    WHERE u.usergroup_id = $id AND access_url_id = $urlId ";
129
        } else {
130
            $sql = "SELECT $select
131
                    FROM $this->usergroup_rel_user_table u
132
                    WHERE u.usergroup_id = $id";
133
        }
134
        $limitCondition = '';
135
        if (!empty($start) && !empty($limit)) {
136
            $limitCondition = " LIMIT $start, $limit";
137
        }
138
139
        $sql .= $limitCondition;
140
141
        $result = Database::query($sql);
142
143
        if ($getCount) {
144
            if (Database::num_rows($result)) {
145
                $row = Database::fetch_array($result);
146
147
                return $row['count'];
148
            }
149
150
            return 0;
151
        } else {
152
            $list = [];
153
            $showCalendar = 'true' === api_get_plugin_setting('learning_calendar', 'enabled');
154
            $calendarPlugin = null;
155
            if ($showCalendar) {
156
                $calendarPlugin = LearningCalendarPlugin::create();
157
            }
158
            $url = api_get_path(WEB_PLUGIN_PATH).'LearningCalendar/calendar.php?';
159
            while ($data = Database::fetch_array($result)) {
160
                $userId = $data['user_id'];
161
                $userInfo = api_get_user_info($userId);
162
                $data['title'] = $userInfo['complete_name_with_username'];
163
164
                if ($showCalendar) {
165
                    $calendar = $calendarPlugin->getUserCalendar($userId);
166
                    $data['calendar_id'] = 0;
167
                    $data['calendar'] = '';
168
                    if (!empty($calendar)) {
169
                        $calendarInfo = $calendarPlugin->getCalendar($calendar['calendar_id']);
170
                        if ($calendarInfo) {
171
                            $data['calendar_id'] = $calendar['calendar_id'];
172
                            $data['calendar'] = Display::url(
173
                                $calendarInfo['title'],
174
                                $url.'&id='.$calendar['calendar_id']
175
                            );
176
                        }
177
                    }
178
179
                    $courseAndSessionList = Tracking::show_user_progress(
180
                        $userId,
181
                        0,
182
                        '',
183
                        true,
184
                        true,
185
                        true
186
                    );
187
188
                    $stats = $calendarPlugin->getUserStats($userId, $courseAndSessionList);
189
                    $evaluations = $calendarPlugin->getGradebookEvaluationListToString($userId, $courseAndSessionList);
190
                    $data['gradebook_items'] = $evaluations;
191
                    $totalTime = 0;
192
                    foreach ($courseAndSessionList as $sessionId => $course) {
193
                        foreach ($course as $courseId) {
194
                            $totalTime += Tracking::get_time_spent_on_the_course($userId, $courseId, $sessionId);
195
                        }
196
                    }
197
198
                    $data['time_spent'] = api_time_to_hms($totalTime);
199
                    $data['lp_day_completed'] = $stats['completed'];
200
                    $data['days_diff'] = $stats['completed'] - $stats['user_event_count'];
201
                }
202
                $data['id'] = $data['user_id'];
203
                $list[] = $data;
204
            }
205
206
            return $list;
207
        }
208
    }
209
210
    /**
211
     * Returns all user groups (id + title), ordered by title.
212
     * This method ignores multi-URL restrictions because it's used
213
     * for initial assignment of groups to access URLs.
214
     */
215
    public function getAllUserGroups(): array
216
    {
217
        $sql = "SELECT id, title FROM {$this->table} ORDER BY title";
218
219
        $stmt = Database::getManager()->getConnection()->executeQuery($sql);
220
221
        return Database::store_result($stmt, 'ASSOC');
222
    }
223
224
    /**
225
     * @param string $extraWhereCondition
226
     *
227
     * @return int
228
     */
229
    public function get_count($extraWhereCondition = '')
230
    {
231
        $authorCondition = '';
232
233
        if ($this->allowTeachers()) {
234
            if (!api_is_platform_admin()) {
235
                $userId = api_get_user_id();
236
                $authorCondition = " AND author_id = $userId";
237
            }
238
        }
239
240
        if ($this->getUseMultipleUrl()) {
241
            $urlId = api_get_current_access_url_id();
242
            $sql = "SELECT count(u.id) as count
243
                    FROM $this->table u
244
                    INNER JOIN $this->access_url_rel_usergroup a
245
                    ON (u.id = a.usergroup_id)
246
                    WHERE access_url_id = $urlId $authorCondition
247
                    AND $extraWhereCondition
248
            ";
249
250
            $result = Database::query($sql);
251
            if (Database::num_rows($result)) {
252
                $row = Database::fetch_array($result);
253
254
                return $row['count'];
255
            }
256
        } else {
257
            $sql = "SELECT count(a.id) as count
258
                    FROM {$this->table} a
259
                    WHERE 1 = 1
260
                    $authorCondition
261
                    AND $extraWhereCondition
262
            ";
263
            $result = Database::query($sql);
264
            if (Database::num_rows($result)) {
265
                $row = Database::fetch_array($result);
266
267
                return $row['count'];
268
            }
269
        }
270
271
        return 0;
272
    }
273
274
    /**
275
     * @param int $course_id
276
     * @param int $type
277
     *
278
     * @return mixed
279
     */
280
    public function getUserGroupByCourseWithDataCount($course_id, $type = -1)
281
    {
282
        if ($this->getUseMultipleUrl()) {
283
            $course_id = (int) $course_id;
284
            $urlId = api_get_current_access_url_id();
285
            $sql = "SELECT count(c.usergroup_id) as count
286
                    FROM {$this->usergroup_rel_course_table} c
287
                    INNER JOIN {$this->access_url_rel_usergroup} a
288
                    ON (c.usergroup_id = a.usergroup_id)
289
                    WHERE access_url_id = $urlId AND course_id = $course_id
290
            ";
291
            $result = Database::query($sql);
292
            if (Database::num_rows($result)) {
293
                $row = Database::fetch_array($result);
294
295
                return $row['count'];
296
            }
297
298
            return 0;
299
        } else {
300
            $typeCondition = '';
301
            if (-1 != $type) {
302
                $type = (int) $type;
303
                $typeCondition = " AND group_type = $type ";
304
            }
305
            $sql = "SELECT count(c.usergroup_id) as count
306
                    FROM {$this->usergroup_rel_course_table} c
307
                    INNER JOIN {$this->table} a
308
                    ON (c.usergroup_id = a.id)
309
                    WHERE
310
                        course_id = $course_id
311
                        $typeCondition
312
            ";
313
            $result = Database::query($sql);
314
            if (Database::num_rows($result)) {
315
                $row = Database::fetch_array($result);
316
317
                return $row['count'];
318
            }
319
320
            return 0;
321
        }
322
    }
323
324
    /**
325
     * @param string $name
326
     *
327
     * @return int
328
     */
329
    public function getIdByName($name)
330
    {
331
        $row = Database::select(
332
            'id',
333
            $this->table,
334
            ['where' => ['title = ?' => $name]],
335
            'first'
336
        );
337
338
        if ($row) {
339
            return (int) $row['id'];
340
        }
341
342
        return 0;
343
    }
344
345
    /**
346
     * Displays the title + grid.
347
     */
348
    public function returnGrid()
349
    {
350
        $html = '';
351
        $actions = '';
352
        if (api_is_platform_admin()) {
353
            $actions .= '<a href="../admin/index.php">'.
354
                Display::getMdiIcon(
355
                    ActionIcon::BACK,
356
                    'ch-tool-icon',
357
                    null,
358
                    ICON_SIZE_MEDIUM,
359
                    get_lang('Back to').' '.get_lang('Administration')
360
                ).
361
                '</a>';
362
        }
363
364
        $actions .= '<a href="'.api_get_self().'?action=add">'.
365
            Display::getMdiIcon(ActionIcon::ADD, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Add classes')).
366
            '</a>';
367
        $actions .= Display::url(
368
            Display::getMdiIcon(ActionIcon::IMPORT_ARCHIVE, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Import')),
369
            'usergroup_import.php'
370
        );
371
        $actions .= Display::url(
372
            Display::getMdiIcon(ActionIcon::EXPORT_CSV, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Export')),
373
            'usergroup_export.php'
374
        );
375
        $html .= Display::toolbarAction('toolbar', [$actions]);
376
        $html .= Display::grid_html('usergroups');
377
378
        return $html;
379
    }
380
381
    /**
382
     * Displays the title + grid.
383
     */
384
    public function displayToolBarUserGroupUsers()
385
    {
386
        // action links
387
        echo '<div class="actions">';
388
        $courseInfo = api_get_course_info();
389
        if (empty($courseInfo)) {
390
            echo '<a href="../admin/usergroups.php">'.
391
                Display::getMdiIcon(
392
                    ActionIcon::BACK,
393
                    'ch-tool-icon',
394
                    null,
395
                    ICON_SIZE_MEDIUM,
396
                    get_lang('Back to').' '.get_lang('Administration')
397
                ).
398
                '</a>';
399
        } else {
400
            echo Display::url(
401
                Display::getMdiIcon(
402
                    ActionIcon::BACK,
403
                    'ch-tool-icon',
404
                    null,
405
                    ICON_SIZE_MEDIUM,
406
                    get_lang('Back to').' '.get_lang('Administration')
407
                ),
408
                api_get_path(WEB_CODE_PATH).'user/class.php?'.api_get_cidreq()
409
            );
410
        }
411
412
        echo '</div>';
413
        echo Display::grid_html('usergroups');
414
    }
415
416
    /**
417
     * Get HTML grid.
418
     */
419
    public function display_teacher_view()
420
    {
421
        echo Display::grid_html('usergroups');
422
    }
423
424
    /**
425
     * Gets a list of course ids by user group.
426
     *
427
     * @param int  $id             user group id
428
     * @param bool $loadCourseData
429
     *
430
     * @return array
431
     */
432
    public function get_courses_by_usergroup($id, $loadCourseData = false)
433
    {
434
        if ($this->getUseMultipleUrl()) {
435
            $urlId = api_get_current_access_url_id();
436
            $from = $this->usergroup_rel_course_table." c
437
                    INNER JOIN {$this->access_url_rel_usergroup} a
438
                    ON (a.usergroup_id = c.usergroup_id) ";
439
            $whereConditionSql = 'a.usergroup_id = ? AND access_url_id = ? ';
440
            $whereConditionValues = [$id, $urlId];
441
        } else {
442
            $whereConditionSql = 'usergroup_id = ?';
443
            $whereConditionValues = [$id];
444
            $from = $this->usergroup_rel_course_table.' c ';
445
        }
446
447
        if ($loadCourseData) {
448
            $from .= " INNER JOIN {$this->table_course} as course ON c.course_id = course.id";
449
        }
450
451
        $where = ['where' => [$whereConditionSql => $whereConditionValues]];
452
453
        $select = 'course_id';
454
        if ($loadCourseData) {
455
            $select = 'course.*';
456
        }
457
458
        $results = Database::select(
459
            $select,
460
            $from,
461
            $where
462
        );
463
464
        $array = [];
465
        if (!empty($results)) {
466
            foreach ($results as $row) {
467
                if ($loadCourseData) {
468
                    $array[$row['id']] = $row;
469
                } else {
470
                    $array[] = $row['course_id'];
471
                }
472
            }
473
        }
474
475
        return $array;
476
    }
477
478
    /**
479
     * Gets all users that are part of a group or class.
480
     *
481
     * Example to obtain the number of registered:
482
     * <code>
483
     * <?php
484
     *
485
     * $options['where'] = [' usergroup.course_id = ? ' => $course_id];
486
     * $obj = new UserGroupModel();
487
     * $count = $obj->getUserGroupInCourse(
488
     * $options,
489
     * -1,
490
     * true,
491
     * true
492
     * );
493
     * echo "<pre>".var_export($count,true)."</pre>";
494
     * ?>
495
     * </code>
496
     *
497
     *
498
     * Example to obtain the list of classes or groups registered:
499
     * <code>
500
     * <?php
501
     *
502
     * $options['where'] = [' usergroup.course_id = ? ' => $course_id];
503
     * $obj = new UserGroupModel();
504
     * $students = $obj->getUserGroupInCourse(
505
     * $options,
506
     * -1,
507
     * false,
508
     * true
509
     * );
510
     * echo "<pre>".var_export($students,true)."</pre>";
511
     * ?>
512
     * </code>
513
     *
514
     * @param array $options
515
     * @param int   $type        0 = classes / 1 = social groups
516
     * @param bool  $withClasses Return with classes.
517
     *
518
     * @return array
519
     */
520
    public function getUserGroupInCourse(
521
        $options = [],
522
        $type = -1,
523
        $getCount = false,
524
        $withClasses = false
525
    ) {
526
        $data = [];
527
        $sqlClasses = '';
528
        $whereClasess = '';
529
        $resultClasess = null;
530
        $counts = 0;
531
        $select = 'DISTINCT u.*';
532
        if ($getCount) {
533
            $select = 'count(u.id) as count';
534
        }
535
536
        if (
537
            true == $withClasses &&
538
            isset($options['session_id']) &&
539
            0 != (int) $options['session_id']
540
        ) {
541
            $sessionId = (int) $options['session_id'];
542
            $courseId = (int) $options['course_id'];
543
            unset($options['session_id']);
544
            $whereClasess = " WHERE ur.session_id = $sessionId AND sc.c_id = $courseId ";
545
        } else {
546
            $withClasses = false;
547
        }
548
549
        if ($this->getUseMultipleUrl()) {
550
            if (true != $withClasses) {
551
                $sql = "SELECT $select
552
                    FROM {$this->usergroup_rel_course_table} usergroup
553
                    INNER JOIN {$this->table} u
554
                    ON (u.id = usergroup.usergroup_id)
555
                    INNER JOIN {$this->table_course} c
556
                    ON (usergroup.course_id = c.id)
557
                    INNER JOIN {$this->access_url_rel_usergroup} a
558
                    ON (a.usergroup_id = u.id)
559
                   ";
560
            } else {
561
                $sqlClasses = "SELECT".
562
                    " $select ".
563
                    " FROM".
564
                    " {$this->usergroup_rel_session_table} ur".
565
                    " INNER JOIN {$this->usergroup_table} u ON  u.id = ur.usergroup_id ".
566
                    " INNER JOIN `{$this->session_table}` s ON  s.id = ur.session_id".
567
                    " INNER JOIN {$this->access_url_rel_usergroup} a ON (a.usergroup_id = u.id) ".
568
                    " INNER JOIN {$this->session_rel_course_table} sc ON s.id = sc.session_id ".
569
                    " $whereClasess ";
570
            }
571
        } else {
572
            if (true != $withClasses) {
573
                $sql = "SELECT $select
574
                    FROM {$this->usergroup_rel_course_table} usergroup
575
                    INNER JOIN {$this->table} u
576
                    ON (u.id = usergroup.usergroup_id)
577
                    INNER JOIN {$this->table_course} c
578
                    ON (usergroup.course_id = c.id)
579
                   ";
580
            } else {
581
                $sqlClasses = "SELECT".
582
                    " $select ".
583
                    " FROM".
584
                    " {$this->usergroup_rel_session_table} ur".
585
                    " INNER JOIN {$this->usergroup_table} u ON  u.id = ur.usergroup_id ".
586
                    " INNER JOIN `{$this->session_table}` s ON  s.id = ur.session_id".
587
                    " INNER JOIN {$this->session_rel_course_table} sc ON s.id = sc.session_id ".
588
                    " $whereClasess ";
589
            }
590
        }
591
        if (-1 != $type) {
592
            $type = (int) $type;
593
            $options['where']['AND group_type = ? '] = $type;
594
        }
595
        if ($this->getUseMultipleUrl()) {
596
            $urlId = api_get_current_access_url_id();
597
            $options['where']['AND access_url_id = ? '] = $urlId;
598
        }
599
600
        $conditions = Database::parse_conditions($options);
601
        if (true == $withClasses) {
602
            $resultClasess = Database::query($sqlClasses);
603
        } else {
604
            $sql .= $conditions;
605
606
            $result = Database::query($sql);
607
        }
608
609
        if ($getCount) {
610
            if (!empty($result)) {
611
                if (Database::num_rows($result)) {
612
                    $row = Database::fetch_array($result);
613
                    $counts += $row['count'];
614
                }
615
            }
616
            if (!empty($sqlClasses)) {
617
                if (Database::num_rows($resultClasess)) {
618
                    $row = Database::fetch_array($resultClasess);
619
                    $counts += $row['count'];
620
                }
621
            }
622
623
            return $counts;
624
        }
625
        if (!empty($result)) {
626
            if (Database::num_rows($result) > 0) {
627
                while ($row = Database::fetch_assoc($result)) {
628
                    $data[] = $row;
629
                }
630
            }
631
        }
632
        if (!empty($sqlClasses)) {
633
            if (Database::num_rows($resultClasess) > 0) {
634
                while ($row = Database::fetch_assoc($resultClasess)) {
635
                    $data[] = $row;
636
                }
637
            }
638
        }
639
640
        return $data;
641
    }
642
643
    /**
644
     * @param array $options
645
     * @param int   $type
646
     * @param bool  $getCount
647
     * @param bool  $withClasses
648
     *
649
     * @return array|bool
650
     */
651
    public function getUserGroupNotInCourse(
652
        $options = [],
653
        $type = -1,
654
        $getCount = false,
655
        $withClasses = false
656
    ) {
657
        $data = [];
658
        $sqlClasses = '';
659
        $whereClasess = '';
660
        $resultClasess = null;
661
        $course_id = null;
662
        if (isset($options['course_id'])) {
663
            $course_id = (int) $options['course_id'];
664
            unset($options['course_id']);
665
        }
666
667
        if (empty($course_id)) {
668
            return false;
669
        }
670
671
        $select = 'DISTINCT u.*';
672
        if ($getCount) {
673
            $select = 'count(u.id) as count';
674
        }
675
676
        if (
677
            true == $withClasses &&
678
            isset($options['session_id']) &&
679
            0 != (int) $options['session_id']
680
        ) {
681
            $sessionId = (int) $options['session_id'];
682
            unset($options['session_id']);
683
            $whereClasess = " WHERE ur.session_id != $sessionId ";
684
        } else {
685
            $withClasses = false;
686
        }
687
688
        if ($this->getUseMultipleUrl()) {
689
            if (false == $withClasses) {
690
                $sql = "SELECT $select
691
                    FROM {$this->table} u
692
                    INNER JOIN {$this->access_url_rel_usergroup} a
693
                    ON (a.usergroup_id = u.id)
694
                    LEFT OUTER JOIN {$this->usergroup_rel_course_table} urc
695
                    ON (u.id = urc.usergroup_id AND course_id = $course_id)
696
            ";
697
            } else {
698
                $sqlClasses = " SELECT".
699
                    " $select".
700
                    " FROM".
701
                    " {$this->usergroup_rel_session_table} ur".
702
                    " LEFT OUTER  JOIN {$this->usergroup_table} u ON u.id = ur.usergroup_id".
703
                    " INNER JOIN {$this->access_url_rel_usergroup} a ON (a.usergroup_id = u.id) ".
704
                    " LEFT JOIN `{$this->session_table}` s ON s.id = ur.session_id".
705
                    " LEFT JOIN {$this->session_rel_course_table} sc ON s.id = sc.session_id ".
706
                    " $whereClasess ";
707
            }
708
        } else {
709
            if (false == $withClasses) {
710
                $sql = "SELECT $select
711
                    FROM {$this->table} u
712
                    LEFT OUTER JOIN {$this->usergroup_rel_course_table} urc
713
                    ON (u.id = urc.usergroup_id AND course_id = $course_id)
714
            ";
715
            } else {
716
                $sqlClasses = " SELECT".
717
                    " $select".
718
                    " FROM".
719
                    " {$this->usergroup_rel_session_table} ur".
720
                    " LEFT OUTER  JOIN {$this->usergroup_table} u ON u.id = ur.usergroup_id".
721
                    " LEFT JOIN `{$this->session_table}` s ON s.id = ur.session_id".
722
                    " LEFT JOIN {$this->session_rel_course_table} sc ON s.id = sc.session_id ".
723
                    " $whereClasess ";
724
            }
725
        }
726
727
        if (-1 != $type) {
728
            $type = (int) $type;
729
            $options['where']['AND group_type = ? '] = $type;
730
        }
731
        if ($this->getUseMultipleUrl()) {
732
            $urlId = api_get_current_access_url_id();
733
            $options['where']['AND access_url_id = ? '] = $urlId;
734
        }
735
736
        /*if ($this->allowTeachers()) {
737
            if (!api_is_platform_admin()) {
738
                $userId = api_get_user_id();
739
                $options['where']['AND author_id = ? '] = $userId;
740
            }
741
        }*/
742
743
        $conditions = Database::parse_conditions($options);
744
745
        if (true == $withClasses) {
746
            $resultClasess = Database::query($sqlClasses);
747
        } else {
748
            $sql .= $conditions;
749
            $result = Database::query($sql);
750
        }
751
752
        if ($getCount) {
753
            if (!empty($result)) {
754
                $result = Database::query($sql);
755
                $array = Database::fetch_assoc($result);
756
757
                return $array['count'];
758
            }
759
            if (!empty($sqlClasses)) {
760
                if (Database::num_rows($resultClasess)) {
761
                    $row = Database::fetch_array($resultClasess);
762
763
                    return $row['count'];
764
                }
765
            }
766
        }
767
        if (!empty($result)) {
768
            if (Database::num_rows($result) > 0) {
769
                while ($row = Database::fetch_assoc($result)) {
770
                    $data[] = $row;
771
                }
772
            }
773
        }
774
        if (!empty($sqlClasses)) {
775
            if (Database::num_rows($resultClasess) > 0) {
776
                while ($row = Database::fetch_assoc($resultClasess)) {
777
                    $data[] = $row;
778
                }
779
            }
780
        }
781
782
        return $data;
783
    }
784
785
    /**
786
     * @param int $course_id
787
     *
788
     * @deprecated  ?
789
     *
790
     * @return array
791
     */
792
    public function get_usergroup_by_course($course_id)
793
    {
794
        if ($this->getUseMultipleUrl()) {
795
            $urlId = api_get_current_access_url_id();
796
            $options = [
797
                'where' => [
798
                    'c.course_id = ? AND access_url_id = ?' => [
799
                        $course_id,
800
                        $urlId,
801
                    ],
802
                ],
803
            ];
804
            $from = " $this->usergroup_rel_course_table as c
805
                    INNER JOIN $this->access_url_rel_usergroup a
806
                    ON c.usergroup_id = a.usergroup_id ";
807
        } else {
808
            $options = ['where' => ['c.course_id = ?' => $course_id]];
809
            $from = $this->usergroup_rel_course_table." c";
810
        }
811
812
        $results = Database::select('c.usergroup_id', $from, $options);
813
        $array = [];
814
        if (!empty($results)) {
815
            foreach ($results as $row) {
816
                $array[] = $row['usergroup_id'];
817
            }
818
        }
819
820
        return $array;
821
    }
822
823
    /**
824
     * @param int $usergroup_id
825
     * @param int $course_id
826
     *
827
     * @return bool
828
     */
829
    public function usergroup_was_added_in_course(
830
        $usergroup_id,
831
        $course_id,
832
        $Session = 0
833
    ) {
834
        $Session = (int) $Session;
835
        $results = Database::select(
836
            'usergroup_id',
837
            $this->usergroup_rel_course_table,
838
            ['where' => ['course_id = ? AND usergroup_id = ?' => [$course_id, $usergroup_id]]]
839
        );
840
841
        $resultSession = Database::select(
842
            'usergroup_id',
843
            $this->usergroup_rel_session_table,
844
            ['where' => ['session_id = ? AND usergroup_id = ?' => [$Session, $usergroup_id]]]
845
        );
846
847
        if (empty($results) && 0 == $Session) {
848
            return false;
849
        }
850
        if ((empty($resultSession)) && 0 != $Session) {
851
            return false;
852
        }
853
854
        return true;
855
    }
856
857
    /**
858
     * Gets a list of session ids by user group.
859
     *
860
     * @param int $id group id
861
     *
862
     * @return array
863
     */
864
    public function get_sessions_by_usergroup($id)
865
    {
866
        $results = Database::select(
867
            'session_id',
868
            $this->usergroup_rel_session_table,
869
            ['where' => ['usergroup_id = ?' => $id]]
870
        );
871
872
        $array = [];
873
        if (!empty($results)) {
874
            foreach ($results as $row) {
875
                $array[] = $row['session_id'];
876
            }
877
        }
878
879
        return $array;
880
    }
881
882
    /**
883
     * Gets a list of user ids by user group.
884
     *
885
     * @param int   $id    user group id
886
     * @param array $roles
887
     *
888
     * @return array with a list of user ids
889
     */
890
    public function get_users_by_usergroup($id = null, $roles = [])
891
    {
892
        $relationCondition = '';
893
        if (!empty($roles)) {
894
            $relationConditionArray = [];
895
            foreach ($roles as $relation) {
896
                $relation = (int) $relation;
897
898
                if (0 === $relation) {
899
                    $relationConditionArray[] =
900
                        ' (relation_type = '.GROUP_USER_PERMISSION_READER.' OR relation_type = 2 OR relation_type IS NULL OR relation_type = \'\') ';
901
                } else {
902
                    $relationConditionArray[] = " relation_type = $relation ";
903
                }
904
            }
905
            $relationCondition = ' AND ( ';
906
            $relationCondition .= implode('OR', $relationConditionArray);
907
            $relationCondition .= ' ) ';
908
        }
909
910
        if (empty($id)) {
911
            $conditions = [];
912
        } else {
913
            $conditions = ['where' => ["usergroup_id = ? $relationCondition " => $id]];
914
        }
915
916
        $results = Database::select(
917
            'user_id',
918
            $this->usergroup_rel_user_table,
919
            $conditions
920
        );
921
922
        $array = [];
923
        if (!empty($results)) {
924
            foreach ($results as $row) {
925
                $array[] = $row['user_id'];
926
            }
927
        }
928
929
        return $array;
930
    }
931
932
    /**
933
     * Gets a list of user ids by user group and relation type.
934
     *
935
     * @param int $id       user group id
936
     * @param int $relation relation type
937
     *
938
     * @return array with a list of user ids
939
     */
940
    public function getUsersByUsergroupAndRelation($id, $relation = 0)
941
    {
942
        $relation = (int) $relation;
943
944
        if (0 === $relation) {
945
            // Default reader role: include canonical (0) + legacy (2) + null / empty
946
            $conditions = [
947
                'where' => [
948
                    'usergroup_id = ? AND (relation_type = ? OR relation_type = 2 OR relation_type IS NULL OR relation_type = \'\') ' => [
949
                        $id,
950
                        GROUP_USER_PERMISSION_READER,
951
                    ],
952
                ],
953
            ];
954
        } else {
955
            $conditions = [
956
                'where' => [
957
                    'usergroup_id = ? AND relation_type = ?' => [$id, $relation],
958
                ],
959
            ];
960
        }
961
962
        $results = Database::select(
963
            'user_id',
964
            $this->usergroup_rel_user_table,
965
            $conditions
966
        );
967
968
        $array = [];
969
        if (!empty($results)) {
970
            foreach ($results as $row) {
971
                $array[] = $row['user_id'];
972
            }
973
        }
974
975
        return $array;
976
    }
977
978
    /**
979
     * Get the group list for a user.
980
     *
981
     * @param int $userId       The user ID
982
     * @param int $filterByType Optional. The type of group
983
     *
984
     * @return array
985
     */
986
    public function getUserGroupListByUser($userId, $filterByType = null)
987
    {
988
        $userId = (int) $userId;
989
        if ($this->getUseMultipleUrl()) {
990
            $urlId = api_get_current_access_url_id();
991
            $from = $this->usergroup_rel_user_table." u
992
                INNER JOIN {$this->access_url_rel_usergroup} a
993
                ON (a.usergroup_id AND u.usergroup_id)
994
                INNER JOIN {$this->table} g
995
                ON (u.usergroup_id = g.id)
996
                ";
997
            $where = ['where' => ['user_id = ? AND access_url_id = ? ' => [$userId, $urlId]]];
998
        } else {
999
            $from = $this->usergroup_rel_user_table." u
1000
                INNER JOIN {$this->table} g
1001
                ON (u.usergroup_id = g.id)
1002
                ";
1003
            $where = ['where' => ['user_id = ?' => $userId]];
1004
        }
1005
1006
        if (null !== $filterByType) {
1007
            $where['where'][' AND g.group_type = ?'] = (int) $filterByType;
1008
        }
1009
1010
        $results = Database::select(
1011
            'g.*',
1012
            $from,
1013
            $where
1014
        );
1015
        $array = [];
1016
        if (!empty($results)) {
1017
            foreach ($results as $row) {
1018
                $array[] = $row;
1019
            }
1020
        }
1021
1022
        return $array;
1023
    }
1024
1025
    /**
1026
     * Gets the usergroup id list by user id.
1027
     *
1028
     * @param int $userId user id
1029
     *
1030
     * @return array
1031
     */
1032
    public function get_usergroup_by_user($userId)
1033
    {
1034
        $userId = (int) $userId;
1035
        if ($this->getUseMultipleUrl()) {
1036
            $urlId = api_get_current_access_url_id();
1037
            $from = $this->usergroup_rel_user_table." u
1038
                    INNER JOIN {$this->access_url_rel_usergroup} a
1039
                    ON (a.usergroup_id = u.usergroup_id) ";
1040
            $where = ['where' => ['user_id = ? AND access_url_id = ? ' => [$userId, $urlId]]];
1041
        } else {
1042
            $from = $this->usergroup_rel_user_table.' u ';
1043
            $where = ['where' => ['user_id = ?' => $userId]];
1044
        }
1045
1046
        $results = Database::select(
1047
            'u.usergroup_id',
1048
            $from,
1049
            $where
1050
        );
1051
1052
        $array = [];
1053
        if (!empty($results)) {
1054
            foreach ($results as $row) {
1055
                $array[] = $row['usergroup_id'];
1056
            }
1057
        }
1058
1059
        return $array;
1060
    }
1061
1062
    /**
1063
     * Subscribes sessions to a group  (also adding the members of the group in the session and course).
1064
     *
1065
     * @param int   $usergroup_id          usergroup id
1066
     * @param array $list                  list of session ids
1067
     * @param bool  $deleteCurrentSessions Optional. Empty the session list for the usergroup (class)
1068
     */
1069
    public function subscribe_sessions_to_usergroup($usergroup_id, $list, $deleteCurrentSessions = true)
1070
    {
1071
        $current_list = $this->get_sessions_by_usergroup($usergroup_id);
1072
        $user_list = $this->get_users_by_usergroup($usergroup_id);
1073
1074
        $delete_items = $new_items = [];
1075
        if (!empty($list)) {
1076
            foreach ($list as $session_id) {
1077
                if (!in_array($session_id, $current_list)) {
1078
                    $new_items[] = $session_id;
1079
                }
1080
            }
1081
        }
1082
        if ($deleteCurrentSessions) {
1083
            if (!empty($current_list)) {
1084
                foreach ($current_list as $session_id) {
1085
                    if (!in_array($session_id, $list)) {
1086
                        $delete_items[] = $session_id;
1087
                    }
1088
                }
1089
            }
1090
1091
            // Deleting items
1092
            if (!empty($delete_items)) {
1093
                foreach ($delete_items as $session_id) {
1094
                    if (!empty($user_list)) {
1095
                        foreach ($user_list as $user_id) {
1096
                            SessionManager::unsubscribe_user_from_session($session_id, $user_id);
1097
                        }
1098
                    }
1099
                    Database::delete(
1100
                        $this->usergroup_rel_session_table,
1101
                        ['usergroup_id = ? AND session_id = ?' => [$usergroup_id, $session_id]]
1102
                    );
1103
                }
1104
            }
1105
        }
1106
1107
        // Adding new relationships.
1108
        if (!empty($new_items)) {
1109
            foreach ($new_items as $session_id) {
1110
                $params = ['session_id' => $session_id, 'usergroup_id' => $usergroup_id];
1111
                Database::insert($this->usergroup_rel_session_table, $params);
1112
1113
                if (!empty($user_list)) {
1114
                    SessionManager::subscribeUsersToSession(
1115
                        $session_id,
1116
                        $user_list,
1117
                        null,
1118
                        false
1119
                    );
1120
                }
1121
            }
1122
        }
1123
    }
1124
1125
    /**
1126
     * Subscribes courses to a group (also adding the members of the group in the course).
1127
     *
1128
     * @param int   $usergroup_id  usergroup id
1129
     * @param array $list          list of course ids (integers)
1130
     * @param bool  $delete_groups
1131
     */
1132
    public function subscribe_courses_to_usergroup($usergroup_id, $list, $delete_groups = true)
1133
    {
1134
        $current_list = $this->get_courses_by_usergroup($usergroup_id);
1135
        $user_list = $this->get_users_by_usergroup($usergroup_id);
1136
1137
        $delete_items = [];
1138
        $new_items    = [];
1139
1140
        // Detect new course assignments
1141
        if (!empty($list)) {
1142
            foreach ($list as $course_id) {
1143
                if (!in_array($course_id, $current_list)) {
1144
                    $new_items[] = (int) $course_id;
1145
                }
1146
            }
1147
        }
1148
1149
        // Detect removed course assignments
1150
        if (!empty($current_list)) {
1151
            foreach ($current_list as $course_id) {
1152
                if (!in_array($course_id, $list)) {
1153
                    $delete_items[] = (int) $course_id;
1154
                }
1155
            }
1156
        }
1157
1158
        // Remove old relations if required
1159
        if ($delete_groups && !empty($delete_items)) {
1160
            $this->unsubscribe_courses_from_usergroup($usergroup_id, $delete_items);
1161
        }
1162
1163
        // Hosting / platform user limit
1164
        $userLimit = (int) api_get_setting('platform.hosting_limit_users_per_course');
1165
1166
        // Add new course relations
1167
        if (!empty($new_items)) {
1168
            foreach ($new_items as $course_id) {
1169
                $course_info = api_get_course_info_by_id($course_id);
1170
                if (empty($course_info)) {
1171
                    continue;
1172
                }
1173
1174
                // Count current users already subscribed to the course
1175
                $currentCourseUsers = CourseManager::get_user_list_from_course_code(
1176
                    $course_info['code'],
1177
                    null,
1178
                    null,
1179
                    null,
1180
                    true
1181
                );
1182
                $currentUserCount = is_array($currentCourseUsers) ? count($currentCourseUsers) : 0;
1183
1184
                // Number of users coming from the class
1185
                $incomingUsersCount = is_array($user_list) ? count($user_list) : 0;
1186
1187
                // Validate hosting user limit
1188
                if ($userLimit > 0 && ($currentUserCount + $incomingUsersCount) > $userLimit) {
1189
                    // Skip this course assignment silently
1190
                    // Reason: assigning this class would exceed the user limit
1191
                    continue;
1192
                }
1193
1194
                // Subscribe users to course
1195
                if (!empty($user_list)) {
1196
                    foreach ($user_list as $user_id) {
1197
                        CourseManager::subscribeUser($user_id, $course_id);
1198
                    }
1199
                }
1200
1201
                // Persist relation usergroup ↔ course
1202
                Database::insert(
1203
                    $this->usergroup_rel_course_table,
1204
                    [
1205
                        'course_id'    => $course_id,
1206
                        'usergroup_id' => $usergroup_id,
1207
                    ]
1208
                );
1209
            }
1210
        }
1211
    }
1212
1213
    /**
1214
     * @param int   $usergroup_id
1215
     * @param array $delete_items
1216
     */
1217
    public function unsubscribe_courses_from_usergroup($usergroup_id, $delete_items, $sessionId = 0)
1218
    {
1219
        $sessionId = (int) $sessionId;
1220
        // Deleting items.
1221
        if (!empty($delete_items)) {
1222
            $user_list = $this->get_users_by_usergroup($usergroup_id);
1223
1224
            $groupId = isset($_GET['id']) ? (int) $_GET['id'] : 0;
1225
            foreach ($delete_items as $course_id) {
1226
                $course_info = api_get_course_info_by_id($course_id);
1227
                if ($course_info) {
1228
                    if (!empty($user_list)) {
1229
                        foreach ($user_list as $user_id) {
1230
                            CourseManager::unsubscribe_user(
1231
                                $user_id,
1232
                                $course_info['code'],
1233
                                $sessionId
1234
                            );
1235
                        }
1236
                    }
1237
1238
                    Database::delete(
1239
                        $this->usergroup_rel_course_table,
1240
                        [
1241
                            'usergroup_id = ? AND course_id = ?' => [
1242
                                $usergroup_id,
1243
                                $course_id,
1244
                            ],
1245
                        ]
1246
                    );
1247
                }
1248
                if (0 != $sessionId && 0 != $groupId) {
1249
                    $this->subscribe_sessions_to_usergroup($groupId, [0]);
1250
                } else {
1251
                    $s = $sessionId;
1252
                }
1253
            }
1254
        }
1255
    }
1256
1257
    /**
1258
     * Subscribe users to a group.
1259
     *
1260
     * @param int   $usergroup_id                     usergroup id
1261
     * @param array $list                             list of user ids
1262
     * @param bool  $delete_users_not_present_in_list
1263
     * @param int   $relationType
1264
     */
1265
    public function subscribe_users_to_usergroup(
1266
        $usergroup_id,
1267
        $list,
1268
        $delete_users_not_present_in_list = true,
1269
        $relationType = 0
1270
    ) {
1271
        // Normalize relation type
1272
        $relationType = (int) $relationType;
1273
1274
        // Detect group type to keep legacy behaviour for classic classes
1275
        $groupInfo = $this->get($usergroup_id);
1276
        $isSocialGroup = isset($groupInfo['group_type']) && (int) $groupInfo['group_type'] === Usergroup::SOCIAL_CLASS;
1277
        $isClassGroup  = isset($groupInfo['group_type']) && (int) $groupInfo['group_type'] === Usergroup::NORMAL_CLASS;
1278
1279
        if ($isSocialGroup) {
1280
            $current_list = $this->getUsersByUsergroupAndRelation($usergroup_id, $relationType);
1281
        } else {
1282
            $current_list = $this->get_users_by_usergroup($usergroup_id);
1283
        }
1284
1285
        $course_list  = $this->get_courses_by_usergroup($usergroup_id);
1286
        $session_list = $this->get_sessions_by_usergroup($usergroup_id);
1287
        $session_list = array_filter($session_list);
1288
1289
        $delete_items = [];
1290
        $new_items    = [];
1291
1292
        // Compute new users to add
1293
        if (!empty($list)) {
1294
            foreach ($list as $user_id) {
1295
                if (!in_array($user_id, $current_list)) {
1296
                    $new_items[] = $user_id;
1297
                }
1298
            }
1299
        }
1300
1301
        // Compute users to delete (present before, not present now)
1302
        if (!empty($current_list)) {
1303
            foreach ($current_list as $user_id) {
1304
                if (!in_array($user_id, $list)) {
1305
                    $delete_items[] = $user_id;
1306
                }
1307
            }
1308
        }
1309
1310
        // Deleting items
1311
        if (!empty($delete_items) && $delete_users_not_present_in_list) {
1312
            foreach ($delete_items as $user_id) {
1313
                // Remove course subscriptions
1314
                if (!empty($course_list)) {
1315
                    foreach ($course_list as $course_id) {
1316
                        $course_info = api_get_course_info_by_id($course_id);
1317
                        CourseManager::unsubscribe_user($user_id, $course_info['code']);
1318
                    }
1319
                }
1320
1321
                // Remove session subscriptions
1322
                if (!empty($session_list)) {
1323
                    foreach ($session_list as $session_id) {
1324
                        SessionManager::unsubscribe_user_from_session($session_id, $user_id);
1325
                    }
1326
                }
1327
1328
                // Remove from usergroup_rel_user:
1329
                // - Social groups: delete exactly this role (even if it is 0 = reader).
1330
                // - Normal classes: keep legacy default behaviour.
1331
                if ($isSocialGroup) {
1332
                    // Strict per-role deletion, with reader-role legacy tolerance
1333
                    if ($relationType === 0) {
1334
                        // Default reader role: treat legacy 2 as equivalent
1335
                        Database::delete(
1336
                            $this->usergroup_rel_user_table,
1337
                            [
1338
                                'usergroup_id = ? AND user_id = ? AND (relation_type = "0" OR relation_type = "2" OR relation_type IS NULL OR relation_type = "")' => [
1339
                                    $usergroup_id,
1340
                                    $user_id,
1341
                                ],
1342
                            ]
1343
                        );
1344
                    } else {
1345
                        // Other roles: delete only this specific role
1346
                        Database::delete(
1347
                            $this->usergroup_rel_user_table,
1348
                            [
1349
                                'usergroup_id = ? AND user_id = ? AND relation_type = ?' => [
1350
                                    $usergroup_id,
1351
                                    $user_id,
1352
                                    $relationType,
1353
                                ],
1354
                            ]
1355
                        );
1356
                    }
1357
                } else {
1358
                    // Legacy: default/empty relation_type
1359
                    Database::delete(
1360
                        $this->usergroup_rel_user_table,
1361
                        [
1362
                            'usergroup_id = ? AND (relation_type = "0" OR relation_type = "2" OR relation_type IS NULL OR relation_type = "")' => [
1363
                                $usergroup_id,
1364
                                $user_id,
1365
                            ],
1366
                        ]
1367
                    );
1368
                }
1369
            }
1370
        }
1371
1372
        // Adding new relationships
1373
        if (!empty($new_items)) {
1374
            // Add sessions
1375
            if (!empty($session_list)) {
1376
                foreach ($session_list as $session_id) {
1377
                    SessionManager::subscribeUsersToSession($session_id, $new_items, null, false);
1378
                }
1379
            }
1380
1381
            foreach ($new_items as $user_id) {
1382
                // Add courses
1383
                if (!empty($course_list)) {
1384
                    foreach ($course_list as $course_id) {
1385
                        CourseManager::subscribeUser($user_id, $course_id);
1386
                    }
1387
                }
1388
1389
                // Persist relation in usergroup_rel_user
1390
                $params = [
1391
                    'user_id'      => $user_id,
1392
                    'usergroup_id' => $usergroup_id,
1393
                    'relation_type'=> $relationType,
1394
                ];
1395
1396
                Database::insert($this->usergroup_rel_user_table, $params);
1397
            }
1398
        }
1399
    }
1400
1401
    /**
1402
     * @deprecated Use UsergroupRepository::getByTitleInUrl().
1403
     *
1404
     * @param string $title
1405
     *
1406
     * @return bool
1407
     * @throws Exception
1408
     */
1409
    public function usergroup_exists(string $title): bool
1410
    {
1411
        $title = Database::escape_string($title);
1412
        if ($this->getUseMultipleUrl()) {
1413
            $urlId = api_get_current_access_url_id();
1414
            $sql = "SELECT * FROM $this->table u
1415
                    INNER JOIN {$this->access_url_rel_usergroup} a
1416
                    ON (a.usergroup_id = u.id)
1417
                    WHERE title = '".$title."' AND access_url_id = $urlId";
1418
        } else {
1419
            $sql = "SELECT * FROM $this->table WHERE title = '".$title."'";
1420
        }
1421
1422
        $res = Database::query($sql);
1423
1424
        return 0 != Database::num_rows($res);
1425
    }
1426
1427
    /**
1428
     * @return bool
1429
     */
1430
    public function allowTeachers()
1431
    {
1432
        return 'true' === api_get_setting('profile.allow_teachers_to_classes');
1433
    }
1434
1435
    /**
1436
     * @param int    $sidx
1437
     * @param int    $sord
1438
     * @param int    $start
1439
     * @param int    $limit
1440
     * @param string $extraWhereCondition
1441
     *
1442
     * @return array
1443
     */
1444
    public function getUsergroupsPagination($sidx, $sord, $start, $limit, $extraWhereCondition = '')
1445
    {
1446
        $sord = in_array(strtolower($sord), ['asc', 'desc']) ? $sord : 'desc';
1447
1448
        $start = (int) $start;
1449
        $limit = (int) $limit;
1450
1451
        $sqlFrom = "{$this->table} u ";
1452
        $sqlWhere = '1 = 1 ';
1453
1454
        if ($this->getUseMultipleUrl()) {
1455
            $urlId = api_get_current_access_url_id();
1456
            $sqlFrom .= " INNER JOIN {$this->access_url_rel_usergroup} a ON (u.id = a.usergroup_id) ";
1457
            $sqlWhere .= " AND a.access_url_id = $urlId ";
1458
        }
1459
1460
        if ($this->allowTeachers()) {
1461
            if (!api_is_platform_admin()) {
1462
                $userId = api_get_user_id();
1463
                $sqlWhere .= " AND author_id = $userId ";
1464
            }
1465
        }
1466
1467
        if ($extraWhereCondition) {
1468
            $sqlWhere .= " AND $extraWhereCondition ";
1469
        }
1470
1471
        $result = Database::store_result(
1472
            Database::query("SELECT DISTINCT u.* FROM $sqlFrom WHERE $sqlWhere ORDER BY title $sord LIMIT $start, $limit")
1473
        );
1474
1475
        $new_result = [];
1476
        if (!empty($result)) {
1477
            foreach ($result as $group) {
1478
                $group['sessions'] = count($this->get_sessions_by_usergroup($group['id']));
1479
                $validCourses = $this->get_courses_by_usergroup($group['id'], true);
1480
                $group['courses'] = is_array($validCourses) ? count($validCourses) : 0;
1481
                $roles = [];
1482
                switch ($group['group_type']) {
1483
                    case 0:
1484
                        $group['group_type'] = Display::label(get_lang('Class'), 'info');
1485
                        $roles = [0];
1486
                        break;
1487
                    case 1:
1488
                        $group['group_type'] = Display::label(get_lang('Social'), 'success');
1489
                        $roles = [
1490
                            GROUP_USER_PERMISSION_ADMIN,
1491
                            GROUP_USER_PERMISSION_READER,
1492
                            GROUP_USER_PERMISSION_MODERATOR,
1493
                            GROUP_USER_PERMISSION_HRM,
1494
                        ];
1495
                        break;
1496
                }
1497
                $group['users'] = Display::url(
1498
                    count($this->get_users_by_usergroup($group['id'], $roles)),
1499
                    api_get_path(WEB_CODE_PATH).'admin/usergroup_users.php?id='.$group['id']
1500
                );
1501
                $new_result[] = $group;
1502
            }
1503
            $result = $new_result;
1504
        }
1505
        $columns = ['title', 'users', 'courses', 'sessions', 'group_type'];
1506
1507
        if (!in_array($sidx, $columns)) {
1508
            $sidx = 'title';
1509
        }
1510
1511
        // Multidimensional sort
1512
        $result = msort($result, $sidx, $sord);
1513
1514
        return $result;
1515
    }
1516
1517
    /**
1518
     * @param array $options
1519
     *
1520
     * @return array
1521
     */
1522
    public function getDataToExport($options = [])
1523
    {
1524
        if ($this->getUseMultipleUrl()) {
1525
            $urlId = api_get_current_access_url_id();
1526
            $from = $this->table." u
1527
                    INNER JOIN {$this->access_url_rel_usergroup} a
1528
                    ON (u.id = a.usergroup_id)";
1529
            $options = ['where' => ['access_url_id = ? ' => $urlId]];
1530
            if ($this->allowTeachers()) {
1531
                $options['where'] = [' author_id = ? ' => api_get_user_id()];
1532
            }
1533
            $classes = Database::select('a.id, title, description', $from, $options);
1534
        } else {
1535
            if ($this->allowTeachers()) {
1536
                $options['where'] = [' author_id = ? ' => api_get_user_id()];
1537
            }
1538
            $classes = Database::select('id, title, description', $this->table, $options);
1539
        }
1540
1541
        $result = [];
1542
        if (!empty($classes)) {
1543
            foreach ($classes as $data) {
1544
                $users = $this->getUserListByUserGroup($data['id']);
1545
                $userToString = null;
1546
                if (!empty($users)) {
1547
                    $userNameList = [];
1548
                    foreach ($users as $userData) {
1549
                        $userNameList[] = $userData['username'];
1550
                    }
1551
                    $userToString = implode(',', $userNameList);
1552
                }
1553
                $data['users'] = $userToString;
1554
                $result[] = $data;
1555
            }
1556
        }
1557
1558
        return $result;
1559
    }
1560
1561
    /**
1562
     * @param string $firstLetter
1563
     * @param int    $limit
1564
     *
1565
     * @return array
1566
     */
1567
    public function filterByFirstLetter($firstLetter, $limit = 0)
1568
    {
1569
        $firstLetter = Database::escape_string($firstLetter);
1570
        $limit = (int) $limit;
1571
1572
        $sql = ' SELECT g.id, title ';
1573
1574
        $urlCondition = '';
1575
        if ($this->getUseMultipleUrl()) {
1576
            $urlId = api_get_current_access_url_id();
1577
            $sql .= " FROM $this->table g
1578
                    INNER JOIN $this->access_url_rel_usergroup a
1579
                    ON (g.id = a.usergroup_id) ";
1580
            $urlCondition = " AND access_url_id = $urlId ";
1581
        } else {
1582
            $sql = " FROM $this->table g ";
1583
        }
1584
        $sql .= "
1585
		        WHERE
1586
		            title LIKE '".$firstLetter."%' OR
1587
		            title LIKE '".api_strtolower($firstLetter)."%'
1588
		            $urlCondition
1589
		        ORDER BY title DESC ";
1590
1591
        if (!empty($limit)) {
1592
            $sql .= " LIMIT $limit ";
1593
        }
1594
1595
        $result = Database::query($sql);
1596
1597
        return Database::store_result($result);
1598
    }
1599
1600
    /**
1601
     * Select user group not in list.
1602
     */
1603
    public function getUserGroupNotInList(array $list, int $accessUrlId): array
1604
    {
1605
        $params = [];
1606
1607
        $sql = "SELECT g.*
1608
            FROM {$this->table} g";
1609
1610
        if ($this->getUseMultipleUrl()) {
1611
            $sql .= " LEFT JOIN {$this->access_url_rel_usergroup} a
1612
                  ON (g.id = a.usergroup_id AND a.access_url_id = ?)";
1613
            $params[] = $accessUrlId;
1614
            $sql .= " WHERE a.usergroup_id IS NULL";
1615
        } else {
1616
            $sql .= " WHERE 1=1";
1617
        }
1618
1619
        if (!empty($list)) {
1620
            $placeholders = implode(',', array_fill(0, count($list), '?'));
1621
            $sql .= " AND g.id NOT IN ($placeholders)";
1622
            $params = array_merge($params, array_map('intval', $list));
1623
        }
1624
1625
        $sql .= " ORDER BY g.title";
1626
1627
        $stmt = Database::getManager()->getConnection()->executeQuery($sql, $params);
1628
1629
        return Database::store_result($stmt, 'ASSOC');
1630
    }
1631
1632
    /**
1633
     * @param $params
1634
     * @param bool $showQuery
1635
     *
1636
     * @return bool|int
1637
     */
1638
    public function save($params, $showQuery = false)
1639
    {
1640
        $params['updated_at'] = $params['created_at'] = api_get_utc_datetime();
1641
        $params['group_type'] = isset($params['group_type']) ? Usergroup::SOCIAL_CLASS : Usergroup::NORMAL_CLASS;
1642
        $params['allow_members_leave_group'] = isset($params['allow_members_leave_group']) ? 1 : 0;
1643
        $params['url'] = $params['url'] ?? "";
1644
        $params['visibility'] = $params['visibility'] ?? Usergroup::GROUP_PERMISSION_OPEN;
1645
1646
        $userGroupExists = $this->usergroup_exists(trim($params['title']));
1647
        if (false === $userGroupExists) {
1648
            $userGroup = new Usergroup();
1649
            $repo = Container::getUsergroupRepository();
1650
            $userGroup
1651
                ->setTitle(trim($params['title']))
1652
                ->setDescription($params['description'])
1653
                ->setUrl($params['url'])
1654
                ->setVisibility($params['visibility'])
1655
                ->setGroupType($params['group_type'])
1656
                ->setAllowMembersToLeaveGroup($params['allow_members_leave_group'])
1657
            ;
1658
            if ($this->allowTeachers()) {
1659
                $userGroup->setAuthorId(api_get_user_id());
1660
            }
1661
1662
            $repo->create($userGroup);
1663
1664
            $id = $userGroup->getId();
1665
            if ($id) {
1666
                if ($this->getUseMultipleUrl()) {
1667
                    $this->subscribeToUrl($id, api_get_current_access_url_id());
1668
                }
1669
1670
                if (Usergroup::SOCIAL_CLASS == $params['group_type']) {
1671
                    $this->add_user_to_group(
1672
                        api_get_user_id(),
1673
                        $id,
1674
                        $params['group_type']
1675
                    );
1676
                }
1677
                $request = Container::getRequest();
1678
                $file = $request->files->get('picture');
1679
                if (null !== $file) {
1680
                    $this->manageFileUpload($userGroup, $file);
1681
                }
1682
            }
1683
1684
            return $id;
1685
        }
1686
1687
        return false;
1688
    }
1689
1690
    public function update($params, $showQuery = false): bool
1691
    {
1692
        $em = Database::getManager();
1693
        $repo = Container::getUsergroupRepository();
1694
        /** @var Usergroup $userGroup */
1695
        $userGroup = $repo->find($params['id']);
1696
        if (null === $userGroup) {
1697
            return false;
1698
        }
1699
1700
        if (isset($params['title'])) {
1701
            $userGroup->setTitle($params['title']);
1702
        }
1703
1704
        if (isset($params['description'])) {
1705
            $userGroup->setDescription($params['description']);
1706
        }
1707
1708
        if (isset($params['visibility'])) {
1709
            $userGroup->setVisibility($params['visibility']);
1710
        }
1711
1712
        if (isset($params['url'])) {
1713
            $userGroup->setUrl($params['url']);
1714
        }
1715
1716
        $userGroup
1717
            ->setGroupType(isset($params['group_type']) ? Usergroup::SOCIAL_CLASS : Usergroup::NORMAL_CLASS)
1718
            ->setAllowMembersToLeaveGroup(isset($params['allow_members_leave_group']) ? 1 : 0)
1719
        ;
1720
        $cropImage = $params['picture_crop_result'] ?? null;
1721
        $picture = $_FILES['picture'] ?? null;
1722
        if (!empty($picture)) {
1723
            $request = Container::getRequest();
1724
            $file = $request->files->get('picture');
1725
            if (null !== $file) {
1726
                $this->manageFileUpload($userGroup, $file, $cropImage);
1727
            }
1728
        }
1729
1730
        $em->persist($userGroup);
1731
        $em->flush();
1732
1733
        if (isset($params['delete_picture'])) {
1734
            $this->delete_group_picture($params['id']);
1735
        }
1736
1737
        return true;
1738
    }
1739
1740
    public function manageFileUpload(
1741
        Usergroup $userGroup,
1742
        UploadedFile $picture,
1743
        string $cropParameters = ''
1744
    ): ?ResourceFile {
1745
        $illustrationRepo = Container::getIllustrationRepository();
1746
1747
        return $illustrationRepo->addIllustration($userGroup, api_get_user_entity(), $picture, $cropParameters);
1748
    }
1749
1750
    /**
1751
     * @param int $groupId
1752
     *
1753
     * @return string
1754
     */
1755
    public function delete_group_picture($groupId)
1756
    {
1757
        $repo = Container::getUsergroupRepository();
1758
        $userGroup = $repo->find($groupId);
1759
        if ($userGroup) {
1760
            $illustrationRepo = Container::getIllustrationRepository();
1761
            $illustrationRepo->deleteIllustration($userGroup);
1762
        }
1763
    }
1764
1765
    /**
1766
     * @return mixed
1767
     */
1768
    public function getGroupType()
1769
    {
1770
        return $this->groupType;
1771
    }
1772
1773
    /**
1774
     * @param int $id
1775
     *
1776
     * @return bool|void
1777
     */
1778
    public function delete($id)
1779
    {
1780
        $id = (int) $id;
1781
        if ($this->getUseMultipleUrl()) {
1782
            $this->unsubscribeToUrl($id, api_get_current_access_url_id());
1783
        }
1784
1785
        $sql = "DELETE FROM $this->usergroup_rel_user_table
1786
                WHERE usergroup_id = $id";
1787
        Database::query($sql);
1788
1789
        $sql = "DELETE FROM $this->usergroup_rel_course_table
1790
                WHERE usergroup_id = $id";
1791
        Database::query($sql);
1792
1793
        $sql = "DELETE FROM $this->usergroup_rel_session_table
1794
                WHERE usergroup_id = $id";
1795
        Database::query($sql);
1796
1797
        $repo = Container::getUsergroupRepository();
1798
        $userGroup = $repo->find($id);
1799
        $repo->delete($userGroup);
1800
    }
1801
1802
    /**
1803
     * @param int $id
1804
     * @param int $urlId
1805
     */
1806
    public function subscribeToUrl($id, $urlId)
1807
    {
1808
        Database::insert(
1809
            $this->access_url_rel_usergroup,
1810
            [
1811
                'access_url_id' => $urlId,
1812
                'usergroup_id' => $id,
1813
            ]
1814
        );
1815
    }
1816
1817
    /**
1818
     * @param int $id
1819
     * @param int $urlId
1820
     */
1821
    public function unsubscribeToUrl($id, $urlId)
1822
    {
1823
        Database::delete(
1824
            $this->access_url_rel_usergroup,
1825
            [
1826
                'access_url_id = ? AND usergroup_id = ? ' => [$urlId, $id],
1827
            ]
1828
        );
1829
    }
1830
1831
    /**
1832
     * @param $needle
1833
     *
1834
     * @return xajaxResponse
1835
     */
1836
    public static function searchUserGroupAjax($needle)
1837
    {
1838
        $response = new xajaxResponse();
1839
        $return = '';
1840
1841
        if (!empty($needle)) {
1842
            // xajax send utf8 datas... datas in db can be non-utf8 datas
1843
            $charset = api_get_system_encoding();
1844
            $needle = api_convert_encoding($needle, $charset, 'utf-8');
1845
            $needle = Database::escape_string($needle);
1846
1847
            $sql = 'SELECT id, title
1848
                    FROM '.Database::get_main_table(TABLE_USERGROUP).' u
1849
                    WHERE title LIKE "'.$needle.'%"
1850
                    ORDER BY title
1851
                    LIMIT 11';
1852
            $result = Database::query($sql);
1853
            $i = 0;
1854
            while ($data = Database::fetch_array($result)) {
1855
                $i++;
1856
                if ($i <= 10) {
1857
                    $return .= '<a
1858
                    href="javascript: void(0);"
1859
                    onclick="javascript: add_user_to_url(\''.addslashes($data['id']).'\',\''.addslashes($data['title']).' \')">'.$data['title'].' </a><br />';
1860
                } else {
1861
                    $return .= '...<br />';
1862
                }
1863
            }
1864
        }
1865
        $response->addAssign('ajax_list_courses', 'innerHTML', api_utf8_encode($return));
1866
1867
        return $response;
1868
    }
1869
1870
    /**
1871
     * Get user list by usergroup.
1872
     *
1873
     * @param int    $id
1874
     * @param string $orderBy
1875
     *
1876
     * @return array
1877
     */
1878
    public function getUserListByUserGroup($id, $orderBy = '')
1879
    {
1880
        $id = (int) $id;
1881
        $sql = "SELECT u.* FROM $this->table_user u
1882
                INNER JOIN $this->usergroup_rel_user_table c
1883
                ON c.user_id = u.id
1884
                WHERE u.active <> ".USER_SOFT_DELETED." AND c.usergroup_id = $id"
1885
        ;
1886
        if (!empty($orderBy)) {
1887
            $orderBy = Database::escape_string($orderBy);
1888
            $sql .= " ORDER BY $orderBy ";
1889
        }
1890
        $result = Database::query($sql);
1891
1892
        return Database::store_result($result);
1893
    }
1894
1895
    /**
1896
     * @param FormValidator $form
1897
     * @param string        $type
1898
     */
1899
    public function setForm($form, $type = 'add', Usergroup $userGroup = null)
1900
    {
1901
        $header = '';
1902
        switch ($type) {
1903
            case 'add':
1904
                $header = get_lang('Add');
1905
                break;
1906
            case 'edit':
1907
                $header = get_lang('Edit');
1908
                break;
1909
        }
1910
1911
        $form->addHeader($header);
1912
1913
        // Name
1914
        $form->addText('title', get_lang('Title'), true, ['maxlength' => 255]);
1915
        $form->addRule('title', '', 'maxlength', 255);
1916
1917
        // Description
1918
        $form->addHtmlEditor(
1919
            'description',
1920
            get_lang('Description'),
1921
            true,
1922
            false,
1923
            [
1924
                'ToolbarSet' => 'Minimal',
1925
            ]
1926
        );
1927
        $form->applyFilter('description', 'trim');
1928
1929
        if ($this->showGroupTypeSetting) {
1930
            $form->addElement(
1931
                'checkbox',
1932
                'group_type',
1933
                null,
1934
                get_lang('Social group')
1935
            );
1936
        }
1937
1938
        // url
1939
        $form->addText('url', get_lang('URL'), false);
1940
1941
        // Picture
1942
        //$allowed_picture_types = $this->getAllowedPictureExtensions();
1943
1944
        // Picture
1945
        $form->addFile(
1946
            'picture',
1947
            get_lang('Add a picture'),
1948
            ['id' => 'picture', 'class' => 'picture-form', 'crop_image' => true, 'crop_ratio' => '1 / 1']
1949
        );
1950
1951
        $repo = Container::getIllustrationRepository();
1952
        if ($userGroup && $repo->hasIllustration($userGroup)) {
1953
            $picture = $repo->getIllustrationUrl($userGroup);
1954
            $img = '<img src="'.$picture.'" />';
1955
            $form->addLabel(null, $img);
1956
            $form->addElement('checkbox', 'delete_picture', '', get_lang('Remove picture'));
1957
        }
1958
1959
        $form->addSelect('visibility', get_lang('Group Permissions'), $this->getGroupStatusList());
1960
        $form->setRequiredNote('<span class="form_required">*</span> <small>'.get_lang('Required field').'</small>');
1961
        $form->addElement('checkbox', 'allow_members_leave_group', '', get_lang('Allow members to leave group'));
1962
1963
        // Setting the form elements
1964
        if ('add' === $type) {
1965
            $form->addButtonCreate($header);
1966
        } else {
1967
            $form->addButtonUpdate($header);
1968
        }
1969
    }
1970
1971
    /**
1972
     * Gets the current group image.
1973
     *
1974
     * @param string $id group id
1975
     * @param string picture group name
1976
     * @param string height
1977
     * @param int $size_picture picture size it can be small_,  medium_  or  big_
1978
     * @param string style css
1979
     *
1980
     * @return string
1981
     */
1982
    public function get_picture_group(
1983
        $id,
1984
        $picture_file,
1985
        $height,
1986
        $size_picture = GROUP_IMAGE_SIZE_MEDIUM,
1987
        $style = ''
1988
    ) {
1989
        $repoIllustration = Container::getIllustrationRepository();
1990
        $repoUserGroup = Container::getUsergroupRepository();
1991
        $userGroup = $repoUserGroup->find($id);
1992
1993
        return $repoIllustration->getIllustrationUrl($userGroup);
1994
1995
        /*
1996
        $picture = [];
1997
        //$picture['style'] = $style;
1998
        if ('unknown.jpg' === $picture_file) {
1999
            $picture['file'] = Display::returnIconPath($picture_file);
2000
2001
            return $picture;
2002
        }
2003
2004
        switch ($size_picture) {
2005
            case GROUP_IMAGE_SIZE_ORIGINAL:
2006
                $size_picture = '';
2007
                break;
2008
            case GROUP_IMAGE_SIZE_BIG:
2009
                $size_picture = 'big_';
2010
                break;
2011
            case GROUP_IMAGE_SIZE_MEDIUM:
2012
                $size_picture = 'medium_';
2013
                break;
2014
            case GROUP_IMAGE_SIZE_SMALL:
2015
                $size_picture = 'small_';
2016
                break;
2017
            default:
2018
                $size_picture = 'medium_';
2019
        }
2020
2021
        $image_array_sys = $this->get_group_picture_path_by_id($id, 'system', false, true);
2022
        $image_array = $this->get_group_picture_path_by_id($id, 'web', false, true);
2023
        $file = $image_array_sys['dir'].$size_picture.$picture_file;
2024
        if (file_exists($file)) {
2025
            $picture['file'] = $image_array['dir'].$size_picture.$picture_file;
2026
            //$picture['style'] = '';
2027
            if ($height > 0) {
2028
                $dimension = api_getimagesize($picture['file']);
2029
                $margin = ($height - $dimension['width']) / 2;
2030
                //@ todo the padding-top should not be here
2031
            }
2032
        } else {
2033
            $file = $image_array_sys['dir'].$picture_file;
2034
            if (file_exists($file) && !is_dir($file)) {
2035
                $picture['file'] = $image_array['dir'].$picture_file;
2036
            } else {
2037
                $picture['file'] = Display::returnIconPath('group_na.png', 64);
2038
            }
2039
        }
2040
2041
        return $picture;*/
2042
    }
2043
2044
    /**
2045
     * @return array
2046
     */
2047
    public function getAllowedPictureExtensions()
2048
    {
2049
        return ['jpg', 'jpeg', 'png', 'gif'];
2050
    }
2051
2052
    public function getGroupStatusList(): array
2053
    {
2054
        return [
2055
            GROUP_PERMISSION_OPEN => get_lang('Open'),
2056
            GROUP_PERMISSION_CLOSED => get_lang('Closed'),
2057
        ];
2058
    }
2059
2060
    /**
2061
     * @param int $type
2062
     */
2063
    public function setGroupType($type)
2064
    {
2065
        $this->groupType = (int) $type;
2066
    }
2067
2068
    /**
2069
     * @param int $group_id
2070
     * @param int $user_id
2071
     *
2072
     * @return bool
2073
     */
2074
    public function is_group_admin($group_id, $user_id = 0)
2075
    {
2076
        if (empty($user_id)) {
2077
            $user_id = api_get_user_id();
2078
        }
2079
        $user_role = $this->get_user_group_role($user_id, $group_id);
2080
        if (in_array($user_role, [GROUP_USER_PERMISSION_ADMIN])) {
2081
            return true;
2082
        }
2083
2084
        return false;
2085
    }
2086
2087
    /**
2088
     * @param int $group_id
2089
     * @param int $user_id
2090
     *
2091
     * @return bool
2092
     */
2093
    public function isGroupModerator($group_id, $user_id = 0)
2094
    {
2095
        if (empty($user_id)) {
2096
            $user_id = api_get_user_id();
2097
        }
2098
        $user_role = $this->get_user_group_role($user_id, $group_id);
2099
        if (in_array($user_role, [GROUP_USER_PERMISSION_ADMIN, GROUP_USER_PERMISSION_MODERATOR])) {
2100
            return true;
2101
        } else {
2102
            return false;
2103
        }
2104
    }
2105
2106
    /**
2107
     * @param int $group_id
2108
     * @param int $user_id
2109
     *
2110
     * @return bool
2111
     */
2112
    public function is_group_member($group_id, $user_id = 0)
2113
    {
2114
        if (api_is_platform_admin()) {
2115
            return true;
2116
        }
2117
        if (empty($user_id)) {
2118
            $user_id = api_get_user_id();
2119
        }
2120
        $roles = [
2121
            GROUP_USER_PERMISSION_ADMIN,
2122
            GROUP_USER_PERMISSION_MODERATOR,
2123
            GROUP_USER_PERMISSION_READER,
2124
            GROUP_USER_PERMISSION_HRM,
2125
        ];
2126
        $user_role = $this->get_user_group_role($user_id, $group_id);
2127
        if (in_array($user_role, $roles)) {
2128
            return true;
2129
        } else {
2130
            return false;
2131
        }
2132
    }
2133
2134
    /**
2135
     * Gets the relationship between a group and a User.
2136
     *
2137
     * @author Julio Montoya
2138
     *
2139
     * @param int $user_id
2140
     * @param int $group_id
2141
     *
2142
     * @return int 0 if there is no relationship; otherwise the normalized role
2143
     */
2144
    public function get_user_group_role($user_id, $group_id)
2145
    {
2146
        $table_group_rel_user = $this->usergroup_rel_user_table;
2147
        $return_value = 0;
2148
        $user_id = (int) $user_id;
2149
        $group_id = (int) $group_id;
2150
2151
        if (!empty($user_id) && !empty($group_id)) {
2152
            $sql = "SELECT relation_type
2153
                    FROM $table_group_rel_user
2154
                    WHERE
2155
                        usergroup_id = $group_id AND
2156
                        user_id = $user_id";
2157
            $result = Database::query($sql);
2158
            if (Database::num_rows($result) > 0) {
2159
                $row = Database::fetch_assoc($result);
2160
                $relationType = (int) $row['relation_type'];
2161
2162
                // Normalize legacy reader (2) to the canonical reader role
2163
                if (2 === $relationType) {
2164
                    $relationType = GROUP_USER_PERMISSION_READER;
2165
                }
2166
2167
                $return_value = $relationType;
2168
            }
2169
        }
2170
2171
        return $return_value;
2172
    }
2173
2174
    /**
2175
     * @param int $userId
2176
     * @param int $groupId
2177
     *
2178
     * @return string
2179
     */
2180
    public function getUserRoleToString($userId, $groupId)
2181
    {
2182
        $role = $this->get_user_group_role($userId, $groupId);
2183
        $roleToString = '';
2184
2185
        switch ($role) {
2186
            case GROUP_USER_PERMISSION_ADMIN:
2187
                $roleToString = get_lang('Admin');
2188
                break;
2189
            case GROUP_USER_PERMISSION_READER:
2190
                $roleToString = get_lang('Reader');
2191
                break;
2192
            case GROUP_USER_PERMISSION_PENDING_INVITATION:
2193
                $roleToString = get_lang('Pending invitation');
2194
                break;
2195
            case GROUP_USER_PERMISSION_MODERATOR:
2196
                $roleToString = get_lang('Moderator');
2197
                break;
2198
            case GROUP_USER_PERMISSION_HRM:
2199
                $roleToString = get_lang('Human Resources Manager');
2200
                break;
2201
        }
2202
2203
        return $roleToString;
2204
    }
2205
2206
    /**
2207
     * Add a group of users into a group of URLs.
2208
     *
2209
     * @author Julio Montoya
2210
     *
2211
     * @param array $user_list
2212
     * @param array $group_list
2213
     * @param int   $relation_type
2214
     *
2215
     * @return array
2216
     */
2217
    public function add_users_to_groups($user_list, $group_list, $relation_type = GROUP_USER_PERMISSION_READER)
2218
    {
2219
        $table_url_rel_group = $this->usergroup_rel_user_table;
2220
        $result_array = [];
2221
        $relation_type = (int) $relation_type;
2222
2223
        if (is_array($user_list) && is_array($group_list)) {
2224
            foreach ($group_list as $group_id) {
2225
                foreach ($user_list as $user_id) {
2226
                    $user_id = (int) $user_id;
2227
                    $group_id = (int) $group_id;
2228
2229
                    $role = $this->get_user_group_role($user_id, $group_id);
2230
                    if (0 == $role) {
2231
                        $sql = "INSERT INTO $table_url_rel_group
2232
		               			SET
2233
		               			    user_id = $user_id ,
2234
		               			    usergroup_id = $group_id ,
2235
		               			    relation_type = $relation_type ";
2236
2237
                        $result = Database::query($sql);
2238
                        if ($result) {
2239
                            $result_array[$group_id][$user_id] = 1;
2240
                        } else {
2241
                            $result_array[$group_id][$user_id] = 0;
2242
                        }
2243
                    }
2244
                }
2245
            }
2246
        }
2247
2248
        return $result_array;
2249
    }
2250
2251
    /**
2252
     * Deletes an url and session relationship.
2253
     *
2254
     * @author Julio Montoya
2255
     *
2256
     * @param int $userId
2257
     * @param int $groupId
2258
     *
2259
     * @return bool true if success
2260
     * */
2261
    public function delete_user_rel_group($userId, $groupId)
2262
    {
2263
        $userId = (int) $userId;
2264
        $groupId = (int) $groupId;
2265
        if (empty($userId) || empty($groupId)) {
2266
            return false;
2267
        }
2268
2269
        $table = $this->usergroup_rel_user_table;
2270
        $sql = "DELETE FROM $table
2271
                WHERE
2272
                    user_id = $userId AND
2273
                    usergroup_id = $groupId";
2274
2275
        $result = Database::query($sql);
2276
2277
        return $result;
2278
    }
2279
2280
    /**
2281
     * Add a user into a group.
2282
     *
2283
     * @author Julio Montoya
2284
     *
2285
     * @param int $user_id
2286
     * @param int $group_id
2287
     * @param int $relation_type
2288
     *
2289
     * @return bool true if success
2290
     */
2291
    public function add_user_to_group($user_id, $group_id, $relation_type = GROUP_USER_PERMISSION_READER)
2292
    {
2293
        $table_rel = $this->usergroup_rel_user_table;
2294
        $user_id = (int) $user_id;
2295
        $group_id = (int) $group_id;
2296
        $relation_type = (int) $relation_type;
2297
2298
        if (empty($user_id) || empty($group_id)) {
2299
            return false;
2300
        }
2301
2302
        // Normalize relation type for classes vs social groups
2303
        $groupInfo = $this->get($group_id); // returns ['group_type' => ...] among others
2304
        if (!empty($groupInfo) && isset($groupInfo['group_type'])) {
2305
            if ((int) $groupInfo['group_type'] === self::NORMAL_CLASS) {
2306
                // For class memberships, we want relation_type = 0 as the canonical "reader"
2307
                if ($relation_type === GROUP_USER_PERMISSION_READER) {
2308
                    $relation_type = 0;
2309
                }
2310
            }
2311
        }
2312
2313
        // Current role (raw value from usergroup_rel_user)
2314
        $role = $this->get_user_group_role($user_id, $group_id);
2315
2316
        if (0 === $role) {
2317
            // No relationship yet → insert normalized relation_type
2318
            $sql = "INSERT INTO $table_rel
2319
                SET
2320
                    user_id = $user_id,
2321
                    usergroup_id = $group_id,
2322
                    relation_type = $relation_type";
2323
            Database::query($sql);
2324
        } elseif (GROUP_USER_PERMISSION_PENDING_INVITATION === $role) {
2325
            // If somebody already invited the user, upgrade to final role
2326
            self::update_user_role(
2327
                $user_id,
2328
                $group_id,
2329
                $relation_type ?: GROUP_USER_PERMISSION_READER
2330
            );
2331
        } elseif (
2332
            // Backward-compatibility: old "reader = 2" for classes → normalize to 0
2333
            GROUP_USER_PERMISSION_READER === $role
2334
            && $relation_type === 0
2335
        ) {
2336
            self::update_user_role($user_id, $group_id, 0);
2337
        }
2338
2339
        return true;
2340
    }
2341
2342
    /**
2343
     * Updates the group_rel_user table  with a given user and group ids.
2344
     *
2345
     * @author Julio Montoya
2346
     *
2347
     * @param int $user_id
2348
     * @param int $group_id
2349
     * @param int $relation_type
2350
     */
2351
    public function update_user_role($user_id, $group_id, $relation_type = GROUP_USER_PERMISSION_READER)
2352
    {
2353
        $table_group_rel_user = $this->usergroup_rel_user_table;
2354
        $group_id = (int) $group_id;
2355
        $user_id = (int) $user_id;
2356
        $relation_type = (int) $relation_type;
2357
2358
        $sql = "UPDATE $table_group_rel_user
2359
   				SET relation_type = $relation_type
2360
                WHERE user_id = $user_id AND usergroup_id = $group_id";
2361
        Database::query($sql);
2362
    }
2363
2364
    /**
2365
     * Gets the inner join from users and group table.
2366
     *
2367
     * @return array|int Database::store_result of the result
2368
     *
2369
     * @author Julio Montoya
2370
     * */
2371
    public function get_groups_by_user($user_id, $relationType = GROUP_USER_PERMISSION_READER, $with_image = false)
2372
    {
2373
        $table_group_rel_user = $this->usergroup_rel_user_table;
2374
        $tbl_group = $this->table;
2375
        $user_id = (int) $user_id;
2376
2377
        if (0 == $relationType) {
2378
            $relationCondition = '';
2379
        } else {
2380
            if (is_array($relationType)) {
2381
                $relationType = array_map('intval', $relationType);
2382
                $relationType = implode("','", $relationType);
2383
                $relationCondition = " AND ( gu.relation_type IN ('$relationType')) ";
2384
            } else {
2385
                $relationType = (int) $relationType;
2386
                $relationCondition = " AND gu.relation_type = $relationType ";
2387
            }
2388
        }
2389
2390
        $sql = 'SELECT
2391
                    g.picture,
2392
                    g.title,
2393
                    g.description,
2394
                    g.id ,
2395
                    gu.relation_type';
2396
2397
        $urlCondition = '';
2398
        if ($this->getUseMultipleUrl()) {
2399
            $sql .= " FROM $tbl_group g
2400
                    INNER JOIN ".$this->access_url_rel_usergroup." a
2401
                    ON (g.id = a.usergroup_id)
2402
                    INNER JOIN $table_group_rel_user gu
2403
                    ON gu.usergroup_id = g.id";
2404
            $urlId = api_get_current_access_url_id();
2405
            $urlCondition = " AND access_url_id = $urlId ";
2406
        } else {
2407
            $sql .= " FROM $tbl_group g
2408
                    INNER JOIN $table_group_rel_user gu
2409
                    ON gu.usergroup_id = g.id";
2410
        }
2411
2412
        $sql .= " WHERE
2413
				    g.group_type = ".Usergroup::SOCIAL_CLASS." AND
2414
                    gu.user_id = $user_id
2415
                    $relationCondition
2416
                    $urlCondition
2417
                ORDER BY created_at DESC ";
2418
        $result = Database::query($sql);
2419
        $array = [];
2420
        if (Database::num_rows($result) > 0) {
2421
            while ($row = Database::fetch_assoc($result)) {
2422
                if ($with_image) {
2423
                    $picture = $this->get_picture_group($row['id'], $row['picture'], 80);
2424
                    $img = '<img src="'.$picture['file'].'" />';
2425
                    $row['picture'] = $img;
2426
                }
2427
                $array[$row['id']] = $row;
2428
            }
2429
        }
2430
2431
        return $array;
2432
    }
2433
2434
    /** Gets the inner join of users and group table.
2435
     * @param int  quantity of records
2436
     * @param bool show groups with image or not
2437
     *
2438
     * @return array with group content
2439
     *
2440
     * @author Julio Montoya
2441
     * */
2442
    public function get_groups_by_popularity($num = 6, $with_image = true)
2443
    {
2444
        $table_group_rel_user = $this->usergroup_rel_user_table;
2445
        $tbl_group = $this->table;
2446
        if (empty($num)) {
2447
            $num = 6;
2448
        } else {
2449
            $num = (int) $num;
2450
        }
2451
        // only show admins and readers
2452
        $whereCondition = " WHERE
2453
                              g.group_type = ".Usergroup::SOCIAL_CLASS." AND
2454
                              gu.relation_type IN
2455
                              ('".GROUP_USER_PERMISSION_ADMIN."' , '".GROUP_USER_PERMISSION_READER."', '".GROUP_USER_PERMISSION_HRM."') ";
2456
2457
        $sql = 'SELECT DISTINCT count(user_id) as count, g.picture, g.title, g.description, g.id ';
2458
2459
        $urlCondition = '';
2460
        if ($this->getUseMultipleUrl()) {
2461
            $sql .= " FROM $tbl_group g
2462
                    INNER JOIN ".$this->access_url_rel_usergroup." a
2463
                    ON (g.id = a.usergroup_id)
2464
                    INNER JOIN $table_group_rel_user gu
2465
                    ON gu.usergroup_id = g.id";
2466
            $urlId = api_get_current_access_url_id();
2467
            $urlCondition = " AND access_url_id = $urlId ";
2468
        } else {
2469
            $sql .= " FROM $tbl_group g
2470
                    INNER JOIN $table_group_rel_user gu
2471
                    ON gu.usergroup_id = g.id";
2472
        }
2473
2474
        $sql .= "
2475
				$whereCondition
2476
				$urlCondition
2477
				GROUP BY g.id
2478
				ORDER BY count DESC
2479
				LIMIT $num";
2480
2481
        $result = Database::query($sql);
2482
        $array = [];
2483
        while ($row = Database::fetch_assoc($result)) {
2484
            if ($with_image) {
2485
                $picture = $this->get_picture_group($row['id'], $row['picture'], 80);
2486
                $img = '<img src="'.$picture['file'].'" />';
2487
                $row['picture'] = $img;
2488
            }
2489
            if (empty($row['id'])) {
2490
                continue;
2491
            }
2492
            $array[$row['id']] = $row;
2493
        }
2494
2495
        return $array;
2496
    }
2497
2498
    /** Gets the last groups created.
2499
     * @param int  $num       quantity of records
2500
     * @param bool $withImage show groups with image or not
2501
     *
2502
     * @return array with group content
2503
     *
2504
     * @author Julio Montoya
2505
     * */
2506
    public function get_groups_by_age($num = 6, $withImage = true)
2507
    {
2508
        $table_group_rel_user = $this->usergroup_rel_user_table;
2509
        $tbl_group = $this->table;
2510
2511
        if (empty($num)) {
2512
            $num = 6;
2513
        } else {
2514
            $num = (int) $num;
2515
        }
2516
2517
        $where = " WHERE
2518
                        g.group_type = ".Usergroup::SOCIAL_CLASS." AND
2519
                        gu.relation_type IN
2520
                        ('".GROUP_USER_PERMISSION_ADMIN."' ,
2521
                        '".GROUP_USER_PERMISSION_READER."',
2522
                        '".GROUP_USER_PERMISSION_MODERATOR."',
2523
                        '".GROUP_USER_PERMISSION_HRM."')
2524
                    ";
2525
        $sql = 'SELECT DISTINCT
2526
                  count(user_id) as count,
2527
                  g.picture,
2528
                  g.title,
2529
                  g.description,
2530
                  g.id ';
2531
2532
        $urlCondition = '';
2533
        if ($this->getUseMultipleUrl()) {
2534
            $sql .= " FROM $tbl_group g
2535
                    INNER JOIN ".$this->access_url_rel_usergroup." a
2536
                    ON (g.id = a.usergroup_id)
2537
                    INNER JOIN $table_group_rel_user gu
2538
                    ON gu.usergroup_id = g.id";
2539
            $urlId = api_get_current_access_url_id();
2540
            $urlCondition = " AND access_url_id = $urlId ";
2541
        } else {
2542
            $sql .= " FROM $tbl_group g
2543
                    INNER JOIN $table_group_rel_user gu
2544
                    ON gu.usergroup_id = g.id";
2545
        }
2546
        $sql .= "
2547
                $where
2548
                $urlCondition
2549
                GROUP BY g.id
2550
                ORDER BY created_at DESC
2551
                LIMIT $num ";
2552
2553
        $result = Database::query($sql);
2554
        $array = [];
2555
        while ($row = Database::fetch_assoc($result)) {
2556
            if ($withImage) {
2557
                $picture = $this->get_picture_group($row['id'], $row['picture'], 80);
2558
                $img = '<img src="'.$picture['file'].'" />';
2559
                $row['picture'] = $img;
2560
            }
2561
            if (empty($row['id'])) {
2562
                continue;
2563
            }
2564
            $array[$row['id']] = $row;
2565
        }
2566
2567
        return $array;
2568
    }
2569
2570
    /**
2571
     * Gets the group's members.
2572
     *
2573
     * @param int group id
2574
     * @param bool show image or not of the group
2575
     * @param array list of relation type use constants
2576
     * @param int from value
2577
     * @param int limit
2578
     * @param array image configuration, i.e array('height'=>'20px', 'size'=> '20px')
2579
     *
2580
     * @return array list of users in a group
2581
     */
2582
    public function get_users_by_group(
2583
        $group_id,
2584
        $withImage = false,
2585
        $relation_type = [],
2586
        $from = null,
2587
        $limit = null,
2588
        $image_conf = ['size' => USER_IMAGE_SIZE_MEDIUM, 'height' => 80]
2589
    ) {
2590
        $table_group_rel_user = $this->usergroup_rel_user_table;
2591
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
2592
        $group_id = (int) $group_id;
2593
2594
        if (empty($group_id)) {
2595
            return [];
2596
        }
2597
2598
        $limit_text = '';
2599
        if (isset($from) && isset($limit)) {
2600
            $from = (int) $from;
2601
            $limit = (int) $limit;
2602
            $limit_text = "LIMIT $from, $limit";
2603
        }
2604
2605
        if (0 == count($relation_type)) {
2606
            $where_relation_condition = '';
2607
        } else {
2608
            $new_relation_type = [];
2609
            foreach ($relation_type as $rel) {
2610
                $rel = (int) $rel;
2611
                $new_relation_type[] = "'$rel'";
2612
            }
2613
            $relation_type = implode(',', $new_relation_type);
2614
            if (!empty($relation_type)) {
2615
                $where_relation_condition = "AND gu.relation_type IN ($relation_type) ";
2616
            }
2617
        }
2618
2619
        $sql = "SELECT
2620
                    picture_uri as image,
2621
                    u.id,
2622
                    CONCAT (u.firstname,' ', u.lastname) as fullname,
2623
                    relation_type
2624
    		    FROM $tbl_user u
2625
    		    INNER JOIN $table_group_rel_user gu
2626
    			ON (gu.user_id = u.id)
2627
    			WHERE
2628
    			    u.active <> ".USER_SOFT_DELETED." AND
2629
    			    gu.usergroup_id= $group_id
2630
    			    $where_relation_condition
2631
    			ORDER BY relation_type, firstname
2632
    			$limit_text";
2633
2634
        $result = Database::query($sql);
2635
        $array = [];
2636
        while ($row = Database::fetch_assoc($result)) {
2637
            if ($withImage) {
2638
                $userInfo = api_get_user_info($row['id']);
2639
                $userPicture = UserManager::getUserPicture($row['id']);
2640
                $row['image'] = '<img src="'.$userPicture.'"  />';
2641
                $row['user_info'] = $userInfo;
2642
            }
2643
2644
            $row['user_id'] = $row['id'];
2645
            $array[$row['id']] = $row;
2646
        }
2647
2648
        return $array;
2649
    }
2650
2651
    /**
2652
     * Gets all the members of a group no matter the relationship for
2653
     * more specifications use get_users_by_group.
2654
     *
2655
     * @param int group id
2656
     *
2657
     * @return array
2658
     */
2659
    public function get_all_users_by_group($group_id)
2660
    {
2661
        $table_group_rel_user = $this->usergroup_rel_user_table;
2662
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
2663
        $group_id = (int) $group_id;
2664
2665
        if (empty($group_id)) {
2666
            return [];
2667
        }
2668
2669
        $sql = "SELECT u.id, u.firstname, u.lastname, relation_type
2670
                FROM $tbl_user u
2671
			    INNER JOIN $table_group_rel_user gu
2672
			    ON (gu.user_id = u.id)
2673
			    WHERE u.active <> ".USER_SOFT_DELETED." AND gu.usergroup_id= $group_id
2674
			    ORDER BY relation_type, firstname";
2675
2676
        $result = Database::query($sql);
2677
        $array = [];
2678
        while ($row = Database::fetch_assoc($result)) {
2679
            $array[$row['id']] = $row;
2680
        }
2681
2682
        return $array;
2683
    }
2684
2685
    /**
2686
     * Shows the left column of the group page.
2687
     *
2688
     * @param int    $group_id
2689
     * @param int    $user_id
2690
     * @param string $show
2691
     *
2692
     * @return string
2693
     */
2694
    public function show_group_column_information($group_id, $user_id, $show = '')
2695
    {
2696
        $html = '';
2697
        $group_info = $this->get($group_id);
2698
2699
        //my relation with the group is set here
2700
        $my_group_role = $this->get_user_group_role($user_id, $group_id);
2701
2702
        // Loading group permission
2703
        $links = '';
2704
        switch ($my_group_role) {
2705
            case GROUP_USER_PERMISSION_READER:
2706
                // I'm just a reader
2707
                $relation_group_title = get_lang('I am a reader');
2708
                $links .= '<li class="'.('invite_friends' == $show ? 'active' : '').'"><a href="group_invitation.php?id='.$group_id.'">'.
2709
                    Display::getMdiIcon(ObjectIcon::INVITATION, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Invite friends')).get_lang('Invite friends').'</a></li>';
2710
                if (self::canLeave($group_info)) {
2711
                    $links .= '<li><a href="group_view.php?id='.$group_id.'&action=leave&u='.api_get_user_id().'">'.
2712
                        Display::getMdiIcon(ActionIcon::EXIT, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Leave group')).get_lang('Leave group').'</a></li>';
2713
                }
2714
                break;
2715
            case GROUP_USER_PERMISSION_ADMIN:
2716
                $relation_group_title = get_lang('I am an admin');
2717
                $links .= '<li class="'.('group_edit' == $show ? 'active' : '').'"><a href="group_edit.php?id='.$group_id.'">'.
2718
                    Display::getMdiIcon(ActionIcon::EDIT, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Edit this group')).get_lang('Edit this group').'</a></li>';
2719
                $links .= '<li class="'.('member_list' == $show ? 'active' : '').'"><a href="group_waiting_list.php?id='.$group_id.'">'.
2720
                    Display::getMdiIcon(ObjectIcon::WAITING_LIST, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Waiting list')).get_lang('Waiting list').'</a></li>';
2721
                $links .= '<li class="'.('invite_friends' == $show ? 'active' : '').'"><a href="group_invitation.php?id='.$group_id.'">'.
2722
                    Display::getMdiIcon(ObjectIcon::INVITATION, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Invite friends')).get_lang('Invite friends').'</a></li>';
2723
                if (self::canLeave($group_info)) {
2724
                    $links .= '<li><a href="group_view.php?id='.$group_id.'&action=leave&u='.api_get_user_id().'">'.
2725
                        Display::getMdiIcon(ActionIcon::EXIT, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Leave group')).get_lang('Leave group').'</a></li>';
2726
                }
2727
                break;
2728
            case GROUP_USER_PERMISSION_PENDING_INVITATION:
2729
//				$links .=  '<li><a href="groups.php?id='.$group_id.'&action=join&u='.api_get_user_id().'">'.Display::return_icon('addd.gif', get_lang('You have been invited to join now'), array('hspace'=>'6')).'<span class="social-menu-text4" >'.get_lang('You have been invited to join now').'</span></a></li>';
2730
                break;
2731
            case GROUP_USER_PERMISSION_PENDING_INVITATION_SENT_BY_USER:
2732
                $relation_group_title = get_lang('Waiting for admin response');
2733
                break;
2734
            case GROUP_USER_PERMISSION_MODERATOR:
2735
                $relation_group_title = get_lang('I am a moderator');
2736
                //$links .=  '<li><a href="'.api_get_path(WEB_CODE_PATH).'social/message_for_group_form.inc.php?view_panel=1&height=400&width=610&&user_friend='.api_get_user_id().'&group_id='.$group_id.'&action=add_message_group" class="thickbox" title="'.get_lang('Compose message').'">'.Display::getMdiIcon(ActionIcon::EDIT, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Create thread')).'<span class="social-menu-text4" >'.get_lang('Create thread').'</span></a></li>';
2737
                //$links .=  '<li><a href="groups.php?id='.$group_id.'">'.				Display::getMdiIcon(ToolIcon::MESSAGE, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Messages list')).'<span class="'.($show=='messages_list'?'social-menu-text-active':'social-menu-text4').'" >'.get_lang('Messages list').'</span></a></li>';
2738
                //$links .=  '<li><a href="group_members.php?id='.$group_id.'">'.		Display::getMdiIcon(ObjectIcon::GROUP, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Members list')).'<span class="'.($show=='member_list'?'social-menu-text-active':'social-menu-text4').'" >'.get_lang('Members list').'</span></a></li>';
2739
                if (GROUP_PERMISSION_CLOSED == $group_info['visibility']) {
2740
                    $links .= '<li><a href="group_waiting_list.php?id='.$group_id.'">'.
2741
                        Display::getMdiIcon(ObjectIcon::WAITING_LIST, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Waiting list')).get_lang('Waiting list').'</a></li>';
2742
                }
2743
                $links .= '<li><a href="group_invitation.php?id='.$group_id.'">'.
2744
                    Display::getMdiIcon(ObjectIcon::INVITATION, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Invite friends')).get_lang('Invite friends').'</a></li>';
2745
                if (self::canLeave($group_info)) {
2746
                    $links .= '<li><a href="group_view.php?id='.$group_id.'&action=leave&u='.api_get_user_id().'">'.
2747
                        Display::getMdiIcon(ActionIcon::EXIT, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Leave group')).get_lang('Leave group').'</a></li>';
2748
                }
2749
                break;
2750
            case GROUP_USER_PERMISSION_HRM:
2751
                $relation_group_title = get_lang('I am a human resources manager');
2752
                $links .= '<li><a href="'.api_get_path(WEB_CODE_PATH).'social/message_for_group_form.inc.php?view_panel=1&height=400&width=610&&user_friend='.api_get_user_id().'&group_id='.$group_id.'&action=add_message_group" class="ajax" title="'.get_lang('Compose message').'" data-size="lg" data-title="'.get_lang('Compose message').'">'.
2753
                    Display::getMdiIcon(ActionIcon::EDIT, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Create thread')).get_lang('Create thread').'</a></li>';
2754
                $links .= '<li><a href="group_view.php?id='.$group_id.'">'.
2755
                    Display::getMdiIcon(ToolIcon::MESSAGE, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Messages list')).get_lang('Messages list').'</a></li>';
2756
                $links .= '<li><a href="group_invitation.php?id='.$group_id.'">'.
2757
                    Display::getMdiIcon(ObjectIcon::INVITATION, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Invite friends')).get_lang('Invite friends').'</a></li>';
2758
                $links .= '<li><a href="group_members.php?id='.$group_id.'">'.
2759
                    Display::getMdiIcon(ObjectIcon::GROUP, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Members list')).get_lang('Members list').'</a></li>';
2760
                $links .= '<li><a href="group_view.php?id='.$group_id.'&action=leave&u='.api_get_user_id().'">'.
2761
                    Display::getMdiIcon(ActionIcon::EXIT, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Leave group')).get_lang('Leave group').'</a></li>';
2762
                break;
2763
            default:
2764
                //$links .=  '<li><a href="groups.php?id='.$group_id.'&action=join&u='.api_get_user_id().'">'.Display::return_icon('addd.gif', get_lang('Join group'), array('hspace'=>'6')).'<span class="social-menu-text4" >'.get_lang('Join group').'</a></span></li>';
2765
                break;
2766
        }
2767
        if (!empty($links)) {
2768
            $list = '<ul class="nav nav-pills">';
2769
            $list .= $links;
2770
            $list .= '</ul>';
2771
            $html .= Display::panelCollapse(
2772
                get_lang('Social groups'),
2773
                $list,
2774
                'sm-groups',
2775
                [],
2776
                'groups-acordeon',
2777
                'groups-collapse'
2778
            );
2779
        }
2780
2781
        return $html;
2782
    }
2783
2784
    /**
2785
     * @param int $group_id
2786
     * @param int $topic_id
2787
     */
2788
    public function delete_topic($group_id, $topic_id)
2789
    {
2790
        $table_message = Database::get_main_table(TABLE_MESSAGE);
2791
        $topic_id = (int) $topic_id;
2792
        $group_id = (int) $group_id;
2793
2794
        $sql = "UPDATE $table_message SET
2795
                    msg_type = 3
2796
                WHERE
2797
                    group_id = $group_id AND
2798
                    (id = '$topic_id' OR parent_id = $topic_id)
2799
                ";
2800
        Database::query($sql);
2801
    }
2802
2803
    /**
2804
     * @param string $user_id
2805
     * @param int    $relation_type
2806
     * @param bool   $with_image
2807
     *
2808
     * @deprecated
2809
     *
2810
     * @return int
2811
     */
2812
    public function get_groups_by_user_count(
2813
        $user_id = '',
2814
        $relation_type = GROUP_USER_PERMISSION_READER,
2815
        $with_image = false
2816
    ) {
2817
        $table_group_rel_user = $this->usergroup_rel_user_table;
2818
        $tbl_group = $this->table;
2819
        $user_id = (int) $user_id;
2820
2821
        if (0 == $relation_type) {
2822
            $where_relation_condition = '';
2823
        } else {
2824
            $relation_type = (int) $relation_type;
2825
            $where_relation_condition = "AND gu.relation_type = $relation_type ";
2826
        }
2827
2828
        $sql = "SELECT count(g.id) as count
2829
				FROM $tbl_group g
2830
				INNER JOIN $table_group_rel_user gu
2831
				ON gu.usergroup_id = g.id
2832
				WHERE gu.user_id = $user_id $where_relation_condition ";
2833
2834
        $result = Database::query($sql);
2835
        if (Database::num_rows($result) > 0) {
2836
            $row = Database::fetch_assoc($result);
2837
2838
            return $row['count'];
2839
        }
2840
2841
        return 0;
2842
    }
2843
2844
    /**
2845
     * @param string $tag
2846
     * @param int    $from
2847
     * @param int    $number_of_items
2848
     *
2849
     * @return array
2850
     */
2851
    public function get_all_group_tags($tag, $from = 0, $number_of_items = 10, $getCount = false)
2852
    {
2853
        $group_table = $this->table;
2854
        $tag = Database::escape_string($tag);
2855
        $from = (int) $from;
2856
        $number_of_items = (int) $number_of_items;
2857
        $return = [];
2858
2859
        $keyword = $tag;
2860
        $sql = 'SELECT  g.id, g.title, g.description, g.url, g.picture ';
2861
        $urlCondition = '';
2862
        if ($this->getUseMultipleUrl()) {
2863
            $urlId = api_get_current_access_url_id();
2864
            $sql .= " FROM $this->table g
2865
                    INNER JOIN $this->access_url_rel_usergroup a
2866
                    ON (g.id = a.usergroup_id)";
2867
            $urlCondition = " AND access_url_id = $urlId ";
2868
        } else {
2869
            $sql .= " FROM $group_table g";
2870
        }
2871
        if (isset($keyword)) {
2872
            $sql .= " WHERE (
2873
                        g.title LIKE '%".$keyword."%' OR
2874
                        g.description LIKE '%".$keyword."%' OR
2875
                        g.url LIKE '%".$keyword."%'
2876
                     ) $urlCondition
2877
                     ";
2878
        } else {
2879
            $sql .= " WHERE 1 = 1 $urlCondition ";
2880
        }
2881
2882
        $direction = 'ASC';
2883
        if (!in_array($direction, ['ASC', 'DESC'])) {
2884
            $direction = 'ASC';
2885
        }
2886
2887
        $sql .= " LIMIT $from, $number_of_items";
2888
2889
        $res = Database::query($sql);
2890
        if (Database::num_rows($res) > 0) {
2891
            while ($row = Database::fetch_assoc($res)) {
2892
                if (!in_array($row['id'], $return)) {
2893
                    $return[$row['id']] = $row;
2894
                }
2895
            }
2896
        }
2897
2898
        return $return;
2899
    }
2900
2901
    /**
2902
     * @param int $group_id
2903
     *
2904
     * @return array
2905
     */
2906
    public static function get_parent_groups($group_id)
2907
    {
2908
        $t_rel_group = Database::get_main_table(TABLE_USERGROUP_REL_USERGROUP);
2909
        $group_id = (int) $group_id;
2910
2911
        $max_level = 10;
2912
        $select_part = 'SELECT ';
2913
        $cond_part = '';
2914
        for ($i = 1; $i <= $max_level; $i++) {
2915
            $rg_number = $i - 1;
2916
            if ($i == $max_level) {
2917
                $select_part .= "rg$rg_number.group_id as id_$rg_number ";
2918
            } else {
2919
                $select_part .= "rg$rg_number.group_id as id_$rg_number, ";
2920
            }
2921
            if (1 == $i) {
2922
                $cond_part .= "FROM $t_rel_group rg0
2923
                               LEFT JOIN $t_rel_group rg$i
2924
                               ON rg$rg_number.group_id = rg$i.subgroup_id ";
2925
            } else {
2926
                $cond_part .= " LEFT JOIN $t_rel_group rg$i
2927
                                ON rg$rg_number.group_id = rg$i.subgroup_id ";
2928
            }
2929
        }
2930
        $sql = $select_part.' '.$cond_part."WHERE rg0.subgroup_id='$group_id'";
2931
        $res = Database::query($sql);
2932
        $temp_arr = Database::fetch_array($res, 'NUM');
2933
        $toReturn = [];
2934
        if (is_array($temp_arr)) {
2935
            foreach ($temp_arr as $elt) {
2936
                if (isset($elt)) {
2937
                    $toReturn[] = $elt;
2938
                }
2939
            }
2940
        }
2941
2942
        return $toReturn;
2943
    }
2944
2945
    /**
2946
     * Get the group member list by a user and his group role.
2947
     *
2948
     * @param int  $userId                The user ID
2949
     * @param int  $relationType          Optional. The relation type. GROUP_USER_PERMISSION_ADMIN by default
2950
     * @param bool $includeSubgroupsUsers Optional. Whether include the users from subgroups
2951
     *
2952
     * @return array
2953
     */
2954
    public function getGroupUsersByUser(
2955
        $userId,
2956
        $relationType = GROUP_USER_PERMISSION_ADMIN,
2957
        $includeSubgroupsUsers = true
2958
    ) {
2959
        $userId = (int) $userId;
2960
        $groups = $this->get_groups_by_user($userId, $relationType);
2961
        $groupsId = array_keys($groups);
2962
        $subgroupsId = [];
2963
        $userIdList = [];
2964
2965
        if ($includeSubgroupsUsers) {
2966
            foreach ($groupsId as $groupId) {
2967
                $subgroupsId = array_merge($subgroupsId, self::getGroupsByDepthLevel($groupId));
2968
            }
2969
2970
            $groupsId = array_merge($groupsId, $subgroupsId);
2971
        }
2972
2973
        $groupsId = array_unique($groupsId);
2974
2975
        if (empty($groupsId)) {
2976
            return [];
2977
        }
2978
2979
        foreach ($groupsId as $groupId) {
2980
            $groupUsers = $this->get_users_by_group($groupId);
2981
2982
            if (empty($groupUsers)) {
2983
                continue;
2984
            }
2985
2986
            foreach ($groupUsers as $member) {
2987
                if ($member['user_id'] == $userId) {
2988
                    continue;
2989
                }
2990
2991
                $userIdList[] = (int) $member['user_id'];
2992
            }
2993
        }
2994
2995
        return array_unique($userIdList);
2996
    }
2997
2998
    /**
2999
     * Get the subgroups ID from a group.
3000
     * The default $levels value is 10 considering it as a extensive level of depth.
3001
     *
3002
     * @param int $groupId The parent group ID
3003
     * @param int $levels  The depth levels
3004
     *
3005
     * @return array The list of ID
3006
     */
3007
    public static function getGroupsByDepthLevel($groupId, $levels = 10)
3008
    {
3009
        $groups = [];
3010
        $groupId = (int) $groupId;
3011
3012
        $groupTable = Database::get_main_table(TABLE_USERGROUP);
3013
        $groupRelGroupTable = Database::get_main_table(TABLE_USERGROUP_REL_USERGROUP);
3014
3015
        $select = 'SELECT ';
3016
        $from = "FROM $groupTable g1 ";
3017
3018
        for ($i = 1; $i <= $levels; $i++) {
3019
            $tableIndexNumber = $i;
3020
            $tableIndexJoinNumber = $i - 1;
3021
            $select .= "g$i.id as id_$i ";
3022
            $select .= $i != $levels ? ', ' : null;
3023
3024
            if (1 == $i) {
3025
                $from .= " INNER JOIN $groupRelGroupTable gg0
3026
                           ON g1.id = gg0.subgroup_id and gg0.group_id = $groupId ";
3027
            } else {
3028
                $from .= "LEFT JOIN $groupRelGroupTable gg$tableIndexJoinNumber ";
3029
                $from .= " ON g$tableIndexJoinNumber.id = gg$tableIndexJoinNumber.group_id ";
3030
                $from .= "LEFT JOIN $groupTable g$tableIndexNumber ";
3031
                $from .= " ON gg$tableIndexJoinNumber.subgroup_id = g$tableIndexNumber.id ";
3032
            }
3033
        }
3034
3035
        $result = Database::query("$select $from");
3036
3037
        while ($item = Database::fetch_assoc($result)) {
3038
            foreach ($item as $myGroupId) {
3039
                if (!empty($myGroupId)) {
3040
                    $groups[] = $myGroupId;
3041
                }
3042
            }
3043
        }
3044
3045
        return array_map('intval', $groups);
3046
    }
3047
3048
    /**
3049
     * Set a parent group.
3050
     *
3051
     * @param int $group_id
3052
     * @param int $parent_group_id if 0, we delete the parent_group association
3053
     * @param int $relation_type
3054
     *
3055
     * @return \Doctrine\DBAL\Statement
3056
     */
3057
    public function setParentGroup($group_id, $parent_group_id, $relation_type = 1)
3058
    {
3059
        $table = Database::get_main_table(TABLE_USERGROUP_REL_USERGROUP);
3060
        $group_id = (int) $group_id;
3061
        $parent_group_id = (int) $parent_group_id;
3062
        if (0 == $parent_group_id) {
3063
            $sql = "DELETE FROM $table WHERE subgroup_id = $group_id";
3064
        } else {
3065
            $sql = "SELECT group_id FROM $table WHERE subgroup_id = $group_id";
3066
            $res = Database::query($sql);
3067
            if (0 == Database::num_rows($res)) {
3068
                $sql = "INSERT INTO $table SET
3069
                        group_id = $parent_group_id,
3070
                        subgroup_id = $group_id,
3071
                        relation_type = $relation_type";
3072
            } else {
3073
                $sql = "UPDATE $table SET
3074
                        group_id = $parent_group_id,
3075
                        relation_type = $relation_type
3076
                        WHERE subgroup_id = $group_id";
3077
            }
3078
        }
3079
        $res = Database::query($sql);
3080
3081
        return $res;
3082
    }
3083
3084
    /**
3085
     * Filter the groups/classes info to get a name list only.
3086
     *
3087
     * @param int $userId       The user ID
3088
     * @param int $filterByType Optional. The type of group
3089
     *
3090
     * @return array
3091
     */
3092
    public function getNameListByUser($userId, $filterByType = null)
3093
    {
3094
        $userClasses = $this->getUserGroupListByUser($userId, $filterByType);
3095
3096
        return array_column($userClasses, 'title');
3097
    }
3098
3099
    /**
3100
     * Get the HTML necessary for display the groups/classes name list.
3101
     *
3102
     * @param int $userId       The user ID
3103
     * @param int $filterByType Optional. The type of group
3104
     *
3105
     * @return string
3106
     */
3107
    public function getLabelsFromNameList($userId, $filterByType = null)
3108
    {
3109
        $groupsNameListParsed = $this->getNameListByUser($userId, $filterByType);
3110
3111
        if (empty($groupsNameListParsed)) {
3112
            return '';
3113
        }
3114
3115
        $nameList = '<ul class="list-unstyled">';
3116
        foreach ($groupsNameListParsed as $name) {
3117
            $nameList .= '<li>'.Display::span($name, ['class' => 'label label-info']).'</li>';
3118
        }
3119
3120
        $nameList .= '</ul>';
3121
3122
        return $nameList;
3123
    }
3124
3125
    /**
3126
     * @param array $groupInfo
3127
     *
3128
     * @return bool
3129
     */
3130
    public static function canLeave($groupInfo)
3131
    {
3132
        return 1 == $groupInfo['allow_members_leave_group'] ? true : false;
3133
    }
3134
3135
    /**
3136
     * Check permissions and blocks the page.
3137
     *
3138
     * @param array $userGroupInfo
3139
     * @param bool  $checkAuthor
3140
     * @param bool  $checkCourseIsAllow
3141
     */
3142
    public function protectScript($userGroupInfo = [], $checkAuthor = true, $checkCourseIsAllow = false)
3143
    {
3144
        api_block_anonymous_users();
3145
3146
        if (api_is_platform_admin()) {
3147
            return true;
3148
        }
3149
3150
        if ($checkCourseIsAllow) {
3151
            if (api_is_allowed_to_edit()) {
3152
                return true;
3153
            }
3154
        }
3155
3156
        if ($this->allowTeachers() && api_is_teacher()) {
3157
            if ($checkAuthor && !empty($userGroupInfo)) {
3158
                if (isset($userGroupInfo['author_id']) && $userGroupInfo['author_id'] != api_get_user_id()) {
3159
                    api_not_allowed(true);
3160
                }
3161
            }
3162
3163
            return true;
3164
        } else {
3165
            api_protect_admin_script(true);
3166
            api_protect_limit_for_session_admin();
3167
        }
3168
    }
3169
3170
    public function getGroupsByLp($lpId, $courseId, $sessionId)
3171
    {
3172
        $lpId = (int) $lpId;
3173
        $courseId = (int) $courseId;
3174
        $sessionId = (int) $sessionId;
3175
        $sessionCondition = api_get_session_condition($sessionId, true);
3176
        $table = Database::get_course_table(TABLE_LP_REL_USERGROUP);
3177
        $sql = "SELECT usergroup_id FROM $table
3178
                WHERE
3179
                    c_id = $courseId AND
3180
                    lp_id = $lpId
3181
                    $sessionCondition
3182
                    ";
3183
        $result = Database::query($sql);
3184
3185
        return Database::store_result($result, 'ASSOC');
3186
    }
3187
3188
    public function getGroupsByLpCategory($categoryId, $courseId, $sessionId)
3189
    {
3190
        $categoryId = (int) $categoryId;
3191
        $courseId = (int) $courseId;
3192
        $sessionId = (int) $sessionId;
3193
        $sessionCondition = api_get_session_condition($sessionId, true);
3194
3195
        $table = Database::get_course_table(TABLE_LP_CATEGORY_REL_USERGROUP);
3196
        $sql = "SELECT usergroup_id FROM $table
3197
                WHERE
3198
                    c_id = $courseId AND
3199
                    lp_category_id = $categoryId
3200
                    $sessionCondition
3201
                ";
3202
        $result = Database::query($sql);
3203
3204
        return Database::store_result($result, 'ASSOC');
3205
    }
3206
3207
    public static function getRoleName($relation)
3208
    {
3209
        switch ((int) $relation) {
3210
            case GROUP_USER_PERMISSION_ADMIN:
3211
                return get_lang('Admin');
3212
            case GROUP_USER_PERMISSION_READER:
3213
                return get_lang('Reader');
3214
            case GROUP_USER_PERMISSION_PENDING_INVITATION:
3215
                return get_lang('Pending invitation');
3216
            case GROUP_USER_PERMISSION_MODERATOR:
3217
                return get_lang('Moderator');
3218
            case GROUP_USER_PERMISSION_HRM:
3219
                return get_lang('Human Resources Manager');
3220
            default:
3221
                return get_lang('Custom or undefined role');
3222
        }
3223
    }
3224
}
3225