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

CourseManager::get_user_course_vote()   B

Complexity

Conditions 5
Paths 12

Size

Total Lines 32
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 20
nc 12
nop 4
dl 0
loc 32
rs 8.439
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt*/
3
4
use Chamilo\CourseBundle\ToolChain;
5
use Chamilo\CoreBundle\Entity\ExtraField as EntityExtraField;
6
use ChamiloSession as Session;
7
use Chamilo\CourseBundle\Component\CourseCopy\CourseBuilder;
8
use Chamilo\CourseBundle\Component\CourseCopy\CourseRestorer;
9
10
/**
11
 * Class CourseManager
12
 *
13
 * This is the course library for Chamilo.
14
 *
15
 * All main course functions should be placed here.
16
 *
17
 * Many functions of this library deal with providing support for
18
 * virtual/linked/combined courses (this was already used in several universities
19
 * but not available in standard Chamilo).
20
 *
21
 * There are probably some places left with the wrong code.
22
 *
23
 * @package chamilo.library
24
 */
25
class CourseManager
26
{
27
    const MAX_COURSE_LENGTH_CODE = 40;
28
    /** This constant is used to show separate user names in the course
29
     * list (userportal), footer, etc */
30
    const USER_SEPARATOR = ' |';
31
    const COURSE_FIELD_TYPE_CHECKBOX = 10;
32
    public $columns = [];
33
    public static $em;
34
    private static $manager;
35
    public static $toolList;
36
    public static $courseSettingsManager;
37
38
    /**
39
     * @param \Doctrine\ORM\EntityManager
40
     */
41
    public static function setEntityManager($em)
42
    {
43
        self::$em = $em;
44
    }
45
46
    /**
47
     * @return \Doctrine\ORM\EntityManager
48
     */
49
    public static function getEntityManager()
50
    {
51
        return self::$em;
52
    }
53
54
    public static function setCourseManager($manager)
55
    {
56
        self::$manager = $manager;
57
    }
58
59
    /**
60
     * @return SettingsManager
61
     */
62
    public static function getCourseSettingsManager()
63
    {
64
        return self::$courseSettingsManager;
65
    }
66
67
    /**
68
     * @param SettingsManager $courseSettingsManager
69
     */
70
    public static function setCourseSettingsManager($courseSettingsManager)
71
    {
72
        self::$courseSettingsManager = $courseSettingsManager;
73
    }
74
75
    /**
76
     * @return Chamilo\CoreBundle\Entity\Manager\CourseManager
77
     */
78
    public static function getManager()
79
    {
80
        return self::$manager;
81
    }
82
83
    /**
84
     * Creates a course
85
     * @param array $params columns in the main.course table
86
     * @param int $authorId
87
     * @return  mixed  false if the course was not created, array with the course info
88
     */
89
    public static function create_course($params, $authorId = 0)
90
    {
91
        global $_configuration;
92
        // Check portal limits
93
        $access_url_id = 1;
94
        if (api_get_multiple_access_url()) {
95
            $access_url_id = api_get_current_access_url_id();
96
        }
97
98
        $authorId = empty($authorId) ? api_get_user_id() : (int) $authorId;
99
100
        if (isset($_configuration[$access_url_id]) && is_array($_configuration[$access_url_id])) {
101
            $return = self::checkCreateCourseAccessUrlParam(
102
                $_configuration,
103
                $access_url_id,
104
                'hosting_limit_courses',
105
                'PortalCoursesLimitReached'
106
            );
107
            if ($return != 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...
108
                return $return;
109
            }
110
            $return = self::checkCreateCourseAccessUrlParam(
111
                $_configuration,
112
                $access_url_id,
113
                'hosting_limit_active_courses',
114
                'PortalActiveCoursesLimitReached'
115
            );
116
            if ($return != 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...
117
                return $return;
118
            }
119
        }
120
121
        if (empty($params['title'])) {
122
            return false;
123
        }
124
125
        if (empty($params['wanted_code'])) {
126
            $params['wanted_code'] = $params['title'];
127
            // Check whether the requested course code has already been occupied.
128
            $substring = api_substr($params['title'], 0, self::MAX_COURSE_LENGTH_CODE);
129
            if ($substring === false || empty($substring)) {
130
                return false;
131
            } else {
132
                $params['wanted_code'] = self::generate_course_code($substring);
133
            }
134
        }
135
        // Create the course keys
136
        $keys = AddCourse::define_course_keys($params['wanted_code']);
137
138
        $params['exemplary_content'] = isset($params['exemplary_content']) ? $params['exemplary_content'] : false;
139
140
        if (count($keys)) {
141
            $params['code'] = $keys['currentCourseCode'];
142
            $params['visual_code'] = $keys['currentCourseId'];
143
            $params['directory'] = $keys['currentCourseRepository'];
144
145
            $course_info = api_get_course_info($params['code']);
146
            if (empty($course_info)) {
147
                $course_id = AddCourse::register_course($params);
148
                $course_info = api_get_course_info_by_id($course_id);
149
150
                if (!empty($course_info)) {
151
                    self::fillCourse($course_info, $params, $authorId);
152
153
                    return $course_info;
154
                }
155
            }
156
        }
157
158
        return false;
159
    }
160
161
    /**
162
     * Returns all the information of a given course code
163
     * @param string $course_code , the course code
164
     * @return array with all the fields of the course table
165
     * @deprecated Use api_get_course_info() instead
166
     * @author Patrick Cool <[email protected]>, Ghent University
167
     * @assert ('') === false
168
     */
169
    public static function get_course_information($course_code)
170
    {
171
        return Database::fetch_array(
172
            Database::query(
173
                "SELECT *, id as real_id FROM ".Database::get_main_table(TABLE_MAIN_COURSE)."
174
                WHERE code='" . Database::escape_string($course_code)."'"
175
            ),
176
            'ASSOC'
177
        );
178
    }
179
180
    /**
181
     * Returns a list of courses. Should work with quickform syntax
182
     * @param    integer $from Offset (from the 7th = '6'). Optional.
183
     * @param    integer $howmany Number of results we want. Optional.
184
     * @param    int $orderby The column we want to order it by. Optional, defaults to first column.
185
     * @param    string $orderdirection The direction of the order (ASC or DESC). Optional, defaults to ASC.
186
     * @param    int $visibility The visibility of the course, or all by default.
187
     * @param    string $startwith If defined, only return results for which the course *title* begins with this string
188
     * @param    string $urlId The Access URL ID, if using multiple URLs
189
     * @param    bool $alsoSearchCode An extension option to indicate that we also want to search for course codes (not *only* titles)
190
     * @param    array $conditionsLike
191
     * @return array
192
     */
193
    public static function get_courses_list(
194
        $from = 0,
195
        $howmany = 0,
196
        $orderby = 1,
197
        $orderdirection = 'ASC',
198
        $visibility = -1,
199
        $startwith = '',
200
        $urlId = null,
201
        $alsoSearchCode = false,
202
        $conditionsLike = []
203
    ) {
204
        $sql = "SELECT course.* FROM ".Database::get_main_table(TABLE_MAIN_COURSE)." course ";
205
206
        if (!empty($urlId)) {
207
            $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
208
            $sql .= " INNER JOIN $table url ON (url.c_id = course.id) ";
209
        }
210
211
        if (!empty($startwith)) {
212
            $sql .= "WHERE (title LIKE '".Database::escape_string($startwith)."%' ";
213
            if ($alsoSearchCode) {
214
                $sql .= "OR code LIKE '".Database::escape_string($startwith)."%' ";
215
            }
216
            $sql .= ') ';
217
            if ($visibility !== -1 && $visibility == strval(intval($visibility))) {
218
                $sql .= " AND visibility = $visibility ";
219
            }
220
        } else {
221
            $sql .= "WHERE 1 ";
222
            if ($visibility !== -1 && $visibility == strval(intval($visibility))) {
223
                $sql .= " AND visibility = $visibility ";
224
            }
225
        }
226
227
        if (!empty($urlId)) {
228
            $urlId = intval($urlId);
229
            $sql .= " AND access_url_id= $urlId";
230
        }
231
232
        $allowedFields = [
233
            'title',
234
            'code'
235
        ];
236
237
        if (count($conditionsLike) > 0) {
238
            $sql .= ' AND ';
239
            $temp_conditions = [];
240
            foreach ($conditionsLike as $field => $value) {
241
                if (!in_array($field, $allowedFields)) {
242
                    continue;
243
                }
244
                $field = Database::escape_string($field);
245
                $value = Database::escape_string($value);
246
                $simple_like = false;
247
                if ($simple_like) {
248
                    $temp_conditions[] = $field." LIKE '$value%'";
249
                } else {
250
                    $temp_conditions[] = $field.' LIKE \'%'.$value.'%\'';
251
                }
252
            }
253
            $condition = ' AND ';
254
            if (!empty($temp_conditions)) {
255
                $sql .= implode(' '.$condition.' ', $temp_conditions);
256
            }
257
        }
258
259
        if (!empty($orderby)) {
260
            $sql .= " ORDER BY ".Database::escape_string($orderby)." ";
261
        } else {
262
            $sql .= " ORDER BY 1 ";
263
        }
264
265
        if (!in_array($orderdirection, ['ASC', 'DESC'])) {
266
            $sql .= 'ASC';
267
        } else {
268
            $sql .= ($orderdirection == 'ASC' ? 'ASC' : 'DESC');
269
        }
270
271
        if (!empty($howmany) && is_int($howmany) and $howmany > 0) {
272
            $sql .= ' LIMIT '.Database::escape_string($howmany);
273
        } else {
274
            $sql .= ' LIMIT 1000000'; //virtually no limit
275
        }
276
        if (!empty($from)) {
277
            $from = intval($from);
278
            $sql .= ' OFFSET '.intval($from);
279
        } else {
280
            $sql .= ' OFFSET 0';
281
        }
282
283
        $data = [];
284
        $res = Database::query($sql);
285
        if (Database::num_rows($res) > 0) {
286
            while ($row = Database::fetch_array($res, 'ASSOC')) {
287
                $data[] = $row;
288
            }
289
        }
290
291
        return $data;
292
    }
293
294
    /**
295
     * Returns the status of a user in a course, which is COURSEMANAGER or STUDENT.
296
     * @param   int $userId
297
     * @param   int $courseId
298
     *
299
     * @return int|bool the status of the user in that course (or false if the user is not in that course)
300
     */
301
    public static function getUserInCourseStatus($userId, $courseId)
302
    {
303
        $courseId = (int) $courseId;
304
        if (empty($courseId)) {
305
            return false;
306
        }
307
308
        $result = Database::fetch_array(
309
            Database::query(
310
                "SELECT status FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
311
                WHERE
312
                    c_id  = $courseId AND
313
                    user_id = ".intval($userId)
314
            )
315
        );
316
317
        return $result['status'];
318
    }
319
320
    /**
321
     * @param int $userId
322
     * @param int $courseId
323
     *
324
     * @return mixed
325
     */
326
    public static function getUserCourseInfo($userId, $courseId)
327
    {
328
        $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
329
                WHERE
330
                    c_id  = '".intval($courseId)."' AND
331
                    user_id = ".intval($userId);
332
        $result = Database::fetch_array(Database::query($sql));
333
334
        return $result;
335
    }
336
337
    /**
338
     * @param int  $userId
339
     * @param int  $courseId
340
     * @param bool $isTutor
341
     *
342
     * @return bool
343
     */
344
    public static function updateUserCourseTutor($userId, $courseId, $isTutor)
345
    {
346
        $table = Database::escape_string(TABLE_MAIN_COURSE_USER);
347
348
        $courseId = intval($courseId);
349
        $isTutor = intval($isTutor);
350
351
        $sql = "UPDATE $table SET is_tutor = '".$isTutor."'
352
			    WHERE
353
				    user_id = '".$userId."' AND
354
				    c_id = '".$courseId."'";
355
356
        $result = Database::query($sql);
357
358
        if (Database::affected_rows($result) > 0) {
359
            return true;
360
        } else {
361
            return false;
362
        }
363
    }
364
365
    /**
366
     * @param int $user_id
367
     * @param int $courseId
368
     *
369
     * @return mixed
370
     */
371
    public static function get_tutor_in_course_status($user_id, $courseId)
372
    {
373
        $result = Database::fetch_array(
374
            Database::query(
375
                "
376
                SELECT is_tutor
377
                FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER)."
378
                WHERE
379
                    c_id = '".Database::escape_string($courseId)."' AND
380
                    user_id = ".intval($user_id)
381
            )
382
        );
383
384
        return $result['is_tutor'];
385
    }
386
387
    /**
388
     * Unsubscribe one or more users from a course
389
     *
390
     * @param   mixed   user_id or an array with user ids
391
     * @param   string  course code
392
     * @param   int     session id
393
     * @assert ('', '') === false
394
     *
395
     */
396
    public static function unsubscribe_user($user_id, $course_code, $session_id = 0)
397
    {
398
        if (empty($user_id)) {
399
            return;
400
        }
401
        if (!is_array($user_id)) {
402
            $user_id = [$user_id];
403
        }
404
405
        if (count($user_id) == 0) {
406
            return;
407
        }
408
409
        if (!empty($session_id)) {
410
            $session_id = intval($session_id);
411
        } else {
412
            $session_id = api_get_session_id();
413
        }
414
415
        $userList = [];
416
417
        // Cleaning the $user_id variable
418
        if (is_array($user_id)) {
419
            $new_user_id_list = [];
420
            foreach ($user_id as $my_user_id) {
421
                $new_user_id_list[] = intval($my_user_id);
422
            }
423
            $new_user_id_list = array_filter($new_user_id_list);
424
            $userList = $new_user_id_list;
425
            $user_ids = implode(',', $new_user_id_list);
426
        } else {
427
            $user_ids = intval($user_id);
428
            $userList[] = $user_id;
429
        }
430
431
        $course_info = api_get_course_info($course_code);
432
        $course_id = $course_info['real_id'];
433
434
        // Unsubscribe user from all groups in the course.
435
        $sql = "DELETE FROM ".Database::get_course_table(TABLE_GROUP_USER)."
436
                WHERE c_id = $course_id AND user_id IN (".$user_ids.")";
437
        Database::query($sql);
438
        $sql = "DELETE FROM ".Database::get_course_table(TABLE_GROUP_TUTOR)."
439
                WHERE c_id = $course_id AND user_id IN (".$user_ids.")";
440
        Database::query($sql);
441
442
        // Erase user student publications (works) in the course - by André Boivin
443
444
        if (!empty($userList)) {
445
            require_once api_get_path(SYS_CODE_PATH).'work/work.lib.php';
446
            foreach ($userList as $userId) {
447
                // Getting all work from user
448
                $workList = getWorkPerUser($userId);
449
                if (!empty($workList)) {
450
                    foreach ($workList as $work) {
451
                        $work = $work['work'];
452
                        // Getting user results
453
                        if (!empty($work->user_results)) {
454
                            foreach ($work->user_results as $workSent) {
455
                                deleteWorkItem($workSent['id'], $course_info);
456
                            }
457
                        }
458
                    }
459
                }
460
            }
461
        }
462
463
        // Unsubscribe user from all blogs in the course.
464
        $sql = "DELETE FROM ".Database::get_course_table(TABLE_BLOGS_REL_USER)." 
465
                WHERE c_id = $course_id AND user_id IN (".$user_ids.")";
466
        Database::query($sql);
467
468
        $sql = "DELETE FROM ".Database::get_course_table(TABLE_BLOGS_TASKS_REL_USER)." 
469
                WHERE c_id = $course_id AND user_id IN (".$user_ids.")";
470
        Database::query($sql);
471
472
        // Deleting users in forum_notification and mailqueue course tables
473
        $sql = "DELETE FROM  ".Database::get_course_table(TABLE_FORUM_NOTIFICATION)."
474
                WHERE c_id = $course_id AND user_id IN (".$user_ids.")";
475
        Database::query($sql);
476
477
        $sql = "DELETE FROM ".Database::get_course_table(TABLE_FORUM_MAIL_QUEUE)."
478
                WHERE c_id = $course_id AND user_id IN (".$user_ids.")";
479
        Database::query($sql);
480
481
        // Unsubscribe user from the course.
482
        if (!empty($session_id)) {
483
            // Delete in table session_rel_course_rel_user
484
            $sql = "DELETE FROM ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)."
485
                    WHERE
486
                        session_id ='" . $session_id."' AND
487
                        c_id = '" . $course_id."' AND
488
                        user_id IN ($user_ids)";
489
            Database::query($sql);
490
491
            foreach ($userList as $uid) {
492
                // check if a user is register in the session with other course
493
                $sql = "SELECT user_id FROM ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)."
494
                        WHERE session_id='$session_id' AND user_id='$uid'";
495
                $rs = Database::query($sql);
496
497
                if (Database::num_rows($rs) == 0) {
498
                    // Delete in table session_rel_user
499
                    $sql = "DELETE FROM ".Database::get_main_table(TABLE_MAIN_SESSION_USER)."
500
                            WHERE
501
                                session_id ='" . $session_id."' AND
502
                                user_id = '$uid' AND
503
                                relation_type<>".SESSION_RELATION_TYPE_RRHH."";
504
                    Database::query($sql);
505
                }
506
            }
507
508
            // Update the table session
509
            $sql = "SELECT COUNT(*) FROM ".Database::get_main_table(TABLE_MAIN_SESSION_USER)."
510
                    WHERE session_id = '" . $session_id."' AND relation_type <> ".SESSION_RELATION_TYPE_RRHH;
511
            $row = Database::fetch_array(Database::query($sql));
512
            $count = $row[0];
513
            // number of users by session
514
            $sql = "UPDATE ".Database::get_main_table(TABLE_MAIN_SESSION)." SET nbr_users = '$count'
515
                    WHERE id = '".$session_id."'";
516
            Database::query($sql);
517
518
            // Update the table session_rel_course
519
            $sql = "SELECT COUNT(*) FROM ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)."
520
                    WHERE session_id = '$session_id' AND c_id = '$course_id' AND status<>2";
521
            $row = Database::fetch_array(@Database::query($sql));
522
            $count = $row[0];
523
524
            // number of users by session and course
525
            $sql = "UPDATE ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE)."
526
                    SET nbr_users = '$count'
527
                    WHERE session_id = '$session_id' AND c_id = '$course_id'";
528
            Database::query($sql);
529
530
            Event::addEvent(
531
                LOG_UNSUBSCRIBE_USER_FROM_COURSE,
532
                LOG_COURSE_CODE,
533
                $course_code,
534
                api_get_utc_datetime(),
535
                $user_id,
536
                $course_id,
537
                $session_id
538
            );
539
        } else {
540
            $sql = "DELETE FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
541
                    WHERE
542
                        user_id IN (".$user_ids.") AND
543
                        relation_type <> ".COURSE_RELATION_TYPE_RRHH." AND
544
                        c_id = '".$course_id."'";
545
            Database::query($sql);
546
547
            // add event to system log
548
            $user_id = api_get_user_id();
549
550
            Event::addEvent(
551
                LOG_UNSUBSCRIBE_USER_FROM_COURSE,
552
                LOG_COURSE_CODE,
553
                $course_code,
554
                api_get_utc_datetime(),
555
                $user_id,
556
                $course_id
557
            );
558
559
            foreach ($userList as $userId) {
560
                $userInfo = api_get_user_info($userId);
561
                Event::addEvent(
562
                    LOG_UNSUBSCRIBE_USER_FROM_COURSE,
563
                    LOG_USER_OBJECT,
564
                    $userInfo,
565
                    api_get_utc_datetime(),
566
                    $user_id,
567
                    $course_id
568
                );
569
            }
570
        }
571
    }
572
573
    /**
574
     * Subscribe a user to a course. No checks are performed here to see if
575
     * course subscription is allowed.
576
     * @param   int     $user_id
577
     * @param   string  $course_code
578
     * @param   int     $status (STUDENT, COURSEMANAGER, COURSE_ADMIN, NORMAL_COURSE_MEMBER)
579
     * @param   int $session_id
580
     * @param   int $userCourseCategoryId
581
     *
582
     * @return  bool    True on success, false on failure
583
     * @see add_user_to_course
584
     * @assert ('', '') === false
585
     */
586
    public static function subscribe_user(
587
        $user_id,
588
        $course_code,
589
        $status = STUDENT,
590
        $session_id = 0,
591
        $userCourseCategoryId = 0
592
    ) {
593
        if ($user_id != strval(intval($user_id))) {
594
            return false; //detected possible SQL injection
595
        }
596
597
        $course_code = Database::escape_string($course_code);
598
        $courseInfo = api_get_course_info($course_code);
599
        $courseId = $courseInfo['real_id'];
600
        $courseCode = $courseInfo['code'];
601
        $userCourseCategoryId = intval($userCourseCategoryId);
602
603
        if (empty($user_id) || empty($course_code)) {
604
            return false;
605
        }
606
607
        if (!empty($session_id)) {
608
            $session_id = intval($session_id);
609
        } else {
610
            $session_id = api_get_session_id();
611
        }
612
613
        $status = ($status == STUDENT || $status == COURSEMANAGER) ? $status : STUDENT;
614
615
        // A preliminary check whether the user has bben already registered on the platform.
616
        $sql = "SELECT status FROM ".Database::get_main_table(TABLE_MAIN_USER)."
617
                WHERE user_id = '$user_id' ";
618
        if (Database::num_rows(Database::query($sql)) == 0) {
619
            return false; // The user has not been registered to the platform.
620
        }
621
622
        // Check whether the user has not been already subscribed to the course.
623
        $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."                    
624
                WHERE 
625
                    user_id = '$user_id' AND 
626
                    relation_type <> ".COURSE_RELATION_TYPE_RRHH." AND 
627
                    c_id = $courseId
628
                ";
629
        if (empty($session_id)) {
630
            if (Database::num_rows(Database::query($sql)) > 0) {
631
                // The user has been already subscribed to the course.
632
                return false;
633
            }
634
        }
635
636
        if (!empty($session_id)) {
637
            SessionManager::subscribe_users_to_session_course(
638
                [$user_id],
639
                $session_id,
640
                $courseCode
641
            );
642
            // Add event to the system log
643
            Event::addEvent(
644
                LOG_SUBSCRIBE_USER_TO_COURSE,
645
                LOG_COURSE_CODE,
646
                $course_code,
647
                api_get_utc_datetime(),
648
                api_get_user_id(),
649
                $courseId,
650
                $session_id
651
            );
652
            $user_info = api_get_user_info($user_id);
653
            Event::addEvent(
654
                LOG_SUBSCRIBE_USER_TO_COURSE,
655
                LOG_USER_OBJECT,
656
                $user_info,
657
                api_get_utc_datetime(),
658
                api_get_user_id(),
659
                $courseId,
660
                $session_id
661
            );
662
        } else {
663
            self::add_user_to_course(
664
                $user_id,
665
                $courseCode,
666
                $status,
667
                $userCourseCategoryId
668
            );
669
670
            // Add event to the system log
671
            Event::addEvent(
672
                LOG_SUBSCRIBE_USER_TO_COURSE,
673
                LOG_COURSE_CODE,
674
                $course_code,
675
                api_get_utc_datetime(),
676
                api_get_user_id(),
677
                $courseId
678
            );
679
680
            $user_info = api_get_user_info($user_id);
681
            Event::addEvent(
682
                LOG_SUBSCRIBE_USER_TO_COURSE,
683
                LOG_USER_OBJECT,
684
                $user_info,
685
                api_get_utc_datetime(),
686
                api_get_user_id(),
687
                $courseId
688
            );
689
        }
690
691
        return true;
692
    }
693
694
    /**
695
     * Get the course id based on the original id and field name in the
696
     * extra fields. Returns 0 if course was not found
697
     *
698
     * @param string $original_course_id_value
699
     * @param string $original_course_id_name
700
     * @return int Course id
701
     *
702
     * @assert ('', '') === false
703
     */
704
    public static function get_course_code_from_original_id(
705
        $original_course_id_value,
706
        $original_course_id_name
707
    ) {
708
        $t_cfv = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
709
        $table_field = Database::get_main_table(TABLE_EXTRA_FIELD);
710
        $extraFieldType = EntityExtraField::COURSE_FIELD_TYPE;
711
        $original_course_id_value = Database::escape_string($original_course_id_value);
712
        $original_course_id_name = Database::escape_string($original_course_id_name);
713
714
        $sql = "SELECT item_id
715
                FROM $table_field cf
716
                INNER JOIN $t_cfv cfv
717
                ON cfv.field_id=cf.id
718
                WHERE
719
                    variable = '$original_course_id_name' AND
720
                    value = '$original_course_id_value' AND
721
                    cf.extra_field_type = $extraFieldType
722
                ";
723
        $res = Database::query($sql);
724
        $row = Database::fetch_object($res);
725
        if ($row) {
726
            return $row->item_id;
727
        } else {
728
            return 0;
729
        }
730
    }
731
732
    /**
733
     * Gets the course code from the course id. Returns null if course id was not found
734
     *
735
     * @param int $id Course id
736
     * @return string Course code
737
     * @assert ('') === false
738
     */
739
    public static function get_course_code_from_course_id($id)
740
    {
741
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
742
        $id = intval($id);
743
        $sql = "SELECT code FROM $table WHERE id = '$id' ";
744
        $res = Database::query($sql);
745
        $row = Database::fetch_object($res);
746
        if ($row) {
747
            return $row->code;
748
        } else {
749
            return null;
750
        }
751
    }
752
753
    /**
754
     * Subscribe a user $user_id to a course defined by $courseCode.
755
     * @author Hugues Peeters
756
     * @author Roan Embrechts
757
     *
758
     * @param   int $user_id the id of the user
759
     * @param   string $courseCode the course code
760
     * @param   int $status (optional) The user's status in the course
761
     * @param   int $userCourseCategoryId
762
     * @param   int The user category in which this subscription will be classified
763
     *
764
     * @return false|string true if subscription succeeds, boolean false otherwise.
765
     * @assert ('', '') === false
766
     */
767
    public static function add_user_to_course(
768
        $user_id,
769
        $courseCode,
770
        $status = STUDENT,
771
        $userCourseCategoryId = 0
772
    ) {
773
        $debug = false;
774
        $user_table = Database::get_main_table(TABLE_MAIN_USER);
775
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
776
        $course_user_table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
777
778
        $status = ($status == STUDENT || $status == COURSEMANAGER) ? $status : STUDENT;
779
        if (empty($user_id) || empty($courseCode) || ($user_id != strval(intval($user_id)))) {
780
            return false;
781
        }
782
783
        $courseCode = Database::escape_string($courseCode);
784
        $courseInfo = api_get_course_info($courseCode);
785
        $courseId = $courseInfo['real_id'];
786
787
        // Check in advance whether the user has already been registered on the platform.
788
        $sql = "SELECT status FROM ".$user_table." WHERE user_id = $user_id ";
789
        if (Database::num_rows(Database::query($sql)) == 0) {
790
            if ($debug) {
791
                error_log('The user has not been registered to the platform');
792
            }
793
            return false; // The user has not been registered to the platform.
794
        }
795
796
        // Check whether the user has already been subscribed to this course.
797
        $sql = "SELECT * FROM $course_user_table
798
                WHERE
799
                    user_id = $user_id AND
800
                    relation_type <> ".COURSE_RELATION_TYPE_RRHH." AND
801
                    c_id = $courseId";
802
        if (Database::num_rows(Database::query($sql)) > 0) {
803
            if ($debug) {
804
                error_log('The user has been already subscribed to the course');
805
            }
806
            return false; // The user has been subscribed to the course.
807
        }
808
809
        if (!api_is_course_admin()) {
810
            // Check in advance whether subscription is allowed or not for this course.
811
            $sql = "SELECT code, visibility FROM $course_table
812
                    WHERE id = $courseId AND subscribe = '".SUBSCRIBE_NOT_ALLOWED."'";
813
            if (Database::num_rows(Database::query($sql)) > 0) {
814
                if ($debug) {
815
                    error_log('Subscription is not allowed for this course');
816
                }
817
                return false; // Subscription is not allowed for this course.
818
            }
819
        }
820
821
        // Ok, subscribe the user.
822
        $max_sort = api_max_sort_value('0', $user_id);
823
        $params = [
824
            'c_id' => $courseId,
825
            'user_id' => $user_id,
826
            'status' => $status,
827
            'sort' => $max_sort + 1,
828
            'relation_type' => 0,
829
            'user_course_cat' => (int) $userCourseCategoryId
830
        ];
831
        $insertId = Database::insert($course_user_table, $params);
832
833
        return $insertId;
834
    }
835
836
    /**
837
     * Add the user $userId visibility to the course $courseCode in the catalogue.
838
     * @author David Nos (https://github.com/dnos)
839
     *
840
     * @param  int $userId the id of the user
841
     * @param  string $courseCode the course code
842
     * @param  int $visible (optional) The course visibility in the catalogue to the user (1=visible, 0=invisible)
843
     *
844
     * @return boolean true if added succesfully, false otherwise.
845
     */
846
    public static function addUserVisibilityToCourseInCatalogue(
847
        $userId,
848
        $courseCode,
849
        $visible = 1
850
    ) {
851
        $debug = false;
852
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
853
        $courseUserTable = Database::get_main_table(TABLE_MAIN_COURSE_CATALOGUE_USER);
854
        $visible = (int) $visible;
855
        if (empty($userId) || empty($courseCode) || ($userId != strval(intval($userId)))) {
856
            return false;
857
        }
858
859
        $courseCode = Database::escape_string($courseCode);
860
        $courseInfo = api_get_course_info($courseCode);
861
        $courseId = $courseInfo['real_id'];
862
863
        // Check in advance whether the user has already been registered on the platform.
864
        $sql = "SELECT status FROM ".$userTable." WHERE user_id = $userId ";
865
        if (Database::num_rows(Database::query($sql)) == 0) {
866
            if ($debug) {
867
                error_log('The user has not been registered to the platform');
868
            }
869
            return false; // The user has not been registered to the platform.
870
        }
871
872
        // Check whether the user has already been registered to the course visibility in the catalogue.
873
        $sql = "SELECT * FROM $courseUserTable
874
                WHERE
875
                    user_id = $userId AND
876
                    visible = $visible AND
877
                    c_id = $courseId";
878
        if (Database::num_rows(Database::query($sql)) > 0) {
879
            if ($debug) {
880
                error_log('The user has been already registered to the course visibility in the catalogue');
881
            }
882
            return true; // The visibility of the user to the course in the catalogue does already exist.
883
        }
884
885
        // Register the user visibility to course in catalogue.
886
        $params = [
887
            'user_id' => $userId,
888
            'c_id' => $courseId,
889
            'visible' => $visible
890
        ];
891
        $insertId = Database::insert($courseUserTable, $params);
892
893
        return $insertId;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $insertId also could return the type integer which is incompatible with the documented return type boolean.
Loading history...
894
    }
