Completed
Push — master ( ae5621...ef667c )
by Julito
13:23
created

CourseManager::getCountPostInForumPerUser()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 25
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 13
nc 1
nop 3
dl 0
loc 25
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt*/
3
4
use Chamilo\CoreBundle\Entity\ExtraField as EntityExtraField;
5
use Chamilo\CourseBundle\Component\CourseCopy\CourseBuilder;
6
use Chamilo\CourseBundle\Component\CourseCopy\CourseRestorer;
7
use Chamilo\CourseBundle\Manager\SettingsManager;
8
use Chamilo\CourseBundle\ToolChain;
9
use ChamiloSession as Session;
10
11
/**
12
 * Class CourseManager.
13
 *
14
 * This is the course library for Chamilo.
15
 *
16
 * All main course functions should be placed here.
17
 *
18
 * Many functions of this library deal with providing support for
19
 * virtual/linked/combined courses (this was already used in several universities
20
 * but not available in standard Chamilo).
21
 *
22
 * There are probably some places left with the wrong code.
23
 *
24
 * @package chamilo.library
25
 */
26
class CourseManager
27
{
28
    const MAX_COURSE_LENGTH_CODE = 40;
29
    /** This constant is used to show separate user names in the course
30
     * list (userportal), footer, etc */
31
    const USER_SEPARATOR = ' |';
32
    const COURSE_FIELD_TYPE_CHECKBOX = 10;
33
    public $columns = [];
34
    public static $em;
35
    public static $toolList;
36
    public static $courseSettingsManager;
37
    private static $manager;
38
39
    /**
40
     * @param \Doctrine\ORM\EntityManager
41
     */
42
    public static function setEntityManager($em)
43
    {
44
        self::$em = $em;
45
    }
46
47
    /**
48
     * @return \Doctrine\ORM\EntityManager
49
     */
50
    public static function getEntityManager()
51
    {
52
        return self::$em;
53
    }
54
55
    /**
56
     * @param $manager
57
     */
58
    public static function setCourseManager($manager)
59
    {
60
        self::$manager = $manager;
61
    }
62
63
    /**
64
     * @return SettingsManager
65
     */
66
    public static function getCourseSettingsManager()
67
    {
68
        return self::$courseSettingsManager;
69
    }
70
71
    /**
72
     * @param SettingsManager $courseSettingsManager
73
     */
74
    public static function setCourseSettingsManager($courseSettingsManager)
75
    {
76
        self::$courseSettingsManager = $courseSettingsManager;
77
    }
78
79
    /**
80
     * @return Chamilo\CoreBundle\Entity\Manager\CourseManager
81
     */
82
    public static function getManager()
83
    {
84
        return self::$manager;
85
    }
86
87
    /**
88
     * Creates a course.
89
     *
90
     * @param array $params   columns in the main.course table
91
     * @param int   $authorId
92
     *
93
     * @return mixed false if the course was not created, array with the course info
94
     */
95
    public static function create_course($params, $authorId = 0)
96
    {
97
        global $_configuration;
98
        // Check portal limits
99
        $access_url_id = 1;
100
        if (api_get_multiple_access_url()) {
101
            $access_url_id = api_get_current_access_url_id();
102
        }
103
104
        $authorId = empty($authorId) ? api_get_user_id() : (int) $authorId;
105
106
        if (isset($_configuration[$access_url_id]) && is_array($_configuration[$access_url_id])) {
107
            $return = self::checkCreateCourseAccessUrlParam(
108
                $_configuration,
109
                $access_url_id,
110
                'hosting_limit_courses',
111
                'PortalCoursesLimitReached'
112
            );
113
            if ($return != false) {
114
                return $return;
115
            }
116
            $return = self::checkCreateCourseAccessUrlParam(
117
                $_configuration,
118
                $access_url_id,
119
                'hosting_limit_active_courses',
120
                'PortalActiveCoursesLimitReached'
121
            );
122
            if ($return != false) {
123
                return $return;
124
            }
125
        }
126
127
        if (empty($params['title'])) {
128
            return false;
129
        }
130
131
        if (empty($params['wanted_code'])) {
132
            $params['wanted_code'] = $params['title'];
133
            // Check whether the requested course code has already been occupied.
134
            $substring = api_substr($params['title'], 0, self::MAX_COURSE_LENGTH_CODE);
135
            if ($substring === false || empty($substring)) {
136
                return false;
137
            } else {
138
                $params['wanted_code'] = self::generate_course_code($substring);
139
            }
140
        }
141
142
        // Create the course keys
143
        $keys = AddCourse::define_course_keys($params['wanted_code']);
144
        $params['exemplary_content'] = isset($params['exemplary_content']) ? $params['exemplary_content'] : false;
145
146
        if (count($keys)) {
147
            $params['code'] = $keys['currentCourseCode'];
148
            $params['visual_code'] = $keys['currentCourseId'];
149
            $params['directory'] = $keys['currentCourseRepository'];
150
            $courseInfo = api_get_course_info($params['code']);
151
            if (empty($courseInfo)) {
152
                $courseId = AddCourse::register_course($params);
153
                $courseInfo = api_get_course_info_by_id($courseId);
154
155
                if (!empty($courseInfo)) {
156
                    self::fillCourse($courseInfo, $params, $authorId);
157
158
                    return $courseInfo;
159
                }
160
            }
161
        }
162
163
        return false;
164
    }
165
166
    /**
167
     * Returns all the information of a given course code.
168
     *
169
     * @param string $course_code , the course code
170
     *
171
     * @return array with all the fields of the course table
172
     *
173
     * @deprecated Use api_get_course_info() instead
174
     *
175
     * @author Patrick Cool <[email protected]>, Ghent University
176
     * @assert ('') === false
177
     */
178
    public static function get_course_information($course_code)
179
    {
180
        return Database::fetch_array(
181
            Database::query(
182
                "SELECT *, id as real_id FROM ".Database::get_main_table(TABLE_MAIN_COURSE)."
183
                WHERE code = '".Database::escape_string($course_code)."'"
184
            ),
185
            'ASSOC'
186
        );
187
    }
188
189
    /**
190
     * Returns a list of courses. Should work with quickform syntax.
191
     *
192
     * @param int    $from           Offset (from the 7th = '6'). Optional.
193
     * @param int    $howmany        Number of results we want. Optional.
194
     * @param int    $orderby        The column we want to order it by. Optional, defaults to first column.
195
     * @param string $orderdirection The direction of the order (ASC or DESC). Optional, defaults to ASC.
196
     * @param int    $visibility     the visibility of the course, or all by default
197
     * @param string $startwith      If defined, only return results for which the course *title* begins with this string
198
     * @param string $urlId          The Access URL ID, if using multiple URLs
199
     * @param bool   $alsoSearchCode An extension option to indicate that we also want to search for course codes (not *only* titles)
200
     * @param array  $conditionsLike
201
     *
202
     * @return array
203
     */
204
    public static function get_courses_list(
205
        $from = 0,
206
        $howmany = 0,
207
        $orderby = 1,
208
        $orderdirection = 'ASC',
209
        $visibility = -1,
210
        $startwith = '',
211
        $urlId = null,
212
        $alsoSearchCode = false,
213
        $conditionsLike = []
214
    ) {
215
        $sql = "SELECT course.* FROM ".Database::get_main_table(TABLE_MAIN_COURSE)." course ";
216
217
        if (!empty($urlId)) {
218
            $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
219
            $sql .= " INNER JOIN $table url ON (url.c_id = course.id) ";
220
        }
221
222
        if (!empty($startwith)) {
223
            $sql .= "WHERE (title LIKE '".Database::escape_string($startwith)."%' ";
224
            if ($alsoSearchCode) {
225
                $sql .= "OR code LIKE '".Database::escape_string($startwith)."%' ";
226
            }
227
            $sql .= ') ';
228
            if ($visibility !== -1 && $visibility == strval(intval($visibility))) {
229
                $sql .= " AND visibility = $visibility ";
230
            }
231
        } else {
232
            $sql .= "WHERE 1 ";
233
            if ($visibility !== -1 && $visibility == strval(intval($visibility))) {
234
                $sql .= " AND visibility = $visibility ";
235
            }
236
        }
237
238
        if (!empty($urlId)) {
239
            $urlId = intval($urlId);
240
            $sql .= " AND access_url_id = $urlId";
241
        }
242
243
        $allowedFields = [
244
            'title',
245
            'code',
246
        ];
247
248
        if (count($conditionsLike) > 0) {
249
            $sql .= ' AND ';
250
            $temp_conditions = [];
251
            foreach ($conditionsLike as $field => $value) {
252
                if (!in_array($field, $allowedFields)) {
253
                    continue;
254
                }
255
                $field = Database::escape_string($field);
256
                $value = Database::escape_string($value);
257
                $simple_like = false;
258
                if ($simple_like) {
259
                    $temp_conditions[] = $field." LIKE '$value%'";
260
                } else {
261
                    $temp_conditions[] = $field.' LIKE \'%'.$value.'%\'';
262
                }
263
            }
264
            $condition = ' AND ';
265
            if (!empty($temp_conditions)) {
266
                $sql .= implode(' '.$condition.' ', $temp_conditions);
267
            }
268
        }
269
270
        if (!empty($orderby)) {
271
            $sql .= " ORDER BY ".Database::escape_string($orderby)." ";
272
        } else {
273
            $sql .= " ORDER BY 1 ";
274
        }
275
276
        if (!in_array($orderdirection, ['ASC', 'DESC'])) {
277
            $sql .= 'ASC';
278
        } else {
279
            $sql .= ($orderdirection == 'ASC' ? 'ASC' : 'DESC');
280
        }
281
282
        if (!empty($howmany) && is_int($howmany) and $howmany > 0) {
283
            $sql .= ' LIMIT '.Database::escape_string($howmany);
284
        } else {
285
            $sql .= ' LIMIT 1000000'; //virtually no limit
286
        }
287
        if (!empty($from)) {
288
            $from = intval($from);
289
            $sql .= ' OFFSET '.intval($from);
290
        } else {
291
            $sql .= ' OFFSET 0';
292
        }
293
294
        $data = [];
295
        $res = Database::query($sql);
296
        if (Database::num_rows($res) > 0) {
297
            while ($row = Database::fetch_array($res, 'ASSOC')) {
298
                $data[] = $row;
299
            }
300
        }
301
302
        return $data;
303
    }
304
305
    /**
306
     * Returns the status of a user in a course, which is COURSEMANAGER or STUDENT.
307
     *
308
     * @param int $userId
309
     * @param int $courseId
310
     *
311
     * @return int|bool the status of the user in that course (or false if the user is not in that course)
312
     */
313
    public static function getUserInCourseStatus($userId, $courseId)
314
    {
315
        $courseId = (int) $courseId;
316
        if (empty($courseId)) {
317
            return false;
318
        }
319
320
        $result = Database::fetch_array(
321
            Database::query(
322
                "SELECT status FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
323
                WHERE
324
                    c_id  = $courseId AND
325
                    user_id = ".intval($userId)
326
            )
327
        );
328
329
        return $result['status'];
330
    }
331
332
    /**
333
     * @param int $userId
334
     * @param int $courseId
335
     *
336
     * @return mixed
337
     */
338
    public static function getUserCourseInfo($userId, $courseId)
339
    {
340
        $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
341
                WHERE
342
                    c_id  = ".intval($courseId)." AND
343
                    user_id = ".intval($userId);
344
        $result = Database::fetch_array(Database::query($sql));
345
346
        return $result;
347
    }
348
349
    /**
350
     * @param int  $userId
351
     * @param int  $courseId
352
     * @param bool $isTutor
353
     *
354
     * @return bool
355
     */
356
    public static function updateUserCourseTutor($userId, $courseId, $isTutor)
357
    {
358
        $table = Database::escape_string(TABLE_MAIN_COURSE_USER);
359
360
        $courseId = intval($courseId);
361
        $isTutor = intval($isTutor);
362
363
        $sql = "UPDATE $table SET is_tutor = '".$isTutor."'
364
			    WHERE
365
				    user_id = ".$userId." AND
366
				    c_id = ".$courseId;
367
368
        $result = Database::query($sql);
369
370
        if (Database::affected_rows($result) > 0) {
371
            return true;
372
        } else {
373
            return false;
374
        }
375
    }
376
377
    /**
378
     * @param int $user_id
379
     * @param int $courseId
380
     *
381
     * @return mixed
382
     */
383
    public static function get_tutor_in_course_status($userId, $courseId)
384
    {
385
        $userId = intval($userId);
386
        $courseId = intval($courseId);
387
        $result = Database::fetch_array(
388
            Database::query(
389
                "SELECT is_tutor
390
                FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
391
                WHERE
392
                    c_id = $courseId AND
393
                    user_id = $userId"
394
            )
395
        );
396
397
        return $result['is_tutor'];
398
    }
399
400
    /**
401
     * Unsubscribe one or more users from a course.
402
     *
403
     * @param   mixed   user_id or an array with user ids
404
     * @param   string  course code
405
     * @param   int     session id
406
     * @assert ('', '') === false
407
     */
408
    public static function unsubscribe_user($user_id, $course_code, $session_id = 0)
409
    {
410
        if (empty($user_id)) {
411
            return;
412
        }
413
        if (!is_array($user_id)) {
414
            $user_id = [$user_id];
415
        }
416
417
        if (count($user_id) == 0) {
418
            return;
419
        }
420
421
        if (!empty($session_id)) {
422
            $session_id = intval($session_id);
423
        } else {
424
            $session_id = api_get_session_id();
425
        }
426
427
        $userList = [];
428
429
        // Cleaning the $user_id variable
430
        if (is_array($user_id)) {
431
            $new_user_id_list = [];
432
            foreach ($user_id as $my_user_id) {
433
                $new_user_id_list[] = intval($my_user_id);
434
            }
435
            $new_user_id_list = array_filter($new_user_id_list);
436
            $userList = $new_user_id_list;
437
            $user_ids = implode(',', $new_user_id_list);
438
        } else {
439
            $user_ids = intval($user_id);
440
            $userList[] = $user_id;
441
        }
442
443
        $course_info = api_get_course_info($course_code);
444
        $course_id = $course_info['real_id'];
445
446
        // Unsubscribe user from all groups in the course.
447
        $sql = "DELETE FROM ".Database::get_course_table(TABLE_GROUP_USER)."
448
                WHERE c_id = $course_id AND user_id IN (".$user_ids.")";
449
        Database::query($sql);
450
        $sql = "DELETE FROM ".Database::get_course_table(TABLE_GROUP_TUTOR)."
451
                WHERE c_id = $course_id AND user_id IN (".$user_ids.")";
452
        Database::query($sql);
453
454
        // Erase user student publications (works) in the course - by André Boivin
455
456
        if (!empty($userList)) {
457
            require_once api_get_path(SYS_CODE_PATH).'work/work.lib.php';
458
            foreach ($userList as $userId) {
459
                // Getting all work from user
460
                $workList = getWorkPerUser($userId);
461
                if (!empty($workList)) {
462
                    foreach ($workList as $work) {
463
                        $work = $work['work'];
464
                        // Getting user results
465
                        if (!empty($work->user_results)) {
466
                            foreach ($work->user_results as $workSent) {
467
                                deleteWorkItem($workSent['id'], $course_info);
468
                            }
469
                        }
470
                    }
471
                }
472
            }
473
        }
474
475
        // Unsubscribe user from all blogs in the course.
476
        $sql = "DELETE FROM ".Database::get_course_table(TABLE_BLOGS_REL_USER)." 
477
                WHERE c_id = $course_id AND user_id IN ($user_ids)";
478
        Database::query($sql);
479
480
        $sql = "DELETE FROM ".Database::get_course_table(TABLE_BLOGS_TASKS_REL_USER)." 
481
                WHERE c_id = $course_id AND user_id IN ($user_ids)";
482
        Database::query($sql);
483
484
        // Deleting users in forum_notification and mailqueue course tables
485
        $sql = "DELETE FROM  ".Database::get_course_table(TABLE_FORUM_NOTIFICATION)."
486
                WHERE c_id = $course_id AND user_id IN ($user_ids)";
487
        Database::query($sql);
488
489
        $sql = "DELETE FROM ".Database::get_course_table(TABLE_FORUM_MAIL_QUEUE)."
490
                WHERE c_id = $course_id AND user_id IN ($user_ids)";
491
        Database::query($sql);
492
493
        // Unsubscribe user from the course.
494
        if (!empty($session_id)) {
495
            // Delete in table session_rel_course_rel_user
496
            $sql = "DELETE FROM ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)."
497
                    WHERE
498
                        session_id = $session_id AND
499
                        c_id = $course_id AND
500
                        user_id IN ($user_ids)";
501
            Database::query($sql);
502
503
            foreach ($userList as $uid) {
504
                // check if a user is register in the session with other course
505
                $sql = "SELECT user_id FROM ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)."
506
                        WHERE session_id = $session_id AND user_id = $uid";
507
                $rs = Database::query($sql);
508
509
                if (Database::num_rows($rs) == 0) {
510
                    // Delete in table session_rel_user
511
                    $sql = "DELETE FROM ".Database::get_main_table(TABLE_MAIN_SESSION_USER)."
512
                            WHERE
513
                                session_id = $session_id AND
514
                                user_id = $uid AND
515
                                relation_type<>".SESSION_RELATION_TYPE_RRHH;
516
                    Database::query($sql);
517
                }
518
            }
519
520
            // Update the table session
521
            $sql = "SELECT COUNT(*) FROM ".Database::get_main_table(TABLE_MAIN_SESSION_USER)."
522
                    WHERE session_id = '".$session_id."' AND relation_type <> ".SESSION_RELATION_TYPE_RRHH;
523
            $row = Database::fetch_array(Database::query($sql));
524
            $count = $row[0];
525
            // number of users by session
526
            $sql = "UPDATE ".Database::get_main_table(TABLE_MAIN_SESSION)." SET nbr_users = $count
527
                    WHERE id = $session_id";
528
            Database::query($sql);
529
530
            // Update the table session_rel_course
531
            $sql = "SELECT COUNT(*) FROM ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)."
532
                    WHERE session_id = $session_id AND c_id = $course_id AND status <> 2";
533
            $row = Database::fetch_array(@Database::query($sql));
534
            $count = $row[0];
535
536
            // number of users by session and course
537
            $sql = "UPDATE ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE)."
538
                    SET nbr_users = $count
539
                    WHERE session_id = $session_id AND c_id = $course_id";
540
            Database::query($sql);
541
542
            Event::addEvent(
543
                LOG_UNSUBSCRIBE_USER_FROM_COURSE,
544
                LOG_COURSE_CODE,
545
                $course_code,
546
                api_get_utc_datetime(),
547
                $user_id,
548
                $course_id,
549
                $session_id
550
            );
551
        } else {
552
            $sql = "DELETE FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
553
                    WHERE
554
                        user_id IN ($user_ids) AND
555
                        relation_type <> ".COURSE_RELATION_TYPE_RRHH." AND
556
                        c_id = $course_id";
557
            Database::query($sql);
558
559
            // add event to system log
560
            $user_id = api_get_user_id();
561
562
            Event::addEvent(
563
                LOG_UNSUBSCRIBE_USER_FROM_COURSE,
564
                LOG_COURSE_CODE,
565
                $course_code,
566
                api_get_utc_datetime(),
567
                $user_id,
568
                $course_id
569
            );
570
571
            foreach ($userList as $userId) {
572
                $userInfo = api_get_user_info($userId);
573
                Event::addEvent(
574
                    LOG_UNSUBSCRIBE_USER_FROM_COURSE,
575
                    LOG_USER_OBJECT,
576
                    $userInfo,
577
                    api_get_utc_datetime(),
578
                    $user_id,
579
                    $course_id
580
                );
581
            }
582
        }
583
    }
584
585
    /**
586
     * Subscribe a user to a course. No checks are performed here to see if
587
     * course subscription is allowed.
588
     *
589
     * @param int    $user_id
590
     * @param string $course_code
591
     * @param int    $status               (STUDENT, COURSEMANAGER, COURSE_ADMIN, NORMAL_COURSE_MEMBER)
592
     * @param int    $session_id
593
     * @param int    $userCourseCategoryId
594
     *
595
     * @return bool True on success, false on failure
596
     *
597
     * @see add_user_to_course
598
     * @assert ('', '') === false
599
     */
600
    public static function subscribe_user(
601
        $user_id,
602
        $course_code,
603
        $status = STUDENT,
604
        $session_id = 0,
605
        $userCourseCategoryId = 0
606
    ) {
607
        if ($user_id != strval(intval($user_id))) {
608
            return false; //detected possible SQL injection
609
        }
610
611
        $course_code = Database::escape_string($course_code);
612
        $courseInfo = api_get_course_info($course_code);
613
        $courseId = $courseInfo['real_id'];
614
        $courseCode = $courseInfo['code'];
615
        $userCourseCategoryId = intval($userCourseCategoryId);
616
617
        if (empty($user_id) || empty($course_code)) {
618
            return false;
619
        }
620
621
        if (!empty($session_id)) {
622
            $session_id = intval($session_id);
623
        } else {
624
            $session_id = api_get_session_id();
625
        }
626
627
        $status = ($status == STUDENT || $status == COURSEMANAGER) ? $status : STUDENT;
628
629
        // A preliminary check whether the user has bben already registered on the platform.
630
        $sql = "SELECT status FROM ".Database::get_main_table(TABLE_MAIN_USER)."
631
                WHERE user_id = $user_id";
632
        if (Database::num_rows(Database::query($sql)) == 0) {
633
            return false; // The user has not been registered to the platform.
634
        }
635
636
        // Check whether the user has not been already subscribed to the course.
637
        $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."                    
638
                WHERE 
639
                    user_id = $user_id AND 
640
                    relation_type <> ".COURSE_RELATION_TYPE_RRHH." AND 
641
                    c_id = $courseId
642
                ";
643
        if (empty($session_id)) {
644
            if (Database::num_rows(Database::query($sql)) > 0) {
645
                // The user has been already subscribed to the course.
646
                return false;
647
            }
648
        }
649
650
        if (!empty($session_id)) {
651
            SessionManager::subscribe_users_to_session_course(
652
                [$user_id],
653
                $session_id,
654
                $courseCode
655
            );
656
            // Add event to the system log
657
            Event::addEvent(
658
                LOG_SUBSCRIBE_USER_TO_COURSE,
659
                LOG_COURSE_CODE,
660
                $course_code,
661
                api_get_utc_datetime(),
662
                api_get_user_id(),
663
                $courseId,
664
                $session_id
665
            );
666
            $user_info = api_get_user_info($user_id);
667
            Event::addEvent(
668
                LOG_SUBSCRIBE_USER_TO_COURSE,
669
                LOG_USER_OBJECT,
670
                $user_info,
671
                api_get_utc_datetime(),
672
                api_get_user_id(),
673
                $courseId,
674
                $session_id
675
            );
676
        } else {
677
            self::add_user_to_course(
678
                $user_id,
679
                $courseCode,
680
                $status,
681
                $userCourseCategoryId
682
            );
683
684
            // Add event to the system log
685
            Event::addEvent(
686
                LOG_SUBSCRIBE_USER_TO_COURSE,
687
                LOG_COURSE_CODE,
688
                $course_code,
689
                api_get_utc_datetime(),
690
                api_get_user_id(),
691
                $courseId
692
            );
693
694
            $user_info = api_get_user_info($user_id);
695
            Event::addEvent(
696
                LOG_SUBSCRIBE_USER_TO_COURSE,
697
                LOG_USER_OBJECT,
698
                $user_info,
699
                api_get_utc_datetime(),
700
                api_get_user_id(),
701
                $courseId
702
            );
703
        }
704
705
        return true;
706
    }
707
708
    /**
709
     * Get the course id based on the original id and field name in the
710
     * extra fields. Returns 0 if course was not found.
711
     *
712
     * @param string $original_course_id_value
713
     * @param string $original_course_id_name
714
     *
715
     * @return int Course id
716
     *
717
     * @assert ('', '') === false
718
     */
719
    public static function get_course_code_from_original_id(
720
        $original_course_id_value,
721
        $original_course_id_name
722
    ) {
723
        $t_cfv = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
724
        $table_field = Database::get_main_table(TABLE_EXTRA_FIELD);
725
        $extraFieldType = EntityExtraField::COURSE_FIELD_TYPE;
726
        $original_course_id_value = Database::escape_string($original_course_id_value);
727
        $original_course_id_name = Database::escape_string($original_course_id_name);
728
729
        $sql = "SELECT item_id
730
                FROM $table_field cf
731
                INNER JOIN $t_cfv cfv
732
                ON cfv.field_id=cf.id
733
                WHERE
734
                    variable = '$original_course_id_name' AND
735
                    value = '$original_course_id_value' AND
736
                    cf.extra_field_type = $extraFieldType
737
                ";
738
        $res = Database::query($sql);
739
        $row = Database::fetch_object($res);
740
        if ($row) {
741
            return $row->item_id;
742
        } else {
743
            return 0;
744
        }
745
    }
746
747
    /**
748
     * Gets the course code from the course id. Returns null if course id was not found.
749
     *
750
     * @param int $id Course id
751
     *
752
     * @return string Course code
753
     * @assert ('') === false
754
     */
755
    public static function get_course_code_from_course_id($id)
756
    {
757
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
758
        $id = intval($id);
759
        $sql = "SELECT code FROM $table WHERE id = $id ";
760
        $res = Database::query($sql);
761
        $row = Database::fetch_object($res);
762
        if ($row) {
763
            return $row->code;
764
        } else {
765
            return null;
766
        }
767
    }
768
769
    /**
770
     * Subscribe a user $user_id to a course defined by $courseCode.
771
     *
772
     * @author Hugues Peeters
773
     * @author Roan Embrechts
774
     *
775
     * @param int    $user_id              the id of the user
776
     * @param string $courseCode           the course code
777
     * @param int    $status               (optional) The user's status in the course
778
     * @param int    $userCourseCategoryId
779
     * @param   int The user category in which this subscription will be classified
780
     *
781
     * @return false|string true if subscription succeeds, boolean false otherwise
782
     * @assert ('', '') === false
783
     */
784
    public static function add_user_to_course(
785
        $user_id,
786
        $courseCode,
787
        $status = STUDENT,
788
        $userCourseCategoryId = 0
789
    ) {
790
        $debug = false;
791
        $user_table = Database::get_main_table(TABLE_MAIN_USER);
792
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
793
        $course_user_table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
794
795
        $status = ($status == STUDENT || $status == COURSEMANAGER) ? $status : STUDENT;
796
        if (empty($user_id) || empty($courseCode) || ($user_id != strval(intval($user_id)))) {
797
            return false;
798
        }
799
800
        $courseCode = Database::escape_string($courseCode);
801
        $courseInfo = api_get_course_info($courseCode);
802
        $courseId = $courseInfo['real_id'];
803
804
        // Check in advance whether the user has already been registered on the platform.
805
        $sql = "SELECT status FROM $user_table WHERE user_id = $user_id ";
806
        if (Database::num_rows(Database::query($sql)) == 0) {
807
            if ($debug) {
808
                error_log('The user has not been registered to the platform');
809
            }
810
811
            return false; // The user has not been registered to the platform.
812
        }
813
814
        // Check whether the user has already been subscribed to this course.
815
        $sql = "SELECT * FROM $course_user_table
816
                WHERE
817
                    user_id = $user_id AND
818
                    relation_type <> ".COURSE_RELATION_TYPE_RRHH." AND
819
                    c_id = $courseId";
820
        if (Database::num_rows(Database::query($sql)) > 0) {
821
            if ($debug) {
822
                error_log('The user has been already subscribed to the course');
823
            }
824
825
            return false; // The user has been subscribed to the course.
826
        }
827
828
        if (!api_is_course_admin()) {
829
            // Check in advance whether subscription is allowed or not for this course.
830
            $sql = "SELECT code, visibility FROM $course_table
831
                    WHERE id = $courseId AND subscribe = '".SUBSCRIBE_NOT_ALLOWED."'";
832
            if (Database::num_rows(Database::query($sql)) > 0) {
833
                if ($debug) {
834
                    error_log('Subscription is not allowed for this course');
835
                }
836
837
                return false; // Subscription is not allowed for this course.
838
            }
839
        }
840
841
        // Ok, subscribe the user.
842
        $max_sort = api_max_sort_value('0', $user_id);
843
        $params = [
844
            'c_id' => $courseId,
845
            'user_id' => $user_id,
846
            'status' => $status,
847
            'sort' => $max_sort + 1,
848
            'relation_type' => 0,
849
            'user_course_cat' => (int) $userCourseCategoryId,
850
        ];
851
        $insertId = Database::insert($course_user_table, $params);
852
853
        return $insertId;
854
    }
855
856
    /**
857
     * Add the user $userId visibility to the course $courseCode in the catalogue.
858
     *
859
     * @author David Nos (https://github.com/dnos)
860
     *
861
     * @param int    $userId     the id of the user
862
     * @param string $courseCode the course code
863
     * @param int    $visible    (optional) The course visibility in the catalogue to the user (1=visible, 0=invisible)
864
     *
865
     * @return bool true if added succesfully, false otherwise
866
     */
867
    public static function addUserVisibilityToCourseInCatalogue(
868
        $userId,
869
        $courseCode,
870
        $visible = 1
871
    ) {
872
        $debug = false;
873
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
874
        $courseUserTable = Database::get_main_table(TABLE_MAIN_COURSE_CATALOGUE_USER);
875
        $visible = (int) $visible;
876
        if (empty($userId) || empty($courseCode) || ($userId != strval(intval($userId)))) {
877
            return false;
878
        }
879
880
        $courseCode = Database::escape_string($courseCode);
881
        $courseInfo = api_get_course_info($courseCode);
882
        $courseId = $courseInfo['real_id'];
883
884
        // Check in advance whether the user has already been registered on the platform.
885
        $sql = "SELECT status FROM ".$userTable." WHERE user_id = $userId ";
886
        if (Database::num_rows(Database::query($sql)) == 0) {
887
            if ($debug) {
888
                error_log('The user has not been registered to the platform');
889
            }
890
891
            return false; // The user has not been registered to the platform.
892
        }
893
894
        // Check whether the user has already been registered to the course visibility in the catalogue.
895
        $sql = "SELECT * FROM $courseUserTable
896
                WHERE
897
                    user_id = $userId AND
898
                    visible = $visible AND
899
                    c_id = $courseId";
900
        if (Database::num_rows(Database::query($sql)) > 0) {
901
            if ($debug) {
902
                error_log('The user has been already registered to the course visibility in the catalogue');
903
            }
904
905
            return true; // The visibility of the user to the course in the catalogue does already exist.
906
        }
907
908
        // Register the user visibility to course in catalogue.
909
        $params = [
910
            'user_id' => $userId,
911
            'c_id' => $courseId,
912
            'visible' => $visible,
913
        ];
914
        $insertId = Database::insert($courseUserTable, $params);
915
916
        return $insertId;
917
    }
918
919
    /**
920
     * Remove the user $userId visibility to the course $courseCode in the catalogue.
921
     *
922
     * @author David Nos (https://github.com/dnos)
923
     *
924
     * @param int    $userId     the id of the user
925
     * @param string $courseCode the course code
926
     * @param int    $visible    (optional) The course visibility in the catalogue to the user (1=visible, 0=invisible)
927
     *
928
     * @return bool true if removed succesfully or register not found, false otherwise
929
     */
930
    public static function removeUserVisibilityToCourseInCatalogue(
931
        $userId,
932
        $courseCode,
933
        $visible = 1
934
    ) {
935
        $courseUserTable = Database::get_main_table(TABLE_MAIN_COURSE_CATALOGUE_USER);
936
937
        if (empty($userId) || empty($courseCode) || ($userId != strval(intval($userId)))) {
938
            return false;
939
        }
940
941
        $courseCode = Database::escape_string($courseCode);
942
        $courseInfo = api_get_course_info($courseCode);
943
        $courseId = $courseInfo['real_id'];
944
945
        // Check whether the user has already been registered to the course visibility in the catalogue.
946
        $sql = "SELECT * FROM $courseUserTable
947
                WHERE
948
                    user_id = $userId AND
949
                    visible = $visible AND
950
                    c_id = $courseId";
951
        if (Database::num_rows(Database::query($sql)) > 0) {
952
            $cond = [
953
                'user_id = ? AND c_id = ? AND visible = ? ' => [
954
                    $userId,
955
                    $courseId,
956
                    $visible,
957
                ],
958
            ];
959
960
            return Database::delete($courseUserTable, $cond);
961
        } else {
962
            return true; // Register does not exist
963
        }
964
    }
965
966
    /**
967
     * @param string $code
968
     *
969
     * @return bool if there already are one or more courses
970
     *              with the same code OR visual_code (visualcode), false otherwise
971
     */
972
    public static function course_code_exists($code)
973
    {
974
        $code = Database::escape_string($code);
975
        $sql = "SELECT COUNT(*) as number
976
                FROM ".Database::get_main_table(TABLE_MAIN_COURSE)."
977
                WHERE code = '$code' OR visual_code = '$code'";
978
        $result = Database::fetch_array(Database::query($sql));
979
980
        return $result['number'] > 0;
981
    }
982
983
    /**
984
     * @param int    $user_id
985
     * @param string $startsWith Optional
986
     *
987
     * @return array an array with the course info of all the courses (real and virtual)
988
     *               of which the current user is course admin
989
     */
990
    public static function get_course_list_of_user_as_course_admin($user_id, $startsWith = '')
991
    {
992
        if ($user_id != strval(intval($user_id))) {
993
            return [];
994
        }
995
996
        // Definitions database tables and variables
997
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
998
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
999
        $user_id = intval($user_id);
1000
        $data = [];
1001
1002
        $sql = "SELECT
1003
                    course.code,
1004
                    course.title,
1005
                    course.id,
1006
                    course.id as real_id,
1007
                    course.category_code
1008
                FROM $tbl_course_user as course_rel_user
1009
                INNER JOIN $tbl_course as course
1010
                ON course.id = course_rel_user.c_id
1011
                WHERE
1012
                    course_rel_user.user_id = $user_id AND
1013
                    course_rel_user.status = 1
1014
        ";
1015
1016
        if (api_get_multiple_access_url()) {
1017
            $tbl_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
1018
            $access_url_id = api_get_current_access_url_id();
1019
            if ($access_url_id != -1) {
1020
                $sql = "
1021
                    SELECT
1022
                        course.code,
1023
                        course.title,
1024
                        course.id,
1025
                        course.id as real_id
1026
                    FROM $tbl_course_user as course_rel_user
1027
                    INNER JOIN $tbl_course as course
1028
                    ON course.id = course_rel_user.c_id
1029
                    INNER JOIN $tbl_course_rel_access_url course_rel_url
1030
                    ON (course_rel_url.c_id = course.id)
1031
                    WHERE
1032
                        access_url_id = $access_url_id  AND
1033
                        course_rel_user.user_id = $user_id AND
1034
                        course_rel_user.status = 1
1035
                ";
1036
            }
1037
        }
1038
1039
        if (!empty($startsWith)) {
1040
            $startsWith = Database::escape_string($startsWith);
1041
1042
            $sql .= " AND (course.title LIKE '$startsWith%' OR course.code LIKE '$startsWith%')";
1043
        }
1044
1045
        $sql .= ' ORDER BY course.title';
1046
1047
        $result_nb_cours = Database::query($sql);
1048
        if (Database::num_rows($result_nb_cours) > 0) {
1049
            while ($row = Database::fetch_array($result_nb_cours, 'ASSOC')) {
1050
                $data[$row['id']] = $row;
1051
            }
1052
        }
1053
1054
        return $data;
1055
    }
1056
1057
    /**
1058
     * @param int   $userId
1059
     * @param array $courseInfo
1060
     *
1061
     * @return bool|null
1062
     */
1063
    public static function isUserSubscribedInCourseAsDrh($userId, $courseInfo)
1064
    {
1065
        $userId = intval($userId);
1066
1067
        if (!api_is_drh()) {
1068
            return false;
1069
        }
1070
1071
        if (empty($courseInfo) || empty($userId)) {
1072
            return false;
1073
        }
1074
1075
        $courseId = intval($courseInfo['real_id']);
1076
        $table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1077
1078
        $sql = "SELECT * FROM $table
1079
                WHERE
1080
                    user_id = $userId AND
1081
                    relation_type = ".COURSE_RELATION_TYPE_RRHH." AND
1082
                    c_id = $courseId";
1083
1084
        $result = Database::fetch_array(Database::query($sql));
1085
1086
        if (!empty($result)) {
1087
            // The user has been registered in this course.
1088
            return true;
1089
        }
1090
    }
1091
1092
    /**
1093
     * Check if user is subscribed inside a course.
1094
     *
1095
     * @param int    $user_id
1096
     * @param string $course_code  , if this parameter is null, it'll check for all courses
1097
     * @param bool   $in_a_session True for checking inside sessions too, by default is not checked
1098
     *
1099
     * @return bool $session_id true if the user is registered in the course, false otherwise
1100
     */
1101
    public static function is_user_subscribed_in_course(
1102
        $user_id,
1103
        $course_code = null,
1104
        $in_a_session = false,
1105
        $session_id = 0
1106
    ) {
1107
        $user_id = intval($user_id);
1108
1109
        if (empty($session_id)) {
1110
            $session_id = api_get_session_id();
1111
        } else {
1112
            $session_id = intval($session_id);
1113
        }
1114
1115
        $condition_course = '';
1116
        if (isset($course_code)) {
1117
            $courseInfo = api_get_course_info($course_code);
1118
            if (empty($courseInfo)) {
1119
                return false;
1120
            }
1121
            $courseId = $courseInfo['real_id'];
1122
            $condition_course = ' AND c_id = '.$courseId;
1123
        }
1124
1125
        $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
1126
                WHERE
1127
                    user_id = $user_id AND
1128
                    relation_type<>".COURSE_RELATION_TYPE_RRHH."
1129
                    $condition_course ";
1130
1131
        $result = Database::fetch_array(Database::query($sql));
1132
1133
        if (!empty($result)) {
1134
            // The user has been registered in this course.
1135
            return true;
1136
        }
1137
1138
        if (!$in_a_session) {
1139
            // The user has not been registered in this course.
1140
            return false;
1141
        }
1142
1143
        $tableSessionCourseUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
1144
        $sql = 'SELECT 1 FROM '.$tableSessionCourseUser.
1145
            ' WHERE user_id = '.$user_id.' '.$condition_course;
1146
        if (Database::num_rows(Database::query($sql)) > 0) {
1147
            return true;
1148
        }
1149
1150
        $sql = 'SELECT 1 FROM '.$tableSessionCourseUser.' WHERE user_id = '.$user_id.' AND status = 2 '.$condition_course;
1151
        if (Database::num_rows(Database::query($sql)) > 0) {
1152
            return true;
1153
        }
1154
1155
        $sql = 'SELECT 1 FROM '.Database::get_main_table(TABLE_MAIN_SESSION).
1156
            ' WHERE id = '.$session_id.' AND id_coach='.$user_id;
1157
1158
        if (Database::num_rows(Database::query($sql)) > 0) {
1159
            return true;
1160
        }
1161
1162
        return false;
1163
    }
1164
1165
    /**
1166
     * Is the user a teacher in the given course?
1167
     *
1168
     * @param int    $user_id     , the id (int) of the user
1169
     * @param string $course_code , the course code
1170
     *
1171
     * @return bool if the user is a teacher in the course, false otherwise
1172
     */
1173
    public static function is_course_teacher($user_id, $course_code)
1174
    {
1175
        if ($user_id != strval(intval($user_id))) {
1176
            return false;
1177
        }
1178
1179
        $courseInfo = api_get_course_info($course_code);
1180
        if (empty($courseInfo)) {
1181
            return false;
1182
        }
1183
        $courseId = $courseInfo['real_id'];
1184
        $sql = "SELECT status FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
1185
                WHERE c_id = $courseId AND user_id = $user_id ";
1186
        $result = Database::query($sql);
1187
1188
        if (Database::num_rows($result) > 0) {
1189
            return Database::result($result, 0, 'status') == 1;
1190
        }
1191
1192
        return false;
1193
    }
1194
1195
    /**
1196
     *    Is the user subscribed in the real course or linked courses?
1197
     *
1198
     * @param int the id of the user
1199
     * @param int $courseId
1200
     *
1201
     * @deprecated linked_courses definition doesn't exists
1202
     *
1203
     * @return bool if the user is registered in the real course or linked courses, false otherwise
1204
     */
1205
    public static function is_user_subscribed_in_real_or_linked_course($user_id, $courseId, $session_id = 0)
1206
    {
1207
        if ($user_id != strval(intval($user_id))) {
1208
            return false;
1209
        }
1210
1211
        $courseId = intval($courseId);
1212
        $session_id = intval($session_id);
1213
1214
        if (empty($session_id)) {
1215
            $result = Database::fetch_array(
1216
                Database::query(
1217
                    "SELECT *
1218
                    FROM ".Database::get_main_table(TABLE_MAIN_COURSE)." course
1219
                    LEFT JOIN ".Database::get_main_table(TABLE_MAIN_COURSE_USER)." course_user
1220
                    ON course.id = course_user.c_id
1221
                    WHERE
1222
                        course_user.user_id = $user_id AND
1223
                        course_user.relation_type<>".COURSE_RELATION_TYPE_RRHH." AND
1224
                        ( course.id = $courseId)"
1225
                )
1226
            );
1227
1228
            return !empty($result);
1229
        }
1230
1231
        // From here we trust session id.
1232
        // Is he/she subscribed to the session's course?
1233
        // A user?
1234
        if (Database::num_rows(Database::query("SELECT user_id
1235
                FROM ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)."
1236
                WHERE session_id = $session_id
1237
                AND user_id = $user_id"))
1238
        ) {
1239
            return true;
1240
        }
1241
1242
        // A course coach?
1243
        if (Database::num_rows(Database::query("SELECT user_id
1244
                FROM ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)."
1245
                WHERE session_id = $session_id
1246
                AND user_id = $user_id AND status = 2
1247
                AND c_id = $courseId"))
1248
        ) {
1249
            return true;
1250
        }
1251
1252
        // A session coach?
1253
        if (Database::num_rows(Database::query("SELECT id_coach
1254
                FROM ".Database::get_main_table(TABLE_MAIN_SESSION)." AS session
1255
                WHERE session.id = $session_id
1256
                AND id_coach = $user_id"))
1257
        ) {
1258
            return true;
1259
        }
1260
1261
        return false;
1262
    }
1263
1264
    /**
1265
     * Return user info array of all users registered in a course
1266
     * This only returns the users that are registered in this actual course, not linked courses.
1267
     *
1268
     * @param string    $course_code
1269
     * @param int       $session_id
1270
     * @param string    $limit
1271
     * @param string    $order_by         the field to order the users by.
1272
     *                                    Valid values are 'lastname', 'firstname', 'username', 'email', 'official_code' OR a part of a SQL statement
1273
     *                                    that starts with ORDER BY ...
1274
     * @param int|null  $filter_by_status if using the session_id: 0 or 2 (student, coach),
1275
     *                                    if using session_id = 0 STUDENT or COURSEMANAGER
1276
     * @param bool|null $return_count
1277
     * @param bool      $add_reports
1278
     * @param bool      $resumed_report
1279
     * @param array     $extra_field
1280
     * @param array     $courseCodeList
1281
     * @param array     $userIdList
1282
     * @param string    $filterByActive
1283
     * @param array     $sessionIdList
1284
     *
1285
     * @return array|int
1286
     */
1287
    public static function get_user_list_from_course_code(
1288
        $course_code = null,
1289
        $session_id = 0,
1290
        $limit = null,
1291
        $order_by = null,
1292
        $filter_by_status = null,
1293
        $return_count = null,
1294
        $add_reports = false,
1295
        $resumed_report = false,
1296
        $extra_field = [],
1297
        $courseCodeList = [],
1298
        $userIdList = [],
1299
        $filterByActive = null,
1300
        $sessionIdList = []
1301
    ) {
1302
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1303
        $sessionTable = Database::get_main_table(TABLE_MAIN_SESSION);
1304
1305
        $session_id = intval($session_id);
1306
        $course_code = Database::escape_string($course_code);
1307
        $courseInfo = api_get_course_info($course_code);
1308
        $courseId = 0;
1309
        if (!empty($courseInfo)) {
1310
            $courseId = $courseInfo['real_id'];
1311
        }
1312
1313
        $where = [];
1314
        if (empty($order_by)) {
1315
            $order_by = 'user.lastname, user.firstname';
1316
            if (api_is_western_name_order()) {
1317
                $order_by = 'user.firstname, user.lastname';
1318
            }
1319
        }
1320
1321
        // if the $order_by does not contain 'ORDER BY'
1322
        // we have to check if it is a valid field that can be sorted on
1323
        if (!strstr($order_by, 'ORDER BY')) {
1324
            if (!empty($order_by)) {
1325
                $order_by = 'ORDER BY '.$order_by;
1326
            } else {
1327
                $order_by = '';
1328
            }
1329
        }
1330
1331
        $filter_by_status_condition = null;
1332
1333
        if (!empty($session_id) || !empty($sessionIdList)) {
1334
            $sql = 'SELECT DISTINCT
1335
                        user.user_id,
1336
                        user.email,
1337
                        session_course_user.status as status_session,
1338
                        session_id,
1339
                        user.*,
1340
                        course.*,
1341
                        session.name as session_name
1342
                    ';
1343
            if ($return_count) {
1344
                $sql = " SELECT COUNT(user.user_id) as count";
1345
            }
1346
1347
            $sessionCondition = " session_course_user.session_id = $session_id";
1348
            if (!empty($sessionIdList)) {
1349
                $sessionIdListTostring = implode("','", array_map('intval', $sessionIdList));
1350
                $sessionCondition = " session_course_user.session_id IN ('$sessionIdListTostring') ";
1351
            }
1352
1353
            $courseCondition = " course.id = $courseId";
1354
            if (!empty($courseCodeList)) {
1355
                $courseCodeListForSession = array_map(['Database', 'escape_string'], $courseCodeList);
1356
                $courseCodeListForSession = implode('","', $courseCodeListForSession);
1357
                $courseCondition = ' course.code IN ("'.$courseCodeListForSession.'")  ';
1358
            }
1359
1360
            $sql .= ' FROM '.Database::get_main_table(TABLE_MAIN_USER).' as user ';
1361
            $sql .= " LEFT JOIN ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)." as session_course_user
1362
                      ON
1363
                        user.id = session_course_user.user_id AND
1364
                        $sessionCondition
1365
                        INNER JOIN $course_table course 
1366
                        ON session_course_user.c_id = course.id AND
1367
                        $courseCondition
1368
                        INNER JOIN $sessionTable session 
1369
                        ON session_course_user.session_id = session.id
1370
                   ";
1371
            $where[] = ' session_course_user.c_id IS NOT NULL ';
1372
1373
            // 2 = coach
1374
            // 0 = student
1375
            if (isset($filter_by_status)) {
1376
                $filter_by_status = intval($filter_by_status);
1377
                $filter_by_status_condition = " session_course_user.status = $filter_by_status AND ";
1378
            }
1379
        } else {
1380
            if ($return_count) {
1381
                $sql = " SELECT COUNT(*) as count";
1382
            } else {
1383
                if (empty($course_code)) {
1384
                    $sql = 'SELECT DISTINCT
1385
                                course.title,
1386
                                course.code,
1387
                                course_rel_user.status as status_rel,
1388
                                user.id as user_id,
1389
                                user.email,
1390
                                course_rel_user.is_tutor,
1391
                                user.*  ';
1392
                } else {
1393
                    $sql = 'SELECT DISTINCT
1394
                                course_rel_user.status as status_rel,
1395
                                user.id as user_id,
1396
                                user.email,
1397
                                course_rel_user.is_tutor,
1398
                                user.*  ';
1399
                }
1400
            }
1401
1402
            $sql .= ' FROM '.Database::get_main_table(TABLE_MAIN_USER).' as user '
1403
                  .' LEFT JOIN '.Database::get_main_table(TABLE_MAIN_COURSE_USER).' as course_rel_user
1404
                      ON 
1405
                        user.id = course_rel_user.user_id AND
1406
                        course_rel_user.relation_type <> '.COURSE_RELATION_TYPE_RRHH.'  '
1407
                  ." INNER JOIN $course_table course ON course_rel_user.c_id = course.id ";
1408
1409
            if (!empty($course_code)) {
1410
                $sql .= ' AND course_rel_user.c_id = "'.$courseId.'"';
1411
            }
1412
            $where[] = ' course_rel_user.c_id IS NOT NULL ';
1413
1414
            if (isset($filter_by_status) && is_numeric($filter_by_status)) {
1415
                $filter_by_status = intval($filter_by_status);
1416
                $filter_by_status_condition = " course_rel_user.status = $filter_by_status AND ";
1417
            }
1418
        }
1419
1420
        $multiple_access_url = api_get_multiple_access_url();
1421
        if ($multiple_access_url) {
1422
            $sql .= ' LEFT JOIN '.Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER).' au
1423
                      ON (au.user_id = user.id) ';
1424
        }
1425
1426
        $extraFieldWasAdded = false;
1427
        if ($return_count && $resumed_report) {
1428
            foreach ($extra_field as $extraField) {
1429
                $extraFieldInfo = UserManager::get_extra_field_information_by_name($extraField);
1430
                if (!empty($extraFieldInfo)) {
1431
                    $fieldValuesTable = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
1432
                    $sql .= ' LEFT JOIN '.$fieldValuesTable.' as ufv
1433
                            ON (
1434
                                user.id = ufv.item_id AND
1435
                                (field_id = '.$extraFieldInfo['id'].' OR field_id IS NULL)
1436
                            )';
1437
                    $extraFieldWasAdded = true;
1438
                }
1439
            }
1440
        }
1441
1442
        $sql .= ' WHERE '.$filter_by_status_condition.' '.implode(' OR ', $where);
1443
1444
        if ($multiple_access_url) {
1445
            $current_access_url_id = api_get_current_access_url_id();
1446
            $sql .= " AND (access_url_id =  $current_access_url_id ) ";
1447
        }
1448
1449
        if ($return_count && $resumed_report && $extraFieldWasAdded) {
1450
            $sql .= ' AND field_id IS NOT NULL GROUP BY value ';
1451
        }
1452
1453
        if (!empty($courseCodeList)) {
1454
            $courseCodeList = array_map(['Database', 'escape_string'], $courseCodeList);
1455
            $courseCodeList = implode('","', $courseCodeList);
1456
            if (empty($sessionIdList)) {
1457
                $sql .= ' AND course.code IN ("'.$courseCodeList.'")';
1458
            }
1459
        }
1460
1461
        if (!empty($userIdList)) {
1462
            $userIdList = array_map('intval', $userIdList);
1463
            $userIdList = implode('","', $userIdList);
1464
            $sql .= ' AND user.id IN ("'.$userIdList.'")';
1465
        }
1466
1467
        if (isset($filterByActive)) {
1468
            $filterByActive = intval($filterByActive);
1469
            $sql .= ' AND user.active = '.$filterByActive;
1470
        }
1471
1472
        $sql .= ' '.$order_by.' '.$limit;
1473
1474
        $rs = Database::query($sql);
1475
        $users = [];
1476
1477
        $extra_fields = UserManager::get_extra_fields(
1478
            0,
1479
            100,
1480
            null,
1481
            null,
1482
            true,
1483
            true
1484
        );
1485
1486
        $counter = 1;
1487
        $count_rows = Database::num_rows($rs);
1488
1489
        if ($return_count && $resumed_report) {
1490
            return $count_rows;
1491
        }
1492
1493
        $table_user_field_value = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
1494
        $tableExtraField = Database::get_main_table(TABLE_EXTRA_FIELD);
1495
        if ($count_rows) {
1496
            while ($user = Database::fetch_array($rs)) {
1497
                if ($return_count) {
1498
                    return $user['count'];
1499
                }
1500
                $report_info = [];
1501
                $user_info = $user;
1502
                $user_info['status'] = $user['status'];
1503
                if (isset($user['is_tutor'])) {
1504
                    $user_info['is_tutor'] = $user['is_tutor'];
1505
                }
1506
                if (!empty($session_id)) {
1507
                    $user_info['status_session'] = $user['status_session'];
1508
                }
1509
1510
                $sessionId = isset($user['session_id']) ? $user['session_id'] : 0;
1511
                $course_code = isset($user['code']) ? $user['code'] : null;
1512
1513
                if ($add_reports) {
1514
                    if ($resumed_report) {
1515
                        $extra = [];
1516
1517
                        if (!empty($extra_fields)) {
1518
                            foreach ($extra_fields as $extra) {
1519
                                if (in_array($extra['1'], $extra_field)) {
1520
                                    $user_data = UserManager::get_extra_user_data_by_field(
1521
                                        $user['user_id'],
1522
                                        $extra['1']
1523
                                    );
1524
                                    break;
1525
                                }
1526
                            }
1527
                        }
1528
1529
                        $row_key = '-1';
1530
                        $name = '-';
1531
1532
                        if (!empty($extra)) {
1533
                            if (!empty($user_data[$extra['1']])) {
1534
                                $row_key = $user_data[$extra['1']];
1535
                                $name = $user_data[$extra['1']];
1536
                                $users[$row_key]['extra_'.$extra['1']] = $name;
1537
                            }
1538
                        }
1539
1540
                        $users[$row_key]['training_hours'] += Tracking::get_time_spent_on_the_course(
1541
                            $user['user_id'],
1542
                            $courseId,
1543
                            $sessionId
1544
                        );
1545
1546
                        $users[$row_key]['count_users'] += $counter;
1547
1548
                        $registered_users_with_extra_field = self::getCountRegisteredUsersWithCourseExtraField(
1549
                            $name,
1550
                            $tableExtraField,
1551
                            $table_user_field_value
1552
                        );
1553
1554
                        $users[$row_key]['count_users_registered'] = $registered_users_with_extra_field;
1555
                        $users[$row_key]['average_hours_per_user'] = $users[$row_key]['training_hours'] / $users[$row_key]['count_users'];
1556
1557
                        $category = Category:: load(
1558
                            null,
1559
                            null,
1560
                            $course_code,
1561
                            null,
1562
                            null,
1563
                            $sessionId
1564
                        );
1565
1566
                        if (!isset($users[$row_key]['count_certificates'])) {
1567
                            $users[$row_key]['count_certificates'] = 0;
1568
                        }
1569
1570
                        if (isset($category[0]) && $category[0]->is_certificate_available($user['user_id'])) {
1571
                            $users[$row_key]['count_certificates']++;
1572
                        }
1573
1574
                        foreach ($extra_fields as $extra) {
1575
                            if ($extra['1'] == 'ruc') {
1576
                                continue;
1577
                            }
1578
1579
                            if (!isset($users[$row_key][$extra['1']])) {
1580
                                $user_data = UserManager::get_extra_user_data_by_field($user['user_id'], $extra['1']);
1581
                                if (!empty($user_data[$extra['1']])) {
1582
                                    $users[$row_key][$extra['1']] = $user_data[$extra['1']];
1583
                                }
1584
                            }
1585
                        }
1586
                    } else {
1587
                        $sessionName = !empty($sessionId) ? ' - '.$user['session_name'] : '';
1588
                        $report_info['course'] = $user['title'].$sessionName;
1589
                        $report_info['user'] = api_get_person_name($user['firstname'], $user['lastname']);
1590
                        $report_info['email'] = $user['email'];
1591
                        $report_info['time'] = api_time_to_hms(
1592
                            Tracking::get_time_spent_on_the_course(
1593
                                $user['user_id'],
1594
                                $courseId,
1595
                                $sessionId
1596
                            )
1597
                        );
1598
1599
                        $category = Category:: load(
1600
                            null,
1601
                            null,
1602
                            $course_code,
1603
                            null,
1604
                            null,
1605
                            $sessionId
1606
                        );
1607
1608
                        $report_info['certificate'] = Display::label(get_lang('No'));
1609
                        if (isset($category[0]) && $category[0]->is_certificate_available($user['user_id'])) {
1610
                            $report_info['certificate'] = Display::label(get_lang('Yes'), 'success');
1611
                        }
1612
1613
                        $progress = intval(
1614
                            Tracking::get_avg_student_progress(
1615
                                $user['user_id'],
1616
                                $course_code,
1617
                                [],
1618
                                $sessionId
1619
                            )
1620
                        );
1621
                        $report_info['progress_100'] = $progress == 100 ? Display::label(get_lang('Yes'), 'success') : Display::label(get_lang('No'));
1622
                        $report_info['progress'] = $progress."%";
1623
1624
                        foreach ($extra_fields as $extra) {
1625
                            $user_data = UserManager::get_extra_user_data_by_field($user['user_id'], $extra['1']);
1626
                            $report_info[$extra['1']] = $user_data[$extra['1']];
1627
                        }
1628
                        $report_info['user_id'] = $user['user_id'];
1629
                        $users[] = $report_info;
1630
                    }
1631
                } else {
1632
                    $users[$user['user_id']] = $user_info;
1633
                }
1634
            }
1635
        }
1636
1637
        return $users;
1638
    }
1639
1640
    /**
1641
     * @param bool  $resumed_report
1642
     * @param array $extra_field
1643
     * @param array $courseCodeList
1644
     * @param array $userIdList
1645
     * @param array $sessionIdList
1646
     *
1647
     * @return array|int
1648
     */
1649
    public static function get_count_user_list_from_course_code(
1650
        $resumed_report = false,
1651
        $extra_field = [],
1652
        $courseCodeList = [],
1653
        $userIdList = [],
1654
        $sessionIdList = []
1655
    ) {
1656
        return self::get_user_list_from_course_code(
1657
            null,
1658
            0,
1659
            null,
1660
            null,
1661
            null,
1662
            true,
1663
            false,
1664
            $resumed_report,
1665
            $extra_field,
1666
            $courseCodeList,
1667
            $userIdList,
1668
            null,
1669
            $sessionIdList
1670
        );
1671
    }
1672
1673
    /**
1674
     * Gets subscribed users in a course or in a course/session.
1675
     *
1676
     * @param string $course_code
1677
     * @param int    $session_id
1678
     *
1679
     * @return int
1680
     */
1681
    public static function get_users_count_in_course(
1682
        $course_code,
1683
        $session_id = 0,
1684
        $status = null
1685
    ) {
1686
        // variable initialisation
1687
        $session_id = intval($session_id);
1688
        $course_code = Database::escape_string($course_code);
1689
        $tblUser = Database::get_main_table(TABLE_MAIN_USER);
1690
        $tblSessionCourseUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
1691
        $tblCourseUser = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1692
        $tblUrlUser = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
1693
1694
        $courseInfo = api_get_course_info($course_code);
1695
        $courseId = $courseInfo['real_id'];
1696
1697
        $sql = "
1698
            SELECT DISTINCT count(user.id) as count  
1699
            FROM $tblUser as user
1700
        ";
1701
        $where = [];
1702
        if (!empty($session_id)) {
1703
            $sql .= "
1704
                LEFT JOIN $tblSessionCourseUser as session_course_user
1705
                    ON user.user_id = session_course_user.user_id
1706
                    AND session_course_user.c_id = $courseId
1707
                    AND session_course_user.session_id = $session_id
1708
            ";
1709
1710
            $where[] = ' session_course_user.c_id IS NOT NULL ';
1711
        } else {
1712
            $sql .= "
1713
                LEFT JOIN $tblCourseUser as course_rel_user
1714
                    ON user.user_id = course_rel_user.user_id
1715
                    AND course_rel_user.relation_type <> ".COURSE_RELATION_TYPE_RRHH."
1716
                    AND course_rel_user.c_id = $courseId
1717
            ";
1718
            $where[] = ' course_rel_user.c_id IS NOT NULL ';
1719
        }
1720
1721
        $multiple_access_url = api_get_multiple_access_url();
1722
        if ($multiple_access_url) {
1723
            $sql .= " LEFT JOIN $tblUrlUser au ON (au.user_id = user.user_id) ";
1724
        }
1725
1726
        $sql .= ' WHERE '.implode(' OR ', $where);
1727
1728
        if ($multiple_access_url) {
1729
            $current_access_url_id = api_get_current_access_url_id();
1730
            $sql .= " AND (access_url_id =  $current_access_url_id ) ";
1731
        }
1732
        $rs = Database::query($sql);
1733
        $count = 0;
1734
        if (Database::num_rows($rs)) {
1735
            $user = Database::fetch_array($rs);
1736
            $count = $user['count'];
1737
        }
1738
1739
        return $count;
1740
    }
1741
1742
    /**
1743
     * Get a list of coaches of a course and a session.
1744
     *
1745
     * @param string $course_code
1746
     * @param int    $session_id
1747
     * @param bool   $addGeneralCoach
1748
     *
1749
     * @return array List of users
1750
     */
1751
    public static function get_coach_list_from_course_code(
1752
        $course_code,
1753
        $session_id,
1754
        $addGeneralCoach = true
1755
    ) {
1756
        if (empty($course_code) || empty($session_id)) {
1757
            return [];
1758
        }
1759
1760
        $course_code = Database::escape_string($course_code);
1761
        $courseInfo = api_get_course_info($course_code);
1762
        $courseId = $courseInfo['real_id'];
1763
        $session_id = intval($session_id);
1764
        $users = [];
1765
1766
        // We get the coach for the given course in a given session.
1767
        $sql = 'SELECT user_id FROM '.Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER).
1768
               ' WHERE session_id = '.$session_id.' AND c_id = '.$courseId.' AND status = 2';
1769
        $rs = Database::query($sql);
1770
        while ($user = Database::fetch_array($rs)) {
1771
            $userInfo = api_get_user_info($user['user_id']);
1772
            if ($userInfo) {
1773
                $users[$user['user_id']] = $userInfo;
1774
            }
1775
        }
1776
1777
        if ($addGeneralCoach) {
1778
            $table = Database::get_main_table(TABLE_MAIN_SESSION);
1779
            // We get the session coach.
1780
            $sql = "SELECT id_coach FROM $table WHERE id = $session_id";
1781
            $rs = Database::query($sql);
1782
            $session_id_coach = Database::result($rs, 0, 'id_coach');
1783
            if (is_int($session_id_coach)) {
1784
                $userInfo = api_get_user_info($session_id_coach);
1785
                if ($userInfo) {
1786
                    $users[$session_id_coach] = $userInfo;
1787
                }
1788
            }
1789
        }
1790
1791
        return $users;
1792
    }
1793
1794
    /**
1795
     *  Return user info array of all users registered in a course
1796
     *  This only returns the users that are registered in this actual course, not linked courses.
1797
     *
1798
     * @param string $course_code
1799
     * @param bool   $with_session
1800
     * @param int    $session_id
1801
     * @param string $date_from
1802
     * @param string $date_to
1803
     * @param bool   $includeInvitedUsers Whether include the invited users
1804
     * @param int    $groupId
1805
     *
1806
     * @return array with user id
1807
     */
1808
    public static function get_student_list_from_course_code(
1809
        $course_code,
1810
        $with_session = false,
1811
        $session_id = 0,
1812
        $date_from = null,
1813
        $date_to = null,
1814
        $includeInvitedUsers = true,
1815
        $groupId = 0
1816
    ) {
1817
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
1818
        $session_id = intval($session_id);
1819
        $course_code = Database::escape_string($course_code);
1820
        $courseInfo = api_get_course_info($course_code);
1821
        $courseId = $courseInfo['real_id'];
1822
        $students = [];
1823
1824
        if ($session_id == 0) {
1825
            if (empty($groupId)) {
1826
                // students directly subscribed to the course
1827
                $sql = "SELECT *
1828
                        FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)." cu
1829
                        INNER JOIN $userTable u
1830
                        ON cu.user_id = u.user_id
1831
                        WHERE c_id = '$courseId' AND cu.status = ".STUDENT;
1832
1833
                if (!$includeInvitedUsers) {
1834
                    $sql .= " AND u.status != ".INVITEE;
1835
                }
1836
                $rs = Database::query($sql);
1837
                while ($student = Database::fetch_array($rs)) {
1838
                    $students[$student['user_id']] = $student;
1839
                }
1840
            } else {
1841
                $students = GroupManager::get_users(
1842
                    $groupId,
1843
                    false,
1844
                    null,
1845
                    null,
1846
                    false,
1847
                    $courseInfo['real_id']
1848
                );
1849
                $students = array_flip($students);
1850
            }
1851
        }
1852
1853
        // students subscribed to the course through a session
1854
        if ($with_session) {
1855
            $joinSession = '';
1856
            //Session creation date
1857
            if (!empty($date_from) && !empty($date_to)) {
1858
                $joinSession = "INNER JOIN ".Database::get_main_table(TABLE_MAIN_SESSION)." s";
1859
            }
1860
1861
            $sql_query = "SELECT *
1862
                          FROM ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)." scu
1863
                          $joinSession
1864
                          INNER JOIN $userTable u ON scu.user_id = u.user_id
1865
                          WHERE scu.c_id = $courseId AND scu.status <> 2";
1866
1867
            if (!empty($date_from) && !empty($date_to)) {
1868
                $date_from = Database::escape_string($date_from);
1869
                $date_to = Database::escape_string($date_to);
1870
                $sql_query .= " AND s.access_start_date >= '$date_from' AND s.access_end_date <= '$date_to'";
1871
            }
1872
1873
            if ($session_id != 0) {
1874
                $sql_query .= ' AND scu.session_id = '.$session_id;
1875
            }
1876
1877
            if (!$includeInvitedUsers) {
1878
                $sql_query .= " AND u.status != ".INVITEE;
1879
            }
1880
1881
            $rs = Database::query($sql_query);
1882
            while ($student = Database::fetch_array($rs)) {
1883
                $students[$student['user_id']] = $student;
1884
            }
1885
        }
1886
1887
        return $students;
1888
    }
1889
1890
    /**
1891
     * Return user info array of all teacher-users registered in a course
1892
     * This only returns the users that are registered in this actual course, not linked courses.
1893
     *
1894
     * @param string $course_code
1895
     *
1896
     * @return array with user id
1897
     */
1898
    public static function get_teacher_list_from_course_code($course_code)
1899
    {
1900
        $courseInfo = api_get_course_info($course_code);
1901
        $courseId = $courseInfo['real_id'];
1902
        if (empty($courseId)) {
1903
            return false;
1904
        }
1905
1906
        $sql = "SELECT DISTINCT
1907
                    u.id as user_id,
1908
                    u.lastname,
1909
                    u.firstname,
1910
                    u.email,
1911
                    u.username,
1912
                    u.status
1913
                FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)." cu
1914
                INNER JOIN ".Database::get_main_table(TABLE_MAIN_USER)." u
1915
                ON (cu.user_id = u.id)
1916
                WHERE
1917
                    cu.c_id = $courseId AND
1918
                    cu.status = 1 ";
1919
        $rs = Database::query($sql);
1920
        $teachers = [];
1921
        while ($teacher = Database::fetch_array($rs)) {
1922
            $teachers[$teacher['user_id']] = $teacher;
1923
        }
1924
1925
        return $teachers;
1926
    }
