Passed
Push — master ( 6f8cb0...cccadf )
by Julito
09:47
created

CourseManager::get_courses_list()   F

Complexity

Conditions 22
Paths 6912

Size

Total Lines 110
Code Lines 67

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 22
eloc 67
c 0
b 0
f 0
nc 6912
nop 10
dl 0
loc 110
rs 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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