895
896
    /**
897
     * Remove the user $userId visibility to the course $courseCode in the catalogue.
898
     * @author David Nos (https://github.com/dnos)
899
     *
900
     * @param  int $userId the id of the user
901
     * @param  string $courseCode the course code
902
     * @param  int $visible (optional) The course visibility in the catalogue to the user (1=visible, 0=invisible)
903
     *
904
     * @return boolean true if removed succesfully or register not found, false otherwise.
905
     */
906
    public static function removeUserVisibilityToCourseInCatalogue(
907
        $userId,
908
        $courseCode,
909
        $visible = 1
910
    ) {
911
        $courseUserTable = Database::get_main_table(TABLE_MAIN_COURSE_CATALOGUE_USER);
912
913
        if (empty($userId) || empty($courseCode) || ($userId != strval(intval($userId)))) {
914
            return false;
915
        }
916
917
        $courseCode = Database::escape_string($courseCode);
918
        $courseInfo = api_get_course_info($courseCode);
919
        $courseId = $courseInfo['real_id'];
920
921
        // Check whether the user has already been registered to the course visibility in the catalogue.
922
        $sql = "SELECT * FROM $courseUserTable
923
                WHERE
924
                    user_id = $userId AND
925
                    visible = ".$visible." AND
926
                    c_id = $courseId";
927
        if (Database::num_rows(Database::query($sql)) > 0) {
928
            $cond = [
929
                'user_id = ? AND c_id = ? AND visible = ? ' => [
930
                    $userId,
931
                    $courseId,
932
                    $visible
933
                ]
934
            ];
935
            return Database::delete($courseUserTable, $cond);
0 ignored issues
show
Bug Best Practice introduced by
The expression return Database::delete($courseUserTable, $cond) returns the type integer which is incompatible with the documented return type boolean.
Loading history...
936
        } else {
937
            return true; // Register does not exist
938
        }
939
    }
940
941
    /**
942
     * @param string $code
943
     * @return boolean if there already are one or more courses
944
     *  with the same code OR visual_code (visualcode), false otherwise
945
     */
946
    public static function course_code_exists($code)
947
    {
948
        $code = Database::escape_string($code);
949
        $sql = "SELECT COUNT(*) as number
950
                FROM ".Database::get_main_table(TABLE_MAIN_COURSE)."
951
                WHERE code = '$code' OR visual_code = '$code'";
952
        $result = Database::fetch_array(Database::query($sql));
953
954
        return $result['number'] > 0;
955
    }
956
957
    /**
958
     * @param int $user_id
959
     * @param string $startsWith Optional
960
     * @return array An array with the course info of all the courses (real and virtual)
961
     * of which the current user is course admin.
962
     */
963
    public static function get_course_list_of_user_as_course_admin($user_id, $startsWith = '')
964
    {
965
        if ($user_id != strval(intval($user_id))) {
966
            return [];
967
        }
968
969
        // Definitions database tables and variables
970
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
971
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
972
        $user_id = intval($user_id);
973
        $data = [];
974
975
        $sql = "SELECT
976
                    course.code,
977
                    course.title,
978
                    course.id,
979
                    course.id as real_id,
980
                    course.category_code
981
                FROM $tbl_course_user as course_rel_user
982
                INNER JOIN $tbl_course as course
983
                ON course.id = course_rel_user.c_id
984
                WHERE
985
                    course_rel_user.user_id='$user_id' AND
986
                    course_rel_user.status='1'
987
        ";
988
989
        if (api_get_multiple_access_url()) {
990
            $tbl_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
991
            $access_url_id = api_get_current_access_url_id();
992
            if ($access_url_id != -1) {
993
                $sql = "
994
                    SELECT
995
                        course.code,
996
                        course.title,
997
                        course.id,
998
                        course.id as real_id
999
                    FROM $tbl_course_user as course_rel_user
1000
                    INNER JOIN $tbl_course as course
1001
                    ON course.id = course_rel_user.c_id
1002
                    INNER JOIN $tbl_course_rel_access_url course_rel_url
1003
                    ON (course_rel_url.c_id = course.id)
1004
                    WHERE
1005
                        access_url_id = $access_url_id  AND
1006
                        course_rel_user.user_id = '$user_id' AND
1007
                        course_rel_user.status = '1'
1008
                ";
1009
            }
1010
        }
1011
1012
        if (!empty($startsWith)) {
1013
            $startsWith = Database::escape_string($startsWith);
1014
1015
            $sql .= " AND (course.title LIKE '$startsWith%' OR course.code LIKE '$startsWith%')";
1016
        }
1017
1018
        $sql .= ' ORDER BY course.title';
1019
1020
        $result_nb_cours = Database::query($sql);
1021
        if (Database::num_rows($result_nb_cours) > 0) {
1022
            while ($row = Database::fetch_array($result_nb_cours, 'ASSOC')) {
1023
                $data[$row['id']] = $row;
1024
            }
1025
        }
1026
1027
        return $data;
1028
    }
1029
1030
    /**
1031
     * @param int $userId
1032
     * @param array $courseInfo
1033
     * @return boolean|null
1034
     */
1035
    public static function isUserSubscribedInCourseAsDrh($userId, $courseInfo)
1036
    {
1037
        $userId = intval($userId);
1038
1039
        if (!api_is_drh()) {
1040
            return false;
1041
        }
1042
1043
        if (empty($courseInfo) || empty($userId)) {
1044
            return false;
1045
        }
1046
1047
        $courseId = intval($courseInfo['real_id']);
1048
        $table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1049
1050
        $sql = "SELECT * FROM $table
1051
                WHERE
1052
                    user_id = $userId AND
1053
                    relation_type = ".COURSE_RELATION_TYPE_RRHH." AND
1054
                    c_id = $courseId";
1055
1056
        $result = Database::fetch_array(Database::query($sql));
1057
1058
        if (!empty($result)) {
1059
            // The user has been registered in this course.
1060
            return true;
1061
        }
1062
    }
1063
1064
    /**
1065
     * Check if user is subscribed inside a course
1066
     * @param  int $user_id
1067
     * @param  string $course_code , if this parameter is null, it'll check for all courses
1068
     * @param  bool $in_a_session True for checking inside sessions too, by default is not checked
1069
     * @return bool   $session_id true if the user is registered in the course, false otherwise
1070
     */
1071
    public static function is_user_subscribed_in_course(
1072
        $user_id,
1073
        $course_code = null,
1074
        $in_a_session = false,
1075
        $session_id = 0
1076
    ) {
1077
        $user_id = intval($user_id);
1078
1079
        if (empty($session_id)) {
1080
            $session_id = api_get_session_id();
1081
        } else {
1082
            $session_id = intval($session_id);
1083
        }
1084
1085
        $condition_course = '';
1086
        if (isset($course_code)) {
1087
            $courseInfo = api_get_course_info($course_code);
1088
            if (empty($courseInfo)) {
1089
                return false;
1090
            }
1091
            $courseId = $courseInfo['real_id'];
1092
            $condition_course = ' AND c_id = '.$courseId;
1093
        }
1094
1095
        $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
1096
                WHERE
1097
                    user_id = $user_id AND
1098
                    relation_type<>".COURSE_RELATION_TYPE_RRHH."
1099
                    $condition_course ";
1100
1101
        $result = Database::fetch_array(Database::query($sql));
1102
1103
        if (!empty($result)) {
1104
            // The user has been registered in this course.
1105
            return true;
1106
        }
1107
1108
        if (!$in_a_session) {
1109
            // The user has not been registered in this course.
1110
            return false;
1111
        }
1112
1113
        $tableSessionCourseUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
1114
        $sql = 'SELECT 1 FROM '.$tableSessionCourseUser.
1115
            ' WHERE user_id = '.$user_id.' '.$condition_course;
1116
        if (Database::num_rows(Database::query($sql)) > 0) {
1117
            return true;
1118
        }
1119
1120
        $sql = 'SELECT 1 FROM '.$tableSessionCourseUser.' WHERE user_id = '.$user_id.' AND status=2 '.$condition_course;
1121
        if (Database::num_rows(Database::query($sql)) > 0) {
1122
            return true;
1123
        }
1124
1125
        $sql = 'SELECT 1 FROM '.Database::get_main_table(TABLE_MAIN_SESSION).
1126
            ' WHERE id = '.$session_id.' AND id_coach='.$user_id;
1127
1128
        if (Database::num_rows(Database::query($sql)) > 0) {
1129
            return true;
1130
        }
1131
1132
        return false;
1133
    }
1134
1135
    /**
1136
     * Is the user a teacher in the given course?
1137
     *
1138
     * @param integer $user_id , the id (int) of the user
1139
     * @param string $course_code , the course code
1140
     *
1141
     * @return boolean if the user is a teacher in the course, false otherwise
1142
     */
1143
    public static function is_course_teacher($user_id, $course_code)
1144
    {
1145
        if ($user_id != strval(intval($user_id))) {
1146
            return false;
1147
        }
1148
1149
        $courseInfo = api_get_course_info($course_code);
1150
        if (empty($courseInfo)) {
1151
            return false;
1152
        }
1153
        $courseId = $courseInfo['real_id'];
1154
        $sql = "SELECT status FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
1155
                WHERE c_id = $courseId AND user_id = $user_id ";
1156
        $result = Database::query($sql);
1157
1158
        if (Database::num_rows($result) > 0) {
1159
            return Database::result($result, 0, 'status') == 1;
1160
        }
1161
1162
        return false;
1163
    }
1164
1165
    /**
1166
     *    Is the user subscribed in the real course or linked courses?
1167
     *
1168
     * @param int the id of the user
1169
     * @param int $courseId
1170
     * @deprecated linked_courses definition doesn't exists
1171
     * @return boolean if the user is registered in the real course or linked courses, false otherwise
1172
     */
1173
    public static function is_user_subscribed_in_real_or_linked_course($user_id, $courseId, $session_id = 0)
1174
    {
1175
        if ($user_id != strval(intval($user_id))) {
1176
            return false;
1177
        }
1178
1179
        $courseId = intval($courseId);
1180
        $session_id = intval($session_id);
1181
1182
        if (empty($session_id)) {
1183
            $result = Database::fetch_array(
1184
                Database::query(
1185
                    "SELECT *
1186
                    FROM " . Database::get_main_table(TABLE_MAIN_COURSE)." course
1187
                    LEFT JOIN " . Database::get_main_table(TABLE_MAIN_COURSE_USER)." course_user
1188
                    ON course.id = course_user.c_id
1189
                    WHERE
1190
                        course_user.user_id = '$user_id' AND
1191
                        course_user.relation_type<>".COURSE_RELATION_TYPE_RRHH." AND
1192
                        ( course.id = '$courseId')"
1193
                )
1194
            );
1195
            return !empty($result);
1196
        }
1197
1198
1199
        // From here we trust session id.
1200
        // Is he/she subscribed to the session's course?
1201
        // A user?
1202
        if (Database::num_rows(Database::query("SELECT user_id
1203
                FROM " . Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)."
1204
                WHERE session_id='".$session_id."'
1205
                AND user_id ='$user_id'"))
1206
        ) {
1207
            return true;
1208
        }
1209
1210
        // A course coach?
1211
        if (Database::num_rows(Database::query("SELECT user_id
1212
                FROM ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)."
1213
                WHERE session_id='".$session_id."'
1214
                AND user_id = '$user_id' AND status = 2
1215
                AND c_id = '$courseId'"))
1216
        ) {
1217
            return true;
1218
        }
1219
1220
        // A session coach?
1221
        if (Database::num_rows(Database::query("SELECT id_coach
1222
                FROM " . Database::get_main_table(TABLE_MAIN_SESSION)." AS session
1223
                WHERE session.id='".$session_id."'
1224
                AND id_coach = '$user_id'"))
1225
        ) {
1226
            return true;
1227
        }
1228
1229
        return false;
1230
    }
1231
1232
    /**
1233
     * Return user info array of all users registered in a course
1234
     * This only returns the users that are registered in this actual course, not linked courses.
1235
     * @param string $course_code
1236
     * @param int $session_id
1237
     * @param string $limit
1238
     * @param string $order_by the field to order the users by.
1239
     * Valid values are 'lastname', 'firstname', 'username', 'email', 'official_code' OR a part of a SQL statement
1240
     * that starts with ORDER BY ...
1241
     * @param integer|null $filter_by_status if using the session_id: 0 or 2 (student, coach),
1242
     * if using session_id = 0 STUDENT or COURSEMANAGER
1243
     * @param boolean|null $return_count
1244
     * @param bool $add_reports
1245
     * @param bool $resumed_report
1246
     * @param array $extra_field
1247
     * @param array $courseCodeList
1248
     * @param array $userIdList
1249
     * @param string $filterByActive
1250
     * @param array $sessionIdList
1251
     * @return array|int
1252
     */
1253
    public static function get_user_list_from_course_code(
1254
        $course_code = null,
1255
        $session_id = 0,
1256
        $limit = null,
1257
        $order_by = null,
1258
        $filter_by_status = null,
1259
        $return_count = null,
1260
        $add_reports = false,
1261
        $resumed_report = false,
1262
        $extra_field = [],
1263
        $courseCodeList = [],
1264
        $userIdList = [],
1265
        $filterByActive = null,
1266
        $sessionIdList = []
1267
    ) {
1268
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1269
        $sessionTable = Database::get_main_table(TABLE_MAIN_SESSION);
1270
1271
        $session_id = intval($session_id);
1272
        $course_code = Database::escape_string($course_code);
1273
        $courseInfo = api_get_course_info($course_code);
1274
        $courseId = 0;
1275
        if (!empty($courseInfo)) {
1276
            $courseId = $courseInfo['real_id'];
1277
        }
1278
1279
        $where = [];
1280
        if (empty($order_by)) {
1281
            $order_by = 'user.lastname, user.firstname';
1282
            if (api_is_western_name_order()) {
1283
                $order_by = 'user.firstname, user.lastname';
1284
            }
1285
        }
1286
1287
        // if the $order_by does not contain 'ORDER BY'
1288
        // we have to check if it is a valid field that can be sorted on
1289
        if (!strstr($order_by, 'ORDER BY')) {
1290
            if (!empty($order_by)) {
1291
                $order_by = 'ORDER BY '.$order_by;
1292
            } else {
1293
                $order_by = '';
1294
            }
1295
        }
1296
1297
        $filter_by_status_condition = null;
1298
1299
        if (!empty($session_id) || !empty($sessionIdList)) {
1300
            $sql = 'SELECT DISTINCT
1301
                        user.user_id,
1302
                        user.email,
1303
                        session_course_user.status as status_session,
1304
                        session_id,
1305
                        user.*,
1306
                        course.*,
1307
                        session.name as session_name
1308
                    ';
1309
            if ($return_count) {
1310
                $sql = " SELECT COUNT(user.user_id) as count";
1311
            }
1312
1313
            $sessionCondition = " session_course_user.session_id = $session_id";
1314
            if (!empty($sessionIdList)) {
1315
                $sessionIdListTostring = implode("','", array_map('intval', $sessionIdList));
1316
                $sessionCondition = " session_course_user.session_id IN ('$sessionIdListTostring') ";
1317
            }
1318
1319
            $courseCondition = " course.id = $courseId";
1320
            if (!empty($courseCodeList)) {
1321
                $courseCodeListForSession = array_map(['Database', 'escape_string'], $courseCodeList);
1322
                $courseCodeListForSession = implode('","', $courseCodeListForSession);
1323
                $courseCondition = ' course.code IN ("'.$courseCodeListForSession.'")  ';
1324
            }
1325
1326
            $sql .= ' FROM '.Database::get_main_table(TABLE_MAIN_USER).' as user ';
1327
            $sql .= " LEFT JOIN ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)." as session_course_user
1328
                      ON
1329
                        user.id = session_course_user.user_id AND
1330
                        $sessionCondition
1331
                        INNER JOIN $course_table course 
1332
                        ON session_course_user.c_id = course.id AND
1333
                        $courseCondition
1334
                        INNER JOIN $sessionTable session 
1335
                        ON session_course_user.session_id = session.id
1336
                   ";
1337
            $where[] = ' session_course_user.c_id IS NOT NULL ';
1338
1339
            // 2 = coach
1340
            // 0 = student
1341
            if (isset($filter_by_status)) {
1342
                $filter_by_status = intval($filter_by_status);
1343
                $filter_by_status_condition = " session_course_user.status = $filter_by_status AND ";
1344
            }
1345
        } else {
1346
            if ($return_count) {
1347
                $sql = " SELECT COUNT(*) as count";
1348
            } else {
1349
                if (empty($course_code)) {
1350
                    $sql = 'SELECT DISTINCT
1351
                                course.title,
1352
                                course.code,
1353
                                course_rel_user.status as status_rel,
1354
                                user.id as user_id,
1355
                                user.email,
1356
                                course_rel_user.is_tutor,
1357
                                user.*  ';
1358
                } else {
1359
                    $sql = 'SELECT DISTINCT
1360
                                course_rel_user.status as status_rel,
1361
                                user.id as user_id,
1362
                                user.email,
1363
                                course_rel_user.is_tutor,
1364
                                user.*  ';
1365
                }
1366
            }
1367
1368
            $sql .= ' FROM '.Database::get_main_table(TABLE_MAIN_USER).' as user '
1369
                  . ' LEFT JOIN '.Database::get_main_table(TABLE_MAIN_COURSE_USER).' as course_rel_user
1370
                      ON 
1371
                        user.id = course_rel_user.user_id AND
1372
                        course_rel_user.relation_type <> ' . COURSE_RELATION_TYPE_RRHH.'  '
1373
                  . " INNER JOIN $course_table course ON course_rel_user.c_id = course.id ";
1374
1375
            if (!empty($course_code)) {
1376
                $sql .= ' AND course_rel_user.c_id = "'.$courseId.'"';
1377
            }
1378
            $where[] = ' course_rel_user.c_id IS NOT NULL ';
1379
1380
            if (isset($filter_by_status) && is_numeric($filter_by_status)) {
1381
                $filter_by_status = intval($filter_by_status);
1382
                $filter_by_status_condition = " course_rel_user.status = $filter_by_status AND ";
1383
            }
1384
        }
1385
1386
        $multiple_access_url = api_get_multiple_access_url();
1387
        if ($multiple_access_url) {
1388
            $sql .= ' LEFT JOIN '.Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER).' au
1389
                      ON (au.user_id = user.id) ';
1390
        }
1391
1392
        $extraFieldWasAdded = false;
1393
        if ($return_count && $resumed_report) {
1394
            foreach ($extra_field as $extraField) {
1395
                $extraFieldInfo = UserManager::get_extra_field_information_by_name($extraField);
1396
                if (!empty($extraFieldInfo)) {
1397
                    $fieldValuesTable = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
1398
                    $sql .= ' LEFT JOIN '.$fieldValuesTable.' as ufv
1399
                            ON (
1400
                                user.id = ufv.item_id AND
1401
                                (field_id = '.$extraFieldInfo['id'].' OR field_id IS NULL)
1402
                            )';
1403
                    $extraFieldWasAdded = true;
1404
                }
1405
            }
1406
        }
1407
1408
        $sql .= ' WHERE '.$filter_by_status_condition.' '.implode(' OR ', $where);
1409
1410
        if ($multiple_access_url) {
1411
            $current_access_url_id = api_get_current_access_url_id();
1412
            $sql .= " AND (access_url_id =  $current_access_url_id ) ";
1413
        }
1414
1415
        if ($return_count && $resumed_report && $extraFieldWasAdded) {
1416
            $sql .= ' AND field_id IS NOT NULL GROUP BY value ';
1417
        }
1418
1419
        if (!empty($courseCodeList)) {
1420
            $courseCodeList = array_map(['Database', 'escape_string'], $courseCodeList);
1421
            $courseCodeList = implode('","', $courseCodeList);
1422
            if (empty($sessionIdList)) {
1423
                $sql .= ' AND course.code IN ("'.$courseCodeList.'")';
1424
            }
1425
        }
1426
1427
        if (!empty($userIdList)) {
1428
            $userIdList = array_map('intval', $userIdList);
1429
            $userIdList = implode('","', $userIdList);
1430
            $sql .= ' AND user.id IN ("'.$userIdList.'")';
1431
        }
1432
1433
        if (isset($filterByActive)) {
1434
            $filterByActive = intval($filterByActive);
1435
            $sql .= ' AND user.active = '.$filterByActive;
1436
        }
1437
1438
        $sql .= ' '.$order_by.' '.$limit;
1439
1440
        $rs = Database::query($sql);
1441
        $users = [];
1442
1443
        $extra_fields = UserManager::get_extra_fields(
1444
            0,
1445
            100,
1446
            null,
1447
            null,
1448
            true,
1449
            true
1450
        );
1451
1452
        $counter = 1;
1453
        $count_rows = Database::num_rows($rs);
1454
1455
        if ($return_count && $resumed_report) {
1456
            return $count_rows;
1457
        }
1458
1459
        $table_user_field_value = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
1460
        $tableExtraField = Database::get_main_table(TABLE_EXTRA_FIELD);
1461
        if ($count_rows) {
1462
            while ($user = Database::fetch_array($rs)) {
1463
                if ($return_count) {
1464
                    return $user['count'];
1465
                }
1466
                $report_info = [];
1467
                $user_info = $user;
1468
                $user_info['status'] = $user['status'];
1469
                if (isset($user['is_tutor'])) {
1470
                    $user_info['is_tutor'] = $user['is_tutor'];
1471
                }
1472
                if (!empty($session_id)) {
1473
                    $user_info['status_session'] = $user['status_session'];
1474
                }
1475
1476
                $sessionId = isset($user['session_id']) ? $user['session_id'] : 0;
1477
                $course_code = isset($user['code']) ? $user['code'] : null;
1478
1479
                if ($add_reports) {
1480
                    if ($resumed_report) {
1481
                        $extra = [];
1482
1483
                        if (!empty($extra_fields)) {
1484
                            foreach ($extra_fields as $extra) {
1485
                                if (in_array($extra['1'], $extra_field)) {
1486
                                    $user_data = UserManager::get_extra_user_data_by_field(
1487
                                        $user['user_id'],
1488
                                        $extra['1']
1489
                                    );
1490
                                    break;
1491
                                }
1492
                            }
1493
                        }
1494
1495
                        $row_key = '-1';
1496
                        $name = '-';
1497
1498
                        if (!empty($extra)) {
1499
                            if (!empty($user_data[$extra['1']])) {
1500
                                $row_key = $user_data[$extra['1']];
1501
                                $name = $user_data[$extra['1']];
1502
                                $users[$row_key]['extra_'.$extra['1']] = $name;
1503
                            }
1504
                        }
1505
1506
                        $users[$row_key]['training_hours'] += Tracking::get_time_spent_on_the_course(
1507
                            $user['user_id'],
1508
                            $courseId,
1509
                            $sessionId
1510
                        );
1511
1512
                        $users[$row_key]['count_users'] += $counter;
1513
1514
                        $registered_users_with_extra_field = self::getCountRegisteredUsersWithCourseExtraField(
1515
                            $name,
1516
                            $tableExtraField,
1517
                            $table_user_field_value
1518
                        );
1519
1520
                        $users[$row_key]['count_users_registered'] = $registered_users_with_extra_field;
1521
                        $users[$row_key]['average_hours_per_user'] = $users[$row_key]['training_hours'] / $users[$row_key]['count_users'];
1522
1523
                        $category = Category:: load(
1524
                            null,
1525
                            null,
1526
                            $course_code,
1527
                            null,
1528
                            null,
1529
                            $sessionId
1530
                        );
1531
1532
                        if (!isset($users[$row_key]['count_certificates'])) {
1533
                            $users[$row_key]['count_certificates'] = 0;
1534
                        }
1535
1536
                        if (isset($category[0]) && $category[0]->is_certificate_available($user['user_id'])) {
1537
                            $users[$row_key]['count_certificates']++;
1538
                        }
1539
1540
                        foreach ($extra_fields as $extra) {
1541
                            if ($extra['1'] == 'ruc') {
1542
                                continue;
1543
                            }
1544
1545
                            if (!isset($users[$row_key][$extra['1']])) {
1546
                                $user_data = UserManager::get_extra_user_data_by_field($user['user_id'], $extra['1']);
1547
                                if (!empty($user_data[$extra['1']])) {
1548
                                    $users[$row_key][$extra['1']] = $user_data[$extra['1']];
1549
                                }
1550
                            }
1551
                        }
1552
                    } else {
1553
                        $sessionName = !empty($sessionId) ? ' - '.$user['session_name'] : '';
1554
                        $report_info['course'] = $user['title'].$sessionName;
1555
                        $report_info['user'] = api_get_person_name($user['firstname'], $user['lastname']);
1556
                        $report_info['email'] = $user['email'];
1557
                        $report_info['time'] = api_time_to_hms(
1558
                            Tracking::get_time_spent_on_the_course(
1559
                                $user['user_id'],
1560
                                $courseId,
1561
                                $sessionId
1562
                            )
1563
                        );
1564
1565
                        $category = Category:: load(
1566
                            null,
1567
                            null,
1568
                            $course_code,
1569
                            null,
1570
                            null,
1571
                            $sessionId
1572
                        );
1573
1574
                        $report_info['certificate'] = Display::label(get_lang('No'));
1575
                        if (isset($category[0]) && $category[0]->is_certificate_available($user['user_id'])) {
1576
                            $report_info['certificate'] = Display::label(get_lang('Yes'), 'success');
1577
                        }
1578
1579
                        $progress = intval(
1580
                            Tracking::get_avg_student_progress(
1581
                                $user['user_id'],
1582
                                $course_code,
1583
                                [],
1584
                                $sessionId
1585
                            )
1586
                        );
1587
                        $report_info['progress_100'] = $progress == 100 ? Display::label(get_lang('Yes'), 'success') : Display::label(get_lang('No'));
1588
                        $report_info['progress'] = $progress."%";
1589
1590
                        foreach ($extra_fields as $extra) {
1591
                            $user_data = UserManager::get_extra_user_data_by_field($user['user_id'], $extra['1']);
1592
                            $report_info[$extra['1']] = $user_data[$extra['1']];
1593
                        }
1594
                        $report_info['user_id'] = $user['user_id'];
1595
                        $users[] = $report_info;
1596
                    }
1597
                } else {
1598
                    $users[$user['user_id']] = $user_info;
1599
                }
1600
            }
1601
        }
1602
1603
        return $users;
1604
    }
1605
1606
    /**
1607
     * @param bool $resumed_report
1608
     * @param array $extra_field
1609
     * @param array $courseCodeList
1610
     * @param array $userIdList
1611
     * @param array $sessionIdList
1612
     * @return array|int
1613
     */
1614
    public static function get_count_user_list_from_course_code(
1615
        $resumed_report = false,
1616
        $extra_field = [],
1617
        $courseCodeList = [],
1618
        $userIdList = [],
1619
        $sessionIdList = []
1620
    ) {
1621
        return self::get_user_list_from_course_code(
1622
            null,
1623
            0,
1624
            null,
1625
            null,
1626
            null,
1627
            true,
1628
            false,
1629
            $resumed_report,
1630
            $extra_field,
1631
            $courseCodeList,
1632
            $userIdList,
1633
            null,
1634
            $sessionIdList
1635
        );
1636
    }
1637
1638
    /**
1639
     * Gets subscribed users in a course or in a course/session
1640
     *
1641
     * @param   string $course_code
1642
     * @param   int $session_id
1643
     * @return  int
1644
     */
1645
    public static function get_users_count_in_course(
1646
        $course_code,
1647
        $session_id = 0,
1648
        $status = null
1649
    ) {
1650
        // variable initialisation
1651
        $session_id = intval($session_id);
1652
        $course_code = Database::escape_string($course_code);
1653
        $tblUser = Database::get_main_table(TABLE_MAIN_USER);
1654
        $tblSessionCourseUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
1655
        $tblCourseUser = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1656
        $tblUrlUser = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
1657
1658
        $courseInfo = api_get_course_info($course_code);
1659
        $courseId = $courseInfo['real_id'];
1660
1661
        $sql = "
1662
            SELECT DISTINCT count(user.id) as count  
1663
            FROM $tblUser as user
1664
        ";
1665
        $where = [];
1666
        if (!empty($session_id)) {
1667
            $sql .= "
1668
                LEFT JOIN $tblSessionCourseUser as session_course_user
1669
                    ON user.user_id = session_course_user.user_id
1670
                    AND session_course_user.c_id = $courseId
1671
                    AND session_course_user.session_id = $session_id
1672
            ";
1673
1674
            $where[] = ' session_course_user.c_id IS NOT NULL ';
1675
        } else {
1676
            $sql .= "
1677
                LEFT JOIN $tblCourseUser as course_rel_user
1678
                    ON user.user_id = course_rel_user.user_id
1679
                    AND course_rel_user.relation_type <> ".COURSE_RELATION_TYPE_RRHH."
1680
                    AND course_rel_user.c_id = $courseId
1681
            ";
1682
            $where[] = ' course_rel_user.c_id IS NOT NULL ';
1683
        }
1684
1685
        $multiple_access_url = api_get_multiple_access_url();
1686
        if ($multiple_access_url) {
1687
            $sql .= " LEFT JOIN $tblUrlUser au ON (au.user_id = user.user_id) ";
1688
        }
1689
1690
        $sql .= ' WHERE '.implode(' OR ', $where);
1691
1692
        if ($multiple_access_url) {
1693
            $current_access_url_id = api_get_current_access_url_id();
1694
            $sql .= " AND (access_url_id =  $current_access_url_id ) ";
1695
        }
1696
        $rs = Database::query($sql);
1697
        $count = 0;
1698
        if (Database::num_rows($rs)) {
1699
            $user = Database::fetch_array($rs);
1700
            $count = $user['count'];
1701
        }
1702
1703
        return $count;
1704
    }
1705
1706
    /**
1707
     * Get a list of coaches of a course and a session
1708
     * @param   string  $course_code
1709
     * @param   int     $session_id
1710
     * @param   bool $addGeneralCoach
1711
     * @return  array   List of users
1712
     */
1713
    public static function get_coach_list_from_course_code(
1714
        $course_code,
1715
        $session_id,
1716
        $addGeneralCoach = true
1717
    ) {
1718
        if (empty($course_code) || empty($session_id)) {
1719
            return [];
1720
        }
1721
1722
        $course_code = Database::escape_string($course_code);
1723
        $courseInfo = api_get_course_info($course_code);
1724
        $courseId = $courseInfo['real_id'];
1725
        $session_id = intval($session_id);
1726
        $users = [];
1727
1728
        // We get the coach for the given course in a given session.
1729
        $sql = 'SELECT user_id FROM '.Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER).
1730
               ' WHERE session_id ="'.$session_id.'" AND c_id="'.$courseId.'" AND status = 2';
1731
        $rs = Database::query($sql);
1732
        while ($user = Database::fetch_array($rs)) {
1733
            $userInfo = api_get_user_info($user['user_id']);
1734
            if ($userInfo) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $userInfo 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...
1735
                $users[$user['user_id']] = $userInfo;
1736
            }
1737
        }
1738
1739
        if ($addGeneralCoach) {
1740
            $table = Database::get_main_table(TABLE_MAIN_SESSION);
1741
            // We get the session coach.
1742
            $sql = 'SELECT id_coach FROM '.$table.' WHERE id='.$session_id;
1743
            $rs = Database::query($sql);
1744
            $session_id_coach = Database::result($rs, 0, 'id_coach');
1745
            $userInfo = api_get_user_info($session_id_coach);
1746
            if ($userInfo) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $userInfo 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...
1747
                $users[$session_id_coach] = $userInfo;
1748
            }
1749
        }
1750
1751
        return $users;
1752
    }
1753
1754
    /**
1755
     *  Return user info array of all users registered in a course
1756
     *  This only returns the users that are registered in this actual course, not linked courses.
1757
     *
1758
     * @param string $course_code
1759
     * @param boolean $with_session
1760
     * @param integer $session_id
1761
     * @param string $date_from
1762
     * @param string $date_to
1763
     * @param boolean $includeInvitedUsers Whether include the invited users
1764
     * @param int $groupId
1765
     * @return array with user id
1766
     */
1767
    public static function get_student_list_from_course_code(
1768
        $course_code,
1769
        $with_session = false,
1770
        $session_id = 0,
1771
        $date_from = null,
1772
        $date_to = null,
1773
        $includeInvitedUsers = true,
1774
        $groupId = 0
1775
    ) {
1776
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
1777
        $session_id = intval($session_id);
1778
        $course_code = Database::escape_string($course_code);
1779
        $courseInfo = api_get_course_info($course_code);
1780
        $courseId = $courseInfo['real_id'];
1781
        $students = [];
1782
1783
        if ($session_id == 0) {
1784
            if (empty($groupId)) {
1785
                // students directly subscribed to the course
1786
                $sql = "SELECT *
1787
                        FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)." cu
1788
                        INNER JOIN $userTable u
1789
                        ON cu.user_id = u.user_id
1790
                        WHERE c_id = '$courseId' AND cu.status = ".STUDENT;
1791
1792
                if (!$includeInvitedUsers) {
1793
                    $sql .= " AND u.status != ".INVITEE;
1794
                }
1795
                $rs = Database::query($sql);
1796
                while ($student = Database::fetch_array($rs)) {
1797
                    $students[$student['user_id']] = $student;
1798
                }
1799
            } else {
1800
                $students = GroupManager::get_users(
1801
                    $groupId,
1802
                    false,
1803
                    null,
1804
                    null,
1805
                    false,
1806
                    $courseInfo['real_id']
1807
                );
1808
                $students = array_flip($students);
1809
            }
1810
        }
1811
1812
        // students subscribed to the course through a session
1813
        if ($with_session) {
1814
            $joinSession = '';
1815
            //Session creation date
1816
            if (!empty($date_from) && !empty($date_to)) {
1817
                $joinSession = "INNER JOIN ".Database::get_main_table(TABLE_MAIN_SESSION)." s";
1818
            }
1819
1820
            $sql_query = "SELECT *
1821
                          FROM " . Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)." scu
1822
                          $joinSession
1823
                          INNER JOIN $userTable u ON scu.user_id = u.user_id
1824
                          WHERE scu.c_id = '$courseId' AND scu.status <> 2";
1825
1826
            if (!empty($date_from) && !empty($date_to)) {
1827
                $date_from = Database::escape_string($date_from);
1828
                $date_to = Database::escape_string($date_to);
1829
                $sql_query .= " AND s.access_start_date >= '$date_from' AND s.access_end_date <= '$date_to'";
1830
            }
1831
1832
            if ($session_id != 0) {
1833
                $sql_query .= ' AND scu.session_id = '.$session_id;
1834
            }
1835
1836
            if (!$includeInvitedUsers) {
1837
                $sql_query .= " AND u.status != ".INVITEE;
1838
            }
1839
1840
            $rs = Database::query($sql_query);
1841
            while ($student = Database::fetch_array($rs)) {
1842
                $students[$student['user_id']] = $student;
1843
            }
1844
        }
1845
1846
        return $students;
1847
    }
