Passed
Push — master ( f490bd...2431f4 )
by
unknown
22:59 queued 11:23
created

UserGroupModel::allowTeachers()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
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 = $new_items = [];
1138
        if (!empty($list)) {
1139
            foreach ($list as $id) {
1140
                if (!in_array($id, $current_list)) {
1141
                    $new_items[] = $id;
1142
                }
1143
            }
1144
        }
1145
1146
        if (!empty($current_list)) {
1147
            foreach ($current_list as $id) {
1148
                if (!in_array($id, $list)) {
1149
                    $delete_items[] = $id;
1150
                }
1151
            }
1152
        }
1153
1154
        if ($delete_groups) {
1155
            $this->unsubscribe_courses_from_usergroup($usergroup_id, $delete_items);
1156
        }
1157
1158
        // Adding new relationships
1159
        if (!empty($new_items)) {
1160
            foreach ($new_items as $course_id) {
1161
                $course_info = api_get_course_info_by_id($course_id);
1162
                if ($course_info) {
1163
                    if (!empty($user_list)) {
1164
                        foreach ($user_list as $user_id) {
1165
                            CourseManager::subscribeUser(
1166
                                $user_id,
1167
                                $course_id
1168
                            );
1169
                        }
1170
                    }
1171
                    $params = [
1172
                        'course_id' => $course_id,
1173
                        'usergroup_id' => $usergroup_id,
1174
                    ];
1175
                    Database::insert(
1176
                        $this->usergroup_rel_course_table,
1177
                        $params
1178
                    );
1179
                }
1180
            }
1181
        }
1182
    }
1183
1184
    /**
1185
     * @param int   $usergroup_id
1186
     * @param array $delete_items
1187
     */
1188
    public function unsubscribe_courses_from_usergroup($usergroup_id, $delete_items, $sessionId = 0)
1189
    {
1190
        $sessionId = (int) $sessionId;
1191
        // Deleting items.
1192
        if (!empty($delete_items)) {
1193
            $user_list = $this->get_users_by_usergroup($usergroup_id);
1194
1195
            $groupId = isset($_GET['id']) ? (int) $_GET['id'] : 0;
1196
            foreach ($delete_items as $course_id) {
1197
                $course_info = api_get_course_info_by_id($course_id);
1198
                if ($course_info) {
1199
                    if (!empty($user_list)) {
1200
                        foreach ($user_list as $user_id) {
1201
                            CourseManager::unsubscribe_user(
1202
                                $user_id,
1203
                                $course_info['code'],
1204
                                $sessionId
1205
                            );
1206
                        }
1207
                    }
1208
1209
                    Database::delete(
1210
                        $this->usergroup_rel_course_table,
1211
                        [
1212
                            'usergroup_id = ? AND course_id = ?' => [
1213
                                $usergroup_id,
1214
                                $course_id,
1215
                            ],
1216
                        ]
1217
                    );
1218
                }
1219
                if (0 != $sessionId && 0 != $groupId) {
1220
                    $this->subscribe_sessions_to_usergroup($groupId, [0]);
1221
                } else {
1222
                    $s = $sessionId;
1223
                }
1224
            }
1225
        }
1226
    }
1227
1228
    /**
1229
     * Subscribe users to a group.
1230
     *
1231
     * @param int   $usergroup_id                     usergroup id
1232
     * @param array $list                             list of user ids
1233
     * @param bool  $delete_users_not_present_in_list
1234
     * @param int   $relationType
1235
     */
1236
    public function subscribe_users_to_usergroup(
1237
        $usergroup_id,
1238
        $list,
1239
        $delete_users_not_present_in_list = true,
1240
        $relationType = 0
1241
    ) {
1242
        // Normalize relation type
1243
        $relationType = (int) $relationType;
1244
1245
        // Detect group type to keep legacy behaviour for classic classes
1246
        $groupInfo = $this->get($usergroup_id);
1247
        $isSocialGroup = isset($groupInfo['group_type']) && (int) $groupInfo['group_type'] === Usergroup::SOCIAL_CLASS;
1248
        $isClassGroup  = isset($groupInfo['group_type']) && (int) $groupInfo['group_type'] === Usergroup::NORMAL_CLASS;
1249
1250
        if ($isSocialGroup) {
1251
            $current_list = $this->getUsersByUsergroupAndRelation($usergroup_id, $relationType);
1252
        } else {
1253
            $current_list = $this->get_users_by_usergroup($usergroup_id);
1254
        }
1255
1256
        $course_list  = $this->get_courses_by_usergroup($usergroup_id);
1257
        $session_list = $this->get_sessions_by_usergroup($usergroup_id);
1258
        $session_list = array_filter($session_list);
1259
1260
        $delete_items = [];
1261
        $new_items    = [];
1262
1263
        // Compute new users to add
1264
        if (!empty($list)) {
1265
            foreach ($list as $user_id) {
1266
                if (!in_array($user_id, $current_list)) {
1267
                    $new_items[] = $user_id;
1268
                }
1269
            }
1270
        }
1271
1272
        // Compute users to delete (present before, not present now)
1273
        if (!empty($current_list)) {
1274
            foreach ($current_list as $user_id) {
1275
                if (!in_array($user_id, $list)) {
1276
                    $delete_items[] = $user_id;
1277
                }
1278
            }
1279
        }
1280
1281
        // Deleting items
1282
        if (!empty($delete_items) && $delete_users_not_present_in_list) {
1283
            foreach ($delete_items as $user_id) {
1284
                // Remove course subscriptions
1285
                if (!empty($course_list)) {
1286
                    foreach ($course_list as $course_id) {
1287
                        $course_info = api_get_course_info_by_id($course_id);
1288
                        CourseManager::unsubscribe_user($user_id, $course_info['code']);
1289
                    }
1290
                }
1291
1292
                // Remove session subscriptions
1293
                if (!empty($session_list)) {
1294
                    foreach ($session_list as $session_id) {
1295
                        SessionManager::unsubscribe_user_from_session($session_id, $user_id);
1296
                    }
1297
                }
1298
1299
                // Remove from usergroup_rel_user:
1300
                // - Social groups: delete exactly this role (even if it is 0 = reader).
1301
                // - Normal classes: keep legacy default behaviour.
1302
                if ($isSocialGroup) {
1303
                    // Strict per-role deletion, with reader-role legacy tolerance
1304
                    if ($relationType === 0) {
1305
                        // Default reader role: treat legacy 2 as equivalent
1306
                        Database::delete(
1307
                            $this->usergroup_rel_user_table,
1308
                            [
1309
                                'usergroup_id = ? AND user_id = ? AND (relation_type = "0" OR relation_type = "2" OR relation_type IS NULL OR relation_type = "")' => [
1310
                                    $usergroup_id,
1311
                                    $user_id,
1312
                                ],
1313
                            ]
1314
                        );
1315
                    } else {
1316
                        // Other roles: delete only this specific role
1317
                        Database::delete(
1318
                            $this->usergroup_rel_user_table,
1319
                            [
1320
                                'usergroup_id = ? AND user_id = ? AND relation_type = ?' => [
1321
                                    $usergroup_id,
1322
                                    $user_id,
1323
                                    $relationType,
1324
                                ],
1325
                            ]
1326
                        );
1327
                    }
1328
                } else {
1329
                    // Legacy: default/empty relation_type
1330
                    Database::delete(
1331
                        $this->usergroup_rel_user_table,
1332
                        [
1333
                            'usergroup_id = ? AND (relation_type = "0" OR relation_type = "2" OR relation_type IS NULL OR relation_type = "")' => [
1334
                                $usergroup_id,
1335
                                $user_id,
1336
                            ],
1337
                        ]
1338
                    );
1339
                }
1340
            }
1341
        }
1342
1343
        // Adding new relationships
1344
        if (!empty($new_items)) {
1345
            // Add sessions
1346
            if (!empty($session_list)) {
1347
                foreach ($session_list as $session_id) {
1348
                    SessionManager::subscribeUsersToSession($session_id, $new_items, null, false);
1349
                }
1350
            }
1351
1352
            foreach ($new_items as $user_id) {
1353
                // Add courses
1354
                if (!empty($course_list)) {
1355
                    foreach ($course_list as $course_id) {
1356
                        CourseManager::subscribeUser($user_id, $course_id);
1357
                    }
1358
                }
1359
1360
                // Persist relation in usergroup_rel_user
1361
                $params = [
1362
                    'user_id'      => $user_id,
1363
                    'usergroup_id' => $usergroup_id,
1364
                    'relation_type'=> $relationType,
1365
                ];
1366
1367
                Database::insert($this->usergroup_rel_user_table, $params);
1368
            }
1369
        }
1370
    }
1371
1372
    /**
1373
     * @deprecated Use UsergroupRepository::getByTitleInUrl().
1374
     *
1375
     * @param string $title
1376
     *
1377
     * @return bool
1378
     * @throws Exception
1379
     */
1380
    public function usergroup_exists(string $title): bool
1381
    {
1382
        $title = Database::escape_string($title);
1383
        if ($this->getUseMultipleUrl()) {
1384
            $urlId = api_get_current_access_url_id();
1385
            $sql = "SELECT * FROM $this->table u
1386
                    INNER JOIN {$this->access_url_rel_usergroup} a
1387
                    ON (a.usergroup_id = u.id)
1388
                    WHERE title = '".$title."' AND access_url_id = $urlId";
1389
        } else {
1390
            $sql = "SELECT * FROM $this->table WHERE title = '".$title."'";
1391
        }
1392
1393
        $res = Database::query($sql);
1394
1395
        return 0 != Database::num_rows($res);
1396
    }
1397
1398
    /**
1399
     * @return bool
1400
     */