1927
1928
    /**
1929
     * Return user info array of all teacher-users registered in a course
1930
     * This only returns the users that are registered in this actual course, not linked courses.
1931
     *
1932
     * @param int  $courseId
1933
     * @param bool $loadAvatars
1934
     *
1935
     * @return array with user id
1936
     */
1937
    public static function getTeachersFromCourse($courseId, $loadAvatars = true)
1938
    {
1939
        $courseId = (int) $courseId;
1940
1941
        if (empty($courseId)) {
1942
            return false;
1943
        }
1944
1945
        $sql = "SELECT DISTINCT
1946
                    u.id as user_id,
1947
                    u.lastname,
1948
                    u.firstname,
1949
                    u.email,
1950
                    u.username,
1951
                    u.status
1952
                FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)." cu
1953
                INNER JOIN ".Database::get_main_table(TABLE_MAIN_USER)." u
1954
                ON (cu.user_id = u.id)
1955
                WHERE
1956
                    cu.c_id = $courseId AND
1957
                    cu.status = 1 ";
1958
        $rs = Database::query($sql);
1959
        $listTeachers = [];
1960
        $teachers = [];
1961
        $url = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&course_id='.$courseId;
1962
        while ($teacher = Database::fetch_array($rs)) {
1963
            $teachers['id'] = $teacher['user_id'];
1964
            $teachers['lastname'] = $teacher['lastname'];
1965
            $teachers['firstname'] = $teacher['firstname'];
1966
            $teachers['email'] = $teacher['email'];
1967
            $teachers['username'] = $teacher['username'];
1968
            $teachers['status'] = $teacher['status'];
1969
            $teachers['fullname'] = api_get_person_name($teacher['firstname'], $teacher['lastname']);
1970
            $teachers['avatar'] = '';
1971
            if ($loadAvatars) {
1972
                $userPicture = UserManager::getUserPicture($teacher['user_id'], USER_IMAGE_SIZE_SMALL);
1973
                $teachers['avatar'] = $userPicture;
1974
            }
1975
            $teachers['url'] = $url.'&user_id='.$teacher['user_id'];
1976
            $listTeachers[] = $teachers;
1977
        }
