Completed
Push — master ( 27e209...a08afa )
by Julito
186:04 queued 150:53
created

UserGroup::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 8
nc 1
nop 0
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
/**
5
 * Class UserGroup
6
 *
7
 * This class provides methods for the UserGroup management.
8
 * Include/require it in your code to use its features.
9
 * @package chamilo.library
10
 *
11
 */
12
class UserGroup extends Model
13
{
14
    public $columns = [
15
        'id',
16
        'name',
17
        'description',
18
        'group_type',
19
        'picture',
20
        'url',
21
        'allow_members_leave_group',
22
        'visibility',
23
        'updated_at',
24
        'created_at'
25
    ];
26
27
    public $useMultipleUrl = false;
28
29
    const SOCIAL_CLASS = 1;
30
    const NORMAL_CLASS = 0;
31
    public $groupType = 0;
32
    public $showGroupTypeSetting = false;
33
34
    /**
35
     * Set ups DB tables
36
     */
37
    public function __construct()
38
    {
39
        $this->table = Database::get_main_table(TABLE_USERGROUP);
40
        $this->usergroup_rel_user_table = Database::get_main_table(TABLE_USERGROUP_REL_USER);
0 ignored issues
show
Bug Best Practice introduced by
The property usergroup_rel_user_table does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
41
        $this->usergroup_rel_course_table = Database::get_main_table(TABLE_USERGROUP_REL_COURSE);
0 ignored issues
show
Bug Best Practice introduced by
The property usergroup_rel_course_table does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
42
        $this->usergroup_rel_session_table = Database::get_main_table(TABLE_USERGROUP_REL_SESSION);
0 ignored issues
show
Bug Best Practice introduced by
The property usergroup_rel_session_table does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
43
        $this->access_url_rel_usergroup = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USERGROUP);
0 ignored issues
show
Bug Best Practice introduced by
The property access_url_rel_usergroup does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
44
        $this->table_course = Database::get_main_table(TABLE_MAIN_COURSE);
0 ignored issues
show
Bug Best Practice introduced by
The property table_course does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
45
        $this->table_user = Database::get_main_table(TABLE_MAIN_USER);
0 ignored issues
show
Bug Best Practice introduced by
The property table_user does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
46
        $this->useMultipleUrl = api_get_configuration_value('multiple_access_urls');
47
    }
48
49
    /**
50
     * @return bool
51
     */
52
    public function getUseMultipleUrl()
53
    {
54
        return $this->useMultipleUrl;
55
    }
56
57
    /**
58
     * @return int
59
     */
60
    public function getTotalCount()
61
    {
62
        $row = Database::select('count(*) as count', $this->table, [], 'first');
63
64
        return $row['count'];
65
    }
66
67
    /**
68
     * @param int $type
69
     *
70
     * @return int
71
     */
72
    public function get_count($type = -1)
73
    {
74
        if ($this->useMultipleUrl) {
75
            $urlId = api_get_current_access_url_id();
76
            $sql = "SELECT count(u.id) as count FROM ".$this->table." u
77
                    INNER JOIN ".$this->access_url_rel_usergroup." a
78
                        ON (u.id = a.usergroup_id)
79
                    WHERE access_url_id = $urlId
80
            ";
81
            $result = Database::query($sql);
82
            if (Database::num_rows($result)) {
83
                $row = Database::fetch_array($result);
84
85
                return $row['count'];
86
            }
87
88
            return 0;
89
        } else {
90
            $typeCondition = '';
91
            if ($type != -1) {
92
                $type = intval($type);
93
                $typeCondition = " WHERE group_type = $type ";
94
            }
95
96
            $sql = "SELECT count(a.id) as count
97
                    FROM {$this->table} a
98
                    $typeCondition
99
            ";
100
            $result = Database::query($sql);
101
            if (Database::num_rows($result)) {
102
                $row = Database::fetch_array($result);
103
                return $row['count'];
104
            }
105
        }
106
    }
107
108
    /**
109
     * @param int $course_id
110
     * @param int $type
111
     *
112
     * @return mixed
113
     */
114
    public function getUserGroupByCourseWithDataCount($course_id, $type = -1)
115
    {
116
        if ($this->useMultipleUrl) {
117
            $course_id = intval($course_id);
118
            $urlId = api_get_current_access_url_id();
119
            $sql = "SELECT count(c.usergroup_id) as count
120
                    FROM {$this->usergroup_rel_course_table} c
121
                    INNER JOIN {$this->access_url_rel_usergroup} a
122
                    ON (c.usergroup_id = a.usergroup_id)
123
                    WHERE access_url_id = $urlId AND course_id = $course_id
124
            ";
125
            $result = Database::query($sql);
126
            if (Database::num_rows($result)) {
127
                $row = Database::fetch_array($result);
128
                return $row['count'];
129
            }
130
131
            return 0;
132
        } else {
133
            $typeCondition = '';
134
            if ($type != -1) {
135
                $type = intval($type);
136
                $typeCondition = " AND group_type = $type ";
137
            }
138
            $sql = "SELECT count(c.usergroup_id) as count
139
                    FROM {$this->usergroup_rel_course_table} c
140
                    INNER JOIN {$this->table} a
141
                    ON (c.usergroup_id = a.id)
142
                    WHERE
143
                        course_id = $course_id
144
                        $typeCondition
145
            ";
146
            $result = Database::query($sql);
147
            if (Database::num_rows($result)) {
148
                $row = Database::fetch_array($result);
149
                return $row['count'];
150
            }
151
152
            return 0;
153
        }
154
    }
155
156
    /**
157
     * @param string $name
158
     *
159
     * @return mixed
160
     */
161
    public function get_id_by_name($name)
162
    {
163
        $row = Database::select(
164
            'id',
165
            $this->table,
166
            ['where' => ['name = ?' => $name]],
167
            'first'
168
        );
169
170
        return $row['id'];
171
    }
172
173
    /**
174
     * Displays the title + grid
175
     */
176
    public function display()
177
    {
178
        // action links
179
        echo '<div class="actions">';
180
        echo '<a href="../admin/index.php">'.
181
            Display::return_icon('back.png', get_lang('BackTo').' '.get_lang('PlatformAdmin'), '', '32').
182
            '</a>';
183
        echo '<a href="'.api_get_self().'?action=add">'.
184
            Display::return_icon('new_class.png', get_lang('AddClasses'), '', '32').
185
            '</a>';
186
        echo Display::url(
187
            Display::return_icon('import_csv.png', get_lang('Import'), [], ICON_SIZE_MEDIUM),
188
            'usergroup_import.php'
189
        );
190
        echo Display::url(
191
            Display::return_icon('export_csv.png', get_lang('Export'), [], ICON_SIZE_MEDIUM),
192
            'usergroup_export.php'
193
        );
194
        echo '</div>';
195
        echo Display::grid_html('usergroups');
196
    }
197
198
    /**
199
     * Get HTML grid
200
     */
201
    public function display_teacher_view()
202
    {
203
        echo Display::grid_html('usergroups');
204
    }
205
206
    /**
207
     * Gets a list of course ids by user group
208
     * @param int $id user group id
209
     * @param array $loadCourseData
210
     *
211
     * @return  array
212
     */
213
    public function get_courses_by_usergroup($id, $loadCourseData = false)
214
    {
215
        if ($this->useMultipleUrl) {
216
            $urlId = api_get_current_access_url_id();
217
            $from = $this->usergroup_rel_course_table." c
218
                    INNER JOIN {$this->access_url_rel_usergroup} a
219
                    ON (a.usergroup_id = c.usergroup_id) ";
220
            $whereConditionSql = 'a.usergroup_id = ? AND access_url_id = ? ';
221
            $whereConditionValues = [$id, $urlId];
222
        } else {
223
            $whereConditionSql = 'usergroup_id = ?';
224
            $whereConditionValues = [$id];
225
            $from = $this->usergroup_rel_course_table." c ";
226
        }
227
228
        if ($loadCourseData) {
229
            $from .= " INNER JOIN {$this->table_course} as course ON c.course_id = course.id";
230
        }
231
232
        /*
233
        if (!empty($conditionsLike)) {
234
            $from .= " INNER JOIN {$this->table_course} as course ON c.course_id = course.id";
235
            $conditionSql = [];
236
            foreach ($conditionsLike as $field => $value) {
237
                $conditionSql[] = $field.' LIKE %?%';
238
                $whereConditionValues[] = $value;
239
            }
240
            $whereConditionSql .= ' AND '.implode(' AND ', $conditionSql);
241
        }*/
242
243
        $where = ['where' => [$whereConditionSql => $whereConditionValues]];
244
245
        if ($loadCourseData) {
246
            $select = 'course.*';
247
        } else {
248
            $select = 'course_id';
249
        }
250
251
        $results = Database::select(
252
            $select,
253
            $from,
254
            $where
255
        );
256
257
        $array = [];
258
        if (!empty($results)) {
259
            foreach ($results as $row) {
260
                if ($loadCourseData) {
261
                    $array[$row['id']] = $row;
262
                } else {
263
                    $array[] = $row['course_id'];
264
                }
265
            }
266
        }
267
268
        return $array;
269
    }
270
271
    /**
272
     * @param array $options
273
     *
274
     * @return array
275
     */
276
    public function getUserGroupInCourse($options = [], $type = -1)
277
    {
278
        if ($this->useMultipleUrl) {
279
            $sql = "SELECT u.* FROM {$this->usergroup_rel_course_table} usergroup
280
                    INNER JOIN  {$this->table} u
281
                    ON (u.id = usergroup.usergroup_id)
282
                    INNER JOIN {$this->table_course} c
283
                    ON (usergroup.course_id = c.id)
284
                    INNER JOIN {$this->access_url_rel_usergroup} a
285
                    ON (a.usergroup_id = u.id)
286
                   ";
287
        } else {
288
            $sql = "SELECT u.* FROM {$this->usergroup_rel_course_table} usergroup
289
                    INNER JOIN  {$this->table} u
290
                    ON (u.id = usergroup.usergroup_id)
291
                    INNER JOIN {$this->table_course} c
292
                    ON (usergroup.course_id = c.id)
293
                   ";
294
        }
295
296
        $conditions = Database::parse_conditions($options);
297
298
        $typeCondition = '';
299
        if ($type != -1) {
300
            $type = intval($type);
301
            $typeCondition = " AND group_type = $type ";
302
        }
303
304
        if (empty($conditions)) {
305
            $conditions .= "WHERE 1 = 1 $typeCondition ";
306
        } else {
307
            $conditions .= " $typeCondition ";
308
        }
309
310
        $sql .= $conditions;
311
312
        if ($this->useMultipleUrl) {
313
            $urlId = api_get_current_access_url_id();
314
            $sql .= " AND access_url_id = $urlId ";
315
        }
316
317
318
        if (isset($options['LIMIT'])) {
319
            $limits = explode(',', $options['LIMIT']);
320
            $limits = array_map('intval', $limits);
321
            if (isset($limits[0]) && isset($limits[1])) {
322
                $sql .= " LIMIT ".$limits[0].', '.$limits[1];
323
            }
324
        }
325
326
        $result = Database::query($sql);
327
        $array = Database::store_result($result, 'ASSOC');
328
329
        return $array;
330
    }
331
332
    /**
333
     * @param array $options
334
     * @param int   $type
335
     *
336
     * @return array|bool
337
     */
338
    public function getUserGroupNotInCourse($options = [], $type = -1)
339
    {
340
        $course_id = null;
341
        if (isset($options['course_id'])) {
342
            $course_id = intval($options['course_id']);
343
            unset($options['course_id']);
344
        }
345
346
        if (empty($course_id)) {
347
            return false;
348
        }
349
350
        $typeCondition = '';
351
        if ($type != -1) {
352
            $type = intval($type);
353
            $typeCondition = " AND group_type = $type ";
354
        }
355
356
        if ($this->useMultipleUrl) {
357
            $urlId = api_get_current_access_url_id();
358
            $sql = "SELECT DISTINCT u.*
359
                    FROM {$this->table} u
360
                    INNER JOIN {$this->access_url_rel_usergroup} a
361
                    ON (a.usergroup_id = u.id)
362
                    LEFT OUTER JOIN {$this->usergroup_rel_course_table} urc
363
                    ON (u.id = urc.usergroup_id AND course_id = $course_id)
364
            ";
365
        } else {
366
            $sql = "SELECT DISTINCT u.*
367
                    FROM {$this->table} u
368
                    LEFT OUTER JOIN {$this->usergroup_rel_course_table} urc
369
                    ON (u.id = urc.usergroup_id AND course_id = $course_id)
370
            ";
371
        }
372
        $conditions = Database::parse_conditions($options);
373
374
        if (empty($conditions)) {
375
            $conditions .= "WHERE 1 = 1 $typeCondition ";
376
        } else {
377
            $conditions .= " $typeCondition ";
378
        }
379
380
        $sql .= $conditions;
381
382
        if ($this->useMultipleUrl) {
383
            $sql .= " AND access_url_id = $urlId";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $urlId does not seem to be defined for all execution paths leading up to this point.
Loading history...
384
        }
385
386
        if (isset($options['LIMIT'])) {
387
            $limits = explode(',', $options['LIMIT']);
388
            $limits = array_map('intval', $limits);
389
            if (isset($limits[0]) && isset($limits[1])) {
390
                $sql .= " LIMIT ".$limits[0].', '.$limits[1];
391
            }
392
        }
393
394
        $result = Database::query($sql);
395
        $array = Database::store_result($result, 'ASSOC');
396
397
        return $array;
398
    }