1848
1849
    /**
1850
     * Return user info array of all teacher-users registered in a course
1851
     * This only returns the users that are registered in this actual course, not linked courses.
1852
     *
1853
     * @param string $course_code
1854
     * @return array with user id
1855
     */
1856
    public static function get_teacher_list_from_course_code($course_code)
1857
    {
1858
        $courseInfo = api_get_course_info($course_code);
1859
        $courseId = $courseInfo['real_id'];
1860
        if (empty($courseId)) {
1861
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type array.
Loading history...
1862
        }
1863
1864
        $sql = "SELECT DISTINCT
1865
                    u.id as user_id,
1866
                    u.lastname,
1867
                    u.firstname,
1868
                    u.email,
1869
                    u.username,
1870
                    u.status
1871
                FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER)." cu
1872
                INNER JOIN " . Database::get_main_table(TABLE_MAIN_USER)." u
1873
                ON (cu.user_id = u.id)
1874
                WHERE
1875
                    cu.c_id = $courseId AND
1876
                    cu.status = 1 ";
1877
        $rs = Database::query($sql);
1878
        $teachers = [];
1879
        while ($teacher = Database::fetch_array($rs)) {
1880
            $teachers[$teacher['user_id']] = $teacher;
1881
        }
1882
1883
        return $teachers;
1884
    }
1885
1886
    /**
1887
     * Return user info array of all teacher-users registered in a course
1888
     * This only returns the users that are registered in this actual course, not linked courses.
1889
     *
1890
     * @param int $courseId
1891
     * @param bool $loadAvatars
1892
     *
1893
     * @return array with user id
1894
     */
1895
    public static function getTeachersFromCourse($courseId, $loadAvatars = true)
1896
    {
1897
        $courseId = (int) $courseId;
1898
1899
        if (empty($courseId)) {
1900
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type array.
Loading history...
1901
        }
1902
1903
        $sql = "SELECT DISTINCT
1904
                    u.id as user_id,
1905
                    u.lastname,
1906
                    u.firstname,
1907
                    u.email,
1908
                    u.username,
1909
                    u.status
1910
                FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER)." cu
1911
                INNER JOIN " . Database::get_main_table(TABLE_MAIN_USER)." u
1912
                ON (cu.user_id = u.id)
1913
                WHERE
1914
                    cu.c_id = $courseId AND
1915
                    cu.status = 1 ";
1916
        $rs = Database::query($sql);
1917
        $listTeachers = [];
1918
        $teachers = [];
1919
        $url = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&course_id='.$courseId;
1920
        while ($teacher = Database::fetch_array($rs)) {
1921
            $teachers['id'] = $teacher['user_id'];
1922
            $teachers['lastname'] = $teacher['lastname'];
1923
            $teachers['firstname'] = $teacher['firstname'];
1924
            $teachers['email'] = $teacher['email'];
1925
            $teachers['username'] = $teacher['username'];
1926
            $teachers['status'] = $teacher['status'];
1927
            $teachers['fullname'] = api_get_person_name($teacher['firstname'], $teacher['lastname']);
1928
            $teachers['avatar'] = '';
1929
            if ($loadAvatars) {
1930
                $userPicture = UserManager::getUserPicture($teacher['user_id'], USER_IMAGE_SIZE_SMALL);
1931
                $teachers['avatar'] = $userPicture;
1932
            }
1933
            $teachers['url'] = $url.'&user_id='.$teacher['user_id'];
1934
            $listTeachers[] = $teachers;
1935
        }
1936
1937
        return $listTeachers;
1938
    }
1939
1940
    /**
1941
     * Returns a string list of teachers assigned to the given course
1942
     * @param string $course_code
1943
     * @param string $separator between teachers names
1944
     * @param bool $add_link_to_profile Whether to add a link to the teacher's profile
1945
     * @param bool $orderList
1946
     * @return string List of teachers teaching the course
1947
     */
1948
    public static function getTeacherListFromCourseCodeToString(
1949
        $course_code,
1950
        $separator = self::USER_SEPARATOR,
1951
        $add_link_to_profile = false,
1952
        $orderList = false
1953
    ) {
1954
        $teacher_list = self::get_teacher_list_from_course_code($course_code);
1955
        $html = '';
1956
        $list = [];
1957
        if (!empty($teacher_list)) {
1958
            foreach ($teacher_list as $teacher) {
1959
                $teacher_name = api_get_person_name(
1960
                    $teacher['firstname'],
1961
                    $teacher['lastname']
1962
                );
1963
                if ($add_link_to_profile) {
1964
                    $url = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&user_id='.$teacher['user_id'];
1965
                    $teacher_name = Display::url(
1966
                        $teacher_name,
1967
                        $url,
1968
                        [
1969
                            'class' => 'ajax',
1970
                            'data-title' => $teacher_name
1971
                        ]
1972
                    );
1973
                }
1974
                $list[] = $teacher_name;
1975
            }
1976
1977
            if (!empty($list)) {
1978
                if ($orderList === true) {
1979
                    $html .= '<ul class="user-teacher">';
1980
                    foreach ($list as $teacher) {
1981
                        $html .= '<li>';
1982
                        $html .= Display::return_icon('teacher.png', '', null, ICON_SIZE_TINY);
1983
                        $html .= ' '.$teacher;
1984
                        $html .= '</li>';
1985
                    }
1986
                    $html .= '</ul>';
1987
                } else {
1988
                    $html .= array_to_string($list, $separator);
1989
                }
1990
            }
1991
        }
1992
1993
        return $html;
1994
    }
1995
1996
    /**
1997
     * This function returns information about coachs from a course in session
1998
     * @param int $session_id
1999
     * @param int $courseId
2000
     *
2001
     * @return array containing user_id, lastname, firstname, username
2002
     */
2003
    public static function get_coachs_from_course($session_id = 0, $courseId = 0)
2004
    {
2005
        if (!empty($session_id)) {
2006
            $session_id = intval($session_id);
2007
        } else {
2008
            $session_id = api_get_session_id();
2009
        }
2010
2011
        if (!empty($courseId)) {
2012
            $courseId = intval($courseId);
2013
        } else {
2014
            $courseId = api_get_course_int_id();
2015
        }
2016
2017
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
2018
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2019
2020
        $sql = "SELECT DISTINCT 
2021
                    u.user_id,
2022
                    u.lastname,
2023
                    u.firstname,
2024
                    u.username
2025
                FROM $tbl_user u 
2026
                INNER JOIN $tbl_session_course_user scu
2027
                ON (u.user_id = scu.user_id)
2028
                WHERE
2029
                    scu.session_id = '$session_id' AND
2030
                    scu.c_id = '$courseId' AND
2031
                    scu.status = 2";
2032
        $rs = Database::query($sql);
2033
2034
        $coaches = [];
2035
        if (Database::num_rows($rs) > 0) {
2036
            while ($row = Database::fetch_array($rs)) {
2037
                $completeName = api_get_person_name($row['firstname'], $row['lastname']);
2038
                $coaches[] = $row + ['full_name' => $completeName];
2039
            }
2040
        }
2041
2042
        return $coaches;
2043
    }
2044
2045
    /**
2046
     * @param int $session_id
2047
     * @param int $courseId
2048
     * @param string $separator
2049
     * @param bool $add_link_to_profile
2050
     * @param bool $orderList
2051
     * @return string
2052
     */
2053
    public static function get_coachs_from_course_to_string(
2054
        $session_id = 0,
2055
        $courseId = 0,
2056
        $separator = self::USER_SEPARATOR,
2057
        $add_link_to_profile = false,
2058
        $orderList = false
2059
    ) {
2060
        $coachList = self::get_coachs_from_course($session_id, $courseId);
2061
        $course_coachs = [];
2062
        if (!empty($coachList)) {
2063
            foreach ($coachList as $coach_course) {
2064
                $coach_name = $coach_course['full_name'];
2065
                if ($add_link_to_profile) {
2066
                    $url = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&user_id='.$coach_course['user_id'].'&course_id='.$courseId.'&session_id='.$session_id;
2067
                    $coach_name = Display::url(
2068
                        $coach_name,
2069
                        $url,
2070
                        [
2071
                            'class' => 'ajax',
2072
                            'data-title' => $coach_name
2073
                        ]
2074
                    );
2075
                }
2076
                $course_coachs[] = $coach_name;
2077
            }
2078
        }
2079
2080
        $html = '';
2081
        if (!empty($course_coachs)) {
2082
            if ($orderList === true) {
2083
                $html .= '<ul class="user-coachs">';
2084
                foreach ($course_coachs as $coachs) {
2085
                    $html .= Display::tag(
2086
                        'li',
2087
                        Display::return_icon(
2088
                            'teacher.png',
2089
                            $coachs,
2090
                            null,
2091
                            ICON_SIZE_TINY
2092
                        ).' '.$coachs
2093
                    );
2094
                }
2095
                $html .= '</ul>';
2096
            } else {
2097
                $html = array_to_string($course_coachs, $separator);
2098
            }
2099
        }
2100
2101
        return $html;
2102
    }
2103
2104
    /**
2105
     * Get the list of groups from the course
2106
     * @param   string $course_code
2107
     * @param   int $session_id Session ID (optional)
2108
     * @param   integer $in_get_empty_group get empty groups (optional)
2109
     * @return  array   List of groups info
2110
     */
2111
    public static function get_group_list_of_course(
2112
        $course_code,
2113
        $session_id = 0,
2114
        $in_get_empty_group = 0
2115
    ) {
2116
        $course_info = api_get_course_info($course_code);
2117
2118
        if (empty($course_info)) {
2119
            return [];
2120
        }
2121
        $course_id = $course_info['real_id'];
2122
2123
        if (empty($course_id)) {
2124
            return [];
2125
        }
2126
2127
        $group_list = [];
2128
        $session_id != 0 ? $session_condition = ' WHERE g.session_id IN(1,'.intval($session_id).')' : $session_condition = ' WHERE g.session_id = 0';
2129
2130
        if ($in_get_empty_group == 0) {
2131
            // get only groups that are not empty
2132
            $sql = "SELECT DISTINCT g.id, g.iid, g.name
2133
                    FROM ".Database::get_course_table(TABLE_GROUP)." AS g
2134
                    INNER JOIN ".Database::get_course_table(TABLE_GROUP_USER)." gu
2135
                    ON (g.id = gu.group_id AND g.c_id = $course_id AND gu.c_id = $course_id)
2136
                    $session_condition
2137
                    ORDER BY g.name";
2138
        } else {
2139
            // get all groups even if they are empty
2140
            $sql = "SELECT g.id, g.name, g.iid 
2141
                    FROM ".Database::get_course_table(TABLE_GROUP)." AS g
2142
                    $session_condition
2143
                    AND c_id = $course_id";
2144
        }
2145
        $result = Database::query($sql);
2146
2147
        while ($group_data = Database::fetch_array($result)) {
2148
            $group_data['userNb'] = GroupManager::number_of_students($group_data['id'], $course_id);
2149
            $group_list[$group_data['id']] = $group_data;
2150
        }
2151
        return $group_list;
2152
    }
2153
2154
    /**
2155
     * Delete a course
2156
     * This function deletes a whole course-area from the platform. When the
2157
     * given course is a virtual course, the database and directory will not be
2158
     * deleted.
2159
     * When the given course is a real course, also all virtual courses refering
2160
     * to the given course will be deleted.
2161
     * Considering the fact that we remove all traces of the course in the main
2162
     * database, it makes sense to remove all tracking as well (if stats databases exist)
2163
     * so that a new course created with this code would not use the remains of an older
2164
     * course.
2165
     *
2166
     * @param string $code The code of the course to delete
2167
     * @todo When deleting a virtual course: unsubscribe users from that virtual
2168
     * course from the groups in the real course if they are not subscribed in
2169
     * that real course.
2170
     */
2171
    public static function delete_course($code)
2172
    {
2173
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
2174
        $table_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2175
        $table_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2176
        $table_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2177
        $table_course_survey = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY);
2178
        $table_course_survey_question = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION);
2179
        $table_course_survey_question_option = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
2180
        $table_course_rel_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2181
2182
        $table_stats_hotpots = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTPOTATOES);
2183
        $table_stats_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
2184
        $table_stats_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
2185
        $table_stats_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS);
2186
        $table_stats_lastaccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
2187
        $table_stats_course_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
2188
        $table_stats_online = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ONLINE);
2189
        $table_stats_default = Database::get_main_table(TABLE_STATISTIC_TRACK_E_DEFAULT);
2190
        $table_stats_downloads = Database::get_main_table(TABLE_STATISTIC_TRACK_E_DOWNLOADS);
2191
        $table_stats_links = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LINKS);
2192
        $table_stats_uploads = Database::get_main_table(TABLE_STATISTIC_TRACK_E_UPLOADS);
2193
2194
        $codeFiltered = Database::escape_string($code);
2195
        $sql = "SELECT * FROM $table_course WHERE code='".$codeFiltered."'";
2196
        $res = Database::query($sql);
2197
2198
        if (Database::num_rows($res) == 0) {
2199
            return;
2200
        }
2201
2202
        $sql = "SELECT * FROM $table_course
2203
                WHERE code = '".$codeFiltered."'";
2204
        $res = Database::query($sql);
2205
        $course = Database::fetch_array($res);
2206
        $courseId = $course['id'];
2207
2208
        $count = 0;
2209
        if (api_is_multiple_url_enabled()) {
2210
            $url_id = 1;
2211
            if (api_get_current_access_url_id() != -1) {
2212
                $url_id = api_get_current_access_url_id();
2213
            }
2214
            UrlManager::delete_url_rel_course($courseId, $url_id);
2215
            $count = UrlManager::getCountUrlRelCourse($courseId);
2216
        }
2217
2218
        if ($count == 0) {
2219
            self::create_database_dump($code);
2220
2221
            $course_tables = AddCourse::get_course_tables();
2222
2223
            // Cleaning group categories
2224
            $groupCategories = GroupManager::get_categories($course['code']);
2225
2226
            if (!empty($groupCategories)) {
2227
                foreach ($groupCategories as $category) {
2228
                    GroupManager::delete_category($category['id'], $course['code']);
2229
                }
2230
            }
2231
2232
            // Cleaning groups
2233
            $groups = GroupManager::get_groups($courseId);
2234
            if (!empty($groups)) {
2235
                foreach ($groups as $group) {
2236
                    GroupManager::delete_groups($group, $course['code']);
2237
                }
2238
            }
2239
2240
            // Cleaning c_x tables
2241
            if (!empty($courseId)) {
2242
                foreach ($course_tables as $table) {
2243
                    $table = Database::get_course_table($table);
2244
                    $sql = "DELETE FROM $table WHERE c_id = $courseId ";
2245
                    Database::query($sql);
2246
                }
2247
            }
2248
2249
            $course_dir = api_get_path(SYS_COURSE_PATH).$course['directory'];
2250
            $archive_dir = api_get_path(SYS_ARCHIVE_PATH).$course['directory'].'_'.time();
2251
            if (is_dir($course_dir)) {
2252
                rename($course_dir, $archive_dir);
2253
            }
2254
2255
            // Unsubscribe all users from the course
2256
            $sql = "DELETE FROM $table_course_user WHERE c_id='".$courseId."'";
2257
            Database::query($sql);
2258
            // Delete the course from the sessions tables
2259
            $sql = "DELETE FROM $table_session_course WHERE c_id='".$courseId."'";
2260
            Database::query($sql);
2261
            $sql = "DELETE FROM $table_session_course_user WHERE c_id='".$courseId."'";
2262
            Database::query($sql);
2263
2264
            // Delete from Course - URL
2265
            $sql = "DELETE FROM $table_course_rel_url WHERE c_id = '".$courseId."'";
2266
            Database::query($sql);
2267
2268
            $sql = 'SELECT survey_id FROM '.$table_course_survey.' WHERE course_code="'.$codeFiltered.'"';
2269
            $result_surveys = Database::query($sql);
2270
            while ($surveys = Database::fetch_array($result_surveys)) {
2271
                $survey_id = $surveys[0];
2272
                $sql = 'DELETE FROM '.$table_course_survey_question.' WHERE survey_id="'.$survey_id.'"';
2273
                Database::query($sql);
2274
                $sql = 'DELETE FROM '.$table_course_survey_question_option.' WHERE survey_id="'.$survey_id.'"';
2275
                Database::query($sql);
2276
                $sql = 'DELETE FROM '.$table_course_survey.' WHERE survey_id="'.$survey_id.'"';
2277
                Database::query($sql);
2278
            }
2279
2280
            // Delete the course from the stats tables
2281
            $sql = "DELETE FROM $table_stats_hotpots WHERE c_id = $courseId";
2282
            Database::query($sql);
2283
            $sql = "DELETE FROM $table_stats_attempt WHERE c_id = $courseId";
2284
            Database::query($sql);
2285
            $sql = "DELETE FROM $table_stats_exercises WHERE c_id = $courseId";
2286
            Database::query($sql);
2287
            $sql = "DELETE FROM $table_stats_access WHERE c_id = $courseId";
2288
            Database::query($sql);
2289
            $sql = "DELETE FROM $table_stats_lastaccess WHERE c_id = $courseId";
2290
            Database::query($sql);
2291
            $sql = "DELETE FROM $table_stats_course_access WHERE c_id = $courseId";
2292
            Database::query($sql);
2293
            $sql = "DELETE FROM $table_stats_online WHERE c_id = $courseId";
2294
            Database::query($sql);
2295
            // Do not delete rows from track_e_default as these include course
2296
            // creation and other important things that do not take much space
2297
            // but give information on the course history
2298
            //$sql = "DELETE FROM $table_stats_default WHERE c_id = $courseId";
2299
            //Database::query($sql);
2300
            $sql = "DELETE FROM $table_stats_downloads WHERE c_id = $courseId";
2301
            Database::query($sql);
2302
            $sql = "DELETE FROM $table_stats_links WHERE c_id = $courseId";
2303
            Database::query($sql);
2304
            $sql = "DELETE FROM $table_stats_uploads WHERE c_id = $courseId";
2305
            Database::query($sql);
2306
2307
            // Update ticket
2308
            $table = Database::get_main_table(TABLE_TICKET_TICKET);
2309
            $sql = "UPDATE $table SET course_id = NULL WHERE course_id = $courseId";
2310
            Database::query($sql);
2311
2312
            // Class
2313
            $table = Database::get_main_table(TABLE_USERGROUP_REL_COURSE);
2314
            $sql = "DELETE FROM $table
2315
                    WHERE course_id = $courseId";
2316
            Database::query($sql);
2317
2318
            // Skills
2319
            $table = Database::get_main_table(TABLE_MAIN_SKILL_REL_USER);
2320
            $argumentation = Database::escape_string(sprintf(get_lang('SkillFromCourseXDeletedSinceThen'), $course['code']));
2321
            $sql = "UPDATE $table SET course_id = NULL, session_id = NULL, argumentation = '$argumentation' WHERE course_id = $courseId";
2322
            Database::query($sql);
2323
2324
            // Delete the course from the database
2325
            $sql = "DELETE FROM $table_course WHERE code = '".$codeFiltered."'";
2326
            Database::query($sql);
2327
2328
            // delete extra course fields
2329
            $extraFieldValues = new ExtraFieldValue('course');
2330
            $extraFieldValues->deleteValuesByItem($courseId);
2331
2332
            // Add event to system log
2333
            Event::addEvent(
2334
                LOG_COURSE_DELETE,
2335
                LOG_COURSE_CODE,
2336
                $code,
2337
                api_get_utc_datetime(),
2338
                api_get_user_id(),
2339
                $courseId
2340
            );
2341
        }
2342
    }
2343
2344
    /**
2345
     * Creates a file called mysql_dump.sql in the course folder
2346
     * @param string $course_code The code of the course
2347
     * @todo Implementation for single database
2348
     */
2349
    public static function create_database_dump($course_code)
2350
    {
2351
        $sql_dump = '';
2352
        $course_code = Database::escape_string($course_code);
2353
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
2354
        $sql = "SELECT * FROM $table_course WHERE code = '$course_code'";
2355
        $res = Database::query($sql);
2356
        $course = Database::fetch_array($res);
2357
2358
        $course_tables = AddCourse::get_course_tables();
2359
2360
        if (!empty($course['id'])) {
2361
            //Cleaning c_x tables
2362
            foreach ($course_tables as $table) {
2363
                $table = Database::get_course_table($table);
2364
                $sql = "SELECT * FROM $table WHERE c_id = {$course['id']} ";
2365
                $res_table = Database::query($sql);
2366
2367
                while ($row = Database::fetch_array($res_table, 'ASSOC')) {
2368
                    $row_to_save = [];
2369
                    foreach ($row as $key => $value) {
2370
                        $row_to_save[$key] = $key."='".Database::escape_string($row[$key])."'";
2371
                    }
2372
                    $sql_dump .= "\nINSERT INTO $table SET ".implode(', ', $row_to_save).';';
2373
                }
2374
            }
2375
        }
2376
2377
        if (is_dir(api_get_path(SYS_COURSE_PATH).$course['directory'])) {
2378
            $file_name = api_get_path(SYS_COURSE_PATH).$course['directory'].'/mysql_dump.sql';
2379
            $handle = fopen($file_name, 'a+');
2380
            if ($handle !== false) {
2381
                fwrite($handle, $sql_dump);
2382
                fclose($handle);
2383
            } else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
2384
                //TODO trigger exception in a try-catch
2385
            }
2386
        }
2387
    }
2388
2389
    /**
2390
     * Sort courses for a specific user ??
2391
     * @param   int    $user_id User ID
2392
     * @param   string  $course_code Course code
2393
     * @return  int     Minimum course order
2394
     * @todo Review documentation
2395
     */
2396
    public static function userCourseSort($user_id, $course_code)
2397
    {
2398
        if ($user_id != strval(intval($user_id))) {
2399
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type integer.
Loading history...
2400
        }
2401
2402
        $course_code = Database::escape_string($course_code);
2403
        $TABLECOURSE = Database::get_main_table(TABLE_MAIN_COURSE);
2404
        $TABLECOURSUSER = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2405
2406
        $course_title = Database::result(
2407
            Database::query(
2408
                'SELECT title FROM '.$TABLECOURSE.' WHERE code="'.$course_code.'"'
2409
            ),
2410
            0,
2411
            0
2412
        );
2413
2414
        $sql = 'SELECT course.code as code, course.title as title, cu.sort as sort
2415
                FROM '.$TABLECOURSUSER.' as cu, '.$TABLECOURSE.' as course
2416
                WHERE   course.id = cu.c_id AND user_id = "' . $user_id.'" AND
2417
                        cu.relation_type<>' . COURSE_RELATION_TYPE_RRHH.' AND
2418
                        user_course_cat = 0
2419
                ORDER BY cu.sort';
2420
        $result = Database::query($sql);
2421
2422
        $course_title_precedent = '';
2423
        $counter = 0;
2424
        $course_found = false;
2425
        $course_sort = 1;
2426
2427
        if (Database::num_rows($result) > 0) {
2428
            while ($courses = Database::fetch_array($result)) {
2429
                if ($course_title_precedent == '') {
2430
                    $course_title_precedent = $courses['title'];
2431
                }
2432
                if (api_strcasecmp($course_title_precedent, $course_title) < 0) {
2433
                    $course_found = true;
2434
                    $course_sort = $courses['sort'];
2435
                    if ($counter == 0) {
2436
                        $sql = 'UPDATE '.$TABLECOURSUSER.'
2437
                                SET sort = sort+1
2438
                                WHERE
2439
                                    user_id= "' . $user_id.'" AND
2440
                                    relation_type<>' . COURSE_RELATION_TYPE_RRHH.'
2441
                                    AND user_course_cat="0"
2442
                                    AND sort > "' . $course_sort.'"';
2443
                        $course_sort++;
2444
                    } else {
2445
                        $sql = 'UPDATE '.$TABLECOURSUSER.' SET sort = sort+1
2446
                                WHERE
2447
                                    user_id= "' . $user_id.'" AND
2448
                                    relation_type<>' . COURSE_RELATION_TYPE_RRHH.' AND
2449
                                    user_course_cat="0" AND
2450
                                    sort >= "' . $course_sort.'"';
2451
                    }
2452
                    Database::query($sql);
2453
                    break;
2454
                } else {
2455
                    $course_title_precedent = $courses['title'];
2456
                }
2457
                $counter++;
2458
            }
2459
2460
            // We must register the course in the beginning of the list
2461
            if (!$course_found) {
2462
                $course_sort = Database::result(
2463
                    Database::query(
2464
                        'SELECT min(sort) as min_sort FROM '.$TABLECOURSUSER.' WHERE user_id="'.$user_id.'" AND user_course_cat="0"'
2465
                    ),
2466
                    0,
2467
                    0
2468
                );
2469
                Database::query('UPDATE '.$TABLECOURSUSER.' SET sort = sort+1 WHERE user_id= "'.$user_id.'" AND user_course_cat="0"');
2470
            }
2471
        }
2472
        return $course_sort;
2473
    }
2474
2475
    /**
2476
     * check if course exists
2477
     * @param string $course_code
2478
     * @return integer if exists, false else
2479
     */
2480
    public static function course_exists($course_code)
2481
    {
2482
        $sql = 'SELECT 1 FROM '.Database::get_main_table(TABLE_MAIN_COURSE).'
2483
                WHERE code="'.Database::escape_string($course_code).'"';
2484
2485
        return Database::num_rows(Database::query($sql));
2486
    }
2487
2488
    /**
2489
     * Send an email to tutor after the auth-suscription of a student in your course
2490
     * @author Carlos Vargas <[email protected]>, Dokeos Latino
2491
     * @param  int $user_id the id of the user
2492
     * @param  string $courseId the course code
2493
     * @param  bool $send_to_tutor_also
2494
     * @return false|null we return the message that is displayed when the action is successful
2495
     */
2496
    public static function email_to_tutor($user_id, $courseId, $send_to_tutor_also = false)
2497
    {
2498
        if ($user_id != strval(intval($user_id))) {
2499
            return false;
2500
        }
2501
        $courseId = intval($courseId);
2502
        $information = api_get_course_info_by_id($courseId);
2503
        $course_code = $information['code'];
2504
        $student = api_get_user_info($user_id);
2505
2506
        $name_course = $information['title'];
2507
        $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)." 
2508
                WHERE c_id ='" . $courseId."'";
2509
2510
        // TODO: Ivan: This is a mistake, please, have a look at it. Intention here is diffcult to be guessed.
2511
        //if ($send_to_tutor_also = true)
2512
        // Proposed change:
2513
        if ($send_to_tutor_also) {
2514
            $sql .= " AND is_tutor=1";
2515
        } else {
2516
            $sql .= " AND status=1";
2517
        }
2518
2519
        $result = Database::query($sql);