1978
1979
        return $listTeachers;
1980
    }
1981
1982
    /**
1983
     * Returns a string list of teachers assigned to the given course.
1984
     *
1985
     * @param string $course_code
1986
     * @param string $separator           between teachers names
1987
     * @param bool   $add_link_to_profile Whether to add a link to the teacher's profile
1988
     * @param bool   $orderList
1989
     *
1990
     * @return string List of teachers teaching the course
1991
     */
1992
    public static function getTeacherListFromCourseCodeToString(
1993
        $course_code,
1994
        $separator = self::USER_SEPARATOR,
1995
        $add_link_to_profile = false,
1996
        $orderList = false
1997
    ) {
1998
        $teacher_list = self::get_teacher_list_from_course_code($course_code);
1999
        $html = '';
2000
        $list = [];
2001
        if (!empty($teacher_list)) {
2002
            foreach ($teacher_list as $teacher) {
2003
                $teacher_name = api_get_person_name(
2004
                    $teacher['firstname'],
2005
                    $teacher['lastname']
2006
                );
2007
                if ($add_link_to_profile) {
2008
                    $url = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&user_id='.$teacher['user_id'];
2009
                    $teacher_name = Display::url(
2010
                        $teacher_name,
2011
                        $url,
2012
                        [
2013
                            'class' => 'ajax',
2014
                            'data-title' => $teacher_name,
2015
                        ]
2016
                    );
2017
                }
2018
                $list[] = $teacher_name;
2019
            }
2020
2021
            if (!empty($list)) {
2022
                if ($orderList === true) {
2023
                    $html .= '<ul class="user-teacher">';
2024
                    foreach ($list as $teacher) {
2025
                        $html .= '<li>';
2026
                        $html .= Display::return_icon('teacher.png', '', null, ICON_SIZE_TINY);
2027
                        $html .= ' '.$teacher;
2028
                        $html .= '</li>';
2029
                    }
2030
                    $html .= '</ul>';
2031
                } else {
2032
                    $html .= array_to_string($list, $separator);
2033
                }
2034
            }
2035
        }
2036
2037
        return $html;
2038
    }
2039
2040
    /**
2041
     * This function returns information about coachs from a course in session.
2042
     *
2043
     * @param int $session_id
2044
     * @param int $courseId
2045
     *
2046
     * @return array containing user_id, lastname, firstname, username
2047
     */
2048
    public static function get_coachs_from_course($session_id = 0, $courseId = 0)
2049
    {
2050
        if (!empty($session_id)) {
2051
            $session_id = intval($session_id);
2052
        } else {
2053
            $session_id = api_get_session_id();
2054
        }
2055
2056
        if (!empty($courseId)) {
2057
            $courseId = intval($courseId);
2058
        } else {
2059
            $courseId = api_get_course_int_id();
2060
        }
2061
2062
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
2063
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2064
2065
        $sql = "SELECT DISTINCT 
2066
                    u.user_id,
2067
                    u.lastname,
2068
                    u.firstname,
2069
                    u.username
2070
                FROM $tbl_user u 
2071
                INNER JOIN $tbl_session_course_user scu
2072
                ON (u.user_id = scu.user_id)
2073
                WHERE
2074
                    scu.session_id = $session_id AND
2075
                    scu.c_id = $courseId AND
2076
                    scu.status = 2";
2077
        $rs = Database::query($sql);
2078
2079
        $coaches = [];
2080
        if (Database::num_rows($rs) > 0) {
2081
            while ($row = Database::fetch_array($rs)) {
2082
                $completeName = api_get_person_name($row['firstname'], $row['lastname']);
2083
                $coaches[] = $row + ['full_name' => $completeName];
2084
            }
2085
        }
2086
2087
        return $coaches;
2088
    }
2089
2090
    /**
2091
     * @param int    $session_id
2092
     * @param int    $courseId
2093
     * @param string $separator
2094
     * @param bool   $add_link_to_profile
2095
     * @param bool   $orderList
2096
     *
2097
     * @return string
2098
     */
2099
    public static function get_coachs_from_course_to_string(
2100
        $session_id = 0,
2101
        $courseId = 0,
2102
        $separator = self::USER_SEPARATOR,
2103
        $add_link_to_profile = false,
2104
        $orderList = false
2105
    ) {
2106
        $coachList = self::get_coachs_from_course($session_id, $courseId);
2107
        $course_coachs = [];
2108
        if (!empty($coachList)) {
2109
            foreach ($coachList as $coach_course) {
2110
                $coach_name = $coach_course['full_name'];
2111
                if ($add_link_to_profile) {
2112
                    $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;
2113
                    $coach_name = Display::url(
2114
                        $coach_name,
2115
                        $url,
2116
                        [
2117
                            'class' => 'ajax',
2118
                            'data-title' => $coach_name,
2119
                        ]
2120
                    );
2121
                }
2122
                $course_coachs[] = $coach_name;
2123
            }
2124
        }
2125
2126
        $html = '';
2127
        if (!empty($course_coachs)) {
2128
            if ($orderList === true) {
2129
                $html .= '<ul class="user-coachs">';
2130
                foreach ($course_coachs as $coachs) {
2131
                    $html .= Display::tag(
2132
                        'li',
2133
                        Display::return_icon(
2134
                            'teacher.png',
2135
                            get_lang('Coach'),
2136
                            null,
2137
                            ICON_SIZE_TINY
2138
                        ).' '.$coachs
2139
                    );
2140
                }
2141
                $html .= '</ul>';
2142
            } else {
2143
                $html = array_to_string($course_coachs, $separator);
2144
            }
2145
        }
2146
2147
        return $html;
2148
    }
2149
2150
    /**
2151
     * Get the list of groups from the course.
2152
     *
2153
     * @param string $course_code
2154
     * @param int    $session_id         Session ID (optional)
2155
     * @param int    $in_get_empty_group get empty groups (optional)
2156
     *
2157
     * @return array List of groups info
2158
     */
2159
    public static function get_group_list_of_course(
2160
        $course_code,
2161
        $session_id = 0,
2162
        $in_get_empty_group = 0
2163
    ) {
2164
        $course_info = api_get_course_info($course_code);
2165
2166
        if (empty($course_info)) {
2167
            return [];
2168
        }
2169
        $course_id = $course_info['real_id'];
2170
2171
        if (empty($course_id)) {
2172
            return [];
2173
        }
2174
2175
        $session_id != 0 ? $session_condition = ' WHERE g.session_id IN(1,'.intval($session_id).')' : $session_condition = ' WHERE g.session_id = 0';
2176
        if ($in_get_empty_group == 0) {
2177
            // get only groups that are not empty
2178
            $sql = "SELECT DISTINCT g.id, g.iid, g.name
2179
                    FROM ".Database::get_course_table(TABLE_GROUP)." AS g
2180
                    INNER JOIN ".Database::get_course_table(TABLE_GROUP_USER)." gu
2181
                    ON (g.id = gu.group_id AND g.c_id = $course_id AND gu.c_id = $course_id)
2182
                    $session_condition
2183
                    ORDER BY g.name";
2184
        } else {
2185
            // get all groups even if they are empty
2186
            $sql = "SELECT g.id, g.name, g.iid 
2187
                    FROM ".Database::get_course_table(TABLE_GROUP)." AS g
2188
                    $session_condition
2189
                    AND c_id = $course_id";
2190
        }
2191
2192
        $result = Database::query($sql);
2193
        $groupList = [];
2194
        while ($groupData = Database::fetch_array($result)) {
2195
            $groupData['userNb'] = GroupManager::number_of_students($groupData['id'], $course_id);
2196
            $groupList[$groupData['iid']] = $groupData;
2197
        }
2198
2199
        return $groupList;
2200
    }
2201
2202
    /**
2203
     * Delete a course
2204
     * This function deletes a whole course-area from the platform. When the
2205
     * given course is a virtual course, the database and directory will not be
2206
     * deleted.
2207
     * When the given course is a real course, also all virtual courses refering
2208
     * to the given course will be deleted.
2209
     * Considering the fact that we remove all traces of the course in the main
2210
     * database, it makes sense to remove all tracking as well (if stats databases exist)
2211
     * so that a new course created with this code would not use the remains of an older
2212
     * course.
2213
     *
2214
     * @param string $code The code of the course to delete
2215
     *
2216
     * @todo When deleting a virtual course: unsubscribe users from that virtual
2217
     * course from the groups in the real course if they are not subscribed in
2218
     * that real course.
2219
     */
2220
    public static function delete_course($code)
2221
    {
2222
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
2223
        $table_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2224
        $table_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2225
        $table_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2226
        $table_course_survey = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY);
2227
        $table_course_survey_question = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION);
2228
        $table_course_survey_question_option = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
2229
        $table_course_rel_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2230
2231
        $table_stats_hotpots = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTPOTATOES);
2232
        $table_stats_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
2233
        $table_stats_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
2234
        $table_stats_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS);
2235
        $table_stats_lastaccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
2236
        $table_stats_course_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
2237
        $table_stats_online = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ONLINE);
2238
        $table_stats_default = Database::get_main_table(TABLE_STATISTIC_TRACK_E_DEFAULT);
2239
        $table_stats_downloads = Database::get_main_table(TABLE_STATISTIC_TRACK_E_DOWNLOADS);
2240
        $table_stats_links = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LINKS);
2241
        $table_stats_uploads = Database::get_main_table(TABLE_STATISTIC_TRACK_E_UPLOADS);
2242
2243
        $codeFiltered = Database::escape_string($code);
2244
        $sql = "SELECT * FROM $table_course WHERE code='".$codeFiltered."'";
2245
        $res = Database::query($sql);
2246
2247
        if (Database::num_rows($res) == 0) {
2248
            return;
2249
        }
2250
2251
        $sql = "SELECT * FROM $table_course
2252
                WHERE code = '$codeFiltered'";
2253
        $res = Database::query($sql);
2254
        $course = Database::fetch_array($res);
2255
        $courseId = $course['id']; //int
2256
2257
        $count = 0;
2258
        if (api_is_multiple_url_enabled()) {
2259
            $url_id = 1;
2260
            if (api_get_current_access_url_id() != -1) {
2261
                $url_id = api_get_current_access_url_id();
2262
            }
2263
            UrlManager::delete_url_rel_course($courseId, $url_id);
2264
            $count = UrlManager::getCountUrlRelCourse($courseId);
2265
        }
2266
2267
        if ($count == 0) {
2268
            self::create_database_dump($code);
2269
2270
            $course_tables = AddCourse::get_course_tables();
2271
2272
            // Cleaning group categories
2273
            $groupCategories = GroupManager::get_categories($course['code']);
2274
2275
            if (!empty($groupCategories)) {
2276
                foreach ($groupCategories as $category) {
2277
                    GroupManager::delete_category($category['id'], $course['code']);
2278
                }
2279
            }
2280
2281
            // Cleaning groups
2282
            $groups = GroupManager::get_groups($courseId);
2283
            if (!empty($groups)) {
2284
                foreach ($groups as $group) {
2285
                    GroupManager::delete_groups($group, $course['code']);
2286
                }
2287
            }
2288
2289
            // Cleaning c_x tables
2290
            if (!empty($courseId)) {
2291
                foreach ($course_tables as $table) {
2292
                    $table = Database::get_course_table($table);
2293
                    $sql = "DELETE FROM $table WHERE c_id = $courseId ";
2294
                    Database::query($sql);
2295
                }
2296
            }
2297
2298
            $course_dir = api_get_path(SYS_COURSE_PATH).$course['directory'];
2299
            $archive_dir = api_get_path(SYS_ARCHIVE_PATH).$course['directory'].'_'.time();
2300
            if (is_dir($course_dir)) {
2301
                rename($course_dir, $archive_dir);
2302
            }
2303
2304
            // Unsubscribe all users from the course
2305
            $sql = "DELETE FROM $table_course_user WHERE c_id = $courseId";
2306
            Database::query($sql);
2307
            // Delete the course from the sessions tables
2308
            $sql = "DELETE FROM $table_session_course WHERE c_id = $courseId";
2309
            Database::query($sql);
2310
            $sql = "DELETE FROM $table_session_course_user WHERE c_id = $courseId";
2311
            Database::query($sql);
2312
2313
            // Delete from Course - URL
2314
            $sql = "DELETE FROM $table_course_rel_url WHERE c_id = $courseId";
2315
            Database::query($sql);
2316
2317
            $sql = "SELECT survey_id FROM $table_course_survey WHERE course_code = '$codeFiltered'";
2318
            $result_surveys = Database::query($sql);
2319
            while ($surveys = Database::fetch_array($result_surveys)) {
2320
                $survey_id = $surveys[0]; //int
2321
                $sql = "DELETE FROM $table_course_survey_question WHERE survey_id = $survey_id";
2322
                Database::query($sql);
2323
                $sql = "DELETE FROM $table_course_survey_question_option WHERE survey_id = $survey_id";
2324
                Database::query($sql);
2325
                $sql = "DELETE FROM $table_course_survey WHERE survey_id = $survey_id";
2326
                Database::query($sql);
2327
            }
2328
2329
            // Delete the course from the stats tables
2330
            $sql = "DELETE FROM $table_stats_hotpots WHERE c_id = $courseId";
2331
            Database::query($sql);
2332
            $sql = "DELETE FROM $table_stats_attempt WHERE c_id = $courseId";
2333
            Database::query($sql);
2334
            $sql = "DELETE FROM $table_stats_exercises WHERE c_id = $courseId";
2335
            Database::query($sql);
2336
            $sql = "DELETE FROM $table_stats_access WHERE c_id = $courseId";
2337
            Database::query($sql);
2338
            $sql = "DELETE FROM $table_stats_lastaccess WHERE c_id = $courseId";
2339
            Database::query($sql);
2340
            $sql = "DELETE FROM $table_stats_course_access WHERE c_id = $courseId";
2341
            Database::query($sql);
2342
            $sql = "DELETE FROM $table_stats_online WHERE c_id = $courseId";
2343
            Database::query($sql);
2344
            // Do not delete rows from track_e_default as these include course
2345
            // creation and other important things that do not take much space
2346
            // but give information on the course history
2347
            //$sql = "DELETE FROM $table_stats_default WHERE c_id = $courseId";
2348
            //Database::query($sql);
2349
            $sql = "DELETE FROM $table_stats_downloads WHERE c_id = $courseId";
2350
            Database::query($sql);
2351
            $sql = "DELETE FROM $table_stats_links WHERE c_id = $courseId";
2352
            Database::query($sql);
2353
            $sql = "DELETE FROM $table_stats_uploads WHERE c_id = $courseId";
2354
            Database::query($sql);
2355
2356
            // Update ticket
2357
            $table = Database::get_main_table(TABLE_TICKET_TICKET);
2358
            $sql = "UPDATE $table SET course_id = NULL WHERE course_id = $courseId";
2359
            Database::query($sql);
2360
2361
            // Class
2362
            $table = Database::get_main_table(TABLE_USERGROUP_REL_COURSE);
2363
            $sql = "DELETE FROM $table
2364
                    WHERE course_id = $courseId";
2365
            Database::query($sql);
2366
2367
            // Skills
2368
            $table = Database::get_main_table(TABLE_MAIN_SKILL_REL_USER);
2369
            $argumentation = Database::escape_string(sprintf(get_lang('SkillFromCourseXDeletedSinceThen'), $course['code']));
2370
            $sql = "UPDATE $table SET course_id = NULL, session_id = NULL, argumentation = '$argumentation' WHERE course_id = $courseId";
2371
            Database::query($sql);
2372
2373
            // Delete the course from the database
2374
            $sql = "DELETE FROM $table_course WHERE code = '$codeFiltered'";
2375
            Database::query($sql);
2376
2377
            // delete extra course fields
2378
            $extraFieldValues = new ExtraFieldValue('course');
2379
            $extraFieldValues->deleteValuesByItem($courseId);
2380
2381
            // Add event to system log
2382
            Event::addEvent(
2383
                LOG_COURSE_DELETE,
2384
                LOG_COURSE_CODE,
2385
                $code,
2386
                api_get_utc_datetime(),
2387
                api_get_user_id(),
2388
                $courseId
2389
            );
2390
        }
2391
    }
2392
2393
    /**
2394
     * Creates a file called mysql_dump.sql in the course folder.
2395
     *
2396
     * @param string $course_code The code of the course
2397
     *
2398
     * @todo Implementation for single database
2399
     */
2400
    public static function create_database_dump($course_code)
2401
    {
2402
        $sql_dump = '';
2403
        $course_code = Database::escape_string($course_code);
2404
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
2405
        $sql = "SELECT * FROM $table_course WHERE code = '$course_code'";
2406
        $res = Database::query($sql);
2407
        $course = Database::fetch_array($res);
2408
2409
        $course_tables = AddCourse::get_course_tables();
2410
2411
        if (!empty($course['id'])) {
2412
            //Cleaning c_x tables
2413
            foreach ($course_tables as $table) {
2414
                $table = Database::get_course_table($table);
2415
                $sql = "SELECT * FROM $table WHERE c_id = {$course['id']} ";
2416
                $res_table = Database::query($sql);
2417
2418
                while ($row = Database::fetch_array($res_table, 'ASSOC')) {
2419
                    $row_to_save = [];
2420
                    foreach ($row as $key => $value) {
2421
                        $row_to_save[$key] = $key."='".Database::escape_string($row[$key])."'";
2422
                    }
2423
                    $sql_dump .= "\nINSERT INTO $table SET ".implode(', ', $row_to_save).';';
2424
                }
2425
            }
2426
        }
2427
2428
        if (is_dir(api_get_path(SYS_COURSE_PATH).$course['directory'])) {
2429
            $file_name = api_get_path(SYS_COURSE_PATH).$course['directory'].'/mysql_dump.sql';
2430
            $handle = fopen($file_name, 'a+');
2431
            if ($handle !== false) {
2432
                fwrite($handle, $sql_dump);
2433
                fclose($handle);
2434
            } 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...
2435
                //TODO trigger exception in a try-catch
2436
            }
2437
        }
2438
    }
2439
2440
    /**
2441
     * Sort courses for a specific user ??
2442
     *
2443
     * @param int    $user_id     User ID
2444
     * @param string $course_code Course code
2445
     *
2446
     * @return int Minimum course order
2447
     *
2448
     * @todo Review documentation
2449
     */
2450
    public static function userCourseSort($user_id, $course_code)
2451
    {
2452
        if ($user_id != strval(intval($user_id))) {
2453
            return false;
2454
        }
2455
2456
        $course_code = Database::escape_string($course_code);
2457
        $TABLECOURSE = Database::get_main_table(TABLE_MAIN_COURSE);
2458
        $TABLECOURSUSER = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2459
2460
        $course_title = Database::result(
2461
            Database::query(
2462
                "SELECT title FROM $TABLECOURSE WHERE code = '$course_code'"
2463
            ),
2464
            0,
2465
            0
2466
        );
2467
        if ($course_title === false) {
2468
            $course_title = '';
2469
        }
2470
2471
        $sql = "SELECT course.code as code, course.title as title, cu.sort as sort
2472
                FROM $TABLECOURSUSER as cu, $TABLECOURSE as course
2473
                WHERE   course.id = cu.c_id AND user_id = $user_id AND
2474
                        cu.relation_type <> ".COURSE_RELATION_TYPE_RRHH." AND
2475
                        user_course_cat = 0
2476
                ORDER BY cu.sort";
2477
        $result = Database::query($sql);
2478
2479
        $course_title_precedent = '';
2480
        $counter = 0;
2481
        $course_found = false;
2482
        $course_sort = 1;
2483
2484
        if (Database::num_rows($result) > 0) {
2485
            while ($courses = Database::fetch_array($result)) {
2486
                if ($course_title_precedent == '') {
2487
                    $course_title_precedent = $courses['title'];
2488
                }
2489
                if (api_strcasecmp($course_title_precedent, $course_title) < 0) {
2490
                    $course_found = true;
2491
                    $course_sort = $courses['sort'];
2492
                    if ($counter == 0) {
2493
                        $sql = "UPDATE $TABLECOURSUSER
2494
                                SET sort = sort+1
2495
                                WHERE
2496
                                    user_id= $user_id AND
2497
                                    relation_type <> ".COURSE_RELATION_TYPE_RRHH."
2498
                                    AND user_course_cat = 0
2499
                                    AND sort > $course_sort";
2500
                        $course_sort++;
2501
                    } else {
2502
                        $sql = "UPDATE $TABLECOURSUSER SET sort = sort+1
2503
                                WHERE
2504
                                    user_id= $user_id AND
2505
                                    relation_type <> ".COURSE_RELATION_TYPE_RRHH." AND
2506
                                    user_course_cat = 0 AND
2507
                                    sort >= $course_sort";
2508
                    }
2509
                    Database::query($sql);
2510
                    break;
2511
                } else {
2512
                    $course_title_precedent = $courses['title'];
2513
                }
2514
                $counter++;
2515
            }
2516
2517
            // We must register the course in the beginning of the list
2518
            if (!$course_found) {
2519
                $course_sort = Database::result(
2520
                    Database::query(
2521
                        'SELECT min(sort) as min_sort FROM '.$TABLECOURSUSER.' WHERE user_id = "'.$user_id.'" AND user_course_cat="0"'
2522
                    ),
2523
                    0,
2524
                    0
2525
                );
2526
                Database::query("UPDATE $TABLECOURSUSER SET sort = sort+1 WHERE user_id = $user_id AND user_course_cat = 0");
2527
            }
2528
        }
2529
2530
        return $course_sort;
2531
    }
2532
2533
    /**
2534
     * check if course exists.
2535
     *
2536
     * @param string $courseCode
2537
     *
2538
     * @return int if exists, false else
2539
     */
2540
    public static function course_exists($courseCode)
2541
    {
2542
        $courseCode = Database::escape_string($courseCode);
2543
        $sql = "SELECT 1 FROM ".Database::get_main_table(TABLE_MAIN_COURSE)."
2544
                WHERE code = '$courseCode'";
2545
2546
        return Database::num_rows(Database::query($sql));
2547
    }
2548
2549
    /**
2550
     * Send an email to tutor after the auth-suscription of a student in your course.
2551
     *
2552
     * @author Carlos Vargas <[email protected]>, Dokeos Latino
2553
     *
2554
     * @param int    $user_id            the id of the user
2555
     * @param string $courseId           the course code
2556
     * @param bool   $send_to_tutor_also
2557
     *
2558
     * @return false|null we return the message that is displayed when the action is successful
2559
     */