399
400
    /**
401
     * @param int $course_id
402
     * @return array
403
     */
404
    public function get_usergroup_by_course($course_id)
405
    {
406
        if ($this->useMultipleUrl) {
407
            $urlId = api_get_current_access_url_id();
408
            $options = [
409
                'where' => [
410
                    'c.course_id = ? AND access_url_id = ?' => [
411
                        $course_id,
412
                        $urlId,
413
                    ],
414
                ],
415
            ];
416
            $from = $this->usergroup_rel_course_table." as c INNER JOIN ".$this->access_url_rel_usergroup." a
417
                    ON c.usergroup_id = a.usergroup_id";
418
        } else {
419
            $options = ['where' => ['c.course_id = ?' => $course_id]];
420
            $from = $this->usergroup_rel_course_table." c";
421
        }
422
423
        $results = Database::select('c.usergroup_id', $from, $options);
424
        $array = [];
425
        if (!empty($results)) {
426
            foreach ($results as $row) {
427
                $array[] = $row['usergroup_id'];
428
            }
429
        }
430
431
        return $array;
432
    }
433
434
    /**
435
     * @param int $usergroup_id
436
     * @param int $course_id
437
     * @return bool
438
     */
439
    public function usergroup_was_added_in_course($usergroup_id, $course_id)
440
    {
441
        $results = Database::select(
442
            'usergroup_id',
443
            $this->usergroup_rel_course_table,
444
            ['where' => ['course_id = ? AND usergroup_id = ?' => [$course_id, $usergroup_id]]]
445
        );
446
447
        if (empty($results)) {
448
            return false;
449
        }
450
451
        return true;
452
    }
453
454
    /**
455
     * Gets a list of session ids by user group
456
     * @param   int  $id   user group id
457
     * @return  array
458
     */
459
    public function get_sessions_by_usergroup($id)
460
    {
461
        $results = Database::select(
462
            'session_id',
463
            $this->usergroup_rel_session_table,
464
            ['where' => ['usergroup_id = ?' => $id]]
465
        );
466
467
        $array = [];
468
        if (!empty($results)) {
469
            foreach ($results as $row) {
470
                $array[] = $row['session_id'];
471
            }
472
        }
473
474
        return $array;
475
    }
476
477
    /**
478
     * Gets a list of user ids by user group
479
     * @param   int    $id user group id
480
     * @return  array   with a list of user ids
481
     */
482
    public function get_users_by_usergroup($id = null, $relationList = [])
483
    {
484
        $relationCondition = '';
485
        if (!empty($relationList)) {
486
            $relationConditionArray = [];
487
            foreach ($relationList as $relation) {
488
                $relation = (int) $relation;
489
                if (empty($relation)) {
490
                    $relationConditionArray[] = " (relation_type = 0 OR relation_type IS NULL OR relation_type = '') ";
491
                } else {
492
                    $relationConditionArray[] = " relation_type = $relation ";
493
                }
494
            }
495
            $relationCondition = " AND ( ";
496
            $relationCondition .= implode("AND", $relationConditionArray);
497
            $relationCondition .= " ) ";
498
        }
499
500
        if (empty($id)) {
501
            $conditions = [];
502
        } else {
503
            $conditions = ['where' => ["usergroup_id = ? $relationCondition "=> $id]];
504
        }
505
506
        $results = Database::select(
507
            'user_id',
508
            $this->usergroup_rel_user_table,
509
            $conditions
510
        );
511
        $array = [];
512
        if (!empty($results)) {
513
            foreach ($results as $row) {
514
                $array[] = $row['user_id'];
515
            }
516
        }
517
        return $array;
518
    }
519
520
    /**
521
     * Gets a list of user ids by user group
522
     * @param   int    $id user group id
523
     * @param int $relation
524
     * @return  array   with a list of user ids
525
     */
526
    public function getUsersByUsergroupAndRelation($id, $relation = 0)
527
    {
528
        $relation = (int) $relation;
529
        if (empty($relation)) {
530
            $conditions = ['where' => ['usergroup_id = ? AND (relation_type = 0 OR relation_type IS NULL OR relation_type = "") ' => [$id]]];
531
        } else {
532
            $conditions = ['where' => ['usergroup_id = ? AND relation_type = ?' => [$id, $relation]]];
533
        }
534
535
        $results = Database::select(
536
            'user_id',
537
            $this->usergroup_rel_user_table,
538
            $conditions
539
        );
540
541
        $array = [];
542
        if (!empty($results)) {
543
            foreach ($results as $row) {
544
                $array[] = $row['user_id'];
545
            }
546
        }
547
548
        return $array;
549
    }
550
551
    /**
552
     * Get the group list for a user
553
     * @param int $userId The user ID
554
     * @param int $filterByType Optional. The type of group
555
     * @return array
556
     */
557
    public function getUserGroupListByUser($userId, $filterByType = null)
558
    {
559
        $userId = (int) $userId;
560
        if ($this->useMultipleUrl) {
561
            $urlId = api_get_current_access_url_id();
562
            $from = $this->usergroup_rel_user_table." u
563
                INNER JOIN {$this->access_url_rel_usergroup} a
564
                ON (a.usergroup_id AND u.usergroup_id)
565
                INNER JOIN {$this->table} g
566
                ON (u.usergroup_id = g.id)
567
                ";
568
            $where = ['where' => ['user_id = ? AND access_url_id = ? ' => [$userId, $urlId]]];
569
        } else {
570
            $from = $this->usergroup_rel_user_table." u
571
                INNER JOIN {$this->table} g
572
                ON (u.usergroup_id = g.id)
573
                ";
574
            $where = ['where' => ['user_id = ?' => $userId]];
575
        }
576
577
        if ($filterByType !== null) {
578
            $where['where'][' AND g.group_type = ?'] = (int) $filterByType;
579
        }
580
581
        $results = Database::select(
582
            'g.*',
583
            $from,
584
            $where
585
        );
586
        $array = [];
587
        if (!empty($results)) {
588
            foreach ($results as $row) {
589
                $array[] = $row;
590
            }
591
        }
592
593
        return $array;
594
    }
595
596
    /**
597
     * Gets the usergroup id list by user id
598
     * @param   int $userId user id
599
     * @return array
600
     */
601
    public function get_usergroup_by_user($userId)
602
    {
603
        $userId = (int) $userId;
604
        if ($this->useMultipleUrl) {
605
            $urlId = api_get_current_access_url_id();
606
            $from = $this->usergroup_rel_user_table." u
607
                    INNER JOIN {$this->access_url_rel_usergroup} a ON (a.usergroup_id AND u.usergroup_id)";
608
            $where = ['where' => ['user_id = ? AND access_url_id = ? ' => [$userId, $urlId]]];
609
        } else {
610
            $from = $this->usergroup_rel_user_table." u ";
611
            $where = ['where' => ['user_id = ?' => $userId]];
612
        }
613
614
        $results = Database::select(
615
            'u.usergroup_id',
616
            $from,
617
            $where
618
        );
619
620
        $array = [];
621
        if (!empty($results)) {
622
            foreach ($results as $row) {
623
                $array[] = $row['usergroup_id'];
624
            }
625
        }
626
627
        return $array;
628
    }
629
630
    /**
631
     * Subscribes sessions to a group  (also adding the members of the group in the session and course)
632
     * @param   int $usergroup_id usergroup id
633
     * @param   array $list list of session ids
634
     * @param bool $deleteCurrentSessions Optional. Empty the session list for the usergroup (class)
635
     */
636
    public function subscribe_sessions_to_usergroup($usergroup_id, $list, $deleteCurrentSessions = true)
637
    {
638
        $current_list = self::get_sessions_by_usergroup($usergroup_id);
0 ignored issues
show
Bug Best Practice introduced by
The method UserGroup::get_sessions_by_usergroup() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

638
        /** @scrutinizer ignore-call */ 
639
        $current_list = self::get_sessions_by_usergroup($usergroup_id);
Loading history...
639
        $user_list = self::get_users_by_usergroup($usergroup_id);
0 ignored issues
show
Bug Best Practice introduced by
The method UserGroup::get_users_by_usergroup() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

639
        /** @scrutinizer ignore-call */ 
640
        $user_list = self::get_users_by_usergroup($usergroup_id);
Loading history...
640
641
        $delete_items = $new_items = [];
642
        if (!empty($list)) {
643
            foreach ($list as $session_id) {
644
                if (!in_array($session_id, $current_list)) {
645
                    $new_items[] = $session_id;
646
                }
647
            }
648
        }
649
        if ($deleteCurrentSessions) {
650
            if (!empty($current_list)) {
651
                foreach ($current_list as $session_id) {
652
                    if (!in_array($session_id, $list)) {
653
                        $delete_items[] = $session_id;
654
                    }
655
                }
656
            }
657
658
            // Deleting items
659
            if (!empty($delete_items)) {
660
                foreach ($delete_items as $session_id) {
661
                    if (!empty($user_list)) {
662
                        foreach ($user_list as $user_id) {
663
                            SessionManager::unsubscribe_user_from_session($session_id, $user_id);
664
                        }
665
                    }
666
                    Database::delete(
667
                        $this->usergroup_rel_session_table,
668
                        ['usergroup_id = ? AND session_id = ?' => [$usergroup_id, $session_id]]
669
                    );
670
                }
671
            }
672
        }
673
674
        // Adding new relationships.
675
        if (!empty($new_items)) {
676
            foreach ($new_items as $session_id) {
677
                $params = ['session_id' => $session_id, 'usergroup_id' => $usergroup_id];
678
                Database::insert($this->usergroup_rel_session_table, $params);
679
680
                if (!empty($user_list)) {
681
                    SessionManager::subscribe_users_to_session(
682
                        $session_id,
683
                        $user_list,
684
                        null,
685
                        false
686
                    );
687
                }
688
            }
689
        }
690
    }
691
692
    /**
693
     * Subscribes courses to a group (also adding the members of the group in the course)
694
     * @param int   $usergroup_id  usergroup id
695
     * @param array $list  list of course ids (integers)
696
     * @param bool $delete_groups
697
     */
698
    public function subscribe_courses_to_usergroup($usergroup_id, $list, $delete_groups = true)
699
    {
700
        $current_list = self::get_courses_by_usergroup($usergroup_id);
0 ignored issues
show
Bug Best Practice introduced by
The method UserGroup::get_courses_by_usergroup() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

700
        /** @scrutinizer ignore-call */ 
701
        $current_list = self::get_courses_by_usergroup($usergroup_id);
Loading history...
701
        $user_list = self::get_users_by_usergroup($usergroup_id);
0 ignored issues
show
Bug Best Practice introduced by
The method UserGroup::get_users_by_usergroup() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

701
        /** @scrutinizer ignore-call */ 
702
        $user_list = self::get_users_by_usergroup($usergroup_id);
Loading history...
702
703
        $delete_items = $new_items = [];
704
        if (!empty($list)) {
705
            foreach ($list as $id) {
706
                if (!in_array($id, $current_list)) {
707
                    $new_items[] = $id;
708
                }
709
            }
710
        }
711
712
        if (!empty($current_list)) {
713
            foreach ($current_list as $id) {
714
                if (!in_array($id, $list)) {
715
                    $delete_items[] = $id;
716
                }
717
            }
718
        }
719
720
        if ($delete_groups) {
721
            self::unsubscribe_courses_from_usergroup($usergroup_id, $delete_items);
0 ignored issues
show
Bug Best Practice introduced by
The method UserGroup::unsubscribe_courses_from_usergroup() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

721
            self::/** @scrutinizer ignore-call */ 
722
                  unsubscribe_courses_from_usergroup($usergroup_id, $delete_items);
Loading history...
722
        }
723
724
        // Adding new relationships
725
        if (!empty($new_items)) {
726
            foreach ($new_items as $course_id) {
727
                $course_info = api_get_course_info_by_id($course_id);
728
                if ($course_info) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $course_info of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
729
                    if (!empty($user_list)) {
730
                        foreach ($user_list as $user_id) {
731
                            CourseManager::subscribe_user(
732
                                $user_id,
733
                                $course_info['code']
734
                            );
735
                        }
736
                    }
737
                    $params = [
738
                        'course_id' => $course_id,
739
                        'usergroup_id' => $usergroup_id,
740
                    ];
741
                    Database::insert(
742
                        $this->usergroup_rel_course_table,
743
                        $params
744
                    );
745
                }
746
            }
747
        }