2520
        while ($row = Database::fetch_array($result)) {
2521
            $tutor = api_get_user_info($row['user_id']);
2522
            $emailto = $tutor['email'];
2523
            $emailsubject = get_lang('NewUserInTheCourse').': '.$name_course;
2524
            $emailbody = get_lang('Dear').': '.api_get_person_name($tutor['firstname'], $tutor['lastname'])."\n";
2525
            $emailbody .= get_lang('MessageNewUserInTheCourse').': '.$name_course."\n";
2526
            $emailbody .= get_lang('UserName').': '.$student['username']."\n";
2527
            if (api_is_western_name_order()) {
2528
                $emailbody .= get_lang('FirstName').': '.$student['firstname']."\n";
2529
                $emailbody .= get_lang('LastName').': '.$student['lastname']."\n";
2530
            } else {
2531
                $emailbody .= get_lang('LastName').': '.$student['lastname']."\n";
2532
                $emailbody .= get_lang('FirstName').': '.$student['firstname']."\n";
2533
            }
2534
            $emailbody .= get_lang('Email').': <a href="mailto:'.$student['email'].'">'.$student['email']."</a>\n\n";
2535
            $recipient_name = api_get_person_name(
2536
                $tutor['firstname'],
2537
                $tutor['lastname'],
2538
                null,
2539
                PERSON_NAME_EMAIL_ADDRESS
2540
            );
2541
            $sender_name = api_get_person_name(
2542
                api_get_setting('administratorName'),
2543
                api_get_setting('administratorSurname'),
2544
                null,
2545
                PERSON_NAME_EMAIL_ADDRESS
2546
            );
2547
            $email_admin = api_get_setting('emailAdministrator');
2548
2549
            $additionalParameters = [
2550
                'smsType' => SmsPlugin::NEW_USER_SUBSCRIBED_COURSE,
2551
                'userId' => $tutor['user_id'],
2552
                'userUsername' => $student['username'],
2553
                'courseCode' => $course_code
2554
            ];
2555
            api_mail_html(
2556
                $recipient_name,
2557
                $emailto,
2558
                $emailsubject,
2559
                $emailbody,
2560
                $sender_name,
2561
                $email_admin,
2562
                null,
2563
                null,
2564
                null,
2565
                $additionalParameters
2566
            );
2567
        }
2568
    }
2569
2570
    /**
2571
     * @return array
2572
     */
2573
    public static function get_special_course_list()
2574
    {
2575
        $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
2576
        $tbl_course_field = Database::get_main_table(TABLE_EXTRA_FIELD);
2577
        $tbl_course_field_value = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
2578
2579
        //we filter the courses from the URL
2580
        $join_access_url = $where_access_url = '';
2581
        if (api_get_multiple_access_url()) {
2582
            $access_url_id = api_get_current_access_url_id();
2583
            if ($access_url_id != -1) {
2584
                $tbl_url_course = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2585
                $join_access_url = "LEFT JOIN $tbl_url_course url_rel_course
2586
                                    ON url_rel_course.c_id = tcfv.item_id ";
2587
                $where_access_url = " AND access_url_id = $access_url_id ";
2588
            }
2589
        }
2590
2591
        $extraFieldType = EntityExtraField::COURSE_FIELD_TYPE;
2592
2593
        // get course list auto-register
2594
        $sql = "SELECT DISTINCT(c.id)
2595
                FROM $tbl_course_field_value tcfv
2596
                INNER JOIN $tbl_course_field tcf
2597
                ON tcfv.field_id =  tcf.id $join_access_url
2598
                INNER JOIN $courseTable c
2599
                ON (c.id = tcfv.item_id)
2600
                WHERE
2601
                    tcf.extra_field_type = $extraFieldType AND
2602
                    tcf.variable = 'special_course' AND
2603
                    tcfv.value = 1  $where_access_url";
2604
2605
        $result = Database::query($sql);
2606
        $courseList = [];
2607
2608
        if (Database::num_rows($result) > 0) {
2609
            while ($row = Database::fetch_array($result)) {
2610
                $courseList[] = $row['id'];
2611
            }
2612
        }
2613
2614
        return $courseList;
2615
    }
2616
2617
    /**
2618
     * Get the course codes that have been restricted in the catalogue, and if byUserId is set
2619
     * then the courses that the user is allowed or not to see in catalogue
2620
     *
2621
     * @param bool $allowed Either if the courses have some users that are or are not allowed to see in catalogue
2622
     * @param int $byUserId if the courses are or are not allowed to see to the user
2623
     * @return array Course codes allowed or not to see in catalogue by some user or the user
2624
     */
2625
    public static function getCatalogueCourseList($allowed = true, $byUserId = -1)
2626
    {
2627
        $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
2628
        $tblCourseRelUserCatalogue = Database::get_main_table(TABLE_MAIN_COURSE_CATALOGUE_USER);
2629
        $visibility = $allowed ? 1 : 0;
2630
2631
        // Restriction by user id
2632
        $currentUserRestriction = '';
2633
        if ($byUserId > 0) {
2634
            $byUserId = (int) $byUserId;
2635
            $currentUserRestriction = " AND tcruc.user_id = $byUserId ";
2636
        }
2637
2638
        //we filter the courses from the URL
2639
        $joinAccessUrl = '';
2640
        $whereAccessUrl = '';
2641
        if (api_get_multiple_access_url()) {
2642
            $accessUrlId = api_get_current_access_url_id();
2643
            if ($accessUrlId != -1) {
2644
                $tblUrlCourse = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2645
                $joinAccessUrl = "LEFT JOIN $tblUrlCourse url_rel_course
2646
                                  ON url_rel_course.c_id = c.id ";
2647
                $whereAccessUrl = " AND access_url_id = $accessUrlId ";
2648
            }
2649
        }
2650
2651
        // get course list auto-register
2652
        $sql = "SELECT DISTINCT(c.code)
2653
                FROM $tblCourseRelUserCatalogue tcruc
2654
                INNER JOIN $courseTable c
2655
                ON (c.id = tcruc.c_id) $joinAccessUrl
2656
                WHERE tcruc.visible = $visibility $currentUserRestriction $whereAccessUrl";
2657
2658
        $result = Database::query($sql);
2659
        $courseList = [];
2660
2661
        if (Database::num_rows($result) > 0) {
2662
            while ($resultRow = Database::fetch_array($result)) {
2663
                $courseList[] = $resultRow['code'];
2664
            }
2665
        }
2666
2667
        return $courseList;
2668
    }
2669
2670
    /**
2671
     * Get list of courses for a given user
2672
     *
2673
     * @param int $user_id
2674
     * @param boolean $include_sessions Whether to include courses from session or not
2675
     * @param boolean $adminGetsAllCourses If the user is platform admin,
2676
     * whether he gets all the courses or just his. Note: This does *not* include all sessions
2677
     * @param bool $loadSpecialCourses
2678
     * @param array $skipCourseList List of course ids to skip
2679
     * @param bool $useUserLanguageFilterIfAvailable
2680
     * @param bool $showCoursesSessionWithDifferentKey
2681
     * @return array List of codes and db name
2682
     * @author isaac flores paz
2683
     */
2684
    public static function get_courses_list_by_user_id(
2685
        $user_id,
2686
        $include_sessions = false,
2687
        $adminGetsAllCourses = false,
2688
        $loadSpecialCourses = true,
2689
        $skipCourseList = [],
2690
        $useUserLanguageFilterIfAvailable = true,
2691
        $showCoursesSessionWithDifferentKey = false
2692
    ) {
2693
        $user_id = intval($user_id);
2694
        $urlId = api_get_current_access_url_id();
2695
        $course_list = [];
2696
        $codes = [];
2697
2698
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
2699
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2700
        $tbl_user_course_category = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
2701
        $tableCourseUrl = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2702
2703
        $languageCondition = '';
2704
        $onlyInUserLanguage = api_get_configuration_value('my_courses_show_courses_in_user_language_only');
2705
        if ($useUserLanguageFilterIfAvailable && $onlyInUserLanguage) {
2706
            $userInfo = api_get_user_info(api_get_user_id());
2707
            if (!empty($userInfo['language'])) {
2708
                $languageCondition = " AND course.course_language = '".$userInfo['language']."' ";
2709
            }
2710
        }
2711
2712
        if ($adminGetsAllCourses && UserManager::is_admin($user_id)) {
2713
            // get the whole courses list
2714
            $sql = "SELECT DISTINCT(course.code), course.id as real_id, course.title
2715
                    FROM $tbl_course course 
2716
                    INNER JOIN $tableCourseUrl url 
2717
                    ON (course.id = url.c_id)
2718
                    WHERE 
2719
                        url.access_url_id = $urlId     
2720
                        $languageCondition 
2721
                ";
2722
        } else {
2723
            $withSpecialCourses = $withoutSpecialCourses = '';
2724
2725
            if ($loadSpecialCourses) {
2726
                $specialCourseList = self::get_special_course_list();
2727
2728
                if (!empty($specialCourseList)) {
2729
                    $specialCourseToString = '"'.implode('","', $specialCourseList).'"';
2730
                    $withSpecialCourses = ' AND course.id IN ('.$specialCourseToString.')';
2731
                    $withoutSpecialCourses = ' AND course.id NOT IN ('.$specialCourseToString.')';
2732
                }
2733
2734
                if (!empty($withSpecialCourses)) {
2735
                    $sql = "SELECT DISTINCT (course.code), 
2736
                            course.id as real_id,
2737
                            course.category_code AS category,
2738
                            course.title
2739
                            FROM $tbl_course_user course_rel_user
2740
                            LEFT JOIN $tbl_course course
2741
                            ON course.id = course_rel_user.c_id
2742
                            LEFT JOIN $tbl_user_course_category user_course_category
2743
                            ON course_rel_user.user_course_cat = user_course_category.id
2744
                            INNER JOIN $tableCourseUrl url 
2745
                            ON (course.id = url.c_id)  
2746
                            WHERE url.access_url_id = $urlId 
2747
                            $withSpecialCourses
2748
                            $languageCondition                        
2749
                            GROUP BY course.code
2750
                            ORDER BY user_course_category.sort, course.title, course_rel_user.sort ASC
2751
                    ";
2752
                    $result = Database::query($sql);
2753
                    if (Database::num_rows($result) > 0) {
2754
                        while ($result_row = Database::fetch_array($result, 'ASSOC')) {
2755
                            $result_row['special_course'] = 1;
2756
                            $course_list[] = $result_row;
2757
                            $codes[] = $result_row['real_id'];
2758
                        }
2759
                    }
2760
                }
2761
            }
2762
2763
            // get course list not auto-register. Use Distinct to avoid multiple
2764
            // entries when a course is assigned to a HRD (DRH) as watcher
2765
            $sql = "SELECT 
2766
                        DISTINCT(course.code), 
2767
                        course.id as real_id, 
2768
                        course.category_code AS category,
2769
                        course.title
2770
                    FROM $tbl_course course
2771
                    INNER JOIN $tbl_course_user cru 
2772
                    ON (course.id = cru.c_id)
2773
                    INNER JOIN $tableCourseUrl url 
2774
                    ON (course.id = url.c_id) 
2775
                    WHERE 
2776
                        url.access_url_id = $urlId AND 
2777
                        cru.user_id = '$user_id' 
2778
                        $withoutSpecialCourses
2779
                        $languageCondition
2780
                    ORDER BY course.title
2781
                    ";
2782
        }
2783
        $result = Database::query($sql);
2784
2785
        if (Database::num_rows($result)) {
2786
            while ($row = Database::fetch_array($result, 'ASSOC')) {
2787
                if (!empty($skipCourseList)) {
2788
                    if (in_array($row['real_id'], $skipCourseList)) {
2789
                        continue;
2790
                    }
2791
                }
2792
                $course_list[] = $row;
2793
                $codes[] = $row['real_id'];
2794
            }
2795
        }
2796
2797
        if ($include_sessions === true) {
2798
            $sql = "SELECT DISTINCT (c.code), 
2799
                        c.id as real_id, 
2800
                        c.category_code AS category,
2801
                        s.id as session_id,
2802
                        s.name as session_name
2803
                    FROM ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)." scu                     
2804
                    INNER JOIN $tbl_course c
2805
                    ON (scu.c_id = c.id)
2806
                    INNER JOIN ".Database::get_main_table(TABLE_MAIN_SESSION)." s
2807
                    ON (s.id = scu.session_id)
2808
                    WHERE user_id = $user_id ";
2809
            $r = Database::query($sql);
2810
            while ($row = Database::fetch_array($r, 'ASSOC')) {
2811
                if (!empty($skipCourseList)) {
2812
                    if (in_array($row['real_id'], $skipCourseList)) {
2813
                        continue;
2814
                    }
2815
                }
2816
2817
                if ($showCoursesSessionWithDifferentKey) {
2818
                    $course_list[] = $row;
2819
                } else {
2820
                    if (!in_array($row['real_id'], $codes)) {
2821
                        $course_list[] = $row;
2822
                    }
2823
                }
2824
            }
2825
        }
2826
2827
        return $course_list;
2828
    }
2829
2830
    /**
2831
     * Get course ID from a given course directory name
2832
     * @param   string  $path Course directory (without any slash)
2833
     *
2834
     * @return  string  Course code, or false if not found
2835
     */
2836
    public static function getCourseCodeFromDirectory($path)