1401
    public function allowTeachers()
1402
    {
1403
        return 'true' === api_get_setting('profile.allow_teachers_to_classes');
1404
    }
1405
1406
    /**
1407
     * @param int    $sidx
1408
     * @param int    $sord
1409
     * @param int    $start
1410
     * @param int    $limit
1411
     * @param string $extraWhereCondition
1412
     *
1413
     * @return array
1414
     */
1415
    public function getUsergroupsPagination($sidx, $sord, $start, $limit, $extraWhereCondition = '')
1416
    {
1417
        $sord = in_array(strtolower($sord), ['asc', 'desc']) ? $sord : 'desc';
1418
1419
        $start = (int) $start;
1420
        $limit = (int) $limit;
1421
1422
        $sqlFrom = "{$this->table} u ";
1423
        $sqlWhere = '1 = 1 ';
1424
1425
        if ($this->getUseMultipleUrl()) {
1426
            $urlId = api_get_current_access_url_id();
1427
            $sqlFrom .= " INNER JOIN {$this->access_url_rel_usergroup} a ON (u.id = a.usergroup_id) ";
1428
            $sqlWhere .= " AND a.access_url_id = $urlId ";
1429
        }
1430
1431
        if ($this->allowTeachers()) {
1432
            if (!api_is_platform_admin()) {
1433
                $userId = api_get_user_id();
1434
                $sqlWhere .= " AND author_id = $userId ";
1435
            }
1436
        }
1437
1438
        if ($extraWhereCondition) {
1439
            $sqlWhere .= " AND $extraWhereCondition ";
1440
        }
1441
1442
        $result = Database::store_result(
1443
            Database::query("SELECT DISTINCT u.* FROM $sqlFrom WHERE $sqlWhere ORDER BY title $sord LIMIT $start, $limit")
1444
        );
1445
1446
        $new_result = [];
1447
        if (!empty($result)) {
1448
            foreach ($result as $group) {
1449
                $group['sessions'] = count($this->get_sessions_by_usergroup($group['id']));
1450
                $group['courses'] = count($this->get_courses_by_usergroup($group['id']));
1451
                $roles = [];
1452
                switch ($group['group_type']) {
1453
                    case 0:
1454
                        $group['group_type'] = Display::label(get_lang('Class'), 'info');
1455
                        $roles = [0];
1456
                        break;
1457
                    case 1:
1458
                        $group['group_type'] = Display::label(get_lang('Social'), 'success');
1459
                        $roles = [
1460
                            GROUP_USER_PERMISSION_ADMIN,
1461
                            GROUP_USER_PERMISSION_READER,
1462
                            GROUP_USER_PERMISSION_MODERATOR,
1463
                            GROUP_USER_PERMISSION_HRM,
1464
                        ];
1465
                        break;
1466
                }
1467
                $group['users'] = Display::url(
1468
                    count($this->get_users_by_usergroup($group['id'], $roles)),
1469
                    api_get_path(WEB_CODE_PATH).'admin/usergroup_users.php?id='.$group['id']
1470
                );
1471
                $new_result[] = $group;
1472
            }
1473
            $result = $new_result;
1474
        }
1475
        $columns = ['title', 'users', 'courses', 'sessions', 'group_type'];
1476
1477
        if (!in_array($sidx, $columns)) {
1478
            $sidx = 'title';
1479
        }
1480
1481
        // Multidimensional sort
1482
        $result = msort($result, $sidx, $sord);
1483
1484
        return $result;
1485
    }
1486
1487
    /**
1488
     * @param array $options
1489
     *
1490
     * @return array
1491
     */
1492
    public function getDataToExport($options = [])
1493
    {
1494
        if ($this->getUseMultipleUrl()) {
1495
            $urlId = api_get_current_access_url_id();
1496
            $from = $this->table." u
1497
                    INNER JOIN {$this->access_url_rel_usergroup} a
1498
                    ON (u.id = a.usergroup_id)";
1499
            $options = ['where' => ['access_url_id = ? ' => $urlId]];
1500
            if ($this->allowTeachers()) {
1501
                $options['where'] = [' author_id = ? ' => api_get_user_id()];
1502
            }
1503
            $classes = Database::select('a.id, title, description', $from, $options);
1504
        } else {
1505
            if ($this->allowTeachers()) {
1506
                $options['where'] = [' author_id = ? ' => api_get_user_id()];
1507
            }
1508
            $classes = Database::select('id, title, description', $this->table, $options);
1509
        }
1510
1511
        $result = [];
1512
        if (!empty($classes)) {
1513
            foreach ($classes as $data) {
1514
                $users = $this->getUserListByUserGroup($data['id']);
1515
                $userToString = null;
1516
                if (!empty($users)) {
1517
                    $userNameList = [];
1518
                    foreach ($users as $userData) {
1519
                        $userNameList[] = $userData['username'];
1520
                    }
1521
                    $userToString = implode(',', $userNameList);
1522
                }
1523
                $data['users'] = $userToString;
1524
                $result[] = $data;
1525
            }
1526
        }
1527
1528
        return $result;
1529
    }
1530
1531
    /**
1532
     * @param string $firstLetter
1533
     * @param int    $limit
1534
     *
1535
     * @return array
1536
     */
1537
    public function filterByFirstLetter($firstLetter, $limit = 0)
1538
    {
1539
        $firstLetter = Database::escape_string($firstLetter);
1540
        $limit = (int) $limit;
1541
1542
        $sql = ' SELECT g.id, title ';
1543
1544
        $urlCondition = '';
1545
        if ($this->getUseMultipleUrl()) {
1546
            $urlId = api_get_current_access_url_id();
1547
            $sql .= " FROM $this->table g
1548
                    INNER JOIN $this->access_url_rel_usergroup a
1549
                    ON (g.id = a.usergroup_id) ";
1550
            $urlCondition = " AND access_url_id = $urlId ";
1551
        } else {
1552
            $sql = " FROM $this->table g ";
1553
        }
1554
        $sql .= "
1555
		        WHERE
1556
		            title LIKE '".$firstLetter."%' OR
1557
		            title LIKE '".api_strtolower($firstLetter)."%'
1558
		            $urlCondition
1559
		        ORDER BY title DESC ";
1560
1561
        if (!empty($limit)) {
1562
            $sql .= " LIMIT $limit ";
1563
        }
1564
1565
        $result = Database::query($sql);
1566
1567
        return Database::store_result($result);
1568
    }
1569
1570
    /**
1571
     * Select user group not in list.
1572
     */
1573
    public function getUserGroupNotInList(array $list, int $accessUrlId): array
1574
    {
1575
        $params = [];
1576
1577
        $sql = "SELECT g.*
1578
            FROM {$this->table} g";
1579
1580
        if ($this->getUseMultipleUrl()) {
1581
            $sql .= " LEFT JOIN {$this->access_url_rel_usergroup} a
1582
                  ON (g.id = a.usergroup_id AND a.access_url_id = ?)";
1583
            $params[] = $accessUrlId;
1584
            $sql .= " WHERE a.usergroup_id IS NULL";
1585
        } else {
1586
            $sql .= " WHERE 1=1";
1587
        }
1588
1589
        if (!empty($list)) {
1590
            $placeholders = implode(',', array_fill(0, count($list), '?'));
1591
            $sql .= " AND g.id NOT IN ($placeholders)";
1592
            $params = array_merge($params, array_map('intval', $list));
1593
        }
1594
1595
        $sql .= " ORDER BY g.title";
1596
1597
        $stmt = Database::getManager()->getConnection()->executeQuery($sql, $params);
1598
1599
        return Database::store_result($stmt, 'ASSOC');
1600
    }
1601
1602
    /**
1603
     * @param $params
1604
     * @param bool $showQuery
1605
     *
1606
     * @return bool|int
1607
     */
1608
    public function save($params, $showQuery = false)
1609
    {
1610
        $params['updated_at'] = $params['created_at'] = api_get_utc_datetime();
1611
        $params['group_type'] = isset($params['group_type']) ? Usergroup::SOCIAL_CLASS : Usergroup::NORMAL_CLASS;
1612
        $params['allow_members_leave_group'] = isset($params['allow_members_leave_group']) ? 1 : 0;
1613
        $params['url'] = $params['url'] ?? "";
1614
        $params['visibility'] = $params['visibility'] ?? Usergroup::GROUP_PERMISSION_OPEN;
1615
1616
        $userGroupExists = $this->usergroup_exists(trim($params['title']));
1617
        if (false === $userGroupExists) {
1618
            $userGroup = new Usergroup();
1619
            $repo = Container::getUsergroupRepository();
1620
            $userGroup
1621
                ->setTitle(trim($params['title']))
1622
                ->setDescription($params['description'])
1623
                ->setUrl($params['url'])
1624
                ->setVisibility($params['visibility'])
1625
                ->setGroupType($params['group_type'])
1626
                ->setAllowMembersToLeaveGroup($params['allow_members_leave_group'])
1627
            ;
1628
            if ($this->allowTeachers()) {
1629
                $userGroup->setAuthorId(api_get_user_id());
1630
            }
1631
1632
            $repo->create($userGroup);
1633
1634
            $id = $userGroup->getId();
1635
            if ($id) {
1636
                if ($this->getUseMultipleUrl()) {
1637
                    $this->subscribeToUrl($id, api_get_current_access_url_id());
1638
                }
1639
1640
                if (Usergroup::SOCIAL_CLASS == $params['group_type']) {
1641
                    $this->add_user_to_group(
1642
                        api_get_user_id(),
1643
                        $id,
1644
                        $params['group_type']
1645
                    );
1646
                }
1647
                $request = Container::getRequest();
1648
                $file = $request->files->get('picture');
1649
                if (null !== $file) {
1650
                    $this->manageFileUpload($userGroup, $file);
1651
                }
1652
            }
1653
1654
            return $id;
1655
        }
1656
1657
        return false;
1658
    }