748
    }
749
750
    /**
751
     * @param int $usergroup_id
752
     * @param array $delete_items
753
     */
754
    public function unsubscribe_courses_from_usergroup($usergroup_id, $delete_items)
755
    {
756
        // Deleting items.
757
        if (!empty($delete_items)) {
758
            $user_list = self::get_users_by_usergroup($usergroup_id);
0 ignored issues
show
Bug Best Practice introduced by
The method UserGroup::get_users_by_usergroup() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

758
            /** @scrutinizer ignore-call */ 
759
            $user_list = self::get_users_by_usergroup($usergroup_id);
Loading history...
759
760
            foreach ($delete_items as $course_id) {
761
                $course_info = api_get_course_info_by_id($course_id);
762
                if ($course_info) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $course_info of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
763
                    if (!empty($user_list)) {
764
                        foreach ($user_list as $user_id) {
765
                            CourseManager::unsubscribe_user(
766
                                $user_id,
767
                                $course_info['code']
768
                            );
769
                        }
770
                    }
771
772
                    Database::delete(
773
                        $this->usergroup_rel_course_table,
774
                        [
775
                            'usergroup_id = ? AND course_id = ?' => [
776
                                $usergroup_id,
777
                                $course_id
778
                            ]
779
                        ]
780
                    );
781
                }
782
            }
783
        }
784
    }
785
786
    /**
787
     * Subscribe users to a group
788
     * @param int $usergroup_id usergroup id
789
     * @param array $list list of user ids
790
     * @param bool $delete_users_not_present_in_list
791
     * @param int $relationType
792
     */
793
    public function subscribe_users_to_usergroup(
794
        $usergroup_id,
795
        $list,
796
        $delete_users_not_present_in_list = true,
797
        $relationType = 0
798
    ) {
799
        $current_list = self::get_users_by_usergroup($usergroup_id);
0 ignored issues
show
Bug Best Practice introduced by
The method UserGroup::get_users_by_usergroup() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

799
        /** @scrutinizer ignore-call */ 
800
        $current_list = self::get_users_by_usergroup($usergroup_id);
Loading history...
800
        $course_list = self::get_courses_by_usergroup($usergroup_id);
0 ignored issues
show
Bug Best Practice introduced by
The method UserGroup::get_courses_by_usergroup() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

800
        /** @scrutinizer ignore-call */ 
801
        $course_list = self::get_courses_by_usergroup($usergroup_id);
Loading history...
801
        $session_list = self::get_sessions_by_usergroup($usergroup_id);
0 ignored issues
show
Bug Best Practice introduced by
The method UserGroup::get_sessions_by_usergroup() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

801
        /** @scrutinizer ignore-call */ 
802
        $session_list = self::get_sessions_by_usergroup($usergroup_id);
Loading history...
802
        $session_list =  array_filter($session_list);
803
        $relationType = (int) $relationType;
804
805
        $delete_items = [];
806
        $new_items = [];
807
808
        if (!empty($list)) {
809
            foreach ($list as $user_id) {
810
                if (!in_array($user_id, $current_list)) {
811
                    $new_items[] = $user_id;
812
                }
813
            }
814
        }
815
816
        if (!empty($current_list)) {
817
            foreach ($current_list as $user_id) {
818
                if (!in_array($user_id, $list)) {
819
                    $delete_items[] = $user_id;
820
                }
821
            }
822
        }
823
824
        // Deleting items
825
        if (!empty($delete_items) && $delete_users_not_present_in_list) {
826
            foreach ($delete_items as $user_id) {
827
                // Removing courses
828
                if (!empty($course_list)) {
829
                    foreach ($course_list as $course_id) {
830
                        $course_info = api_get_course_info_by_id($course_id);
831
                        CourseManager::unsubscribe_user($user_id, $course_info['code']);
832
                    }
833
                }
834
                // Removing sessions
835
                if (!empty($session_list)) {
836
                    foreach ($session_list as $session_id) {
837
                        SessionManager::unsubscribe_user_from_session($session_id, $user_id);
838
                    }
839
                }
840
841
                if (empty($relationType)) {
842
                    Database::delete(
843
                        $this->usergroup_rel_user_table,
844
                        [
845
                            'usergroup_id = ? AND user_id = ? AND (relation_type = "0" OR relation_type IS NULL OR relation_type = "")' => [
846
                                $usergroup_id,
847
                                $user_id,
848
                            ],
849
                        ]
850
                    );
851
                } else {
852
                    Database::delete(
853
                        $this->usergroup_rel_user_table,
854
                        [
855
                            'usergroup_id = ? AND user_id = ? AND relation_type = ?' => [
856
                                $usergroup_id,
857
                                $user_id,
858
                                $relationType,
859
                            ],
860
                        ]
861
                    );
862
                }
863
            }
864
        }
865
866
        // Adding new relationships
867
        if (!empty($new_items)) {
868
            // Adding sessions
869
            if (!empty($session_list)) {
870
                foreach ($session_list as $session_id) {
871
                    SessionManager::subscribe_users_to_session($session_id, $new_items, null, false);
872
                }
873
            }
874
875
            foreach ($new_items as $user_id) {
876
                // Adding courses
877
                if (!empty($course_list)) {
878
                    foreach ($course_list as $course_id) {
879
                        $course_info = api_get_course_info_by_id($course_id);
880
                        CourseManager::subscribe_user($user_id, $course_info['code']);
881
                    }
882
                }
883
                $params = [
884
                    'user_id' => $user_id,
885
                    'usergroup_id' => $usergroup_id,
886
                    'relation_type' => $relationType,
887
                ];
888
                Database::insert($this->usergroup_rel_user_table, $params);
889
            }
890
        }
891
    }
892
893
    /**
894
     * @param string $name
895
     * @return bool
896
     */
897
    public function usergroup_exists($name)
898
    {
899
        $name = Database::escape_string($name);
900
        if ($this->useMultipleUrl) {
901
            $urlId = api_get_current_access_url_id();
902
            $sql = "SELECT * FROM $this->table u
903
                    INNER JOIN {$this->access_url_rel_usergroup} a 
904
                    ON (a.usergroup_id = u.id)
905
                    WHERE name = '".$name."' AND access_url_id = $urlId";
906
        } else {
907
            $sql = "SELECT * FROM $this->table WHERE name = '".$name."'";
908
        }
909
        $res = Database::query($sql);
910
911
        return Database::num_rows($res) != 0;
912
    }
913
914
    /**
915
     * @param int $sidx
916
     * @param int $sord
917
     * @param int $start
918
     * @param int $limit
919
     * @return array
920
     */
921
    public function getUsergroupsPagination($sidx, $sord, $start, $limit)
922
    {
923
        $sord = in_array(strtolower($sord), ['asc', 'desc']) ? $sord : 'desc';
924
925
        $start = intval($start);
926
        $limit = intval($limit);
927
        if ($this->useMultipleUrl) {
928
            $urlId = api_get_current_access_url_id();
929
            $from = $this->table." u INNER JOIN {$this->access_url_rel_usergroup} a ON (u.id = a.usergroup_id)";
930
            $where = [' access_url_id = ?' => $urlId];
931
        } else {
932
            $from = $this->table." u ";
933
            $where = [];
934
        }
935
936
        $result = Database::select(
937
            'u.*',
938
            $from,
939
            [
940
                'where' => $where,
941
                'order' => "name $sord",
942
                'LIMIT' => "$start , $limit"
943
            ]
944
        );
945
946
        $new_result = [];
947
        if (!empty($result)) {
948
            foreach ($result as $group) {
949
                $group['sessions'] = count($this->get_sessions_by_usergroup($group['id']));
950
                $group['courses'] = count($this->get_courses_by_usergroup($group['id']));
951
952
                switch ($group['group_type']) {
953
                    case 0:
954
                        $group['group_type'] = Display::label(get_lang('Class'), 'info');
955
                        $roles = [0];
956
                        break;
957
                    case 1:
958
                        $group['group_type'] = Display::label(get_lang('Social'), 'success');
959
                        $roles = [
960
                            GROUP_USER_PERMISSION_ADMIN,
961
                            GROUP_USER_PERMISSION_READER,
962
                            GROUP_USER_PERMISSION_MODERATOR,
963
                            GROUP_USER_PERMISSION_HRM
964
                        ];
965
                        break;
966
                }
967
                $group['users'] = count($this->get_users_by_usergroup($group['id'], $roles));
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $roles does not seem to be defined for all execution paths leading up to this point.
Loading history...
968
                $new_result[] = $group;
969
            }
970
            $result = $new_result;
971
        }
972
        $columns = ['name', 'users', 'courses', 'sessions', 'group_type'];
973
974
        if (!in_array($sidx, $columns)) {
975
            $sidx = 'name';
976
        }
977
978
        // Multidimensional sort
979
        $result = msort($result, $sidx, $sord);
0 ignored issues
show
Bug introduced by
It seems like $result can also be of type array and array; however, parameter $array of msort() does only seem to accept unsorted, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

979
        $result = msort(/** @scrutinizer ignore-type */ $result, $sidx, $sord);
Loading history...
980
981
        return $result;
982
    }
983
984
    /**
985
     * @param array $options
986
     * @return array
987
     */
988
    public function getDataToExport($options = [])
989
    {
990
        if ($this->useMultipleUrl) {
991
            $urlId = api_get_current_access_url_id();
992
            $from = $this->table." u INNER JOIN {$this->access_url_rel_usergroup} a
993
                    ON (u.id = a.usergroup_id)";
994
            $options = ['where' => ['access_url_id = ? ' => $urlId]];
995
            $classes = Database::select('a.id, name, description', $from, $options);
996
        } else {
997
            $classes = Database::select('id, name, description', $this->table, $options);
998
        }
999
1000
        $result = [];
1001
        if (!empty($classes)) {
1002
            foreach ($classes as $data) {
1003
                $users = self::getUserListByUserGroup($data['id']);
0 ignored issues
show
Bug Best Practice introduced by
The method UserGroup::getUserListByUserGroup() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1003
                /** @scrutinizer ignore-call */ 
1004
                $users = self::getUserListByUserGroup($data['id']);
Loading history...
1004
                $userToString = null;
1005
                if (!empty($users)) {
1006
                    $userNameList = [];
1007
                    foreach ($users as $userData) {
1008
                        $userNameList[] = $userData['username'];
1009
                    }
1010
                    $userToString = implode(',', $userNameList);
1011
                }
1012
                $data['users'] = $userToString;
1013
                $result[] = $data;
1014
            }
1015
        }
1016
1017
        return $result;
1018
    }
1019
1020
    /**
1021
     * @param string $firstLetter
1022
     * @return array
1023
     */
1024
    public function filterByFirstLetter($firstLetter)
1025
    {
1026
        $firstLetter = Database::escape_string($firstLetter);
1027
        $sql = "SELECT id, name FROM $this->table
1028
		        WHERE
1029
		            name LIKE '".$firstLetter."%' OR
1030
		            name LIKE '".api_strtolower($firstLetter)."%'
1031
		        ORDER BY name DESC ";
1032
1033
        $result = Database::query($sql);
1034
        return Database::store_result($result);
1035
    }
1036
1037
    /**
1038
     * Select user group not in list
1039
     * @param array $list
1040
     * @return array
1041
     */
1042
    public function getUserGroupNotInList($list)
1043
    {
1044
        if (empty($list)) {
1045
            return [];
1046
        }
1047
1048
        $list = array_map('intval', $list);
1049
        $listToString = implode("','", $list);
1050
1051
        $sql = "SELECT * FROM {$this->table} WHERE id NOT IN ('$listToString')";
1052
        $result = Database::query($sql);
1053
        return Database::store_result($result, 'ASSOC');
1054
    }