2837
    {
2838
        $path = Database::escape_string(str_replace('.', '', str_replace('/', '', $path)));
2839
        $res = Database::query("SELECT code FROM ".Database::get_main_table(TABLE_MAIN_COURSE)."
2840
                WHERE directory LIKE BINARY '$path'");
2841
        if ($res === false) {
2842
            return false;
2843
        }
2844
        if (Database::num_rows($res) != 1) {
2845
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type string.
Loading history...
2846
        }
2847
        $row = Database::fetch_array($res);
2848
2849
        return $row['code'];
2850
    }
2851
2852
    /**
2853
     * Get course code(s) from visual code
2854
     * @deprecated
2855
     * @param   string  Visual code
2856
     * @return  array   List of codes for the given visual code
2857
     */
2858
    public static function get_courses_info_from_visual_code($code)
2859
    {
2860
        $result = [];
2861
        $sql_result = Database::query("SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE)."
2862
                WHERE visual_code = '" . Database::escape_string($code)."'");
2863
        while ($virtual_course = Database::fetch_array($sql_result)) {
2864
            $result[] = $virtual_course;
2865
        }
2866
        return $result;
2867
    }
2868
2869
    /**
2870
     * Get emails of tutors to course
2871
     * @param int $courseId
2872
     * @return array List of emails of tutors to course
2873
     *
2874
     * @author Carlos Vargas <[email protected]>, Dokeos Latino
2875
     * */
2876
    public static function get_emails_of_tutors_to_course($courseId)
2877
    {
2878
        $list = [];
2879
        $res = Database::query("SELECT user_id FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
2880
                WHERE c_id ='" . intval($courseId)."' AND status=1");
2881
        while ($list_users = Database::fetch_array($res)) {
2882
            $result = Database::query("SELECT * FROM ".Database::get_main_table(TABLE_MAIN_USER)."
2883
                    WHERE user_id=" . $list_users['user_id']);
2884
            while ($row_user = Database::fetch_array($result)) {
2885
                $name_teacher = api_get_person_name($row_user['firstname'], $row_user['lastname']);
2886
                $list[] = [$row_user['email'] => $name_teacher];
2887
            }
2888
        }
2889
        return $list;
2890
    }
2891
2892
    /**
2893
     * Get coaches emails by session
2894
     * @param int $session_id
2895
     * @param int $courseId
2896
     * @return array  array(email => name_tutor)  by coach
2897
     * @author Carlos Vargas <[email protected]>
2898
     */
2899
    public static function get_email_of_tutor_to_session($session_id, $courseId)
2900
    {
2901
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2902
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
2903
        $coachs_emails = [];
2904
2905
        $courseId = intval($courseId);
2906
        $session_id = intval($session_id);
2907
2908
        $sql = "SELECT user_id
2909
                FROM $tbl_session_course_user
2910
                WHERE
2911
                    session_id = '$session_id' AND
2912
                    c_id = '$courseId' AND
2913
                    status = 2
2914
                ";
2915
        $rs = Database::query($sql);
2916
2917
        if (Database::num_rows($rs) > 0) {
2918
            $user_ids = [];
2919
            while ($row = Database::fetch_array($rs)) {
2920
                $user_ids[] = $row['user_id'];
2921
            }
2922
2923
            $sql = "SELECT firstname, lastname, email FROM $tbl_user
2924
                    WHERE user_id IN (".implode(",", $user_ids).")";
2925
            $rs_user = Database::query($sql);
2926
2927
            while ($row_emails = Database::fetch_array($rs_user)) {
2928
                $mail_tutor = [
2929
                    'email' => $row_emails['email'],
2930
                    'complete_name' => api_get_person_name($row_emails['firstname'], $row_emails['lastname'])
2931
                ];
2932
                $coachs_emails[] = $mail_tutor;
2933
            }
2934
        }
2935
        return $coachs_emails;
2936
    }
2937
2938
    /**
2939
     * Creates a new extra field for a given course
2940
     * @param    string    Field's internal variable name
2941
     * @param    int        Field's type
2942
     * @param    string    Field's language var name
2943
     * @param string $default
2944
     * @return boolean     new extra field id
2945
     */
0 ignored issues
show
Documentation Bug introduced by
The doc comment Field's at position 0 could not be parsed: Unknown type name 'Field's' at position 0 in Field's.
Loading history...
2946
    public static function create_course_extra_field($variable, $fieldType, $displayText, $default = '')
2947
    {
2948
        $extraField = new ExtraField('course');
2949
        $params = [
2950
            'variable' => $variable,
2951
            'field_type' => $fieldType,
2952
            'display_text' => $displayText,
2953
            'default_value' => $default
2954
        ];
2955
2956
        return $extraField->save($params);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $extraField->save($params) returns the type integer which is incompatible with the documented return type boolean.
Loading history...
2957
    }
2958
2959
    /**
2960
     * Updates course attribute. Note that you need to check that your
2961
     * attribute is valid before you use this function
2962
     *
2963
     * @param int $id Course id
2964
     * @param string $name Attribute name
2965
     * @param string $value Attribute value
2966
     *
2967
     * @return Doctrine\DBAL\Driver\Statement|null True if attribute was successfully updated,
2968
     * false if course was not found or attribute name is invalid
2969
     */
2970
    public static function update_attribute($id, $name, $value)
2971
    {
2972
        $id = (int) $id;
2973
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
2974
        $sql = "UPDATE $table SET $name = '".Database::escape_string($value)."'
2975
                WHERE id = '$id'";
2976
2977
        return Database::query($sql);
2978
    }
2979
2980
    /**
2981
     * Update course attributes. Will only update attributes with a non-empty value.
2982
     * Note that you NEED to check that your attributes are valid before using this function
2983
     *
2984
     * @param int Course id
2985
     * @param array Associative array with field names as keys and field values as values
2986
     * @return Doctrine\DBAL\Driver\Statement|null True if update was successful, false otherwise
2987
     */
2988
    public static function update_attributes($id, $attributes)
2989
    {
2990
        $id = (int) $id;
2991
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
2992
        $sql = "UPDATE $table SET ";
2993
        $i = 0;
2994
        foreach ($attributes as $name => $value) {
2995
            if ($value != '') {
2996
                if ($i > 0) {
2997
                    $sql .= ", ";
2998
                }
2999
                $sql .= " $name = '".Database::escape_string($value)."'";
3000
                $i++;
3001
            }
3002
        }
3003
        $sql .= " WHERE id = '$id'";
3004
3005
        return Database::query($sql);
3006
    }
3007
3008
    /**
3009
     * Update an extra field value for a given course
3010
     * @param    integer    Course ID
3011
     * @param    string    Field variable name
3012
     * @param    string    Field value
3013
     * @return    boolean|null    true if field updated, false otherwise
3014
     */
3015
    public static function update_course_extra_field_value($course_code, $variable, $value = '')
3016
    {
3017
        $courseInfo = api_get_course_info($course_code);
3018
        $courseId = $courseInfo['real_id'];
3019
3020
        $extraFieldValues = new ExtraFieldValue('course');
3021
        $params = [
3022
            'item_id' => $courseId,
3023
            'variable' => $variable,
3024
            'value' => $value
3025
        ];
3026
3027
        return $extraFieldValues->save($params);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $extraFieldValues->save($params) also could return the type integer which is incompatible with the documented return type null|boolean.
Loading history...
3028
    }
3029
3030
    /**
3031
     * @param int $session_id
3032
     * @return mixed
3033
     */
3034
    public static function get_session_category_id_by_session_id($session_id)
3035
    {
3036
        if (empty($session_id)) {
3037
            return [];
3038
        }
3039
3040
        $sql = 'SELECT sc.id session_category
3041
                FROM ' . Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY).' sc
3042
                INNER JOIN ' . Database::get_main_table(TABLE_MAIN_SESSION).' s
3043
                ON sc.id = s.session_category_id 
3044
                WHERE s.id="' . intval($session_id).'"';
3045
3046
        return Database::result(
3047
            Database::query($sql),
3048
            0,
3049
            'session_category'
3050
        );
3051
    }
3052
3053
    /**
3054
     * Gets the value of a course extra field. Returns null if it was not found
3055
     *
3056
     * @param string $variable Name of the extra field
3057
     * @param string $code Course code
3058
     *
3059
     * @return string Value
3060
     */
3061
    public static function get_course_extra_field_value($variable, $code)
3062
    {
3063
        $courseInfo = api_get_course_info($code);
3064
        $courseId = $courseInfo['real_id'];
3065
3066
        $extraFieldValues = new ExtraFieldValue('course');
3067
        $result = $extraFieldValues->get_values_by_handler_and_field_variable($courseId, $variable);
3068
        if (!empty($result['value'])) {
3069
            return $result['value'];
3070
        }
3071
3072
        return null;
3073
    }
3074
3075
    /**
3076
     * Lists details of the course description
3077
     * @param array        The course description
3078
     * @param string    The encoding
3079
     * @param bool        If true is displayed if false is hidden
3080
     * @return string     The course description in html
3081
     */
3082
    public static function get_details_course_description_html(
3083
        $descriptions,
3084
        $charset,
3085
        $action_show = true
3086
    ) {
3087
        $data = null;
3088
        if (isset($descriptions) && count($descriptions) > 0) {
3089
            foreach ($descriptions as $description) {
3090
                $data .= '<div class="sectiontitle">';
3091
                if (api_is_allowed_to_edit() && $action_show) {
3092
                    //delete
3093
                    $data .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=delete&description_id='.$description->id.'" onclick="javascript:if(!confirm(\''.addslashes(api_htmlentities(
3094
                        get_lang('ConfirmYourChoice'),
3095
                                ENT_QUOTES,
3096
                        $charset
3097
                    )).'\')) return false;">';
3098
                    $data .= Display::return_icon(
3099
                        'delete.gif',
3100
                        get_lang('Delete'),
3101
                        ['style' => 'vertical-align:middle;float:right;']
3102
                    );
3103
                    $data .= '</a> ';
3104
                    //edit
3105
                    $data .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&description_id='.$description->id.'">';
3106
                    $data .= Display::return_icon(
3107
                        'edit.png',
3108
                        get_lang('Edit'),
3109
                        ['style' => 'vertical-align:middle;float:right; padding-right:4px;'],
3110
                        ICON_SIZE_SMALL
3111
                    );
3112
                    $data .= '</a> ';
3113
                }
3114
                $data .= $description->title;
3115
                $data .= '</div>';
3116
                $data .= '<div class="sectioncomment">';
3117
                $data .= Security::remove_XSS($description->content);
3118
                $data .= '</div>';
3119
            }
3120
        } else {
3121
            $data .= '<em>'.get_lang('ThisCourseDescriptionIsEmpty').'</em>';
3122
        }
3123
3124
        return $data;
3125
    }
3126
3127
    /**
3128
     * Returns the details of a course category
3129
     *
3130
     * @param string $code Category code
3131
     * @return array Course category
3132
     */
3133
    public static function get_course_category($code)
3134
    {
3135
        $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
3136
        $code = Database::escape_string($code);
3137
        $sql = "SELECT * FROM $table WHERE code = '$code'";
3138
        return Database::fetch_array(Database::query($sql));
3139
    }
3140
3141
    /**
3142
     * Returns the details of a course category
3143
     *
3144
     * @param string Category code
3145
     * @return array Course category list
3146
     */
3147
    public static function getCategoriesList()
3148
    {
3149
        $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
3150
        $sql = "SELECT * FROM $table";
3151
        $result = Database::query($sql);
3152
        $categoryList = [];
3153
        while ($row = Database::fetch_array($result, 'ASSOC')) {
3154
            $categoryList[$row['code']] = $row['name'];
3155
        }
3156
        return $categoryList;
3157
    }
3158
3159
    /**
3160
     * Subscribes courses to human resource manager (Dashboard feature)
3161
     * @param    int   $hr_manager_id      Human Resource Manager id
3162
     * @param    array $courses_list       Courses code
3163
     * @return int
3164
     **/
3165
    public static function subscribeCoursesToDrhManager($hr_manager_id, $courses_list)
3166
    {
3167
        $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
3168
        $tbl_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
3169
3170
        $hr_manager_id = intval($hr_manager_id);
3171
        $affected_rows = 0;
3172
3173
        //Deleting assigned courses to hrm_id
3174
        if (api_is_multiple_url_enabled()) {
3175
            $sql = "SELECT s.c_id FROM $tbl_course_rel_user s
3176
                    INNER JOIN $tbl_course_rel_access_url a
3177
                    ON (a.c_id = s.c_id)
3178
                    WHERE
3179
                        user_id = $hr_manager_id AND
3180
                        relation_type=".COURSE_RELATION_TYPE_RRHH." AND
3181
                        access_url_id = " . api_get_current_access_url_id()."";
3182
        } else {
3183
            $sql = "SELECT c_id FROM $tbl_course_rel_user
3184
                    WHERE user_id = $hr_manager_id AND relation_type=".COURSE_RELATION_TYPE_RRHH." ";
3185
        }
3186
        $result = Database::query($sql);
3187
        if (Database::num_rows($result) > 0) {
3188
            while ($row = Database::fetch_array($result)) {
3189
                $sql = "DELETE FROM $tbl_course_rel_user
3190
                        WHERE
3191
                            c_id = '{$row['c_id']}' AND
3192
                            user_id = $hr_manager_id AND
3193
                            relation_type=".COURSE_RELATION_TYPE_RRHH." ";
3194
                Database::query($sql);
3195
            }
3196
        }
3197
3198
        // inserting new courses list
3199
        if (is_array($courses_list)) {
3200
            foreach ($courses_list as $course_code) {
3201
                $courseInfo = api_get_course_info($course_code);
3202
                $courseId = $courseInfo['real_id'];
3203
                $sql = "INSERT IGNORE INTO $tbl_course_rel_user(c_id, user_id, status, relation_type)
3204
                        VALUES($courseId, $hr_manager_id, '".DRH."', '".COURSE_RELATION_TYPE_RRHH."')";
3205
                $result = Database::query($sql);
3206
                if (Database::affected_rows($result)) {
3207
                    $affected_rows++;
3208
                }
3209
            }
3210
        }
3211
3212
        return $affected_rows;
3213
    }
3214
3215
    /**
3216
     * get courses followed by human resources manager
3217
     * @param int $user_id
3218
     * @param int $status
3219
     * @param int $from
3220
     * @param int $limit
3221
     * @param string $column
3222
     * @param string $direction
3223
     * @param bool $getCount
3224
     *
3225
     * @return array    courses
3226
     */
3227
    public static function get_courses_followed_by_drh(
3228
        $user_id,
3229
        $status = DRH,
3230
        $from = null,
3231
        $limit = null,
3232
        $column = null,
3233
        $direction = null,
3234
        $getCount = false
3235
    ) {
3236
        return self::getCoursesFollowedByUser(
3237
            $user_id,
3238
            $status,
3239
            $from,
3240
            $limit,
3241
            $column,
3242
            $direction,
3243
            $getCount
3244
        );
3245
    }
3246
3247
    /**
3248
     * get courses followed by user
3249
     * @param   int $user_id
3250
     * @param   int $status
3251
     * @param   int $from
3252
     * @param   int $limit
3253
     * @param   string $column
3254
     * @param   string $direction
3255
     * @param   boolean $getCount
3256
     * @param   string $keyword
3257
     * @param   int $sessionId
3258
     * @param   boolean $showAllAssignedCourses
3259
     * @return  array   courses
3260
     */
3261
    public static function getCoursesFollowedByUser(
3262
        $user_id,
3263
        $status = null,
3264
        $from = null,
3265
        $limit = null,
3266
        $column = null,
3267
        $direction = null,
3268
        $getCount = false,
3269
        $keyword = null,
3270
        $sessionId = 0,
3271
        $showAllAssignedCourses = false
3272
    ) {
3273
        // Database Table Definitions
3274
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
3275
        $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
3276
        $tbl_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
3277
        $sessionId = (int) $sessionId;
3278
        $user_id = (int) $user_id;
3279
        $select = "SELECT DISTINCT *, c.id as real_id ";
3280
3281
        if ($getCount) {
3282
            $select = "SELECT COUNT(DISTINCT c.id) as count";
3283
        }
3284
3285
        $whereConditions = '';
3286
        switch ($status) {
3287
            case COURSEMANAGER:
3288
                $whereConditions .= " AND cru.user_id = '$user_id'";
3289
                if (!$showAllAssignedCourses) {
3290
                    $whereConditions .= " AND cru.status = ".COURSEMANAGER;
3291
                } else {
3292
                    $whereConditions .= " AND relation_type = ".COURSE_RELATION_TYPE_COURSE_MANAGER;
3293
                }
3294
                break;
3295
            case DRH:
3296
                $whereConditions .= " AND
3297
                    cru.user_id = '$user_id' AND
3298
                    cru.status = ".DRH." AND
3299
                    relation_type = '" . COURSE_RELATION_TYPE_RRHH."'
3300
                ";
3301
                break;
3302
        }
3303
3304
        $keywordCondition = null;
3305
        if (!empty($keyword)) {
3306
            $keyword = Database::escape_string($keyword);
3307
            $keywordCondition = " AND (c.code LIKE '%$keyword%' OR c.title LIKE '%$keyword%' ) ";
3308
        }
3309
3310
        $orderBy = null;
3311
        $extraInnerJoin = null;
3312
3313
        if (!empty($sessionId)) {
3314
            if ($status == COURSEMANAGER) {
3315
                // Teacher of course or teacher inside session
3316
                $whereConditions = " AND (cru.status = ".COURSEMANAGER." OR srcru.status = 2) ";
3317
            }
3318
            $courseList = SessionManager::get_course_list_by_session_id(
3319
                $sessionId
3320
            );
3321
            if (!empty($courseList)) {
3322
                $courseListToString = implode("','", array_keys($courseList));
0 ignored issues
show
Bug introduced by
It seems like $courseList can also be of type integer; however, parameter $input of array_keys() does only seem to accept array, 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

3322
                $courseListToString = implode("','", array_keys(/** @scrutinizer ignore-type */ $courseList));
Loading history...
3323
                $whereConditions .= " AND c.id IN ('".$courseListToString."')";
3324
            }
3325
            $tableSessionRelCourse = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
3326
            $tableSessionRelCourseRelUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
3327
            $orderBy = ' ORDER BY position';
3328
            $extraInnerJoin = " INNER JOIN $tableSessionRelCourse src
3329
                                ON (c.id = src.c_id AND src.session_id = $sessionId)
3330
                                INNER JOIN $tableSessionRelCourseRelUser srcru 
3331
                                ON (src.session_id = srcru.session_id AND srcru.c_id = src.c_id)
3332
                            ";
3333
        }
3334
3335
        $whereConditions .= $keywordCondition;
3336
        $sql = "$select
3337
                FROM $tbl_course c
3338
                INNER JOIN $tbl_course_rel_user cru 
3339
                ON (cru.c_id = c.id)
3340
                INNER JOIN $tbl_course_rel_access_url a 
3341
                ON (a.c_id = c.id)
3342
                $extraInnerJoin
3343
                WHERE
3344
                    access_url_id = ".api_get_current_access_url_id()."
3345
                    $whereConditions
3346
                $orderBy
3347
                ";
3348
        if (isset($from) && isset($limit)) {
3349
            $from = intval($from);
3350
            $limit = intval($limit);
3351
            $sql .= " LIMIT $from, $limit";
3352
        }
3353
3354
        $result = Database::query($sql);
3355
3356
        if ($getCount) {
3357
            $row = Database::fetch_array($result);
3358
            return $row['count'];
3359
        }
3360
3361
        $courses = [];
3362
        if (Database::num_rows($result) > 0) {
3363
            while ($row = Database::fetch_array($result)) {
3364
                $courses[$row['code']] = $row;
3365
            }
3366
        }
3367
3368
        return $courses;
3369
    }
3370
3371
    /**
3372
     * check if a course is special (autoregister)
3373
     * @param int $courseId
3374
     * @return bool
3375
     */
3376
    public static function isSpecialCourse($courseId)
3377
    {
3378
        $extraFieldValue = new ExtraFieldValue('course');
3379
        $result = $extraFieldValue->get_values_by_handler_and_field_variable(
3380
            $courseId,
3381
            'special_course'
3382
        );
3383
3384
        if (!empty($result)) {
3385
            if ($result['value'] == 1) {
3386
                return true;
3387
            }
3388
        }
3389
3390
        return false;
3391
    }
3392
3393
    /**
3394
     * Update course picture
3395
     * @param   array  $courseInfo
3396
     * @param   string  File name
3397
     * @param   string  The full system name of the image
3398
     * from which course picture will be created.
3399
     * @param   string $cropParameters Optional string that contents "x,y,width,height" of a cropped image format
3400
     * @return  bool    Returns the resulting. In case of internal error or negative validation returns FALSE.
3401
     */
3402
    public static function update_course_picture(
3403
        $courseInfo,
3404
        $filename,
3405
        $source_file = null,
3406
        $cropParameters = null
3407
    ) {
3408
        if (empty($courseInfo)) {
3409
            return false;
3410
        }
3411
3412
        // course path
3413
        $store_path = api_get_path(SYS_COURSE_PATH).$courseInfo['path'];
3414
        // image name for courses
3415
        $course_image = $store_path.'/course-pic.png';
3416
        $course_medium_image = $store_path.'/course-pic85x85.png';
3417
3418
        if (file_exists($course_image)) {
3419
            unlink($course_image);
3420
        }
3421
        if (file_exists($course_medium_image)) {
3422
            unlink($course_medium_image);
3423
        }
3424
3425
        //Crop the image to adjust 4:3 ratio
3426
        $image = new Image($source_file);
3427
        $image->crop($cropParameters);
3428
3429
        //Resize the images in two formats
3430
        $medium = new Image($source_file);
3431
        $medium->resize(85);
3432
        $medium->send_image($course_medium_image, -1, 'png');
3433
        $normal = new Image($source_file);
3434
        $normal->resize(400);
3435
        $normal->send_image($course_image, -1, 'png');
3436
3437
        $result = $medium && $normal;
3438
3439
        return $result ? $result : false;
3440
    }
3441
3442
    /**
3443
     * Deletes the course picture
3444
     * @param string $courseCode
3445
     */
3446
    public static function deleteCoursePicture($courseCode)
3447
    {
3448
        $course_info = api_get_course_info($courseCode);
3449
        // course path
3450
        $storePath = api_get_path(SYS_COURSE_PATH).$course_info['path'];
3451
        // image name for courses
3452
        $courseImage = $storePath.'/course-pic.png';
3453
        $courseMediumImage = $storePath.'/course-pic85x85.png';
3454
        $courseSmallImage = $storePath.'/course-pic32.png';
3455
3456
        if (file_exists($courseImage)) {
3457
            unlink($courseImage);
3458
        }
3459
        if (file_exists($courseMediumImage)) {
3460
            unlink($courseMediumImage);
3461
        }
3462
        if (file_exists($courseSmallImage)) {
3463
            unlink($courseSmallImage);
3464
        }
3465
    }
3466
3467
    /**
3468
     * Builds the course block in user_portal.php
3469
     * @todo use Twig
3470
     *
3471
     * @param array $params
3472
     * @return string
3473
     */
3474
    public static function course_item_html_no_icon($params)
3475
    {
3476
        $html = '<div class="course_item">';
3477
        $html .= '<div class="row">';
3478
        $html .= '<div class="col-md-7">';
3479
3480
        $notifications = isset($params['notifications']) ? $params['notifications'] : null;
3481
3482
        $html .= '<h3>'.$params['title'].$notifications.'</h3> ';
3483
3484
        if (isset($params['description'])) {
3485
            $html .= '<p>'.$params['description'].'</p>';
3486
        }
3487
        if (!empty($params['subtitle'])) {
3488
            $html .= '<small>'.$params['subtitle'].'</small>';
3489
        }
3490
        if (!empty($params['teachers'])) {
3491
            $html .= '<h5 class="teacher">'.
3492
                Display::return_icon(
3493
                    'teacher.png',
3494
                    get_lang('Teacher'),
3495
                    [],
3496
                    ICON_SIZE_TINY
3497
                ).
3498
                $params['teachers'].'</h5>';
3499
        }
3500
        if (!empty($params['coaches'])) {
3501
            $html .= '<h5 class="teacher">'.
3502
                Display::return_icon(
3503
                    'teacher.png',
3504
                    get_lang('Coach'),
3505
                    [],
3506
                    ICON_SIZE_TINY
3507
                ).
3508
                $params['coaches'].'</h5>';
3509
        }
3510
3511
        $html .= '</div>';
3512
        $params['right_actions'] = isset($params['right_actions']) ? $params['right_actions'] : null;
3513
        $html .= '<div class="pull-right course-box-actions">'.$params['right_actions'].'</div>';
3514
        $html .= '</div>';
3515
        $html .= '</div>';
3516
3517
        return $html;
3518
    }
3519
3520
    /**
3521
     * @param $params
3522
     * @param bool|false $is_sub_content
3523
     * @return string
3524
     */
3525
    public static function session_items_html($params, $is_sub_content = false)
3526
    {
3527
        $html = '';
3528
        $html .= '<div class="row">';
3529
        $html .= '<div class="col-md-2">';
3530
        if (!empty($params['link'])) {
3531
            $html .= '<a class="thumbnail" href="'.$params['link'].'">';
3532
            $html .= $params['icon'];
3533
            $html .= '</a>';
3534
        } else {
3535
            $html .= $params['icon'];
3536
        }
3537
        $html .= '</div>';
3538
        $html .= '<div class="col-md-10">';
3539
        $html .= $params['title'];
3540
        $html .= $params['coaches'];
3541
        $html .= '</div>';
3542
        $html .= '</div>';
3543
3544
        return $html;
3545
    }
3546
3547
    /**
3548
     * Display special courses (and only these) as several HTML divs of class userportal-course-item
3549
     *
3550
     * Special courses are courses that stick on top of the list and are "auto-registerable"
3551
     * in the sense that any user clicking them is registered as a student
3552
     * @param int       $user_id User id
3553
     * @param bool      $load_dirs Whether to show the document quick-loader or not
3554
     * @param bool $useUserLanguageFilterIfAvailable
3555
     * @return array
3556
     */
3557
    public static function returnSpecialCourses(
3558
        $user_id,
3559
        $load_dirs = false,
3560
        $useUserLanguageFilterIfAvailable = true
3561
    ) {
3562
        $user_id = intval($user_id);
3563
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
3564
        $specialCourseList = self::get_special_course_list();
3565
3566
        if (empty($specialCourseList)) {
3567
            return [];
3568
        }
3569
3570
        // Filter by language
3571
        $languageCondition = '';
3572
        $onlyInUserLanguage = api_get_configuration_value('my_courses_show_courses_in_user_language_only');
3573
        if ($useUserLanguageFilterIfAvailable && $onlyInUserLanguage) {
3574
            $userInfo = api_get_user_info(api_get_user_id());
3575
            if (!empty($userInfo['language'])) {
3576
                $languageCondition = " AND course_language = '".$userInfo['language']."' ";
3577
            }
3578
        }
3579
3580
        $sql = "SELECT
3581
                    id,
3582
                    code,
3583
                    subscribe subscr,
3584
                    unsubscribe unsubscr
3585
                FROM $table                      
3586
                WHERE 
3587
                    id IN ('".implode("','", $specialCourseList)."')
3588
                    $languageCondition
3589
                GROUP BY code";
3590
3591
        $rs_special_course = Database::query($sql);
3592
        $number_of_courses = Database::num_rows($rs_special_course);
3593
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
3594
3595
        $courseList = [];
3596
        if ($number_of_courses > 0) {
3597
            while ($course = Database::fetch_array($rs_special_course)) {
3598
                $course_info = api_get_course_info($course['code']);
3599
                $courseId = $course_info['real_id'];
3600
                if ($course_info['visibility'] == COURSE_VISIBILITY_HIDDEN) {
3601
                    continue;
3602
                }
3603
3604
                $params = [];
3605
                //Param (course_code) needed to get the student info in page "My courses"
3606
                $params['course_code'] = $course['code'];
3607
                $params['code'] = $course['code'];
3608
                // Get notifications.
3609
                $course_info['id_session'] = null;
3610
                $courseUserInfo = self::getUserCourseInfo($user_id, $courseId);
3611
3612
                if (empty($courseUserInfo)) {
3613
                    $course_info['status'] = STUDENT;
3614
                } else {
3615
                    $course_info['status'] = $courseUserInfo['status'];
3616
                }
3617
                $show_notification = !api_get_configuration_value('hide_course_notification')
3618
                    ? Display::show_notification($course_info)
3619
                    : '';
3620
                $params['edit_actions'] = '';
3621
                $params['document'] = '';
3622
                if (api_is_platform_admin()) {
3623
                    $params['edit_actions'] .= api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cidReq='.$course['code'];
3624
                    if ($load_dirs) {
3625
                        $params['document'] = '<a id="document_preview_'.$courseId.'_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3626
                           .Display::returnFontAwesomeIcon('folder-open').'</a>';
3627
                        $params['document'] .= Display::div('', ['id' => 'document_result_'.$courseId.'_0', 'class' => 'document_preview_container']);
3628
                    }
3629
                } else {
3630
                    if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED && $load_dirs) {
3631
                        $params['document'] = '<a id="document_preview_'.$courseId.'_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3632
                           .Display::returnFontAwesomeIcon('folder-open').'</a>';
3633
                        $params['document'] .= Display::div('', ['id' => 'document_result_'.$courseId.'_0', 'class' => 'document_preview_container']);
3634
                    }
3635
                }
3636
3637
                $params['visibility'] = $course_info['visibility'];
3638
                $params['status'] = $course_info['status'];
3639
                $params['category'] = $course_info['categoryName'];
3640
                $params['category_code'] = $course_info['categoryCode'];
3641
                $params['icon'] = Display::return_icon(
3642
                    'drawing-pin.png',
3643
                    null,
3644
                    null,
3645
                    ICON_SIZE_LARGE,
3646
                    null
3647
                );
3648
3649
                if (api_get_setting('display_coursecode_in_courselist') == 'true') {
3650
                    $params['code_course'] = '('.$course_info['visual_code'].')';
3651
                }
3652
3653
                $params['title'] = $course_info['title'];
3654
                $params['title_cut'] = $course_info['title'];
3655
                $params['link'] = $course_info['course_public_url'].'?id_session=0&autoreg=1';
3656
                if (api_get_setting('display_teacher_in_courselist') === 'true') {
3657
                    $params['teachers'] = self::getTeachersFromCourse(
3658
                        $courseId,
3659
                        true
3660
                    );
3661
                }
3662
3663
                if ($showCustomIcon === 'true') {
3664
                    $params['thumbnails'] = $course_info['course_image'];
3665
                    $params['image'] = $course_info['course_image_large'];
3666
                }
3667
3668
                if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
3669
                    $params['notifications'] = $show_notification;
3670
                }
3671
3672
                $params['is_special_course'] = true;
3673
                $courseList[] = $params;
3674
            }
3675
        }
3676
3677
        return $courseList;
3678
    }
3679
3680
    /**
3681
     * Display courses (without special courses) as several HTML divs
3682
     * of course categories, as class userportal-catalog-item.
3683
     * @uses displayCoursesInCategory() to display the courses themselves
3684
     * @param int $user_id
3685
     * @param bool  $load_dirs Whether to show the document quick-loader or not
3686
     * @param bool $useUserLanguageFilterIfAvailable
3687
     *
3688
     * @return array
3689
     */
3690
    public static function returnCourses(
3691
        $user_id,
3692
        $load_dirs = false,
3693
        $useUserLanguageFilterIfAvailable = true
3694
    ) {
3695
        $user_id = intval($user_id);
3696
        if (empty($user_id)) {
3697
            $user_id = api_get_user_id();
3698
        }
3699
        // Step 1: We get all the categories of the user
3700
        $table = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
3701
        $sql = "SELECT id, title FROM $table
3702
                WHERE user_id = '".$user_id."'
3703
                ORDER BY sort ASC";
3704
3705
        $result = Database::query($sql);
3706
        $listItems = [
3707
            'in_category' => [],
3708
            'not_category' => []
3709
        ];
3710
        while ($row = Database::fetch_array($result)) {
3711
            // We simply display the title of the category.
3712
            $courseInCategory = self::returnCoursesCategories(
3713
                $row['id'],
3714
                $load_dirs,
3715
                $user_id,
3716
                $useUserLanguageFilterIfAvailable
3717
            );
3718
3719
            $params = [
3720
                'id_category' => $row ['id'],
3721
                'title_category' => $row['title'],
3722
                'courses' => $courseInCategory
3723
            ];
3724
            $listItems['in_category'][] = $params;
3725
        }
3726
3727
        // Step 2: We display the course without a user category.
3728
        $coursesNotCategory = self::returnCoursesCategories(
3729
            0,
3730
            $load_dirs,
3731
            $user_id,
3732
            $useUserLanguageFilterIfAvailable
3733
        );
3734
3735
        if ($coursesNotCategory) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $coursesNotCategory 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...
3736
            $listItems['not_category'] = $coursesNotCategory;
3737
        }
3738
3739
        return $listItems;
3740
    }
3741
3742
    /**
3743
     *  Display courses inside a category (without special courses) as HTML dics of
3744
     *  class userportal-course-item.
3745
     * @param int      $user_category_id User category id
3746
     * @param bool $load_dirs Whether to show the document quick-loader or not
3747
     * @param int $user_id
3748
     * @param bool $useUserLanguageFilterIfAvailable
3749
     * @return array
3750
     */
3751
    public static function returnCoursesCategories(
3752
        $user_category_id,
3753
        $load_dirs = false,
3754
        $user_id = 0,
3755
        $useUserLanguageFilterIfAvailable = true
3756
    ) {
3757
        $user_id = $user_id ?: api_get_user_id();
3758
        $user_category_id = (int) $user_category_id;
3759
3760
        // Table definitions
3761
        $TABLECOURS = Database::get_main_table(TABLE_MAIN_COURSE);
3762
        $TABLECOURSUSER = Database::get_main_table(TABLE_MAIN_COURSE_USER);
3763
        $TABLE_ACCESS_URL_REL_COURSE = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
3764
        $current_url_id = api_get_current_access_url_id();
3765
3766
        // Get course list auto-register
3767
        $special_course_list = self::get_special_course_list();
3768
        $without_special_courses = '';
3769
        if (!empty($special_course_list)) {
3770
            $without_special_courses = ' AND course.id NOT IN ("'.implode('","', $special_course_list).'")';
3771
        }
3772
3773
        $userCategoryCondition = " (course_rel_user.user_course_cat = $user_category_id) ";
3774
        if (empty($user_category_id)) {
3775
            $userCategoryCondition = ' (course_rel_user.user_course_cat = 0 OR course_rel_user.user_course_cat IS NULL) ';
3776
        }
3777
3778
        $languageCondition = '';
3779
        $onlyInUserLanguage = api_get_configuration_value('my_courses_show_courses_in_user_language_only');
3780
        if ($useUserLanguageFilterIfAvailable && $onlyInUserLanguage) {
3781
            $userInfo = api_get_user_info(api_get_user_id());
3782
            if (!empty($userInfo['language'])) {
3783
                $languageCondition = " AND course.course_language = '".$userInfo['language']."' ";
3784
            }
3785
        }
3786
3787
        $sql = "SELECT DISTINCT
3788
                    course.id,
3789
                    course_rel_user.status status,
3790
                    course.code as course_code,
3791
                    user_course_cat,
3792
                    course_rel_user.sort
3793
                FROM $TABLECOURS course 
3794
                INNER JOIN $TABLECOURSUSER course_rel_user
3795
                ON (course.id = course_rel_user.c_id)
3796
                INNER JOIN $TABLE_ACCESS_URL_REL_COURSE url
3797
                ON (url.c_id = course.id)
3798
                WHERE
3799
                    course_rel_user.user_id = '".$user_id."' AND
3800
                    $userCategoryCondition
3801
                    $without_special_courses
3802
                    $languageCondition
3803
                ";
3804
        // If multiple URL access mode is enabled, only fetch courses
3805
        // corresponding to the current URL.
3806
        if (api_get_multiple_access_url() && $current_url_id != -1) {
3807
            $sql .= " AND access_url_id='".$current_url_id."'";
3808
        }
3809
        // Use user's classification for courses (if any).
3810
        $sql .= " ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
3811
        $result = Database::query($sql);
3812
3813
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
3814
        // Browse through all courses.
3815
        $courseAdded = [];
3816
        $courseList = [];
3817
        while ($row = Database::fetch_array($result)) {
3818
            $course_info = api_get_course_info_by_id($row['id']);
3819
3820
            if (isset($course_info['visibility']) &&
3821
                $course_info['visibility'] == COURSE_VISIBILITY_HIDDEN
3822
            ) {
3823
                continue;
3824
            }
3825
3826
            // Skip if already in list
3827
            if (in_array($course_info['real_id'], $courseAdded)) {
3828
                continue;
3829
            }
3830
            $course_info['id_session'] = null;
3831
            $course_info['status'] = $row['status'];
3832
            // For each course, get if there is any notification icon to show
3833
            // (something that would have changed since the user's last visit).
3834
            $showNotification = !api_get_configuration_value('hide_course_notification')
3835
                ? Display::show_notification($course_info)
3836
                : '';
3837
            $iconName = basename($course_info['course_image']);
3838
3839
            $params = [];
3840
            //Param (course_code) needed to get the student process
3841
            $params['course_code'] = $row['course_code'];
3842
            $params['code'] = $row['course_code'];
3843
3844
            if ($showCustomIcon === 'true' && $iconName != 'course.png') {
3845
                $params['thumbnails'] = $course_info['course_image'];
3846
                $params['image'] = $course_info['course_image_large'];
3847
            }
3848
3849
            $thumbnails = null;
3850
            $image = null;
3851
            if ($showCustomIcon === 'true' && $iconName != 'course.png') {
3852
                $thumbnails = $course_info['course_image'];
3853
                $image = $course_info['course_image_large'];
3854
            } else {
3855
                $image = Display::return_icon(
3856
                    'session_default.png',
3857
                    null,
3858
                    null,
3859
                    null,
3860
                    null,
3861
                    true
3862
                );
3863
            }
3864
3865
            $params['course_id'] = $course_info['real_id'];
3866
            $params['edit_actions'] = '';
3867
            $params['document'] = '';
3868
            if (api_is_platform_admin()) {
3869
                $params['edit_actions'] .= api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cidReq='.$course_info['code'];
3870
                if ($load_dirs) {
3871
                    $params['document'] = '<a id="document_preview_'.$course_info['real_id'].'_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3872
                               .Display::returnFontAwesomeIcon('folder-open').'</a>';
3873
                    $params['document'] .= Display::div(
3874
                        '',
3875
                        [
3876
                            'id' => 'document_result_'.$course_info['real_id'].'_0',
3877
                            'class' => 'document_preview_container',
3878
                        ]
3879
                    );
3880
                }
3881
            }
3882
            if ($load_dirs) {
3883
                $params['document'] = '<a id="document_preview_'.$course_info['real_id'].'_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3884
                    . Display::returnFontAwesomeIcon('folder-open').'</a>';
3885
                $params['document'] .= Display::div(
3886
                    '',
3887
                    [
3888
                        'id' => 'document_result_'.$course_info['real_id'].'_0',
3889
                        'class' => 'document_preview_container',
3890
                    ]
3891
                );
3892
            }
3893
3894
            $courseUrl = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/index.php?id_session=0';
3895
            $teachers = [];
3896
            if (api_get_setting('display_teacher_in_courselist') === 'true') {
3897
                $teachers = self::getTeachersFromCourse(
3898
                    $course_info['real_id'],
3899
                    true
3900
                );
3901
            }
3902
3903
            $params['status'] = $row['status'];
3904
            if (api_get_setting('display_coursecode_in_courselist') == 'true') {
3905
                $params['code_course'] = '('.$course_info['visual_code'].') ';
3906
            }
3907
3908
            $params['current_user_is_teacher'] = false;
3909
            /** @var array $teacher */
3910
            foreach ($teachers as $teacher) {
3911
                if ($teacher['id'] != $user_id) {
3912
                    continue;
3913
                }
3914
                $params['current_user_is_teacher'] = true;
3915
            }
3916
3917
            $params['visibility'] = $course_info['visibility'];
3918
            $params['link'] = $courseUrl;
3919
            $params['thumbnails'] = $thumbnails;
3920
            $params['image'] = $image;
3921
            $params['title'] = $course_info['title'];
3922
            $params['title_cut'] = $params['title'];
3923
            $params['category'] = $course_info['categoryName'];
3924
            $params['category_code'] = $course_info['categoryCode'];
3925
            $params['teachers'] = $teachers;
3926
3927
            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
3928
                $params['notifications'] = $showNotification;
3929
            }
3930
            $courseAdded[] = $course_info['real_id'];
3931
            $courseList[] = $params;
3932
        }
3933
3934
        return $courseList;
3935
    }
3936
3937
    /**
3938
     *  Display courses inside a category (without special courses) as HTML dics of
3939
     *  class userportal-course-item.
3940
     * @deprecated use self::returnCoursesCategories(0);
3941
     * @param int      User category id
3942
     * @param bool      Whether to show the document quick-loader or not
3943
     * @return array
3944
     */
3945
    public static function returnCoursesWithoutCategories($user_category_id, $load_dirs = false)
3946
    {
3947
        $user_id = api_get_user_id();
3948
        // Table definitions
3949
        $TABLECOURS = Database::get_main_table(TABLE_MAIN_COURSE);
3950
        $TABLECOURSUSER = Database::get_main_table(TABLE_MAIN_COURSE_USER);
3951
        $TABLE_ACCESS_URL_REL_COURSE = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
3952
        $current_url_id = api_get_current_access_url_id();
3953
        $courseList = [];
3954
3955
        // Get course list auto-register
3956
        $special_course_list = self::get_special_course_list();
3957
3958
        $without_special_courses = '';
3959
        if (!empty($special_course_list)) {
3960
            $without_special_courses = ' AND course.id NOT IN ("'.implode('","', $special_course_list).'")';
3961
        }
3962
3963
        $sql = "SELECT
3964
                    course.id,
3965
                    course.title,
3966
                    course.code,
3967
                    course.subscribe subscr,
3968
                    course.unsubscribe unsubscr,
3969
                    course_rel_user.status status,
3970
                    course_rel_user.sort sort,
3971
                    course_rel_user.user_course_cat user_course_cat
3972
                FROM $TABLECOURS course 
3973
                INNER JOIN $TABLECOURSUSER course_rel_user
3974
                ON (course.id = course_rel_user.c_id)
3975
                INNER JOIN $TABLE_ACCESS_URL_REL_COURSE url
3976
                ON (url.c_id = course.id)
3977
                WHERE
3978
                    course_rel_user.user_id = '".$user_id."' AND
3979
                    course_rel_user.user_course_cat = '" . $user_category_id."'
3980
                    $without_special_courses ";
3981
3982
        // If multiple URL access mode is enabled, only fetch courses
3983
        // corresponding to the current URL.
3984
        if (api_get_multiple_access_url() && $current_url_id != -1) {
3985
            $sql .= " AND url.c_id = course.id AND access_url_id='".$current_url_id."'";
3986
        }
3987
        // Use user's classification for courses (if any).
3988
        $sql .= " ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
3989
        $result = Database::query($sql);
3990
3991
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
3992
        // Browse through all courses.
3993
        while ($row = Database::fetch_array($result)) {
3994
            $course_info = api_get_course_info($row['code']);
3995
            if (isset($course_info['visibility']) &&
3996
                $course_info['visibility'] == COURSE_VISIBILITY_HIDDEN
3997
            ) {
3998
                continue;
3999
            }
4000
            $course_info['id_session'] = null;
4001
            $course_info['status'] = $row['status'];
4002
4003
            // For each course, get if there is any notification icon to show
4004
            // (something that would have changed since the user's last visit).
4005
            $showNotification = !api_get_configuration_value('hide_course_notification')
4006
                ? Display::show_notification($course_info)
4007
                : '';
4008
4009
            $thumbnails = null;
4010
            $image = null;
4011
            $iconName = basename($course_info['course_image']);
4012
            if ($showCustomIcon === 'true' && $iconName != 'course.png') {
4013
                $thumbnails = $course_info['course_image'];
4014
                $image = $course_info['course_image_large'];
4015
            } else {
4016
                $image = Display::return_icon(
4017
                    'session_default.png',
4018
                    null,
4019
                    null,
4020
                    null,
4021
                    null,
4022
                    true
4023
                );
4024
            }
4025
4026
            $params = [];
4027
            //Param (course_code) needed to get the student process
4028
            $params['course_code'] = $row['code'];
4029
            $params['edit_actions'] = '';
4030
            $params['document'] = '';
4031
            if (api_is_platform_admin()) {
4032
                $params['edit_actions'] .= api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cidReq='.$course_info['code'];
4033
                if ($load_dirs) {
4034
                    $params['document'] = '<a id="document_preview_'.$course_info['real_id'].'_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
4035
                               . Display::returnFontAwesomeIcon('folder-open').'</a>';
4036
                    $params['document'] .= Display::div('', ['id' => 'document_result_'.$course_info['real_id'].'_0', 'class' => 'document_preview_container']);
4037
                }
4038
            }
4039
            if ($load_dirs) {
4040
                $params['document'] = '<a id="document_preview_'.$course_info['real_id'].'_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
4041
                    .Display::returnFontAwesomeIcon('folder-open').'</a>';
4042
                $params['document'] .= Display::div('', ['id' => 'document_result_'.$course_info['real_id'].'_0', 'class' => 'document_preview_container']);
4043
            }
4044
4045
            $course_title_url = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/index.php?id_session=0';
4046
4047
            $teachers = [];
4048
            if (api_get_setting('display_teacher_in_courselist') === 'true') {
4049
                $teachers = self::getTeachersFromCourse(
4050
                    $course_info['real_id'],
4051
                    false
4052
                );
4053
            }
4054
            $params['status'] = $row['status'];
4055
4056
            if (api_get_setting('display_coursecode_in_courselist') == 'true') {
4057
                $params['code_course'] = '('.$course_info['visual_code'].') ';
4058
            }
4059
4060
            $params['visibility'] = $course_info['visibility'];
4061
            $params['link'] = $course_title_url;
4062
            $params['thumbnails'] = $thumbnails;
4063
            $params['image'] = $image;
4064
            $params['title'] = $course_info['title'];
4065
            $params['category'] = $course_info['categoryName'];
4066
            $params['teachers'] = $teachers;
4067
4068
            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
4069
                $params['notifications'] = $showNotification;
4070
            }
4071
4072
            $courseList[] = $params;
4073
        }
4074
4075
        return $courseList;
4076
    }
4077
4078
    /**
4079
     * Retrieves the user defined course categories
4080
     * @param int $userId
4081
     * @return array
4082
     */
4083
    public static function get_user_course_categories($userId = 0)
4084
    {
4085
        $userId = empty($userId) ? api_get_user_id() : (int) $userId;
4086
        $table = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
4087
        $sql = "SELECT * FROM $table 
4088
                WHERE user_id = $userId
4089
                ORDER BY sort ASC
4090
                ";
4091
        $result = Database::query($sql);
4092
        $output = [];
4093
        while ($row = Database::fetch_array($result, 'ASSOC')) {
4094
            $output[$row['id']] = $row;
4095
        }
4096
        return $output;
4097
    }
4098
4099
    /**
4100
     * Return an array the user_category id and title for the course $courseId for user $userId
4101
     * @param $userId
4102
     * @param $courseId
4103
     * @return array
4104
     */
4105
    public static function getUserCourseCategoryForCourse($userId, $courseId)
4106
    {
4107
        $tblCourseRelUser = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4108
        $tblUserCategory = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
4109
        $courseId = intval($courseId);
4110
        $userId = intval($userId);
4111
4112
        $sql = "SELECT user_course_cat, title
4113
                FROM $tblCourseRelUser cru
4114
                LEFT JOIN $tblUserCategory ucc
4115
                ON cru.user_course_cat = ucc.id
4116
                WHERE
4117
                    cru.user_id = $userId AND c_id= $courseId ";
4118
4119
        $res = Database::query($sql);
4120
4121
        $data = [];
4122
        if (Database::num_rows($res) > 0) {
4123
            $data = Database::fetch_assoc($res);
4124
        }
4125
4126
        return $data;
4127
    }
4128
4129
    /**
4130
     * Get the course id based on the original id and field name in the extra fields.
4131
     * Returns 0 if course was not found
4132
     *
4133
     * @param string $value Original course code
4134
     * @param string $variable Original field name
4135
     * @return array
4136
     */
4137
    public static function getCourseInfoFromOriginalId($value, $variable)
4138
    {
4139
        $extraFieldValue = new ExtraFieldValue('course');
4140
        $result = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
4141
            $variable,
4142
            $value
4143
        );
4144
4145
        if (!empty($result)) {
4146
            $courseInfo = api_get_course_info_by_id($result['item_id']);
4147
            return $courseInfo;
4148
        }
4149
4150
        return [];
4151
    }