1659
1660
    public function update($params, $showQuery = false): bool
1661
    {
1662
        $em = Database::getManager();
1663
        $repo = Container::getUsergroupRepository();
1664
        /** @var Usergroup $userGroup */
1665
        $userGroup = $repo->find($params['id']);
1666
        if (null === $userGroup) {
1667
            return false;
1668
        }
1669
1670
        if (isset($params['title'])) {
1671
            $userGroup->setTitle($params['title']);
1672
        }
1673
1674
        if (isset($params['description'])) {
1675
            $userGroup->setDescription($params['description']);
1676
        }
1677
1678
        if (isset($params['visibility'])) {
1679
            $userGroup->setVisibility($params['visibility']);
1680
        }
1681
1682
        if (isset($params['url'])) {
1683
            $userGroup->setUrl($params['url']);
1684
        }
1685
1686
        $userGroup
1687
            ->setGroupType(isset($params['group_type']) ? Usergroup::SOCIAL_CLASS : Usergroup::NORMAL_CLASS)
1688
            ->setAllowMembersToLeaveGroup(isset($params['allow_members_leave_group']) ? 1 : 0)
1689
        ;
1690
        $cropImage = $params['picture_crop_result'] ?? null;
1691
        $picture = $_FILES['picture'] ?? null;
1692
        if (!empty($picture)) {
1693
            $request = Container::getRequest();
1694
            $file = $request->files->get('picture');
1695
            if (null !== $file) {
1696
                $this->manageFileUpload($userGroup, $file, $cropImage);
1697
            }
1698
        }
1699
1700
        $em->persist($userGroup);
1701
        $em->flush();
1702
1703
        if (isset($params['delete_picture'])) {
1704
            $this->delete_group_picture($params['id']);
1705
        }
1706
1707
        return true;
1708
    }
1709
1710
    public function manageFileUpload(
1711
        Usergroup $userGroup,
1712
        UploadedFile $picture,
1713
        string $cropParameters = ''
1714
    ): ?ResourceFile {
1715
        $illustrationRepo = Container::getIllustrationRepository();
1716
1717
        return $illustrationRepo->addIllustration($userGroup, api_get_user_entity(), $picture, $cropParameters);
1718
    }
1719
1720
    /**
1721
     * @param int $groupId
1722
     *
1723
     * @return string
1724
     */
1725
    public function delete_group_picture($groupId)
1726
    {
1727
        $repo = Container::getUsergroupRepository();
1728
        $userGroup = $repo->find($groupId);
1729
        if ($userGroup) {
1730
            $illustrationRepo = Container::getIllustrationRepository();
1731
            $illustrationRepo->deleteIllustration($userGroup);
1732
        }
1733
    }
1734
1735
    /**
1736
     * @return mixed
1737
     */
1738
    public function getGroupType()
1739
    {
1740
        return $this->groupType;
1741
    }
1742
1743
    /**
1744
     * @param int $id
1745
     *
1746
     * @return bool|void
1747
     */
1748
    public function delete($id)
1749
    {
1750
        $id = (int) $id;
1751
        if ($this->getUseMultipleUrl()) {
1752
            $this->unsubscribeToUrl($id, api_get_current_access_url_id());
1753
        }
1754
1755
        $sql = "DELETE FROM $this->usergroup_rel_user_table
1756
                WHERE usergroup_id = $id";
1757
        Database::query($sql);
1758
1759
        $sql = "DELETE FROM $this->usergroup_rel_course_table
1760
                WHERE usergroup_id = $id";
1761
        Database::query($sql);
1762
1763
        $sql = "DELETE FROM $this->usergroup_rel_session_table
1764
                WHERE usergroup_id = $id";
1765
        Database::query($sql);
1766
1767
        $repo = Container::getUsergroupRepository();
1768
        $userGroup = $repo->find($id);
1769
        $repo->delete($userGroup);
1770
    }
1771
1772
    /**
1773
     * @param int $id
1774
     * @param int $urlId
1775
     */
1776
    public function subscribeToUrl($id, $urlId)
1777
    {
1778
        Database::insert(
1779
            $this->access_url_rel_usergroup,
1780
            [
1781
                'access_url_id' => $urlId,
1782
                'usergroup_id' => $id,
1783
            ]
1784
        );
1785
    }
1786
1787
    /**
1788
     * @param int $id
1789
     * @param int $urlId
1790
     */
1791
    public function unsubscribeToUrl($id, $urlId)
1792
    {
1793
        Database::delete(
1794
            $this->access_url_rel_usergroup,
1795
            [
1796
                'access_url_id = ? AND usergroup_id = ? ' => [$urlId, $id],
1797
            ]
1798
        );
1799
    }
1800
1801
    /**
1802
     * @param $needle
1803
     *
1804
     * @return xajaxResponse
1805
     */
1806
    public static function searchUserGroupAjax($needle)
1807
    {
1808
        $response = new xajaxResponse();
1809
        $return = '';
1810
1811
        if (!empty($needle)) {
1812
            // xajax send utf8 datas... datas in db can be non-utf8 datas
1813
            $charset = api_get_system_encoding();
1814
            $needle = api_convert_encoding($needle, $charset, 'utf-8');
1815
            $needle = Database::escape_string($needle);
1816
1817
            $sql = 'SELECT id, title
1818
                    FROM '.Database::get_main_table(TABLE_USERGROUP).' u
1819
                    WHERE title LIKE "'.$needle.'%"
1820
                    ORDER BY title
1821
                    LIMIT 11';
1822
            $result = Database::query($sql);
1823
            $i = 0;
1824
            while ($data = Database::fetch_array($result)) {
1825
                $i++;
1826
                if ($i <= 10) {
1827
                    $return .= '<a
1828
                    href="javascript: void(0);"
1829
                    onclick="javascript: add_user_to_url(\''.addslashes($data['id']).'\',\''.addslashes($data['title']).' \')">'.$data['title'].' </a><br />';
1830
                } else {
1831
                    $return .= '...<br />';
1832
                }
1833
            }
1834
        }
1835
        $response->addAssign('ajax_list_courses', 'innerHTML', api_utf8_encode($return));
1836
1837
        return $response;
1838
    }
1839
1840
    /**
1841
     * Get user list by usergroup.
1842
     *
1843
     * @param int    $id
1844
     * @param string $orderBy
1845
     *
1846
     * @return array
1847
     */
1848
    public function getUserListByUserGroup($id, $orderBy = '')
1849
    {
1850
        $id = (int) $id;
1851
        $sql = "SELECT u.* FROM $this->table_user u
1852
                INNER JOIN $this->usergroup_rel_user_table c
1853
                ON c.user_id = u.id
1854
                WHERE u.active <> ".USER_SOFT_DELETED." AND c.usergroup_id = $id"
1855
        ;
1856
        if (!empty($orderBy)) {
1857
            $orderBy = Database::escape_string($orderBy);
1858
            $sql .= " ORDER BY $orderBy ";
1859
        }
1860
        $result = Database::query($sql);
1861
1862
        return Database::store_result($result);
1863
    }
1864
1865
    /**
1866
     * @param FormValidator $form
1867
     * @param string        $type
1868
     */
1869
    public function setForm($form, $type = 'add', Usergroup $userGroup = null)
1870
    {
1871
        $header = '';
1872
        switch ($type) {
1873
            case 'add':
1874
                $header = get_lang('Add');
1875
                break;
1876
            case 'edit':
1877
                $header = get_lang('Edit');
1878
                break;
1879
        }
1880
1881
        $form->addHeader($header);
1882
1883
        // Name
1884
        $form->addText('title', get_lang('Title'), true, ['maxlength' => 255]);
1885
        $form->addRule('title', '', 'maxlength', 255);
1886
1887
        // Description
1888
        $form->addHtmlEditor(
1889
            'description',
1890
            get_lang('Description'),
1891
            true,
1892
            false,
1893
            [
1894
                'ToolbarSet' => 'Minimal',
1895
            ]
1896
        );
1897
        $form->applyFilter('description', 'trim');
1898
1899
        if ($this->showGroupTypeSetting) {
1900
            $form->addElement(
1901
                'checkbox',
1902
                'group_type',
1903
                null,
1904
                get_lang('Social group')
1905
            );
1906
        }
1907
1908
        // url
1909
        $form->addText('url', get_lang('URL'), false);
1910
1911
        // Picture
1912
        //$allowed_picture_types = $this->getAllowedPictureExtensions();
1913
1914
        // Picture
1915
        $form->addFile(
1916
            'picture',
1917
            get_lang('Add a picture'),
1918
            ['id' => 'picture', 'class' => 'picture-form', 'crop_image' => true, 'crop_ratio' => '1 / 1']
1919
        );
1920
1921
        $repo = Container::getIllustrationRepository();
1922
        if ($userGroup && $repo->hasIllustration($userGroup)) {
1923
            $picture = $repo->getIllustrationUrl($userGroup);
1924
            $img = '<img src="'.$picture.'" />';
1925
            $form->addLabel(null, $img);
1926
            $form->addElement('checkbox', 'delete_picture', '', get_lang('Remove picture'));
1927
        }
1928
1929
        $form->addSelect('visibility', get_lang('Group Permissions'), $this->getGroupStatusList());
1930
        $form->setRequiredNote('<span class="form_required">*</span> <small>'.get_lang('Required field').'</small>');
1931
        $form->addElement('checkbox', 'allow_members_leave_group', '', get_lang('Allow members to leave group'));
1932
1933
        // Setting the form elements
1934
        if ('add' === $type) {
1935
            $form->addButtonCreate($header);
1936
        } else {
1937
            $form->addButtonUpdate($header);
1938
        }
1939
    }