1055
1056
    /**
1057
     * @param $params
1058
     * @param bool $show_query
1059
     * @return bool|int
1060
     */
1061
    public function save($params, $show_query = false)
1062
    {
1063
        $params['updated_at'] = $params['created_at'] = api_get_utc_datetime();
1064
        $params['group_type'] = isset($params['group_type']) ? self::SOCIAL_CLASS : self::NORMAL_CLASS;
1065
        $params['allow_members_leave_group'] = isset($params['allow_members_leave_group']) ? 1 : 0;
1066
1067
        $groupExists = $this->usergroup_exists(trim($params['name']));
1068
        if ($groupExists == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
1069
            $id = parent::save($params, $show_query);
1070
            if ($id) {
1071
                if ($this->useMultipleUrl) {
1072
                    $this->subscribeToUrl($id, api_get_current_access_url_id());
1073
                }
1074
1075
                if ($params['group_type'] == self::SOCIAL_CLASS) {
1076
                    $this->add_user_to_group(
1077
                        api_get_user_id(),
1078
                        $id,
1079
                        $params['group_type']
1080
                    );
1081
                }
1082
                $picture = isset($_FILES['picture']) ? $_FILES['picture'] : null;
1083
                $picture = $this->manageFileUpload($id, $picture);
1084
                if ($picture) {
1085
                    $params = [
1086
                        'id' => $id,
1087
                        'picture' => $picture,
1088
                        'group_type' => $params['group_type']
1089
                    ];
1090
                    $this->update($params);
1091
                }
1092
            }
1093
1094
            return $id;
1095
        }
1096
1097
        return false;
1098
    }
1099
1100
    /**
1101
     * @inheritdoc
1102
     */
1103
    public function update($values, $showQuery = false)
1104
    {
1105
        $values['updated_on'] = api_get_utc_datetime();
1106
        $values['group_type'] = isset($values['group_type']) ? self::SOCIAL_CLASS : self::NORMAL_CLASS;
1107
        $values['allow_members_leave_group'] = isset($values['allow_members_leave_group']) ? 1 : 0;
1108
1109
        if (isset($values['id'])) {
1110
            $picture = isset($_FILES['picture']) ? $_FILES['picture'] : null;
1111
            if (!empty($picture)) {
1112
                $picture = $this->manageFileUpload($values['id'], $picture);
1113
                if ($picture) {
1114
                    $values['picture'] = $picture;
1115
                }
1116
            }
1117
1118
            if (isset($values['delete_picture'])) {
1119
                $values['picture'] = null;
1120
            }
1121
        }
1122
1123
        parent::update($values, $showQuery);
1124
1125
        if (isset($values['delete_picture'])) {
1126
            $this->delete_group_picture($values['id']);
1127
        }
1128
1129
        return true;
1130
    }
1131
1132
    /**
1133
     * @param int    $groupId
1134
     * @param string $picture
1135
     *
1136
     * @return bool|string
1137
     */
1138
    public function manageFileUpload($groupId, $picture)
1139
    {
1140
        if (!empty($picture['name'])) {
1141
            return $this->update_group_picture(
1142
                $groupId,
1143
                $picture['name'],
1144
                $picture['tmp_name']
1145
            );
1146
        }
1147
        return false;
1148
    }
1149
1150
    /**
1151
     * @param $group_id
1152
     * @return string
1153
     */
1154
    public function delete_group_picture($group_id)
1155
    {
1156
        return self::update_group_picture($group_id);
0 ignored issues
show
Bug Best Practice introduced by
The method UserGroup::update_group_picture() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1156
        return self::/** @scrutinizer ignore-call */ update_group_picture($group_id);
Loading history...
Bug Best Practice introduced by
The expression return self::update_group_picture($group_id) could also return false which is incompatible with the documented return type string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
1157
    }
1158
1159
    /**
1160
     * Creates new group pictures in various sizes of a user, or deletes user pfotos.
1161
     * Note: This method relies on configuration setting from main/inc/conf/profile.conf.php
1162
     * @param    int    The group id
1163
     * @param    string $file The common file name for the newly created photos.
1164
     * It will be checked and modified for compatibility with the file system.
1165
     * If full name is provided, path component is ignored.
1166
     * If an empty name is provided, then old user photos are deleted only,
1167
     * @see UserManager::delete_user_picture() as the prefered way for deletion.
1168
     * @param    string $source_file The full system name of the image from which user photos will be created.
1169
     * @return   mixed    Returns the resulting common file name of created images which usually should be stored in database.
1170
     * When an image is removed the function returns an empty string. In case of internal error or negative validation it returns FALSE.
1171
     */
1172
    public function update_group_picture($group_id, $file = null, $source_file = null)