4152
4153
    /**
4154
     * Display code for one specific course a logged in user is subscribed to.
4155
     * Shows a link to the course, what's new icons...
4156
     *
4157
     * $my_course['d'] - course directory
4158
     * $my_course['i'] - course title
4159
     * $my_course['c'] - visual course code
4160
     * $my_course['k']  - system course code
4161
     *
4162
     * @param   array       Course details
4163
     * @param   integer     Session ID
4164
     * @param   string      CSS class to apply to course entry
4165
     * @param   boolean     Whether the session is supposedly accessible now
4166
     * (not in the case it has passed and is in invisible/unaccessible mode)
4167
     * @param bool      Whether to show the document quick-loader or not
4168
     * @return  string      The HTML to be printed for the course entry
4169
     *
4170
     * @version 1.0.3
4171
     * @todo refactor into different functions for database calls | logic | display
4172
     * @todo replace single-character $my_course['d'] indices
4173
     * @todo move code for what's new icons to a separate function to clear things up
4174
     * @todo add a parameter user_id so that it is possible to show the
4175
     * courselist of other users (=generalisation).
4176
     * This will prevent having to write a new function for this.
4177
     */
4178
    public static function get_logged_user_course_html(
4179
        $course,
4180
        $session_id = 0,
4181
        $class = 'courses',
4182
        $session_accessible = true,
4183
        $load_dirs = false
4184
    ) {
4185
        $now = date('Y-m-d h:i:s');
4186
        $user_id = api_get_user_id();
4187
        $course_info = api_get_course_info_by_id($course['real_id']);
4188
        $course_visibility = $course_info['visibility'];
4189
4190
        if ($course_visibility == COURSE_VISIBILITY_HIDDEN) {
4191
            return '';
4192
        }
4193
4194
        $userInCourseStatus = self::getUserInCourseStatus(
4195
            $user_id,
4196
            $course_info['real_id']
4197
        );
4198
4199
        $course_info['status'] = empty($session_id) ? $userInCourseStatus : STUDENT;
4200
        $course_info['id_session'] = $session_id;
4201
4202
        $is_coach = api_is_coach($session_id, $course_info['real_id']);
0 ignored issues
show
Bug introduced by
It seems like $course_info['real_id'] can also be of type boolean; however, parameter $courseId of api_is_coach() does only seem to accept integer, 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

4202
        $is_coach = api_is_coach($session_id, /** @scrutinizer ignore-type */ $course_info['real_id']);
Loading history...
4203
4204
        // Display course entry.
4205
        // Show a hyperlink to the course, unless the course is closed and user is not course admin.
4206
        $session_url = '';
4207
        $params = [];
4208
        $params['icon'] = Display::return_icon(
4209
            'blackboard_blue.png',
4210
            null,
4211
            [],
4212
            ICON_SIZE_LARGE,
4213
            null,
4214
            true
4215
        );
4216
        $params['real_id'] = $course_info['real_id'];
4217
4218
        // Display the "what's new" icons
4219
        $notifications = '';
4220
        if (
4221
            ($course_visibility != COURSE_VISIBILITY_CLOSED && $course_visibility != COURSE_VISIBILITY_HIDDEN) ||
4222
            !api_get_configuration_value('hide_course_notification')
4223
        ) {
4224
            $notifications .= Display::show_notification($course_info);
4225
        }
4226
4227
        if ($session_accessible) {
4228
            if ($course_visibility != COURSE_VISIBILITY_CLOSED ||
4229
                $userInCourseStatus == COURSEMANAGER
4230
            ) {
4231
                if (empty($course_info['id_session'])) {
4232
                    $course_info['id_session'] = 0;
4233
                }
4234
4235
                $sessionCourseAvailable = false;
4236
                $sessionCourseStatus = api_get_session_visibility($session_id, $course_info['real_id']);
0 ignored issues
show
Bug introduced by
It seems like $course_info['real_id'] can also be of type boolean; however, parameter $courseId of api_get_session_visibility() does only seem to accept integer, 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

4236
                $sessionCourseStatus = api_get_session_visibility($session_id, /** @scrutinizer ignore-type */ $course_info['real_id']);
Loading history...
4237
4238
                if (in_array(
4239
                    $sessionCourseStatus,
4240
                    [SESSION_VISIBLE_READ_ONLY, SESSION_VISIBLE, SESSION_AVAILABLE]
4241
                )) {
4242
                    $sessionCourseAvailable = true;
4243
                }
4244
4245
                if ($userInCourseStatus == COURSEMANAGER || $sessionCourseAvailable) {
4246
                    $session_url = $course_info['course_public_url'].'?id_session='.$course_info['id_session'];
4247
                    $session_title = '<a href="'.$session_url.'">'.$course_info['name'].'</a>'.$notifications;
4248
                } else {
4249
                    $session_title = $course_info['name'];
4250
                }
4251
            } else {
4252
                $session_title =
4253
                    $course_info['name'].' '.
4254
                    Display::tag('span', get_lang('CourseClosed'), ['class' => 'item_closed']);
4255
            }
4256
        } else {
4257
            $session_title = $course_info['name'];
4258
        }
4259
4260
        $thumbnails = null;
4261
        $image = null;
4262
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
4263
        $iconName = basename($course_info['course_image']);
4264
4265
        if ($showCustomIcon === 'true' && $iconName != 'course.png') {
4266
            $thumbnails = $course_info['course_image'];
4267
            $image = $course_info['course_image_large'];
4268
        } else {
4269
            $image = Display::return_icon(
4270
                'session_default.png',
4271
                null,
4272
                null,
4273
                null,
4274
                null,
4275
                true
4276
            );
4277
        }
4278
        $params['thumbnails'] = $thumbnails;
4279
        $params['image'] = $image;
4280
        $params['link'] = $session_url;
4281
        $params['title'] = $session_title;
4282
        $params['edit_actions'] = '';
4283
        $params['document'] = '';
4284
        $params['category'] = $course_info['categoryName'];
4285
4286
        if ($course_visibility != COURSE_VISIBILITY_CLOSED &&
4287
            $course_visibility != COURSE_VISIBILITY_HIDDEN
4288
        ) {
4289
            if (api_is_platform_admin()) {
4290
                $params['edit_actions'] .= api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cidReq='.$course_info['code'];
4291
                if ($load_dirs) {
4292
                    $params['document'] .= '<a id="document_preview_'.$course_info['real_id'].'_'.$course_info['id_session'].'" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'.
4293
                        Display::returnFontAwesomeIcon('folder-open').'</a>';
4294
                    $params['document'] .= Display::div('', [
4295
                        'id' => 'document_result_'.$course_info['real_id'].'_'.$course_info['id_session'],
4296
                        'class' => 'document_preview_container'
4297
                    ]);
4298
                }
4299
            }
4300
        }
4301
        if (api_get_setting('display_teacher_in_courselist') === 'true') {
4302
            $teacher_list = self::getTeachersFromCourse(
4303
                $course_info['real_id'],
0 ignored issues
show
Bug introduced by
It seems like $course_info['real_id'] can also be of type boolean; however, parameter $courseId of CourseManager::getTeachersFromCourse() does only seem to accept integer, 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

4303
                /** @scrutinizer ignore-type */ $course_info['real_id'],
Loading history...
4304
                true
4305
            );
4306
4307
            $course_coachs = self::get_coachs_from_course(
4308
                $course_info['id_session'],
4309
                $course_info['real_id']
0 ignored issues
show
Bug introduced by
It seems like $course_info['real_id'] can also be of type boolean; however, parameter $courseId of CourseManager::get_coachs_from_course() does only seem to accept integer, 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

4309
                /** @scrutinizer ignore-type */ $course_info['real_id']
Loading history...
4310
            );
4311
            $params['teachers'] = $teacher_list;
4312
4313
            if (($course_info['status'] == STUDENT && !empty($course_info['id_session'])) ||
4314
                ($is_coach && $course_info['status'] != COURSEMANAGER)
4315
            ) {
4316
                $params['coaches'] = $course_coachs;
4317
            }
4318
        }
4319
        $special = isset($course['special_course']) ? true : false;
4320
        $params['title'] = $session_title;
4321
        $params['special'] = $special;
4322
        $params['code'] = $course_info['visual_code'];
4323
        $params['extra'] = '';
4324
        $html = $params;
4325
4326
        $session_category_id = null;
4327
        if (1) {
4328
            $session = '';
4329
            $active = false;
4330
            if (!empty($course_info['id_session'])) {
4331
                $session = api_get_session_info($course_info['id_session']);
4332
                $sessionCoachName = '';
4333
                if (!empty($session['id_coach'])) {
4334
                    $coachInfo = api_get_user_info($session['id_coach']);
4335
                    $sessionCoachName = $coachInfo['complete_name'];
4336
                }
4337
4338
                $session_category_id = self::get_session_category_id_by_session_id($course_info['id_session']);
4339
4340
                if (
4341
                    $session['access_start_date'] == '0000-00-00 00:00:00' || empty($session['access_start_date']) ||
4342
                    $session['access_start_date'] == '0000-00-00'
4343
                ) {
4344
                    $session['dates'] = '';
4345
                    if (api_get_setting('show_session_coach') === 'true') {
4346
                        $session['coach'] = get_lang('GeneralCoach').': '.$sessionCoachName;
4347
                    }
4348
                    $active = true;
4349
                } else {
4350
                    $session ['dates'] = ' - '.get_lang('From').' '.$session['access_start_date'].' '.get_lang('To').' '.$session['access_end_date'];
4351
                    if (api_get_setting('show_session_coach') === 'true') {
4352
                        $session['coach'] = get_lang('GeneralCoach').': '.$sessionCoachName;
4353
                    }
4354
                    $date_start = $session['access_start_date'];
4355
                    $date_end = $session['access_end_date'];
4356
                    $active = !$date_end ? ($date_start <= $now) : ($date_start <= $now && $date_end >= $now);
4357
                }
4358
            }
4359
            $user_course_category = '';
4360
            if (isset($course_info['user_course_cat'])) {
4361
                $user_course_category = $course_info['user_course_cat'];
4362
            }
4363
            $output = [
4364
                $user_course_category,
4365
                $html,
4366
                $course_info['id_session'],
4367
                $session,
4368
                'active' => $active,
4369
                'session_category_id' => $session_category_id
4370
            ];
4371
4372
            if (Skill::isAllowed($user_id, false)) {
4373
                $em = Database::getManager();
4374
                $objUser = api_get_user_entity($user_id);
4375
                $objCourse = $em->find('ChamiloCoreBundle:Course', $course['real_id']);
4376
                $objSession = $em->find('ChamiloCoreBundle:Session', $session_id);
4377
4378
                $skill = $em->getRepository('ChamiloCoreBundle:Skill')->getLastByUser($objUser, $objCourse, $objSession);
4379
4380
                $output['skill'] = null;
4381
                if ($skill) {
4382
                    $output['skill']['name'] = $skill->getName();
4383
                    $output['skill']['icon'] = $skill->getIcon();
4384
                }
4385
            }
4386
        } else {
4387
            $output = [$course_info['user_course_cat'], $html];
4388
        }
4389
4390
        return $output;
4391
    }
4392
4393
    /**
4394
     *
4395
     * @param string $source_course_code
4396
     * @param int $source_session_id
4397
     * @param string $destination_course_code
4398
     * @param int $destination_session_id
4399
     * @param array $params
4400
     *
4401
     * @return  bool
4402
     */
4403
    public static function copy_course(
4404
        $source_course_code,
4405
        $source_session_id,
4406
        $destination_course_code,
4407
        $destination_session_id,
4408
        $params = []
4409
    ) {
4410
        $course_info = api_get_course_info($source_course_code);
4411
4412
        if (!empty($course_info)) {
4413
            $cb = new CourseBuilder('', $course_info);
4414
            $course = $cb->build($source_session_id, $source_course_code, true);
4415
            $course_restorer = new CourseRestorer($course);
4416
            $course_restorer->skip_content = $params;
4417
            $course_restorer->restore(
4418
                $destination_course_code,
4419
                $destination_session_id,
4420
                true,
4421
                true
4422
            );
4423
            return true;
4424
        }
4425
        return false;
4426
    }
4427
4428
    /**
4429
     * A simpler version of the copy_course, the function creates an empty course with an autogenerated course code
4430
     *
4431
     * @param string $new_title new course title
4432
     * @param string source course code
4433
     * @param int source session id
4434
     * @param int destination session id
4435
     * @param array $params
4436
     *
4437
     * @return     array
4438
     */
4439
    public static function copy_course_simple(
4440
        $new_title,
4441
        $source_course_code,
4442
        $source_session_id = 0,
4443
        $destination_session_id = 0,
4444
        $params = []
4445
    ) {
4446
        $source_course_info = api_get_course_info($source_course_code);
4447
        if (!empty($source_course_info)) {
4448
            $new_course_code = self::generate_nice_next_course_code($source_course_code);
4449
            if ($new_course_code) {
4450
                $new_course_info = self::create_course(
4451
                    $new_title,
4452
                    $new_course_code,
4453
                    false
4454
                );
4455
                if (!empty($new_course_info['code'])) {
4456
                    $result = self::copy_course(
4457
                        $source_course_code,
4458
                        $source_session_id,
4459
                        $new_course_info['code'],
4460
                        $destination_session_id,
4461
                        $params
4462
                    );
4463
                    if ($result) {
4464
                        return $new_course_info;
4465
                    }
4466
                }
4467
            }
4468
        }
4469
4470
        return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type array.
Loading history...
4471
    }
4472
4473
    /**
4474
     * Creates a new course code based in a given code
4475
     *
4476
     * @param string    wanted code
4477
     * <code>    $wanted_code = 'curse' if there are in the DB codes like curse1 curse2 the function will return: course3</code>
4478
     * if the course code doest not exist in the DB the same course code will be returned
4479
     * @return string    wanted unused code
4480
     */
4481
    public static function generate_nice_next_course_code($wanted_code)
4482
    {
4483
        $course_code_ok = !self::course_code_exists($wanted_code);
4484
        if (!$course_code_ok) {
4485
            $wanted_code = self::generate_course_code($wanted_code);
4486
            $table = Database::get_main_table(TABLE_MAIN_COURSE);
4487
            $wanted_code = Database::escape_string($wanted_code);
4488
            $sql = "SELECT count(id) as count
4489
                    FROM $table
4490
                    WHERE code LIKE '$wanted_code%'";
4491
            $result = Database::query($sql);
4492
            if (Database::num_rows($result) > 0) {
4493
                $row = Database::fetch_array($result);
4494
                $count = $row['count'] + 1;
4495
                $wanted_code = $wanted_code.'_'.$count;
4496
                $result = api_get_course_info($wanted_code);
4497
                if (empty($result)) {
4498
                    return $wanted_code;
4499
                }
4500
            }
4501
4502
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type string.
Loading history...
4503
        }
4504
4505
        return $wanted_code;
4506
    }
4507
4508
    /**
4509
     * Gets the status of the users agreement in a course course-session
4510
     *
4511
     * @param int $user_id
4512
     * @param string $course_code
4513
     * @param int $session_id
4514
     * @return boolean
4515
     */
4516
    public static function is_user_accepted_legal($user_id, $course_code, $session_id = 0)
4517
    {
4518
        $user_id = intval($user_id);
4519
        $course_code = Database::escape_string($course_code);
4520
        $session_id = intval($session_id);
4521
4522
        $courseInfo = api_get_course_info($course_code);
4523
        $courseId = $courseInfo['real_id'];
4524
4525
        // Course legal
4526
        $enabled = api_get_plugin_setting('courselegal', 'tool_enable');
4527
4528
        if ($enabled == 'true') {
4529
            require_once api_get_path(SYS_PLUGIN_PATH).'courselegal/config.php';
4530
            $plugin = CourseLegalPlugin::create();
4531
            return $plugin->isUserAcceptedLegal($user_id, $course_code, $session_id);
4532
        }
4533
4534
        if (empty($session_id)) {
4535
            $table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4536
            $sql = "SELECT legal_agreement FROM $table
4537
                    WHERE user_id = $user_id AND c_id = $courseId ";
4538
            $result = Database::query($sql);
4539
            if (Database::num_rows($result) > 0) {
4540
                $result = Database::fetch_array($result);
4541
                if ($result['legal_agreement'] == 1) {
4542
                    return true;
4543
                }
4544
            }
4545
            return false;
4546
        } else {
4547
            $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4548
            $sql = "SELECT legal_agreement FROM $table
4549
                    WHERE user_id = $user_id AND c_id = $courseId AND session_id = $session_id";
4550
            $result = Database::query($sql);
4551
            if (Database::num_rows($result) > 0) {
4552
                $result = Database::fetch_array($result);
4553
                if ($result['legal_agreement'] == 1) {
4554
                    return true;
4555
                }
4556
            }
4557
            return false;
4558
        }
4559
    }
4560
4561
    /**
4562
     * Saves the user-course legal agreement
4563
     * @param   int user id
4564
     * @param   string course code
4565
     * @param   int session id
4566
     * @return mixed
4567
     */
4568
    public static function save_user_legal($user_id, $course_code, $session_id = null)
4569
    {
4570
        // Course plugin legal
4571
        $enabled = api_get_plugin_setting('courselegal', 'tool_enable');
4572
        if ($enabled == 'true') {
4573
            require_once api_get_path(SYS_PLUGIN_PATH).'courselegal/config.php';
4574
            $plugin = CourseLegalPlugin::create();
4575
            return $plugin->saveUserLegal($user_id, $course_code, $session_id);
4576
        }
4577
4578
        $user_id = intval($user_id);
4579
        $course_code = Database::escape_string($course_code);
4580
        $session_id = intval($session_id);
4581
        $courseInfo = api_get_course_info($course_code);
4582
        $courseId = $courseInfo['real_id'];
4583
4584
        if (empty($session_id)) {
4585
            $table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4586
            $sql = "UPDATE $table SET legal_agreement = '1'
4587
                    WHERE user_id = $user_id AND c_id  = $courseId ";
4588
            Database::query($sql);
4589
        } else {
4590
            $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4591
            $sql = "UPDATE  $table SET legal_agreement = '1'
4592
                    WHERE user_id = $user_id AND c_id = $courseId AND session_id = $session_id";
4593
            Database::query($sql);
4594
        }
4595
    }
4596
4597
    /**
4598
     * @param int $user_id
4599
     * @param int $course_id
4600
     * @param int $session_id
4601
     * @param int $url_id
4602
     * @return bool
4603
     */
4604
    public static function get_user_course_vote($user_id, $course_id, $session_id = 0, $url_id = 0)
4605
    {
4606
        $table_user_course_vote = Database::get_main_table(TABLE_MAIN_USER_REL_COURSE_VOTE);
4607
        $session_id = !isset($session_id) ? api_get_session_id() : intval($session_id);
4608
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4609
        $user_id = intval($user_id);
4610
4611
        if (empty($user_id)) {
4612
            return false;
4613
        }
4614
4615
        $params = [
4616
            'user_id' => $user_id,
4617
            'c_id' => $course_id,
4618
            'session_id' => $session_id,
4619
            'url_id' => $url_id
4620
        ];
4621
4622
        $result = Database::select(
4623
            'vote',
4624
            $table_user_course_vote,
4625
            [
4626
                'where' => [
4627
                    'user_id = ? AND c_id = ? AND session_id = ? AND url_id = ?' => $params
4628
                ]
4629
            ],
4630
            'first'
4631
        );
4632
        if (!empty($result)) {
4633
            return $result['vote'];
4634
        }
4635
        return false;
4636
    }
4637
4638
    /**
4639
     * @param int $course_id
4640
     * @param int $session_id
4641
     * @param int $url_id
4642
     * @return array
4643
     */
4644
    public static function get_course_ranking(
4645
        $course_id,
4646
        $session_id = 0,
4647
        $url_id = 0
4648
    ) {
4649
        $table_course_ranking = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
4650
4651
        $session_id = empty($session_id) ? api_get_session_id() : intval($session_id);
4652
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4653
        $now = api_get_utc_datetime();
4654
4655
        $params = [
4656
            'c_id' => $course_id,
4657
            'session_id' => $session_id,
4658
            'url_id' => $url_id,
4659
            'creation_date' => $now,
4660
        ];
4661
4662
        $result = Database::select(
4663
            'c_id, accesses, total_score, users',
4664
            $table_course_ranking,
4665
            ['where' => ['c_id = ? AND session_id = ? AND url_id = ?' => $params]],
4666
            'first'
4667
        );
4668
4669
        $point_average_in_percentage = 0;
4670
        $point_average_in_star = 0;
4671
        $users_who_voted = 0;
4672
4673
        if (!empty($result['users'])) {
4674
            $users_who_voted = $result['users'];
4675
            $point_average_in_percentage = round($result['total_score'] / $result['users'] * 100 / 5, 2);
4676
            $point_average_in_star = round($result['total_score'] / $result['users'], 1);
4677
        }
4678
4679
        $result['user_vote'] = false;
4680
        if (!api_is_anonymous()) {
4681
            $result['user_vote'] = self::get_user_course_vote(api_get_user_id(), $course_id, $session_id, $url_id);
4682
        }
4683
4684
        $result['point_average'] = $point_average_in_percentage;
4685
        $result['point_average_star'] = $point_average_in_star;
4686
        $result['users_who_voted'] = $users_who_voted;
4687
4688
        return $result;
4689
    }
4690
4691
    /**
4692
     *
4693
     * Updates the course ranking
4694
     * @param int   course id
4695
     * @param int   $session_id
4696
     * @param int    url id
4697
     * @param $points_to_add
4698
     * @param bool $add_access
4699
     * @param bool $add_user
4700
     * @return array
4701
     **/
4702
    public static function update_course_ranking(
4703
        $course_id = 0,
4704
        $session_id = 0,
4705
        $url_id = 0,
4706
        $points_to_add = null,
4707
        $add_access = true,
4708
        $add_user = true
4709
    ) {
4710
        // Course catalog stats modifications see #4191
4711
        $table_course_ranking = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
4712
        $now = api_get_utc_datetime();
4713
        $course_id = empty($course_id) ? api_get_course_int_id() : intval($course_id);
4714
        $session_id = empty($session_id) ? api_get_session_id() : intval($session_id);
4715
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4716
4717
        $params = [
4718
            'c_id' => $course_id,
4719
            'session_id' => $session_id,
4720
            'url_id' => $url_id,
4721
            'creation_date' => $now,
4722
            'total_score' => 0,
4723
            'users' => 0
4724
        ];
4725
4726
        $result = Database::select(
4727
            'id, accesses, total_score, users',
4728
            $table_course_ranking,
4729
            ['where' => ['c_id = ? AND session_id = ? AND url_id = ?' => $params]],
4730
            'first'
4731
        );
4732
4733
        // Problem here every time we load the courses/XXXX/index.php course home page we update the access
4734
        if (empty($result)) {
4735
            if ($add_access) {
4736
                $params['accesses'] = 1;
4737
            }
4738
            //The votes and users are empty
4739
            if (isset($points_to_add) && !empty($points_to_add)) {
4740
                $params['total_score'] = intval($points_to_add);
4741
            }
4742
            if ($add_user) {
4743
                $params['users'] = 1;
4744
            }
4745
            $result = Database::insert($table_course_ranking, $params);
4746
        } else {
4747
            $my_params = [];
4748
4749
            if ($add_access) {
4750
                $my_params['accesses'] = intval($result['accesses']) + 1;
4751
            }
4752
            if (isset($points_to_add) && !empty($points_to_add)) {
4753
                $my_params['total_score'] = $result['total_score'] + $points_to_add;
4754
            }
4755
            if ($add_user) {
4756
                $my_params['users'] = $result['users'] + 1;
4757
            }
4758
4759
            if (!empty($my_params)) {
4760
                $result = Database::update(
4761
                    $table_course_ranking,
4762
                    $my_params,
4763
                    ['c_id = ? AND session_id = ? AND url_id = ?' => $params]
4764
                );
4765
            }
4766
        }
4767
4768
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result also could return the type integer|false which is incompatible with the documented return type array.
Loading history...
4769
    }
4770
4771
    /**
4772
     * Add user vote to a course
4773
     *
4774
     * @param   int user id
4775
     * @param   int vote [1..5]
4776
     * @param   int course id
4777
     * @param   int session id
4778
     * @param   int url id (access_url_id)
4779
     * @return    false|string 'added', 'updated' or 'nothing'
4780
     */
4781
    public static function add_course_vote(
4782
        $user_id,
4783
        $vote,
4784
        $course_id,
4785
        $session_id = 0,
4786
        $url_id = 0
4787
    ) {
4788
        $table_user_course_vote = Database::get_main_table(TABLE_MAIN_USER_REL_COURSE_VOTE);
4789
        $course_id = empty($course_id) ? api_get_course_int_id() : intval($course_id);
4790
4791
        if (empty($course_id) || empty($user_id)) {
4792
            return false;
4793
        }
4794
4795
        if (!in_array($vote, [1, 2, 3, 4, 5])) {
4796
            return false;
4797
        }
4798
4799
        $session_id = empty($session_id) ? api_get_session_id() : intval($session_id);
4800
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4801
        $vote = intval($vote);
4802
4803
        $params = [
4804
            'user_id' => intval($user_id),
4805
            'c_id' => $course_id,
4806
            'session_id' => $session_id,
4807
            'url_id' => $url_id,
4808
            'vote' => $vote
4809
        ];
4810
4811
        $action_done = 'nothing';
4812
        $result = Database::select(
4813
            'id, vote',
4814
            $table_user_course_vote,
4815
            ['where' => ['user_id = ? AND c_id = ? AND session_id = ? AND url_id = ?' => $params]],
4816
            'first'
4817
        );
4818
4819
        if (empty($result)) {
4820
            Database::insert($table_user_course_vote, $params);
4821
            $points_to_add = $vote;
4822
            $add_user = true;
4823
            $action_done = 'added';
4824
        } else {
4825
            $my_params = ['vote' => $vote];
4826
            $points_to_add = $vote - $result['vote'];
4827
            $add_user = false;
4828
4829
            Database::update(
4830
                $table_user_course_vote,
4831
                $my_params,
4832
                ['user_id = ? AND c_id = ? AND session_id = ? AND url_id = ?' => $params]
4833
            );
4834
            $action_done = 'updated';
4835
        }
4836
4837
        // Current points
4838
        if (!empty($points_to_add)) {
4839
            self::update_course_ranking(
4840
                $course_id,
4841
                $session_id,
4842
                $url_id,
4843
                $points_to_add,
4844
                false,
4845
                $add_user
4846
            );
4847
        }
4848
        return $action_done;
4849
    }
4850
4851
    /**
4852
     * Remove course ranking + user votes
4853
     *
4854
     * @param int $course_id
4855
     * @param int $session_id
4856
     * @param int $url_id
4857
     *
4858
     */
4859
    public static function remove_course_ranking($course_id, $session_id, $url_id = null)
4860
    {
4861
        $table_course_ranking = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
4862
        $table_user_course_vote = Database::get_main_table(TABLE_MAIN_USER_REL_COURSE_VOTE);
4863
4864
        if (!empty($course_id) && isset($session_id)) {
4865
            $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4866
            $params = [
4867
                'c_id' => $course_id,
4868
                'session_id' => $session_id,
4869
                'url_id' => $url_id,
4870
            ];
4871
            Database::delete($table_course_ranking, ['c_id = ? AND session_id = ? AND url_id = ?' => $params]);
4872
            Database::delete($table_user_course_vote, ['c_id = ? AND session_id = ? AND url_id = ?' => $params]);
4873
        }
4874
    }
4875
4876
    /**
4877
     * Returns an array with the hottest courses
4878
     * @param   int $days number of days
4879
     * @param   int $limit number of hottest courses
4880
     * @return array
4881
     */
4882
    public static function return_hot_courses($days = 30, $limit = 6)
4883
    {
4884
        if (api_is_invitee()) {
4885
            return [];
4886
        }
4887
4888
        $limit = intval($limit);
4889
4890
        // Getting my courses
4891
        $my_course_list = self::get_courses_list_by_user_id(api_get_user_id());
4892
4893
        $my_course_code_list = [];
4894
        foreach ($my_course_list as $course) {
4895
            $my_course_code_list[$course['real_id']] = $course['real_id'];
4896
        }
4897
4898
        if (api_is_drh()) {
4899
            $courses = self::get_courses_followed_by_drh(api_get_user_id());
4900
            foreach ($courses as $course) {
4901
                $my_course_code_list[$course['real_id']] = $course['real_id'];
4902
            }
4903
        }
4904
4905
        $table_course_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
4906
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
4907
        $table_course_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
4908
4909
        //$table_course_access table uses the now() and interval ...
4910
        $now = api_get_utc_datetime();
4911
        $sql = "SELECT COUNT(course_access_id) course_count, a.c_id, visibility
4912
                FROM $table_course c
4913
                INNER JOIN $table_course_access a
4914
                ON (c.id = a.c_id)
4915
                INNER JOIN $table_course_url u
4916
                ON u.c_id = c.id
4917
                WHERE
4918
                    u.access_url_id = ".api_get_current_access_url_id()." AND
4919
                    login_course_date <= '$now' AND
4920
                    login_course_date > DATE_SUB('$now', INTERVAL $days DAY) AND
4921
                    visibility <> '".COURSE_VISIBILITY_CLOSED."' AND visibility <> '".COURSE_VISIBILITY_HIDDEN."'
4922
                GROUP BY a.c_id
4923
                ORDER BY course_count DESC
4924
                LIMIT $limit
4925
            ";
4926
4927
        $result = Database::query($sql);
4928
        $courses = [];
4929
4930
        if (Database::num_rows($result)) {
4931
            $courses = Database::store_result($result, 'ASSOC');
4932
            $courses = self::processHotCourseItem($courses, $my_course_code_list);
4933
        }
4934
4935
        return $courses;
4936
    }
4937
4938
    /**
4939
     * @param array $courses
4940
     * @param array $my_course_code_list
4941
     * @return mixed
4942
     */
4943
    public static function processHotCourseItem($courses, $my_course_code_list = [])