2560
    public static function email_to_tutor($user_id, $courseId, $send_to_tutor_also = false)
2561
    {
2562
        if ($user_id != strval(intval($user_id))) {
2563
            return false;
2564
        }
2565
        $courseId = intval($courseId);
2566
        $information = api_get_course_info_by_id($courseId);
2567
        $course_code = $information['code'];
2568
        $student = api_get_user_info($user_id);
2569
2570
        $name_course = $information['title'];
2571
        $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)." 
2572
                WHERE c_id = $courseId";
2573
2574
        // TODO: Ivan: This is a mistake, please, have a look at it. Intention here is diffcult to be guessed.
2575
        //if ($send_to_tutor_also = true)
2576
        // Proposed change:
2577
        if ($send_to_tutor_also) {
2578
            $sql .= " AND is_tutor = 1";
2579
        } else {
2580
            $sql .= " AND status = 1";
2581
        }
2582
2583
        $result = Database::query($sql);
2584
        while ($row = Database::fetch_array($result)) {
2585
            $tutor = api_get_user_info($row['user_id']);
2586
            $emailto = $tutor['email'];
2587
            $emailsubject = get_lang('NewUserInTheCourse').': '.$name_course;
2588
            $emailbody = get_lang('Dear').': '.api_get_person_name($tutor['firstname'], $tutor['lastname'])."\n";
2589
            $emailbody .= get_lang('MessageNewUserInTheCourse').': '.$name_course."\n";
2590
            $emailbody .= get_lang('UserName').': '.$student['username']."\n";
2591
            if (api_is_western_name_order()) {
2592
                $emailbody .= get_lang('FirstName').': '.$student['firstname']."\n";
2593
                $emailbody .= get_lang('LastName').': '.$student['lastname']."\n";
2594
            } else {
2595
                $emailbody .= get_lang('LastName').': '.$student['lastname']."\n";
2596
                $emailbody .= get_lang('FirstName').': '.$student['firstname']."\n";
2597
            }
2598
            $emailbody .= get_lang('Email').': <a href="mailto:'.$student['email'].'">'.$student['email']."</a>\n\n";
2599
            $recipient_name = api_get_person_name(
2600
                $tutor['firstname'],
2601
                $tutor['lastname'],
2602
                null,
2603
                PERSON_NAME_EMAIL_ADDRESS
2604
            );
2605
            $sender_name = api_get_person_name(
2606
                api_get_setting('administratorName'),
2607
                api_get_setting('administratorSurname'),
2608
                null,
2609
                PERSON_NAME_EMAIL_ADDRESS
2610
            );
2611
            $email_admin = api_get_setting('emailAdministrator');
2612
2613
            $additionalParameters = [
2614
                'smsType' => SmsPlugin::NEW_USER_SUBSCRIBED_COURSE,
2615
                'userId' => $tutor['user_id'],
2616
                'userUsername' => $student['username'],
2617
                'courseCode' => $course_code,
2618
            ];
2619
            api_mail_html(
2620
                $recipient_name,
2621
                $emailto,
2622
                $emailsubject,
2623
                $emailbody,
2624
                $sender_name,
2625
                $email_admin,
2626
                null,
2627
                null,
2628
                null,
2629
                $additionalParameters
2630
            );
2631
        }
2632
    }
2633
2634
    /**
2635
     * @return array
2636
     */
2637
    public static function get_special_course_list()
2638
    {
2639
        $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
2640
        $tbl_course_field = Database::get_main_table(TABLE_EXTRA_FIELD);
2641
        $tbl_course_field_value = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
2642
2643
        //we filter the courses from the URL
2644
        $join_access_url = $where_access_url = '';
2645
        if (api_get_multiple_access_url()) {
2646
            $access_url_id = api_get_current_access_url_id();
2647
            if ($access_url_id != -1) {
2648
                $tbl_url_course = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2649
                $join_access_url = "LEFT JOIN $tbl_url_course url_rel_course
2650
                                    ON url_rel_course.c_id = tcfv.item_id ";
2651
                $where_access_url = " AND access_url_id = $access_url_id ";
2652
            }
2653
        }
2654
2655
        $extraFieldType = EntityExtraField::COURSE_FIELD_TYPE;
2656
2657
        // get course list auto-register
2658
        $sql = "SELECT DISTINCT(c.id)
2659
                FROM $tbl_course_field_value tcfv
2660
                INNER JOIN $tbl_course_field tcf
2661
                ON tcfv.field_id =  tcf.id $join_access_url
2662
                INNER JOIN $courseTable c
2663
                ON (c.id = tcfv.item_id)
2664
                WHERE
2665
                    tcf.extra_field_type = $extraFieldType AND
2666
                    tcf.variable = 'special_course' AND
2667
                    tcfv.value = 1 $where_access_url";
2668
2669
        $result = Database::query($sql);
2670
        $courseList = [];
2671
2672
        if (Database::num_rows($result) > 0) {
2673
            while ($row = Database::fetch_array($result)) {
2674
                $courseList[] = $row['id'];
2675
            }
2676
        }
2677
2678
        return $courseList;
2679
    }
2680
2681
    /**
2682
     * Get the course codes that have been restricted in the catalogue, and if byUserId is set
2683
     * then the courses that the user is allowed or not to see in catalogue.
2684
     *
2685
     * @param bool $allowed  Either if the courses have some users that are or are not allowed to see in catalogue
2686
     * @param int  $byUserId if the courses are or are not allowed to see to the user
2687
     *
2688
     * @return array Course codes allowed or not to see in catalogue by some user or the user
2689
     */
2690
    public static function getCatalogueCourseList($allowed = true, $byUserId = -1)
2691
    {
2692
        $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
2693
        $tblCourseRelUserCatalogue = Database::get_main_table(TABLE_MAIN_COURSE_CATALOGUE_USER);
2694
        $visibility = $allowed ? 1 : 0;
2695
2696
        // Restriction by user id
2697
        $currentUserRestriction = '';
2698
        if ($byUserId > 0) {
2699
            $byUserId = (int) $byUserId;
2700
            $currentUserRestriction = " AND tcruc.user_id = $byUserId ";
2701
        }
2702
2703
        //we filter the courses from the URL
2704
        $joinAccessUrl = '';
2705
        $whereAccessUrl = '';
2706
        if (api_get_multiple_access_url()) {
2707
            $accessUrlId = api_get_current_access_url_id();
2708
            if ($accessUrlId != -1) {
2709
                $tblUrlCourse = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2710
                $joinAccessUrl = "LEFT JOIN $tblUrlCourse url_rel_course
2711
                                  ON url_rel_course.c_id = c.id ";
2712
                $whereAccessUrl = " AND access_url_id = $accessUrlId ";
2713
            }
2714
        }
2715
2716
        // get course list auto-register
2717
        $sql = "SELECT DISTINCT(c.code)
2718
                FROM $tblCourseRelUserCatalogue tcruc
2719
                INNER JOIN $courseTable c
2720
                ON (c.id = tcruc.c_id) $joinAccessUrl
2721
                WHERE tcruc.visible = $visibility $currentUserRestriction $whereAccessUrl";
2722
2723
        $result = Database::query($sql);
2724
        $courseList = [];
2725
2726
        if (Database::num_rows($result) > 0) {
2727
            while ($resultRow = Database::fetch_array($result)) {
2728
                $courseList[] = $resultRow['code'];
2729
            }
2730
        }
2731
2732
        return $courseList;
2733
    }
2734
2735
    /**
2736
     * Get list of courses for a given user.
2737
     *
2738
     * @param int   $user_id
2739
     * @param bool  $include_sessions                   Whether to include courses from session or not
2740
     * @param bool  $adminGetsAllCourses                If the user is platform admin,
2741
     *                                                  whether he gets all the courses or just his. Note: This does *not* include all sessions
2742
     * @param bool  $loadSpecialCourses
2743
     * @param array $skipCourseList                     List of course ids to skip
2744
     * @param bool  $useUserLanguageFilterIfAvailable
2745
     * @param bool  $showCoursesSessionWithDifferentKey
2746
     *
2747
     * @return array List of codes and db name
2748
     *
2749
     * @author isaac flores paz
2750
     */
2751
    public static function get_courses_list_by_user_id(
2752
        $user_id,
2753
        $include_sessions = false,
2754
        $adminGetsAllCourses = false,
2755
        $loadSpecialCourses = true,
2756
        $skipCourseList = [],
2757
        $useUserLanguageFilterIfAvailable = true,
2758
        $showCoursesSessionWithDifferentKey = false
2759
    ) {
2760
        $user_id = intval($user_id);
2761
        $urlId = api_get_current_access_url_id();
2762
        $course_list = [];
2763
        $codes = [];
2764
2765
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
2766
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2767
        $tbl_user_course_category = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
2768
        $tableCourseUrl = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2769
2770
        $languageCondition = '';
2771
        $onlyInUserLanguage = api_get_configuration_value('my_courses_show_courses_in_user_language_only');
2772
        if ($useUserLanguageFilterIfAvailable && $onlyInUserLanguage) {
2773
            $userInfo = api_get_user_info(api_get_user_id());
2774
            if (!empty($userInfo['language'])) {
2775
                $languageCondition = " AND course.course_language = '".$userInfo['language']."' ";
2776
            }
2777
        }
2778
2779
        if ($adminGetsAllCourses && UserManager::is_admin($user_id)) {
2780
            // get the whole courses list
2781
            $sql = "SELECT DISTINCT(course.code), course.id as real_id, course.title
2782
                    FROM $tbl_course course 
2783
                    INNER JOIN $tableCourseUrl url 
2784
                    ON (course.id = url.c_id)
2785
                    WHERE 
2786
                        url.access_url_id = $urlId     
2787
                        $languageCondition 
2788
                ";
2789
        } else {
2790
            $withSpecialCourses = $withoutSpecialCourses = '';
2791
2792
            if ($loadSpecialCourses) {
2793
                $specialCourseList = self::get_special_course_list();
2794
2795
                if (!empty($specialCourseList)) {
2796
                    $specialCourseToString = '"'.implode('","', $specialCourseList).'"';
2797
                    $withSpecialCourses = ' AND course.id IN ('.$specialCourseToString.')';
2798
                    $withoutSpecialCourses = ' AND course.id NOT IN ('.$specialCourseToString.')';
2799
                }
2800
2801
                if (!empty($withSpecialCourses)) {
2802
                    $sql = "SELECT DISTINCT (course.code), 
2803
                            course.id as real_id,
2804
                            course.category_code AS category,
2805
                            course.title
2806
                            FROM $tbl_course_user course_rel_user
2807
                            LEFT JOIN $tbl_course course
2808
                            ON course.id = course_rel_user.c_id
2809
                            LEFT JOIN $tbl_user_course_category user_course_category
2810
                            ON course_rel_user.user_course_cat = user_course_category.id
2811
                            INNER JOIN $tableCourseUrl url 
2812
                            ON (course.id = url.c_id)  
2813
                            WHERE url.access_url_id = $urlId 
2814
                            $withSpecialCourses
2815
                            $languageCondition                        
2816
                            GROUP BY course.code
2817
                            ORDER BY user_course_category.sort, course.title, course_rel_user.sort ASC
2818
                    ";
2819
                    $result = Database::query($sql);
2820
                    if (Database::num_rows($result) > 0) {
2821
                        while ($result_row = Database::fetch_array($result, 'ASSOC')) {
2822
                            $result_row['special_course'] = 1;
2823
                            $course_list[] = $result_row;
2824
                            $codes[] = $result_row['real_id'];
2825
                        }
2826
                    }
2827
                }
2828
            }
2829
2830
            // get course list not auto-register. Use Distinct to avoid multiple
2831
            // entries when a course is assigned to a HRD (DRH) as watcher
2832
            $sql = "SELECT 
2833
                        DISTINCT(course.code), 
2834
                        course.id as real_id, 
2835
                        course.category_code AS category,
2836
                        course.title
2837
                    FROM $tbl_course course
2838
                    INNER JOIN $tbl_course_user cru 
2839
                    ON (course.id = cru.c_id)
2840
                    INNER JOIN $tableCourseUrl url 
2841
                    ON (course.id = url.c_id) 
2842
                    WHERE 
2843
                        url.access_url_id = $urlId AND 
2844
                        cru.user_id = '$user_id' 
2845
                        $withoutSpecialCourses
2846
                        $languageCondition
2847
                    ORDER BY course.title
2848
                    ";
2849
        }
2850
        $result = Database::query($sql);
2851
2852
        if (Database::num_rows($result)) {
2853
            while ($row = Database::fetch_array($result, 'ASSOC')) {
2854
                if (!empty($skipCourseList)) {
2855
                    if (in_array($row['real_id'], $skipCourseList)) {
2856
                        continue;
2857
                    }
2858
                }
2859
                $course_list[] = $row;
2860
                $codes[] = $row['real_id'];
2861
            }
2862
        }
2863
2864
        if ($include_sessions === true) {
2865
            $sql = "SELECT DISTINCT (c.code), 
2866
                        c.id as real_id, 
2867
                        c.category_code AS category,
2868
                        s.id as session_id,
2869
                        s.name as session_name
2870
                    FROM ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)." scu                     
2871
                    INNER JOIN $tbl_course c
2872
                    ON (scu.c_id = c.id)
2873
                    INNER JOIN ".Database::get_main_table(TABLE_MAIN_SESSION)." s
2874
                    ON (s.id = scu.session_id)
2875
                    WHERE user_id = $user_id ";
2876
            $r = Database::query($sql);
2877
            while ($row = Database::fetch_array($r, 'ASSOC')) {
2878
                if (!empty($skipCourseList)) {
2879
                    if (in_array($row['real_id'], $skipCourseList)) {
2880
                        continue;
2881
                    }
2882
                }
2883
2884
                if ($showCoursesSessionWithDifferentKey) {
2885
                    $course_list[] = $row;
2886
                } else {
2887
                    if (!in_array($row['real_id'], $codes)) {
2888
                        $course_list[] = $row;
2889
                    }
2890
                }
2891
            }
2892
        }
2893
2894
        return $course_list;
2895
    }
2896
2897
    /**
2898
     * Get course ID from a given course directory name.
2899
     *
2900
     * @param string $path Course directory (without any slash)
2901
     *
2902
     * @return string Course code, or false if not found
2903
     */
2904
    public static function getCourseCodeFromDirectory($path)