1173
    {
1174
        // Validation 1.
1175
        if (empty($group_id)) {
1176
            return false;
1177
        }
1178
        $delete = empty($file);
1179
        if (empty($source_file)) {
1180
            $source_file = $file;
1181
        }
1182
1183
        // User-reserved directory where photos have to be placed.
1184
        $path_info = self::get_group_picture_path_by_id($group_id, 'system', true);
0 ignored issues
show
Bug Best Practice introduced by
The method UserGroup::get_group_picture_path_by_id() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1184
        /** @scrutinizer ignore-call */ 
1185
        $path_info = self::get_group_picture_path_by_id($group_id, 'system', true);
Loading history...
1185
1186
        $path = $path_info['dir'];
1187
1188
        // If this directory does not exist - we create it.
1189
        if (!file_exists($path)) {
1190
            @mkdir($path, api_get_permissions_for_new_directories(), true);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for mkdir(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

1190
            /** @scrutinizer ignore-unhandled */ @mkdir($path, api_get_permissions_for_new_directories(), true);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1191
        }
1192
1193
        // The old photos (if any).
1194
        $old_file = $path_info['file'];
1195
1196
        // Let us delete them.
1197
        if (!empty($old_file)) {
1198
            if (KEEP_THE_OLD_IMAGE_AFTER_CHANGE) {
1199
                $prefix = 'saved_'.date('Y_m_d_H_i_s').'_'.uniqid('').'_';
1200
                @rename($path.'small_'.$old_file, $path.$prefix.'small_'.$old_file);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for rename(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

1200
                /** @scrutinizer ignore-unhandled */ @rename($path.'small_'.$old_file, $path.$prefix.'small_'.$old_file);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1201
                @rename($path.'medium_'.$old_file, $path.$prefix.'medium_'.$old_file);
1202
                @rename($path.'big_'.$old_file, $path.$prefix.'big_'.$old_file);
1203
                @rename($path.$old_file, $path.$prefix.$old_file);
1204
            } else {
1205
                @unlink($path.'small_'.$old_file);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

1205
                /** @scrutinizer ignore-unhandled */ @unlink($path.'small_'.$old_file);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1206
                @unlink($path.'medium_'.$old_file);
1207
                @unlink($path.'big_'.$old_file);
1208
                @unlink($path.$old_file);
1209
            }
1210
        }
1211
1212
        // Exit if only deletion has been requested. Return an empty picture name.
1213
        if ($delete) {
1214
            return '';
1215
        }
1216
1217
        // Validation 2.
1218
        $allowed_types = ['jpg', 'jpeg', 'png', 'gif'];
1219
        $file = str_replace('\\', '/', $file);
1220
        $filename = (($pos = strrpos($file, '/')) !== false) ? substr($file, $pos + 1) : $file;
1221
        $extension = strtolower(substr(strrchr($filename, '.'), 1));
1222
        if (!in_array($extension, $allowed_types)) {
1223
            return false;
1224
        }
1225
1226
        // This is the common name for the new photos.
1227
        if (KEEP_THE_NAME_WHEN_CHANGE_IMAGE && !empty($old_file)) {
1228
            $old_extension = strtolower(substr(strrchr($old_file, '.'), 1));
1229
            $filename = in_array($old_extension, $allowed_types) ? substr($old_file, 0, -strlen($old_extension)) : $old_file;
1230
            $filename = (substr($filename, -1) == '.') ? $filename.$extension : $filename.'.'.$extension;
1231
        } else {
1232
            $filename = api_replace_dangerous_char($filename);
1233
            if (PREFIX_IMAGE_FILENAME_WITH_UID) {
1234
                $filename = uniqid('').'_'.$filename;
1235
            }
1236
            // We always prefix user photos with user ids, so on setting
1237
            // api_get_setting('split_users_upload_directory') === 'true'
1238
            // the correspondent directories to be found successfully.
1239
            $filename = $group_id.'_'.$filename;
1240
        }
1241
1242
        // Storing the new photos in 4 versions with various sizes.
1243
1244
        /*$image->resize(
1245
        // get original size and set width (widen) or height (heighten).
1246
        // width or height will be set maintaining aspect ratio.
1247
            $image->getSize()->widen( 700 )
1248
        );*/
1249
1250
        // Usign the Imagine service
1251
        $imagine = new Imagine\Gd\Imagine();
1252
        $image = $imagine->open($source_file);
1253
1254
        $options = [
1255
            'quality' => 90,
1256
        ];
1257
1258
        //$image->resize(new Imagine\Image\Box(200, 200))->save($path.'big_'.$filename);
1259
        $image->resize($image->getSize()->widen(200))->save($path.'big_'.$filename, $options);
1260
1261
        $image = $imagine->open($source_file);
1262
        $image->resize(new Imagine\Image\Box(85, 85))->save($path.'medium_'.$filename, $options);
1263
1264
        $image = $imagine->open($source_file);
1265
        $image->resize(new Imagine\Image\Box(22, 22))->save($path.'small_'.$filename);
1266
1267
        /*
1268
        $small  = self::resize_picture($source_file, 22);
1269
        $medium = self::resize_picture($source_file, 85);
1270
        $normal = self::resize_picture($source_file, 200);
1271
1272
        $big = new Image($source_file); // This is the original picture.
1273
        $ok = $small && $small->send_image($path.'small_'.$filename)
1274
            && $medium && $medium->send_image($path.'medium_'.$filename)
1275
            && $normal && $normal->send_image($path.'big_'.$filename)
1276
            && $big && $big->send_image($path.$filename);
1277
        return $ok ? $filename : false;*/
1278
        return $filename;
1279
    }
1280
1281
    /**
1282
     * @return mixed
1283
     */
1284
    public function getGroupType()
1285
    {
1286
        return $this->groupType;
1287
    }
1288
1289
    /**
1290
     * @param int $id
1291
     * @return bool|void
1292
     */
1293
    public function delete($id)
1294
    {
1295
        $id = (int) $id;
1296
        if ($this->useMultipleUrl) {
1297
            $this->unsubscribeToUrl($id, api_get_current_access_url_id());
1298
        }
1299
1300
        $sql = "DELETE FROM $this->usergroup_rel_user_table
1301
                WHERE usergroup_id = $id";
1302
        Database::query($sql);
1303
1304
        $sql = "DELETE FROM $this->usergroup_rel_course_table
1305
                WHERE usergroup_id = $id";
1306
        Database::query($sql);
1307
1308
        $sql = "DELETE FROM $this->usergroup_rel_session_table
1309
                WHERE usergroup_id = $id";
1310
        Database::query($sql);
1311
1312
        /*$sql = "DELETE FROM $this->usergroup_rel_
1313
                WHERE usergroup_id = $id";
1314
        Database::query($sql);*/
1315
1316
        parent::delete($id);
1317
    }
1318
1319
    /**
1320
     * @param int $id
1321
     * @param int $urlId
1322
     */
1323
    public function subscribeToUrl($id, $urlId)
1324
    {
1325
        Database::insert(
1326
            $this->access_url_rel_usergroup,
1327
            [
1328
                'access_url_id' => $urlId,
1329
                'usergroup_id' =>$id
1330
            ]
1331
        );
1332
    }
1333
1334
    /**
1335
     * @param int $id
1336
     * @param int $urlId
1337
     */
1338
    public function unsubscribeToUrl($id, $urlId)
1339
    {
1340
        Database::delete(
1341
            $this->access_url_rel_usergroup,
1342
            [
1343
                'access_url_id = ? AND usergroup_id = ? ' => [$urlId, $id]
1344
            ]
1345
        );
1346
    }
1347
1348
    /**
1349
     * @param $needle
1350
     * @return xajaxResponse
1351
     */
1352
    public static function searchUserGroupAjax($needle)
1353
    {
1354
        $response = new xajaxResponse();
1355
        $return = '';
1356
1357
        if (!empty($needle)) {
1358
            // xajax send utf8 datas... datas in db can be non-utf8 datas
1359
            $charset = api_get_system_encoding();
1360
            $needle = api_convert_encoding($needle, $charset, 'utf-8');
1361
            $needle = Database::escape_string($needle);
1362
            // search courses where username or firstname or lastname begins likes $needle
1363
            $sql = 'SELECT id, name 
1364
                    FROM '.Database::get_main_table(TABLE_USERGROUP).' u
1365
                    WHERE name LIKE "'.$needle.'%"
1366
                    ORDER BY name
1367
                    LIMIT 11';
1368
            $result = Database::query($sql);
1369
            $i = 0;
1370
            while ($data = Database::fetch_array($result)) {
1371
                $i++;
1372
                if ($i <= 10) {
1373
                    $return .= '<a
1374
                    href="javascript: void(0);"
1375
                    onclick="javascript: add_user_to_url(\''.addslashes($data['id']).'\',\''.addslashes($data['name']).' \')">'.$data['name'].' </a><br />';
1376
                } else {
1377
                    $return .= '...<br />';
1378
                }
1379
            }
1380
        }
1381
        $response->addAssign('ajax_list_courses', 'innerHTML', api_utf8_encode($return));
1382
1383
        return $response;
1384
    }
1385
1386
    /**
1387
     * Get user list by usergroup
1388
     * @param int $id
1389
     * @return array
1390
     */
1391
    public function getUserListByUserGroup($id)
1392
    {
1393
        $id = (int) $id;
1394
        $sql = "SELECT u.* FROM ".$this->table_user." u
1395
                INNER JOIN ".$this->usergroup_rel_user_table." c
1396
                ON c.user_id = u.id
1397
                WHERE c.usergroup_id = $id"
1398
                ;
1399
        $result = Database::query($sql);
1400
1401
        return Database::store_result($result);
1402
    }
1403
1404
    /**
1405
     * @param FormValidator $form
1406
     * @param string        $type
1407
     * @param array         $data
1408
     */
1409
    public function setForm($form, $type = 'add', $data = [])
1410
    {
1411
        switch ($type) {
1412
            case 'add':
1413
                $header = get_lang('Add');
1414
                break;
1415
            case 'edit':
1416
                $header = get_lang('Edit');
1417
                break;
1418
        }
1419
1420
        $form->addElement('header', $header);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $header does not seem to be defined for all execution paths leading up to this point.
Loading history...
1421
1422
        //Name
1423
        $form->addElement('text', 'name', get_lang('Name'), ['maxlength'=>255]);
1424
        $form->applyFilter('name', 'trim');
1425
1426
        $form->addRule('name', get_lang('ThisFieldIsRequired'), 'required');
1427
        $form->addRule('name', '', 'maxlength', 255);
1428
1429
        // Description
1430
        $form->addTextarea('description', get_lang('Description'), ['cols' => 58]);
1431
        $form->applyFilter('description', 'trim');
1432
1433
        if ($this->showGroupTypeSetting) {
1434
            $form->addElement(
1435
                'checkbox',
1436
                'group_type',
1437
                null,
1438
                get_lang('SocialGroup')
1439
            );
1440
        }
1441
1442
        // url
1443
        $form->addElement('text', 'url', get_lang('Url'));
1444
        $form->applyFilter('url', 'trim');
1445
1446
        // Picture
1447
        $allowed_picture_types = $this->getAllowedPictureExtensions();
1448
1449
        $form->addElement('file', 'picture', get_lang('AddPicture'));
1450
        $form->addRule(
1451
            'picture',
1452
            get_lang('OnlyImagesAllowed').' ('.implode(',', $allowed_picture_types).')',
1453
            'filetype',
1454
            $allowed_picture_types
1455
        );
1456
1457
        if (isset($data['picture']) && strlen($data['picture']) > 0) {
1458
            $picture = $this->get_picture_group($data['id'], $data['picture'], 80);
1459
            $img = '<img src="'.$picture['file'].'" />';
1460
            $form->addElement('label', null, $img);
1461
            $form->addElement('checkbox', 'delete_picture', '', get_lang('DelImage'));
1462
        }
1463
1464
        $form->addElement('select', 'visibility', get_lang('GroupPermissions'), $this->getGroupStatusList());
1465
        $form->setRequiredNote('<span class="form_required">*</span> <small>'.get_lang('ThisFieldIsRequired').'</small>');
1466
        $form->addElement('checkbox', 'allow_members_leave_group', '', get_lang('AllowMemberLeaveGroup'));
1467
1468
        // Setting the form elements
1469
        if ($type === 'add') {
1470
            $form->addButtonCreate($header);
1471
        } else {
1472
            $form->addButtonUpdate($header);
1473
        }
1474
    }
1475
1476
    /**
1477
     * Gets the current group image
1478
     * @param string $id group id
1479
     * @param string picture group name
1480
     * @param string height
1481
     * @param string picture size it can be small_,  medium_  or  big_
1482
     * @param string style css
1483
     * @return array with the file and the style of an image i.e $array['file'] $array['style']
1484
     */
1485
    public function get_picture_group(
1486
        $id,
1487
        $picture_file,
1488
        $height,
1489
        $size_picture = GROUP_IMAGE_SIZE_MEDIUM,
1490
        $style = ''
1491
    ) {
1492
        $picture = [];
1493
        //$picture['style'] = $style;
1494
        if ($picture_file === 'unknown.jpg') {
1495
            $picture['file'] = Display::returnIconPath($picture_file);
1496
            return $picture;
1497
        }
1498
1499
        switch ($size_picture) {
1500
            case GROUP_IMAGE_SIZE_ORIGINAL:
1501
                $size_picture = '';
1502
                break;
1503
            case GROUP_IMAGE_SIZE_BIG:
1504
                $size_picture = 'big_';
1505
                break;
1506
            case GROUP_IMAGE_SIZE_MEDIUM:
1507
                $size_picture = 'medium_';
1508
                break;
1509
            case GROUP_IMAGE_SIZE_SMALL:
1510
                $size_picture = 'small_';
1511
                break;
1512
            default:
1513
                $size_picture = 'medium_';
1514
        }
1515
1516
        $image_array_sys = $this->get_group_picture_path_by_id($id, 'system', false, true);
1517
        $image_array = $this->get_group_picture_path_by_id($id, 'web', false, true);
1518
        $file = $image_array_sys['dir'].$size_picture.$picture_file;
1519
        if (file_exists($file)) {
1520
            $picture['file'] = $image_array['dir'].$size_picture.$picture_file;
1521
            //$picture['style'] = '';
1522
            if ($height > 0) {
1523
                $dimension = api_getimagesize($picture['file']);
1524
                $margin = ($height - $dimension['width']) / 2;
1525
                //@ todo the padding-top should not be here
1526
            }
1527
        } else {
1528
            $file = $image_array_sys['dir'].$picture_file;
1529
            if (file_exists($file) && !is_dir($file)) {
1530
                $picture['file'] = $image_array['dir'].$picture_file;
1531
            } else {
1532
                $picture['file'] = Display::returnIconPath('group_na.png', 64);
1533
            }
1534
        }
1535
1536
        return $picture;
1537
    }
1538
1539
    /**
1540
     * Gets the group picture URL or path from group ID (returns an array).
1541
     * The return format is a complete path, enabling recovery of the directory
1542
     * with dirname() or the file with basename(). This also works for the
1543
     * functions dealing with the user's productions, as they are located in
1544
     * the same directory.
1545
     * @param    integer    User ID
1546
     * @param    string    Type of path to return (can be 'none', 'system', 'rel', 'web')
1547
     * @param    bool    Whether we want to have the directory name returned 'as if'
1548
     * there was a file or not (in the case we want to know which directory to create -
1549
     * otherwise no file means no split subdir)
1550
     * @param    bool    If we want that the function returns the /main/img/unknown.jpg image set it at true
1551
     * @return   array    Array of 2 elements: 'dir' and 'file' which contain the dir
1552
     * and file as the name implies if image does not exist it will return the unknown
1553
     * image if anonymous parameter is true if not it returns an empty er's
1554
     */
1555
    public function get_group_picture_path_by_id($id, $type = 'none', $preview = false, $anonymous = false)
1556
    {
1557
        switch ($type) {
1558
            case 'system': // Base: absolute system path.
1559
                $base = api_get_path(SYS_UPLOAD_PATH);
1560
                break;
1561
            case 'rel': // Base: semi-absolute web path (no server base).
1562
                $base = api_get_path(REL_CODE_PATH);
1563
                break;
1564
            case 'web': // Base: absolute web path.
1565
                $base = api_get_path(WEB_UPLOAD_PATH);
1566
                break;
1567
            case 'none':
1568
            default: // Base: empty, the result path below will be relative.
1569
                $base = '';
1570
        }
1571
1572
        if (empty($id) || empty($type)) {
1573
            return $anonymous ? ['dir' => $base.'img/', 'file' => 'unknown.jpg'] : ['dir' => '', 'file' => ''];
1574
        }
1575
1576
        $id = intval($id);
1577
        $group_table = Database::get_main_table(TABLE_USERGROUP);
1578
        $sql = "SELECT picture FROM $group_table WHERE id = ".$id;
1579
        $res = Database::query($sql);
1580
1581
        if (!Database::num_rows($res)) {
1582
            return $anonymous ? ['dir' => $base.'img/', 'file' => 'unknown.jpg'] : ['dir' => '', 'file' => ''];
1583
        }
1584
        $user = Database::fetch_array($res);
1585
        $picture_filename = trim($user['picture']);
1586
1587
        if (api_get_setting('split_users_upload_directory') === 'true') {
1588
            if (!empty($picture_filename)) {
1589
                $dir = $base.'groups/'.substr($picture_filename, 0, 1).'/'.$id.'/';
1590
            } elseif ($preview) {
1591
                $dir = $base.'groups/'.substr((string) $id, 0, 1).'/'.$id.'/';
1592
            } else {
1593
                $dir = $base.'groups/'.$id.'/';
1594
            }
1595
        } else {
1596
            $dir = $base.'groups/'.$id.'/';
1597
        }
1598
1599
        return ['dir' => $dir, 'file' => $picture_filename];
1600
    }
1601
1602
    /**
1603
     * @return array
1604
     */
1605
    public function getAllowedPictureExtensions()
1606
    {
1607
        return ['jpg', 'jpeg', 'png', 'gif'];
1608
    }
1609
1610
    /**
1611
     * @return array
1612
     */
1613
    public function getGroupStatusList()
1614
    {
1615
        $status = [
1616
            GROUP_PERMISSION_OPEN => get_lang('Open'),
1617
            GROUP_PERMISSION_CLOSED => get_lang('Closed')
1618
        ];
1619
1620
        return $status;
1621
    }
1622
1623
    /**
1624
     * @param int $type
1625
     */
1626
    public function setGroupType($type)
1627
    {
1628
        $this->groupType = intval($type);
1629
    }
1630
1631
    /**
1632
     * @param int $group_id
1633
     * @param int $user_id
1634
     * @return bool
1635
     */
1636
    public function is_group_admin($group_id, $user_id = 0)
1637
    {
1638
        if (empty($user_id)) {
1639
            $user_id = api_get_user_id();
1640
        }
1641
        $user_role = $this->get_user_group_role($user_id, $group_id);
1642
        if (in_array($user_role, [GROUP_USER_PERMISSION_ADMIN])) {
1643
            return true;
1644
        } else {
1645
            return false;
1646
        }
1647
    }
1648
1649
    /**
1650
     * @param int $group_id
1651
     * @param int $user_id
1652
     * @return bool
1653
     */
1654
    public function isGroupModerator($group_id, $user_id = 0)
1655
    {
1656
        if (empty($user_id)) {
1657
            $user_id = api_get_user_id();
1658
        }
1659
        $user_role = $this->get_user_group_role($user_id, $group_id);
1660
        if (in_array($user_role, [GROUP_USER_PERMISSION_ADMIN, GROUP_USER_PERMISSION_MODERATOR])) {
1661
            return true;
1662
        } else {
1663
            return false;
1664
        }
1665
    }
1666
1667
    /**
1668
     * @param int $group_id
1669
     * @param int $user_id
1670
     * @return bool
1671
     */
1672
    public function is_group_member($group_id, $user_id = 0)
1673
    {
1674
        if (api_is_platform_admin()) {
1675
            return true;
1676
        }
1677
        if (empty($user_id)) {
1678
            $user_id = api_get_user_id();
1679
        }
1680
        $roles = [
1681
            GROUP_USER_PERMISSION_ADMIN,
1682
            GROUP_USER_PERMISSION_MODERATOR,
1683
            GROUP_USER_PERMISSION_READER,
1684
            GROUP_USER_PERMISSION_HRM,
1685
        ];
1686
        $user_role = self::get_user_group_role($user_id, $group_id);
0 ignored issues
show
Bug Best Practice introduced by
The method UserGroup::get_user_group_role() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1686
        /** @scrutinizer ignore-call */ 
1687
        $user_role = self::get_user_group_role($user_id, $group_id);
Loading history...
1687
        if (in_array($user_role, $roles)) {
1688
            return true;
1689
        } else {
1690
            return false;
1691
        }
1692
    }
1693
1694
    /**
1695
     * Gets the relationship between a group and a User
1696
     * @author Julio Montoya
1697
     * @param int $user_id
1698
     * @param int $group_id
1699
     * @return int 0 if there are not relationship otherwise returns the user group
1700
     * */
1701
    public function get_user_group_role($user_id, $group_id)
1702
    {
1703
        $table_group_rel_user = $this->usergroup_rel_user_table;
1704
        $return_value = 0;
1705
        if (!empty($user_id) && !empty($group_id)) {
1706
            $sql = "SELECT relation_type FROM $table_group_rel_user
1707
                    WHERE
1708
                        usergroup_id = ".intval($group_id)." AND
1709
                        user_id = ".intval($user_id)." ";
1710
            $result = Database::query($sql);
1711
            if (Database::num_rows($result) > 0) {
1712
                $row = Database::fetch_array($result, 'ASSOC');
1713
                $return_value = $row['relation_type'];
1714
            }
1715
        }
1716
1717
        return $return_value;
1718
    }
1719
1720
    /**
1721
     * @param int $userId
1722
     * @param int $groupId
1723
     * @return string
1724
     */
1725
    public function getUserRoleToString($userId, $groupId)
1726
    {
1727
        $role = self::get_user_group_role($userId, $groupId);
0 ignored issues
show
Bug Best Practice introduced by
The method UserGroup::get_user_group_role() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1727
        /** @scrutinizer ignore-call */ 
1728
        $role = self::get_user_group_role($userId, $groupId);
Loading history...
1728
        $roleToString = '';
1729
1730
        switch ($role) {
1731
            case GROUP_USER_PERMISSION_ADMIN:
1732
                $roleToString = get_lang('Admin');
1733
                break;
1734
            case GROUP_USER_PERMISSION_READER:
1735
                $roleToString = get_lang('Reader');
1736
                break;
1737
            case GROUP_USER_PERMISSION_PENDING_INVITATION:
1738
                $roleToString = get_lang('PendingInvitation');
1739
                break;
1740
            case GROUP_USER_PERMISSION_MODERATOR:
1741
                $roleToString = get_lang('Moderator');
1742
                break;
1743
            case GROUP_USER_PERMISSION_HRM:
1744
                $roleToString = get_lang('Drh');
1745
                break;
1746
        }
1747
1748
        return $roleToString;
1749
    }
1750
1751
    /**
1752
     * Add a group of users into a group of URLs
1753
     * @author Julio Montoya
1754
     * @param array $user_list
1755
     * @param array $group_list
1756
     * @param int $relation_type
1757
     *
1758
     * @return array
1759
     **/
1760
    public function add_users_to_groups($user_list, $group_list, $relation_type = GROUP_USER_PERMISSION_READER)
1761
    {
1762
        $table_url_rel_group = $this->usergroup_rel_user_table;
1763
        $result_array = [];
1764
        $relation_type = intval($relation_type);
1765
1766
        if (is_array($user_list) && is_array($group_list)) {
1767
            foreach ($group_list as $group_id) {
1768
                foreach ($user_list as $user_id) {
1769
                    $role = self::get_user_group_role($user_id, $group_id);
0 ignored issues
show
Bug Best Practice introduced by
The method UserGroup::get_user_group_role() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1769
                    /** @scrutinizer ignore-call */ 
1770
                    $role = self::get_user_group_role($user_id, $group_id);
Loading history...
1770
                    if ($role == 0) {
1771
                        $sql = "INSERT INTO $table_url_rel_group
1772
		               			SET
1773
		               			    user_id = ".intval($user_id).",
1774
		               			    usergroup_id = ".intval($group_id).",
1775
		               			    relation_type = ".intval($relation_type);
1776
1777
                        $result = Database::query($sql);
1778
                        if ($result) {
1779
                            $result_array[$group_id][$user_id] = 1;
1780
                        } else {
1781
                            $result_array[$group_id][$user_id] = 0;
1782
                        }
1783
                    }
1784
                }
1785
            }
1786
        }
1787
        return $result_array;
1788
    }
1789
1790
    /**
1791
     * Deletes an url and session relationship
1792
     * @author Julio Montoya
1793
     * @param  int  $user_id
1794
     * @param  int $group_id
1795
     * @return boolean true if success
1796
     * */
1797
    public function delete_user_rel_group($user_id, $group_id)
1798
    {
1799
        $table = $this->usergroup_rel_user_table;
1800
        $sql = "DELETE FROM $table
1801
                WHERE
1802
                    user_id = ".intval($user_id)." AND
1803
                    usergroup_id = ".intval($group_id)."  ";
1804
        $result = Database::query($sql);
1805
1806
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result returns the type Doctrine\DBAL\Driver\Statement which is incompatible with the documented return type boolean.
Loading history...
1807
    }
1808
1809
    /**
1810
     * Add a user into a group
1811
     * @author Julio Montoya
1812
     * @param  int $user_id
1813
     * @param  int $group_id
1814
     * @param  int $relation_type
1815
    *
1816
     * @return boolean true if success
1817
     **/
1818
    public function add_user_to_group($user_id, $group_id, $relation_type = GROUP_USER_PERMISSION_READER)
1819
    {
1820
        $table_url_rel_group = $this->usergroup_rel_user_table;
1821
        if (!empty($user_id) && !empty($group_id)) {
1822
            $role = self::get_user_group_role($user_id, $group_id);
0 ignored issues
show
Bug Best Practice introduced by
The method UserGroup::get_user_group_role() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1822
            /** @scrutinizer ignore-call */ 
1823
            $role = self::get_user_group_role($user_id, $group_id);
Loading history...
1823
1824
            if ($role == 0) {
1825
                $sql = "INSERT INTO $table_url_rel_group
1826
           				SET
1827
           				    user_id = ".intval($user_id).",
1828
           				    usergroup_id = ".intval($group_id).",
1829
           				    relation_type = ".intval($relation_type);
1830
                Database::query($sql);
1831
            } elseif ($role == GROUP_USER_PERMISSION_PENDING_INVITATION) {
1832
                //if somebody already invited me I can be added
1833
                self::update_user_role($user_id, $group_id, GROUP_USER_PERMISSION_READER);
0 ignored issues
show
Bug Best Practice introduced by
The method UserGroup::update_user_role() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1833
                self::/** @scrutinizer ignore-call */ 
1834
                      update_user_role($user_id, $group_id, GROUP_USER_PERMISSION_READER);
Loading history...
1834
            }
1835
        }
1836
1837
        return true;
1838
    }
1839
1840
    /**
1841
     * Updates the group_rel_user table  with a given user and group ids
1842
     * @author Julio Montoya
1843
     * @param int $user_id
1844
     * @param int $group_id
1845
     * @param int $relation_type
1846
     **/
1847
    public function update_user_role($user_id, $group_id, $relation_type = GROUP_USER_PERMISSION_READER)
1848
    {
1849
        $table_group_rel_user = $this->usergroup_rel_user_table;
1850
        $group_id = intval($group_id);
1851
        $user_id = intval($user_id);
1852
1853
        $sql = "UPDATE $table_group_rel_user
1854
   				SET relation_type = ".intval($relation_type)."
1855
                WHERE user_id = $user_id AND usergroup_id = $group_id";
1856
        Database::query($sql);
1857
    }
1858
1859
    /**
1860
     * Gets the inner join from users and group table
1861
     *
1862
     * @return array   Database::store_result of the result
1863
     *
1864
     * @author Julio Montoya
1865
     * */
1866
    public function get_groups_by_user($user_id = '', $relation_type = GROUP_USER_PERMISSION_READER, $with_image = false)
1867
    {
1868
        $table_group_rel_user = $this->usergroup_rel_user_table;
1869
        $tbl_group = $this->table;
1870
1871
        if ($relation_type == 0) {
1872
            $relationCondition = '';
1873
        } else {
1874
            $relation_type = intval($relation_type);
1875
            $relationCondition = " AND gu.relation_type = $relation_type ";
1876
        }
1877
1878
        $sql = "SELECT
1879
                    g.picture,
1880
                    g.name,
1881
                    g.description,
1882
                    g.id ,
1883
                    gu.relation_type
1884
				FROM $tbl_group g
1885
				INNER JOIN $table_group_rel_user gu
1886
				ON gu.usergroup_id = g.id
1887
				WHERE
1888
				    g.group_type = ".self::SOCIAL_CLASS." AND
1889
                    gu.user_id = $user_id
1890
                    $relationCondition
1891
                ORDER BY created_at DESC ";
1892
        $result = Database::query($sql);
1893
        $array = [];
1894
        if (Database::num_rows($result) > 0) {
1895
            while ($row = Database::fetch_array($result, 'ASSOC')) {
1896
                if ($with_image) {
1897
                    $picture = self::get_picture_group($row['id'], $row['picture'], 80);
0 ignored issues
show
Bug Best Practice introduced by
The method UserGroup::get_picture_group() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1897
                    /** @scrutinizer ignore-call */ 
1898
                    $picture = self::get_picture_group($row['id'], $row['picture'], 80);
Loading history...
1898
                    $img = '<img src="'.$picture['file'].'" />';
1899
                    $row['picture'] = $img;
1900
                }
1901
                $array[$row['id']] = $row;
1902
            }
1903
        }
1904
        return $array;
1905
    }
1906
1907
    /** Gets the inner join of users and group table
1908
     * @param int  quantity of records
1909
     * @param bool show groups with image or not
1910
     * @return array  with group content
1911
     * @author Julio Montoya
1912
     * */
1913
    public function get_groups_by_popularity($num = 6, $with_image = true)
1914
    {
1915
        $table_group_rel_user = $this->usergroup_rel_user_table;
1916
        $tbl_group = $this->table;
1917
        if (empty($num)) {
1918
            $num = 6;
1919
        } else {
1920
            $num = intval($num);
1921
        }
1922
        // only show admins and readers
1923
        $where_relation_condition = " WHERE g.group_type = ".self::SOCIAL_CLASS." AND
1924
                                      gu.relation_type IN ('".GROUP_USER_PERMISSION_ADMIN."' , '".GROUP_USER_PERMISSION_READER."', '".GROUP_USER_PERMISSION_HRM."') ";
1925
        $sql = "SELECT DISTINCT count(user_id) as count, g.picture, g.name, g.description, g.id
1926
				FROM $tbl_group g
1927
				INNER JOIN $table_group_rel_user gu
1928
				ON gu.usergroup_id = g.id $where_relation_condition
1929
				GROUP BY g.id
1930
				ORDER BY count DESC
1931
				LIMIT $num";
1932
1933
        $result = Database::query($sql);
1934
        $array = [];
1935
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1936
            if ($with_image) {
1937
                $picture = self::get_picture_group($row['id'], $row['picture'], 80);
0 ignored issues
show
Bug Best Practice introduced by
The method UserGroup::get_picture_group() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1937
                /** @scrutinizer ignore-call */ 
1938
                $picture = self::get_picture_group($row['id'], $row['picture'], 80);
Loading history...
1938
                $img = '<img src="'.$picture['file'].'" />';
1939
                $row['picture'] = $img;
1940
            }
1941
            if (empty($row['id'])) {
1942
                continue;
1943
            }
1944
            $array[$row['id']] = $row;
1945
        }
1946
1947
        return $array;
1948
    }
1949
1950
    /** Gets the last groups created
1951
     * @param int  $num quantity of records
1952
     * @param bool $with_image show groups with image or not
1953
     * @return array  with group content
1954
     * @author Julio Montoya
1955
     * */
1956
    public function get_groups_by_age($num = 6, $with_image = true)
1957
    {
1958
        $table_group_rel_user = $this->usergroup_rel_user_table;
1959
        $tbl_group = $this->table;
1960
1961
        if (empty($num)) {
1962
            $num = 6;
1963
        } else {
1964
            $num = intval($num);
1965
        }
1966
        $where_relation_condition = " WHERE g.group_type = ".self::SOCIAL_CLASS." AND
1967
                                      gu.relation_type IN ('".GROUP_USER_PERMISSION_ADMIN."' , '".GROUP_USER_PERMISSION_READER."', '".GROUP_USER_PERMISSION_HRM."') ";
1968
        $sql = "SELECT DISTINCT
1969
                  count(user_id) as count,
1970
                  g.picture,
1971
                  g.name,
1972
                  g.description,
1973
                  g.id
1974
                FROM $tbl_group g
1975
                INNER JOIN $table_group_rel_user gu
1976
                ON gu.usergroup_id = g.id
1977
                $where_relation_condition
1978
                GROUP BY g.id
1979
                ORDER BY created_at DESC
1980
                LIMIT $num ";
1981
1982
        $result = Database::query($sql);
1983
        $array = [];
1984
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1985
            if ($with_image) {
1986
                $picture = self::get_picture_group($row['id'], $row['picture'], 80);
0 ignored issues
show
Bug Best Practice introduced by
The method UserGroup::get_picture_group() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1986
                /** @scrutinizer ignore-call */ 
1987
                $picture = self::get_picture_group($row['id'], $row['picture'], 80);
Loading history...
1987
                $img = '<img src="'.$picture['file'].'" />';
1988
                $row['picture'] = $img;
1989
            }
1990
            if (empty($row['id'])) {
1991
                continue;
1992
            }
1993
            $array[$row['id']] = $row;
1994
        }
1995
        return $array;
1996
    }