4944
    {
4945
        $hotCourses = [];
4946
        $ajax_url = api_get_path(WEB_AJAX_PATH).'course.ajax.php?a=add_course_vote';
4947
        $stok = Security::get_existing_token();
4948
        $user_id = api_get_user_id();
4949
4950
        foreach ($courses as $courseId) {
4951
            $course_info = api_get_course_info_by_id($courseId['c_id']);
4952
            $courseCode = $course_info['code'];
4953
            $categoryCode = !empty($course_info['categoryCode']) ? $course_info['categoryCode'] : "";
4954
            $my_course = $course_info;
4955
            $my_course['go_to_course_button'] = '';
4956
            $my_course['register_button'] = '';
4957
4958
            $access_link = self::get_access_link_by_user(
4959
                api_get_user_id(),
4960
                $course_info,
4961
                $my_course_code_list
4962
            );
4963
4964
            $userRegisteredInCourse = self::is_user_subscribed_in_course($user_id, $course_info['code']);
4965
            $userRegisteredInCourseAsTeacher = self::is_course_teacher($user_id, $course_info['code']);
4966
            $userRegistered = $userRegisteredInCourse && $userRegisteredInCourseAsTeacher;
4967
            $my_course['is_registered'] = $userRegistered;
4968
            $my_course['title_cut'] = cut($course_info['title'], 45);
4969
4970
4971
            //Course visibility
4972
            if ($access_link && in_array('register', $access_link)) {
4973
                $my_course['register_button'] = Display::url(
4974
                    get_lang('Subscribe').' '.
4975
                    Display::returnFontAwesomeIcon('sign-in'),
4976
                    api_get_path(WEB_COURSE_PATH).$course_info['path'].
4977
                     '/index.php?action=subscribe&sec_token='.$stok,
4978
                    [
4979
                        'class' => 'btn btn-success btn-sm',
4980
                        'title' => get_lang('Subscribe'),
4981
                        'aria-label' => get_lang('Subscribe')
4982
                    ]
4983
                );
4984
            }
4985
4986
            if ($access_link && in_array('enter', $access_link) ||
4987
                $course_info['visibility'] == COURSE_VISIBILITY_OPEN_WORLD
4988
            ) {
4989
                $my_course['go_to_course_button'] = Display::url(
4990
                    get_lang('GoToCourse').' '.
4991
                    Display::returnFontAwesomeIcon('share'),
4992
                    api_get_path(WEB_COURSE_PATH).$course_info['path'].'/index.php',
4993
                    [
4994
                        'class' => 'btn btn-default btn-sm',
4995
                        'title' => get_lang('GoToCourse'),
4996
                        'aria-label' => get_lang('GoToCourse')
4997
                    ]
4998
                );
4999
            }
5000
5001
            if ($access_link && in_array('unsubscribe', $access_link)) {
5002
                $my_course['unsubscribe_button'] = Display::url(
5003
                    get_lang('Unreg').' '.
5004
                    Display::returnFontAwesomeIcon('sign-out'),
5005
                    api_get_path(WEB_CODE_PATH).'auth/courses.php?action=unsubscribe&unsubscribe='.$courseCode
5006
                    . '&sec_token='.$stok.'&category_code='.$categoryCode,
5007
                    [
5008
                        'class' => 'btn btn-danger btn-sm',
5009
                        'title' => get_lang('Unreg'),
5010
                        'aria-label' => get_lang('Unreg')
5011
                    ]
5012
                );
5013
            }
5014
5015
            // start buycourse validation
5016
            // display the course price and buy button if the buycourses plugin is enabled and this course is configured
5017
            $plugin = BuyCoursesPlugin::create();
5018
            $isThisCourseInSale = $plugin->buyCoursesForGridCatalogValidator(
5019
                $course_info['real_id'],
5020
                BuyCoursesPlugin::PRODUCT_TYPE_COURSE
5021
            );
5022
            if ($isThisCourseInSale) {
5023
                // set the price label
5024
                $my_course['price'] = $isThisCourseInSale['html'];
5025
                // set the Buy button instead register.
5026
                if ($isThisCourseInSale['verificator'] && !empty($my_course['register_button'])) {
5027
                    $my_course['register_button'] = $plugin->returnBuyCourseButton(
5028
                        $course_info['real_id'],
5029
                        BuyCoursesPlugin::PRODUCT_TYPE_COURSE
5030
                    );
5031
                }
5032
            }
5033
            // end buycourse validation
5034
5035
            // Description
5036
            $my_course['description_button'] = self::returnDescriptionButton($course_info);
5037
            $my_course['teachers'] = self::getTeachersFromCourse($course_info['real_id'], true);
5038
            $point_info = self::get_course_ranking($course_info['real_id'], 0);
5039
            $my_course['rating_html'] = '';
5040
            if (api_get_configuration_value('hide_course_rating') === false) {
5041
                $my_course['rating_html'] = Display::return_rating_system(
5042
                    'star_'.$course_info['real_id'],
5043
                    $ajax_url.'&course_id='.$course_info['real_id'],
5044
                    $point_info
5045
                );
5046
            }
5047
            $hotCourses[] = $my_course;
5048
        }
5049
        return $hotCourses;
5050
    }
5051
5052
    /**
5053
     * @param int $limit
5054
     * @return array
5055
     */
5056
    public static function return_most_accessed_courses($limit = 5)
5057
    {
5058
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
5059
        $params['url_id'] = api_get_current_access_url_id();
0 ignored issues
show
Comprehensibility Best Practice introduced by
$params was never initialized. Although not strictly required by PHP, it is generally a good practice to add $params = array(); before regardless.
Loading history...
5060
5061
        $result = Database::select(
5062
            'c_id, accesses, total_score, users',
5063
            $table,
5064
            ['where' => ['url_id = ?' => $params], 'order' => 'accesses DESC', 'limit' => $limit],
5065
            'all',
5066
            true
5067
        );
5068
5069
        return $result;
5070
    }
5071
5072
    /**
5073
     * Get courses count
5074
     * @param int $access_url_id Access URL ID (optional)
5075
     * @param int $visibility
5076
     *
5077
     * @return int Number of courses
5078
     */
5079
    public static function count_courses($access_url_id = null, $visibility = null)
5080
    {
5081
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
5082
        $table_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
5083
        $sql = "SELECT count(c.id) FROM $table_course c";
5084
        if (!empty($access_url_id) && $access_url_id == intval($access_url_id)) {
5085
            $sql .= ", $table_course_rel_access_url u
5086
                    WHERE c.id = u.c_id AND u.access_url_id = $access_url_id";
5087
            if (!empty($visibility)) {
5088
                $visibility = intval($visibility);
5089
                $sql .= " AND visibility = $visibility ";
5090
            }
5091
        } else {
5092
            if (!empty($visibility)) {
5093
                $visibility = intval($visibility);
5094
                $sql .= " WHERE visibility = $visibility ";
5095
            }
5096
        }
5097
5098
        $res = Database::query($sql);
5099
        $row = Database::fetch_row($res);
5100
5101
        return $row[0];
5102
    }
5103
5104
    /**
5105
     * Get active courses count.
5106
     * Active = all courses except the ones with hidden visibility.
5107
     *
5108
     * @param int $urlId Access URL ID (optional)
5109
     * @return int Number of courses
5110
     */
5111
    public static function countActiveCourses($urlId = null)
5112
    {
5113
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
5114
        $table_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
5115
        $sql = "SELECT count(id) FROM $table_course c";
5116
        if (!empty($urlId) && $urlId == intval($urlId)) {
5117
            $sql .= ", $table_course_rel_access_url u
5118
                    WHERE
5119
                        c.id = u.c_id AND
5120
                        u.access_url_id = $urlId AND
5121
                        visibility <> ".COURSE_VISIBILITY_HIDDEN;
5122
        } else {
5123
            $sql .= " WHERE visibility <> ".COURSE_VISIBILITY_HIDDEN;
5124
        }
5125
        $res = Database::query($sql);
5126
        $row = Database::fetch_row($res);
5127
        return $row[0];
5128
    }
5129
5130
    /**
5131
     * Returns the SQL conditions to filter course only visible by the user in the catalogue
5132
     *
5133
     * @param string $courseTableAlias Alias of the course table
5134
     * @param bool $hideClosed Whether to hide closed and hidden courses
5135
     * @return string SQL conditions
5136
     */
5137
    public static function getCourseVisibilitySQLCondition(
5138
        $courseTableAlias,
5139
        $hideClosed = false
5140
    ) {
5141
        $visibilityCondition = '';
5142
        $hidePrivate = api_get_setting('course_catalog_hide_private');
5143
        if ($hidePrivate === 'true') {
5144
            $visibilityCondition .= ' AND '.$courseTableAlias.'.visibility <> '.COURSE_VISIBILITY_REGISTERED;
5145
        }
5146
        if ($hideClosed) {
5147
            $visibilityCondition .= ' AND '.$courseTableAlias.'.visibility NOT IN ('.COURSE_VISIBILITY_CLOSED.','.COURSE_VISIBILITY_HIDDEN.')';
5148
        }
5149
5150
        // Check if course have users allowed to see it in the catalogue, then show only if current user is allowed to see it
5151
        $currentUserId = api_get_user_id();
5152
        $restrictedCourses = self::getCatalogueCourseList(true);
5153
        $allowedCoursesToCurrentUser = self::getCatalogueCourseList(true, $currentUserId);
5154
        if (!empty($restrictedCourses)) {
5155
            $visibilityCondition .= ' AND ('.$courseTableAlias.'.code NOT IN ("'.implode('","', $restrictedCourses).'")';
5156
            $visibilityCondition .= ' OR '.$courseTableAlias.'.code IN ("'.implode('","', $allowedCoursesToCurrentUser).'"))';
5157
        }
5158
5159
        // Check if course have users denied to see it in the catalogue, then show only if current user is not denied to see it
5160
        $restrictedCourses = self::getCatalogueCourseList(false);
5161
        $notAllowedCoursesToCurrentUser = self::getCatalogueCourseList(false, $currentUserId);
5162
        if (!empty($restrictedCourses)) {
5163
            $visibilityCondition .= ' AND ('.$courseTableAlias.'.code NOT IN ("'.implode('","', $restrictedCourses).'")';
5164
            $visibilityCondition .= ' OR '.$courseTableAlias.'.code NOT IN ("'.implode('","', $notAllowedCoursesToCurrentUser).'"))';
5165
        }
5166
5167
        return $visibilityCondition;
5168
    }
5169
5170
    /**
5171
     * Get available le courses count
5172
     * @param int $accessUrlId (optional)
5173
     * @return int Number of courses
5174
     */
5175
    public static function countAvailableCourses($accessUrlId = 1)
5176
    {
5177
        $tableCourse = Database::get_main_table(TABLE_MAIN_COURSE);
5178
        $tableCourseRelAccessUrl = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
5179
        $specialCourseList = self::get_special_course_list();
5180
5181
        $withoutSpecialCourses = '';
5182
        if (!empty($specialCourseList)) {
5183
            $withoutSpecialCourses = ' AND c.id NOT IN ("'.implode('","', $specialCourseList).'")';
5184
        }
5185
5186
        $visibilityCondition = self::getCourseVisibilitySQLCondition('c', true);
5187
5188
        $accessUrlId = (int) $accessUrlId;
5189
        if (empty($accessUrlId)) {
5190
            $accessUrlId = 1;
5191
        }
5192
5193
        $sql = "SELECT count(c.id) 
5194
                FROM $tableCourse c 
5195
                INNER JOIN $tableCourseRelAccessUrl u
5196
                ON (c.id = u.c_id)
5197
                WHERE
5198
                    u.access_url_id = $accessUrlId AND
5199
                    c.visibility != 0 AND
5200
                    c.visibility != 4
5201
                    $withoutSpecialCourses
5202
                    $visibilityCondition
5203
                ";
5204
5205
        $res = Database::query($sql);
5206
        $row = Database::fetch_row($res);
5207
5208
        return $row[0];
5209
    }
5210
5211
    /**
5212
     * Return a link to go to the course, validating the visibility of the
5213
     * course and the user status
5214
     * @param int $uid User ID
5215
     * @param array Course details array
5216
     * @param array  List of courses to which the user is subscribed (if not provided, will be generated)
5217
     *
5218
     * @return mixed 'enter' for a link to go to the course or 'register' for a link to subscribe, or false if no access
5219
     */
5220
    public static function get_access_link_by_user($uid, $course, $user_courses = [])
5221
    {
5222
        if (empty($uid) || empty($course)) {
5223
            return false;
5224
        }
5225
5226
        if (empty($user_courses)) {
5227
            // get the array of courses to which the user is subscribed
5228
            $user_courses = self::get_courses_list_by_user_id($uid);
5229
            foreach ($user_courses as $k => $v) {
5230
                $user_courses[$k] = $v['real_id'];
5231
            }
5232
        }
5233
5234
        if (!isset($course['real_id']) && empty($course['real_id'])) {
5235
            $course = api_get_course_info($course['code']);
5236
        }
5237
5238
        if ($course['visibility'] == COURSE_VISIBILITY_HIDDEN) {
5239
            return [];
5240
        }
5241
5242
        $is_admin = api_is_platform_admin_by_id($uid);
5243
        $options = [];
5244
        // Register button
5245
        if (!api_is_anonymous($uid) &&
5246
            (
5247
            ($course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD || $course['visibility'] == COURSE_VISIBILITY_OPEN_PLATFORM)
5248
                //$course['visibility'] == COURSE_VISIBILITY_REGISTERED && $course['subscribe'] == SUBSCRIBE_ALLOWED
5249
            ) &&
5250
            $course['subscribe'] == SUBSCRIBE_ALLOWED &&
5251
            (!in_array($course['real_id'], $user_courses) || empty($user_courses))
5252
        ) {
5253
            $options[] = 'register';
5254
        }
5255
5256
        // Go To Course button (only if admin, if course public or if student already subscribed)
5257
        if ($is_admin ||
5258
            $course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD && empty($course['registration_code']) ||
5259
            (api_user_is_login($uid) && $course['visibility'] == COURSE_VISIBILITY_OPEN_PLATFORM && empty($course['registration_code'])) ||
5260
            (in_array($course['real_id'], $user_courses) && $course['visibility'] != COURSE_VISIBILITY_CLOSED)
5261
        ) {
5262
            $options[] = 'enter';
5263
        }
5264
5265
        if ($is_admin ||
5266
            $course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD && empty($course['registration_code']) ||
5267
            (api_user_is_login($uid) && $course['visibility'] == COURSE_VISIBILITY_OPEN_PLATFORM && empty($course['registration_code'])) ||
5268
            (in_array($course['real_id'], $user_courses) && $course['visibility'] != COURSE_VISIBILITY_CLOSED)
5269
        ) {
5270
            $options[] = 'enter';
5271
        }
5272
5273
        if ($course['visibility'] != COURSE_VISIBILITY_HIDDEN &&
5274
            empty($course['registration_code']) &&
5275
            $course['unsubscribe'] == UNSUBSCRIBE_ALLOWED &&
5276
            api_user_is_login($uid) &&
5277
            in_array($course['real_id'], $user_courses)
5278
        ) {
5279
            $options[] = 'unsubscribe';
5280
        }
5281
5282
        return $options;
5283
    }
5284
5285
    /**
5286
     * @param array $courseInfo
5287
     * @param array $teachers
5288
     * @param bool $deleteTeachersNotInList
5289
     * @param bool $editTeacherInSessions
5290
     * @param bool $deleteSessionTeacherNotInList
5291
     * @param array $teacherBackup
5292
     * @param Monolog\Logger $logger
5293
     *
5294
     * @return false|null
5295
     */
5296
    public static function updateTeachers(
5297
        $courseInfo,
5298
        $teachers,
5299
        $deleteTeachersNotInList = true,
5300
        $editTeacherInSessions = false,
5301
        $deleteSessionTeacherNotInList = false,
5302
        $teacherBackup = [],
5303
        $logger = null
5304
    ) {
5305
        if (!is_array($teachers)) {
5306
            $teachers = [$teachers];
5307
        }
5308
5309
        if (empty($courseInfo) || !isset($courseInfo['real_id'])) {
5310
            return false;
5311
        }
5312
5313
        $teachers = array_filter($teachers);
5314
        $courseId = $courseInfo['real_id'];
5315
        $course_code = $courseInfo['code'];
5316
5317
        $course_user_table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5318
        $alreadyAddedTeachers = self::get_teacher_list_from_course_code($course_code);
5319
5320
        if ($deleteTeachersNotInList) {
5321
            // Delete only teacher relations that doesn't match the selected teachers
5322
            $cond = null;
5323
            if (count($teachers) > 0) {
5324
                foreach ($teachers as $key) {
5325
                    $key = Database::escape_string($key);
5326
                    $cond .= " AND user_id <> '".$key."'";
5327
                }
5328
            }
5329
5330
            // Recover user categories
5331
            $sql = 'SELECT * FROM '.$course_user_table.'
5332
                    WHERE c_id ="' . $courseId.'" AND status="1" AND relation_type = 0 '.$cond;
5333
            $result = Database::query($sql);
5334
            if (Database::num_rows($result)) {
5335
                $teachersToDelete = Database::store_result($result, 'ASSOC');
5336
                foreach ($teachersToDelete as $data) {
5337
                    $userId = $data['user_id'];
5338
                    $teacherBackup[$userId][$course_code] = $data;
5339
                }
5340
            }
5341
5342
            $sql = 'DELETE FROM '.$course_user_table.'
5343
                    WHERE c_id ="' . $courseId.'" AND status="1" AND relation_type = 0 '.$cond;
5344
5345
            Database::query($sql);
5346
        }
5347
5348
        if (count($teachers) > 0) {
5349
            foreach ($teachers as $userId) {
5350
                $userId = intval($userId);
5351
                // We check if the teacher is already subscribed in this course
5352
                $sql = 'SELECT 1 FROM '.$course_user_table.'
5353
                        WHERE user_id = "' . $userId.'" AND c_id = "'.$courseId.'" ';
5354
                $result = Database::query($sql);
5355
                if (Database::num_rows($result)) {
5356
                    $sql = 'UPDATE '.$course_user_table.' 
5357
                            SET status = "1"
5358
                            WHERE c_id = "' . $courseId.'" AND user_id = "'.$userId.'"  ';
5359
                } else {
5360
                    $userCourseCategory = '0';
5361
                    if (isset($teacherBackup[$userId]) &&
5362
                        isset($teacherBackup[$userId][$course_code])
5363
                    ) {
5364
                        $courseUserData = $teacherBackup[$userId][$course_code];
5365
                        $userCourseCategory = $courseUserData['user_course_cat'];
5366
                        if ($logger) {
5367
                            $logger->addInfo("Recovering user_course_cat: $userCourseCategory");
5368
                        }
5369
                    }
5370
5371
                    $sql = "INSERT INTO $course_user_table SET
5372
                            c_id = $courseId,
5373
                            user_id = $userId,
5374
                            status = '1',
5375
                            is_tutor = '0',
5376
                            sort = '0',
5377
                            relation_type = '0',
5378
                            user_course_cat = '$userCourseCategory'
5379
                    ";
5380
                }
5381
                Database::query($sql);
5382
            }
5383
        }
5384
5385
        if ($editTeacherInSessions) {
5386
            $sessions = SessionManager::get_session_by_course($courseId);
5387
            if (!empty($sessions)) {
5388
                if ($logger) {
5389
                    $logger->addInfo("Edit teachers in sessions");
5390
                }
5391
                foreach ($sessions as $session) {
5392
                    $sessionId = $session['id'];
5393
                    // Remove old and add new
5394
                    if ($deleteSessionTeacherNotInList) {
5395
                        foreach ($teachers as $userId) {
5396
                            if ($logger) {
5397
                                $logger->addInfo("Set coach #$userId in session #$sessionId of course #$courseId ");
5398
                            }
5399
                            SessionManager::set_coach_to_course_session(
5400
                                $userId,
5401
                                $sessionId,
5402
                                $courseId
5403
                            );
5404
                        }
5405
5406
                        $teachersToDelete = [];
5407
                        if (!empty($alreadyAddedTeachers)) {
5408
                            $teachersToDelete = array_diff(array_keys($alreadyAddedTeachers), $teachers);
5409
                        }
5410
5411
                        if (!empty($teachersToDelete)) {
5412
                            foreach ($teachersToDelete as $userId) {
5413
                                if ($logger) {
5414
                                    $logger->addInfo("Delete coach #$userId in session #$sessionId of course #$courseId ");
5415
                                }
5416
                                SessionManager::set_coach_to_course_session(
5417
                                    $userId,
5418
                                    $sessionId,
5419
                                    $courseId,
5420
                                    true
5421
                                );
5422
                            }
5423
                        }
5424
                    } else {
5425
                        // Add new teachers only
5426
                        foreach ($teachers as $userId) {
5427
                            if ($logger) {
5428
                                $logger->addInfo("Add coach #$userId in session #$sessionId of course #$courseId ");
5429
                            }
5430
                            SessionManager::set_coach_to_course_session(
5431
                                $userId,
5432
                                $sessionId,
5433
                                $courseId
5434
                            );
5435
                        }
5436
                    }
5437
                }
5438
            }
5439
        }
5440
    }
5441
5442
    /**
5443
     * Course available settings variables see c_course_setting table
5444
     * @param AppPlugin $appPlugin
5445
     * @return array
5446
     */
5447
    public static function getCourseSettingVariables(AppPlugin $appPlugin)
5448
    {
5449
        $pluginCourseSettings = $appPlugin->getAllPluginCourseSettings();
5450
        $courseSettings = [
5451
            // Get allow_learning_path_theme from table
5452
            'allow_learning_path_theme',
5453
            // Get allow_open_chat_window from table
5454
            'allow_open_chat_window',
5455
            'allow_public_certificates',
5456
            // Get allow_user_edit_agenda from table
5457
            'allow_user_edit_agenda',
5458
            // Get allow_user_edit_announcement from table
5459
            'allow_user_edit_announcement',
5460
            // Get allow_user_image_forum from table
5461
            'allow_user_image_forum',
5462
            //Get allow show user list
5463
            'allow_user_view_user_list',
5464
            // Get course_theme from table
5465
            'course_theme',
5466
            //Get allow show user list
5467
            'display_info_advance_inside_homecourse',
5468
            'documents_default_visibility',
5469
            // Get send_mail_setting (work)from table
5470
            'email_alert_manager_on_new_doc',
5471
            // Get send_mail_setting (work)from table
5472
            'email_alert_manager_on_new_quiz',
5473
            // Get send_mail_setting (dropbox) from table
5474
            'email_alert_on_new_doc_dropbox',
5475
            'email_alert_students_on_new_homework',
5476
            // Get send_mail_setting (auth)from table
5477
            'email_alert_to_teacher_on_new_user_in_course',
5478
            'enable_lp_auto_launch',
5479
            'pdf_export_watermark_text',
5480
            'show_system_folders',
5481
            'exercise_invisible_in_session',
5482
            'enable_forum_auto_launch',
5483
            'show_course_in_user_language',
5484
            'email_to_teachers_on_new_work_feedback'
5485
        ];
5486
5487
        if (!empty(ExerciseLib::getScoreModels())) {
5488
            $courseSettings[] = 'score_model_id';
5489
        }
5490
5491
        $allowLPReturnLink = api_get_setting('allow_lp_return_link');
5492
        if ($allowLPReturnLink === 'true') {
5493
            $courseSettings[] = 'lp_return_link';
5494
        }
5495
5496
        if (!empty($pluginCourseSettings)) {
5497
            $courseSettings = array_merge(
5498
                $courseSettings,
5499
                $pluginCourseSettings
5500
            );
5501
        }
5502
5503
        return $courseSettings;
5504
    }
5505
5506
    /**
5507
     * @param AppPlugin $appPlugin
5508
     * @param string $variable
5509
     * @param string|array $value
5510
     * @param int $courseId
5511
     * @return bool
5512
     */
5513
    public static function saveCourseConfigurationSetting(AppPlugin $appPlugin, $variable, $value, $courseId)
5514
    {
5515
        $settingList = self::getCourseSettingVariables($appPlugin);
5516
5517
        if (!in_array($variable, $settingList)) {
5518
            return false;
5519
        }
5520
5521
        $courseSettingTable = Database::get_course_table(TABLE_COURSE_SETTING);
5522
5523
        if (is_array($value)) {
5524
            $value = implode(',', $value);
5525
        }
5526
5527
        if (self::hasCourseSetting($variable, $courseId)) {
5528
            // Update
5529
            Database::update(
5530
                $courseSettingTable,
5531
                ['value' => $value],
5532
                ['variable = ? AND c_id = ?' => [$variable, $courseId]]
5533
            );
5534
        } else {
5535
            // Create
5536
            Database::insert(
5537
                $courseSettingTable,
5538
                [
5539
                    'title' => $variable,
5540
                    'value' => $value,
5541
                    'c_id' => $courseId,
5542
                    'variable' => $variable,
5543
                ]
5544
            );
5545
        }
5546
        return true;
5547
    }
5548
5549
    /**
5550
     * Check if course setting exists
5551
     * @param string $variable
5552
     * @param int $courseId
5553
     * @return bool
5554
     */
5555
    public static function hasCourseSetting($variable, $courseId)
5556
    {
5557
        $courseSetting = Database::get_course_table(TABLE_COURSE_SETTING);
5558
        $courseId = intval($courseId);
5559
        $variable = Database::escape_string($variable);
5560
        $sql = "SELECT variable FROM $courseSetting
5561
                WHERE c_id = $courseId AND variable = '$variable'";
5562
        $result = Database::query($sql);
5563
5564
        return Database::num_rows($result) > 0;
5565
    }
5566
5567
    /**
5568
     * Get information from the track_e_course_access table
5569
     * @param int $sessionId
5570
     * @param int $userId
5571
     * @param int $limit
5572
     * @return array
5573
     */
5574
    public static function getCourseAccessPerSessionAndUser($sessionId, $userId, $limit = 0)
5575
    {
5576
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
5577
5578
        $sessionId = intval($sessionId);
5579
        $userId = intval($userId);
5580
5581
        $sql = "SELECT * FROM $table
5582
                WHERE session_id = $sessionId AND user_id = $userId";
5583
5584
        if (!empty($limit)) {
5585
            $limit = intval($limit);
5586
            $sql .= " LIMIT $limit";
5587
        }
5588
        $result = Database::query($sql);
5589
5590
        return Database::store_result($result);
5591
    }
5592
5593
    /**
5594
     * Get information from the track_e_course_access table
5595
     * @param int $courseId
5596
     * @param int $sessionId
5597
     * @param string $startDate
5598
     * @param string $endDate
5599
     * @return array
5600
     */
5601
    public static function getCourseAccessPerCourseAndSession(
5602
        $courseId,
5603
        $sessionId,
5604
        $startDate,
5605
        $endDate
5606
    ) {
5607
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
5608
        $courseId = intval($courseId);
5609
        $sessionId = intval($sessionId);
5610
        $startDate = Database::escape_string($startDate);
5611
        $endDate = Database::escape_string($endDate);
5612
5613
        $sql = "SELECT * FROM $table
5614
                WHERE
5615
                    c_id = $courseId AND
5616
                    session_id = $sessionId AND
5617
                    login_course_date BETWEEN '$startDate' AND '$endDate'
5618
                ";
5619
5620
        $result = Database::query($sql);
5621
5622
        return Database::store_result($result);
5623
    }
5624
5625
    /**
5626
     * Get login information from the track_e_course_access table, for any
5627
     * course in the given session
5628
     * @param int $sessionId
5629
     * @param int $userId
5630
     * @return array
5631
     */
5632
    public static function getFirstCourseAccessPerSessionAndUser($sessionId, $userId)
5633
    {
5634
        $sessionId = intval($sessionId);
5635
        $userId = intval($userId);
5636
5637
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
5638
        $sql = "SELECT * FROM $table
5639
                WHERE session_id = $sessionId AND user_id = $userId
5640
                ORDER BY login_course_date ASC
5641
                LIMIT 1";
5642
5643
        $result = Database::query($sql);
5644
        $courseAccess = [];
5645
        if (Database::num_rows($result)) {
5646
            $courseAccess = Database::fetch_array($result, 'ASSOC');
5647
        }
5648
        return $courseAccess;
5649
    }
5650
5651
    /**
5652
     * @param int $courseId
5653
     * @param int $sessionId
5654
     * @param bool $getAllSessions
5655
     * @return mixed
5656
     */
5657
    public static function getCountForum(
5658
        $courseId,
5659
        $sessionId = 0,
5660
        $getAllSessions = false
5661
    ) {
5662
        $forum = Database::get_course_table(TABLE_FORUM);
5663
        if ($getAllSessions) {
5664
            $sql = "SELECT count(*) as count
5665
                    FROM $forum f
5666
                    WHERE f.c_id = %s";
5667
        } else {
5668
            $sql = "SELECT count(*) as count
5669
                    FROM $forum f
5670
                    WHERE f.c_id = %s and f.session_id = %s";
5671
        }
5672
5673
        $sql = sprintf($sql, intval($courseId), intval($sessionId));
5674
        $result = Database::query($sql);
5675
        $row = Database::fetch_array($result);
5676
5677
        return $row['count'];
5678
    }
5679
5680
    /**
5681
     * @param int $userId
5682
     * @param int $courseId
5683
     * @param int $sessionId
5684
     * @return mixed
5685
     */
5686
    public static function getCountPostInForumPerUser(
5687
        $userId,
5688
        $courseId,
5689
        $sessionId = 0
5690
    ) {
5691
        $forum = Database::get_course_table(TABLE_FORUM);
5692
        $forum_post = Database::get_course_table(TABLE_FORUM_POST);
5693
5694
        $sql = "SELECT count(distinct post_id) as count
5695
                FROM $forum_post p
5696
                INNER JOIN $forum f
5697
                ON f.forum_id = p.forum_id AND f.c_id = p.c_id
5698
                WHERE p.poster_id = %s and f.session_id = %s and p.c_id = %s";
5699
5700
        $sql = sprintf(
5701
            $sql,
5702
            intval($userId),
5703
            intval($sessionId),
5704
            intval($courseId)
5705
        );
5706
5707
        $result = Database::query($sql);
5708
        $row = Database::fetch_array($result);
5709
        return $row['count'];
5710
    }
5711
5712
    /**
5713
     * @param int $userId
5714
     * @param int $courseId
5715
     * @param int $sessionId
5716
     * @return mixed
5717
     */
5718
    public static function getCountForumPerUser(
5719
        $userId,
5720
        $courseId,
5721
        $sessionId = 0
5722
    ) {
5723
        $forum = Database::get_course_table(TABLE_FORUM);
5724
        $forum_post = Database::get_course_table(TABLE_FORUM_POST);
5725
5726
        $sql = "SELECT count(distinct f.forum_id) as count
5727
                FROM $forum_post p
5728
                INNER JOIN $forum f
5729
                ON f.forum_id = p.forum_id AND f.c_id = p.c_id
5730
                WHERE p.poster_id = %s and f.session_id = %s and p.c_id = %s";
5731
5732
        $sql = sprintf(
5733
            $sql,
5734
            intval($userId),
5735
            intval($sessionId),
5736
            intval($courseId)
5737
        );
5738
5739
        $result = Database::query($sql);
5740
        $row = Database::fetch_array($result);
5741
        return $row['count'];
5742
    }
5743
5744
    /**
5745
     * Returns the course name from a given code
5746
     * @param string $code
5747
     * @return string
5748
     */
5749
    public static function getCourseNameFromCode($code)