1940
1941
    /**
1942
     * Gets the current group image.
1943
     *
1944
     * @param string $id group id
1945
     * @param string picture group name
1946
     * @param string height
1947
     * @param int $size_picture picture size it can be small_,  medium_  or  big_
1948
     * @param string style css
1949
     *
1950
     * @return string
1951
     */
1952
    public function get_picture_group(
1953
        $id,
1954
        $picture_file,
1955
        $height,
1956
        $size_picture = GROUP_IMAGE_SIZE_MEDIUM,
1957
        $style = ''
1958
    ) {
1959
        $repoIllustration = Container::getIllustrationRepository();
1960
        $repoUserGroup = Container::getUsergroupRepository();
1961
        $userGroup = $repoUserGroup->find($id);
1962
1963
        return $repoIllustration->getIllustrationUrl($userGroup);
1964
1965
        /*
1966
        $picture = [];
1967
        //$picture['style'] = $style;
1968
        if ('unknown.jpg' === $picture_file) {
1969
            $picture['file'] = Display::returnIconPath($picture_file);
1970
1971
            return $picture;
1972
        }
1973
1974
        switch ($size_picture) {
1975
            case GROUP_IMAGE_SIZE_ORIGINAL:
1976
                $size_picture = '';
1977
                break;
1978
            case GROUP_IMAGE_SIZE_BIG:
1979
                $size_picture = 'big_';
1980
                break;
1981
            case GROUP_IMAGE_SIZE_MEDIUM:
1982
                $size_picture = 'medium_';
1983
                break;
1984
            case GROUP_IMAGE_SIZE_SMALL:
1985
                $size_picture = 'small_';
1986
                break;
1987
            default:
1988
                $size_picture = 'medium_';
1989
        }
1990
1991
        $image_array_sys = $this->get_group_picture_path_by_id($id, 'system', false, true);
1992
        $image_array = $this->get_group_picture_path_by_id($id, 'web', false, true);
1993
        $file = $image_array_sys['dir'].$size_picture.$picture_file;
1994
        if (file_exists($file)) {
1995
            $picture['file'] = $image_array['dir'].$size_picture.$picture_file;
1996
            //$picture['style'] = '';
1997
            if ($height > 0) {
1998
                $dimension = api_getimagesize($picture['file']);
1999
                $margin = ($height - $dimension['width']) / 2;
2000
                //@ todo the padding-top should not be here
2001
            }
2002
        } else {
2003
            $file = $image_array_sys['dir'].$picture_file;
2004
            if (file_exists($file) && !is_dir($file)) {
2005
                $picture['file'] = $image_array['dir'].$picture_file;
2006
            } else {
2007
                $picture['file'] = Display::returnIconPath('group_na.png', 64);
2008
            }
2009
        }
2010
2011
        return $picture;*/
2012
    }
2013
2014
    /**
2015
     * @return array
2016
     */
2017
    public function getAllowedPictureExtensions()
2018
    {
2019
        return ['jpg', 'jpeg', 'png', 'gif'];
2020
    }
2021
2022
    public function getGroupStatusList(): array
2023
    {
2024
        return [
2025
            GROUP_PERMISSION_OPEN => get_lang('Open'),
2026
            GROUP_PERMISSION_CLOSED => get_lang('Closed'),
2027
        ];
2028
    }
2029
2030
    /**
2031
     * @param int $type
2032
     */
2033
    public function setGroupType($type)
2034
    {
2035
        $this->groupType = (int) $type;
2036
    }
2037
2038
    /**
2039
     * @param int $group_id
2040
     * @param int $user_id
2041
     *
2042
     * @return bool
2043
     */
2044
    public function is_group_admin($group_id, $user_id = 0)
2045
    {
2046
        if (empty($user_id)) {
2047
            $user_id = api_get_user_id();
2048
        }
2049
        $user_role = $this->get_user_group_role($user_id, $group_id);
2050
        if (in_array($user_role, [GROUP_USER_PERMISSION_ADMIN])) {
2051
            return true;
2052
        }
2053
2054
        return false;
2055
    }
2056
2057
    /**
2058
     * @param int $group_id
2059
     * @param int $user_id
2060
     *
2061
     * @return bool
2062
     */
2063
    public function isGroupModerator($group_id, $user_id = 0)
2064
    {
2065
        if (empty($user_id)) {
2066
            $user_id = api_get_user_id();
2067
        }
2068
        $user_role = $this->get_user_group_role($user_id, $group_id);
2069
        if (in_array($user_role, [GROUP_USER_PERMISSION_ADMIN, GROUP_USER_PERMISSION_MODERATOR])) {
2070
            return true;
2071
        } else {
2072
            return false;
2073
        }
2074
    }
2075
2076
    /**
2077
     * @param int $group_id
2078
     * @param int $user_id
2079
     *
2080
     * @return bool
2081
     */
2082
    public function is_group_member($group_id, $user_id = 0)
2083
    {
2084
        if (api_is_platform_admin()) {
2085
            return true;
2086
        }
2087
        if (empty($user_id)) {
2088
            $user_id = api_get_user_id();
2089
        }
2090
        $roles = [
2091
            GROUP_USER_PERMISSION_ADMIN,
2092
            GROUP_USER_PERMISSION_MODERATOR,
2093
            GROUP_USER_PERMISSION_READER,
2094
            GROUP_USER_PERMISSION_HRM,
2095
        ];
2096
        $user_role = $this->get_user_group_role($user_id, $group_id);
2097
        if (in_array($user_role, $roles)) {
2098
            return true;
2099
        } else {
2100
            return false;
2101
        }
2102
    }
2103
2104
    /**
2105
     * Gets the relationship between a group and a User.
2106
     *
2107
     * @author Julio Montoya
2108
     *
2109
     * @param int $user_id
2110
     * @param int $group_id
2111
     *
2112
     * @return int 0 if there is no relationship; otherwise the normalized role
2113
     */
2114
    public function get_user_group_role($user_id, $group_id)
2115
    {
2116
        $table_group_rel_user = $this->usergroup_rel_user_table;
2117
        $return_value = 0;
2118
        $user_id = (int) $user_id;
2119
        $group_id = (int) $group_id;
2120
2121
        if (!empty($user_id) && !empty($group_id)) {
2122
            $sql = "SELECT relation_type
2123
                    FROM $table_group_rel_user
2124
                    WHERE
2125
                        usergroup_id = $group_id AND
2126
                        user_id = $user_id";
2127
            $result = Database::query($sql);
2128
            if (Database::num_rows($result) > 0) {
2129
                $row = Database::fetch_assoc($result);
2130
                $relationType = (int) $row['relation_type'];
2131
2132
                // Normalize legacy reader (2) to the canonical reader role
2133
                if (2 === $relationType) {
2134
                    $relationType = GROUP_USER_PERMISSION_READER;
2135
                }
2136
2137
                $return_value = $relationType;
2138
            }
2139
        }
2140
2141
        return $return_value;
2142
    }
2143
2144
    /**
2145
     * @param int $userId
2146
     * @param int $groupId
2147
     *
2148
     * @return string
2149
     */
2150
    public function getUserRoleToString($userId, $groupId)
2151
    {
2152
        $role = $this->get_user_group_role($userId, $groupId);
2153
        $roleToString = '';
2154
2155
        switch ($role) {
2156
            case GROUP_USER_PERMISSION_ADMIN:
2157
                $roleToString = get_lang('Admin');
2158
                break;
2159
            case GROUP_USER_PERMISSION_READER:
2160
                $roleToString = get_lang('Reader');
2161
                break;
2162
            case GROUP_USER_PERMISSION_PENDING_INVITATION:
2163
                $roleToString = get_lang('Pending invitation');
2164
                break;
2165
            case GROUP_USER_PERMISSION_MODERATOR:
2166
                $roleToString = get_lang('Moderator');
2167
                break;
2168
            case GROUP_USER_PERMISSION_HRM:
2169
                $roleToString = get_lang('Human Resources Manager');
2170
                break;
2171
        }
2172
2173
        return $roleToString;
2174
    }
2175
2176
    /**
2177
     * Add a group of users into a group of URLs.
2178
     *
2179
     * @author Julio Montoya
2180
     *
2181
     * @param array $user_list
2182
     * @param array $group_list
2183
     * @param int   $relation_type
2184
     *
2185
     * @return array
2186
     */
2187
    public function add_users_to_groups($user_list, $group_list, $relation_type = GROUP_USER_PERMISSION_READER)
2188
    {
2189
        $table_url_rel_group = $this->usergroup_rel_user_table;
2190
        $result_array = [];
2191
        $relation_type = (int) $relation_type;
2192
2193
        if (is_array($user_list) && is_array($group_list)) {
2194
            foreach ($group_list as $group_id) {
2195
                foreach ($user_list as $user_id) {
2196
                    $user_id = (int) $user_id;
2197
                    $group_id = (int) $group_id;
2198
2199
                    $role = $this->get_user_group_role($user_id, $group_id);
2200
                    if (0 == $role) {
2201
                        $sql = "INSERT INTO $table_url_rel_group
2202
		               			SET
2203
		               			    user_id = $user_id ,
2204
		               			    usergroup_id = $group_id ,
2205
		               			    relation_type = $relation_type ";
2206
2207
                        $result = Database::query($sql);
2208
                        if ($result) {
2209
                            $result_array[$group_id][$user_id] = 1;
2210
                        } else {
2211
                            $result_array[$group_id][$user_id] = 0;
2212
                        }
2213
                    }
2214
                }
2215
            }
2216
        }
2217
2218
        return $result_array;
2219
    }