1997
1998
    /**
1999
     * Gets the group's members
2000
     * @param int group id
2001
     * @param bool show image or not of the group
2002
     * @param array list of relation type use constants
2003
     * @param int from value
2004
     * @param int limit
2005
     * @param array image configuration, i.e array('height'=>'20px', 'size'=> '20px')
2006
     * @return array list of users in a group
2007
     */
2008
    public function get_users_by_group(
2009
        $group_id,
2010
        $with_image = false,
2011
        $relation_type = [],
2012
        $from = null,
2013
        $limit = null,
2014
        $image_conf = ['size' => USER_IMAGE_SIZE_MEDIUM, 'height' => 80]
2015
    ) {
2016
        $table_group_rel_user = $this->usergroup_rel_user_table;
2017
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
2018
        $group_id = intval($group_id);
2019
2020
        if (empty($group_id)) {
2021
            return [];
2022
        }
2023
2024
        $limit_text = '';
2025
        if (isset($from) && isset($limit)) {
2026
            $from = intval($from);
2027
            $limit = intval($limit);
2028
            $limit_text = "LIMIT $from, $limit";
2029
        }
2030
2031
        if (count($relation_type) == 0) {
2032
            $where_relation_condition = '';
2033
        } else {
2034
            $new_relation_type = [];
2035
            foreach ($relation_type as $rel) {
2036
                $rel = intval($rel);
2037
                $new_relation_type[] = "'$rel'";
2038
            }
2039
            $relation_type = implode(',', $new_relation_type);
2040
            if (!empty($relation_type)) {
2041
                $where_relation_condition = "AND gu.relation_type IN ($relation_type) ";
2042
            }
2043
        }
2044
2045
        $sql = "SELECT picture_uri as image, u.id, CONCAT (u.firstname,' ', u.lastname) as fullname, relation_type
2046
    		    FROM $tbl_user u
2047
    		    INNER JOIN $table_group_rel_user gu
2048
    			ON (gu.user_id = u.id)
2049
    			WHERE
2050
    			    gu.usergroup_id= $group_id
2051
    			    $where_relation_condition
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $where_relation_condition does not seem to be defined for all execution paths leading up to this point.
Loading history...
2052
    			ORDER BY relation_type, firstname
2053
    			$limit_text";
2054
2055
        $result = Database::query($sql);
2056
        $array  = [];
2057
        while ($row = Database::fetch_array($result, 'ASSOC')) {
2058
            if ($with_image) {
2059
                $userInfo = api_get_user_info($row['id']);
2060
                $userPicture = UserManager::getUserPicture($row['id']);
2061
2062
                $row['image'] = '<img src="'.$userPicture.'"  />';
2063
                $row['user_info'] = $userInfo;
2064
            }
2065
            $array[$row['id']] = $row;
2066
        }
2067
        return $array;
2068
    }