5750
    {
5751
        $tbl_main_categories = Database::get_main_table(TABLE_MAIN_COURSE);
5752
        $sql = 'SELECT title
5753
                FROM ' . $tbl_main_categories.'
5754
                WHERE code = "' . Database::escape_string($code).'"';
5755
        $result = Database::query($sql);
5756
        if ($col = Database::fetch_array($result)) {
5757
            return $col['title'];
5758
        }
5759
    }
5760
5761
    /**
5762
     * Generates a course code from a course title
5763
     * @todo Such a function might be useful in other places too. It might be moved in the CourseManager class.
5764
     * @todo the function might be upgraded for avoiding code duplications (currently,
5765
     * it might suggest a code that is already in use)
5766
     * @param string $title A course title
5767
     * @return string A proposed course code
5768
     * +
5769
     * @assert (null,null) === false
5770
     * @assert ('ABC_DEF', null) === 'ABCDEF'
5771
     * @assert ('ABC09*^[%A', null) === 'ABC09A'
5772
     */
5773
    public static function generate_course_code($title)
5774
    {
5775
        return substr(
5776
            preg_replace('/[^A-Z0-9]/', '', strtoupper(api_replace_dangerous_char($title))),
5777
            0,
5778
            self::MAX_COURSE_LENGTH_CODE
5779
        );
5780
    }
5781
5782
    /**
5783
     * @param $courseId
5784
     * @return array
5785
     */
5786
    public static function getCourseSettings($courseId)
5787
    {
5788
        $settingTable = Database::get_course_table(TABLE_COURSE_SETTING);
5789
        $courseId = intval($courseId);
5790
        $sql = "SELECT * FROM $settingTable WHERE c_id = $courseId";
5791
        $result = Database::query($sql);
5792
        $settings = [];
5793
        if (Database::num_rows($result)) {
5794
            while ($row = Database::fetch_array($result, 'ASSOC')) {
5795
                $settings[$row['variable']] = $row;
5796
            }
5797
        }
5798
        return $settings;
5799
    }
5800
5801
    /**
5802
     * this function gets all the users of the course,
5803
     * including users from linked courses
5804
     * @param $filterByActive
5805
     *
5806
     * @return array
5807
     */
5808
    public static function getCourseUsers($filterByActive = null)
5809
    {
5810
        // This would return only the users from real courses:
5811
        $userList = self::get_user_list_from_course_code(
5812
            api_get_course_id(),
5813
            api_get_session_id(),
5814
            null,
5815
            null,
5816
            null,
5817
            null,
5818
            false,
5819
            false,
5820
            [],
5821
            [],
5822
            [],
5823
            $filterByActive
5824
        );
5825
5826
        return $userList;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $userList also could return the type integer which is incompatible with the documented return type array.
Loading history...
5827
    }
5828
5829
    /**
5830
     * this function gets all the groups of the course,
5831
     * not including linked courses
5832
     */
5833
    public static function getCourseGroups()
5834
    {
5835
        $session_id = api_get_session_id();
5836
        if ($session_id != 0) {
5837
            $new_group_list = self::get_group_list_of_course(
5838
                api_get_course_id(),
5839
                $session_id,
5840
                1
5841
            );
5842
        } else {
5843
            $new_group_list = self::get_group_list_of_course(
5844
                api_get_course_id(),
5845
                0,
5846
                1
5847
            );
5848
        }
5849
5850
        return $new_group_list;
5851
    }
5852
5853
    /**
5854
     * @param FormValidator $form
5855
     * @param array $to_already_selected
5856
     *
5857
     * @return HTML_QuickForm_element
5858
     */
5859
    public static function addUserGroupMultiSelect(&$form, $to_already_selected)
5860
    {
5861
        $userList = self::getCourseUsers(true);
5862
        $group_list = self::getCourseGroups();
5863
        $array = self::buildSelectOptions(
5864
            $group_list,
5865
            $userList,
5866
            $to_already_selected
5867
        );
5868
5869
        $result = [];
5870
        foreach ($array as $content) {
5871
            $result[$content['value']] = $content['content'];
5872
        }
5873
5874
        return $form->addElement(
5875
            'advmultiselect',
5876
            'users',
5877
            get_lang('Users'),
5878
            $result,
5879
            ['select_all_checkbox' => true]
5880
        );
5881
    }
5882
5883
    /**
5884
     * This function separates the users from the groups
5885
     * users have a value USER:XXX (with XXX the groups id have a value
5886
     *  GROUP:YYY (with YYY the group id)
5887
     * @param  array $to Array of strings that define the type and id of each destination
5888
     * @return array Array of groups and users (each an array of IDs)
5889
     */
5890
    public static function separateUsersGroups($to)
5891
    {
5892
        $groupList = [];
5893
        $userList = [];
5894
5895
        foreach ($to as $to_item) {
5896
            if (!empty($to_item)) {
5897
                $parts = explode(':', $to_item);
5898
                $type = isset($parts[0]) ? $parts[0] : '';
5899
                $id = isset($parts[1]) ? $parts[1] : '';
5900
5901
                switch ($type) {
5902
                    case 'GROUP':
5903
                        $groupList[] = intval($id);
5904
                        break;
5905
                    case 'USER':
5906
                        $userList[] = intval($id);
5907
                        break;
5908
                }
5909
            }
5910
        }
5911
5912
        $send_to['groups'] = $groupList;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$send_to was never initialized. Although not strictly required by PHP, it is generally a good practice to add $send_to = array(); before regardless.
Loading history...
5913
        $send_to['users'] = $userList;
5914
5915
        return $send_to;
5916
    }
5917
5918
    /**
5919
     * Shows the form for sending a message to a specific group or user.
5920
     * @param FormValidator $form
5921
     * @param array $groupInfo
5922
     * @param array $to
5923
     *
5924
     * @return HTML_QuickForm_element
5925
     */
5926
    public static function addGroupMultiSelect($form, $groupInfo, $to = [])
5927
    {
5928
        $group_users = GroupManager::get_subscribed_users($groupInfo);
5929
        $array = self::buildSelectOptions(null, $group_users, $to);
5930
5931
        $result = [];
5932
        foreach ($array as $content) {
5933
            $result[$content['value']] = $content['content'];
5934
        }
5935
5936
        return $form->addElement('advmultiselect', 'users', get_lang('Users'), $result);
5937
    }
5938
5939
    /**
5940
     * this function shows the form for sending a message to a specific group or user.
5941
     * @param array $group_list
5942
     * @param array $userList
5943
     * @param array $to_already_selected
5944
     * @return array
5945
     */
5946
    public static function buildSelectOptions(
5947
        $group_list = [],
5948
        $userList = [],
5949
        $to_already_selected = []
5950
    ) {
5951
        if (empty($to_already_selected)) {
5952
            $to_already_selected = [];
5953
        }
5954
5955
        $result = [];
5956
        // adding the groups to the select form
5957
        if ($group_list) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $group_list 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...
5958
            foreach ($group_list as $this_group) {
5959
                if (is_array($to_already_selected)) {
5960
                    if (!in_array(
5961
                        "GROUP:".$this_group['id'],
5962
                        $to_already_selected
5963
                    )
5964
                    ) { // $to_already_selected is the array containing the groups (and users) that are already selected
5965
                        $user_label = ($this_group['userNb'] > 0) ? get_lang('Users') : get_lang('LowerCaseUser');
5966
                        $user_disabled = ($this_group['userNb'] > 0) ? "" : "disabled=disabled";
5967
                        $result[] = [
5968
                            'disabled' => $user_disabled,
5969
                            'value' => "GROUP:".$this_group['id'],
5970
                            // The space before "G" is needed in order to advmultiselect.php js puts groups first
5971
                            'content' => " G: ".$this_group['name']." - ".$this_group['userNb']." ".$user_label
5972
                        ];
5973
                    }
5974
                }
5975
            }
5976
        }
5977
5978
        // adding the individual users to the select form
5979
        if ($userList) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $userList 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...
5980
            foreach ($userList as $user) {
5981
                if (is_array($to_already_selected)) {
5982
                    if (!in_array(
5983
                        "USER:".$user['user_id'],
5984
                        $to_already_selected
5985
                    )
5986
                    ) { // $to_already_selected is the array containing the users (and groups) that are already selected
5987
5988
                        $result[] = [
5989
                            'value' => "USER:".$user['user_id'],
5990
                            'content' => api_get_person_name($user['firstname'], $user['lastname'])
5991
                        ];
5992
                    }
5993
                }
5994
            }
5995
        }
5996
5997
        return $result;
5998
    }
5999
6000
    /**
6001
     * @return array a list (array) of all courses.
6002
     */
6003
    public static function get_course_list()
6004
    {
6005
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
6006
        return Database::store_result(Database::query("SELECT *, id as real_id FROM $table"));
6007
    }
6008
6009
    /**
6010
     * Returns course code from a given gradebook category's id
6011
     * @param int  Category ID
6012
     * @return string  Course code
6013
     */
6014
    public static function get_course_by_category($category_id)
6015
    {
6016
        $category_id = intval($category_id);
6017
        $info = Database::fetch_array(
6018
            Database::query('SELECT course_code FROM '.Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY).'
6019
            WHERE id=' . $category_id),
6020
            'ASSOC'
6021
        );
6022
        return $info ? $info['course_code'] : false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $info ? $info['course_code'] : false 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...
6023
    }
6024
6025
    /**
6026
     * This function gets all the courses that are not in a session
6027
     * @param date Start date
6028
     * @param date End date
6029
     * @param   bool    $includeClosed Whether to include closed and hidden courses
6030
     * @return array Not-in-session courses
6031
     */
6032
    public static function getCoursesWithoutSession(
6033
        $startDate = null,
6034
        $endDate = null,
6035
        $includeClosed = false
6036
    ) {
6037
        $dateConditional = ($startDate && $endDate) ?
6038
            " WHERE session_id IN (SELECT id FROM ".Database::get_main_table(TABLE_MAIN_SESSION).
6039
            " WHERE access_start_date = '$startDate' AND access_end_date = '$endDate')" : null;
6040
        $visibility = ($includeClosed ? '' : 'visibility NOT IN (0, 4) AND ');
6041
6042
        $sql = "SELECT id, code, title
6043
                FROM ".Database::get_main_table(TABLE_MAIN_COURSE)."
6044
                WHERE $visibility code NOT IN (
6045
                    SELECT DISTINCT course_code 
6046
                    FROM ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE).$dateConditional."
6047
                )
6048
                ORDER BY id";
6049
6050
        $result = Database::query($sql);
6051
        $courses = [];
6052
        while ($row = Database::fetch_array($result)) {
6053
            $courses[] = $row;
6054
        }
6055
        return $courses;
6056
    }
6057
6058
    /**
6059
     * Get list of courses based on users of a group for a group admin
6060
     * @param int $userId The user id
6061
     * @return array
6062
     */
6063
    public static function getCoursesFollowedByGroupAdmin($userId)
6064
    {
6065
        $coursesList = [];
6066
        $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
6067
        $courseUserTable = Database::get_main_table(TABLE_MAIN_COURSE_USER);
6068
        $userGroup = new UserGroup();
6069
        $userIdList = $userGroup->getGroupUsersByUser($userId);
6070
6071
        if (empty($userIdList)) {
6072
            return [];
6073
        }
6074
6075
        $sql = "SELECT DISTINCT(c.id), c.title
6076
                FROM $courseTable c
6077
                INNER JOIN $courseUserTable cru ON c.id = cru.c_id
6078
                WHERE (
6079
                    cru.user_id IN (".implode(', ', $userIdList).")
6080
                    AND cru.relation_type = 0
6081
                )";
6082
6083
        if (api_is_multiple_url_enabled()) {
6084
            $courseAccessUrlTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
6085
            $accessUrlId = api_get_current_access_url_id();
6086
6087
            if ($accessUrlId != -1) {
6088
                $sql = "SELECT DISTINCT(c.id), c.title
6089
                        FROM $courseTable c
6090
                        INNER JOIN $courseUserTable cru ON c.id = cru.c_id
6091
                        INNER JOIN $courseAccessUrlTable crau ON c.id = crau.c_id
6092
                        WHERE crau.access_url_id = $accessUrlId
6093
                            AND (
6094
                            cru.id_user IN (".implode(', ', $userIdList).") AND
6095
                            cru.relation_type = 0
6096
                        )";
6097
            }
6098
        }
6099
6100
        $result = Database::query($sql);
6101
        while ($row = Database::fetch_assoc($result)) {
6102
            $coursesList[] = $row;
6103
        }
6104
6105
        return $coursesList;
6106
    }
6107
6108
    /**
6109
     * Direct course link see #5299
6110
     *
6111
     * You can send to your students an URL like this
6112
     * http://chamilodev.beeznest.com/main/auth/inscription.php?c=ABC&e=3
6113
     * Where "c" is the course code and "e" is the exercise Id, after a successful
6114
     * registration the user will be sent to the course or exercise
6115
     *
6116
     */
6117
    public static function redirectToCourse($form_data)
6118
    {
6119
        $course_code_redirect = Session::read('course_redirect');
6120
        $_user = api_get_user_info();
6121
        $user_id = api_get_user_id();
6122
6123
        if (!empty($course_code_redirect)) {
6124
            $course_info = api_get_course_info($course_code_redirect);
6125
            if (!empty($course_info)) {
6126
                if (in_array(
6127
                    $course_info['visibility'],
6128
                    [COURSE_VISIBILITY_OPEN_PLATFORM, COURSE_VISIBILITY_OPEN_WORLD]
6129
                )
6130
                ) {
6131
                    if (self::is_user_subscribed_in_course($user_id, $course_info['code'])) {
6132
                        $form_data['action'] = $course_info['course_public_url'];
6133
                        $form_data['message'] = sprintf(get_lang('YouHaveBeenRegisteredToCourseX'), $course_info['title']);
6134
                        $form_data['button'] = Display::button(
6135
                            'next',
6136
                            get_lang('GoToCourse', null, $_user['language']),
6137
                            ['class' => 'btn btn-primary btn-large']
6138
                        );
6139
6140
                        $exercise_redirect = intval(Session::read('exercise_redirect'));
6141
                        // Specify the course id as the current context does not
6142
                        // hold a global $_course array
6143
                        $objExercise = new Exercise($course_info['real_id']);
6144
                        $result = $objExercise->read($exercise_redirect);
6145
6146
                        if (!empty($exercise_redirect) && !empty($result)) {
6147
                            $form_data['action'] = api_get_path(WEB_CODE_PATH).'exercise/overview.php?exerciseId='.$exercise_redirect.'&cidReq='.$course_info['code'];
6148
                            $form_data['message'] .= '<br />'.get_lang('YouCanAccessTheExercise');
6149
                            $form_data['button'] = Display::button(
6150
                                'next',
6151
                                get_lang('Go', null, $_user['language']),
6152
                                ['class' => 'btn btn-primary btn-large']
6153
                            );
6154
                        }
6155
6156
                        if (!empty($form_data['action'])) {
6157
                            header('Location: '.$form_data['action']);
6158
                            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
6159
                        }
6160
                    }
6161
                }
6162
            }
6163
        }
6164
6165
        return $form_data;
6166
    }
6167
6168
    /**
6169
     * Return tab of params to display a course title in the My Courses tab
6170
     * Check visibility, right, and notification icons, and load_dirs option
6171
     *  // get html course params
6172
     *   //
6173
     * @param $courseId
6174
     * @param bool $loadDirs
6175
     * @return array with keys ['right_actions'] ['teachers'] ['notifications']
6176
     */
6177
    public static function getCourseParamsForDisplay($courseId, $loadDirs = false)
6178
    {
6179
        $user_id = api_get_user_id();
6180
        // Table definitions
6181
        $TABLECOURS = Database::get_main_table(TABLE_MAIN_COURSE);
6182
        $TABLECOURSUSER = Database::get_main_table(TABLE_MAIN_COURSE_USER);
6183
        $TABLE_ACCESS_URL_REL_COURSE = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
6184
        $current_url_id = api_get_current_access_url_id();
6185
6186
        // Get course list auto-register
6187
        $special_course_list = self::get_special_course_list();
6188
6189
        $without_special_courses = '';
6190
        if (!empty($special_course_list)) {
6191
            $without_special_courses = ' AND course.id NOT IN ("'.implode('","', $special_course_list).'")';
6192
        }
6193
6194
        //AND course_rel_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
6195
        $sql = "SELECT 
6196
                    course.id, 
6197
                    course.title, 
6198
                    course.code, 
6199
                    course.subscribe subscr, 
6200
                    course.unsubscribe unsubscr, 
6201
                    course_rel_user.status status,
6202
                    course_rel_user.sort sort, 
6203
                    course_rel_user.user_course_cat user_course_cat
6204
                FROM
6205
                $TABLECOURS course 
6206
                INNER JOIN $TABLECOURSUSER course_rel_user                
6207
                ON (course.id = course_rel_user.c_id)
6208
                INNER JOIN $TABLE_ACCESS_URL_REL_COURSE url
6209
                ON (url.c_id = course.id)
6210
                WHERE
6211
                    course.id=".intval($courseId)." AND
6212
                    course_rel_user.user_id = ".intval($user_id)."
6213
                    $without_special_courses
6214
                ";
6215
6216
        // If multiple URL access mode is enabled, only fetch courses
6217
        // corresponding to the current URL.
6218
        if (api_get_multiple_access_url() && $current_url_id != -1) {
6219
            $sql .= " AND url.c_id = course.id AND access_url_id=".intval($current_url_id);
6220
        }
6221
        // Use user's classification for courses (if any).
6222
        $sql .= " ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
6223
6224
        $result = Database::query($sql);
6225
6226
        // Browse through all courses. We can only have one course because
6227
        // of the  course.id=".intval($courseId) in sql query
6228
        $course = Database::fetch_array($result);
6229
        $course_info = api_get_course_info_by_id($courseId);
6230
        if (empty($course_info)) {
6231
            return '';
0 ignored issues
show
Bug Best Practice introduced by
The expression return '' returns the type string which is incompatible with the documented return type array.
Loading history...
6232
        }
6233
6234
        //$course['id_session'] = null;
6235
        $course_info['id_session'] = null;
6236
        $course_info['status'] = $course['status'];
6237
6238
        // For each course, get if there is any notification icon to show
6239
        // (something that would have changed since the user's last visit).
6240
        $show_notification = !api_get_configuration_value('hide_course_notification')
6241
            ? Display::show_notification($course_info)
6242
            : '';
6243
6244
        // New code displaying the user's status in respect to this course.
6245
        $status_icon = Display::return_icon(
6246
            'blackboard.png',
6247
            $course_info['title'],
6248
            [],
6249
            ICON_SIZE_LARGE
6250
        );
6251
6252
        $params = [];
6253
        $params['right_actions'] = '';
6254
6255
        if (api_is_platform_admin()) {
6256
            if ($loadDirs) {
6257
                $params['right_actions'] .= '<a id="document_preview_'.$course_info['real_id'].'_0" class="document_preview" href="javascript:void(0);">'.Display::return_icon('folder.png', get_lang('Documents'), ['align' => 'absmiddle'], ICON_SIZE_SMALL).'</a>';
6258
                $params['right_actions'] .= '<a href="'.api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cidReq='.$course['code'].'">'.
6259
                    Display::return_icon('edit.png', get_lang('Edit'), ['align' => 'absmiddle'], ICON_SIZE_SMALL).
6260
                    '</a>';
6261
                $params['right_actions'] .= Display::div(
6262
                    '',
6263
                    [
6264
                        'id' => 'document_result_'.$course_info['real_id'].'_0',
6265
                        'class' => 'document_preview_container',
6266
                    ]
6267
                );
6268
            } else {
6269
                $params['right_actions'] .= '<a class="btn btn-default btn-sm" title="'.get_lang('Edit').'" href="'.api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cidReq='.$course['code'].'">'.
6270
                    Display::returnFontAwesomeIcon('pencil').'</a>';
6271
            }
6272
        } else {
6273
            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
6274
                if ($loadDirs) {
6275
                    $params['right_actions'] .= '<a id="document_preview_'.$course_info['real_id'].'_0" class="document_preview" href="javascript:void(0);">'.
6276
                        Display::return_icon('folder.png', get_lang('Documents'), ['align' => 'absmiddle'], ICON_SIZE_SMALL).'</a>';
6277
                    $params['right_actions'] .= Display::div(
6278
                        '',
6279
                        [
6280
                            'id' => 'document_result_'.$course_info['real_id'].'_0',
6281
                            'class' => 'document_preview_container',
6282
                        ]
6283
                    );
6284
                } else {
6285
                    if ($course_info['status'] == COURSEMANAGER) {
6286
                        $params['right_actions'] .= '<a class="btn btn-default btn-sm" title="'.get_lang('Edit').'" href="'.api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cidReq='.$course['code'].'">'.
6287
                            Display::returnFontAwesomeIcon('pencil').'</a>';
6288
                    }
6289
                }
6290
            }
6291
        }
6292
6293
        $course_title_url = '';
6294
        if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED || $course['status'] == COURSEMANAGER) {
6295
            $course_title_url = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/?id_session=0';
6296
            $course_title = Display::url($course_info['title'], $course_title_url);
6297
        } else {
6298
            $course_title = $course_info['title'].' '.Display::tag(
6299
                'span',
6300
                get_lang('CourseClosed'),
6301
                ['class' => 'item_closed']
6302
            );
6303
        }
6304
6305
        // Start displaying the course block itself
6306
        if (api_get_setting('display_coursecode_in_courselist') === 'true') {
6307
            $course_title .= ' ('.$course_info['visual_code'].') ';
6308
        }
6309
        $teachers = '';
6310
        if (api_get_setting('display_teacher_in_courselist') === 'true') {
6311
            $teachers = self::getTeacherListFromCourseCodeToString(
6312
                $course['code'],
6313
                self::USER_SEPARATOR,
6314
                true
6315
            );
6316
        }
6317
        $params['link'] = $course_title_url;
6318
        $params['icon'] = $status_icon;
6319
        $params['title'] = $course_title;
6320
        $params['teachers'] = $teachers;
6321
        if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
6322
            $params['notifications'] = $show_notification;
6323
        }
6324
6325
        return $params;
6326
    }
6327
6328
    /**
6329
     * Get the course id based on the original id and field name in the extra fields.
6330
     * Returns 0 if course was not found
6331
     *
6332
     * @param string $original_course_id_value Original course id
6333
     * @param string $original_course_id_name Original field name
6334
     * @return int Course id
6335
     */
6336
    public static function get_course_id_from_original_id($original_course_id_value, $original_course_id_name)
6337
    {
6338
        $extraFieldValue = new ExtraFieldValue('course');
6339
        $value = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
6340
            $original_course_id_name,
6341
            $original_course_id_value
6342
        );
6343
6344
        if ($value) {
6345
            return $value['item_id'];
6346
        }
6347
        return 0;
6348
    }
6349
6350
    /**
6351
     * Helper function to create a default gradebook (if necessary) upon course creation
6352
     * @param   int     $modelId    The gradebook model ID
6353
     * @param   string  $courseCode Course code
6354
     * @return  void
6355
     */
6356
    public static function createDefaultGradebook($modelId, $courseCode)
6357
    {
6358
        if (api_get_setting('gradebook_enable_grade_model') === 'true') {
6359
            //Create gradebook_category for the new course and add
6360
            // a gradebook model for the course
6361
            if (isset($modelId) &&
6362
                !empty($modelId) &&
6363
                $modelId != '-1'
6364
            ) {
6365
                GradebookUtils::create_default_course_gradebook(
6366
                    $courseCode,
6367
                    $modelId
6368
                );
6369
            }
6370
        }
6371
    }
6372
6373
    /**
6374
     * Helper function to check if there is a course template and, if so, to
6375
     * copy the template as basis for the new course
6376
     * @param   string  $courseCode   Course code
6377
     * @param   int     $courseTemplate 0 if no course template is defined
6378
     */
6379
    public static function useTemplateAsBasisIfRequired($courseCode, $courseTemplate)
6380
    {
6381
        $template = api_get_setting('course_creation_use_template');
6382
        $teacherCanSelectCourseTemplate = api_get_setting('teacher_can_select_course_template') === 'true';
6383
        $courseTemplate = isset($courseTemplate) ? intval($courseTemplate) : 0;
6384
6385
        $useTemplate = false;
6386
6387
        if ($teacherCanSelectCourseTemplate && $courseTemplate) {
6388
            $useTemplate = true;
6389
            $originCourse = api_get_course_info_by_id($courseTemplate);
6390
        } elseif (!empty($template)) {
6391
            $useTemplate = true;
6392
            $originCourse = api_get_course_info_by_id($template);
6393
        }
6394
6395
        if ($useTemplate) {
6396
            // Include the necessary libraries to generate a course copy
6397
            // Call the course copy object
6398
            $originCourse['official_code'] = $originCourse['code'];
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $originCourse does not seem to be defined for all execution paths leading up to this point.
Loading history...
6399
            $cb = new CourseBuilder(null, $originCourse);
6400
            $course = $cb->build(null, $originCourse['code']);
6401
            $cr = new CourseRestorer($course);
6402
            $cr->set_file_option();
6403
            $cr->restore($courseCode);
6404
        }
6405
    }
6406
6407
    /**
6408
     * Helper method to get the number of users defined with a specific course extra field
6409
     * @param   string  $name   Field title
6410
     * @param   string  $tableExtraFields The extra fields table name
6411
     * @param   string  $tableUserFieldValues The user extra field value table name
6412
     * @return  int     The number of users with this extra field with a specific value
6413
     */
6414
    public static function getCountRegisteredUsersWithCourseExtraField(
6415
        $name,
6416
        $tableExtraFields = '',
6417
        $tableUserFieldValues = ''
6418
    ) {
6419
        if (empty($tableExtraFields)) {
6420
            $tableExtraFields = Database::get_main_table(TABLE_EXTRA_FIELD);
6421
        }
6422
        if (empty($tableUserFieldValues)) {
6423
            $tableUserFieldValues = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
6424
        }
6425
6426
        $registered_users_with_extra_field = 0;
6427
        if (!empty($name) && $name != '-') {
6428
            $extraFieldType = EntityExtraField::COURSE_FIELD_TYPE;
6429
            $name = Database::escape_string($name);
6430
            $sql = "SELECT count(v.item_id) as count
6431
                    FROM $tableUserFieldValues v 
6432
                    INNER JOIN $tableExtraFields f
6433
                    ON (f.id = v.field_id)
6434
                    WHERE value = '$name' AND extra_field_type = $extraFieldType";
6435
            $result_count = Database::query($sql);
6436
            if (Database::num_rows($result_count)) {
6437
                $row_count = Database::fetch_array($result_count);
6438
                $registered_users_with_extra_field = $row_count['count'];
6439
            }
6440
        }
6441
6442
        return $registered_users_with_extra_field;
6443
    }
6444
6445
    /**
6446
     * Check if a specific access-url-related setting is a problem or not
6447
     * @param array $_configuration The $_configuration array
6448
     * @param int $accessUrlId The access URL ID
6449
     * @param string $param
6450
     * @param string $msgLabel
6451
     * @return bool|string
6452
     */
6453
    private static function checkCreateCourseAccessUrlParam($_configuration, $accessUrlId, $param, $msgLabel)
6454
    {
6455
        if (isset($_configuration[$accessUrlId][$param]) && $_configuration[$accessUrlId][$param] > 0) {
6456
            $num = self::count_courses($accessUrlId);
6457
            if ($num >= $_configuration[$accessUrlId][$param]) {
6458
                api_warn_hosting_contact($param);
6459
6460
                Display::addFlash(
6461
                    Display::return_message($msgLabel)
6462
                );
6463
            }
6464
        }
6465
        return false;
6466
    }
6467
    /**
6468
     * Fill course with all necessary items
6469
     * @param array $courseInfo Course info array
6470
     * @param array $params Parameters from the course creation form
6471
     * @param int $authorId
6472
     * @return void
6473
     */
6474
    private static function fillCourse($courseInfo, $params, $authorId = 0)
6475
    {
6476
        $authorId = empty($authorId) ? api_get_user_id() : (int) $authorId;
6477
6478
        AddCourse::prepare_course_repository($courseInfo['directory']);
6479
        AddCourse::fill_db_course(
6480
            $courseInfo['real_id'],
6481
            $courseInfo['directory'],
6482
            $courseInfo['course_language'],
6483
            $params['exemplary_content'],
6484
            $authorId
6485
        );
6486
6487
        if (isset($params['gradebook_model_id'])) {
6488
            self::createDefaultGradebook(
6489
                $params['gradebook_model_id'],
6490
                $courseInfo['code']
6491
            );
6492
        }
6493
6494
        // If parameter defined, copy the contents from a specific
6495
        // template course into this new course
6496
        if (isset($params['course_template'])) {
6497
            self::useTemplateAsBasisIfRequired(
6498
                $courseInfo['id'],
6499
                $params['course_template']
6500
            );
6501
        }
6502
        $params['course_code'] = $courseInfo['code'];
6503
        $params['item_id'] = $courseInfo['real_id'];
6504
6505
        $courseFieldValue = new ExtraFieldValue('course');
6506
        $courseFieldValue->saveFieldValues($params);
6507
    }
6508
6509
    /**
6510
     * Get the course categories form a course list
6511
     * @param array $courseList
6512
     * @return array
6513
     */
6514
    public static function getCourseCategoriesFromCourseList(array $courseList)
6515
    {
6516
        $allCategories = array_column($courseList, 'category');
6517
        $categories = array_unique($allCategories);
6518
6519
        sort($categories);
6520
6521
        return $categories;
6522
    }
6523
6524
    /**
6525
     * Display the description button of a course in the course catalog
6526
     * @param array $course
6527
     *
6528
     * @return string HTML string
6529
     */
6530
    public static function returnDescriptionButton($course)
6531
    {
6532
        if (empty($course)) {
6533
            return '';
6534
        }
6535
6536
        if (api_get_setting('show_courses_descriptions_in_catalog') == 'true') {
6537
            $title = $course['title'];
6538
            $url = api_get_path(WEB_CODE_PATH).'inc/ajax/course_home.ajax.php?a=show_course_information&code='.$course['code'];
6539
            $html = Display::url(
6540
                Display::returnFontAwesomeIcon('info-circle', 2),
6541
                $url,
6542
                [
6543
                    'class' => 'ajax btn btn-default btn-sm',
6544
                    'data-title' => $title,
6545
                    'title' => get_lang('Description'),
6546
                    'aria-label' => get_lang('Description'),
6547
                    'data-size' => 'lg'
6548
                ]
6549
            );
6550
            return $html;
6551
        }
6552
        return '';
6553
    }
6554
6555
    /**
6556
     * @param ToolChain $toolList
6557
     */
6558
    public static function setToolList($toolList)
6559
    {
6560
        self::$toolList = $toolList;
6561
    }
6562
6563
    /**
6564
     * @return ToolChain
6565
     */
6566
    public static function getToolList()
6567
    {
6568
        return self::$toolList;
6569
    }
6570
}
6571