2220
2221
    /**
2222
     * Deletes an url and session relationship.
2223
     *
2224
     * @author Julio Montoya
2225
     *
2226
     * @param int $userId
2227
     * @param int $groupId
2228
     *
2229
     * @return bool true if success
2230
     * */
2231
    public function delete_user_rel_group($userId, $groupId)
2232
    {
2233
        $userId = (int) $userId;
2234
        $groupId = (int) $groupId;
2235
        if (empty($userId) || empty($groupId)) {
2236
            return false;
2237
        }
2238
2239
        $table = $this->usergroup_rel_user_table;
2240
        $sql = "DELETE FROM $table
2241
                WHERE
2242
                    user_id = $userId AND
2243
                    usergroup_id = $groupId";
2244
2245
        $result = Database::query($sql);
2246
2247
        return $result;
2248
    }
2249
2250
    /**
2251
     * Add a user into a group.
2252
     *
2253
     * @author Julio Montoya
2254
     *
2255
     * @param int $user_id
2256
     * @param int $group_id
2257
     * @param int $relation_type
2258
     *
2259
     * @return bool true if success
2260
     */
2261
    public function add_user_to_group($user_id, $group_id, $relation_type = GROUP_USER_PERMISSION_READER)
2262
    {
2263
        $table_rel = $this->usergroup_rel_user_table;
2264
        $user_id = (int) $user_id;
2265
        $group_id = (int) $group_id;
2266
        $relation_type = (int) $relation_type;
2267
2268
        if (empty($user_id) || empty($group_id)) {
2269
            return false;
2270
        }
2271
2272
        // Normalize relation type for classes vs social groups
2273
        $groupInfo = $this->get($group_id); // returns ['group_type' => ...] among others
2274
        if (!empty($groupInfo) && isset($groupInfo['group_type'])) {
2275
            if ((int) $groupInfo['group_type'] === self::NORMAL_CLASS) {
2276
                // For class memberships, we want relation_type = 0 as the canonical "reader"
2277
                if ($relation_type === GROUP_USER_PERMISSION_READER) {
2278
                    $relation_type = 0;
2279
                }
2280
            }
2281
        }
2282
2283
        // Current role (raw value from usergroup_rel_user)
2284
        $role = $this->get_user_group_role($user_id, $group_id);
2285
2286
        if (0 === $role) {
2287
            // No relationship yet → insert normalized relation_type
2288
            $sql = "INSERT INTO $table_rel
2289
                SET
2290
                    user_id = $user_id,
2291
                    usergroup_id = $group_id,
2292
                    relation_type = $relation_type";
2293
            Database::query($sql);
2294
        } elseif (GROUP_USER_PERMISSION_PENDING_INVITATION === $role) {
2295
            // If somebody already invited the user, upgrade to final role
2296
            self::update_user_role(
2297
                $user_id,
2298
                $group_id,
2299
                $relation_type ?: GROUP_USER_PERMISSION_READER
2300
            );
2301
        } elseif (
2302
            // Backward-compatibility: old "reader = 2" for classes → normalize to 0
2303
            GROUP_USER_PERMISSION_READER === $role
2304
            && $relation_type === 0
2305
        ) {
2306
            self::update_user_role($user_id, $group_id, 0);
2307
        }
2308
2309
        return true;
2310
    }
2311
2312
    /**
2313
     * Updates the group_rel_user table  with a given user and group ids.
2314
     *
2315
     * @author Julio Montoya
2316
     *
2317
     * @param int $user_id
2318
     * @param int $group_id
2319
     * @param int $relation_type
2320
     */
2321
    public function update_user_role($user_id, $group_id, $relation_type = GROUP_USER_PERMISSION_READER)
2322
    {
2323
        $table_group_rel_user = $this->usergroup_rel_user_table;
2324
        $group_id = (int) $group_id;
2325
        $user_id = (int) $user_id;
2326
        $relation_type = (int) $relation_type;
2327
2328
        $sql = "UPDATE $table_group_rel_user
2329
   				SET relation_type = $relation_type
2330
                WHERE user_id = $user_id AND usergroup_id = $group_id";
2331
        Database::query($sql);
2332
    }
2333
2334
    /**
2335
     * Gets the inner join from users and group table.
2336
     *
2337
     * @return array|int Database::store_result of the result
2338
     *
2339
     * @author Julio Montoya
2340
     * */
2341
    public function get_groups_by_user($user_id, $relationType = GROUP_USER_PERMISSION_READER, $with_image = false)
2342
    {
2343
        $table_group_rel_user = $this->usergroup_rel_user_table;
2344
        $tbl_group = $this->table;
2345
        $user_id = (int) $user_id;
2346
2347
        if (0 == $relationType) {
2348
            $relationCondition = '';
2349
        } else {
2350
            if (is_array($relationType)) {
2351
                $relationType = array_map('intval', $relationType);
2352
                $relationType = implode("','", $relationType);
2353
                $relationCondition = " AND ( gu.relation_type IN ('$relationType')) ";
2354
            } else {
2355
                $relationType = (int) $relationType;
2356
                $relationCondition = " AND gu.relation_type = $relationType ";
2357
            }
2358
        }
2359
2360
        $sql = 'SELECT
2361
                    g.picture,
2362
                    g.title,
2363
                    g.description,
2364
                    g.id ,
2365
                    gu.relation_type';
2366
2367
        $urlCondition = '';
2368
        if ($this->getUseMultipleUrl()) {
2369
            $sql .= " FROM $tbl_group g
2370
                    INNER JOIN ".$this->access_url_rel_usergroup." a
2371
                    ON (g.id = a.usergroup_id)
2372
                    INNER JOIN $table_group_rel_user gu
2373
                    ON gu.usergroup_id = g.id";
2374
            $urlId = api_get_current_access_url_id();
2375
            $urlCondition = " AND access_url_id = $urlId ";
2376
        } else {
2377
            $sql .= " FROM $tbl_group g
2378
                    INNER JOIN $table_group_rel_user gu
2379
                    ON gu.usergroup_id = g.id";
2380
        }
2381
2382
        $sql .= " WHERE
2383
				    g.group_type = ".Usergroup::SOCIAL_CLASS." AND
2384
                    gu.user_id = $user_id
2385
                    $relationCondition
2386
                    $urlCondition
2387
                ORDER BY created_at DESC ";
2388
        $result = Database::query($sql);
2389
        $array = [];
2390
        if (Database::num_rows($result) > 0) {
2391
            while ($row = Database::fetch_assoc($result)) {
2392
                if ($with_image) {
2393
                    $picture = $this->get_picture_group($row['id'], $row['picture'], 80);
2394
                    $img = '<img src="'.$picture['file'].'" />';
2395
                    $row['picture'] = $img;
2396
                }
2397
                $array[$row['id']] = $row;
2398
            }
2399
        }
2400
2401
        return $array;
2402
    }
2403
2404
    /** Gets the inner join of users and group table.
2405
     * @param int  quantity of records
2406
     * @param bool show groups with image or not
2407
     *
2408
     * @return array with group content
2409
     *
2410
     * @author Julio Montoya
2411
     * */
2412
    public function get_groups_by_popularity($num = 6, $with_image = true)
2413
    {
2414
        $table_group_rel_user = $this->usergroup_rel_user_table;
2415
        $tbl_group = $this->table;
2416
        if (empty($num)) {
2417
            $num = 6;
2418
        } else {
2419
            $num = (int) $num;
2420
        }
2421
        // only show admins and readers
2422
        $whereCondition = " WHERE
2423
                              g.group_type = ".Usergroup::SOCIAL_CLASS." AND
2424
                              gu.relation_type IN
2425
                              ('".GROUP_USER_PERMISSION_ADMIN."' , '".GROUP_USER_PERMISSION_READER."', '".GROUP_USER_PERMISSION_HRM."') ";
2426
2427
        $sql = 'SELECT DISTINCT count(user_id) as count, g.picture, g.title, g.description, g.id ';
2428
2429
        $urlCondition = '';
2430
        if ($this->getUseMultipleUrl()) {
2431
            $sql .= " FROM $tbl_group g
2432
                    INNER JOIN ".$this->access_url_rel_usergroup." a
2433
                    ON (g.id = a.usergroup_id)
2434
                    INNER JOIN $table_group_rel_user gu
2435
                    ON gu.usergroup_id = g.id";
2436
            $urlId = api_get_current_access_url_id();
2437
            $urlCondition = " AND access_url_id = $urlId ";
2438
        } else {
2439
            $sql .= " FROM $tbl_group g
2440
                    INNER JOIN $table_group_rel_user gu
2441
                    ON gu.usergroup_id = g.id";
2442
        }
2443
2444
        $sql .= "
2445
				$whereCondition
2446
				$urlCondition
2447
				GROUP BY g.id
2448
				ORDER BY count DESC
2449
				LIMIT $num";
2450
2451
        $result = Database::query($sql);
2452
        $array = [];
2453
        while ($row = Database::fetch_assoc($result)) {
2454
            if ($with_image) {
2455
                $picture = $this->get_picture_group($row['id'], $row['picture'], 80);
2456
                $img = '<img src="'.$picture['file'].'" />';
2457
                $row['picture'] = $img;
2458
            }
2459
            if (empty($row['id'])) {
2460
                continue;
2461
            }
2462
            $array[$row['id']] = $row;
2463
        }
2464
2465
        return $array;
2466
    }