2069
2070
    /**
2071
     * Gets all the members of a group no matter the relationship for
2072
     * more specifications use get_users_by_group
2073
     * @param int group id
2074
     * @return array
2075
     */
2076
    public function get_all_users_by_group($group_id)
2077
    {
2078
        $table_group_rel_user = $this->usergroup_rel_user_table;
2079
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
2080
        $group_id = intval($group_id);
2081
2082
        if (empty($group_id)) {
2083
            return [];
2084
        }
2085
2086
        $sql = "SELECT u.id, u.firstname, u.lastname, relation_type
2087
                FROM $tbl_user u
2088
			    INNER JOIN $table_group_rel_user gu
2089
			    ON (gu.user_id = u.id)
2090
			    WHERE gu.usergroup_id= $group_id
2091
			    ORDER BY relation_type, firstname";
2092
2093
        $result = Database::query($sql);
2094
        $array = [];
2095
        while ($row = Database::fetch_array($result, 'ASSOC')) {
2096
            $array[$row['id']] = $row;
2097
        }
2098
        return $array;
2099
    }
2100
2101
    /**
2102
     * Shows the left column of the group page
2103
     * @param int group id
2104
     * @param int user id
2105
     * @return string
2106
     */
2107
    public function show_group_column_information($group_id, $user_id, $show = '')
2108
    {
2109
        $html = '';
2110
        $group_info = $this->get($group_id);
2111
2112
        //my relation with the group is set here
2113
        $my_group_role = self::get_user_group_role($user_id, $group_id);
0 ignored issues
show
Bug Best Practice introduced by
The method UserGroup::get_user_group_role() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

2113
        /** @scrutinizer ignore-call */ 
2114
        $my_group_role = self::get_user_group_role($user_id, $group_id);
Loading history...
2114
2115
        // Loading group permission
2116
        $links = '';
2117
        switch ($my_group_role) {
2118
            case GROUP_USER_PERMISSION_READER:
2119
                // I'm just a reader
2120
                $relation_group_title = get_lang('IAmAReader');
2121
                $links .= '<li class="'.($show == 'invite_friends' ? 'active' : '').'"><a href="group_invitation.php?id='.$group_id.'">'.
2122
                            Display::return_icon('invitation_friend.png', get_lang('InviteFriends')).get_lang('InviteFriends').'</a></li>';
2123
                if (self::canLeave($group_info)) {
2124
                    $links .= '<li><a href="group_view.php?id='.$group_id.'&action=leave&u='.api_get_user_id().'">'.
2125
                        Display::return_icon('group_leave.png', get_lang('LeaveGroup')).get_lang('LeaveGroup').'</a></li>';
2126
                }
2127
                break;
2128
            case GROUP_USER_PERMISSION_ADMIN:
2129
                $relation_group_title = get_lang('IAmAnAdmin');
2130
                $links .= '<li class="'.($show == 'group_edit' ? 'active' : '').'"><a href="group_edit.php?id='.$group_id.'">'.
2131
                            Display::return_icon('group_edit.png', get_lang('EditGroup')).get_lang('EditGroup').'</a></li>';
2132
                $links .= '<li class="'.($show == 'member_list' ? 'active' : '').'"><a href="group_waiting_list.php?id='.$group_id.'">'.
2133
                            Display::return_icon('waiting_list.png', get_lang('WaitingList')).get_lang('WaitingList').'</a></li>';
2134
                $links .= '<li class="'.($show == 'invite_friends' ? 'active' : '').'"><a href="group_invitation.php?id='.$group_id.'">'.
2135
                            Display::return_icon('invitation_friend.png', get_lang('InviteFriends')).get_lang('InviteFriends').'</a></li>';
2136
                if (self::canLeave($group_info)) {
2137
                    $links .= '<li><a href="group_view.php?id='.$group_id.'&action=leave&u='.api_get_user_id().'">'.
2138
                        Display::return_icon('group_leave.png', get_lang('LeaveGroup')).get_lang('LeaveGroup').'</a></li>';
2139
                }
2140
                break;
2141
            case GROUP_USER_PERMISSION_PENDING_INVITATION:
2142
//				$links .=  '<li><a href="groups.php?id='.$group_id.'&action=join&u='.api_get_user_id().'">'.Display::return_icon('addd.gif', get_lang('YouHaveBeenInvitedJoinNow'), array('hspace'=>'6')).'<span class="social-menu-text4" >'.get_lang('YouHaveBeenInvitedJoinNow').'</span></a></li>';
2143
                break;
2144
            case GROUP_USER_PERMISSION_PENDING_INVITATION_SENT_BY_USER:
2145
                $relation_group_title = get_lang('WaitingForAdminResponse');
2146
                break;
2147
            case GROUP_USER_PERMISSION_MODERATOR:
2148
                $relation_group_title = get_lang('IAmAModerator');
2149
                //$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('ComposeMessage').'">'.Display::return_icon('compose_message.png', get_lang('NewTopic'), array('hspace'=>'6')).'<span class="social-menu-text4" >'.get_lang('NewTopic').'</span></a></li>';
2150
                //$links .=  '<li><a href="groups.php?id='.$group_id.'">'.				Display::return_icon('message_list.png', get_lang('MessageList'), array('hspace'=>'6')).'<span class="'.($show=='messages_list'?'social-menu-text-active':'social-menu-text4').'" >'.get_lang('MessageList').'</span></a></li>';
2151
                //$links .=  '<li><a href="group_members.php?id='.$group_id.'">'.		Display::return_icon('member_list.png', get_lang('MemberList'), array('hspace'=>'6')).'<span class="'.($show=='member_list'?'social-menu-text-active':'social-menu-text4').'" >'.get_lang('MemberList').'</span></a></li>';
2152
                if ($group_info['visibility'] == GROUP_PERMISSION_CLOSED) {
2153
                    $links .= '<li><a href="group_waiting_list.php?id='.$group_id.'">'.
2154
                                Display::return_icon('waiting_list.png', get_lang('WaitingList')).get_lang('WaitingList').'</a></li>';
2155
                }
2156
                $links .= '<li><a href="group_invitation.php?id='.$group_id.'">'.
2157
                            Display::return_icon('invitation_friend.png', get_lang('InviteFriends')).get_lang('InviteFriends').'</a></li>';
2158
                if (self::canLeave($group_info)) {
2159
                    $links .= '<li><a href="group_view.php?id='.$group_id.'&action=leave&u='.api_get_user_id().'">'.
2160
                        Display::return_icon('group_leave.png', get_lang('LeaveGroup')).get_lang('LeaveGroup').'</a></li>';
2161
                }
2162
                break;
2163
            case GROUP_USER_PERMISSION_HRM:
2164
                $relation_group_title = get_lang('IAmAHRM');
2165
                $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('ComposeMessage').'" data-size="lg" data-title="'.get_lang('ComposeMessage').'">'.
2166
                            Display::return_icon('new-message.png', get_lang('NewTopic')).get_lang('NewTopic').'</a></li>';
2167
                $links .= '<li><a href="group_view.php?id='.$group_id.'">'.
2168
                            Display::return_icon('message_list.png', get_lang('MessageList')).get_lang('MessageList').'</a></li>';
2169
                $links .= '<li><a href="group_invitation.php?id='.$group_id.'">'.
2170
                            Display::return_icon('invitation_friend.png', get_lang('InviteFriends')).get_lang('InviteFriends').'</a></li>';
2171
                $links .= '<li><a href="group_members.php?id='.$group_id.'">'.
2172
                            Display::return_icon('member_list.png', get_lang('MemberList')).get_lang('MemberList').'</a></li>';
2173
                $links .= '<li><a href="group_view.php?id='.$group_id.'&action=leave&u='.api_get_user_id().'">'.
2174
                            Display::return_icon('delete_data.gif', get_lang('LeaveGroup')).get_lang('LeaveGroup').'</a></li>';
2175
                break;
2176
            default:
2177
                //$links .=  '<li><a href="groups.php?id='.$group_id.'&action=join&u='.api_get_user_id().'">'.Display::return_icon('addd.gif', get_lang('JoinGroup'), array('hspace'=>'6')).'<span class="social-menu-text4" >'.get_lang('JoinGroup').'</a></span></li>';
2178
                break;
2179
        }
2180
        if (!empty($links)) {
2181
            $list = '<ul class="nav nav-pills">';
2182
            $list .= $links;
2183
            $list .= '</ul>';
2184
            $html .= Display::panelCollapse(
2185
                get_lang('SocialGroups'),
2186
                $list,
2187
                'sm-groups',
2188
                [],
2189
                'groups-acordeon',
2190
                'groups-collapse'
2191
            );
2192
        }
2193
        return $html;
2194
    }