2905
    {
2906
        $path = Database::escape_string(str_replace('.', '', str_replace('/', '', $path)));
2907
        $res = Database::query("SELECT code FROM ".Database::get_main_table(TABLE_MAIN_COURSE)."
2908
                WHERE directory LIKE BINARY '$path'");
2909
        if ($res === false) {
2910
            return false;
2911
        }
2912
        if (Database::num_rows($res) != 1) {
2913
            return false;
2914
        }
2915
        $row = Database::fetch_array($res);
2916
2917
        return $row['code'];
2918
    }
2919
2920
    /**
2921
     * Get course code(s) from visual code.
2922
     *
2923
     * @deprecated
2924
     *
2925
     * @param   string  Visual code
2926
     *
2927
     * @return array List of codes for the given visual code
2928
     */
2929
    public static function get_courses_info_from_visual_code($code)
2930
    {
2931
        $result = [];
2932
        $sql_result = Database::query("SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE)."
2933
                WHERE visual_code = '".Database::escape_string($code)."'");
2934
        while ($virtual_course = Database::fetch_array($sql_result)) {
2935
            $result[] = $virtual_course;
2936
        }
2937
2938
        return $result;
2939
    }
2940
2941
    /**
2942
     * Get emails of tutors to course.
2943
     *
2944
     * @param int $courseId
2945
     *
2946
     * @return array List of emails of tutors to course
2947
     *
2948
     * @author Carlos Vargas <[email protected]>, Dokeos Latino
2949
     * */
2950
    public static function get_emails_of_tutors_to_course($courseId)
2951
    {
2952
        $list = [];
2953
        $courseId = intval($courseId);
2954
        $res = Database::query(
2955
            "SELECT user_id 
2956
            FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
2957
            WHERE c_id = $courseId AND status = 1"
2958
        );
2959
        while ($list_users = Database::fetch_array($res)) {
2960
            $result = Database::query(
2961
                "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_USER)."
2962
                WHERE user_id = ".$list_users['user_id']
2963
            );
2964
            while ($row_user = Database::fetch_array($result)) {
2965
                $name_teacher = api_get_person_name($row_user['firstname'], $row_user['lastname']);
2966
                $list[] = [$row_user['email'] => $name_teacher];
2967
            }
2968
        }
2969
2970
        return $list;
2971
    }
2972
2973
    /**
2974
     * Get coaches emails by session.
2975
     *
2976
     * @param int $session_id
2977
     * @param int $courseId
2978
     *
2979
     * @return array array(email => name_tutor)  by coach
2980
     *
2981
     * @author Carlos Vargas <[email protected]>
2982
     */
2983
    public static function get_email_of_tutor_to_session($session_id, $courseId)
2984
    {
2985
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2986
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
2987
        $coachs_emails = [];
2988
2989
        $courseId = intval($courseId);
2990
        $session_id = intval($session_id);
2991
2992
        $sql = "SELECT user_id
2993
                FROM $tbl_session_course_user
2994
                WHERE
2995
                    session_id = $session_id AND
2996
                    c_id = $courseId AND
2997
                    status = 2
2998
                ";
2999
        $rs = Database::query($sql);
3000
3001
        if (Database::num_rows($rs) > 0) {
3002
            $user_ids = [];
3003
            while ($row = Database::fetch_array($rs)) {
3004
                $user_ids[] = $row['user_id'];
3005
            }
3006
3007
            $sql = "SELECT firstname, lastname, email FROM $tbl_user
3008
                    WHERE user_id IN (".implode(",", $user_ids).")";
3009
            $rs_user = Database::query($sql);
3010
3011
            while ($row_emails = Database::fetch_array($rs_user)) {
3012
                $mail_tutor = [
3013
                    'email' => $row_emails['email'],
3014
                    'complete_name' => api_get_person_name($row_emails['firstname'], $row_emails['lastname']),
3015
                ];
3016
                $coachs_emails[] = $mail_tutor;
3017
            }
3018
        }
3019
3020
        return $coachs_emails;
3021
    }
3022
3023
    /**
3024
     * Creates a new extra field for a given course.
3025
     *
3026
     * @param string $variable    Field's internal variable name
3027
     * @param int    $fieldType   Field's type
3028
     * @param string $displayText Field's language var name
3029
     * @param string $default     Optional. The default value
3030
     *
3031
     * @return int New extra field ID
3032
     */
3033
    public static function create_course_extra_field($variable, $fieldType, $displayText, $default = '')
3034
    {
3035
        $extraField = new ExtraField('course');
3036
        $params = [
3037
            'variable' => $variable,
3038
            'field_type' => $fieldType,
3039
            'display_text' => $displayText,
3040
            'default_value' => $default,
3041
        ];
3042
3043
        return $extraField->save($params);
3044
    }
3045
3046
    /**
3047
     * Updates course attribute. Note that you need to check that your
3048
     * attribute is valid before you use this function.
3049
     *
3050
     * @param int    $id    Course id
3051
     * @param string $name  Attribute name
3052
     * @param string $value Attribute value
3053
     *
3054
     * @return Doctrine\DBAL\Driver\Statement|null True if attribute was successfully updated,
3055
     *                                             false if course was not found or attribute name is invalid
3056
     */
3057
    public static function update_attribute($id, $name, $value)
3058
    {
3059
        $id = (int) $id;
3060
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
3061
        $sql = "UPDATE $table SET $name = '".Database::escape_string($value)."'
3062
                WHERE id = $id";
3063
3064
        return Database::query($sql);
3065
    }
3066
3067
    /**
3068
     * Update course attributes. Will only update attributes with a non-empty value.
3069
     * Note that you NEED to check that your attributes are valid before using this function.
3070
     *
3071
     * @param int Course id
3072
     * @param array Associative array with field names as keys and field values as values
3073
     *
3074
     * @return Doctrine\DBAL\Driver\Statement|null True if update was successful, false otherwise
3075
     */
3076
    public static function update_attributes($id, $attributes)
3077
    {
3078
        $id = (int) $id;
3079
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
3080
        $sql = "UPDATE $table SET ";
3081
        $i = 0;
3082
        foreach ($attributes as $name => $value) {
3083
            if ($value != '') {
3084
                if ($i > 0) {
3085
                    $sql .= ", ";
3086
                }
3087
                $sql .= " $name = '".Database::escape_string($value)."'";
3088
                $i++;
3089
            }
3090
        }
3091
        $sql .= " WHERE id = $id";
3092
3093
        return Database::query($sql);
3094
    }
3095
3096
    /**
3097
     * Update an extra field value for a given course.
3098
     *
3099
     * @param string $course_code Course code
3100
     * @param string $variable    Field variable name
3101
     * @param string $value       Optional. Default field value
3102
     *
3103
     * @return bool|int An integer when register a new extra field. And boolean when update the extrafield
3104
     */
3105
    public static function update_course_extra_field_value($course_code, $variable, $value = '')
3106
    {
3107
        $courseInfo = api_get_course_info($course_code);
3108
        $courseId = $courseInfo['real_id'];
3109
3110
        $extraFieldValues = new ExtraFieldValue('course');
3111
        $params = [
3112
            'item_id' => $courseId,
3113
            'variable' => $variable,
3114
            'value' => $value,
3115
        ];
3116
3117
        return $extraFieldValues->save($params);
3118
    }
3119
3120
    /**
3121
     * @param int $sessionId
3122
     *
3123
     * @return mixed
3124
     */
3125
    public static function get_session_category_id_by_session_id($sessionId)
3126
    {
3127
        if (empty($sessionId)) {
3128
            return [];
3129
        }
3130
        $sessionId = intval($sessionId);
3131
        $sql = 'SELECT sc.id session_category
3132
                FROM '.Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY).' sc
3133
                INNER JOIN '.Database::get_main_table(TABLE_MAIN_SESSION).' s
3134
                ON sc.id = s.session_category_id 
3135
                WHERE s.id = '.$sessionId;
3136
3137
        return Database::result(
3138
            Database::query($sql),
3139
            0,
3140
            'session_category'
3141
        );
3142
    }
3143
3144
    /**
3145
     * Gets the value of a course extra field. Returns null if it was not found.
3146
     *
3147
     * @param string $variable Name of the extra field
3148
     * @param string $code     Course code
3149
     *
3150
     * @return string Value
3151
     */
3152
    public static function get_course_extra_field_value($variable, $code)
3153
    {
3154
        $courseInfo = api_get_course_info($code);
3155
        $courseId = $courseInfo['real_id'];
3156
3157
        $extraFieldValues = new ExtraFieldValue('course');
3158
        $result = $extraFieldValues->get_values_by_handler_and_field_variable($courseId, $variable);
3159
        if (!empty($result['value'])) {
3160
            return $result['value'];
3161
        }
3162
3163
        return null;
3164
    }
3165
3166
    /**
3167
     * Lists details of the course description.
3168
     *
3169
     * @param array        The course description
3170
     * @param string    The encoding
3171
     * @param bool        If true is displayed if false is hidden
3172
     *
3173
     * @return string The course description in html
3174
     */
3175
    public static function get_details_course_description_html(
3176
        $descriptions,
3177
        $charset,
3178
        $action_show = true
3179
    ) {
3180
        $data = null;
3181
        if (isset($descriptions) && count($descriptions) > 0) {
3182
            foreach ($descriptions as $description) {
3183
                $data .= '<div class="sectiontitle">';
3184
                if (api_is_allowed_to_edit() && $action_show) {
3185
                    //delete
3186
                    $data .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=delete&description_id='.$description->id.'" onclick="javascript:if(!confirm(\''.addslashes(api_htmlentities(
3187
                        get_lang('ConfirmYourChoice'),
3188
                                ENT_QUOTES,
3189
                        $charset
3190
                    )).'\')) return false;">';
3191
                    $data .= Display::return_icon(
3192
                        'delete.gif',
3193
                        get_lang('Delete'),
3194
                        ['style' => 'vertical-align:middle;float:right;']
3195
                    );
3196
                    $data .= '</a> ';
3197
                    //edit
3198
                    $data .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&description_id='.$description->id.'">';
3199
                    $data .= Display::return_icon(
3200
                        'edit.png',
3201
                        get_lang('Edit'),
3202
                        ['style' => 'vertical-align:middle;float:right; padding-right:4px;'],
3203
                        ICON_SIZE_SMALL
3204
                    );
3205
                    $data .= '</a> ';
3206
                }
3207
                $data .= $description->title;
3208
                $data .= '</div>';
3209
                $data .= '<div class="sectioncomment">';
3210
                $data .= Security::remove_XSS($description->content);
3211
                $data .= '</div>';
3212
            }
3213
        } else {
3214
            $data .= '<em>'.get_lang('ThisCourseDescriptionIsEmpty').'</em>';
3215
        }
3216
3217
        return $data;
3218
    }
3219
3220
    /**
3221
     * Returns the details of a course category.
3222
     *
3223
     * @param string $code Category code
3224
     *
3225
     * @return array Course category
3226
     */
3227
    public static function get_course_category($code)
3228
    {
3229
        $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
3230
        $code = Database::escape_string($code);
3231
        $sql = "SELECT * FROM $table WHERE code = '$code'";
3232
3233
        return Database::fetch_array(Database::query($sql));
3234
    }
3235
3236
    /**
3237
     * Subscribes courses to human resource manager (Dashboard feature).
3238
     *
3239
     * @param int   $hr_manager_id Human Resource Manager id
3240
     * @param array $courses_list  Courses code
3241
     *
3242
     * @return int
3243
     */
3244
    public static function subscribeCoursesToDrhManager($hr_manager_id, $courses_list)
3245
    {
3246
        $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
3247
        $tbl_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
3248
3249
        $hr_manager_id = intval($hr_manager_id);
3250
        $affected_rows = 0;
3251
3252
        //Deleting assigned courses to hrm_id
3253
        if (api_is_multiple_url_enabled()) {
3254
            $sql = "SELECT s.c_id FROM $tbl_course_rel_user s
3255
                    INNER JOIN $tbl_course_rel_access_url a
3256
                    ON (a.c_id = s.c_id)
3257
                    WHERE
3258
                        user_id = $hr_manager_id AND
3259
                        relation_type = ".COURSE_RELATION_TYPE_RRHH." AND
3260
                        access_url_id = ".api_get_current_access_url_id();
3261
        } else {
3262
            $sql = "SELECT c_id FROM $tbl_course_rel_user
3263
                    WHERE user_id = $hr_manager_id AND relation_type = ".COURSE_RELATION_TYPE_RRHH;
3264
        }
3265
        $result = Database::query($sql);
3266
        if (Database::num_rows($result) > 0) {
3267
            while ($row = Database::fetch_array($result)) {
3268
                $sql = "DELETE FROM $tbl_course_rel_user
3269
                        WHERE
3270
                            c_id = {$row['c_id']} AND
3271
                            user_id = $hr_manager_id AND
3272
                            relation_type = ".COURSE_RELATION_TYPE_RRHH;
3273
                Database::query($sql);
3274
            }
3275
        }
3276
3277
        // inserting new courses list
3278
        if (is_array($courses_list)) {
3279
            foreach ($courses_list as $course_code) {
3280
                $courseInfo = api_get_course_info($course_code);
3281
                $courseId = $courseInfo['real_id'];
3282
                $sql = "INSERT IGNORE INTO $tbl_course_rel_user(c_id, user_id, status, relation_type)
3283
                        VALUES($courseId, $hr_manager_id, ".DRH.", ".COURSE_RELATION_TYPE_RRHH.")";
3284
                $result = Database::query($sql);
3285
                if (Database::affected_rows($result)) {
3286
                    $affected_rows++;
3287
                }
3288
            }
3289
        }
3290
3291
        return $affected_rows;
3292
    }
3293
3294
    /**
3295
     * get courses followed by human resources manager.
3296
     *
3297
     * @param int    $user_id
3298
     * @param int    $status
3299
     * @param int    $from
3300
     * @param int    $limit
3301
     * @param string $column
3302
     * @param string $direction
3303
     * @param bool   $getCount
3304
     *
3305
     * @return array courses
3306
     */
3307
    public static function get_courses_followed_by_drh(
3308
        $user_id,
3309
        $status = DRH,
3310
        $from = null,
3311
        $limit = null,
3312
        $column = null,
3313
        $direction = null,
3314
        $getCount = false
3315
    ) {
3316
        return self::getCoursesFollowedByUser(
3317
            $user_id,
3318
            $status,
3319
            $from,
3320
            $limit,
3321
            $column,
3322
            $direction,
3323
            $getCount
3324
        );
3325
    }
3326
3327
    /**
3328
     * get courses followed by user.
3329
     *
3330
     * @param int    $user_id
3331
     * @param int    $status
3332
     * @param int    $from
3333
     * @param int    $limit
3334
     * @param string $column
3335
     * @param string $direction
3336
     * @param bool   $getCount
3337
     * @param string $keyword
3338
     * @param int    $sessionId
3339
     * @param bool   $showAllAssignedCourses
3340
     *
3341
     * @return array courses
3342
     */
3343
    public static function getCoursesFollowedByUser(
3344
        $user_id,
3345
        $status = null,
3346
        $from = null,
3347
        $limit = null,
3348
        $column = null,
3349
        $direction = null,
3350
        $getCount = false,
3351
        $keyword = null,
3352
        $sessionId = 0,
3353
        $showAllAssignedCourses = false
3354
    ) {
3355
        // Database Table Definitions
3356
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
3357
        $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
3358
        $tbl_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
3359
        $sessionId = (int) $sessionId;
3360
        $user_id = (int) $user_id;
3361
        $select = "SELECT DISTINCT *, c.id as real_id ";
3362
3363
        if ($getCount) {
3364
            $select = "SELECT COUNT(DISTINCT c.id) as count";
3365
        }
3366
3367
        $whereConditions = '';
3368
        switch ($status) {
3369
            case COURSEMANAGER:
3370
                $whereConditions .= " AND cru.user_id = $user_id";
3371
                if (!$showAllAssignedCourses) {
3372
                    $whereConditions .= " AND cru.status = ".COURSEMANAGER;
3373
                } else {
3374
                    $whereConditions .= " AND relation_type = ".COURSE_RELATION_TYPE_COURSE_MANAGER;
3375
                }
3376
                break;
3377
            case DRH:
3378
                $whereConditions .= " AND
3379
                    cru.user_id = $user_id AND
3380
                    cru.status = ".DRH." AND
3381
                    relation_type = '".COURSE_RELATION_TYPE_RRHH."'
3382
                ";
3383
                break;
3384
        }
3385
3386
        $keywordCondition = null;
3387
        if (!empty($keyword)) {
3388
            $keyword = Database::escape_string($keyword);
3389
            $keywordCondition = " AND (c.code LIKE '%$keyword%' OR c.title LIKE '%$keyword%' ) ";
3390
        }
3391
3392
        $orderBy = null;
3393
        $extraInnerJoin = null;
3394
3395
        if (!empty($sessionId)) {
3396
            if ($status == COURSEMANAGER) {
3397
                // Teacher of course or teacher inside session
3398
                $whereConditions = " AND (cru.status = ".COURSEMANAGER." OR srcru.status = 2) ";
3399
            }
3400
            $courseList = SessionManager::get_course_list_by_session_id(
3401
                $sessionId
3402
            );
3403
            if (!empty($courseList)) {
3404
                $courseListToString = implode("','", array_keys($courseList));
3405
                $whereConditions .= " AND c.id IN ('".$courseListToString."')";
3406
            }
3407
            $tableSessionRelCourse = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
3408
            $tableSessionRelCourseRelUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
3409
            $orderBy = ' ORDER BY position';
3410
            $extraInnerJoin = " INNER JOIN $tableSessionRelCourse src
3411
                                ON (c.id = src.c_id AND src.session_id = $sessionId)
3412
                                INNER JOIN $tableSessionRelCourseRelUser srcru 
3413
                                ON (src.session_id = srcru.session_id AND srcru.c_id = src.c_id)
3414
                            ";
3415
        }
3416
3417
        $whereConditions .= $keywordCondition;
3418
        $sql = "$select
3419
                FROM $tbl_course c
3420
                INNER JOIN $tbl_course_rel_user cru 
3421
                ON (cru.c_id = c.id)
3422
                INNER JOIN $tbl_course_rel_access_url a 
3423
                ON (a.c_id = c.id)
3424
                $extraInnerJoin
3425
                WHERE
3426
                    access_url_id = ".api_get_current_access_url_id()."
3427
                    $whereConditions
3428
                $orderBy
3429
                ";
3430
        if (isset($from) && isset($limit)) {
3431
            $from = intval($from);
3432
            $limit = intval($limit);
3433
            $sql .= " LIMIT $from, $limit";
3434
        }
3435
3436
        $result = Database::query($sql);
3437
3438
        if ($getCount) {
3439
            $row = Database::fetch_array($result);
3440
3441
            return $row['count'];
3442
        }
3443
3444
        $courses = [];
3445
        if (Database::num_rows($result) > 0) {
3446
            while ($row = Database::fetch_array($result)) {
3447
                $courses[$row['code']] = $row;
3448
            }
3449
        }
3450
3451
        return $courses;
3452
    }
3453
3454
    /**
3455
     * check if a course is special (autoregister).
3456
     *
3457
     * @param int $courseId
3458
     *
3459
     * @return bool
3460
     */
3461
    public static function isSpecialCourse($courseId)
3462
    {
3463
        $extraFieldValue = new ExtraFieldValue('course');
3464
        $result = $extraFieldValue->get_values_by_handler_and_field_variable(
3465
            $courseId,
3466
            'special_course'
3467
        );
3468
3469
        if (!empty($result)) {
3470
            if ($result['value'] == 1) {
3471
                return true;
3472
            }
3473
        }
3474
3475
        return false;
3476
    }
3477
3478
    /**
3479
     * Update course picture.
3480
     *
3481
     * @param array $courseInfo
3482
     * @param   string  File name
3483
     * @param   string  the full system name of the image
3484
     * from which course picture will be created
3485
     * @param string $cropParameters Optional string that contents "x,y,width,height" of a cropped image format
3486
     *
3487
     * @return bool Returns the resulting. In case of internal error or negative validation returns FALSE.
3488
     */
3489
    public static function update_course_picture(
3490
        $courseInfo,
3491
        $filename,
3492
        $source_file = null,
3493
        $cropParameters = null
3494
    ) {
3495
        if (empty($courseInfo)) {
3496
            return false;
3497
        }
3498
3499
        // course path
3500
        $store_path = api_get_path(SYS_COURSE_PATH).$courseInfo['path'];
3501
        // image name for courses
3502
        $course_image = $store_path.'/course-pic.png';
3503
        $course_medium_image = $store_path.'/course-pic85x85.png';
3504
3505
        if (file_exists($course_image)) {
3506
            unlink($course_image);
3507
        }
3508
        if (file_exists($course_medium_image)) {
3509
            unlink($course_medium_image);
3510
        }
3511
3512
        //Crop the image to adjust 4:3 ratio
3513
        $image = new Image($source_file);
3514
        $image->crop($cropParameters);
3515
3516
        //Resize the images in two formats
3517
        $medium = new Image($source_file);
3518
        $medium->resize(85);
3519
        $medium->send_image($course_medium_image, -1, 'png');
3520
        $normal = new Image($source_file);
3521
        $normal->resize(400);
3522
        $normal->send_image($course_image, -1, 'png');
3523
3524
        $result = $medium && $normal;
3525
3526
        return $result ? $result : false;
3527
    }
3528
3529
    /**
3530
     * Deletes the course picture.
3531
     *
3532
     * @param string $courseCode
3533
     */
3534
    public static function deleteCoursePicture($courseCode)
3535
    {
3536
        $course_info = api_get_course_info($courseCode);
3537
        // course path
3538
        $storePath = api_get_path(SYS_COURSE_PATH).$course_info['path'];
3539
        // image name for courses
3540
        $courseImage = $storePath.'/course-pic.png';
3541
        $courseMediumImage = $storePath.'/course-pic85x85.png';
3542
        $courseSmallImage = $storePath.'/course-pic32.png';
3543
3544
        if (file_exists($courseImage)) {
3545
            unlink($courseImage);
3546
        }
3547
        if (file_exists($courseMediumImage)) {
3548
            unlink($courseMediumImage);
3549
        }
3550
        if (file_exists($courseSmallImage)) {
3551
            unlink($courseSmallImage);
3552
        }
3553
    }
3554
3555
    /**
3556
     * Builds the course block in user_portal.php.
3557
     *
3558
     * @todo use Twig
3559
     *
3560
     * @param array $params
3561
     *
3562
     * @return string
3563
     */
3564
    public static function course_item_html_no_icon($params)
3565
    {
3566
        $html = '<div class="course_item">';
3567
        $html .= '<div class="row">';
3568
        $html .= '<div class="col-md-7">';
3569
3570
        $notifications = isset($params['notifications']) ? $params['notifications'] : null;
3571
3572
        $html .= '<h3>'.$params['title'].$notifications.'</h3> ';
3573
3574
        if (isset($params['description'])) {
3575
            $html .= '<p>'.$params['description'].'</p>';
3576
        }
3577
        if (!empty($params['subtitle'])) {
3578
            $html .= '<small>'.$params['subtitle'].'</small>';
3579
        }
3580
        if (!empty($params['teachers'])) {
3581
            $html .= '<h5 class="teacher">'.
3582
                Display::return_icon(
3583
                    'teacher.png',
3584
                    get_lang('Teacher'),
3585
                    [],
3586
                    ICON_SIZE_TINY
3587
                ).
3588
                $params['teachers'].'</h5>';
3589
        }
3590
        if (!empty($params['coaches'])) {
3591
            $html .= '<h5 class="teacher">'.
3592
                Display::return_icon(
3593
                    'teacher.png',
3594
                    get_lang('Coach'),
3595
                    [],
3596
                    ICON_SIZE_TINY
3597
                ).
3598
                $params['coaches'].'</h5>';
3599
        }
3600
3601
        $html .= '</div>';
3602
        $params['right_actions'] = isset($params['right_actions']) ? $params['right_actions'] : null;
3603
        $html .= '<div class="pull-right course-box-actions">'.$params['right_actions'].'</div>';
3604
        $html .= '</div>';
3605
        $html .= '</div>';
3606
3607
        return $html;
3608
    }
3609
3610
    /**
3611
     * @param $params
3612
     * @param bool|false $is_sub_content
3613
     *
3614
     * @return string
3615
     */
3616
    public static function session_items_html($params, $is_sub_content = false)
3617
    {
3618
        $html = '';
3619
        $html .= '<div class="row">';
3620
        $html .= '<div class="col-md-2">';
3621
        if (!empty($params['link'])) {
3622
            $html .= '<a class="thumbnail" href="'.$params['link'].'">';
3623
            $html .= $params['icon'];
3624
            $html .= '</a>';
3625
        } else {
3626
            $html .= $params['icon'];
3627
        }
3628
        $html .= '</div>';
3629
        $html .= '<div class="col-md-10">';
3630
        $html .= $params['title'];
3631
        $html .= $params['coaches'];
3632
        $html .= '</div>';
3633
        $html .= '</div>';
3634
3635
        return $html;
3636
    }
3637
3638
    /**
3639
     * Display special courses (and only these) as several HTML divs of class userportal-course-item.
3640
     *
3641
     * Special courses are courses that stick on top of the list and are "auto-registerable"
3642
     * in the sense that any user clicking them is registered as a student
3643
     *
3644
     * @param int  $user_id                          User id
3645
     * @param bool $load_dirs                        Whether to show the document quick-loader or not
3646
     * @param bool $useUserLanguageFilterIfAvailable
3647
     *
3648
     * @return array
3649
     */
3650
    public static function returnSpecialCourses(
3651
        $user_id,
3652
        $load_dirs = false,
3653
        $useUserLanguageFilterIfAvailable = true
3654
    ) {
3655
        $user_id = intval($user_id);
3656
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
3657
        $specialCourseList = self::get_special_course_list();
3658
3659
        if (empty($specialCourseList)) {
3660
            return [];
3661
        }
3662
3663
        // Filter by language
3664
        $languageCondition = '';
3665
        $onlyInUserLanguage = api_get_configuration_value('my_courses_show_courses_in_user_language_only');
3666
        if ($useUserLanguageFilterIfAvailable && $onlyInUserLanguage) {
3667
            $userInfo = api_get_user_info(api_get_user_id());
3668
            if (!empty($userInfo['language'])) {
3669
                $languageCondition = " AND course_language = '".$userInfo['language']."' ";
3670
            }
3671
        }
3672
3673
        $sql = "SELECT
3674
                    id,
3675
                    code,
3676
                    subscribe subscr,
3677
                    unsubscribe unsubscr
3678
                FROM $table                      
3679
                WHERE 
3680
                    id IN ('".implode("','", $specialCourseList)."')
3681
                    $languageCondition
3682
                GROUP BY code";
3683
3684
        $rs_special_course = Database::query($sql);
3685
        $number_of_courses = Database::num_rows($rs_special_course);
3686
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
3687
3688
        $courseList = [];
3689
        if ($number_of_courses > 0) {
3690
            while ($course = Database::fetch_array($rs_special_course)) {
3691
                $course_info = api_get_course_info($course['code']);
3692
                $courseId = $course_info['real_id'];
3693
                if ($course_info['visibility'] == COURSE_VISIBILITY_HIDDEN) {
3694
                    continue;
3695
                }
3696
3697
                $params = [];
3698
                //Param (course_code) needed to get the student info in page "My courses"
3699
                $params['course_code'] = $course['code'];
3700
                $params['code'] = $course['code'];
3701
                // Get notifications.
3702
                $course_info['id_session'] = null;
3703
                $courseUserInfo = self::getUserCourseInfo($user_id, $courseId);
3704
3705
                if (empty($courseUserInfo)) {
3706
                    $course_info['status'] = STUDENT;
3707
                } else {
3708
                    $course_info['status'] = $courseUserInfo['status'];
3709
                }
3710
                $show_notification = !api_get_configuration_value('hide_course_notification')
3711
                    ? Display::show_notification($course_info)
3712
                    : '';
3713
                $params['edit_actions'] = '';
3714
                $params['document'] = '';
3715
                if (api_is_platform_admin()) {
3716
                    $params['edit_actions'] .= api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cidReq='.$course['code'];
3717
                    if ($load_dirs) {
3718
                        $params['document'] = '<a id="document_preview_'.$courseId.'_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3719
                           .Display::returnFontAwesomeIcon('folder-open').'</a>';
3720
                        $params['document'] .= Display::div('', ['id' => 'document_result_'.$courseId.'_0', 'class' => 'document_preview_container']);
3721
                    }
3722
                } else {
3723
                    if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED && $load_dirs) {
3724
                        $params['document'] = '<a id="document_preview_'.$courseId.'_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3725
                           .Display::returnFontAwesomeIcon('folder-open').'</a>';
3726
                        $params['document'] .= Display::div('', ['id' => 'document_result_'.$courseId.'_0', 'class' => 'document_preview_container']);
3727
                    }
3728
                }
3729
3730
                $params['visibility'] = $course_info['visibility'];
3731
                $params['status'] = $course_info['status'];
3732
                $params['category'] = $course_info['categoryName'];
3733
                $params['category_code'] = $course_info['categoryCode'];
3734
                $params['icon'] = Display::return_icon(
3735
                    'drawing-pin.png',
3736
                    null,
3737
                    null,
3738
                    ICON_SIZE_LARGE,
3739
                    null
3740
                );
3741
3742
                if (api_get_setting('display_coursecode_in_courselist') == 'true') {
3743
                    $params['code_course'] = '('.$course_info['visual_code'].')';
3744
                }
3745
3746
                $params['title'] = $course_info['title'];
3747
                $params['title_cut'] = $course_info['title'];
3748
                $params['link'] = $course_info['course_public_url'].'?id_session=0&autoreg=1';
3749
                if (api_get_setting('display_teacher_in_courselist') === 'true') {
3750
                    $params['teachers'] = self::getTeachersFromCourse(
3751
                        $courseId,
3752
                        true
3753
                    );
3754
                }
3755
3756
                if ($showCustomIcon === 'true') {
3757
                    $params['thumbnails'] = $course_info['course_image'];
3758
                    $params['image'] = $course_info['course_image_large'];
3759
                }
3760
3761
                if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
3762
                    $params['notifications'] = $show_notification;
3763
                }
3764
3765
                $params['is_special_course'] = true;
3766
                $courseList[] = $params;
3767
            }
3768
        }
3769
3770
        return $courseList;
3771
    }
3772
3773
    /**
3774
     * Display courses (without special courses) as several HTML divs
3775
     * of course categories, as class userportal-catalog-item.
3776
     *
3777
     * @uses \displayCoursesInCategory() to display the courses themselves
3778
     *
3779
     * @param int  $user_id
3780
     * @param bool $load_dirs                        Whether to show the document quick-loader or not
3781
     * @param bool $useUserLanguageFilterIfAvailable
3782
     *
3783
     * @return array
3784
     */
3785
    public static function returnCourses(
3786
        $user_id,
3787
        $load_dirs = false,
3788
        $useUserLanguageFilterIfAvailable = true
3789
    ) {
3790
        $user_id = intval($user_id);
3791
        if (empty($user_id)) {
3792
            $user_id = api_get_user_id();
3793
        }
3794
        // Step 1: We get all the categories of the user
3795
        $table = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
3796
        $sql = "SELECT id, title FROM $table
3797
                WHERE user_id = '".$user_id."'
3798
                ORDER BY sort ASC";
3799
3800
        $result = Database::query($sql);
3801
        $listItems = [
3802
            'in_category' => [],
3803
            'not_category' => [],
3804
        ];
3805
        while ($row = Database::fetch_array($result)) {
3806
            // We simply display the title of the category.
3807
            $courseInCategory = self::returnCoursesCategories(
3808
                $row['id'],
3809
                $load_dirs,
3810
                $user_id,
3811
                $useUserLanguageFilterIfAvailable
3812
            );
3813
3814
            $params = [
3815
                'id_category' => $row['id'],
3816
                'title_category' => $row['title'],
3817
                'courses' => $courseInCategory,
3818
            ];
3819
            $listItems['in_category'][] = $params;
3820
        }
3821
3822
        // Step 2: We display the course without a user category.
3823
        $coursesNotCategory = self::returnCoursesCategories(
3824
            0,
3825
            $load_dirs,
3826
            $user_id,
3827
            $useUserLanguageFilterIfAvailable
3828
        );
3829
3830
        if ($coursesNotCategory) {
3831
            $listItems['not_category'] = $coursesNotCategory;
3832
        }
3833
3834
        return $listItems;
3835
    }
3836
3837
    /**
3838
     *  Display courses inside a category (without special courses) as HTML dics of
3839
     *  class userportal-course-item.
3840
     *
3841
     * @param int  $user_category_id                 User category id
3842
     * @param bool $load_dirs                        Whether to show the document quick-loader or not
3843
     * @param int  $user_id
3844
     * @param bool $useUserLanguageFilterIfAvailable
3845
     *
3846
     * @return array
3847
     */
3848
    public static function returnCoursesCategories(
3849
        $user_category_id,
3850
        $load_dirs = false,
3851
        $user_id = 0,
3852
        $useUserLanguageFilterIfAvailable = true
3853
    ) {
3854
        $user_id = $user_id ?: api_get_user_id();
3855
        $user_category_id = (int) $user_category_id;
3856
3857
        // Table definitions
3858
        $TABLECOURS = Database::get_main_table(TABLE_MAIN_COURSE);
3859
        $TABLECOURSUSER = Database::get_main_table(TABLE_MAIN_COURSE_USER);
3860
        $TABLE_ACCESS_URL_REL_COURSE = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
3861
        $current_url_id = api_get_current_access_url_id();
3862
3863
        // Get course list auto-register
3864
        $special_course_list = self::get_special_course_list();
3865
        $without_special_courses = '';
3866
        if (!empty($special_course_list)) {
3867
            $without_special_courses = ' AND course.id NOT IN ("'.implode('","', $special_course_list).'")';
3868
        }
3869
3870
        $userCategoryCondition = " (course_rel_user.user_course_cat = $user_category_id) ";
3871
        if (empty($user_category_id)) {
3872
            $userCategoryCondition = ' (course_rel_user.user_course_cat = 0 OR course_rel_user.user_course_cat IS NULL) ';
3873
        }
3874
3875
        $languageCondition = '';
3876
        $onlyInUserLanguage = api_get_configuration_value('my_courses_show_courses_in_user_language_only');
3877
        if ($useUserLanguageFilterIfAvailable && $onlyInUserLanguage) {
3878
            $userInfo = api_get_user_info(api_get_user_id());
3879
            if (!empty($userInfo['language'])) {
3880
                $languageCondition = " AND course.course_language = '".$userInfo['language']."' ";
3881
            }
3882
        }
3883
3884
        $sql = "SELECT DISTINCT
3885
                    course.id,
3886
                    course_rel_user.status status,
3887
                    course.code as course_code,
3888
                    user_course_cat,
3889
                    course_rel_user.sort
3890
                FROM $TABLECOURS course 
3891
                INNER JOIN $TABLECOURSUSER course_rel_user
3892
                ON (course.id = course_rel_user.c_id)
3893
                INNER JOIN $TABLE_ACCESS_URL_REL_COURSE url
3894
                ON (url.c_id = course.id)
3895
                WHERE
3896
                    course_rel_user.user_id = '".$user_id."' AND
3897
                    $userCategoryCondition
3898
                    $without_special_courses
3899
                    $languageCondition
3900
                ";
3901
        // If multiple URL access mode is enabled, only fetch courses
3902
        // corresponding to the current URL.
3903
        if (api_get_multiple_access_url() && $current_url_id != -1) {
3904
            $sql .= " AND access_url_id='".$current_url_id."'";
3905
        }
3906
        // Use user's classification for courses (if any).
3907
        $sql .= " ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
3908
        $result = Database::query($sql);
3909
3910
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
3911
        // Browse through all courses.
3912
        $courseAdded = [];
3913
        $courseList = [];
3914
        while ($row = Database::fetch_array($result)) {
3915
            $course_info = api_get_course_info_by_id($row['id']);
3916
3917
            if (isset($course_info['visibility']) &&
3918
                $course_info['visibility'] == COURSE_VISIBILITY_HIDDEN
3919
            ) {
3920
                continue;
3921
            }
3922
3923
            // Skip if already in list
3924
            if (in_array($course_info['real_id'], $courseAdded)) {
3925
                continue;
3926
            }
3927
            $course_info['id_session'] = null;
3928
            $course_info['status'] = $row['status'];
3929
            // For each course, get if there is any notification icon to show
3930
            // (something that would have changed since the user's last visit).
3931
            $showNotification = !api_get_configuration_value('hide_course_notification')
3932
                ? Display::show_notification($course_info)
3933
                : '';
3934
            $iconName = basename($course_info['course_image']);
3935
3936
            $params = [];
3937
            //Param (course_code) needed to get the student process
3938
            $params['course_code'] = $row['course_code'];
3939
            $params['code'] = $row['course_code'];
3940
3941
            if ($showCustomIcon === 'true' && $iconName != 'course.png') {
3942
                $params['thumbnails'] = $course_info['course_image'];
3943
                $params['image'] = $course_info['course_image_large'];
3944
            }
3945
3946
            $thumbnails = null;
3947
            $image = null;
3948
            if ($showCustomIcon === 'true' && $iconName != 'course.png') {
3949
                $thumbnails = $course_info['course_image'];
3950
                $image = $course_info['course_image_large'];
3951
            } else {
3952
                $image = Display::return_icon(
3953
                    'session_default.png',
3954
                    null,
3955
                    null,
3956
                    null,
3957
                    null,
3958
                    true
3959
                );
3960
            }
3961
3962
            $params['course_id'] = $course_info['real_id'];
3963
            $params['edit_actions'] = '';
3964
            $params['document'] = '';
3965
            if (api_is_platform_admin()) {
3966
                $params['edit_actions'] .= api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cidReq='.$course_info['code'];
3967
                if ($load_dirs) {
3968
                    $params['document'] = '<a id="document_preview_'.$course_info['real_id'].'_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3969
                               .Display::returnFontAwesomeIcon('folder-open').'</a>';
3970
                    $params['document'] .= Display::div(
3971
                        '',
3972
                        [
3973
                            'id' => 'document_result_'.$course_info['real_id'].'_0',
3974
                            'class' => 'document_preview_container',
3975
                        ]
3976
                    );
3977
                }
3978
            }
3979
            if ($load_dirs) {
3980
                $params['document'] = '<a id="document_preview_'.$course_info['real_id'].'_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3981
                    .Display::returnFontAwesomeIcon('folder-open').'</a>';
3982
                $params['document'] .= Display::div(
3983
                    '',
3984
                    [
3985
                        'id' => 'document_result_'.$course_info['real_id'].'_0',
3986
                        'class' => 'document_preview_container',
3987
                    ]
3988
                );
3989
            }
3990
3991
            $courseUrl = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/index.php?id_session=0';
3992
            $teachers = [];
3993
            if (api_get_setting('display_teacher_in_courselist') === 'true') {
3994
                $teachers = self::getTeachersFromCourse(
3995
                    $course_info['real_id'],
3996
                    true
3997
                );
3998
            }
3999
4000
            $params['status'] = $row['status'];
4001
            if (api_get_setting('display_coursecode_in_courselist') == 'true') {
4002
                $params['code_course'] = '('.$course_info['visual_code'].') ';
4003
            }
4004
4005
            $params['current_user_is_teacher'] = false;
4006
            /** @var array $teacher */
4007
            foreach ($teachers as $teacher) {
4008
                if ($teacher['id'] != $user_id) {
4009
                    continue;
4010
                }
4011
                $params['current_user_is_teacher'] = true;
4012
            }
4013
4014
            $params['visibility'] = $course_info['visibility'];
4015
            $params['link'] = $courseUrl;
4016
            $params['thumbnails'] = $thumbnails;
4017
            $params['image'] = $image;
4018
            $params['title'] = $course_info['title'];
4019
            $params['title_cut'] = $params['title'];
4020
            $params['category'] = $course_info['categoryName'];
4021
            $params['category_code'] = $course_info['categoryCode'];
4022
            $params['teachers'] = $teachers;
4023
4024
            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
4025
                $params['notifications'] = $showNotification;
4026
            }
4027
            $courseAdded[] = $course_info['real_id'];
4028
            $courseList[] = $params;
4029
        }
4030
4031
        return $courseList;
4032
    }
4033
4034
    /**
4035
     *  Display courses inside a category (without special courses) as HTML dics of
4036
     *  class userportal-course-item.
4037
     *
4038
     * @deprecated use self::returnCoursesCategories(0);
4039
     *
4040
     * @param int      User category id
4041
     * @param bool      Whether to show the document quick-loader or not
4042
     *
4043
     * @return array
4044
     */
4045
    public static function returnCoursesWithoutCategories($user_category_id, $load_dirs = false)
4046
    {
4047
        $user_id = api_get_user_id();
4048
        // Table definitions
4049
        $TABLECOURS = Database::get_main_table(TABLE_MAIN_COURSE);
4050
        $TABLECOURSUSER = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4051
        $TABLE_ACCESS_URL_REL_COURSE = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
4052
        $current_url_id = api_get_current_access_url_id();
4053
        $courseList = [];
4054
4055
        // Get course list auto-register
4056
        $special_course_list = self::get_special_course_list();
4057
4058
        $without_special_courses = '';
4059
        if (!empty($special_course_list)) {
4060
            $without_special_courses = ' AND course.id NOT IN ("'.implode('","', $special_course_list).'")';
4061
        }
4062
4063
        $sql = "SELECT
4064
                    course.id,
4065
                    course.title,
4066
                    course.code,
4067
                    course.subscribe subscr,
4068
                    course.unsubscribe unsubscr,
4069
                    course_rel_user.status status,
4070
                    course_rel_user.sort sort,
4071
                    course_rel_user.user_course_cat user_course_cat
4072
                FROM $TABLECOURS course 
4073
                INNER JOIN $TABLECOURSUSER course_rel_user
4074
                ON (course.id = course_rel_user.c_id)
4075
                INNER JOIN $TABLE_ACCESS_URL_REL_COURSE url
4076
                ON (url.c_id = course.id)
4077
                WHERE
4078
                    course_rel_user.user_id = $user_id AND
4079
                    course_rel_user.user_course_cat = $user_category_id
4080
                    $without_special_courses ";
4081
4082
        // If multiple URL access mode is enabled, only fetch courses
4083
        // corresponding to the current URL.
4084
        if (api_get_multiple_access_url() && $current_url_id != -1) {
4085
            $sql .= " AND url.c_id = course.id AND access_url_id = $current_url_id ";
4086
        }
4087
        // Use user's classification for courses (if any).
4088
        $sql .= " ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
4089
        $result = Database::query($sql);
4090
4091
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
4092
        // Browse through all courses.
4093
        while ($row = Database::fetch_array($result)) {
4094
            $course_info = api_get_course_info($row['code']);
4095
            if (isset($course_info['visibility']) &&
4096
                $course_info['visibility'] == COURSE_VISIBILITY_HIDDEN
4097
            ) {
4098
                continue;
4099
            }
4100
            $course_info['id_session'] = null;
4101
            $course_info['status'] = $row['status'];
4102
4103
            // For each course, get if there is any notification icon to show
4104
            // (something that would have changed since the user's last visit).
4105
            $showNotification = !api_get_configuration_value('hide_course_notification')
4106
                ? Display::show_notification($course_info)
4107
                : '';
4108
4109
            $thumbnails = null;
4110
            $image = null;
4111
            $iconName = basename($course_info['course_image']);
4112
            if ($showCustomIcon === 'true' && $iconName != 'course.png') {
4113
                $thumbnails = $course_info['course_image'];
4114
                $image = $course_info['course_image_large'];
4115
            } else {
4116
                $image = Display::return_icon(
4117
                    'session_default.png',
4118
                    null,
4119
                    null,
4120
                    null,
4121
                    null,
4122
                    true
4123
                );
4124
            }
4125
4126
            $params = [];
4127
            //Param (course_code) needed to get the student process
4128
            $params['course_code'] = $row['code'];
4129
            $params['edit_actions'] = '';
4130
            $params['document'] = '';
4131
            if (api_is_platform_admin()) {
4132
                $params['edit_actions'] .= api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cidReq='.$course_info['code'];
4133
                if ($load_dirs) {
4134
                    $params['document'] = '<a id="document_preview_'.$course_info['real_id'].'_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
4135
                               .Display::returnFontAwesomeIcon('folder-open').'</a>';
4136
                    $params['document'] .= Display::div('', ['id' => 'document_result_'.$course_info['real_id'].'_0', 'class' => 'document_preview_container']);
4137
                }
4138
            }
4139
            if ($load_dirs) {
4140
                $params['document'] = '<a id="document_preview_'.$course_info['real_id'].'_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
4141
                    .Display::returnFontAwesomeIcon('folder-open').'</a>';
4142
                $params['document'] .= Display::div('', ['id' => 'document_result_'.$course_info['real_id'].'_0', 'class' => 'document_preview_container']);
4143
            }
4144
4145
            $course_title_url = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/index.php?id_session=0';
4146
4147
            $teachers = [];
4148
            if (api_get_setting('display_teacher_in_courselist') === 'true') {
4149
                $teachers = self::getTeachersFromCourse(
4150
                    $course_info['real_id'],
4151
                    false
4152
                );
4153
            }
4154
            $params['status'] = $row['status'];
4155
4156
            if (api_get_setting('display_coursecode_in_courselist') == 'true') {
4157
                $params['code_course'] = '('.$course_info['visual_code'].') ';
4158
            }
4159
4160
            $params['visibility'] = $course_info['visibility'];
4161
            $params['link'] = $course_title_url;
4162
            $params['thumbnails'] = $thumbnails;
4163
            $params['image'] = $image;
4164
            $params['title'] = $course_info['title'];
4165
            $params['category'] = $course_info['categoryName'];
4166
            $params['teachers'] = $teachers;
4167
4168
            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
4169
                $params['notifications'] = $showNotification;
4170
            }
4171
4172
            $courseList[] = $params;
4173
        }
4174
4175
        return $courseList;
4176
    }
4177
4178
    /**
4179
     * Retrieves the user defined course categories.
4180
     *
4181
     * @param int $userId
4182
     *
4183
     * @return array
4184
     */
4185
    public static function get_user_course_categories($userId = 0)
4186
    {
4187
        $userId = empty($userId) ? api_get_user_id() : (int) $userId;
4188
        $table = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
4189
        $sql = "SELECT * FROM $table 
4190
                WHERE user_id = $userId
4191
                ORDER BY sort ASC
4192
                ";
4193
        $result = Database::query($sql);
4194
        $output = [];
4195
        while ($row = Database::fetch_array($result, 'ASSOC')) {
4196
            $output[$row['id']] = $row;
4197
        }
4198
4199
        return $output;
4200
    }