2467
2468
    /** Gets the last groups created.
2469
     * @param int  $num       quantity of records
2470
     * @param bool $withImage show groups with image or not
2471
     *
2472
     * @return array with group content
2473
     *
2474
     * @author Julio Montoya
2475
     * */
2476
    public function get_groups_by_age($num = 6, $withImage = true)
2477
    {
2478
        $table_group_rel_user = $this->usergroup_rel_user_table;
2479
        $tbl_group = $this->table;
2480
2481
        if (empty($num)) {
2482
            $num = 6;
2483
        } else {
2484
            $num = (int) $num;
2485
        }
2486
2487
        $where = " WHERE
2488
                        g.group_type = ".Usergroup::SOCIAL_CLASS." AND
2489
                        gu.relation_type IN
2490
                        ('".GROUP_USER_PERMISSION_ADMIN."' ,
2491
                        '".GROUP_USER_PERMISSION_READER."',
2492
                        '".GROUP_USER_PERMISSION_MODERATOR."',
2493
                        '".GROUP_USER_PERMISSION_HRM."')
2494
                    ";
2495
        $sql = 'SELECT DISTINCT
2496
                  count(user_id) as count,
2497
                  g.picture,
2498
                  g.title,
2499
                  g.description,
2500
                  g.id ';
2501
2502
        $urlCondition = '';
2503
        if ($this->getUseMultipleUrl()) {
2504
            $sql .= " FROM $tbl_group g
2505
                    INNER JOIN ".$this->access_url_rel_usergroup." a
2506
                    ON (g.id = a.usergroup_id)
2507
                    INNER JOIN $table_group_rel_user gu
2508
                    ON gu.usergroup_id = g.id";
2509
            $urlId = api_get_current_access_url_id();
2510
            $urlCondition = " AND access_url_id = $urlId ";
2511
        } else {
2512
            $sql .= " FROM $tbl_group g
2513
                    INNER JOIN $table_group_rel_user gu
2514
                    ON gu.usergroup_id = g.id";
2515
        }
2516
        $sql .= "
2517
                $where
2518
                $urlCondition
2519
                GROUP BY g.id
2520
                ORDER BY created_at DESC
2521
                LIMIT $num ";
2522
2523
        $result = Database::query($sql);
2524
        $array = [];
2525
        while ($row = Database::fetch_assoc($result)) {
2526
            if ($withImage) {
2527
                $picture = $this->get_picture_group($row['id'], $row['picture'], 80);
2528
                $img = '<img src="'.$picture['file'].'" />';
2529
                $row['picture'] = $img;
2530
            }
2531
            if (empty($row['id'])) {
2532
                continue;
2533
            }
2534
            $array[$row['id']] = $row;
2535
        }
2536
2537
        return $array;
2538
    }
2539
2540
    /**
2541
     * Gets the group's members.
2542
     *
2543
     * @param int group id
2544
     * @param bool show image or not of the group
2545
     * @param array list of relation type use constants
2546
     * @param int from value
2547
     * @param int limit
2548
     * @param array image configuration, i.e array('height'=>'20px', 'size'=> '20px')
2549
     *
2550
     * @return array list of users in a group
2551
     */
2552
    public function get_users_by_group(
2553
        $group_id,
2554
        $withImage = false,
2555
        $relation_type = [],
2556
        $from = null,
2557
        $limit = null,
2558
        $image_conf = ['size' => USER_IMAGE_SIZE_MEDIUM, 'height' => 80]
2559
    ) {
2560
        $table_group_rel_user = $this->usergroup_rel_user_table;
2561
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
2562
        $group_id = (int) $group_id;
2563
2564
        if (empty($group_id)) {
2565
            return [];
2566
        }
2567
2568
        $limit_text = '';
2569
        if (isset($from) && isset($limit)) {
2570
            $from = (int) $from;
2571
            $limit = (int) $limit;
2572
            $limit_text = "LIMIT $from, $limit";
2573
        }
2574
2575
        if (0 == count($relation_type)) {
2576
            $where_relation_condition = '';
2577
        } else {
2578
            $new_relation_type = [];
2579
            foreach ($relation_type as $rel) {
2580
                $rel = (int) $rel;
2581
                $new_relation_type[] = "'$rel'";
2582
            }
2583
            $relation_type = implode(',', $new_relation_type);
2584
            if (!empty($relation_type)) {
2585
                $where_relation_condition = "AND gu.relation_type IN ($relation_type) ";
2586
            }
2587
        }
2588
2589
        $sql = "SELECT
2590
                    picture_uri as image,
2591
                    u.id,
2592
                    CONCAT (u.firstname,' ', u.lastname) as fullname,
2593
                    relation_type
2594
    		    FROM $tbl_user u
2595
    		    INNER JOIN $table_group_rel_user gu
2596
    			ON (gu.user_id = u.id)
2597
    			WHERE
2598
    			    u.active <> ".USER_SOFT_DELETED." AND
2599
    			    gu.usergroup_id= $group_id
2600
    			    $where_relation_condition
2601
    			ORDER BY relation_type, firstname
2602
    			$limit_text";
2603
2604
        $result = Database::query($sql);
2605
        $array = [];
2606
        while ($row = Database::fetch_assoc($result)) {
2607
            if ($withImage) {
2608
                $userInfo = api_get_user_info($row['id']);
2609
                $userPicture = UserManager::getUserPicture($row['id']);
2610
                $row['image'] = '<img src="'.$userPicture.'"  />';
2611
                $row['user_info'] = $userInfo;
2612
            }
2613
2614
            $row['user_id'] = $row['id'];
2615
            $array[$row['id']] = $row;
2616
        }
2617
2618
        return $array;
2619
    }
2620
2621
    /**
2622
     * Gets all the members of a group no matter the relationship for
2623
     * more specifications use get_users_by_group.
2624
     *
2625
     * @param int group id
2626
     *
2627
     * @return array
2628
     */
2629
    public function get_all_users_by_group($group_id)
2630
    {
2631
        $table_group_rel_user = $this->usergroup_rel_user_table;
2632
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
2633
        $group_id = (int) $group_id;
2634
2635
        if (empty($group_id)) {
2636
            return [];
2637
        }
2638
2639
        $sql = "SELECT u.id, u.firstname, u.lastname, relation_type
2640
                FROM $tbl_user u
2641
			    INNER JOIN $table_group_rel_user gu
2642
			    ON (gu.user_id = u.id)
2643
			    WHERE u.active <> ".USER_SOFT_DELETED." AND gu.usergroup_id= $group_id
2644
			    ORDER BY relation_type, firstname";
2645
2646
        $result = Database::query($sql);
2647
        $array = [];
2648
        while ($row = Database::fetch_assoc($result)) {
2649
            $array[$row['id']] = $row;
2650
        }
2651
2652
        return $array;
2653
    }
2654
2655
    /**
2656
     * Shows the left column of the group page.
2657
     *
2658
     * @param int    $group_id
2659
     * @param int    $user_id
2660
     * @param string $show
2661
     *
2662
     * @return string
2663
     */
2664
    public function show_group_column_information($group_id, $user_id, $show = '')