2195
2196
    /**
2197
     * @param int $group_id
2198
     * @param int $topic_id
2199
     */
2200
    public function delete_topic($group_id, $topic_id)
2201
    {
2202
        $table_message = Database::get_main_table(TABLE_MESSAGE);
2203
        $topic_id = intval($topic_id);
2204
        $group_id = intval($group_id);
2205
        $sql = "UPDATE $table_message SET
2206
                msg_status = 3
2207
                WHERE
2208
                    group_id = $group_id AND
2209
                    (id = '$topic_id' OR parent_id = $topic_id)
2210
                ";
2211
        Database::query($sql);
2212
    }
2213
2214
    /**
2215
     * @param string $user_id
2216
     * @param string $relation_type
2217
     * @param bool $with_image
2218
     * @return int
2219
     */
2220
    public function get_groups_by_user_count(
2221
        $user_id = '',
2222
        $relation_type = GROUP_USER_PERMISSION_READER,
2223
        $with_image = false
2224
    ) {
2225
        $table_group_rel_user = $this->usergroup_rel_user_table;
2226
        $tbl_group = $this->table;
2227
        $user_id = intval($user_id);
2228
2229
        if ($relation_type == 0) {
2230
            $where_relation_condition = '';
2231
        } else {
2232
            $relation_type = intval($relation_type);
2233
            $where_relation_condition = "AND gu.relation_type = $relation_type ";
2234
        }
2235
2236
        $sql = "SELECT count(g.id) as count
2237
				FROM $tbl_group g
2238
				INNER JOIN $table_group_rel_user gu
2239
				ON gu.usergroup_id = g.id
2240
				WHERE gu.user_id = $user_id $where_relation_condition ";
2241
2242
        $result = Database::query($sql);
2243
        if (Database::num_rows($result) > 0) {
2244
            $row = Database::fetch_array($result, 'ASSOC');
2245
            return $row['count'];
2246
        }
2247
        return 0;
2248
    }
2249
2250
    /**
2251
     * @param string $tag
2252
     * @param int    $from
2253
     * @param int    $number_of_items
2254
     *
2255
     * @return array
2256
     */
2257
    public function get_all_group_tags($tag, $from = 0, $number_of_items = 10, $getCount = false)
2258
    {
2259
        $group_table = $this->table;
2260
        $tag = Database::escape_string($tag);
2261
        $from = intval($from);
2262
        $number_of_items = intval($number_of_items);
2263
        $return = [];
2264
2265
        $keyword = $tag;
2266
        $sql = "SELECT  g.id, g.name, g.description, g.url, g.picture
2267
                FROM $group_table g";
2268
        if (isset($keyword)) {
2269
            $sql .= " WHERE (
2270
                        g.name LIKE '%".$keyword."%' OR
2271
                        g.description LIKE '%".$keyword."%' OR
2272
                        g.url LIKE '%".$keyword."%'
2273
                     )";
2274
        }
2275
2276
        $direction = 'ASC';
2277
        if (!in_array($direction, ['ASC', 'DESC'])) {
2278
            $direction = 'ASC';
2279
        }
2280
2281
        $from = intval($from);
2282
        $number_of_items = intval($number_of_items);
2283
2284
        //$sql .= " ORDER BY col$column $direction ";
2285
        $sql .= " LIMIT $from,$number_of_items";
2286
2287
        $res = Database::query($sql);
2288
        if (Database::num_rows($res) > 0) {
2289
            while ($row = Database::fetch_array($res, 'ASSOC')) {
2290
                if (!in_array($row['id'], $return)) {
2291
                    $return[$row['id']] = $row;
2292
                }
2293
            }
2294
        }
2295
        return $return;
2296
    }
2297
2298
    /**
2299
     * @param int $group_id
2300
     * @return array
2301
     */
2302
    public static function get_parent_groups($group_id)
2303
    {
2304
        $t_rel_group = Database::get_main_table(TABLE_USERGROUP_REL_USERGROUP);
2305
        $max_level = 10;
2306
        $select_part = "SELECT ";
2307
        $cond_part = '';
2308
        for ($i = 1; $i <= $max_level; $i++) {
2309
            $g_number = $i;
2310
            $rg_number = $i - 1;
2311
            if ($i == $max_level) {
2312
                $select_part .= "rg$rg_number.group_id as id_$rg_number ";
2313
            } else {
2314
                $select_part .= "rg$rg_number.group_id as id_$rg_number, ";
2315
            }
2316
            if ($i == 1) {
2317
                $cond_part .= "FROM $t_rel_group rg0 LEFT JOIN $t_rel_group rg$i on rg$rg_number.group_id = rg$i.subgroup_id ";
2318
            } else {
2319
                $cond_part .= " LEFT JOIN $t_rel_group rg$i on rg$rg_number.group_id = rg$i.subgroup_id ";
2320
            }
2321
        }
2322
        $sql = $select_part.' '.$cond_part."WHERE rg0.subgroup_id='$group_id'";
2323
        $res = Database::query($sql);
2324
        $temp_arr = Database::fetch_array($res, 'NUM');
2325
        $toReturn = [];
2326
        if (is_array($temp_arr)) {
2327
            foreach ($temp_arr as $elt) {
2328
                if (isset($elt)) {
2329
                    $toReturn[] = $elt;
2330
                }
2331
            }
2332
        }
2333
2334
        return $toReturn;
2335
    }
2336
2337
    /**
2338
     * Get the group member list by a user and his group role
2339
     * @param int $userId The user ID
2340
     * @param int $relationType Optional. The relation type. GROUP_USER_PERMISSION_ADMIN by default
2341
     * @param boolean $includeSubgroupsUsers Optional. Whether include the users from subgroups
2342
     * @return array
2343
     */
2344
    public function getGroupUsersByUser(
2345
        $userId,
2346
        $relationType = GROUP_USER_PERMISSION_ADMIN,
2347
        $includeSubgroupsUsers = true
2348
    ) {
2349
        $userId = intval($userId);
2350
        $groups = $this->get_groups_by_user($userId, $relationType);
2351
        $groupsId = array_keys($groups);
2352
        $subgroupsId = [];
2353
        $userIdList = [];
2354
2355
        if ($includeSubgroupsUsers) {
2356
            foreach ($groupsId as $groupId) {
2357
                $subgroupsId = array_merge($subgroupsId, self::getGroupsByDepthLevel($groupId));
2358
            }
2359
2360
            $groupsId = array_merge($groupsId, $subgroupsId);
2361
        }
2362
2363
        $groupsId = array_unique($groupsId);
2364
2365
        if (empty($groupsId)) {
2366
            return [];
2367
        }
2368
2369
        foreach ($groupsId as $groupId) {
2370
            $groupUsers = self::get_users_by_group($groupId);
0 ignored issues
show
Bug Best Practice introduced by
The method UserGroup::get_users_by_group() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

2370
            /** @scrutinizer ignore-call */ 
2371
            $groupUsers = self::get_users_by_group($groupId);
Loading history...
2371
2372
            if (empty($groupUsers)) {
2373
                continue;
2374
            }
2375
2376
            foreach ($groupUsers as $member) {
2377
                if ($member['user_id'] == $userId) {
2378
                    continue;
2379
                }
2380
2381
                $userIdList[] = intval($member['user_id']);
2382
            }
2383
        }
2384
2385
        return array_unique($userIdList);
2386
    }
2387
2388
    /**
2389
     * Get the subgroups ID from a group.
2390
     * The default $levels value is 10 considering it as a extensive level of depth
2391
     * @param int $groupId The parent group ID
2392
     * @param int $levels The depth levels
2393
     * @return array The list of ID
2394
     */
2395
    public static function getGroupsByDepthLevel($groupId, $levels = 10)
2396
    {
2397
        $groups = [];
2398
        $groupId = intval($groupId);
2399
2400
        $groupTable = Database::get_main_table(TABLE_USERGROUP);
2401
        $groupRelGroupTable = Database::get_main_table(TABLE_USERGROUP_REL_USERGROUP);
2402
2403
        $select = "SELECT ";
2404
        $from = "FROM $groupTable g1 ";
2405
2406
        for ($i = 1; $i <= $levels; $i++) {
2407
            $tableIndexNumber = $i;
2408
            $tableIndexJoinNumber = $i - 1;
2409
            $select .= "g$i.id as id_$i ";
2410
            $select .= ($i != $levels ? ", " : null);
2411
2412
            if ($i == 1) {
2413
                $from .= "INNER JOIN $groupRelGroupTable gg0 ON g1.id = gg0.subgroup_id and gg0.group_id = $groupId ";
2414
            } else {
2415
                $from .= "LEFT JOIN $groupRelGroupTable gg$tableIndexJoinNumber ";
2416
                $from .= " ON g$tableIndexJoinNumber.id = gg$tableIndexJoinNumber.group_id ";
2417
                $from .= "LEFT JOIN $groupTable g$tableIndexNumber ";
2418
                $from .= " ON gg$tableIndexJoinNumber.subgroup_id = g$tableIndexNumber.id ";
2419
            }
2420
        }
2421
2422
        $result = Database::query("$select $from");
2423
2424
        while ($item = Database::fetch_assoc($result)) {
2425
            foreach ($item as $myGroupId) {
2426
                if (!empty($myGroupId)) {
2427
                    $groups[] = $myGroupId;
2428
                }
2429
            }
2430
        }
2431
2432
        return array_map('intval', $groups);
2433
    }
2434
2435
    /**
2436
     * Set a parent group
2437
     * @param int $group_id
2438
     * @param int $parent_group_id if 0, we delete the parent_group association
2439
     * @param int $relation_type
2440
     * @return \Doctrine\DBAL\Statement
2441
     **/
2442
    public function setParentGroup($group_id, $parent_group_id, $relation_type = 1)
2443
    {
2444
        $table = Database::get_main_table(TABLE_USERGROUP_REL_USERGROUP);
2445
        $group_id = intval($group_id);
2446
        $parent_group_id = intval($parent_group_id);
2447
        if ($parent_group_id == 0) {
2448
            $sql = "DELETE FROM $table WHERE subgroup_id = $group_id";
2449
        } else {
2450
            $sql = "SELECT group_id FROM $table WHERE subgroup_id = $group_id";
2451
            $res = Database::query($sql);
2452
            if (Database::num_rows($res) == 0) {
2453
                $sql = "INSERT INTO $table SET
2454
                        group_id = $parent_group_id,
2455
                        subgroup_id = $group_id,
2456
                        relation_type = $relation_type";
2457
            } else {
2458
                $sql = "UPDATE $table SET
2459
                        group_id = $parent_group_id,
2460
                        relation_type = $relation_type
2461
                        WHERE subgroup_id = $group_id";
2462
            }
2463
        }
2464
        $res = Database::query($sql);
2465
2466
        return $res;
2467
    }
2468
2469
    /**
2470
     * Filter the groups/classes info to get a name list only
2471
     * @param int $userId The user ID
2472
     * @param int $filterByType Optional. The type of group
2473
     * @return array
2474
     */
2475
    public function getNameListByUser($userId, $filterByType = null)
2476
    {
2477
        $userClasses = $this->getUserGroupListByUser($userId, $filterByType);
2478
2479
        return array_column($userClasses, 'name');
2480
    }
2481
2482
    /**
2483
     * Get the HTML necessary for display the groups/classes name list
2484
     * @param int $userId The user ID
2485
     * @param int $filterByType Optional. The type of group
2486
     * @return string
2487
     */
2488
    public function getLabelsFromNameList($userId, $filterByType = null)
2489
    {
2490
        $groupsNameListParsed = $this->getNameListByUser($userId, $filterByType);
2491
2492
        if (empty($groupsNameListParsed)) {
2493
            return '';
2494
        }
2495
2496
        $nameList = '<ul class="list-unstyled">';
2497
2498
        foreach ($groupsNameListParsed as $name) {
2499
            $nameList .= '<li>'.Display::span($name, ['class' => 'label label-info']).'</li>';
2500
        }
2501
2502
        $nameList .= '</ul>';
2503
2504
        return $nameList;
2505
    }
2506
2507
    /**
2508
     * @param array $groupInfo
2509
     * @return bool
2510
     */
2511
    public static function canLeave($groupInfo)
2512
    {
2513
        return $groupInfo['allow_members_leave_group'] == 1 ? true : false;
2514
    }
2515
}
2516