4201
4202
    /**
4203
     * Return an array the user_category id and title for the course $courseId for user $userId.
4204
     *
4205
     * @param $userId
4206
     * @param $courseId
4207
     *
4208
     * @return array
4209
     */
4210
    public static function getUserCourseCategoryForCourse($userId, $courseId)
4211
    {
4212
        $tblCourseRelUser = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4213
        $tblUserCategory = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
4214
        $courseId = intval($courseId);
4215
        $userId = intval($userId);
4216
4217
        $sql = "SELECT user_course_cat, title
4218
                FROM $tblCourseRelUser cru
4219
                LEFT JOIN $tblUserCategory ucc
4220
                ON cru.user_course_cat = ucc.id
4221
                WHERE
4222
                    cru.user_id = $userId AND c_id = $courseId ";
4223
4224
        $res = Database::query($sql);
4225
4226
        $data = [];
4227
        if (Database::num_rows($res) > 0) {
4228
            $data = Database::fetch_assoc($res);
4229
        }
4230
4231
        return $data;
4232
    }
4233
4234
    /**
4235
     * Get the course id based on the original id and field name in the extra fields.
4236
     * Returns 0 if course was not found.
4237
     *
4238
     * @param string $value    Original course code
4239
     * @param string $variable Original field name
4240
     *
4241
     * @return array
4242
     */
4243
    public static function getCourseInfoFromOriginalId($value, $variable)
4244
    {
4245
        $extraFieldValue = new ExtraFieldValue('course');
4246
        $result = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
4247
            $variable,
4248
            $value
4249
        );
4250
4251
        if (!empty($result)) {
4252
            $courseInfo = api_get_course_info_by_id($result['item_id']);
4253
4254
            return $courseInfo;
4255
        }
4256
4257
        return [];
4258
    }
4259
4260
    /**
4261
     * Display code for one specific course a logged in user is subscribed to.
4262
     * Shows a link to the course, what's new icons...
4263
     *
4264
     * $my_course['d'] - course directory
4265
     * $my_course['i'] - course title
4266
     * $my_course['c'] - visual course code
4267
     * $my_course['k']  - system course code
4268
     *
4269
     * @param   array       Course details
4270
     * @param   int     Session ID
4271
     * @param   string      CSS class to apply to course entry
4272
     * @param   bool     Whether the session is supposedly accessible now
4273
     * (not in the case it has passed and is in invisible/unaccessible mode)
4274
     * @param bool      Whether to show the document quick-loader or not
4275
     *
4276
     * @return string The HTML to be printed for the course entry
4277
     *
4278
     * @version 1.0.3
4279
     *
4280
     * @todo refactor into different functions for database calls | logic | display
4281
     * @todo replace single-character $my_course['d'] indices
4282
     * @todo move code for what's new icons to a separate function to clear things up
4283
     * @todo add a parameter user_id so that it is possible to show the
4284
     * courselist of other users (=generalisation).
4285
     * This will prevent having to write a new function for this.
4286
     */
4287
    public static function get_logged_user_course_html(
4288
        $course,
4289
        $session_id = 0,
4290
        $class = 'courses',
4291
        $session_accessible = true,
4292
        $load_dirs = false
4293
    ) {
4294
        $now = date('Y-m-d h:i:s');
4295
        $user_id = api_get_user_id();
4296
        $course_info = api_get_course_info_by_id($course['real_id']);
4297
        $course_visibility = $course_info['visibility'];
4298
4299
        if ($course_visibility == COURSE_VISIBILITY_HIDDEN) {
4300
            return '';
4301
        }
4302
4303
        $userInCourseStatus = self::getUserInCourseStatus(
4304
            $user_id,
4305
            $course_info['real_id']
4306
        );
4307
4308
        $course_info['status'] = empty($session_id) ? $userInCourseStatus : STUDENT;
4309
        $course_info['id_session'] = $session_id;
4310
4311
        $is_coach = api_is_coach($session_id, $course_info['real_id']);
4312
4313
        // Display course entry.
4314
        // Show a hyperlink to the course, unless the course is closed and user is not course admin.
4315
        $session_url = '';
4316
        $params = [];
4317
        $params['icon'] = Display::return_icon(
4318
            'blackboard_blue.png',
4319
            null,
4320
            [],
4321
            ICON_SIZE_LARGE,
4322
            null,
4323
            true
4324
        );
4325
        $params['real_id'] = $course_info['real_id'];
4326
4327
        // Display the "what's new" icons
4328
        $notifications = '';
4329
        if (
4330
            ($course_visibility != COURSE_VISIBILITY_CLOSED && $course_visibility != COURSE_VISIBILITY_HIDDEN) ||
4331
            !api_get_configuration_value('hide_course_notification')
4332
        ) {
4333
            $notifications .= Display::show_notification($course_info);
4334
        }
4335
4336
        if ($session_accessible) {
4337
            if ($course_visibility != COURSE_VISIBILITY_CLOSED ||
4338
                $userInCourseStatus == COURSEMANAGER
4339
            ) {
4340
                if (empty($course_info['id_session'])) {
4341
                    $course_info['id_session'] = 0;
4342
                }
4343
4344
                $sessionCourseAvailable = false;
4345
                $sessionCourseStatus = api_get_session_visibility($session_id, $course_info['real_id']);
4346
4347
                if (in_array(
4348
                    $sessionCourseStatus,
4349
                    [SESSION_VISIBLE_READ_ONLY, SESSION_VISIBLE, SESSION_AVAILABLE]
4350
                )) {
4351
                    $sessionCourseAvailable = true;
4352
                }
4353
4354
                if ($userInCourseStatus == COURSEMANAGER || $sessionCourseAvailable) {
4355
                    $session_url = $course_info['course_public_url'].'?id_session='.$course_info['id_session'];
4356
                    $session_title = '<a href="'.$session_url.'">'.$course_info['name'].'</a>'.$notifications;
4357
                } else {
4358
                    $session_title = $course_info['name'];
4359
                }
4360
            } else {
4361
                $session_title =
4362
                    $course_info['name'].' '.
4363
                    Display::tag('span', get_lang('CourseClosed'), ['class' => 'item_closed']);
4364
            }
4365
        } else {
4366
            $session_title = $course_info['name'];
4367
        }
4368
4369
        $thumbnails = null;
4370
        $image = null;
4371
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
4372
        $iconName = basename($course_info['course_image']);
4373
4374
        if ($showCustomIcon === 'true' && $iconName != 'course.png') {
4375
            $thumbnails = $course_info['course_image'];
4376
            $image = $course_info['course_image_large'];
4377
        } else {
4378
            $image = Display::return_icon(
4379
                'session_default.png',
4380
                null,
4381
                null,
4382
                null,
4383
                null,
4384
                true
4385
            );
4386
        }
4387
        $params['thumbnails'] = $thumbnails;
4388
        $params['image'] = $image;
4389
        $params['link'] = $session_url;
4390
        $params['title'] = $session_title;
4391
        $params['edit_actions'] = '';
4392
        $params['document'] = '';
4393
        $params['category'] = $course_info['categoryName'];
4394
4395
        if ($course_visibility != COURSE_VISIBILITY_CLOSED &&
4396
            $course_visibility != COURSE_VISIBILITY_HIDDEN
4397
        ) {
4398
            if (api_is_platform_admin()) {
4399
                $params['edit_actions'] .= api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cidReq='.$course_info['code'];
4400
                if ($load_dirs) {
4401
                    $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);">'.
4402
                        Display::returnFontAwesomeIcon('folder-open').'</a>';
4403
                    $params['document'] .= Display::div('', [
4404
                        'id' => 'document_result_'.$course_info['real_id'].'_'.$course_info['id_session'],
4405
                        'class' => 'document_preview_container',
4406
                    ]);
4407
                }
4408
            }
4409
        }
4410
        if (api_get_setting('display_teacher_in_courselist') === 'true') {
4411
            $teacher_list = self::getTeachersFromCourse(
4412
                $course_info['real_id'],
4413
                true
4414
            );
4415
4416
            $course_coachs = self::get_coachs_from_course(
4417
                $course_info['id_session'],
4418
                $course_info['real_id']
4419
            );
4420
            $params['teachers'] = $teacher_list;
4421
4422
            if (($course_info['status'] == STUDENT && !empty($course_info['id_session'])) ||
4423
                ($is_coach && $course_info['status'] != COURSEMANAGER)
4424
            ) {
4425
                $params['coaches'] = $course_coachs;
4426
            }
4427
        }
4428
        $special = isset($course['special_course']) ? true : false;
4429
        $params['title'] = $session_title;
4430
        $params['special'] = $special;
4431
        $params['code'] = $course_info['visual_code'];
4432
        $params['extra'] = '';
4433
        $html = $params;
4434
4435
        $session_category_id = null;
4436
        if (1) {
4437
            $session = '';
4438
            $active = false;
4439
            if (!empty($course_info['id_session'])) {
4440
                $session = api_get_session_info($course_info['id_session']);
4441
                $sessionCoachName = '';
4442
                if (!empty($session['id_coach'])) {
4443
                    $coachInfo = api_get_user_info($session['id_coach']);
4444
                    $sessionCoachName = $coachInfo['complete_name'];
4445
                }
4446
4447
                $session_category_id = self::get_session_category_id_by_session_id($course_info['id_session']);
4448
4449
                if (
4450
                    $session['access_start_date'] == '0000-00-00 00:00:00' || empty($session['access_start_date']) ||
4451
                    $session['access_start_date'] == '0000-00-00'
4452
                ) {
4453
                    $session['dates'] = '';
4454
                    if (api_get_setting('show_session_coach') === 'true') {
4455
                        $session['coach'] = get_lang('GeneralCoach').': '.$sessionCoachName;
4456
                    }
4457
                    $active = true;
4458
                } else {
4459
                    $session['dates'] = ' - '.get_lang('From').' '.$session['access_start_date'].' '.get_lang('To').' '.$session['access_end_date'];
4460
                    if (api_get_setting('show_session_coach') === 'true') {
4461
                        $session['coach'] = get_lang('GeneralCoach').': '.$sessionCoachName;
4462
                    }
4463
                    $date_start = $session['access_start_date'];
4464
                    $date_end = $session['access_end_date'];
4465
                    $active = !$date_end ? ($date_start <= $now) : ($date_start <= $now && $date_end >= $now);
4466
                }
4467
            }
4468
            $user_course_category = '';
4469
            if (isset($course_info['user_course_cat'])) {
4470
                $user_course_category = $course_info['user_course_cat'];
4471
            }
4472
            $output = [
4473
                $user_course_category,
4474
                $html,
4475
                $course_info['id_session'],
4476
                $session,
4477
                'active' => $active,
4478
                'session_category_id' => $session_category_id,
4479
            ];
4480
4481
            if (Skill::isAllowed($user_id, false)) {
4482
                $em = Database::getManager();
4483
                $objUser = api_get_user_entity($user_id);
4484
                $objCourse = $em->find('ChamiloCoreBundle:Course', $course['real_id']);
4485
                $objSession = $em->find('ChamiloCoreBundle:Session', $session_id);
4486
4487
                $skill = $em->getRepository('ChamiloCoreBundle:Skill')->getLastByUser($objUser, $objCourse, $objSession);
4488
4489
                $output['skill'] = null;
4490
                if ($skill) {
4491
                    $output['skill']['name'] = $skill->getName();
4492
                    $output['skill']['icon'] = $skill->getIcon();
4493
                }
4494
            }
4495
        } else {
4496
            $output = [$course_info['user_course_cat'], $html];
4497
        }
4498
4499
        return $output;
4500
    }
4501
4502
    /**
4503
     * @param string $source_course_code
4504
     * @param int    $source_session_id
4505
     * @param string $destination_course_code
4506
     * @param int    $destination_session_id
4507
     * @param array  $params
4508
     *
4509
     * @return bool
4510
     */
4511
    public static function copy_course(
4512
        $source_course_code,
4513
        $source_session_id,
4514
        $destination_course_code,
4515
        $destination_session_id,
4516
        $params = []
4517
    ) {
4518
        $course_info = api_get_course_info($source_course_code);
4519
4520
        if (!empty($course_info)) {
4521
            $cb = new CourseBuilder('', $course_info);
4522
            $course = $cb->build($source_session_id, $source_course_code, true);
4523
            $course_restorer = new CourseRestorer($course);
4524
            $course_restorer->skip_content = $params;
4525
            $course_restorer->restore(
4526
                $destination_course_code,
4527
                $destination_session_id,
4528
                true,
4529
                true
4530
            );
4531
4532
            return true;
4533
        }
4534
4535
        return false;
4536
    }
4537
4538
    /**
4539
     * A simpler version of the copy_course, the function creates an empty course with an autogenerated course code.
4540
     *
4541
     * @param string $new_title new course title
4542
     * @param string source course code
4543
     * @param int source session id
4544
     * @param int destination session id
4545
     * @param array $params
4546
     *
4547
     * @return array
4548
     */
4549
    public static function copy_course_simple(
4550
        $new_title,
4551
        $source_course_code,
4552
        $source_session_id = 0,
4553
        $destination_session_id = 0,
4554
        $params = []
4555
    ) {
4556
        $source_course_info = api_get_course_info($source_course_code);
4557
        if (!empty($source_course_info)) {
4558
            $new_course_code = self::generate_nice_next_course_code($source_course_code);
4559
            if ($new_course_code) {
4560
                $new_course_info = self::create_course(
4561
                    $new_title,
4562
                    $new_course_code,
4563
                    false
4564
                );
4565
                if (!empty($new_course_info['code'])) {
4566
                    $result = self::copy_course(
4567
                        $source_course_code,
4568
                        $source_session_id,
4569
                        $new_course_info['code'],
4570
                        $destination_session_id,
4571
                        $params
4572
                    );
4573
                    if ($result) {
4574
                        return $new_course_info;
4575
                    }
4576
                }
4577
            }
4578
        }
4579
4580
        return false;
4581
    }
4582
4583
    /**
4584
     * Creates a new course code based in a given code.
4585
     *
4586
     * @param string    wanted code
4587
     * <code>    $wanted_code = 'curse' if there are in the DB codes like curse1 curse2 the function will return: course3</code>
4588
     * if the course code doest not exist in the DB the same course code will be returned
4589
     *
4590
     * @return string wanted unused code
4591
     */
4592
    public static function generate_nice_next_course_code($wanted_code)
4593
    {
4594
        $course_code_ok = !self::course_code_exists($wanted_code);
4595
        if (!$course_code_ok) {
4596
            $wanted_code = self::generate_course_code($wanted_code);
4597
            $table = Database::get_main_table(TABLE_MAIN_COURSE);
4598
            $wanted_code = Database::escape_string($wanted_code);
4599
            $sql = "SELECT count(id) as count
4600
                    FROM $table
4601
                    WHERE code LIKE '$wanted_code%'";
4602
            $result = Database::query($sql);
4603
            if (Database::num_rows($result) > 0) {
4604
                $row = Database::fetch_array($result);
4605
                $count = $row['count'] + 1;
4606
                $wanted_code = $wanted_code.'_'.$count;
4607
                $result = api_get_course_info($wanted_code);
4608
                if (empty($result)) {
4609
                    return $wanted_code;
4610
                }
4611
            }
4612
4613
            return false;
4614
        }
4615
4616
        return $wanted_code;
4617
    }
4618
4619
    /**
4620
     * Gets the status of the users agreement in a course course-session.
4621
     *
4622
     * @param int    $user_id
4623
     * @param string $course_code
4624
     * @param int    $session_id
4625
     *
4626
     * @return bool
4627
     */
4628
    public static function is_user_accepted_legal($user_id, $course_code, $session_id = 0)
4629
    {
4630
        $user_id = intval($user_id);
4631
        $course_code = Database::escape_string($course_code);
4632
        $session_id = intval($session_id);
4633
4634
        $courseInfo = api_get_course_info($course_code);
4635
        $courseId = $courseInfo['real_id'];
4636
4637
        // Course legal
4638
        $enabled = api_get_plugin_setting('courselegal', 'tool_enable');
4639
4640
        if ($enabled == 'true') {
4641
            require_once api_get_path(SYS_PLUGIN_PATH).'courselegal/config.php';
4642
            $plugin = CourseLegalPlugin::create();
4643
4644
            return $plugin->isUserAcceptedLegal($user_id, $course_code, $session_id);
4645
        }
4646
4647
        if (empty($session_id)) {
4648
            $table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4649
            $sql = "SELECT legal_agreement FROM $table
4650
                    WHERE user_id = $user_id AND c_id = $courseId ";
4651
            $result = Database::query($sql);
4652
            if (Database::num_rows($result) > 0) {
4653
                $result = Database::fetch_array($result);
4654
                if ($result['legal_agreement'] == 1) {
4655
                    return true;
4656
                }
4657
            }
4658
4659
            return false;
4660
        } else {
4661
            $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4662
            $sql = "SELECT legal_agreement FROM $table
4663
                    WHERE user_id = $user_id AND c_id = $courseId AND session_id = $session_id";
4664
            $result = Database::query($sql);
4665
            if (Database::num_rows($result) > 0) {
4666
                $result = Database::fetch_array($result);
4667
                if ($result['legal_agreement'] == 1) {
4668
                    return true;
4669
                }
4670
            }
4671
4672
            return false;
4673
        }
4674
    }
4675
4676
    /**
4677
     * Saves the user-course legal agreement.
4678
     *
4679
     * @param   int user id
4680
     * @param   string course code
4681
     * @param   int session id
4682
     *
4683
     * @return mixed
4684
     */
4685
    public static function save_user_legal($user_id, $course_code, $session_id = null)
4686
    {
4687
        // Course plugin legal
4688
        $enabled = api_get_plugin_setting('courselegal', 'tool_enable');
4689
        if ($enabled == 'true') {
4690
            require_once api_get_path(SYS_PLUGIN_PATH).'courselegal/config.php';
4691
            $plugin = CourseLegalPlugin::create();
4692
4693
            return $plugin->saveUserLegal($user_id, $course_code, $session_id);
4694
        }
4695
4696
        $user_id = intval($user_id);
4697
        $course_code = Database::escape_string($course_code);
4698
        $session_id = intval($session_id);
4699
        $courseInfo = api_get_course_info($course_code);
4700
        $courseId = $courseInfo['real_id'];
4701
4702
        if (empty($session_id)) {
4703
            $table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4704
            $sql = "UPDATE $table SET legal_agreement = '1'
4705
                    WHERE user_id = $user_id AND c_id  = $courseId ";
4706
            Database::query($sql);
4707
        } else {
4708
            $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4709
            $sql = "UPDATE  $table SET legal_agreement = '1'
4710
                    WHERE user_id = $user_id AND c_id = $courseId AND session_id = $session_id";
4711
            Database::query($sql);
4712
        }
4713
    }
4714
4715
    /**
4716
     * @param int $user_id
4717
     * @param int $course_id
4718
     * @param int $session_id
4719
     * @param int $url_id
4720
     *
4721
     * @return bool
4722
     */
4723
    public static function get_user_course_vote($user_id, $course_id, $session_id = 0, $url_id = 0)
4724
    {
4725
        $table_user_course_vote = Database::get_main_table(TABLE_MAIN_USER_REL_COURSE_VOTE);
4726
        $session_id = !isset($session_id) ? api_get_session_id() : intval($session_id);
4727
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4728
        $user_id = intval($user_id);
4729
4730
        if (empty($user_id)) {
4731
            return false;
4732
        }
4733
4734
        $params = [
4735
            'user_id' => $user_id,
4736
            'c_id' => $course_id,
4737
            'session_id' => $session_id,
4738
            'url_id' => $url_id,
4739
        ];
4740
4741
        $result = Database::select(
4742
            'vote',
4743
            $table_user_course_vote,
4744
            [
4745
                'where' => [
4746
                    'user_id = ? AND c_id = ? AND session_id = ? AND url_id = ?' => $params,
4747
                ],
4748
            ],
4749
            'first'
4750
        );
4751
        if (!empty($result)) {
4752
            return $result['vote'];
4753
        }
4754
4755
        return false;
4756
    }
4757
4758
    /**
4759
     * @param int $course_id
4760
     * @param int $session_id
4761
     * @param int $url_id
4762
     *
4763
     * @return array
4764
     */
4765
    public static function get_course_ranking(
4766
        $course_id,
4767
        $session_id = 0,
4768
        $url_id = 0
4769
    ) {
4770
        $table_course_ranking = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
4771
4772
        $session_id = empty($session_id) ? api_get_session_id() : intval($session_id);
4773
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4774
        $now = api_get_utc_datetime();
4775
4776
        $params = [
4777
            'c_id' => $course_id,
4778
            'session_id' => $session_id,
4779
            'url_id' => $url_id,
4780
            'creation_date' => $now,
4781
        ];
4782
4783
        $result = Database::select(
4784
            'c_id, accesses, total_score, users',
4785
            $table_course_ranking,
4786
            ['where' => ['c_id = ? AND session_id = ? AND url_id = ?' => $params]],
4787
            'first'
4788
        );
4789
4790
        $point_average_in_percentage = 0;
4791
        $point_average_in_star = 0;
4792
        $users_who_voted = 0;
4793
4794
        if (!empty($result['users'])) {
4795
            $users_who_voted = $result['users'];
4796
            $point_average_in_percentage = round($result['total_score'] / $result['users'] * 100 / 5, 2);
4797
            $point_average_in_star = round($result['total_score'] / $result['users'], 1);
4798
        }
4799
4800
        $result['user_vote'] = false;
4801
        if (!api_is_anonymous()) {
4802
            $result['user_vote'] = self::get_user_course_vote(api_get_user_id(), $course_id, $session_id, $url_id);
4803
        }
4804
4805
        $result['point_average'] = $point_average_in_percentage;
4806
        $result['point_average_star'] = $point_average_in_star;
4807
        $result['users_who_voted'] = $users_who_voted;
4808
4809
        return $result;
4810
    }
4811
4812
    /**
4813
     * Updates the course ranking.
4814
     *
4815
     * @param int   course id
4816
     * @param int $session_id
4817
     * @param int    url id
4818
     * @param $points_to_add
4819
     * @param bool $add_access
4820
     * @param bool $add_user
4821
     *
4822
     * @return array
4823
     */
4824
    public static function update_course_ranking(
4825
        $course_id = 0,
4826
        $session_id = 0,
4827
        $url_id = 0,
4828
        $points_to_add = null,
4829
        $add_access = true,
4830
        $add_user = true
4831
    ) {
4832
        // Course catalog stats modifications see #4191
4833
        $table_course_ranking = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
4834
        $now = api_get_utc_datetime();
4835
        $course_id = empty($course_id) ? api_get_course_int_id() : intval($course_id);
4836
        $session_id = empty($session_id) ? api_get_session_id() : intval($session_id);
4837
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4838
4839
        $params = [
4840
            'c_id' => $course_id,
4841
            'session_id' => $session_id,
4842
            'url_id' => $url_id,
4843
            'creation_date' => $now,
4844
            'total_score' => 0,
4845
            'users' => 0,
4846
        ];
4847
4848
        $result = Database::select(
4849
            'id, accesses, total_score, users',
4850
            $table_course_ranking,
4851
            ['where' => ['c_id = ? AND session_id = ? AND url_id = ?' => $params]],
4852
            'first'
4853
        );
4854
4855
        // Problem here every time we load the courses/XXXX/index.php course home page we update the access
4856
        if (empty($result)) {
4857
            if ($add_access) {
4858
                $params['accesses'] = 1;
4859
            }
4860
            //The votes and users are empty
4861
            if (isset($points_to_add) && !empty($points_to_add)) {
4862
                $params['total_score'] = intval($points_to_add);
4863
            }
4864
            if ($add_user) {
4865
                $params['users'] = 1;
4866
            }
4867
            $result = Database::insert($table_course_ranking, $params);
4868
        } else {
4869
            $my_params = [];
4870
4871
            if ($add_access) {
4872
                $my_params['accesses'] = intval($result['accesses']) + 1;
4873
            }
4874
            if (isset($points_to_add) && !empty($points_to_add)) {
4875
                $my_params['total_score'] = $result['total_score'] + $points_to_add;
4876
            }
4877
            if ($add_user) {
4878
                $my_params['users'] = $result['users'] + 1;
4879
            }
4880
4881
            if (!empty($my_params)) {
4882
                $result = Database::update(
4883
                    $table_course_ranking,
4884
                    $my_params,
4885
                    ['c_id = ? AND session_id = ? AND url_id = ?' => $params]
4886
                );
4887
            }
4888
        }
4889
4890
        return $result;
4891
    }
4892
4893
    /**
4894
     * Add user vote to a course.
4895
     *
4896
     * @param   int user id
4897
     * @param   int vote [1..5]
4898
     * @param   int course id
4899
     * @param   int session id
4900
     * @param   int url id (access_url_id)
4901
     *
4902
     * @return false|string 'added', 'updated' or 'nothing'
4903
     */
4904
    public static function add_course_vote(
4905
        $user_id,
4906
        $vote,
4907
        $course_id,
4908
        $session_id = 0,
4909
        $url_id = 0
4910
    ) {
4911
        $table_user_course_vote = Database::get_main_table(TABLE_MAIN_USER_REL_COURSE_VOTE);
4912
        $course_id = empty($course_id) ? api_get_course_int_id() : intval($course_id);
4913
4914
        if (empty($course_id) || empty($user_id)) {
4915
            return false;
4916
        }
4917
4918
        if (!in_array($vote, [1, 2, 3, 4, 5])) {
4919
            return false;
4920
        }
4921
4922
        $session_id = empty($session_id) ? api_get_session_id() : intval($session_id);
4923
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4924
        $vote = intval($vote);
4925
4926
        $params = [
4927
            'user_id' => intval($user_id),
4928
            'c_id' => $course_id,
4929
            'session_id' => $session_id,
4930
            'url_id' => $url_id,
4931
            'vote' => $vote,
4932
        ];
4933
4934
        $action_done = 'nothing';
4935
        $result = Database::select(
4936
            'id, vote',
4937
            $table_user_course_vote,
4938
            ['where' => ['user_id = ? AND c_id = ? AND session_id = ? AND url_id = ?' => $params]],
4939
            'first'
4940
        );
4941
4942
        if (empty($result)) {
4943
            Database::insert($table_user_course_vote, $params);
4944
            $points_to_add = $vote;
4945
            $add_user = true;
4946
            $action_done = 'added';
4947
        } else {
4948
            $my_params = ['vote' => $vote];
4949
            $points_to_add = $vote - $result['vote'];
4950
            $add_user = false;
4951
4952
            Database::update(
4953
                $table_user_course_vote,
4954
                $my_params,
4955
                ['user_id = ? AND c_id = ? AND session_id = ? AND url_id = ?' => $params]
4956
            );
4957
            $action_done = 'updated';
4958
        }
4959
4960
        // Current points
4961
        if (!empty($points_to_add)) {
4962
            self::update_course_ranking(
4963
                $course_id,
4964
                $session_id,
4965
                $url_id,
4966
                $points_to_add,
4967
                false,
4968
                $add_user
4969
            );
4970
        }
4971
4972
        return $action_done;
4973
    }
4974
4975
    /**
4976
     * Remove course ranking + user votes.
4977
     *
4978
     * @param int $course_id
4979
     * @param int $session_id
4980
     * @param int $url_id
4981
     */
4982
    public static function remove_course_ranking($course_id, $session_id, $url_id = null)
4983
    {
4984
        $table_course_ranking = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
4985
        $table_user_course_vote = Database::get_main_table(TABLE_MAIN_USER_REL_COURSE_VOTE);
4986
4987
        if (!empty($course_id) && isset($session_id)) {
4988
            $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4989
            $params = [
4990
                'c_id' => $course_id,
4991
                'session_id' => $session_id,
4992
                'url_id' => $url_id,
4993
            ];
4994
            Database::delete($table_course_ranking, ['c_id = ? AND session_id = ? AND url_id = ?' => $params]);
4995
            Database::delete($table_user_course_vote, ['c_id = ? AND session_id = ? AND url_id = ?' => $params]);
4996
        }
4997
    }
4998
4999
    /**
5000
     * Returns an array with the hottest courses.
5001
     *
5002
     * @param int $days  number of days
5003
     * @param int $limit number of hottest courses
5004
     *
5005
     * @return array
5006
     */
5007
    public static function return_hot_courses($days = 30, $limit = 6)
5008
    {
5009
        if (api_is_invitee()) {
5010
            return [];
5011
        }
5012
5013
        $limit = intval($limit);
5014
5015
        // Getting my courses
5016
        $my_course_list = self::get_courses_list_by_user_id(api_get_user_id());
5017
5018
        $my_course_code_list = [];
5019
        foreach ($my_course_list as $course) {
5020
            $my_course_code_list[$course['real_id']] = $course['real_id'];
5021
        }
5022
5023
        if (api_is_drh()) {
5024
            $courses = self::get_courses_followed_by_drh(api_get_user_id());
5025
            foreach ($courses as $course) {
5026
                $my_course_code_list[$course['real_id']] = $course['real_id'];
5027
            }
5028
        }
5029
5030
        $table_course_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
5031
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
5032
        $table_course_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
5033
        $urlId = api_get_current_access_url_id();
5034
        //$table_course_access table uses the now() and interval ...
5035
        $now = api_get_utc_datetime();
5036
        $sql = "SELECT COUNT(course_access_id) course_count, a.c_id, visibility
5037
                FROM $table_course c
5038
                INNER JOIN $table_course_access a
5039
                ON (c.id = a.c_id)
5040
                INNER JOIN $table_course_url u
5041
                ON u.c_id = c.id
5042
                WHERE
5043
                    u.access_url_id = $urlId AND
5044
                    login_course_date <= '$now' AND
5045
                    login_course_date > DATE_SUB('$now', INTERVAL $days DAY) AND
5046
                    visibility <> ".COURSE_VISIBILITY_CLOSED." AND
5047
                    visibility <> ".COURSE_VISIBILITY_HIDDEN." 
5048
                GROUP BY a.c_id
5049
                ORDER BY course_count DESC
5050
                LIMIT $limit
5051
            ";
5052
5053
        $result = Database::query($sql);
5054
        $courses = [];
5055
5056
        if (Database::num_rows($result)) {
5057
            $courses = Database::store_result($result, 'ASSOC');
5058
            $courses = self::processHotCourseItem($courses, $my_course_code_list);
5059
        }
5060
5061
        return $courses;
5062
    }