2665
    {
2666
        $html = '';
2667
        $group_info = $this->get($group_id);
2668
2669
        //my relation with the group is set here
2670
        $my_group_role = $this->get_user_group_role($user_id, $group_id);
2671
2672
        // Loading group permission
2673
        $links = '';
2674
        switch ($my_group_role) {
2675
            case GROUP_USER_PERMISSION_READER:
2676
                // I'm just a reader
2677
                $relation_group_title = get_lang('I am a reader');
2678
                $links .= '<li class="'.('invite_friends' == $show ? 'active' : '').'"><a href="group_invitation.php?id='.$group_id.'">'.
2679
                    Display::getMdiIcon(ObjectIcon::INVITATION, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Invite friends')).get_lang('Invite friends').'</a></li>';
2680
                if (self::canLeave($group_info)) {
2681
                    $links .= '<li><a href="group_view.php?id='.$group_id.'&action=leave&u='.api_get_user_id().'">'.
2682
                        Display::getMdiIcon(ActionIcon::EXIT, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Leave group')).get_lang('Leave group').'</a></li>';
2683
                }
2684
                break;
2685
            case GROUP_USER_PERMISSION_ADMIN:
2686
                $relation_group_title = get_lang('I am an admin');
2687
                $links .= '<li class="'.('group_edit' == $show ? 'active' : '').'"><a href="group_edit.php?id='.$group_id.'">'.
2688
                    Display::getMdiIcon(ActionIcon::EDIT, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Edit this group')).get_lang('Edit this group').'</a></li>';
2689
                $links .= '<li class="'.('member_list' == $show ? 'active' : '').'"><a href="group_waiting_list.php?id='.$group_id.'">'.
2690
                    Display::getMdiIcon(ObjectIcon::WAITING_LIST, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Waiting list')).get_lang('Waiting list').'</a></li>';
2691
                $links .= '<li class="'.('invite_friends' == $show ? 'active' : '').'"><a href="group_invitation.php?id='.$group_id.'">'.
2692
                    Display::getMdiIcon(ObjectIcon::INVITATION, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Invite friends')).get_lang('Invite friends').'</a></li>';
2693
                if (self::canLeave($group_info)) {
2694
                    $links .= '<li><a href="group_view.php?id='.$group_id.'&action=leave&u='.api_get_user_id().'">'.
2695
                        Display::getMdiIcon(ActionIcon::EXIT, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Leave group')).get_lang('Leave group').'</a></li>';
2696
                }
2697
                break;
2698
            case GROUP_USER_PERMISSION_PENDING_INVITATION:
2699
//				$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>';
2700
                break;
2701
            case GROUP_USER_PERMISSION_PENDING_INVITATION_SENT_BY_USER:
2702
                $relation_group_title = get_lang('Waiting for admin response');
2703
                break;
2704
            case GROUP_USER_PERMISSION_MODERATOR:
2705
                $relation_group_title = get_lang('I am a moderator');
2706
                //$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>';
2707
                //$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>';
2708
                //$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>';
2709
                if (GROUP_PERMISSION_CLOSED == $group_info['visibility']) {
2710
                    $links .= '<li><a href="group_waiting_list.php?id='.$group_id.'">'.
2711
                        Display::getMdiIcon(ObjectIcon::WAITING_LIST, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Waiting list')).get_lang('Waiting list').'</a></li>';
2712
                }
2713
                $links .= '<li><a href="group_invitation.php?id='.$group_id.'">'.
2714
                    Display::getMdiIcon(ObjectIcon::INVITATION, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Invite friends')).get_lang('Invite friends').'</a></li>';
2715
                if (self::canLeave($group_info)) {
2716
                    $links .= '<li><a href="group_view.php?id='.$group_id.'&action=leave&u='.api_get_user_id().'">'.
2717
                        Display::getMdiIcon(ActionIcon::EXIT, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Leave group')).get_lang('Leave group').'</a></li>';
2718
                }
2719
                break;
2720
            case GROUP_USER_PERMISSION_HRM:
2721
                $relation_group_title = get_lang('I am a human resources manager');
2722
                $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').'">'.
2723
                    Display::getMdiIcon(ActionIcon::EDIT, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Create thread')).get_lang('Create thread').'</a></li>';
2724
                $links .= '<li><a href="group_view.php?id='.$group_id.'">'.
2725
                    Display::getMdiIcon(ToolIcon::MESSAGE, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Messages list')).get_lang('Messages list').'</a></li>';
2726
                $links .= '<li><a href="group_invitation.php?id='.$group_id.'">'.
2727
                    Display::getMdiIcon(ObjectIcon::INVITATION, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Invite friends')).get_lang('Invite friends').'</a></li>';
2728
                $links .= '<li><a href="group_members.php?id='.$group_id.'">'.
2729
                    Display::getMdiIcon(ObjectIcon::GROUP, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Members list')).get_lang('Members list').'</a></li>';
2730
                $links .= '<li><a href="group_view.php?id='.$group_id.'&action=leave&u='.api_get_user_id().'">'.
2731
                    Display::getMdiIcon(ActionIcon::EXIT, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Leave group')).get_lang('Leave group').'</a></li>';
2732
                break;
2733
            default:
2734
                //$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>';
2735
                break;
2736
        }
2737
        if (!empty($links)) {
2738
            $list = '<ul class="nav nav-pills">';
2739
            $list .= $links;
2740
            $list .= '</ul>';
2741
            $html .= Display::panelCollapse(
2742
                get_lang('Social groups'),
2743
                $list,
2744
                'sm-groups',
2745
                [],
2746
                'groups-acordeon',
2747
                'groups-collapse'
2748
            );
2749
        }
2750
2751
        return $html;
2752
    }
2753
2754
    /**
2755
     * @param int $group_id
2756
     * @param int $topic_id
2757
     */
2758
    public function delete_topic($group_id, $topic_id)
2759
    {
2760
        $table_message = Database::get_main_table(TABLE_MESSAGE);
2761
        $topic_id = (int) $topic_id;
2762
        $group_id = (int) $group_id;
2763
2764
        $sql = "UPDATE $table_message SET
2765
                    msg_type = 3
2766
                WHERE
2767
                    group_id = $group_id AND
2768
                    (id = '$topic_id' OR parent_id = $topic_id)
2769
                ";
2770
        Database::query($sql);
2771
    }
2772
2773
    /**
2774
     * @param string $user_id
2775
     * @param int    $relation_type
2776
     * @param bool   $with_image
2777
     *
2778
     * @deprecated
2779
     *
2780
     * @return int
2781
     */
2782
    public function get_groups_by_user_count(
2783
        $user_id = '',
2784
        $relation_type = GROUP_USER_PERMISSION_READER,
2785
        $with_image = false
2786
    ) {
2787
        $table_group_rel_user = $this->usergroup_rel_user_table;
2788
        $tbl_group = $this->table;
2789
        $user_id = (int) $user_id;
2790
2791
        if (0 == $relation_type) {
2792
            $where_relation_condition = '';
2793
        } else {
2794
            $relation_type = (int) $relation_type;
2795
            $where_relation_condition = "AND gu.relation_type = $relation_type ";
2796
        }
2797
2798
        $sql = "SELECT count(g.id) as count
2799
				FROM $tbl_group g
2800
				INNER JOIN $table_group_rel_user gu
2801
				ON gu.usergroup_id = g.id
2802
				WHERE gu.user_id = $user_id $where_relation_condition ";
2803
2804
        $result = Database::query($sql);
2805
        if (Database::num_rows($result) > 0) {
2806
            $row = Database::fetch_assoc($result);
2807
2808
            return $row['count'];
2809
        }
2810
2811
        return 0;
2812
    }
2813
2814
    /**
2815
     * @param string $tag
2816
     * @param int    $from
2817
     * @param int    $number_of_items
2818
     *
2819
     * @return array
2820
     */
2821
    public function get_all_group_tags($tag, $from = 0, $number_of_items = 10, $getCount = false)
2822
    {
2823
        $group_table = $this->table;
2824
        $tag = Database::escape_string($tag);
2825
        $from = (int) $from;
2826
        $number_of_items = (int) $number_of_items;
2827
        $return = [];
2828
2829
        $keyword = $tag;
2830
        $sql = 'SELECT  g.id, g.title, g.description, g.url, g.picture ';
2831
        $urlCondition = '';
2832
        if ($this->getUseMultipleUrl()) {
2833
            $urlId = api_get_current_access_url_id();
2834
            $sql .= " FROM $this->table g
2835
                    INNER JOIN $this->access_url_rel_usergroup a
2836
                    ON (g.id = a.usergroup_id)";
2837
            $urlCondition = " AND access_url_id = $urlId ";
2838
        } else {
2839
            $sql .= " FROM $group_table g";
2840
        }
2841
        if (isset($keyword)) {
2842
            $sql .= " WHERE (
2843
                        g.title LIKE '%".$keyword."%' OR
2844
                        g.description LIKE '%".$keyword."%' OR
2845
                        g.url LIKE '%".$keyword."%'
2846
                     ) $urlCondition
2847
                     ";
2848
        } else {
2849
            $sql .= " WHERE 1 = 1 $urlCondition ";
2850
        }
2851
2852
        $direction = 'ASC';
2853
        if (!in_array($direction, ['ASC', 'DESC'])) {
2854
            $direction = 'ASC';
2855
        }
2856
2857
        $sql .= " LIMIT $from, $number_of_items";
2858
2859
        $res = Database::query($sql);
2860
        if (Database::num_rows($res) > 0) {
2861
            while ($row = Database::fetch_assoc($res)) {
2862
                if (!in_array($row['id'], $return)) {
2863
                    $return[$row['id']] = $row;
2864
                }
2865
            }
2866
        }
2867
2868
        return $return;
2869
    }
2870
2871
    /**
2872
     * @param int $group_id
2873
     *
2874
     * @return array
2875
     */
2876
    public static function get_parent_groups($group_id)
2877
    {
2878
        $t_rel_group = Database::get_main_table(TABLE_USERGROUP_REL_USERGROUP);
2879
        $group_id = (int) $group_id;
2880
2881
        $max_level = 10;
2882
        $select_part = 'SELECT ';
2883
        $cond_part = '';
2884
        for ($i = 1; $i <= $max_level; $i++) {
2885
            $rg_number = $i - 1;
2886
            if ($i == $max_level) {
2887
                $select_part .= "rg$rg_number.group_id as id_$rg_number ";
2888
            } else {
2889
                $select_part .= "rg$rg_number.group_id as id_$rg_number, ";
2890
            }
2891
            if (1 == $i) {
2892
                $cond_part .= "FROM $t_rel_group rg0
2893
                               LEFT JOIN $t_rel_group rg$i
2894
                               ON rg$rg_number.group_id = rg$i.subgroup_id ";
2895
            } else {
2896
                $cond_part .= " LEFT JOIN $t_rel_group rg$i
2897
                                ON rg$rg_number.group_id = rg$i.subgroup_id ";
2898
            }
2899
        }
2900
        $sql = $select_part.' '.$cond_part."WHERE rg0.subgroup_id='$group_id'";
2901
        $res = Database::query($sql);
2902
        $temp_arr = Database::fetch_array($res, 'NUM');
2903
        $toReturn = [];
2904
        if (is_array($temp_arr)) {
2905
            foreach ($temp_arr as $elt) {
2906
                if (isset($elt)) {
2907
                    $toReturn[] = $elt;
2908
                }
2909
            }
2910
        }
2911
2912
        return $toReturn;
2913
    }
2914
2915
    /**
2916
     * Get the group member list by a user and his group role.
2917
     *
2918
     * @param int  $userId                The user ID
2919
     * @param int  $relationType          Optional. The relation type. GROUP_USER_PERMISSION_ADMIN by default
2920
     * @param bool $includeSubgroupsUsers Optional. Whether include the users from subgroups
2921
     *
2922
     * @return array
2923
     */
2924
    public function getGroupUsersByUser(
2925
        $userId,
2926
        $relationType = GROUP_USER_PERMISSION_ADMIN,
2927
        $includeSubgroupsUsers = true
2928
    ) {
2929
        $userId = (int) $userId;
2930
        $groups = $this->get_groups_by_user($userId, $relationType);
2931
        $groupsId = array_keys($groups);
2932
        $subgroupsId = [];
2933
        $userIdList = [];
2934
2935
        if ($includeSubgroupsUsers) {
2936
            foreach ($groupsId as $groupId) {
2937
                $subgroupsId = array_merge($subgroupsId, self::getGroupsByDepthLevel($groupId));
2938
            }
2939
2940
            $groupsId = array_merge($groupsId, $subgroupsId);
2941
        }
2942
2943
        $groupsId = array_unique($groupsId);
2944
2945
        if (empty($groupsId)) {
2946
            return [];
2947
        }
2948
2949
        foreach ($groupsId as $groupId) {
2950
            $groupUsers = $this->get_users_by_group($groupId);
2951
2952
            if (empty($groupUsers)) {
2953
                continue;
2954
            }
2955
2956
            foreach ($groupUsers as $member) {
2957
                if ($member['user_id'] == $userId) {
2958
                    continue;
2959
                }
2960
2961
                $userIdList[] = (int) $member['user_id'];
2962
            }
2963
        }
2964
2965
        return array_unique($userIdList);
2966
    }
2967
2968
    /**
2969
     * Get the subgroups ID from a group.
2970
     * The default $levels value is 10 considering it as a extensive level of depth.
2971
     *
2972
     * @param int $groupId The parent group ID
2973
     * @param int $levels  The depth levels
2974
     *
2975
     * @return array The list of ID
2976
     */
2977
    public static function getGroupsByDepthLevel($groupId, $levels = 10)
2978
    {
2979
        $groups = [];
2980
        $groupId = (int) $groupId;
2981
2982
        $groupTable = Database::get_main_table(TABLE_USERGROUP);
2983
        $groupRelGroupTable = Database::get_main_table(TABLE_USERGROUP_REL_USERGROUP);
2984
2985
        $select = 'SELECT ';
2986
        $from = "FROM $groupTable g1 ";
2987
2988
        for ($i = 1; $i <= $levels; $i++) {
2989
            $tableIndexNumber = $i;
2990
            $tableIndexJoinNumber = $i - 1;
2991
            $select .= "g$i.id as id_$i ";
2992
            $select .= $i != $levels ? ', ' : null;
2993
2994
            if (1 == $i) {
2995
                $from .= " INNER JOIN $groupRelGroupTable gg0
2996
                           ON g1.id = gg0.subgroup_id and gg0.group_id = $groupId ";
2997
            } else {
2998
                $from .= "LEFT JOIN $groupRelGroupTable gg$tableIndexJoinNumber ";
2999
                $from .= " ON g$tableIndexJoinNumber.id = gg$tableIndexJoinNumber.group_id ";
3000
                $from .= "LEFT JOIN $groupTable g$tableIndexNumber ";
3001
                $from .= " ON gg$tableIndexJoinNumber.subgroup_id = g$tableIndexNumber.id ";
3002
            }
3003
        }
3004
3005
        $result = Database::query("$select $from");
3006
3007
        while ($item = Database::fetch_assoc($result)) {
3008
            foreach ($item as $myGroupId) {
3009
                if (!empty($myGroupId)) {
3010
                    $groups[] = $myGroupId;
3011
                }
3012
            }
3013
        }
3014
3015
        return array_map('intval', $groups);
3016
    }
3017
3018
    /**
3019
     * Set a parent group.
3020
     *
3021
     * @param int $group_id
3022
     * @param int $parent_group_id if 0, we delete the parent_group association
3023
     * @param int $relation_type
3024
     *
3025
     * @return \Doctrine\DBAL\Statement
3026
     */
3027
    public function setParentGroup($group_id, $parent_group_id, $relation_type = 1)
3028
    {
3029
        $table = Database::get_main_table(TABLE_USERGROUP_REL_USERGROUP);
3030
        $group_id = (int) $group_id;
3031
        $parent_group_id = (int) $parent_group_id;
3032
        if (0 == $parent_group_id) {
3033
            $sql = "DELETE FROM $table WHERE subgroup_id = $group_id";
3034
        } else {
3035
            $sql = "SELECT group_id FROM $table WHERE subgroup_id = $group_id";
3036
            $res = Database::query($sql);
3037
            if (0 == Database::num_rows($res)) {
3038
                $sql = "INSERT INTO $table SET
3039
                        group_id = $parent_group_id,
3040
                        subgroup_id = $group_id,
3041
                        relation_type = $relation_type";
3042
            } else {
3043
                $sql = "UPDATE $table SET
3044
                        group_id = $parent_group_id,
3045
                        relation_type = $relation_type
3046
                        WHERE subgroup_id = $group_id";
3047
            }
3048
        }
3049
        $res = Database::query($sql);
3050
3051
        return $res;
3052
    }
3053
3054
    /**
3055
     * Filter the groups/classes info to get a name list only.
3056
     *
3057
     * @param int $userId       The user ID
3058
     * @param int $filterByType Optional. The type of group
3059
     *
3060
     * @return array
3061
     */
3062
    public function getNameListByUser($userId, $filterByType = null)
3063
    {
3064
        $userClasses = $this->getUserGroupListByUser($userId, $filterByType);
3065
3066
        return array_column($userClasses, 'title');
3067
    }
3068
3069
    /**
3070
     * Get the HTML necessary for display the groups/classes name list.
3071
     *
3072
     * @param int $userId       The user ID
3073
     * @param int $filterByType Optional. The type of group
3074
     *
3075
     * @return string
3076
     */
3077
    public function getLabelsFromNameList($userId, $filterByType = null)
3078
    {
3079
        $groupsNameListParsed = $this->getNameListByUser($userId, $filterByType);
3080
3081
        if (empty($groupsNameListParsed)) {
3082
            return '';
3083
        }
3084
3085
        $nameList = '<ul class="list-unstyled">';
3086
        foreach ($groupsNameListParsed as $name) {
3087
            $nameList .= '<li>'.Display::span($name, ['class' => 'label label-info']).'</li>';
3088
        }
3089
3090
        $nameList .= '</ul>';
3091
3092
        return $nameList;
3093
    }
3094
3095
    /**
3096
     * @param array $groupInfo
3097
     *
3098
     * @return bool
3099
     */
3100
    public static function canLeave($groupInfo)
3101
    {
3102
        return 1 == $groupInfo['allow_members_leave_group'] ? true : false;
3103
    }
3104
3105
    /**
3106
     * Check permissions and blocks the page.
3107
     *
3108
     * @param array $userGroupInfo
3109
     * @param bool  $checkAuthor
3110
     * @param bool  $checkCourseIsAllow
3111
     */
3112
    public function protectScript($userGroupInfo = [], $checkAuthor = true, $checkCourseIsAllow = false)
3113
    {
3114
        api_block_anonymous_users();
3115
3116
        if (api_is_platform_admin()) {
3117
            return true;
3118
        }
3119
3120
        if ($checkCourseIsAllow) {
3121
            if (api_is_allowed_to_edit()) {
3122
                return true;
3123
            }
3124
        }
3125
3126
        if ($this->allowTeachers() && api_is_teacher()) {
3127
            if ($checkAuthor && !empty($userGroupInfo)) {
3128
                if (isset($userGroupInfo['author_id']) && $userGroupInfo['author_id'] != api_get_user_id()) {
3129
                    api_not_allowed(true);
3130
                }
3131
            }
3132
3133
            return true;
3134
        } else {
3135
            api_protect_admin_script(true);
3136
            api_protect_limit_for_session_admin();
3137
        }
3138
    }
3139
3140
    public function getGroupsByLp($lpId, $courseId, $sessionId)
3141
    {
3142
        $lpId = (int) $lpId;
3143
        $courseId = (int) $courseId;
3144
        $sessionId = (int) $sessionId;
3145
        $sessionCondition = api_get_session_condition($sessionId, true);
3146
        $table = Database::get_course_table(TABLE_LP_REL_USERGROUP);
3147
        $sql = "SELECT usergroup_id FROM $table
3148
                WHERE
3149
                    c_id = $courseId AND
3150
                    lp_id = $lpId
3151
                    $sessionCondition
3152
                    ";
3153
        $result = Database::query($sql);
3154
3155
        return Database::store_result($result, 'ASSOC');
3156
    }
3157
3158
    public function getGroupsByLpCategory($categoryId, $courseId, $sessionId)
3159
    {
3160
        $categoryId = (int) $categoryId;
3161
        $courseId = (int) $courseId;
3162
        $sessionId = (int) $sessionId;
3163
        $sessionCondition = api_get_session_condition($sessionId, true);
3164
3165
        $table = Database::get_course_table(TABLE_LP_CATEGORY_REL_USERGROUP);
3166
        $sql = "SELECT usergroup_id FROM $table
3167
                WHERE
3168
                    c_id = $courseId AND
3169
                    lp_category_id = $categoryId
3170
                    $sessionCondition
3171
                ";
3172
        $result = Database::query($sql);
3173
3174
        return Database::store_result($result, 'ASSOC');
3175
    }
3176
3177
    public static function getRoleName($relation)
3178
    {
3179
        switch ((int) $relation) {
3180
            case GROUP_USER_PERMISSION_ADMIN:
3181
                return get_lang('Admin');
3182
            case GROUP_USER_PERMISSION_READER:
3183
                return get_lang('Reader');
3184
            case GROUP_USER_PERMISSION_PENDING_INVITATION:
3185
                return get_lang('Pending invitation');
3186
            case GROUP_USER_PERMISSION_MODERATOR:
3187
                return get_lang('Moderator');
3188
            case GROUP_USER_PERMISSION_HRM:
3189
                return get_lang('Human Resources Manager');
3190
            default:
3191
                return get_lang('Custom or undefined role');
3192
        }
3193
    }
3194
}
3195