5063
5064
    /**
5065
     * @param array $courses
5066
     * @param array $my_course_code_list
5067
     *
5068
     * @return mixed
5069
     */
5070
    public static function processHotCourseItem($courses, $my_course_code_list = [])
5071
    {
5072
        $hotCourses = [];
5073
        $ajax_url = api_get_path(WEB_AJAX_PATH).'course.ajax.php?a=add_course_vote';
5074
        $stok = Security::get_existing_token();
5075
        $user_id = api_get_user_id();
5076
5077
        foreach ($courses as $courseId) {
5078
            $course_info = api_get_course_info_by_id($courseId['c_id']);
5079
            $courseCode = $course_info['code'];
5080
            $categoryCode = !empty($course_info['categoryCode']) ? $course_info['categoryCode'] : "";
5081
            $my_course = $course_info;
5082
            $my_course['go_to_course_button'] = '';
5083
            $my_course['register_button'] = '';
5084
5085
            $access_link = self::get_access_link_by_user(
5086
                api_get_user_id(),
5087
                $course_info,
5088
                $my_course_code_list
5089
            );
5090
5091
            $userRegisteredInCourse = self::is_user_subscribed_in_course($user_id, $course_info['code']);
5092
            $userRegisteredInCourseAsTeacher = self::is_course_teacher($user_id, $course_info['code']);
5093
            $userRegistered = $userRegisteredInCourse && $userRegisteredInCourseAsTeacher;
5094
            $my_course['is_registered'] = $userRegistered;
5095
            $my_course['title_cut'] = cut($course_info['title'], 45);
5096
5097
            // Course visibility
5098
            if ($access_link && in_array('register', $access_link)) {
5099
                $my_course['register_button'] = Display::url(
5100
                    get_lang('Subscribe').' '.
5101
                    Display::returnFontAwesomeIcon('sign-in'),
5102
                    api_get_path(WEB_COURSE_PATH).$course_info['path'].
5103
                     '/index.php?action=subscribe&sec_token='.$stok,
5104
                    [
5105
                        'class' => 'btn btn-success btn-sm',
5106
                        'title' => get_lang('Subscribe'),
5107
                        'aria-label' => get_lang('Subscribe'),
5108
                    ]
5109
                );
5110
            }
5111
5112
            if ($access_link && in_array('enter', $access_link) ||
5113
                $course_info['visibility'] == COURSE_VISIBILITY_OPEN_WORLD
5114
            ) {
5115
                $my_course['go_to_course_button'] = Display::url(
5116
                    get_lang('GoToCourse').' '.
5117
                    Display::returnFontAwesomeIcon('share'),
5118
                    api_get_path(WEB_COURSE_PATH).$course_info['path'].'/index.php',
5119
                    [
5120
                        'class' => 'btn btn-default btn-sm',
5121
                        'title' => get_lang('GoToCourse'),
5122
                        'aria-label' => get_lang('GoToCourse'),
5123
                    ]
5124
                );
5125
            }
5126
5127
            if ($access_link && in_array('unsubscribe', $access_link)) {
5128
                $my_course['unsubscribe_button'] = Display::url(
5129
                    get_lang('Unreg').' '.
5130
                    Display::returnFontAwesomeIcon('sign-out'),
5131
                    api_get_path(WEB_CODE_PATH).'auth/courses.php?action=unsubscribe&unsubscribe='.$courseCode
5132
                    .'&sec_token='.$stok.'&category_code='.$categoryCode,
5133
                    [
5134
                        'class' => 'btn btn-danger btn-sm',
5135
                        'title' => get_lang('Unreg'),
5136
                        'aria-label' => get_lang('Unreg'),
5137
                    ]
5138
                );
5139
            }
5140
5141
            // start buycourse validation
5142
            // display the course price and buy button if the buycourses plugin is enabled and this course is configured
5143
            $plugin = BuyCoursesPlugin::create();
5144
            $isThisCourseInSale = $plugin->buyCoursesForGridCatalogValidator(
5145
                $course_info['real_id'],
5146
                BuyCoursesPlugin::PRODUCT_TYPE_COURSE
5147
            );
5148
            if ($isThisCourseInSale) {
5149
                // set the price label
5150
                $my_course['price'] = $isThisCourseInSale['html'];
5151
                // set the Buy button instead register.
5152
                if ($isThisCourseInSale['verificator'] && !empty($my_course['register_button'])) {
5153
                    $my_course['register_button'] = $plugin->returnBuyCourseButton(
5154
                        $course_info['real_id'],
5155
                        BuyCoursesPlugin::PRODUCT_TYPE_COURSE
5156
                    );
5157
                }
5158
            }
5159
            // end buycourse validation
5160
5161
            // Description
5162
            $my_course['description_button'] = self::returnDescriptionButton($course_info);
5163
            $my_course['teachers'] = self::getTeachersFromCourse($course_info['real_id'], true);
5164
            $point_info = self::get_course_ranking($course_info['real_id'], 0);
5165
            $my_course['rating_html'] = '';
5166
            if (api_get_configuration_value('hide_course_rating') === false) {
5167
                $my_course['rating_html'] = Display::return_rating_system(
5168
                    'star_'.$course_info['real_id'],
5169
                    $ajax_url.'&course_id='.$course_info['real_id'],
5170
                    $point_info
5171
                );
5172
            }
5173
            $hotCourses[] = $my_course;
5174
        }
5175
5176
        return $hotCourses;
5177
    }
5178
5179
    /**
5180
     * @param int $limit
5181
     *
5182
     * @return array
5183
     */
5184
    public static function return_most_accessed_courses($limit = 5)
5185
    {
5186
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
5187
        $params['url_id'] = api_get_current_access_url_id();
5188
5189
        $result = Database::select(
5190
            'c_id, accesses, total_score, users',
5191
            $table,
5192
            ['where' => ['url_id = ?' => $params], 'order' => 'accesses DESC', 'limit' => $limit],
5193
            'all',
5194
            true
5195
        );
5196
5197
        return $result;
5198
    }
5199
5200
    /**
5201
     * Get courses count.
5202
     *
5203
     * @param int $access_url_id Access URL ID (optional)
5204
     * @param int $visibility
5205
     *
5206
     * @return int Number of courses
5207
     */
5208
    public static function count_courses($access_url_id = null, $visibility = null)
5209
    {
5210
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
5211
        $table_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
5212
        $sql = "SELECT count(c.id) FROM $table_course c";
5213
        if (!empty($access_url_id) && $access_url_id == intval($access_url_id)) {
5214
            $sql .= ", $table_course_rel_access_url u
5215
                    WHERE c.id = u.c_id AND u.access_url_id = $access_url_id";
5216
            if (!empty($visibility)) {
5217
                $visibility = intval($visibility);
5218
                $sql .= " AND visibility = $visibility ";
5219
            }
5220
        } else {
5221
            if (!empty($visibility)) {
5222
                $visibility = intval($visibility);
5223
                $sql .= " WHERE visibility = $visibility ";
5224
            }
5225
        }
5226
5227
        $res = Database::query($sql);
5228
        $row = Database::fetch_row($res);
5229
5230
        return $row[0];
5231
    }
5232
5233
    /**
5234
     * Get active courses count.
5235
     * Active = all courses except the ones with hidden visibility.
5236
     *
5237
     * @param int $urlId Access URL ID (optional)
5238
     *
5239
     * @return int Number of courses
5240
     */
5241
    public static function countActiveCourses($urlId = null)
5242
    {
5243
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
5244
        $table_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
5245
        $sql = "SELECT count(id) FROM $table_course c";
5246
        if (!empty($urlId) && $urlId == intval($urlId)) {
5247
            $sql .= ", $table_course_rel_access_url u
5248
                    WHERE
5249
                        c.id = u.c_id AND
5250
                        u.access_url_id = $urlId AND
5251
                        visibility <> ".COURSE_VISIBILITY_HIDDEN;
5252
        } else {
5253
            $sql .= " WHERE visibility <> ".COURSE_VISIBILITY_HIDDEN;
5254
        }
5255
        $res = Database::query($sql);
5256
        $row = Database::fetch_row($res);
5257
5258
        return $row[0];
5259
    }
5260
5261
    /**
5262
     * Returns the SQL conditions to filter course only visible by the user in the catalogue.
5263
     *
5264
     * @param string $courseTableAlias Alias of the course table
5265
     * @param bool   $hideClosed       Whether to hide closed and hidden courses
5266
     *
5267
     * @return string SQL conditions
5268
     */
5269
    public static function getCourseVisibilitySQLCondition(
5270
        $courseTableAlias,
5271
        $hideClosed = false
5272
    ) {
5273
        $visibilityCondition = '';
5274
        $hidePrivate = api_get_setting('course_catalog_hide_private');
5275
        if ($hidePrivate === 'true') {
5276
            $visibilityCondition .= ' AND '.$courseTableAlias.'.visibility <> '.COURSE_VISIBILITY_REGISTERED;
5277
        }
5278
        if ($hideClosed) {
5279
            $visibilityCondition .= ' AND '.$courseTableAlias.'.visibility NOT IN ('.COURSE_VISIBILITY_CLOSED.','.COURSE_VISIBILITY_HIDDEN.')';
5280
        }
5281
5282
        // Check if course have users allowed to see it in the catalogue, then show only if current user is allowed to see it
5283
        $currentUserId = api_get_user_id();
5284
        $restrictedCourses = self::getCatalogueCourseList(true);
5285
        $allowedCoursesToCurrentUser = self::getCatalogueCourseList(true, $currentUserId);
5286
        if (!empty($restrictedCourses)) {
5287
            $visibilityCondition .= ' AND ('.$courseTableAlias.'.code NOT IN ("'.implode('","', $restrictedCourses).'")';
5288
            $visibilityCondition .= ' OR '.$courseTableAlias.'.code IN ("'.implode('","', $allowedCoursesToCurrentUser).'"))';
5289
        }
5290
5291
        // Check if course have users denied to see it in the catalogue, then show only if current user is not denied to see it
5292
        $restrictedCourses = self::getCatalogueCourseList(false);
5293
        $notAllowedCoursesToCurrentUser = self::getCatalogueCourseList(false, $currentUserId);
5294
        if (!empty($restrictedCourses)) {
5295
            $visibilityCondition .= ' AND ('.$courseTableAlias.'.code NOT IN ("'.implode('","', $restrictedCourses).'")';
5296
            $visibilityCondition .= ' OR '.$courseTableAlias.'.code NOT IN ("'.implode('","', $notAllowedCoursesToCurrentUser).'"))';
5297
        }
5298
5299
        return $visibilityCondition;
5300
    }
5301
5302
    /**
5303
     * Return a link to go to the course, validating the visibility of the
5304
     * course and the user status.
5305
     *
5306
     * @param int $uid User ID
5307
     * @param array Course details array
5308
     * @param array  List of courses to which the user is subscribed (if not provided, will be generated)
5309
     *
5310
     * @return mixed 'enter' for a link to go to the course or 'register' for a link to subscribe, or false if no access
5311
     */
5312
    public static function get_access_link_by_user($uid, $course, $user_courses = [])
5313
    {
5314
        if (empty($uid) || empty($course)) {
5315
            return false;
5316
        }
5317
5318
        if (empty($user_courses)) {
5319
            // get the array of courses to which the user is subscribed
5320
            $user_courses = self::get_courses_list_by_user_id($uid);
5321
            foreach ($user_courses as $k => $v) {
5322
                $user_courses[$k] = $v['real_id'];
5323
            }
5324
        }
5325
5326
        if (!isset($course['real_id']) && empty($course['real_id'])) {
5327
            $course = api_get_course_info($course['code']);
5328
        }
5329
5330
        if ($course['visibility'] == COURSE_VISIBILITY_HIDDEN) {
5331
            return [];
5332
        }
5333
5334
        $is_admin = api_is_platform_admin_by_id($uid);
5335
        $options = [];
5336
        // Register button
5337
        if (!api_is_anonymous($uid) &&
5338
            (
5339
            ($course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD || $course['visibility'] == COURSE_VISIBILITY_OPEN_PLATFORM)
5340
                //$course['visibility'] == COURSE_VISIBILITY_REGISTERED && $course['subscribe'] == SUBSCRIBE_ALLOWED
5341
            ) &&
5342
            $course['subscribe'] == SUBSCRIBE_ALLOWED &&
5343
            (!in_array($course['real_id'], $user_courses) || empty($user_courses))
5344
        ) {
5345
            $options[] = 'register';
5346
        }
5347
5348
        // Go To Course button (only if admin, if course public or if student already subscribed)
5349
        if ($is_admin ||
5350
            $course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD && empty($course['registration_code']) ||
5351
            (api_user_is_login($uid) && $course['visibility'] == COURSE_VISIBILITY_OPEN_PLATFORM && empty($course['registration_code'])) ||
5352
            (in_array($course['real_id'], $user_courses) && $course['visibility'] != COURSE_VISIBILITY_CLOSED)
5353
        ) {
5354
            $options[] = 'enter';
5355
        }
5356
5357
        if ($is_admin ||
5358
            $course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD && empty($course['registration_code']) ||
5359
            (api_user_is_login($uid) && $course['visibility'] == COURSE_VISIBILITY_OPEN_PLATFORM && empty($course['registration_code'])) ||
5360
            (in_array($course['real_id'], $user_courses) && $course['visibility'] != COURSE_VISIBILITY_CLOSED)
5361
        ) {
5362
            $options[] = 'enter';
5363
        }
5364
5365
        if ($course['visibility'] != COURSE_VISIBILITY_HIDDEN &&
5366
            empty($course['registration_code']) &&
5367
            $course['unsubscribe'] == UNSUBSCRIBE_ALLOWED &&
5368
            api_user_is_login($uid) &&
5369
            in_array($course['real_id'], $user_courses)
5370
        ) {
5371
            $options[] = 'unsubscribe';
5372
        }
5373
5374
        return $options;
5375
    }
5376
5377
    /**
5378
     * @param array          $courseInfo
5379
     * @param array          $teachers
5380
     * @param bool           $deleteTeachersNotInList
5381
     * @param bool           $editTeacherInSessions
5382
     * @param bool           $deleteSessionTeacherNotInList
5383
     * @param array          $teacherBackup
5384
     * @param Monolog\Logger $logger
5385
     *
5386
     * @return false|null
5387
     */
5388
    public static function updateTeachers(
5389
        $courseInfo,
5390
        $teachers,
5391
        $deleteTeachersNotInList = true,
5392
        $editTeacherInSessions = false,
5393
        $deleteSessionTeacherNotInList = false,
5394
        $teacherBackup = [],
5395
        $logger = null
5396
    ) {
5397
        if (!is_array($teachers)) {
5398
            $teachers = [$teachers];
5399
        }
5400
5401
        if (empty($courseInfo) || !isset($courseInfo['real_id'])) {
5402
            return false;
5403
        }
5404
5405
        $teachers = array_filter($teachers);
5406
        $courseId = $courseInfo['real_id'];
5407
        $course_code = $courseInfo['code'];
5408
5409
        $course_user_table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5410
        $alreadyAddedTeachers = self::get_teacher_list_from_course_code($course_code);
5411
5412
        if ($deleteTeachersNotInList) {
5413
            // Delete only teacher relations that doesn't match the selected teachers
5414
            $cond = null;
5415
            if (count($teachers) > 0) {
5416
                foreach ($teachers as $key) {
5417
                    $key = Database::escape_string($key);
5418
                    $cond .= " AND user_id <> '".$key."'";
5419
                }
5420
            }
5421
5422
            // Recover user categories
5423
            $sql = "SELECT * FROM $course_user_table
5424
                    WHERE c_id = $courseId AND status = 1 AND relation_type = 0 ".$cond;
5425
            $result = Database::query($sql);
5426
            if (Database::num_rows($result)) {
5427
                $teachersToDelete = Database::store_result($result, 'ASSOC');
5428
                foreach ($teachersToDelete as $data) {
5429
                    $userId = $data['user_id'];
5430
                    $teacherBackup[$userId][$course_code] = $data;
5431
                }
5432
            }
5433
5434
            $sql = "DELETE FROM $course_user_table
5435
                    WHERE c_id = $courseId AND status = 1 AND relation_type = 0 ".$cond;
5436
5437
            Database::query($sql);
5438
        }
5439
5440
        if (count($teachers) > 0) {
5441
            foreach ($teachers as $userId) {
5442
                $userId = intval($userId);
5443
                // We check if the teacher is already subscribed in this course
5444
                $sql = "SELECT 1 FROM $course_user_table
5445
                        WHERE user_id = $userId AND c_id = $courseId";
5446
                $result = Database::query($sql);
5447
                if (Database::num_rows($result)) {
5448
                    $sql = "UPDATE $course_user_table 
5449
                            SET status = 1
5450
                            WHERE c_id = $courseId AND user_id = $userId ";
5451
                } else {
5452
                    $userCourseCategory = '0';
5453
                    if (isset($teacherBackup[$userId]) &&
5454
                        isset($teacherBackup[$userId][$course_code])
5455
                    ) {
5456
                        $courseUserData = $teacherBackup[$userId][$course_code];
5457
                        $userCourseCategory = $courseUserData['user_course_cat'];
5458
                        if ($logger) {
5459
                            $logger->addInfo("Recovering user_course_cat: $userCourseCategory");
5460
                        }
5461
                    }
5462
5463
                    $sql = "INSERT INTO $course_user_table SET
5464
                            c_id = $courseId,
5465
                            user_id = $userId,
5466
                            status = 1,
5467
                            is_tutor = 0,
5468
                            sort = 0,
5469
                            relation_type = 0,
5470
                            user_course_cat = $userCourseCategory
5471
                    ";
5472
                }
5473
                Database::query($sql);
5474
            }
5475
        }
5476
5477
        if ($editTeacherInSessions) {
5478
            $sessions = SessionManager::get_session_by_course($courseId);
5479
            if (!empty($sessions)) {
5480
                if ($logger) {
5481
                    $logger->addInfo("Edit teachers in sessions");
5482
                }
5483
                foreach ($sessions as $session) {
5484
                    $sessionId = $session['id'];
5485
                    // Remove old and add new
5486
                    if ($deleteSessionTeacherNotInList) {
5487
                        foreach ($teachers as $userId) {
5488
                            if ($logger) {
5489
                                $logger->addInfo("Set coach #$userId in session #$sessionId of course #$courseId ");
5490
                            }
5491
                            SessionManager::set_coach_to_course_session(
5492
                                $userId,
5493
                                $sessionId,
5494
                                $courseId
5495
                            );
5496
                        }
5497
5498
                        $teachersToDelete = [];
5499
                        if (!empty($alreadyAddedTeachers)) {
5500
                            $teachersToDelete = array_diff(array_keys($alreadyAddedTeachers), $teachers);
5501
                        }
5502
5503
                        if (!empty($teachersToDelete)) {
5504
                            foreach ($teachersToDelete as $userId) {
5505
                                if ($logger) {
5506
                                    $logger->addInfo("Delete coach #$userId in session #$sessionId of course #$courseId ");
5507
                                }
5508
                                SessionManager::set_coach_to_course_session(
5509
                                    $userId,
5510
                                    $sessionId,
5511
                                    $courseId,
5512
                                    true
5513
                                );
5514
                            }
5515
                        }
5516
                    } else {
5517
                        // Add new teachers only
5518
                        foreach ($teachers as $userId) {
5519
                            if ($logger) {
5520
                                $logger->addInfo("Add coach #$userId in session #$sessionId of course #$courseId ");
5521
                            }
5522
                            SessionManager::set_coach_to_course_session(
5523
                                $userId,
5524
                                $sessionId,
5525
                                $courseId
5526
                            );
5527
                        }
5528
                    }
5529
                }
5530
            }
5531
        }
5532
    }
5533
5534
    /**
5535
     * Course available settings variables see c_course_setting table.
5536
     *
5537
     * @param AppPlugin $appPlugin
5538
     *
5539
     * @return array
5540
     */
5541
    public static function getCourseSettingVariables(AppPlugin $appPlugin)
5542
    {
5543
        $pluginCourseSettings = $appPlugin->getAllPluginCourseSettings();
5544
        $courseSettings = [
5545
            // Get allow_learning_path_theme from table
5546
            'allow_learning_path_theme',
5547
            // Get allow_open_chat_window from table
5548
            'allow_open_chat_window',
5549
            'allow_public_certificates',
5550
            // Get allow_user_edit_agenda from table
5551
            'allow_user_edit_agenda',
5552
            // Get allow_user_edit_announcement from table
5553
            'allow_user_edit_announcement',
5554
            // Get allow_user_image_forum from table
5555
            'allow_user_image_forum',
5556
            //Get allow show user list
5557
            'allow_user_view_user_list',
5558
            // Get course_theme from table
5559
            'course_theme',
5560
            //Get allow show user list
5561
            'display_info_advance_inside_homecourse',
5562
            'documents_default_visibility',
5563
            // Get send_mail_setting (work)from table
5564
            'email_alert_manager_on_new_doc',
5565
            // Get send_mail_setting (work)from table
5566
            'email_alert_manager_on_new_quiz',
5567
            // Get send_mail_setting (dropbox) from table
5568
            'email_alert_on_new_doc_dropbox',
5569
            'email_alert_students_on_new_homework',
5570
            // Get send_mail_setting (auth)from table
5571
            'email_alert_to_teacher_on_new_user_in_course',
5572
            'enable_lp_auto_launch',
5573
            'enable_exercise_auto_launch',
5574
            'enable_document_auto_launch',
5575
            'pdf_export_watermark_text',
5576
            'show_system_folders',
5577
            'exercise_invisible_in_session',
5578
            'enable_forum_auto_launch',
5579
            'show_course_in_user_language',
5580
            'email_to_teachers_on_new_work_feedback',
5581
        ];
5582
5583
        $courseModels = ExerciseLib::getScoreModels();
5584
        if (!empty($courseModels)) {
5585
            $courseSettings[] = 'score_model_id';
5586
        }
5587
5588
        $allowLPReturnLink = api_get_setting('allow_lp_return_link');
5589
        if ($allowLPReturnLink === 'true') {
5590
            $courseSettings[] = 'lp_return_link';
5591
        }
5592
5593
        if (!empty($pluginCourseSettings)) {
5594
            $courseSettings = array_merge(
5595
                $courseSettings,
5596
                $pluginCourseSettings
5597
            );
5598
        }
5599
5600
        return $courseSettings;
5601
    }
5602
5603
    /**
5604
     * @param AppPlugin    $appPlugin
5605
     * @param string       $variable
5606
     * @param string|array $value
5607
     * @param int          $courseId
5608
     *
5609
     * @return bool
5610
     */
5611
    public static function saveCourseConfigurationSetting(AppPlugin $appPlugin, $variable, $value, $courseId)
5612
    {
5613
        $settingList = self::getCourseSettingVariables($appPlugin);
5614
5615
        if (!in_array($variable, $settingList)) {
5616
            return false;
5617
        }
5618
5619
        $courseSettingTable = Database::get_course_table(TABLE_COURSE_SETTING);
5620
5621
        if (is_array($value)) {
5622
            $value = implode(',', $value);
5623
        }
5624
5625
        if (self::hasCourseSetting($variable, $courseId)) {
5626
            // Update
5627
            Database::update(
5628
                $courseSettingTable,
5629
                ['value' => $value],
5630
                ['variable = ? AND c_id = ?' => [$variable, $courseId]]
5631
            );
5632
        } else {
5633
            // Create
5634
            Database::insert(
5635
                $courseSettingTable,
5636
                [
5637
                    'title' => $variable,
5638
                    'value' => $value,
5639
                    'c_id' => $courseId,
5640
                    'variable' => $variable,
5641
                ]
5642
            );
5643
        }
5644
5645
        return true;
5646
    }
5647
5648
    /**
5649
     * Check if course setting exists.
5650
     *
5651
     * @param string $variable
5652
     * @param int    $courseId
5653
     *
5654
     * @return bool
5655
     */
5656
    public static function hasCourseSetting($variable, $courseId)
5657
    {
5658
        $courseSetting = Database::get_course_table(TABLE_COURSE_SETTING);
5659
        $courseId = intval($courseId);
5660
        $variable = Database::escape_string($variable);
5661
        $sql = "SELECT variable FROM $courseSetting
5662
                WHERE c_id = $courseId AND variable = '$variable'";
5663
        $result = Database::query($sql);
5664
5665
        return Database::num_rows($result) > 0;
5666
    }
5667
5668
    /**
5669
     * Get information from the track_e_course_access table.
5670
     *
5671
     * @param int $sessionId
5672
     * @param int $userId
5673
     * @param int $limit
5674
     *
5675
     * @return array
5676
     */
5677
    public static function getCourseAccessPerSessionAndUser($sessionId, $userId, $limit = 0)
5678
    {
5679
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
5680
5681
        $sessionId = intval($sessionId);
5682
        $userId = intval($userId);
5683
5684
        $sql = "SELECT * FROM $table
5685
                WHERE session_id = $sessionId AND user_id = $userId";
5686
5687
        if (!empty($limit)) {
5688
            $limit = intval($limit);
5689
            $sql .= " LIMIT $limit";
5690
        }
5691
        $result = Database::query($sql);
5692
5693
        return Database::store_result($result);
5694
    }
5695
5696
    /**
5697
     * Get information from the track_e_course_access table.
5698
     *
5699
     * @param int    $courseId
5700
     * @param int    $sessionId
5701
     * @param string $startDate
5702
     * @param string $endDate
5703
     *
5704
     * @return array
5705
     */
5706
    public static function getCourseAccessPerCourseAndSession(
5707
        $courseId,
5708
        $sessionId,
5709
        $startDate,
5710
        $endDate
5711
    ) {
5712
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
5713
        $courseId = intval($courseId);
5714
        $sessionId = intval($sessionId);
5715
        $startDate = Database::escape_string($startDate);
5716
        $endDate = Database::escape_string($endDate);
5717
5718
        $sql = "SELECT * FROM $table
5719
                WHERE
5720
                    c_id = $courseId AND
5721
                    session_id = $sessionId AND
5722
                    login_course_date BETWEEN '$startDate' AND '$endDate'
5723
                ";
5724
5725
        $result = Database::query($sql);
5726
5727
        return Database::store_result($result);
5728
    }
5729
5730
    /**
5731
     * Get login information from the track_e_course_access table, for any
5732
     * course in the given session.
5733
     *
5734
     * @param int $sessionId
5735
     * @param int $userId
5736
     *
5737
     * @return array
5738
     */
5739
    public static function getFirstCourseAccessPerSessionAndUser($sessionId, $userId)
5740
    {
5741
        $sessionId = intval($sessionId);
5742
        $userId = intval($userId);
5743
5744
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
5745
        $sql = "SELECT * FROM $table
5746
                WHERE session_id = $sessionId AND user_id = $userId
5747
                ORDER BY login_course_date ASC
5748
                LIMIT 1";
5749
5750
        $result = Database::query($sql);
5751
        $courseAccess = [];
5752
        if (Database::num_rows($result)) {
5753
            $courseAccess = Database::fetch_array($result, 'ASSOC');
5754
        }
5755
5756
        return $courseAccess;
5757
    }
5758
5759
    /**
5760
     * @param int  $courseId
5761
     * @param int  $sessionId
5762
     * @param bool $getAllSessions
5763
     *
5764
     * @return mixed
5765
     */
5766
    public static function getCountForum(
5767
        $courseId,
5768
        $sessionId = 0,
5769
        $getAllSessions = false
5770
    ) {
5771
        $forum = Database::get_course_table(TABLE_FORUM);
5772
        if ($getAllSessions) {
5773
            $sql = "SELECT count(*) as count
5774
                    FROM $forum f
5775
                    WHERE f.c_id = %s";
5776
        } else {
5777
            $sql = "SELECT count(*) as count
5778
                    FROM $forum f
5779
                    WHERE f.c_id = %s and f.session_id = %s";
5780
        }
5781
5782
        $sql = sprintf($sql, intval($courseId), intval($sessionId));
5783
        $result = Database::query($sql);
5784
        $row = Database::fetch_array($result);
5785
5786
        return $row['count'];
5787
    }
5788
5789
    /**
5790
     * @param int $userId
5791
     * @param int $courseId
5792
     * @param int $sessionId
5793
     *
5794
     * @return mixed
5795
     */
5796
    public static function getCountPostInForumPerUser(
5797
        $userId,
5798
        $courseId,
5799
        $sessionId = 0
5800
    ) {
5801
        $forum = Database::get_course_table(TABLE_FORUM);
5802
        $forum_post = Database::get_course_table(TABLE_FORUM_POST);
5803
5804
        $sql = "SELECT count(distinct post_id) as count
5805
                FROM $forum_post p
5806
                INNER JOIN $forum f
5807
                ON f.forum_id = p.forum_id AND f.c_id = p.c_id
5808
                WHERE p.poster_id = %s and f.session_id = %s and p.c_id = %s";
5809
5810
        $sql = sprintf(
5811
            $sql,
5812
            intval($userId),
5813
            intval($sessionId),
5814
            intval($courseId)
5815
        );
5816
5817
        $result = Database::query($sql);
5818
        $row = Database::fetch_array($result);
5819
5820
        return $row['count'];
5821
    }
5822
5823
    /**
5824
     * @param int $userId
5825
     * @param int $courseId
5826
     * @param int $sessionId
5827
     *
5828
     * @return mixed
5829
     */
5830
    public static function getCountForumPerUser(
5831
        $userId,
5832
        $courseId,
5833
        $sessionId = 0
5834
    ) {
5835
        $forum = Database::get_course_table(TABLE_FORUM);
5836
        $forum_post = Database::get_course_table(TABLE_FORUM_POST);
5837
5838
        $sql = "SELECT count(distinct f.forum_id) as count
5839
                FROM $forum_post p
5840
                INNER JOIN $forum f
5841
                ON f.forum_id = p.forum_id AND f.c_id = p.c_id
5842
                WHERE p.poster_id = %s and f.session_id = %s and p.c_id = %s";
5843
5844
        $sql = sprintf(
5845
            $sql,
5846
            intval($userId),
5847
            intval($sessionId),
5848
            intval($courseId)
5849
        );
5850
5851
        $result = Database::query($sql);
5852
        $row = Database::fetch_array($result);
5853
5854
        return $row['count'];
5855
    }
5856
5857
    /**
5858
     * Returns the course name from a given code.
5859
     *
5860
     * @param string $code
5861
     *
5862
     * @return string
5863
     */
5864
    public static function getCourseNameFromCode($code)
5865
    {
5866
        $tbl_main_categories = Database::get_main_table(TABLE_MAIN_COURSE);
5867
        $code = Database::escape_string($code);
5868
        $sql = "SELECT title
5869
                FROM $tbl_main_categories
5870
                WHERE code = '$code'";
5871
        $result = Database::query($sql);
5872
        if ($col = Database::fetch_array($result)) {
5873
            return $col['title'];
5874
        }
5875
    }
5876
5877
    /**
5878
     * Generates a course code from a course title.
5879
     *
5880
     * @todo Such a function might be useful in other places too. It might be moved in the CourseManager class.
5881
     * @todo the function might be upgraded for avoiding code duplications (currently,
5882
     * it might suggest a code that is already in use)
5883
     *
5884
     * @param string $title A course title
5885
     *
5886
     * @return string A proposed course code
5887
     *                +
5888
     * @assert (null,null) === false
5889
     * @assert ('ABC_DEF', null) === 'ABCDEF'
5890
     * @assert ('ABC09*^[%A', null) === 'ABC09A'
5891
     */
5892
    public static function generate_course_code($title)
5893
    {
5894
        return substr(
5895
            preg_replace('/[^A-Z0-9]/', '', strtoupper(api_replace_dangerous_char($title))),
5896
            0,
5897
            self::MAX_COURSE_LENGTH_CODE
5898
        );
5899
    }
5900
5901
    /**
5902
     * @param $courseId
5903
     *
5904
     * @return array
5905
     */
5906
    public static function getCourseSettings($courseId)
5907
    {
5908
        $settingTable = Database::get_course_table(TABLE_COURSE_SETTING);
5909
        $courseId = intval($courseId);
5910
        $sql = "SELECT * FROM $settingTable WHERE c_id = $courseId";
5911
        $result = Database::query($sql);
5912
        $settings = [];
5913
        if (Database::num_rows($result)) {
5914
            while ($row = Database::fetch_array($result, 'ASSOC')) {
5915
                $settings[$row['variable']] = $row;
5916
            }
5917
        }
5918
5919
        return $settings;
5920
    }
5921
5922
    /**
5923
     * this function gets all the users of the course,
5924
     * including users from linked courses.
5925
     *
5926
     * @param $filterByActive
5927
     *
5928
     * @return array
5929
     */
5930
    public static function getCourseUsers($filterByActive = null)
5931
    {
5932
        // This would return only the users from real courses:
5933
        $userList = self::get_user_list_from_course_code(
5934
            api_get_course_id(),
5935
            api_get_session_id(),
5936
            null,
5937
            null,
5938
            null,
5939
            null,
5940
            false,
5941
            false,
5942
            [],
5943
            [],
5944
            [],
5945
            $filterByActive
5946
        );
5947
5948
        return $userList;
5949
    }
5950
5951
    /**
5952
     * this function gets all the groups of the course,
5953
     * not including linked courses.
5954
     */
5955
    public static function getCourseGroups()
5956
    {
5957
        $sessionId = api_get_session_id();
5958
        if ($sessionId != 0) {
5959
            $groupList = self::get_group_list_of_course(
5960
                api_get_course_id(),
5961
                $sessionId,
5962
                1
5963
            );
5964
        } else {
5965
            $groupList = self::get_group_list_of_course(
5966
                api_get_course_id(),
5967
                0,
5968
                1
5969
            );
5970
        }
5971
5972
        return $groupList;
5973
    }
5974
5975
    /**
5976
     * @param FormValidator $form
5977
     * @param array         $alreadySelected
5978
     *
5979
     * @return HTML_QuickForm_element
5980
     */
5981
    public static function addUserGroupMultiSelect(&$form, $alreadySelected)
5982
    {
5983
        $userList = self::getCourseUsers(true);
5984
        $groupList = self::getCourseGroups();
5985
        $array = self::buildSelectOptions(
5986
            $groupList,
5987
            $userList,
5988
            $alreadySelected
5989
        );
5990
5991
        $result = [];
5992
        foreach ($array as $content) {
5993
            $result[$content['value']] = $content['content'];
5994
        }
5995
5996
        return $form->addElement(
5997
            'advmultiselect',
5998
            'users',
5999
            get_lang('Users'),
6000
            $result,
6001
            ['select_all_checkbox' => true]
6002
        );
6003
    }
6004
6005
    /**
6006
     * This function separates the users from the groups
6007
     * users have a value USER:XXX (with XXX the groups id have a value
6008
     *  GROUP:YYY (with YYY the group id).
6009
     *
6010
     * @param array $to Array of strings that define the type and id of each destination
6011
     *
6012
     * @return array Array of groups and users (each an array of IDs)
6013
     */
6014
    public static function separateUsersGroups($to)
6015
    {
6016
        $groupList = [];
6017
        $userList = [];
6018
6019
        foreach ($to as $to_item) {
6020
            if (!empty($to_item)) {
6021
                $parts = explode(':', $to_item);
6022
                $type = isset($parts[0]) ? $parts[0] : '';
6023
                $id = isset($parts[1]) ? $parts[1] : '';
6024
6025
                switch ($type) {
6026
                    case 'GROUP':
6027
                        $groupList[] = intval($id);
6028
                        break;
6029
                    case 'USER':
6030
                        $userList[] = intval($id);
6031
                        break;
6032
                }
6033
            }
6034
        }
6035
6036
        $send_to['groups'] = $groupList;
6037
        $send_to['users'] = $userList;
6038
6039
        return $send_to;
6040
    }
6041
6042
    /**
6043
     * Shows the form for sending a message to a specific group or user.
6044
     *
6045
     * @param FormValidator $form
6046
     * @param array         $groupInfo
6047
     * @param array         $to
6048
     *
6049
     * @return HTML_QuickForm_element
6050
     */
6051
    public static function addGroupMultiSelect($form, $groupInfo, $to = [])
6052
    {
6053
        $group_users = GroupManager::get_subscribed_users($groupInfo);
6054
        $array = self::buildSelectOptions(null, $group_users, $to);
6055
6056
        $result = [];
6057
        foreach ($array as $content) {
6058
            $result[$content['value']] = $content['content'];
6059
        }
6060
6061
        return $form->addElement('advmultiselect', 'users', get_lang('Users'), $result);
6062
    }
6063
6064
    /**
6065
     * this function shows the form for sending a message to a specific group or user.
6066
     *
6067
     * @param array $groupList
6068
     * @param array $userList
6069
     * @param array $alreadySelected
6070
     *
6071
     * @return array
6072
     */
6073
    public static function buildSelectOptions(
6074
        $groupList = [],
6075
        $userList = [],
6076
        $alreadySelected = []
6077
    ) {
6078
        if (empty($alreadySelected)) {
6079
            $alreadySelected = [];
6080
        }
6081
6082
        $result = [];
6083
        // adding the groups to the select form
6084
        if ($groupList) {
6085
            foreach ($groupList as $thisGroup) {
6086
                $groupId = $thisGroup['iid'];
6087
                if (is_array($alreadySelected)) {
6088
                    if (!in_array(
6089
                        "GROUP:".$groupId,
6090
                        $alreadySelected
6091
                    )
6092
                    ) { // $alreadySelected is the array containing the groups (and users) that are already selected
6093
                        $user_label = ($thisGroup['userNb'] > 0) ? get_lang('Users') : get_lang('LowerCaseUser');
6094
                        $user_disabled = ($thisGroup['userNb'] > 0) ? "" : "disabled=disabled";
6095
                        $result[] = [
6096
                            'disabled' => $user_disabled,
6097
                            'value' => "GROUP:".$groupId,
6098
                            // The space before "G" is needed in order to advmultiselect.php js puts groups first
6099
                            'content' => " G: ".$thisGroup['name']." - ".$thisGroup['userNb']." ".$user_label,
6100
                        ];
6101
                    }
6102
                }
6103
            }
6104
        }
6105
6106
        // adding the individual users to the select form
6107
        if ($userList) {
6108
            foreach ($userList as $user) {
6109
                if (is_array($alreadySelected)) {
6110
                    if (!in_array(
6111
                        "USER:".$user['user_id'],
6112
                        $alreadySelected
6113
                    )
6114
                    ) {
6115
                        // $alreadySelected is the array containing the users (and groups) that are already selected
6116
                        $result[] = [
6117
                            'value' => "USER:".$user['user_id'],
6118
                            'content' => api_get_person_name($user['firstname'], $user['lastname']),
6119
                        ];
6120
                    }
6121
                }
6122
            }
6123
        }
6124
6125
        return $result;
6126
    }
6127
6128
    /**
6129
     * @return array a list (array) of all courses
6130
     */
6131
    public static function get_course_list()
6132
    {
6133
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
6134
6135
        return Database::store_result(Database::query("SELECT *, id as real_id FROM $table"));
6136
    }
6137
6138
    /**
6139
     * Returns course code from a given gradebook category's id.
6140
     *
6141
     * @param int  Category ID
6142
     *
6143
     * @return string Course code
6144
     */
6145
    public static function get_course_by_category($category_id)
6146
    {
6147
        $category_id = (int) $category_id;
6148
        $sql = 'SELECT c_id FROM '.Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY).'
6149
                WHERE id='.$category_id;
6150
        $info = Database::fetch_array(Database::query($sql), 'ASSOC');
6151
6152
        return $info ? $info['c_id'] : false;
6153
    }
6154
6155
    /**
6156
     * This function gets all the courses that are not in a session.
6157
     *
6158
     * @param date Start date
6159
     * @param date End date
6160
     * @param bool $includeClosed Whether to include closed and hidden courses
6161
     *
6162
     * @return array Not-in-session courses
6163
     */
6164
    public static function getCoursesWithoutSession(
6165
        $startDate = null,
6166
        $endDate = null,
6167
        $includeClosed = false
6168
    ) {
6169
        $dateConditional = ($startDate && $endDate) ?
6170
            " WHERE session_id IN (SELECT id FROM ".Database::get_main_table(TABLE_MAIN_SESSION).
6171
            " WHERE access_start_date = '$startDate' AND access_end_date = '$endDate')" : null;
6172
        $visibility = ($includeClosed ? '' : 'visibility NOT IN (0, 4) AND ');
6173
6174
        $sql = "SELECT id, code, title
6175
                FROM ".Database::get_main_table(TABLE_MAIN_COURSE)."
6176
                WHERE $visibility code NOT IN (
6177
                    SELECT DISTINCT course_code 
6178
                    FROM ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE).$dateConditional."
6179
                )
6180
                ORDER BY id";
6181
6182
        $result = Database::query($sql);
6183
        $courses = [];
6184
        while ($row = Database::fetch_array($result)) {
6185
            $courses[] = $row;
6186
        }
6187
6188
        return $courses;
6189
    }
6190
6191
    /**
6192
     * Get list of courses based on users of a group for a group admin.
6193
     *
6194
     * @param int $userId The user id
6195
     *
6196
     * @return array
6197
     */
6198
    public static function getCoursesFollowedByGroupAdmin($userId)
6199
    {
6200
        $coursesList = [];
6201
        $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
6202
        $courseUserTable = Database::get_main_table(TABLE_MAIN_COURSE_USER);
6203
        $userGroup = new UserGroup();
6204
        $userIdList = $userGroup->getGroupUsersByUser($userId);
6205
6206
        if (empty($userIdList)) {
6207
            return [];
6208
        }
6209
6210
        $sql = "SELECT DISTINCT(c.id), c.title
6211
                FROM $courseTable c
6212
                INNER JOIN $courseUserTable cru ON c.id = cru.c_id
6213
                WHERE (
6214
                    cru.user_id IN (".implode(', ', $userIdList).")
6215
                    AND cru.relation_type = 0
6216
                )";
6217
6218
        if (api_is_multiple_url_enabled()) {
6219
            $courseAccessUrlTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
6220
            $accessUrlId = api_get_current_access_url_id();
6221
6222
            if ($accessUrlId != -1) {
6223
                $sql = "SELECT DISTINCT(c.id), c.title
6224
                        FROM $courseTable c
6225
                        INNER JOIN $courseUserTable cru ON c.id = cru.c_id
6226
                        INNER JOIN $courseAccessUrlTable crau ON c.id = crau.c_id
6227
                        WHERE crau.access_url_id = $accessUrlId
6228
                            AND (
6229
                            cru.id_user IN (".implode(', ', $userIdList).") AND
6230
                            cru.relation_type = 0
6231
                        )";
6232
            }
6233
        }
6234
6235
        $result = Database::query($sql);
6236
        while ($row = Database::fetch_assoc($result)) {
6237
            $coursesList[] = $row;
6238
        }
6239
6240
        return $coursesList;
6241
    }
6242
6243
    /**
6244
     * Direct course link see #5299.
6245
     *
6246
     * You can send to your students an URL like this
6247
     * http://chamilodev.beeznest.com/main/auth/inscription.php?c=ABC&e=3
6248
     * Where "c" is the course code and "e" is the exercise Id, after a successful
6249
     * registration the user will be sent to the course or exercise
6250
     *
6251
     * @param array $form_data
6252
     *
6253
     * @return array
6254
     */
6255
    public static function redirectToCourse($form_data)
6256
    {
6257
        $course_code_redirect = Session::read('course_redirect');
6258
        $_user = api_get_user_info();
6259
        $userId = api_get_user_id();
6260
6261
        if (!empty($course_code_redirect)) {
6262
            $course_info = api_get_course_info($course_code_redirect);
6263
            if (!empty($course_info)) {
6264
                if (in_array(
6265
                    $course_info['visibility'],
6266
                    [COURSE_VISIBILITY_OPEN_PLATFORM, COURSE_VISIBILITY_OPEN_WORLD]
6267
                )
6268
                ) {
6269
                    if (self::is_user_subscribed_in_course($userId, $course_info['code'])) {
6270
                        $form_data['action'] = $course_info['course_public_url'];
6271
                        $form_data['message'] = sprintf(get_lang('YouHaveBeenRegisteredToCourseX'), $course_info['title']);
6272
                        $form_data['button'] = Display::button(
6273
                            'next',
6274
                            get_lang('GoToCourse', null, $_user['language']),
6275
                            ['class' => 'btn btn-primary btn-large']
6276
                        );
6277
6278
                        $exercise_redirect = intval(Session::read('exercise_redirect'));
6279
                        // Specify the course id as the current context does not
6280
                        // hold a global $_course array
6281
                        $objExercise = new Exercise($course_info['real_id']);
6282
                        $result = $objExercise->read($exercise_redirect);
6283
6284
                        if (!empty($exercise_redirect) && !empty($result)) {
6285
                            $form_data['action'] = api_get_path(WEB_CODE_PATH).
6286
                                'exercise/overview.php?exerciseId='.$exercise_redirect.'&cidReq='.$course_info['code'];
6287
                            $form_data['message'] .= '<br />'.get_lang('YouCanAccessTheExercise');
6288
                            $form_data['button'] = Display::button(
6289
                                'next',
6290
                                get_lang('Go', null, $_user['language']),
6291
                                ['class' => 'btn btn-primary btn-large']
6292
                            );
6293
                        }
6294
6295
                        if (!empty($form_data['action'])) {
6296
                            header('Location: '.$form_data['action']);
6297
                            exit;
6298
                        }
6299
                    }
6300
                }
6301
            }
6302
        }
6303
6304
        return $form_data;
6305
    }
6306
6307
    /**
6308
     * Return tab of params to display a course title in the My Courses tab
6309
     * Check visibility, right, and notification icons, and load_dirs option
6310
     * get html course params.
6311
     *
6312
     * @param $courseId
6313
     * @param bool $loadDirs
6314
     *
6315
     * @return array with keys ['right_actions'] ['teachers'] ['notifications']
6316
     */
6317
    public static function getCourseParamsForDisplay($courseId, $loadDirs = false)
6318
    {
6319
        $userId = api_get_user_id();
6320
        $courseId = intval($courseId);
6321
        // Table definitions
6322
        $TABLECOURS = Database::get_main_table(TABLE_MAIN_COURSE);
6323
        $TABLECOURSUSER = Database::get_main_table(TABLE_MAIN_COURSE_USER);
6324
        $TABLE_ACCESS_URL_REL_COURSE = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
6325
        $current_url_id = api_get_current_access_url_id();
6326
6327
        // Get course list auto-register
6328
        $special_course_list = self::get_special_course_list();
6329
6330
        $without_special_courses = '';
6331
        if (!empty($special_course_list)) {
6332
            $without_special_courses = ' AND course.id NOT IN ("'.implode('","', $special_course_list).'")';
6333
        }
6334
6335
        //AND course_rel_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
6336
        $sql = "SELECT 
6337
                    course.id, 
6338
                    course.title, 
6339
                    course.code, 
6340
                    course.subscribe subscr, 
6341
                    course.unsubscribe unsubscr, 
6342
                    course_rel_user.status status,
6343
                    course_rel_user.sort sort, 
6344
                    course_rel_user.user_course_cat user_course_cat
6345
                FROM
6346
                $TABLECOURS course 
6347
                INNER JOIN $TABLECOURSUSER course_rel_user                
6348
                ON (course.id = course_rel_user.c_id)
6349
                INNER JOIN $TABLE_ACCESS_URL_REL_COURSE url
6350
                ON (url.c_id = course.id)
6351
                WHERE
6352
                    course.id = $courseId AND
6353
                    course_rel_user.user_id = $userId
6354
                    $without_special_courses
6355
                ";
6356
6357
        // If multiple URL access mode is enabled, only fetch courses
6358
        // corresponding to the current URL.
6359
        if (api_get_multiple_access_url() && $current_url_id != -1) {
6360
            $sql .= " AND url.c_id = course.id AND access_url_id = $current_url_id";
6361
        }
6362
        // Use user's classification for courses (if any).
6363
        $sql .= " ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
6364
6365
        $result = Database::query($sql);
6366
6367
        // Browse through all courses. We can only have one course because
6368
        // of the  course.id=".intval($courseId) in sql query
6369
        $course = Database::fetch_array($result);
6370
        $course_info = api_get_course_info_by_id($courseId);
6371
        if (empty($course_info)) {
6372
            return '';
6373
        }
6374
6375
        //$course['id_session'] = null;
6376
        $course_info['id_session'] = null;
6377
        $course_info['status'] = $course['status'];
6378
6379
        // For each course, get if there is any notification icon to show
6380
        // (something that would have changed since the user's last visit).
6381
        $show_notification = !api_get_configuration_value('hide_course_notification')
6382
            ? Display::show_notification($course_info)
6383
            : '';
6384
6385
        // New code displaying the user's status in respect to this course.
6386
        $status_icon = Display::return_icon(
6387
            'blackboard.png',
6388
            $course_info['title'],
6389
            [],
6390
            ICON_SIZE_LARGE
6391
        );
6392
6393
        $params = [];
6394
        $params['right_actions'] = '';
6395
6396
        if (api_is_platform_admin()) {
6397
            if ($loadDirs) {
6398
                $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>';
6399
                $params['right_actions'] .= '<a href="'.api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cidReq='.$course['code'].'">'.
6400
                    Display::return_icon('edit.png', get_lang('Edit'), ['align' => 'absmiddle'], ICON_SIZE_SMALL).
6401
                    '</a>';
6402
                $params['right_actions'] .= Display::div(
6403
                    '',
6404
                    [
6405
                        'id' => 'document_result_'.$course_info['real_id'].'_0',
6406
                        'class' => 'document_preview_container',
6407
                    ]
6408
                );
6409
            } else {
6410
                $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'].'">'.
6411
                    Display::returnFontAwesomeIcon('pencil').'</a>';
6412
            }
6413
        } else {
6414
            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
6415
                if ($loadDirs) {
6416
                    $params['right_actions'] .= '<a id="document_preview_'.$course_info['real_id'].'_0" class="document_preview" href="javascript:void(0);">'.
6417
                        Display::return_icon('folder.png', get_lang('Documents'), ['align' => 'absmiddle'], ICON_SIZE_SMALL).'</a>';
6418
                    $params['right_actions'] .= Display::div(
6419
                        '',
6420
                        [
6421
                            'id' => 'document_result_'.$course_info['real_id'].'_0',
6422
                            'class' => 'document_preview_container',
6423
                        ]
6424
                    );
6425
                } else {
6426
                    if ($course_info['status'] == COURSEMANAGER) {
6427
                        $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'].'">'.
6428
                            Display::returnFontAwesomeIcon('pencil').'</a>';
6429
                    }
6430
                }
6431
            }
6432
        }
6433
6434
        $course_title_url = '';
6435
        if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED || $course['status'] == COURSEMANAGER) {
6436
            $course_title_url = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/?id_session=0';
6437
            $course_title = Display::url($course_info['title'], $course_title_url);
6438
        } else {
6439
            $course_title = $course_info['title'].' '.Display::tag(
6440
                'span',
6441
                get_lang('CourseClosed'),
6442
                ['class' => 'item_closed']
6443
            );
6444
        }
6445
6446
        // Start displaying the course block itself
6447
        if (api_get_setting('display_coursecode_in_courselist') === 'true') {
6448
            $course_title .= ' ('.$course_info['visual_code'].') ';
6449
        }
6450
        $teachers = '';
6451
        if (api_get_setting('display_teacher_in_courselist') === 'true') {
6452
            $teachers = self::getTeacherListFromCourseCodeToString(
6453
                $course['code'],
6454
                self::USER_SEPARATOR,
6455
                true
6456
            );
6457
        }
6458
        $params['link'] = $course_title_url;
6459
        $params['icon'] = $status_icon;
6460
        $params['title'] = $course_title;
6461
        $params['teachers'] = $teachers;
6462
        if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
6463
            $params['notifications'] = $show_notification;
6464
        }
6465
6466
        return $params;
6467
    }
6468
6469
    /**
6470
     * Get the course id based on the original id and field name in the extra fields.
6471
     * Returns 0 if course was not found.
6472
     *
6473
     * @param string $original_course_id_value Original course id
6474
     * @param string $original_course_id_name  Original field name
6475
     *
6476
     * @return int Course id
6477
     */
6478
    public static function get_course_id_from_original_id($original_course_id_value, $original_course_id_name)
6479
    {
6480
        $extraFieldValue = new ExtraFieldValue('course');
6481
        $value = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
6482
            $original_course_id_name,
6483
            $original_course_id_value
6484
        );
6485
6486
        if ($value) {
6487
            return $value['item_id'];
6488
        }
6489
6490
        return 0;
6491
    }
6492
6493
    /**
6494
     * Helper function to create a default gradebook (if necessary) upon course creation.
6495
     *
6496
     * @param int    $modelId    The gradebook model ID
6497
     * @param string $courseCode Course code
6498
     */
6499
    public static function createDefaultGradebook($modelId, $courseCode)
6500
    {
6501
        if (api_get_setting('gradebook_enable_grade_model') === 'true') {
6502
            //Create gradebook_category for the new course and add
6503
            // a gradebook model for the course
6504
            if (isset($modelId) &&
6505
                !empty($modelId) &&
6506
                $modelId != '-1'
6507
            ) {
6508
                GradebookUtils::create_default_course_gradebook(
6509
                    $courseCode,
6510
                    $modelId
6511
                );
6512
            }
6513
        }
6514
    }
6515
6516
    /**
6517
     * Helper function to check if there is a course template and, if so, to
6518
     * copy the template as basis for the new course.
6519
     *
6520
     * @param string $courseCode     Course code
6521
     * @param int    $courseTemplate 0 if no course template is defined
6522
     */
6523
    public static function useTemplateAsBasisIfRequired($courseCode, $courseTemplate)
6524
    {
6525
        $template = api_get_setting('course_creation_use_template');
6526
        $teacherCanSelectCourseTemplate = api_get_setting('teacher_can_select_course_template') === 'true';
6527
        $courseTemplate = isset($courseTemplate) ? intval($courseTemplate) : 0;
6528
6529
        $useTemplate = false;
6530
6531
        if ($teacherCanSelectCourseTemplate && $courseTemplate) {
6532
            $useTemplate = true;
6533
            $originCourse = api_get_course_info_by_id($courseTemplate);
6534
        } elseif (!empty($template)) {
6535
            $useTemplate = true;
6536
            $originCourse = api_get_course_info_by_id($template);
6537
        }
6538
6539
        if ($useTemplate) {
6540
            // Include the necessary libraries to generate a course copy
6541
            // Call the course copy object
6542
            $originCourse['official_code'] = $originCourse['code'];
6543
            $cb = new CourseBuilder(null, $originCourse);
6544
            $course = $cb->build(null, $originCourse['code']);
6545
            $cr = new CourseRestorer($course);
6546
            $cr->set_file_option();
6547
            $cr->restore($courseCode);
6548
        }
6549
    }
6550
6551
    /**
6552
     * Helper method to get the number of users defined with a specific course extra field.
6553
     *
6554
     * @param string $name                 Field title
6555
     * @param string $tableExtraFields     The extra fields table name
6556
     * @param string $tableUserFieldValues The user extra field value table name
6557
     *
6558
     * @return int The number of users with this extra field with a specific value
6559
     */
6560
    public static function getCountRegisteredUsersWithCourseExtraField(
6561
        $name,
6562
        $tableExtraFields = '',
6563
        $tableUserFieldValues = ''
6564
    ) {
6565
        if (empty($tableExtraFields)) {
6566
            $tableExtraFields = Database::get_main_table(TABLE_EXTRA_FIELD);
6567
        }
6568
        if (empty($tableUserFieldValues)) {
6569
            $tableUserFieldValues = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
6570
        }
6571
6572
        $registered_users_with_extra_field = 0;
6573
        if (!empty($name) && $name != '-') {
6574
            $extraFieldType = EntityExtraField::COURSE_FIELD_TYPE;
6575
            $name = Database::escape_string($name);
6576
            $sql = "SELECT count(v.item_id) as count
6577
                    FROM $tableUserFieldValues v 
6578
                    INNER JOIN $tableExtraFields f
6579
                    ON (f.id = v.field_id)
6580
                    WHERE value = '$name' AND extra_field_type = $extraFieldType";
6581
            $result_count = Database::query($sql);
6582
            if (Database::num_rows($result_count)) {
6583
                $row_count = Database::fetch_array($result_count);
6584
                $registered_users_with_extra_field = $row_count['count'];
6585
            }
6586
        }
6587
6588
        return $registered_users_with_extra_field;
6589
    }
6590
6591
    /**
6592
     * Get the course categories form a course list.
6593
     *
6594
     * @param array $courseList
6595
     *
6596
     * @return array
6597
     */
6598
    public static function getCourseCategoriesFromCourseList(array $courseList)
6599
    {
6600
        $allCategories = array_column($courseList, 'category');
6601
        $categories = array_unique($allCategories);
6602
6603
        sort($categories);
6604
6605
        return $categories;
6606
    }
6607
6608
    /**
6609
     * Display the description button of a course in the course catalog.
6610
     *
6611
     * @param array $course
6612
     *
6613
     * @return string HTML string
6614
     */
6615
    public static function returnDescriptionButton($course)
6616
    {
6617
        if (empty($course)) {
6618
            return '';
6619
        }
6620
6621
        if (api_get_setting('show_courses_descriptions_in_catalog') == 'true') {
6622
            $title = $course['title'];
6623
            $url = api_get_path(WEB_CODE_PATH).'inc/ajax/course_home.ajax.php?a=show_course_information&code='.$course['code'];
6624
            $html = Display::url(
6625
                Display::returnFontAwesomeIcon('info-circle', 'lg'),
6626
                $url,
6627
                [
6628
                    'class' => 'ajax btn btn-default btn-sm',
6629
                    'data-title' => $title,
6630
                    'title' => get_lang('Description'),
6631
                    'aria-label' => get_lang('Description'),
6632
                    'data-size' => 'lg',
6633
                ]
6634
            );
6635
6636
            return $html;
6637
        }
6638
6639
        return '';
6640
    }
6641
6642
    /**
6643
     * @param ToolChain $toolList
6644
     */
6645
    public static function setToolList($toolList)
6646
    {
6647
        self::$toolList = $toolList;
6648
    }
6649
6650
    /**
6651
     * @return ToolChain
6652
     */
6653
    public static function getToolList()
6654
    {
6655
        return self::$toolList;
6656
    }
6657
6658
    /**
6659
     * Check if a specific access-url-related setting is a problem or not.
6660
     *
6661
     * @param array  $_configuration The $_configuration array
6662
     * @param int    $accessUrlId    The access URL ID
6663
     * @param string $param
6664
     * @param string $msgLabel
6665
     *
6666
     * @return bool|string
6667
     */
6668
    private static function checkCreateCourseAccessUrlParam($_configuration, $accessUrlId, $param, $msgLabel)
6669
    {
6670
        if (isset($_configuration[$accessUrlId][$param]) && $_configuration[$accessUrlId][$param] > 0) {
6671
            $num = self::count_courses($accessUrlId);
6672
            if ($num >= $_configuration[$accessUrlId][$param]) {
6673
                api_warn_hosting_contact($param);
6674
6675
                Display::addFlash(
6676
                    Display::return_message($msgLabel)
6677
                );
6678
            }
6679
        }
6680
6681
        return false;
6682
    }
6683
6684
    /**
6685
     * Fill course with all necessary items.
6686
     *
6687
     * @param array $courseInfo Course info array
6688
     * @param array $params     Parameters from the course creation form
6689
     * @param int   $authorId
6690
     */
6691
    private static function fillCourse($courseInfo, $params, $authorId = 0)
6692
    {
6693
        $authorId = empty($authorId) ? api_get_user_id() : (int) $authorId;
6694
6695
        AddCourse::prepare_course_repository($courseInfo['directory']);
6696
        AddCourse::fill_db_course(
6697
            $courseInfo['real_id'],
6698
            $courseInfo['directory'],
6699
            $courseInfo['course_language'],
6700
            $params['exemplary_content'],
6701
            $authorId
6702
        );
6703
6704
        if (isset($params['gradebook_model_id'])) {
6705
            self::createDefaultGradebook(
6706
                $params['gradebook_model_id'],
6707
                $courseInfo['code']
6708
            );
6709
        }
6710
6711
        // If parameter defined, copy the contents from a specific
6712
        // template course into this new course
6713
        if (isset($params['course_template'])) {
6714
            self::useTemplateAsBasisIfRequired(
6715
                $courseInfo['id'],
6716
                $params['course_template']
6717
            );
6718
        }
6719
        $params['course_code'] = $courseInfo['code'];
6720
        $params['item_id'] = $courseInfo['real_id'];
6721
6722
        $courseFieldValue = new ExtraFieldValue('course');
6723
        $courseFieldValue->saveFieldValues($params);
6724
    }
6725
}
6726