Passed
Push — master ( 6d3a7a...482b77 )
by Julito
12:08 queued 02:23
created

CourseManager::delete_course()   D

Complexity

Conditions 15
Paths 54

Size

Total Lines 209
Code Lines 128

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 15
eloc 128
nc 54
nop 1
dl 0
loc 209
rs 4.7333
c 0
b 0
f 0

How to fix   Long Method    Complexity   

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:

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

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
2499
        $course_code = Database::escape_string($course_code);
2500
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
2501
        $sql = "SELECT * FROM $table_course WHERE code = '$course_code'";
2502
        $res = Database::query($sql);
2503
        $course = Database::fetch_array($res);
2504
2505
        $course_tables = AddCourse::get_course_tables();
2506
2507
        if (!empty($course['id'])) {
2508
            //Cleaning c_x tables
2509
            foreach ($course_tables as $table) {
2510
                $table = Database::get_course_table($table);
2511
                $sql = "SELECT * FROM $table WHERE c_id = {$course['id']} ";
2512
                $res_table = Database::query($sql);
2513
2514
                while ($row = Database::fetch_array($res_table, 'ASSOC')) {
2515
                    $row_to_save = [];
2516
                    foreach ($row as $key => $value) {
2517
                        $row_to_save[$key] = $key."='".Database::escape_string($row[$key])."'";
2518
                    }
2519
                    $sql_dump .= "\nINSERT INTO $table SET ".implode(', ', $row_to_save).';';
2520
                }
2521
            }
2522
        }
2523
2524
        if (is_dir(api_get_path(SYS_COURSE_PATH).$course['directory'])) {
2525
            $file_name = api_get_path(SYS_COURSE_PATH).$course['directory'].'/mysql_dump.sql';
2526
            $handle = fopen($file_name, 'a+');
2527
            if (false !== $handle) {
2528
                fwrite($handle, $sql_dump);
2529
                fclose($handle);
2530
            } else {
2531
                //TODO trigger exception in a try-catch
2532
            }
2533
        }
2534
    }
2535
2536
    /**
2537
     * Sort courses for a specific user ??
2538
     *
2539
     * @param int    $user_id     User ID
2540
     * @param string $course_code Course code
2541
     *
2542
     * @return int Minimum course order
2543
     *
2544
     * @todo Review documentation
2545
     */
2546
    public static function userCourseSort($user_id, $course_code)
2547
    {
2548
        if ($user_id != strval(intval($user_id))) {
2549
            return false;
2550
        }
2551
2552
        $course_code = Database::escape_string($course_code);
2553
        $TABLECOURSE = Database::get_main_table(TABLE_MAIN_COURSE);
2554
        $TABLECOURSUSER = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2555
2556
        $course_title = Database::result(
2557
            Database::query(
2558
                "SELECT title FROM $TABLECOURSE WHERE code = '$course_code'"
2559
            ),
2560
            0,
2561
            0
2562
        );
2563
        if (false === $course_title) {
2564
            $course_title = '';
2565
        }
2566
2567
        $sql = "SELECT course.code as code, course.title as title, cu.sort as sort
2568
                FROM $TABLECOURSUSER as cu, $TABLECOURSE as course
2569
                WHERE   course.id = cu.c_id AND user_id = $user_id AND
2570
                        cu.relation_type <> ".COURSE_RELATION_TYPE_RRHH." AND
2571
                        user_course_cat = 0
2572
                ORDER BY cu.sort";
2573
        $result = Database::query($sql);
2574
2575
        $course_title_precedent = '';
2576
        $counter = 0;
2577
        $course_found = false;
2578
        $course_sort = 1;
2579
2580
        if (Database::num_rows($result) > 0) {
2581
            while ($courses = Database::fetch_array($result)) {
2582
                if ('' == $course_title_precedent) {
2583
                    $course_title_precedent = $courses['title'];
2584
                }
2585
                if (api_strcasecmp($course_title_precedent, $course_title) < 0) {
2586
                    $course_found = true;
2587
                    $course_sort = $courses['sort'];
2588
                    if (0 == $counter) {
2589
                        $sql = "UPDATE $TABLECOURSUSER
2590
                                SET sort = sort+1
2591
                                WHERE
2592
                                    user_id= $user_id AND
2593
                                    relation_type <> ".COURSE_RELATION_TYPE_RRHH."
2594
                                    AND user_course_cat = 0
2595
                                    AND sort > $course_sort";
2596
                        $course_sort++;
2597
                    } else {
2598
                        $sql = "UPDATE $TABLECOURSUSER SET sort = sort+1
2599
                                WHERE
2600
                                    user_id= $user_id AND
2601
                                    relation_type <> ".COURSE_RELATION_TYPE_RRHH." AND
2602
                                    user_course_cat = 0 AND
2603
                                    sort >= $course_sort";
2604
                    }
2605
                    Database::query($sql);
2606
                    break;
2607
                } else {
2608
                    $course_title_precedent = $courses['title'];
2609
                }
2610
                $counter++;
2611
            }
2612
2613
            // We must register the course in the beginning of the list
2614
            if (!$course_found) {
2615
                $course_sort = Database::result(
2616
                    Database::query(
2617
                        'SELECT min(sort) as min_sort FROM '.$TABLECOURSUSER.' WHERE user_id = "'.$user_id.'" AND user_course_cat="0"'
2618
                    ),
2619
                    0,
2620
                    0
2621
                );
2622
                Database::query("UPDATE $TABLECOURSUSER SET sort = sort+1 WHERE user_id = $user_id AND user_course_cat = 0");
2623
            }
2624
        }
2625
2626
        return $course_sort;
2627
    }
2628
2629
    /**
2630
     * check if course exists.
2631
     *
2632
     * @param string $courseCode
2633
     *
2634
     * @return int if exists, false else
2635
     */
2636
    public static function course_exists($courseCode)
2637
    {
2638
        $courseCode = Database::escape_string($courseCode);
2639
        $sql = "SELECT 1 FROM ".Database::get_main_table(TABLE_MAIN_COURSE)."
2640
                WHERE code = '$courseCode'";
2641
2642
        return Database::num_rows(Database::query($sql));
2643
    }
2644
2645
    /**
2646
     * Send an email to tutor after the auth-suscription of a student in your course.
2647
     *
2648
     * @author Carlos Vargas <[email protected]>, Dokeos Latino
2649
     *
2650
     * @param int    $user_id            the id of the user
2651
     * @param string $courseId           the course code
2652
     * @param bool   $send_to_tutor_also
2653
     *
2654
     * @return false|null we return the message that is displayed when the action is successful
2655
     */
2656
    public static function email_to_tutor($user_id, $courseId, $send_to_tutor_also = false)
2657
    {
2658
        $user_id = (int) $user_id;
2659
        $courseId = (int) $courseId;
2660
        $information = api_get_course_info_by_id($courseId);
2661
        $course_code = $information['code'];
2662
        $student = api_get_user_info($user_id);
2663
2664
        $name_course = $information['title'];
2665
        $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
2666
                WHERE c_id = $courseId";
2667
2668
        // TODO: Ivan: This is a mistake, please, have a look at it. Intention here is diffcult to be guessed.
2669
        //if ($send_to_tutor_also = true)
2670
        // Proposed change:
2671
        if ($send_to_tutor_also) {
2672
            $sql .= ' AND is_tutor = 1';
2673
        } else {
2674
            $sql .= ' AND status = 1';
2675
        }
2676
2677
        $result = Database::query($sql);
2678
        while ($row = Database::fetch_array($result)) {
2679
            $tutor = api_get_user_info($row['user_id']);
2680
            $emailto = $tutor['email'];
2681
            $emailsubject = get_lang('New user in the course').': '.$name_course;
2682
            $emailbody = get_lang('Dear').': '.api_get_person_name($tutor['firstname'], $tutor['lastname'])."\n";
2683
            $emailbody .= get_lang('MessageNew user in the course').': '.$name_course."\n";
2684
            $emailbody .= get_lang('Username').': '.$student['username']."\n";
2685
            if (api_is_western_name_order()) {
2686
                $emailbody .= get_lang('First name').': '.$student['firstname']."\n";
2687
                $emailbody .= get_lang('Last name').': '.$student['lastname']."\n";
2688
            } else {
2689
                $emailbody .= get_lang('Last name').': '.$student['lastname']."\n";
2690
                $emailbody .= get_lang('First name').': '.$student['firstname']."\n";
2691
            }
2692
            $emailbody .= get_lang('e-mail').': <a href="mailto:'.$student['email'].'">'.$student['email']."</a>\n\n";
2693
            $recipient_name = api_get_person_name(
2694
                $tutor['firstname'],
2695
                $tutor['lastname'],
2696
                null,
2697
                PERSON_NAME_EMAIL_ADDRESS
2698
            );
2699
            $sender_name = api_get_person_name(
2700
                api_get_setting('administratorName'),
2701
                api_get_setting('administratorSurname'),
2702
                null,
2703
                PERSON_NAME_EMAIL_ADDRESS
2704
            );
2705
            $email_admin = api_get_setting('emailAdministrator');
2706
2707
            $additionalParameters = [
2708
                'smsType' => SmsPlugin::NEW_USER_SUBSCRIBED_COURSE,
2709
                'userId' => $tutor['user_id'],
2710
                'userUsername' => $student['username'],
2711
                'courseCode' => $course_code,
2712
            ];
2713
            api_mail_html(
2714
                $recipient_name,
2715
                $emailto,
2716
                $emailsubject,
2717
                $emailbody,
2718
                $sender_name,
2719
                $email_admin,
2720
                null,
2721
                null,
2722
                null,
2723
                $additionalParameters
2724
            );
2725
        }
2726
    }
2727
2728
    /**
2729
     * @return array
2730
     */
2731
    public static function get_special_course_list()
2732
    {
2733
        $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
2734
        $tbl_course_field = Database::get_main_table(TABLE_EXTRA_FIELD);
2735
        $tbl_course_field_value = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
2736
2737
        //we filter the courses from the URL
2738
        $join_access_url = $where_access_url = '';
2739
        if (api_get_multiple_access_url()) {
2740
            $access_url_id = api_get_current_access_url_id();
2741
            if (-1 != $access_url_id) {
2742
                $tbl_url_course = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2743
                $join_access_url = "LEFT JOIN $tbl_url_course url_rel_course
2744
                                    ON url_rel_course.c_id = tcfv.item_id ";
2745
                $where_access_url = " AND access_url_id = $access_url_id ";
2746
            }
2747
        }
2748
2749
        $extraFieldType = EntityExtraField::COURSE_FIELD_TYPE;
2750
2751
        // get course list auto-register
2752
        $sql = "SELECT DISTINCT(c.id)
2753
                FROM $tbl_course_field_value tcfv
2754
                INNER JOIN $tbl_course_field tcf
2755
                ON tcfv.field_id =  tcf.id $join_access_url
2756
                INNER JOIN $courseTable c
2757
                ON (c.id = tcfv.item_id)
2758
                WHERE
2759
                    tcf.extra_field_type = $extraFieldType AND
2760
                    tcf.variable = 'special_course' AND
2761
                    tcfv.value = 1 $where_access_url";
2762
2763
        $result = Database::query($sql);
2764
        $courseList = [];
2765
2766
        if (Database::num_rows($result) > 0) {
2767
            while ($row = Database::fetch_array($result)) {
2768
                $courseList[] = $row['id'];
2769
            }
2770
        }
2771
2772
        return $courseList;
2773
    }
2774
2775
    /**
2776
     * Get the course codes that have been restricted in the catalogue, and if byUserId is set
2777
     * then the courses that the user is allowed or not to see in catalogue.
2778
     *
2779
     * @param bool $allowed  Either if the courses have some users that are or are not allowed to see in catalogue
2780
     * @param int  $byUserId if the courses are or are not allowed to see to the user
2781
     *
2782
     * @return array Course codes allowed or not to see in catalogue by some user or the user
2783
     */
2784
    public static function getCatalogueCourseList($allowed = true, $byUserId = -1)
2785
    {
2786
        $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
2787
        $tblCourseRelUserCatalogue = Database::get_main_table(TABLE_MAIN_COURSE_CATALOGUE_USER);
2788
        $visibility = $allowed ? 1 : 0;
2789
2790
        // Restriction by user id
2791
        $currentUserRestriction = '';
2792
        if ($byUserId > 0) {
2793
            $byUserId = (int) $byUserId;
2794
            $currentUserRestriction = " AND tcruc.user_id = $byUserId ";
2795
        }
2796
2797
        //we filter the courses from the URL
2798
        $joinAccessUrl = '';
2799
        $whereAccessUrl = '';
2800
        if (api_get_multiple_access_url()) {
2801
            $accessUrlId = api_get_current_access_url_id();
2802
            if (-1 != $accessUrlId) {
2803
                $tblUrlCourse = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2804
                $joinAccessUrl = "LEFT JOIN $tblUrlCourse url_rel_course
2805
                                  ON url_rel_course.c_id = c.id ";
2806
                $whereAccessUrl = " AND access_url_id = $accessUrlId ";
2807
            }
2808
        }
2809
2810
        // get course list auto-register
2811
        $sql = "SELECT DISTINCT(c.code)
2812
                FROM $tblCourseRelUserCatalogue tcruc
2813
                INNER JOIN $courseTable c
2814
                ON (c.id = tcruc.c_id) $joinAccessUrl
2815
                WHERE tcruc.visible = $visibility $currentUserRestriction $whereAccessUrl";
2816
2817
        $result = Database::query($sql);
2818
        $courseList = [];
2819
2820
        if (Database::num_rows($result) > 0) {
2821
            while ($resultRow = Database::fetch_array($result)) {
2822
                $courseList[] = $resultRow['code'];
2823
            }
2824
        }
2825
2826
        return $courseList;
2827
    }
2828
2829
    /**
2830
     * Get list of courses for a given user.
2831
     *
2832
     * @param int   $user_id
2833
     * @param bool  $include_sessions                   Whether to include courses from session or not
2834
     * @param bool  $adminGetsAllCourses                If the user is platform admin,
2835
     *                                                  whether he gets all the courses or just his. Note: This does *not* include all sessions
2836
     * @param bool  $loadSpecialCourses
2837
     * @param array $skipCourseList                     List of course ids to skip
2838
     * @param bool  $useUserLanguageFilterIfAvailable
2839
     * @param bool  $showCoursesSessionWithDifferentKey
2840
     *
2841
     * @return array List of codes and db name
2842
     *
2843
     * @author isaac flores paz
2844
     */
2845
    public static function get_courses_list_by_user_id(
2846
        $user_id,
2847
        $include_sessions = false,
2848
        $adminGetsAllCourses = false,
2849
        $loadSpecialCourses = true,
2850
        $skipCourseList = [],
2851
        $useUserLanguageFilterIfAvailable = true,
2852
        $showCoursesSessionWithDifferentKey = false
2853
    ) {
2854
        $user_id = intval($user_id);
2855
        $urlId = api_get_current_access_url_id();
2856
        $course_list = [];
2857
        $codes = [];
2858
2859
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
2860
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2861
        $tbl_user_course_category = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
2862
        $tableCourseUrl = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2863
        $tblCourseCategory = Database::get_main_table(TABLE_MAIN_CATEGORY);
2864
2865
        $languageCondition = '';
2866
        $onlyInUserLanguage = api_get_configuration_value('my_courses_show_courses_in_user_language_only');
2867
        if ($useUserLanguageFilterIfAvailable && $onlyInUserLanguage) {
2868
            $userInfo = api_get_user_info(api_get_user_id());
2869
            if (!empty($userInfo['language'])) {
2870
                $languageCondition = " AND course.course_language = '".$userInfo['language']."' ";
2871
            }
2872
        }
2873
2874
        if ($adminGetsAllCourses && UserManager::is_admin($user_id)) {
2875
            // get the whole courses list
2876
            $sql = "SELECT DISTINCT(course.code), course.id as real_id, course.title
2877
                    FROM $tbl_course course
2878
                    INNER JOIN $tableCourseUrl url
2879
                    ON (course.id = url.c_id)
2880
                    WHERE
2881
                        url.access_url_id = $urlId
2882
                        $languageCondition
2883
                ";
2884
        } else {
2885
            $withSpecialCourses = $withoutSpecialCourses = '';
2886
2887
            if ($loadSpecialCourses) {
2888
                $specialCourseList = self::get_special_course_list();
2889
2890
                if (!empty($specialCourseList)) {
2891
                    $specialCourseToString = '"'.implode('","', $specialCourseList).'"';
2892
                    $withSpecialCourses = ' AND course.id IN ('.$specialCourseToString.')';
2893
                    $withoutSpecialCourses = ' AND course.id NOT IN ('.$specialCourseToString.')';
2894
                }
2895
2896
                if (!empty($withSpecialCourses)) {
2897
                    $sql = "SELECT DISTINCT (course.code),
2898
                            course.id as real_id,
2899
                            course_category.code AS category,
2900
                            course.title
2901
                            FROM $tbl_course_user course_rel_user
2902
                            LEFT JOIN $tbl_course course
2903
                            ON course.id = course_rel_user.c_id
2904
                            LEFT JOIN $tblCourseCategory ON course_category.id = course.category_id
2905
                            LEFT JOIN $tbl_user_course_category user_course_category
2906
                            ON course_rel_user.user_course_cat = user_course_category.id
2907
                            INNER JOIN $tableCourseUrl url
2908
                            ON (course.id = url.c_id)
2909
                            WHERE url.access_url_id = $urlId
2910
                            $withSpecialCourses
2911
                            $languageCondition
2912
                            GROUP BY course.code
2913
                            ORDER BY user_course_category.sort, course.title, course_rel_user.sort ASC
2914
                    ";
2915
                    $result = Database::query($sql);
2916
                    if (Database::num_rows($result) > 0) {
2917
                        while ($result_row = Database::fetch_array($result, 'ASSOC')) {
2918
                            $result_row['special_course'] = 1;
2919
                            $course_list[] = $result_row;
2920
                            $codes[] = $result_row['real_id'];
2921
                        }
2922
                    }
2923
                }
2924
            }
2925
2926
            // get course list not auto-register. Use Distinct to avoid multiple
2927
            // entries when a course is assigned to a HRD (DRH) as watcher
2928
            $sql = "SELECT
2929
                        DISTINCT(course.code),
2930
                        course.id as real_id,
2931
                        course.category_id AS category,
2932
                        course.title
2933
                    FROM $tbl_course course
2934
                    INNER JOIN $tbl_course_user cru
2935
                    ON (course.id = cru.c_id)
2936
                    INNER JOIN $tableCourseUrl url
2937
                    ON (course.id = url.c_id)
2938
                    WHERE
2939
                        url.access_url_id = $urlId AND
2940
                        cru.user_id = $user_id
2941
                        $withoutSpecialCourses
2942
                        $languageCondition
2943
                    ORDER BY course.title
2944
                    ";
2945
        }
2946
        $result = Database::query($sql);
2947
2948
        if (Database::num_rows($result)) {
2949
            while ($row = Database::fetch_array($result, 'ASSOC')) {
2950
                if (!empty($skipCourseList)) {
2951
                    if (in_array($row['real_id'], $skipCourseList)) {
2952
                        continue;
2953
                    }
2954
                }
2955
                $course_list[] = $row;
2956
                $codes[] = $row['real_id'];
2957
            }
2958
        }
2959
2960
        if (true === $include_sessions) {
2961
            $sql = "SELECT DISTINCT (c.code),
2962
                        c.id as real_id,
2963
                        c.category_code AS category,
2964
                        s.id as session_id,
2965
                        s.name as session_name
2966
                    FROM ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)." scu
2967
                    INNER JOIN $tbl_course c
2968
                    ON (scu.c_id = c.id)
2969
                    INNER JOIN ".Database::get_main_table(TABLE_MAIN_SESSION)." s
2970
                    ON (s.id = scu.session_id)
2971
                    WHERE user_id = $user_id ";
2972
            $r = Database::query($sql);
2973
            while ($row = Database::fetch_array($r, 'ASSOC')) {
2974
                if (!empty($skipCourseList)) {
2975
                    if (in_array($row['real_id'], $skipCourseList)) {
2976
                        continue;
2977
                    }
2978
                }
2979
2980
                if ($showCoursesSessionWithDifferentKey) {
2981
                    $course_list[] = $row;
2982
                } else {
2983
                    if (!in_array($row['real_id'], $codes)) {
2984
                        $course_list[] = $row;
2985
                    }
2986
                }
2987
            }
2988
        }
2989
2990
        return $course_list;
2991
    }
2992
2993
    /**
2994
     * Get course ID from a given course directory name.
2995
     *
2996
     * @param string $path Course directory (without any slash)
2997
     *
2998
     * @return string Course code, or false if not found
2999
     */
3000
    public static function getCourseCodeFromDirectory($path)
3001
    {
3002
        $path = Database::escape_string(str_replace('.', '', str_replace('/', '', $path)));
3003
        $res = Database::query("SELECT code FROM ".Database::get_main_table(TABLE_MAIN_COURSE)."
3004
                WHERE directory LIKE BINARY '$path'");
3005
        if (false === $res) {
3006
            return false;
3007
        }
3008
        if (1 != Database::num_rows($res)) {
3009
            return false;
3010
        }
3011
        $row = Database::fetch_array($res);
3012
3013
        return $row['code'];
3014
    }
3015
3016
    /**
3017
     * Get course code(s) from visual code.
3018
     *
3019
     * @deprecated
3020
     *
3021
     * @param   string  Visual code
3022
     *
3023
     * @return array List of codes for the given visual code
3024
     */
3025
    public static function get_courses_info_from_visual_code($code)
3026
    {
3027
        $result = [];
3028
        $sql_result = Database::query("SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE)."
3029
                WHERE visual_code = '".Database::escape_string($code)."'");
3030
        while ($virtual_course = Database::fetch_array($sql_result)) {
3031
            $result[] = $virtual_course;
3032
        }
3033
3034
        return $result;
3035
    }
3036
3037
    /**
3038
     * Creates a new extra field for a given course.
3039
     *
3040
     * @param string $variable    Field's internal variable name
3041
     * @param int    $fieldType   Field's type
3042
     * @param string $displayText Field's language var name
3043
     * @param string $default     Optional. The default value
3044
     *
3045
     * @return int New extra field ID
3046
     */
3047
    public static function create_course_extra_field($variable, $fieldType, $displayText, $default = '')
3048
    {
3049
        $extraField = new ExtraField('course');
3050
        $params = [
3051
            'variable' => $variable,
3052
            'field_type' => $fieldType,
3053
            'display_text' => $displayText,
3054
            'default_value' => $default,
3055
        ];
3056
3057
        return $extraField->save($params);
3058
    }
3059
3060
    /**
3061
     * Update course attributes. Will only update attributes with a non-empty value.
3062
     * Note that you NEED to check that your attributes are valid before using this function.
3063
     *
3064
     * @param int Course id
3065
     * @param array Associative array with field names as keys and field values as values
3066
     *
3067
     * @return Doctrine\DBAL\Driver\Statement|null True if update was successful, false otherwise
3068
     */
3069
    public static function update_attributes($id, $attributes)
3070
    {
3071
        $courseCategory = CourseCategory::getCategory($attributes['category_code']);
3072
3073
        unset($attributes['category_code']);
3074
3075
        if (!empty($courseCategory)) {
3076
            $attributes['category_id'] = $courseCategory['id'];
3077
        }
3078
3079
        $id = (int) $id;
3080
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
3081
        $sql = "UPDATE $table SET ";
3082
        $i = 0;
3083
        foreach ($attributes as $name => $value) {
3084
            if ('' != $value) {
3085
                if ($i > 0) {
3086
                    $sql .= ", ";
3087
                }
3088
                $sql .= " $name = '".Database::escape_string($value)."'";
3089
                $i++;
3090
            }
3091
        }
3092
        $sql .= " WHERE id = $id";
3093
3094
        return Database::query($sql);
3095
    }
3096
3097
    /**
3098
     * Update an extra field value for a given course.
3099
     *
3100
     * @param string $course_code Course code
3101
     * @param string $variable    Field variable name
3102
     * @param string $value       Optional. Default field value
3103
     *
3104
     * @return bool|int An integer when register a new extra field. And boolean when update the extrafield
3105
     */
3106
    public static function update_course_extra_field_value($course_code, $variable, $value = '')
3107
    {
3108
        $courseInfo = api_get_course_info($course_code);
3109
        $courseId = $courseInfo['real_id'];
3110
3111
        $extraFieldValues = new ExtraFieldValue('course');
3112
        $params = [
3113
            'item_id' => $courseId,
3114
            'variable' => $variable,
3115
            'value' => $value,
3116
        ];
3117
3118
        return $extraFieldValues->save($params);
3119
    }
3120
3121
    /**
3122
     * @param int $sessionId
3123
     *
3124
     * @return mixed
3125
     */
3126
    public static function get_session_category_id_by_session_id($sessionId)
3127
    {
3128
        if (empty($sessionId)) {
3129
            return [];
3130
        }
3131
        $sessionId = intval($sessionId);
3132
        $sql = 'SELECT sc.id session_category
3133
                FROM '.Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY).' sc
3134
                INNER JOIN '.Database::get_main_table(TABLE_MAIN_SESSION).' s
3135
                ON sc.id = s.session_category_id
3136
                WHERE s.id = '.$sessionId;
3137
3138
        return Database::result(
3139
            Database::query($sql),
3140
            0,
3141
            'session_category'
3142
        );
3143
    }
3144
3145
    /**
3146
     * Gets the value of a course extra field. Returns null if it was not found.
3147
     *
3148
     * @param string $variable Name of the extra field
3149
     * @param string $code     Course code
3150
     *
3151
     * @return string Value
3152
     */
3153
    public static function get_course_extra_field_value($variable, $code)
3154
    {
3155
        $courseInfo = api_get_course_info($code);
3156
        $courseId = $courseInfo['real_id'];
3157
3158
        $extraFieldValues = new ExtraFieldValue('course');
3159
        $result = $extraFieldValues->get_values_by_handler_and_field_variable($courseId, $variable);
3160
        if (!empty($result['value'])) {
3161
            return $result['value'];
3162
        }
3163
3164
        return null;
3165
    }
3166
3167
    /**
3168
     * Lists details of the course description.
3169
     *
3170
     * @param array        The course description
3171
     * @param string    The encoding
3172
     * @param bool        If true is displayed if false is hidden
3173
     *
3174
     * @return string The course description in html
3175
     */
3176
    public static function get_details_course_description_html(
3177
        $descriptions,
3178
        $charset,
3179
        $action_show = true
3180
    ) {
3181
        $data = null;
3182
        if (isset($descriptions) && count($descriptions) > 0) {
3183
            foreach ($descriptions as $description) {
3184
                $data .= '<div class="sectiontitle">';
3185
                if (api_is_allowed_to_edit() && $action_show) {
3186
                    //delete
3187
                    $data .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=delete&description_id='.$description->id.'" onclick="javascript:if(!confirm(\''.addslashes(api_htmlentities(
3188
                        get_lang('Please confirm your choice'),
3189
                                ENT_QUOTES,
3190
                        $charset
3191
                    )).'\')) return false;">';
3192
                    $data .= Display::return_icon(
3193
                        'delete.gif',
3194
                        get_lang('Delete'),
3195
                        ['style' => 'vertical-align:middle;float:right;']
3196
                    );
3197
                    $data .= '</a> ';
3198
                    //edit
3199
                    $data .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&description_id='.$description->id.'">';
3200
                    $data .= Display::return_icon(
3201
                        'edit.png',
3202
                        get_lang('Edit'),
3203
                        ['style' => 'vertical-align:middle;float:right; padding-right:4px;'],
3204
                        ICON_SIZE_SMALL
3205
                    );
3206
                    $data .= '</a> ';
3207
                }
3208
                $data .= $description->title;
3209
                $data .= '</div>';
3210
                $data .= '<div class="sectioncomment">';
3211
                $data .= Security::remove_XSS($description->content);
3212
                $data .= '</div>';
3213
            }
3214
        } else {
3215
            $data .= '<em>'.get_lang('There is no course description so far.').'</em>';
3216
        }
3217
3218
        return $data;
3219
    }
3220
3221
    /**
3222
     * Returns the details of a course category.
3223
     *
3224
     * @param string $code Category code
3225
     *
3226
     * @return array Course category
3227
     */
3228
    public static function get_course_category($code)
3229
    {
3230
        $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
3231
        $code = Database::escape_string($code);
3232
        $sql = "SELECT * FROM $table WHERE code = '$code'";
3233
3234
        return Database::fetch_array(Database::query($sql));
3235
    }
3236
3237
    /**
3238
     * Subscribes courses to human resource manager (Dashboard feature).
3239
     *
3240
     * @param int   $hr_manager_id Human Resource Manager id
3241
     * @param array $courses_list  Courses code
3242
     *
3243
     * @return int
3244
     */
3245
    public static function subscribeCoursesToDrhManager($hr_manager_id, $courses_list)
3246
    {
3247
        $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
3248
        $tbl_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
3249
3250
        $hr_manager_id = intval($hr_manager_id);
3251
        $affected_rows = 0;
3252
3253
        //Deleting assigned courses to hrm_id
3254
        if (api_is_multiple_url_enabled()) {
3255
            $sql = "SELECT s.c_id FROM $tbl_course_rel_user s
3256
                    INNER JOIN $tbl_course_rel_access_url a
3257
                    ON (a.c_id = s.c_id)
3258
                    WHERE
3259
                        user_id = $hr_manager_id AND
3260
                        relation_type = ".COURSE_RELATION_TYPE_RRHH." AND
3261
                        access_url_id = ".api_get_current_access_url_id();
3262
        } else {
3263
            $sql = "SELECT c_id FROM $tbl_course_rel_user
3264
                    WHERE user_id = $hr_manager_id AND relation_type = ".COURSE_RELATION_TYPE_RRHH;
3265
        }
3266
        $result = Database::query($sql);
3267
        if (Database::num_rows($result) > 0) {
3268
            while ($row = Database::fetch_array($result)) {
3269
                $sql = "DELETE FROM $tbl_course_rel_user
3270
                        WHERE
3271
                            c_id = {$row['c_id']} AND
3272
                            user_id = $hr_manager_id AND
3273
                            relation_type = ".COURSE_RELATION_TYPE_RRHH;
3274
                Database::query($sql);
3275
            }
3276
        }
3277
3278
        // inserting new courses list
3279
        if (is_array($courses_list)) {
3280
            foreach ($courses_list as $course_code) {
3281
                $courseInfo = api_get_course_info($course_code);
3282
                $courseId = $courseInfo['real_id'];
3283
                $sql = "INSERT IGNORE INTO $tbl_course_rel_user(c_id, user_id, status, relation_type)
3284
                        VALUES($courseId, $hr_manager_id, ".DRH.", ".COURSE_RELATION_TYPE_RRHH.")";
3285
                $result = Database::query($sql);
3286
                if (Database::affected_rows($result)) {
3287
                    $affected_rows++;
3288
                }
3289
            }
3290
        }
3291
3292
        return $affected_rows;
3293
    }
3294
3295
    /**
3296
     * get courses followed by human resources manager.
3297
     *
3298
     * @param int    $user_id
3299
     * @param int    $status
3300
     * @param int    $from
3301
     * @param int    $limit
3302
     * @param string $column
3303
     * @param string $direction
3304
     * @param bool   $getCount
3305
     *
3306
     * @return array courses
3307
     */
3308
    public static function get_courses_followed_by_drh(
3309
        $user_id,
3310
        $status = DRH,
3311
        $from = null,
3312
        $limit = null,
3313
        $column = null,
3314
        $direction = null,
3315
        $getCount = false
3316
    ) {
3317
        return self::getCoursesFollowedByUser(
3318
            $user_id,
3319
            $status,
3320
            $from,
3321
            $limit,
3322
            $column,
3323
            $direction,
3324
            $getCount
3325
        );
3326
    }
3327
3328
    /**
3329
     * get courses followed by user.
3330
     *
3331
     * @param int    $user_id
3332
     * @param int    $status
3333
     * @param int    $from
3334
     * @param int    $limit
3335
     * @param string $column
3336
     * @param string $direction
3337
     * @param bool   $getCount
3338
     * @param string $keyword
3339
     * @param int    $sessionId
3340
     * @param bool   $showAllAssignedCourses
3341
     *
3342
     * @return array courses
3343
     */
3344
    public static function getCoursesFollowedByUser(
3345
        $user_id,
3346
        $status = null,
3347
        $from = null,
3348
        $limit = null,
3349
        $column = null,
3350
        $direction = null,
3351
        $getCount = false,
3352
        $keyword = null,
3353
        $sessionId = 0,
3354
        $showAllAssignedCourses = false
3355
    ) {
3356
        // Database Table Definitions
3357
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
3358
        $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
3359
        $tbl_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
3360
        $sessionId = (int) $sessionId;
3361
        $user_id = (int) $user_id;
3362
        $select = "SELECT DISTINCT c.*, c.id as real_id ";
3363
3364
        if ($getCount) {
3365
            $select = "SELECT COUNT(DISTINCT c.id) as count";
3366
        }
3367
3368
        $whereConditions = '';
3369
        switch ($status) {
3370
            case COURSEMANAGER:
3371
                $whereConditions .= " AND cru.user_id = $user_id";
3372
                if (!$showAllAssignedCourses) {
3373
                    $whereConditions .= " AND cru.status = ".COURSEMANAGER;
3374
                } else {
3375
                    $whereConditions .= " AND relation_type = ".COURSE_RELATION_TYPE_COURSE_MANAGER;
3376
                }
3377
                break;
3378
            case DRH:
3379
                $whereConditions .= " AND
3380
                    cru.user_id = $user_id AND
3381
                    cru.status = ".DRH." AND
3382
                    relation_type = '".COURSE_RELATION_TYPE_RRHH."'
3383
                ";
3384
                break;
3385
        }
3386
3387
        $keywordCondition = null;
3388
        if (!empty($keyword)) {
3389
            $keyword = Database::escape_string($keyword);
3390
            $keywordCondition = " AND (c.code LIKE '%$keyword%' OR c.title LIKE '%$keyword%' ) ";
3391
        }
3392
3393
        $orderBy = null;
3394
        $extraInnerJoin = null;
3395
3396
        if (!empty($sessionId)) {
3397
            if (COURSEMANAGER == $status) {
3398
                // Teacher of course or teacher inside session
3399
                $whereConditions = " AND (cru.status = ".COURSEMANAGER." OR srcru.status = 2) ";
3400
            }
3401
            $courseList = SessionManager::get_course_list_by_session_id($sessionId);
3402
            if (!empty($courseList)) {
3403
                $courseListToString = implode("','", array_keys($courseList));
3404
                $whereConditions .= " AND c.id IN ('".$courseListToString."')";
3405
            }
3406
            $tableSessionRelCourse = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
3407
            $tableSessionRelCourseRelUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
3408
            $orderBy = ' ORDER BY position';
3409
            $extraInnerJoin = " INNER JOIN $tableSessionRelCourse src
3410
                                ON (c.id = src.c_id AND src.session_id = $sessionId)
3411
                                INNER JOIN $tableSessionRelCourseRelUser srcru
3412
                                ON (src.session_id = srcru.session_id AND srcru.c_id = src.c_id)
3413
                            ";
3414
        }
3415
3416
        $whereConditions .= $keywordCondition;
3417
        $sql = "$select
3418
                FROM $tbl_course c
3419
                INNER JOIN $tbl_course_rel_user cru
3420
                ON (cru.c_id = c.id)
3421
                INNER JOIN $tbl_course_rel_access_url a
3422
                ON (a.c_id = c.id)
3423
                $extraInnerJoin
3424
                WHERE
3425
                    access_url_id = ".api_get_current_access_url_id()."
3426
                    $whereConditions
3427
                $orderBy
3428
                ";
3429
        if (isset($from) && isset($limit)) {
3430
            $from = intval($from);
3431
            $limit = intval($limit);
3432
            $sql .= " LIMIT $from, $limit";
3433
        }
3434
3435
        $result = Database::query($sql);
3436
3437
        if ($getCount) {
3438
            $row = Database::fetch_array($result);
3439
3440
            return $row['count'];
3441
        }
3442
3443
        $courses = [];
3444
        if (Database::num_rows($result) > 0) {
3445
            while ($row = Database::fetch_array($result)) {
3446
                $courses[$row['code']] = $row;
3447
            }
3448
        }
3449
3450
        return $courses;
3451
    }
3452
3453
    /**
3454
     * check if a course is special (autoregister).
3455
     *
3456
     * @param int $courseId
3457
     *
3458
     * @return bool
3459
     */
3460
    public static function isSpecialCourse($courseId)
3461
    {
3462
        $extraFieldValue = new ExtraFieldValue('course');
3463
        $result = $extraFieldValue->get_values_by_handler_and_field_variable(
3464
            $courseId,
3465
            'special_course'
3466
        );
3467
3468
        if (!empty($result)) {
3469
            if (1 == $result['value']) {
3470
                return true;
3471
            }
3472
        }
3473
3474
        return false;
3475
    }
3476
3477
    /**
3478
     * Display special courses (and only these) as several HTML divs of class userportal-course-item.
3479
     *
3480
     * Special courses are courses that stick on top of the list and are "auto-registerable"
3481
     * in the sense that any user clicking them is registered as a student
3482
     *
3483
     * @param int  $user_id                          User id
3484
     * @param bool $load_dirs                        Whether to show the document quick-loader or not
3485
     * @param bool $useUserLanguageFilterIfAvailable
3486
     *
3487
     * @return array
3488
     */
3489
    public static function returnSpecialCourses(
3490
        $user_id,
3491
        $load_dirs = false,
3492
        $useUserLanguageFilterIfAvailable = true
3493
    ) {
3494
        $user_id = (int) $user_id;
3495
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
3496
        $specialCourseList = self::get_special_course_list();
3497
3498
        if (empty($specialCourseList)) {
3499
            return [];
3500
        }
3501
3502
        // Filter by language
3503
        $languageCondition = '';
3504
        $onlyInUserLanguage = api_get_configuration_value('my_courses_show_courses_in_user_language_only');
3505
        if ($useUserLanguageFilterIfAvailable && $onlyInUserLanguage) {
3506
            $userInfo = api_get_user_info(api_get_user_id());
3507
            if (!empty($userInfo['language'])) {
3508
                $languageCondition = " AND course_language = '".$userInfo['language']."' ";
3509
            }
3510
        }
3511
3512
        $sql = "SELECT
3513
                    id,
3514
                    code,
3515
                    subscribe subscr,
3516
                    unsubscribe unsubscr
3517
                FROM $table
3518
                WHERE
3519
                    id IN ('".implode("','", $specialCourseList)."')
3520
                    $languageCondition
3521
                GROUP BY code";
3522
3523
        $rs_special_course = Database::query($sql);
3524
        $number_of_courses = Database::num_rows($rs_special_course);
3525
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
3526
3527
        $courseList = [];
3528
        if ($number_of_courses > 0) {
3529
            while ($course = Database::fetch_array($rs_special_course)) {
3530
                $course_info = api_get_course_info($course['code']);
3531
                $courseId = $course_info['real_id'];
3532
                if (COURSE_VISIBILITY_HIDDEN == $course_info['visibility']) {
3533
                    continue;
3534
                }
3535
3536
                $params = [];
3537
                //Param (course_code) needed to get the student info in page "My courses"
3538
                $params['course_code'] = $course['code'];
3539
                $params['code'] = $course['code'];
3540
                // Get notifications.
3541
                $course_info['id_session'] = null;
3542
                $courseUserInfo = self::getUserCourseInfo($user_id, $courseId);
3543
3544
                if (empty($courseUserInfo)) {
3545
                    $course_info['status'] = STUDENT;
3546
                } else {
3547
                    $course_info['status'] = $courseUserInfo['status'];
3548
                }
3549
                $show_notification = !api_get_configuration_value('hide_course_notification')
3550
                    ? Display::show_notification($course_info)
3551
                    : '';
3552
                $params['edit_actions'] = '';
3553
                $params['document'] = '';
3554
                if (api_is_platform_admin()) {
3555
                    $params['edit_actions'] .= api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cid='.$course['real_id'];
3556
                    if ($load_dirs) {
3557
                        $params['document'] = '<a id="document_preview_'.$courseId.'_0" class="document_preview btn btn-outline-secondary btn-sm" href="javascript:void(0);">'
3558
                           .Display::returnFontAwesomeIcon('folder-open').'</a>';
3559
                        $params['document'] .= Display::div('', ['id' => 'document_result_'.$courseId.'_0', 'class' => 'document_preview_container']);
3560
                    }
3561
                } else {
3562
                    if (COURSE_VISIBILITY_CLOSED != $course_info['visibility'] && $load_dirs) {
3563
                        $params['document'] = '<a id="document_preview_'.$courseId.'_0" class="document_preview btn btn-outline-secondary btn-sm" href="javascript:void(0);">'
3564
                           .Display::returnFontAwesomeIcon('folder-open').'</a>';
3565
                        $params['document'] .= Display::div('', ['id' => 'document_result_'.$courseId.'_0', 'class' => 'document_preview_container']);
3566
                    }
3567
                }
3568
3569
                $params['visibility'] = $course_info['visibility'];
3570
                $params['status'] = $course_info['status'];
3571
                $params['category'] = $course_info['categoryName'];
3572
                $params['category_code'] = $course_info['categoryCode'];
3573
                $params['icon'] = Display::return_icon(
3574
                    'drawing-pin.png',
3575
                    null,
3576
                    null,
3577
                    ICON_SIZE_LARGE,
3578
                    null
3579
                );
3580
3581
                if ('true' == api_get_setting('display_coursecode_in_courselist')) {
3582
                    $params['code_course'] = '('.$course_info['visual_code'].')';
3583
                }
3584
3585
                $params['title'] = $course_info['title'];
3586
                $params['title_cut'] = $course_info['title'];
3587
                $params['link'] = $course_info['course_public_url'].'?id_session=0&autoreg=1';
3588
                if ('true' === api_get_setting('display_teacher_in_courselist')) {
3589
                    $params['teachers'] = self::getTeachersFromCourse(
3590
                        $courseId,
3591
                        true
3592
                    );
3593
                }
3594
3595
                if ('true' === $showCustomIcon) {
3596
                    $params['thumbnails'] = $course_info['course_image'];
3597
                    $params['image'] = $course_info['course_image_large'];
3598
                }
3599
3600
                if (COURSE_VISIBILITY_CLOSED != $course_info['visibility']) {
3601
                    $params['notifications'] = $show_notification;
3602
                }
3603
3604
                $params['is_special_course'] = true;
3605
                $courseList[] = $params;
3606
            }
3607
        }
3608
3609
        return $courseList;
3610
    }
3611
3612
    /**
3613
     * Display courses (without special courses) as several HTML divs
3614
     * of course categories, as class userportal-catalog-item.
3615
     *
3616
     * @uses \displayCoursesInCategory() to display the courses themselves
3617
     *
3618
     * @param int  $user_id
3619
     * @param bool $load_dirs                        Whether to show the document quick-loader or not
3620
     * @param bool $useUserLanguageFilterIfAvailable
3621
     *
3622
     * @return array
3623
     */
3624
    public static function returnCourses(
3625
        $user_id,
3626
        $load_dirs = false,
3627
        $useUserLanguageFilterIfAvailable = true
3628
    ) {
3629
        $user_id = (int) $user_id;
3630
        if (empty($user_id)) {
3631
            $user_id = api_get_user_id();
3632
        }
3633
        // Step 1: We get all the categories of the user
3634
        $table = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
3635
        $sql = "SELECT * FROM $table
3636
                WHERE user_id = $user_id
3637
                ORDER BY sort ASC";
3638
3639
        $result = Database::query($sql);
3640
        $listItems = [
3641
            'in_category' => [],
3642
            'not_category' => [],
3643
        ];
3644
        $collapsable = api_get_configuration_value('allow_user_course_category_collapsable');
3645
        $stok = Security::get_token();
3646
        while ($row = Database::fetch_array($result)) {
3647
            // We simply display the title of the category.
3648
            $courseInCategory = self::returnCoursesCategories(
3649
                $row['id'],
3650
                $load_dirs,
3651
                $user_id,
3652
                $useUserLanguageFilterIfAvailable
3653
            );
3654
3655
            $collapsed = 0;
3656
            $collapsableLink = '';
3657
            if ($collapsable) {
3658
                $url = api_get_path(WEB_CODE_PATH).
3659
                    'auth/sort_my_courses.php?categoryid='.$row['id'].'&sec_token='.$stok.'&redirect=home';
3660
                $collapsed = isset($row['collapsed']) && $row['collapsed'] ? 1 : 0;
3661
                if (0 === $collapsed) {
3662
                    $collapsableLink = Display::url(
3663
                        '<i class="fa fa-folder-open"></i>',
3664
                        $url.'&action=set_collapsable&option=1'
3665
                    );
3666
                } else {
3667
                    $collapsableLink = Display::url(
3668
                        '<i class="fa fa-folder"></i>',
3669
                        $url.'&action=set_collapsable&option=0'
3670
                    );
3671
                }
3672
            }
3673
3674
            $params = [
3675
                'id_category' => $row['id'],
3676
                'title_category' => $row['title'],
3677
                'collapsed' => $collapsed,
3678
                'collapsable_link' => $collapsableLink,
3679
                'courses' => $courseInCategory,
3680
            ];
3681
            $listItems['in_category'][] = $params;
3682
        }
3683
3684
        // Step 2: We display the course without a user category.
3685
        $coursesNotCategory = self::returnCoursesCategories(
3686
            0,
3687
            $load_dirs,
3688
            $user_id,
3689
            $useUserLanguageFilterIfAvailable
3690
        );
3691
3692
        if ($coursesNotCategory) {
3693
            $listItems['not_category'] = $coursesNotCategory;
3694
        }
3695
3696
        return $listItems;
3697
    }
3698
3699
    /**
3700
     *  Display courses inside a category (without special courses) as HTML dics of
3701
     *  class userportal-course-item.
3702
     *
3703
     * @param int  $user_category_id                 User category id
3704
     * @param bool $load_dirs                        Whether to show the document quick-loader or not
3705
     * @param int  $user_id
3706
     * @param bool $useUserLanguageFilterIfAvailable
3707
     *
3708
     * @return array
3709
     */
3710
    public static function returnCoursesCategories(
3711
        $user_category_id,
3712
        $load_dirs = false,
3713
        $user_id = 0,
3714
        $useUserLanguageFilterIfAvailable = true
3715
    ) {
3716
        $user_id = $user_id ? (int) $user_id : api_get_user_id();
3717
        $user_category_id = (int) $user_category_id;
3718
3719
        // Table definitions
3720
        $TABLECOURS = Database::get_main_table(TABLE_MAIN_COURSE);
3721
        $TABLECOURSUSER = Database::get_main_table(TABLE_MAIN_COURSE_USER);
3722
        $TABLE_ACCESS_URL_REL_COURSE = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
3723
        $current_url_id = api_get_current_access_url_id();
3724
3725
        // Get course list auto-register
3726
        $special_course_list = self::get_special_course_list();
3727
        $without_special_courses = '';
3728
        if (!empty($special_course_list)) {
3729
            $without_special_courses = ' AND course.id NOT IN ("'.implode('","', $special_course_list).'")';
3730
        }
3731
3732
        $userCategoryCondition = " (course_rel_user.user_course_cat = $user_category_id) ";
3733
        if (empty($user_category_id)) {
3734
            $userCategoryCondition = ' (course_rel_user.user_course_cat = 0 OR course_rel_user.user_course_cat IS NULL) ';
3735
        }
3736
3737
        $languageCondition = '';
3738
        $onlyInUserLanguage = api_get_configuration_value('my_courses_show_courses_in_user_language_only');
3739
        if ($useUserLanguageFilterIfAvailable && $onlyInUserLanguage) {
3740
            $userInfo = api_get_user_info(api_get_user_id());
3741
            if (!empty($userInfo['language'])) {
3742
                $languageCondition = " AND course.course_language = '".$userInfo['language']."' ";
3743
            }
3744
        }
3745
3746
        $sql = "SELECT DISTINCT
3747
                    course.id,
3748
                    course_rel_user.status status,
3749
                    course.code as course_code,
3750
                    user_course_cat,
3751
                    course_rel_user.sort
3752
                FROM $TABLECOURS course
3753
                INNER JOIN $TABLECOURSUSER course_rel_user
3754
                ON (course.id = course_rel_user.c_id)
3755
                INNER JOIN $TABLE_ACCESS_URL_REL_COURSE url
3756
                ON (url.c_id = course.id)
3757
                WHERE
3758
                    course_rel_user.user_id = $user_id AND
3759
                    $userCategoryCondition
3760
                    $without_special_courses
3761
                    $languageCondition
3762
                ";
3763
        // If multiple URL access mode is enabled, only fetch courses
3764
        // corresponding to the current URL.
3765
        if (api_get_multiple_access_url() && -1 != $current_url_id) {
3766
            $sql .= " AND access_url_id = $current_url_id";
3767
        }
3768
        // Use user's classification for courses (if any).
3769
        $sql .= ' ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC';
3770
        $result = Database::query($sql);
3771
3772
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
3773
        // Browse through all courses.
3774
        $courseAdded = [];
3775
        $courseList = [];
3776
        while ($row = Database::fetch_array($result)) {
3777
            $course_info = api_get_course_info_by_id($row['id']);
3778
            if (empty($course_info)) {
3779
                continue;
3780
            }
3781
3782
            if (isset($course_info['visibility']) &&
3783
                COURSE_VISIBILITY_HIDDEN == $course_info['visibility']
3784
            ) {
3785
                continue;
3786
            }
3787
3788
            // Skip if already in list
3789
            if (in_array($course_info['real_id'], $courseAdded)) {
3790
                continue;
3791
            }
3792
            $course_info['id_session'] = null;
3793
            $course_info['status'] = $row['status'];
3794
            // For each course, get if there is any notification icon to show
3795
            // (something that would have changed since the user's last visit).
3796
            $showNotification = !api_get_configuration_value('hide_course_notification')
3797
                ? Display::show_notification($course_info)
3798
                : '';
3799
            $iconName = basename($course_info['course_image']);
3800
3801
            $params = [];
3802
            //Param (course_code) needed to get the student process
3803
            $params['course_code'] = $row['course_code'];
3804
            $params['code'] = $row['course_code'];
3805
3806
            if ('true' === $showCustomIcon && 'course.png' != $iconName) {
3807
                $params['thumbnails'] = $course_info['course_image'];
3808
                $params['image'] = $course_info['course_image_large'];
3809
            }
3810
3811
            $thumbnails = null;
3812
            $image = null;
3813
            if ('true' === $showCustomIcon && 'course.png' != $iconName) {
3814
                $thumbnails = $course_info['course_image'];
3815
                $image = $course_info['course_image_large'];
3816
            } else {
3817
                $image = Display::return_icon(
3818
                    'session_default.png',
3819
                    null,
3820
                    null,
3821
                    null,
3822
                    null,
3823
                    true
3824
                );
3825
            }
3826
3827
            $params['course_id'] = $course_info['real_id'];
3828
            $params['edit_actions'] = '';
3829
            $params['document'] = '';
3830
            if (api_is_platform_admin()) {
3831
                $params['edit_actions'] .= api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cid='.$course_info['real_id'];
3832
                if ($load_dirs) {
3833
                    $params['document'] = '<a id="document_preview_'.$course_info['real_id'].'_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3834
                               .Display::returnFontAwesomeIcon('folder-open').'</a>';
3835
                    $params['document'] .= Display::div(
3836
                        '',
3837
                        [
3838
                            'id' => 'document_result_'.$course_info['real_id'].'_0',
3839
                            'class' => 'document_preview_container',
3840
                        ]
3841
                    );
3842
                }
3843
            }
3844
            if ($load_dirs) {
3845
                $params['document'] = '<a id="document_preview_'.$course_info['real_id'].'_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3846
                    .Display::returnFontAwesomeIcon('folder-open').'</a>';
3847
                $params['document'] .= Display::div(
3848
                    '',
3849
                    [
3850
                        'id' => 'document_result_'.$course_info['real_id'].'_0',
3851
                        'class' => 'document_preview_container',
3852
                    ]
3853
                );
3854
            }
3855
3856
            $courseUrl = $course_info['course_public_url'].'?id_session=0';
3857
            $teachers = [];
3858
            if ('true' === api_get_setting('display_teacher_in_courselist')) {
3859
                $teachers = self::getTeachersFromCourse(
3860
                    $course_info['real_id'],
3861
                    true
3862
                );
3863
            }
3864
3865
            $params['status'] = $row['status'];
3866
            if ('true' === api_get_setting('display_coursecode_in_courselist')) {
3867
                $params['code_course'] = '('.$course_info['visual_code'].') ';
3868
            }
3869
3870
            $params['current_user_is_teacher'] = false;
3871
            /** @var array $teacher */
3872
            foreach ($teachers as $teacher) {
3873
                if ($teacher['id'] != $user_id) {
3874
                    continue;
3875
                }
3876
                $params['current_user_is_teacher'] = true;
3877
            }
3878
3879
            $params['visibility'] = $course_info['visibility'];
3880
            $params['link'] = $courseUrl;
3881
            $params['thumbnails'] = $thumbnails;
3882
            $params['image'] = $image;
3883
            $params['title'] = $course_info['title'];
3884
            $params['title_cut'] = $params['title'];
3885
            $params['category'] = $course_info['categoryName'];
3886
            $params['category_code'] = $course_info['categoryCode'];
3887
            $params['teachers'] = $teachers;
3888
            $params['real_id'] = $course_info['real_id'];
3889
3890
            if (COURSE_VISIBILITY_CLOSED != $course_info['visibility']) {
3891
                $params['notifications'] = $showNotification;
3892
            }
3893
            $courseAdded[] = $course_info['real_id'];
3894
            $courseList[] = $params;
3895
        }
3896
3897
        return $courseList;
3898
    }
3899
3900
    /**
3901
     * Retrieves the user defined course categories.
3902
     *
3903
     * @param int $userId
3904
     *
3905
     * @return array
3906
     */
3907
    public static function get_user_course_categories($userId = 0)
3908
    {
3909
        $userId = empty($userId) ? api_get_user_id() : (int) $userId;
3910
        $table = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
3911
        $sql = "SELECT * FROM $table
3912
                WHERE user_id = $userId
3913
                ORDER BY sort ASC
3914
                ";
3915
        $result = Database::query($sql);
3916
        $output = [];
3917
        while ($row = Database::fetch_array($result, 'ASSOC')) {
3918
            $output[$row['id']] = $row;
3919
        }
3920
3921
        return $output;
3922
    }
3923
3924
    /**
3925
     * Return an array the user_category id and title for the course $courseId for user $userId.
3926
     *
3927
     * @param $userId
3928
     * @param $courseId
3929
     *
3930
     * @return array
3931
     */
3932
    public static function getUserCourseCategoryForCourse($userId, $courseId)
3933
    {
3934
        $tblCourseRelUser = Database::get_main_table(TABLE_MAIN_COURSE_USER);
3935
        $tblUserCategory = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
3936
        $courseId = intval($courseId);
3937
        $userId = intval($userId);
3938
3939
        $sql = "SELECT user_course_cat, title
3940
                FROM $tblCourseRelUser cru
3941
                LEFT JOIN $tblUserCategory ucc
3942
                ON cru.user_course_cat = ucc.id
3943
                WHERE
3944
                    cru.user_id = $userId AND c_id = $courseId ";
3945
3946
        $res = Database::query($sql);
3947
3948
        $data = [];
3949
        if (Database::num_rows($res) > 0) {
3950
            $data = Database::fetch_assoc($res);
3951
        }
3952
3953
        return $data;
3954
    }
3955
3956
    /**
3957
     * Get the course id based on the original id and field name in the extra fields.
3958
     * Returns 0 if course was not found.
3959
     *
3960
     * @param string $value    Original course code
3961
     * @param string $variable Original field name
3962
     *
3963
     * @return array
3964
     */
3965
    public static function getCourseInfoFromOriginalId($value, $variable)
3966
    {
3967
        $extraFieldValue = new ExtraFieldValue('course');
3968
        $result = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
3969
            $variable,
3970
            $value
3971
        );
3972
3973
        if (!empty($result)) {
3974
            $courseInfo = api_get_course_info_by_id($result['item_id']);
3975
3976
            return $courseInfo;
3977
        }
3978
3979
        return [];
3980
    }
3981
3982
    /**
3983
     * Display code for one specific course a logged in user is subscribed to.
3984
     * Shows a link to the course, what's new icons...
3985
     *
3986
     * $my_course['d'] - course directory
3987
     * $my_course['i'] - course title
3988
     * $my_course['c'] - visual course code
3989
     * $my_course['k']  - system course code
3990
     *
3991
     * @param   array       Course details
3992
     * @param   int     Session ID
3993
     * @param   string      CSS class to apply to course entry
3994
     * @param   bool     Whether the session is supposedly accessible now
3995
     * (not in the case it has passed and is in invisible/unaccessible mode)
3996
     * @param bool      Whether to show the document quick-loader or not
3997
     *
3998
     * @return string The HTML to be printed for the course entry
3999
     *
4000
     * @version 1.0.3
4001
     *
4002
     * @todo refactor into different functions for database calls | logic | display
4003
     * @todo replace single-character $my_course['d'] indices
4004
     * @todo move code for what's new icons to a separate function to clear things up
4005
     * @todo add a parameter user_id so that it is possible to show the
4006
     * courselist of other users (=generalisation).
4007
     * This will prevent having to write a new function for this.
4008
     */
4009
    public static function get_logged_user_course_html(
4010
        $course,
4011
        $session_id = 0,
4012
        $class = 'courses',
4013
        $session_accessible = true,
4014
        $load_dirs = false
4015
    ) {
4016
        $now = date('Y-m-d h:i:s');
4017
        $user_id = api_get_user_id();
4018
        $course_info = api_get_course_info_by_id($course['real_id']);
4019
        $course_visibility = (int) $course_info['visibility'];
4020
4021
        if (COURSE_VISIBILITY_HIDDEN === $course_visibility) {
4022
            return '';
4023
        }
4024
4025
        $userInCourseStatus = self::getUserInCourseStatus(
4026
            $user_id,
4027
            $course_info['real_id']
4028
        );
4029
4030
        $course_info['status'] = empty($session_id) ? $userInCourseStatus : STUDENT;
4031
        $course_info['id_session'] = $session_id;
4032
4033
        $is_coach = api_is_coach($session_id, $course_info['real_id']);
4034
4035
        // Display course entry.
4036
        // Show a hyperlink to the course, unless the course is closed and user is not course admin.
4037
        $session_url = '';
4038
        $params = [];
4039
        $params['icon'] = Display::return_icon(
4040
            'session.png',
4041
            null,
4042
            [],
4043
            ICON_SIZE_LARGE,
4044
            null,
4045
            true
4046
        );
4047
        $params['real_id'] = $course_info['real_id'];
4048
4049
        // Display the "what's new" icons
4050
        $notifications = '';
4051
        if (
4052
            (COURSE_VISIBILITY_CLOSED != $course_visibility && COURSE_VISIBILITY_HIDDEN != $course_visibility) ||
4053
            !api_get_configuration_value('hide_course_notification')
4054
        ) {
4055
            $notifications .= Display::show_notification($course_info);
4056
        }
4057
4058
        if ($session_accessible) {
4059
            if (COURSE_VISIBILITY_CLOSED != $course_visibility ||
4060
                COURSEMANAGER == $userInCourseStatus
4061
            ) {
4062
                if (empty($course_info['id_session'])) {
4063
                    $course_info['id_session'] = 0;
4064
                }
4065
4066
                $sessionCourseAvailable = false;
4067
                $sessionCourseStatus = api_get_session_visibility($session_id, $course_info['real_id']);
4068
4069
                if (in_array(
4070
                    $sessionCourseStatus,
4071
                    [SESSION_VISIBLE_READ_ONLY, SESSION_VISIBLE, SESSION_AVAILABLE]
4072
                )) {
4073
                    $sessionCourseAvailable = true;
4074
                }
4075
4076
                if (COURSEMANAGER === $userInCourseStatus || $sessionCourseAvailable) {
4077
                    $session_url = $course_info['course_public_url'].'?id_session='.$course_info['id_session'];
4078
                    $session_title = '<a title="'.$course_info['name'].'" href="'.$session_url.'">'.
4079
                        $course_info['name'].'</a>'.$notifications;
4080
                } else {
4081
                    $session_title = $course_info['name'];
4082
                }
4083
            } else {
4084
                $session_title =
4085
                    $course_info['name'].' '.
4086
                    Display::tag('span', get_lang('(the course is currently closed)'), ['class' => 'item_closed']);
4087
            }
4088
        } else {
4089
            $session_title = $course_info['name'];
4090
        }
4091
4092
        $thumbnails = null;
4093
        $image = null;
4094
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
4095
        $iconName = basename($course_info['course_image']);
4096
4097
        if ('true' === $showCustomIcon && 'course.png' != $iconName) {
4098
            $thumbnails = $course_info['course_image'];
4099
            $image = $course_info['course_image_large'];
4100
        } else {
4101
            $image = Display::return_icon(
4102
                'session_default.png',
4103
                null,
4104
                null,
4105
                null,
4106
                null,
4107
                true
4108
            );
4109
        }
4110
        $params['thumbnails'] = $thumbnails;
4111
        $params['image'] = $image;
4112
        $params['html_image'] = '';
4113
        if (!empty($thumbnails)) {
4114
            $params['html_image'] = Display::img($thumbnails, $course_info['name'], ['class' => 'img-responsive']);
4115
        } else {
4116
            $params['html_image'] = Display::return_icon('session.png', $course_info['name'], ['class' => 'img-responsive'], ICON_SIZE_LARGE, $course_info['name']);
4117
        }
4118
        $params['link'] = $session_url;
4119
4120
        $courseController = new CoursesController();
4121
4122
        $entityManager = Database::getManager();
4123
        /** @var SequenceResourceRepository $repo */
4124
        $repo = $entityManager->getRepository('ChamiloCoreBundle:SequenceResource');
4125
        /*$sequences = $repo->getRequirementsAndDependenciesWithinSequences(
4126
            $course_info['real_id'],
4127
            SequenceResource::COURSE_TYPE
4128
        );*/
4129
4130
        $sequences = $repo->getRequirements($course_info['real_id'], SequenceResource::COURSE_TYPE);
4131
        $sequenceList = $repo->checkRequirementsForUser($sequences, SequenceResource::COURSE_TYPE, $user_id);
4132
        $completed = $repo->checkSequenceAreCompleted($sequenceList);
4133
4134
        //var_dump($course_info['real_id'], $completed);
4135
        $params['completed'] = $completed;
4136
        $params['requirements'] = '';
4137
4138
        if ($sequences && false === $completed) {
4139
            $hasRequirements = false;
4140
            foreach ($sequences as $sequence) {
4141
                if (!empty($sequence['requirements'])) {
4142
                    $hasRequirements = true;
4143
                    break;
4144
                }
4145
            }
4146
            if ($hasRequirements) {
4147
                $params['requirements'] = $courseController->getRequirements(
4148
                    $course_info['real_id'],
4149
                    SequenceResource::COURSE_TYPE,
4150
                    false,
4151
                    false
4152
                );
4153
            }
4154
        }
4155
4156
        $params['title'] = $session_title;
4157
        $params['name'] = $course_info['name'];
4158
        $params['edit_actions'] = '';
4159
        $params['document'] = '';
4160
        $params['category'] = $course_info['categoryName'];
4161
4162
        if (COURSE_VISIBILITY_CLOSED != $course_visibility &&
4163
            COURSE_VISIBILITY_HIDDEN != $course_visibility
4164
        ) {
4165
            if (api_is_platform_admin()) {
4166
                $params['edit_actions'] .= api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cid='.$course_info['real_id'];
4167
                if ($load_dirs) {
4168
                    $params['document'] .= '<a
4169
                        id="document_preview_'.$course_info['real_id'].'_'.$course_info['id_session'].'"
4170
                        class="document_preview btn btn-default btn-sm"
4171
                        href="javascript:void(0);">'.
4172
                        Display::returnFontAwesomeIcon('folder-open').'</a>';
4173
                    $params['document'] .= Display::div('', [
4174
                        'id' => 'document_result_'.$course_info['real_id'].'_'.$course_info['id_session'],
4175
                        'class' => 'document_preview_container',
4176
                    ]);
4177
                }
4178
            }
4179
        }
4180
        if ('true' === api_get_setting('display_teacher_in_courselist')) {
4181
            $teacher_list = self::getTeachersFromCourse(
4182
                $course_info['real_id'],
4183
                true
4184
            );
4185
            $course_coachs = self::get_coachs_from_course(
4186
                $course_info['id_session'],
4187
                $course_info['real_id']
4188
            );
4189
            $params['teachers'] = $teacher_list;
4190
4191
            if ((STUDENT == $course_info['status'] && !empty($course_info['id_session'])) ||
4192
                ($is_coach && COURSEMANAGER != $course_info['status'])
4193
            ) {
4194
                $params['coaches'] = $course_coachs;
4195
            }
4196
        }
4197
        $special = isset($course['special_course']) ? true : false;
4198
        $params['title'] = $session_title;
4199
        $params['special'] = $special;
4200
        if ('true' === api_get_setting('display_coursecode_in_courselist')) {
4201
            $params['visual_code'] = '('.$course_info['visual_code'].')';
4202
        }
4203
        $params['extra'] = '';
4204
        $html = $params;
4205
4206
        $session_category_id = null;
4207
        if (1) {
4208
            $session = '';
4209
            $active = false;
4210
            if (!empty($course_info['id_session'])) {
4211
                $session = api_get_session_info($course_info['id_session']);
4212
                $sessionCoachName = '';
4213
                if (!empty($session['id_coach'])) {
4214
                    $coachInfo = api_get_user_info($session['id_coach']);
4215
                    $sessionCoachName = $coachInfo['complete_name'];
4216
                }
4217
4218
                $session_category_id = self::get_session_category_id_by_session_id($course_info['id_session']);
4219
4220
                if (
4221
                    '0000-00-00 00:00:00' === $session['access_start_date'] || empty($session['access_start_date']) ||
4222
                    '0000-00-00' === $session['access_start_date']
4223
                ) {
4224
                    $session['dates'] = '';
4225
                    if ('true' === api_get_setting('show_session_coach')) {
4226
                        $session['coach'] = get_lang('General coach').': '.$sessionCoachName;
4227
                    }
4228
                    $active = true;
4229
                } else {
4230
                    $session['dates'] = ' - '.
4231
                        get_lang('From').' '.$session['access_start_date'].' '.
4232
                        get_lang('To').' '.$session['access_end_date'];
4233
                    if ('true' === api_get_setting('show_session_coach')) {
4234
                        $session['coach'] = get_lang('General coach').': '.$sessionCoachName;
4235
                    }
4236
                    $date_start = $session['access_start_date'];
4237
                    $date_end = $session['access_end_date'];
4238
                    $active = !$date_end ? ($date_start <= $now) : ($date_start <= $now && $date_end >= $now);
4239
                }
4240
            }
4241
            $user_course_category = '';
4242
            if (isset($course_info['user_course_cat'])) {
4243
                $user_course_category = $course_info['user_course_cat'];
4244
            }
4245
            $output = [
4246
                $user_course_category,
4247
                $html,
4248
                $course_info['id_session'],
4249
                $session,
4250
                'active' => $active,
4251
                'session_category_id' => $session_category_id,
4252
            ];
4253
4254
            if (Skill::isAllowed($user_id, false)) {
4255
                $em = Database::getManager();
4256
                $objUser = api_get_user_entity($user_id);
4257
                /** @var Course $objCourse */
4258
                $objCourse = $em->find('ChamiloCoreBundle:Course', $course['real_id']);
4259
                $objSession = $em->find('ChamiloCoreBundle:Session', $session_id);
4260
4261
                $skill = $em->getRepository('ChamiloCoreBundle:Skill')->getLastByUser($objUser, $objCourse, $objSession);
4262
4263
                $output['skill'] = null;
4264
                if ($skill) {
4265
                    $output['skill']['name'] = $skill->getName();
4266
                    $output['skill']['icon'] = $skill->getIcon();
4267
                }
4268
            }
4269
        } else {
4270
            $output = [$course_info['user_course_cat'], $html];
4271
        }
4272
4273
        return $output;
4274
    }
4275
4276
    /**
4277
     * @param string $source_course_code
4278
     * @param int    $source_session_id
4279
     * @param string $destination_course_code
4280
     * @param int    $destination_session_id
4281
     * @param array  $params
4282
     *
4283
     * @return bool
4284
     */
4285
    public static function copy_course(
4286
        $source_course_code,
4287
        $source_session_id,
4288
        $destination_course_code,
4289
        $destination_session_id,
4290
        $params = []
4291
    ) {
4292
        $course_info = api_get_course_info($source_course_code);
4293
4294
        if (!empty($course_info)) {
4295
            $cb = new CourseBuilder('', $course_info);
4296
            $course = $cb->build($source_session_id, $source_course_code, true);
4297
            $course_restorer = new CourseRestorer($course);
4298
            $course_restorer->skip_content = $params;
4299
            $course_restorer->restore(
4300
                $destination_course_code,
4301
                $destination_session_id,
4302
                true,
4303
                true
4304
            );
4305
4306
            return true;
4307
        }
4308
4309
        return false;
4310
    }
4311
4312
    /**
4313
     * A simpler version of the copy_course, the function creates an empty course with an autogenerated course code.
4314
     *
4315
     * @param string $new_title new course title
4316
     * @param string source course code
4317
     * @param int source session id
4318
     * @param int destination session id
4319
     * @param array $params
4320
     *
4321
     * @return array
4322
     */
4323
    public static function copy_course_simple(
4324
        $new_title,
4325
        $source_course_code,
4326
        $source_session_id = 0,
4327
        $destination_session_id = 0,
4328
        $params = []
4329
    ) {
4330
        $source_course_info = api_get_course_info($source_course_code);
4331
        if (!empty($source_course_info)) {
4332
            $new_course_code = self::generate_nice_next_course_code($source_course_code);
4333
            if ($new_course_code) {
4334
                $new_course_info = self::create_course(
4335
                    $new_title,
4336
                    $new_course_code,
4337
                    false
4338
                );
4339
                if (!empty($new_course_info['code'])) {
4340
                    $result = self::copy_course(
4341
                        $source_course_code,
4342
                        $source_session_id,
4343
                        $new_course_info['code'],
4344
                        $destination_session_id,
4345
                        $params
4346
                    );
4347
                    if ($result) {
4348
                        return $new_course_info;
4349
                    }
4350
                }
4351
            }
4352
        }
4353
4354
        return false;
4355
    }
4356
4357
    /**
4358
     * Creates a new course code based in a given code.
4359
     *
4360
     * @param string    wanted code
4361
     * <code>    $wanted_code = 'curse' if there are in the DB codes like curse1 curse2 the function will return: course3</code>
4362
     * if the course code doest not exist in the DB the same course code will be returned
4363
     *
4364
     * @return string wanted unused code
4365
     */
4366
    public static function generate_nice_next_course_code($wanted_code)
4367
    {
4368
        $course_code_ok = !self::course_code_exists($wanted_code);
4369
        if (!$course_code_ok) {
4370
            $wanted_code = self::generate_course_code($wanted_code);
4371
            $table = Database::get_main_table(TABLE_MAIN_COURSE);
4372
            $wanted_code = Database::escape_string($wanted_code);
4373
            $sql = "SELECT count(id) as count
4374
                    FROM $table
4375
                    WHERE code LIKE '$wanted_code%'";
4376
            $result = Database::query($sql);
4377
            if (Database::num_rows($result) > 0) {
4378
                $row = Database::fetch_array($result);
4379
                $count = $row['count'] + 1;
4380
                $wanted_code = $wanted_code.'_'.$count;
4381
                $result = api_get_course_info($wanted_code);
4382
                if (empty($result)) {
4383
                    return $wanted_code;
4384
                }
4385
            }
4386
4387
            return false;
4388
        }
4389
4390
        return $wanted_code;
4391
    }
4392
4393
    /**
4394
     * Gets the status of the users agreement in a course course-session.
4395
     *
4396
     * @param int    $user_id
4397
     * @param string $course_code
4398
     * @param int    $session_id
4399
     *
4400
     * @return bool
4401
     */
4402
    public static function is_user_accepted_legal($user_id, $course_code, $session_id = 0)
4403
    {
4404
        $user_id = intval($user_id);
4405
        $course_code = Database::escape_string($course_code);
4406
        $session_id = intval($session_id);
4407
4408
        $courseInfo = api_get_course_info($course_code);
4409
        $courseId = $courseInfo['real_id'];
4410
4411
        // Course legal
4412
        $enabled = api_get_plugin_setting('courselegal', 'tool_enable');
4413
4414
        if ('true' == $enabled) {
4415
            require_once api_get_path(SYS_PLUGIN_PATH).'courselegal/config.php';
4416
            $plugin = CourseLegalPlugin::create();
4417
4418
            return $plugin->isUserAcceptedLegal($user_id, $course_code, $session_id);
4419
        }
4420
4421
        if (empty($session_id)) {
4422
            $table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4423
            $sql = "SELECT legal_agreement FROM $table
4424
                    WHERE user_id = $user_id AND c_id = $courseId ";
4425
            $result = Database::query($sql);
4426
            if (Database::num_rows($result) > 0) {
4427
                $result = Database::fetch_array($result);
4428
                if (1 == $result['legal_agreement']) {
4429
                    return true;
4430
                }
4431
            }
4432
4433
            return false;
4434
        } else {
4435
            $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4436
            $sql = "SELECT legal_agreement FROM $table
4437
                    WHERE user_id = $user_id AND c_id = $courseId AND session_id = $session_id";
4438
            $result = Database::query($sql);
4439
            if (Database::num_rows($result) > 0) {
4440
                $result = Database::fetch_array($result);
4441
                if (1 == $result['legal_agreement']) {
4442
                    return true;
4443
                }
4444
            }
4445
4446
            return false;
4447
        }
4448
    }
4449
4450
    /**
4451
     * Saves the user-course legal agreement.
4452
     *
4453
     * @param   int user id
4454
     * @param   string course code
4455
     * @param   int session id
4456
     *
4457
     * @return mixed
4458
     */
4459
    public static function save_user_legal($user_id, $course_code, $session_id = null)
4460
    {
4461
        // Course plugin legal
4462
        $enabled = api_get_plugin_setting('courselegal', 'tool_enable');
4463
        if ('true' == $enabled) {
4464
            require_once api_get_path(SYS_PLUGIN_PATH).'courselegal/config.php';
4465
            $plugin = CourseLegalPlugin::create();
4466
4467
            return $plugin->saveUserLegal($user_id, $course_code, $session_id);
4468
        }
4469
4470
        $user_id = intval($user_id);
4471
        $course_code = Database::escape_string($course_code);
4472
        $session_id = intval($session_id);
4473
        $courseInfo = api_get_course_info($course_code);
4474
        $courseId = $courseInfo['real_id'];
4475
4476
        if (empty($session_id)) {
4477
            $table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4478
            $sql = "UPDATE $table SET legal_agreement = '1'
4479
                    WHERE user_id = $user_id AND c_id  = $courseId ";
4480
            Database::query($sql);
4481
        } else {
4482
            $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4483
            $sql = "UPDATE  $table SET legal_agreement = '1'
4484
                    WHERE user_id = $user_id AND c_id = $courseId AND session_id = $session_id";
4485
            Database::query($sql);
4486
        }
4487
    }
4488
4489
    /**
4490
     * @param int $user_id
4491
     * @param int $course_id
4492
     * @param int $session_id
4493
     * @param int $url_id
4494
     *
4495
     * @return bool
4496
     */
4497
    public static function get_user_course_vote($user_id, $course_id, $session_id = 0, $url_id = 0)
4498
    {
4499
        $table_user_course_vote = Database::get_main_table(TABLE_MAIN_USER_REL_COURSE_VOTE);
4500
        $session_id = !isset($session_id) ? api_get_session_id() : intval($session_id);
4501
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4502
        $user_id = intval($user_id);
4503
4504
        if (empty($user_id)) {
4505
            return false;
4506
        }
4507
4508
        $params = [
4509
            'user_id' => $user_id,
4510
            'c_id' => $course_id,
4511
            'session_id' => $session_id,
4512
            'url_id' => $url_id,
4513
        ];
4514
4515
        $result = Database::select(
4516
            'vote',
4517
            $table_user_course_vote,
4518
            [
4519
                'where' => [
4520
                    'user_id = ? AND c_id = ? AND session_id = ? AND url_id = ?' => $params,
4521
                ],
4522
            ],
4523
            'first'
4524
        );
4525
        if (!empty($result)) {
4526
            return $result['vote'];
4527
        }
4528
4529
        return false;
4530
    }
4531
4532
    /**
4533
     * @param int $course_id
4534
     * @param int $session_id
4535
     * @param int $url_id
4536
     *
4537
     * @return array
4538
     */
4539
    public static function get_course_ranking(
4540
        $course_id,
4541
        $session_id = 0,
4542
        $url_id = 0
4543
    ) {
4544
        $table_course_ranking = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
4545
4546
        $session_id = empty($session_id) ? api_get_session_id() : intval($session_id);
4547
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4548
        $now = api_get_utc_datetime();
4549
4550
        $params = [
4551
            'c_id' => $course_id,
4552
            'session_id' => $session_id,
4553
            'url_id' => $url_id,
4554
            'creation_date' => $now,
4555
        ];
4556
4557
        $result = Database::select(
4558
            'c_id, accesses, total_score, users',
4559
            $table_course_ranking,
4560
            ['where' => ['c_id = ? AND session_id = ? AND url_id = ?' => $params]],
4561
            'first'
4562
        );
4563
4564
        $point_average_in_percentage = 0;
4565
        $point_average_in_star = 0;
4566
        $users_who_voted = 0;
4567
4568
        if (!empty($result['users'])) {
4569
            $users_who_voted = $result['users'];
4570
            $point_average_in_percentage = round($result['total_score'] / $result['users'] * 100 / 5, 2);
4571
            $point_average_in_star = round($result['total_score'] / $result['users'], 1);
4572
        }
4573
4574
        $result['user_vote'] = false;
4575
        if (!api_is_anonymous()) {
4576
            $result['user_vote'] = self::get_user_course_vote(api_get_user_id(), $course_id, $session_id, $url_id);
4577
        }
4578
4579
        $result['point_average'] = $point_average_in_percentage;
4580
        $result['point_average_star'] = $point_average_in_star;
4581
        $result['users_who_voted'] = $users_who_voted;
4582
4583
        return $result;
4584
    }
4585
4586
    /**
4587
     * Updates the course ranking.
4588
     *
4589
     * @param int   course id
4590
     * @param int $session_id
4591
     * @param int    url id
4592
     * @param $points_to_add
4593
     * @param bool $add_access
4594
     * @param bool $add_user
4595
     *
4596
     * @return array
4597
     */
4598
    public static function update_course_ranking(
4599
        $course_id = 0,
4600
        $session_id = 0,
4601
        $url_id = 0,
4602
        $points_to_add = null,
4603
        $add_access = true,
4604
        $add_user = true
4605
    ) {
4606
        // Course catalog stats modifications see #4191
4607
        $table_course_ranking = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
4608
        $now = api_get_utc_datetime();
4609
        $course_id = empty($course_id) ? api_get_course_int_id() : intval($course_id);
4610
        $session_id = empty($session_id) ? api_get_session_id() : intval($session_id);
4611
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4612
4613
        $params = [
4614
            'c_id' => $course_id,
4615
            'session_id' => $session_id,
4616
            'url_id' => $url_id,
4617
            'creation_date' => $now,
4618
            'total_score' => 0,
4619
            'users' => 0,
4620
        ];
4621
4622
        $result = Database::select(
4623
            'id, accesses, total_score, users',
4624
            $table_course_ranking,
4625
            ['where' => ['c_id = ? AND session_id = ? AND url_id = ?' => $params]],
4626
            'first'
4627
        );
4628
4629
        // Problem here every time we load the courses/XXXX/index.php course home page we update the access
4630
        if (empty($result)) {
4631
            if ($add_access) {
4632
                $params['accesses'] = 1;
4633
            }
4634
            //The votes and users are empty
4635
            if (isset($points_to_add) && !empty($points_to_add)) {
4636
                $params['total_score'] = intval($points_to_add);
4637
            }
4638
            if ($add_user) {
4639
                $params['users'] = 1;
4640
            }
4641
            $result = Database::insert($table_course_ranking, $params);
4642
        } else {
4643
            $my_params = [];
4644
4645
            if ($add_access) {
4646
                $my_params['accesses'] = intval($result['accesses']) + 1;
4647
            }
4648
            if (isset($points_to_add) && !empty($points_to_add)) {
4649
                $my_params['total_score'] = $result['total_score'] + $points_to_add;
4650
            }
4651
            if ($add_user) {
4652
                $my_params['users'] = $result['users'] + 1;
4653
            }
4654
4655
            if (!empty($my_params)) {
4656
                $result = Database::update(
4657
                    $table_course_ranking,
4658
                    $my_params,
4659
                    ['c_id = ? AND session_id = ? AND url_id = ?' => $params]
4660
                );
4661
            }
4662
        }
4663
4664
        return $result;
4665
    }
4666
4667
    /**
4668
     * Add user vote to a course.
4669
     *
4670
     * @param   int user id
4671
     * @param   int vote [1..5]
4672
     * @param   int course id
4673
     * @param   int session id
4674
     * @param   int url id (access_url_id)
4675
     *
4676
     * @return false|string 'added', 'updated' or 'nothing'
4677
     */
4678
    public static function add_course_vote(
4679
        $user_id,
4680
        $vote,
4681
        $course_id,
4682
        $session_id = 0,
4683
        $url_id = 0
4684
    ) {
4685
        $table_user_course_vote = Database::get_main_table(TABLE_MAIN_USER_REL_COURSE_VOTE);
4686
        $course_id = empty($course_id) ? api_get_course_int_id() : intval($course_id);
4687
4688
        if (empty($course_id) || empty($user_id)) {
4689
            return false;
4690
        }
4691
4692
        if (!in_array($vote, [1, 2, 3, 4, 5])) {
4693
            return false;
4694
        }
4695
4696
        $session_id = empty($session_id) ? api_get_session_id() : intval($session_id);
4697
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4698
        $vote = intval($vote);
4699
4700
        $params = [
4701
            'user_id' => intval($user_id),
4702
            'c_id' => $course_id,
4703
            'session_id' => $session_id,
4704
            'url_id' => $url_id,
4705
            'vote' => $vote,
4706
        ];
4707
4708
        $action_done = 'nothing';
4709
        $result = Database::select(
4710
            'id, vote',
4711
            $table_user_course_vote,
4712
            ['where' => ['user_id = ? AND c_id = ? AND session_id = ? AND url_id = ?' => $params]],
4713
            'first'
4714
        );
4715
4716
        if (empty($result)) {
4717
            Database::insert($table_user_course_vote, $params);
4718
            $points_to_add = $vote;
4719
            $add_user = true;
4720
            $action_done = 'added';
4721
        } else {
4722
            $my_params = ['vote' => $vote];
4723
            $points_to_add = $vote - $result['vote'];
4724
            $add_user = false;
4725
4726
            Database::update(
4727
                $table_user_course_vote,
4728
                $my_params,
4729
                ['user_id = ? AND c_id = ? AND session_id = ? AND url_id = ?' => $params]
4730
            );
4731
            $action_done = 'updated';
4732
        }
4733
4734
        // Current points
4735
        if (!empty($points_to_add)) {
4736
            self::update_course_ranking(
4737
                $course_id,
4738
                $session_id,
4739
                $url_id,
4740
                $points_to_add,
4741
                false,
4742
                $add_user
4743
            );
4744
        }
4745
4746
        return $action_done;
4747
    }
4748
4749
    /**
4750
     * Remove course ranking + user votes.
4751
     *
4752
     * @param int $course_id
4753
     * @param int $session_id
4754
     * @param int $url_id
4755
     */
4756
    public static function remove_course_ranking($course_id, $session_id, $url_id = null)
4757
    {
4758
        $table_course_ranking = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
4759
        $table_user_course_vote = Database::get_main_table(TABLE_MAIN_USER_REL_COURSE_VOTE);
4760
4761
        if (!empty($course_id) && isset($session_id)) {
4762
            $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4763
            $params = [
4764
                'c_id' => $course_id,
4765
                'session_id' => $session_id,
4766
                'url_id' => $url_id,
4767
            ];
4768
            Database::delete($table_course_ranking, ['c_id = ? AND session_id = ? AND url_id = ?' => $params]);
4769
            Database::delete($table_user_course_vote, ['c_id = ? AND session_id = ? AND url_id = ?' => $params]);
4770
        }
4771
    }
4772
4773
    /**
4774
     * Returns an array with the hottest courses.
4775
     *
4776
     * @param int $days  number of days
4777
     * @param int $limit number of hottest courses
4778
     *
4779
     * @return array
4780
     */
4781
    public static function return_hot_courses($days = 30, $limit = 6)
4782
    {
4783
        if (api_is_invitee()) {
4784
            return [];
4785
        }
4786
4787
        $limit = (int) $limit;
4788
        $userId = api_get_user_id();
4789
4790
        // Getting my courses
4791
        $my_course_list = self::get_courses_list_by_user_id($userId);
4792
4793
        $codeList = [];
4794
        foreach ($my_course_list as $course) {
4795
            $codeList[$course['real_id']] = $course['real_id'];
4796
        }
4797
4798
        if (api_is_drh()) {
4799
            $courses = self::get_courses_followed_by_drh($userId);
4800
            foreach ($courses as $course) {
4801
                $codeList[$course['real_id']] = $course['real_id'];
4802
            }
4803
        }
4804
4805
        $table_course_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
4806
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
4807
        $table_course_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
4808
        $urlId = api_get_current_access_url_id();
4809
        //$table_course_access table uses the now() and interval ...
4810
        $now = api_get_utc_datetime();
4811
        $sql = "SELECT COUNT(course_access_id) course_count, a.c_id, visibility
4812
                FROM $table_course c
4813
                INNER JOIN $table_course_access a
4814
                ON (c.id = a.c_id)
4815
                INNER JOIN $table_course_url u
4816
                ON u.c_id = c.id
4817
                WHERE
4818
                    u.access_url_id = $urlId AND
4819
                    login_course_date <= '$now' AND
4820
                    login_course_date > DATE_SUB('$now', INTERVAL $days DAY) AND
4821
                    visibility <> ".COURSE_VISIBILITY_CLOSED." AND
4822
                    visibility <> ".COURSE_VISIBILITY_HIDDEN."
4823
                GROUP BY a.c_id
4824
                ORDER BY course_count DESC
4825
                LIMIT $limit
4826
            ";
4827
4828
        $result = Database::query($sql);
4829
        $courses = [];
4830
        if (Database::num_rows($result)) {
4831
            $courses = Database::store_result($result, 'ASSOC');
4832
            $courses = self::processHotCourseItem($courses, $codeList);
4833
        }
4834
4835
        return $courses;
4836
    }
4837
4838
    /**
4839
     * @param array $courses
4840
     * @param array $codeList
4841
     *
4842
     * @return mixed
4843
     */
4844
    public static function processHotCourseItem($courses, $codeList = [])
4845
    {
4846
        $hotCourses = [];
4847
        $ajax_url = api_get_path(WEB_AJAX_PATH).'course.ajax.php?a=add_course_vote';
4848
        $stok = Security::get_existing_token();
4849
        $user_id = api_get_user_id();
4850
4851
        foreach ($courses as $courseId) {
4852
            $course_info = api_get_course_info_by_id($courseId['c_id']);
4853
            $courseCode = $course_info['code'];
4854
            $categoryCode = !empty($course_info['categoryCode']) ? $course_info['categoryCode'] : "";
4855
            $my_course = $course_info;
4856
            $my_course['go_to_course_button'] = '';
4857
            $my_course['register_button'] = '';
4858
4859
            $access_link = self::get_access_link_by_user(
4860
                api_get_user_id(),
4861
                $course_info,
4862
                $codeList
4863
            );
4864
4865
            $userRegisteredInCourse = self::is_user_subscribed_in_course($user_id, $course_info['code']);
4866
            $userRegisteredInCourseAsTeacher = self::is_course_teacher($user_id, $course_info['code']);
4867
            $userRegistered = $userRegisteredInCourse && $userRegisteredInCourseAsTeacher;
4868
            $my_course['is_course_student'] = $userRegisteredInCourse;
4869
            $my_course['is_course_teacher'] = $userRegisteredInCourseAsTeacher;
4870
            $my_course['is_registered'] = $userRegistered;
4871
            $my_course['title_cut'] = cut($course_info['title'], 45);
4872
4873
            // Course visibility
4874
            if ($access_link && in_array('register', $access_link)) {
4875
                $my_course['register_button'] = Display::url(
4876
                    get_lang('Subscribe').' '.
4877
                    Display::returnFontAwesomeIcon('sign-in'),
4878
                    api_get_path(WEB_COURSE_PATH).$course_info['path'].
4879
                     '/index.php?action=subscribe&sec_token='.$stok,
4880
                    [
4881
                        'class' => 'btn btn-success btn-sm',
4882
                        'title' => get_lang('Subscribe'),
4883
                        'aria-label' => get_lang('Subscribe'),
4884
                    ]
4885
                );
4886
            }
4887
4888
            if ($access_link && in_array('enter', $access_link) ||
4889
                COURSE_VISIBILITY_OPEN_WORLD == $course_info['visibility']
4890
            ) {
4891
                $my_course['go_to_course_button'] = Display::url(
4892
                    get_lang('Go to the course').' '.
4893
                    Display::returnFontAwesomeIcon('share'),
4894
                    api_get_path(WEB_COURSE_PATH).$course_info['path'].'/index.php',
4895
                    [
4896
                        'class' => 'btn btn-default btn-sm',
4897
                        'title' => get_lang('Go to the course'),
4898
                        'aria-label' => get_lang('Go to the course'),
4899
                    ]
4900
                );
4901
            }
4902
4903
            if ($access_link && in_array('unsubscribe', $access_link)) {
4904
                $my_course['unsubscribe_button'] = Display::url(
4905
                    get_lang('Unsubscribe').' '.
4906
                    Display::returnFontAwesomeIcon('sign-out'),
4907
                    api_get_path(WEB_CODE_PATH).'auth/courses.php?action=unsubscribe&unsubscribe='.$courseCode
4908
                    .'&sec_token='.$stok.'&category_code='.$categoryCode,
4909
                    [
4910
                        'class' => 'btn btn-danger btn-sm',
4911
                        'title' => get_lang('Unsubscribe'),
4912
                        'aria-label' => get_lang('Unsubscribe'),
4913
                    ]
4914
                );
4915
            }
4916
4917
            // start buycourse validation
4918
            // display the course price and buy button if the buycourses plugin is enabled and this course is configured
4919
            $plugin = BuyCoursesPlugin::create();
4920
            $isThisCourseInSale = $plugin->buyCoursesForGridCatalogValidator(
4921
                $course_info['real_id'],
4922
                BuyCoursesPlugin::PRODUCT_TYPE_COURSE
4923
            );
4924
            if ($isThisCourseInSale) {
4925
                // set the price label
4926
                $my_course['price'] = $isThisCourseInSale['html'];
4927
                // set the Buy button instead register.
4928
                if ($isThisCourseInSale['verificator'] && !empty($my_course['register_button'])) {
4929
                    $my_course['register_button'] = $plugin->returnBuyCourseButton(
4930
                        $course_info['real_id'],
4931
                        BuyCoursesPlugin::PRODUCT_TYPE_COURSE
4932
                    );
4933
                }
4934
            }
4935
            // end buycourse validation
4936
4937
            // Description
4938
            $my_course['description_button'] = self::returnDescriptionButton($course_info);
4939
            $my_course['teachers'] = self::getTeachersFromCourse($course_info['real_id'], true);
4940
            $point_info = self::get_course_ranking($course_info['real_id'], 0);
4941
            $my_course['rating_html'] = '';
4942
            if (false === api_get_configuration_value('hide_course_rating')) {
4943
                $my_course['rating_html'] = Display::return_rating_system(
4944
                    'star_'.$course_info['real_id'],
4945
                    $ajax_url.'&course_id='.$course_info['real_id'],
4946
                    $point_info
4947
                );
4948
            }
4949
            $hotCourses[] = $my_course;
4950
        }
4951
4952
        return $hotCourses;
4953
    }
4954
4955
    public function totalSubscribedUsersInCourses($urlId)
4956
    {
4957
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
4958
        $table_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
4959
        $courseUsers = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4960
4961
        $urlId = (int) $urlId;
4962
4963
        $sql = "SELECT count(cu.user_id) count
4964
                FROM $courseUsers cu
4965
                INNER JOIN $table_course_rel_access_url u
4966
                ON cu.c_id = u.c_id
4967
                WHERE
4968
                    relation_type <> ".COURSE_RELATION_TYPE_RRHH." AND
4969
                    u.access_url_id = $urlId AND
4970
                    visibility <> ".COURSE_VISIBILITY_CLOSED." AND
4971
                    visibility <> ".COURSE_VISIBILITY_HIDDEN."
4972
                     ";
4973
4974
        $res = Database::query($sql);
4975
        $row = Database::fetch_array($res);
4976
4977
        return $row['count'];
4978
    }
4979
4980
    /**
4981
     * Get courses count.
4982
     *
4983
     * @param int $access_url_id Access URL ID (optional)
4984
     * @param int $visibility
4985
     *
4986
     * @return int Number of courses
4987
     */
4988
    public static function count_courses($access_url_id = null, $visibility = null)
4989
    {
4990
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
4991
        $table_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
4992
        $sql = "SELECT count(c.id) FROM $table_course c";
4993
        if (!empty($access_url_id) && $access_url_id == intval($access_url_id)) {
4994
            $sql .= ", $table_course_rel_access_url u
4995
                    WHERE c.id = u.c_id AND u.access_url_id = $access_url_id";
4996
            if (!empty($visibility)) {
4997
                $visibility = intval($visibility);
4998
                $sql .= " AND visibility = $visibility ";
4999
            }
5000
        } else {
5001
            if (!empty($visibility)) {
5002
                $visibility = intval($visibility);
5003
                $sql .= " WHERE visibility = $visibility ";
5004
            }
5005
        }
5006
5007
        $res = Database::query($sql);
5008
        $row = Database::fetch_row($res);
5009
5010
        return $row[0];
5011
    }
5012
5013
    /**
5014
     * Get active courses count.
5015
     * Active = all courses except the ones with hidden visibility.
5016
     *
5017
     * @param int $urlId Access URL ID (optional)
5018
     *
5019
     * @return int Number of courses
5020
     */
5021
    public static function countActiveCourses($urlId = null)
5022
    {
5023
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
5024
        $table_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
5025
        $sql = "SELECT count(c.id) FROM $table_course c";
5026
        if (!empty($urlId)) {
5027
            $urlId = (int) $urlId;
5028
            $sql .= ", $table_course_rel_access_url u
5029
                    WHERE
5030
                        c.id = u.c_id AND
5031
                        u.access_url_id = $urlId AND
5032
                        visibility <> ".COURSE_VISIBILITY_HIDDEN;
5033
        } else {
5034
            $sql .= " WHERE visibility <> ".COURSE_VISIBILITY_HIDDEN;
5035
        }
5036
        $res = Database::query($sql);
5037
        $row = Database::fetch_row($res);
5038
5039
        return $row[0];
5040
    }
5041
5042
    /**
5043
     * Returns the SQL conditions to filter course only visible by the user in the catalogue.
5044
     *
5045
     * @param string $courseTableAlias Alias of the course table
5046
     * @param bool   $hideClosed       Whether to hide closed and hidden courses
5047
     *
5048
     * @return string SQL conditions
5049
     */
5050
    public static function getCourseVisibilitySQLCondition(
5051
        $courseTableAlias,
5052
        $hideClosed = false
5053
    ) {
5054
        $visibilityCondition = '';
5055
        $hidePrivate = api_get_setting('course_catalog_hide_private');
5056
        if ('true' === $hidePrivate) {
5057
            $visibilityCondition .= " AND $courseTableAlias.visibility <> ".COURSE_VISIBILITY_REGISTERED;
5058
        }
5059
        if ($hideClosed) {
5060
            $visibilityCondition .= " AND $courseTableAlias.visibility NOT IN (".COURSE_VISIBILITY_CLOSED.','.COURSE_VISIBILITY_HIDDEN.')';
5061
        }
5062
5063
        // Check if course have users allowed to see it in the catalogue, then show only if current user is allowed to see it
5064
        $currentUserId = api_get_user_id();
5065
        $restrictedCourses = self::getCatalogueCourseList(true);
5066
        $allowedCoursesToCurrentUser = self::getCatalogueCourseList(true, $currentUserId);
5067
        if (!empty($restrictedCourses)) {
5068
            $visibilityCondition .= ' AND ('.$courseTableAlias.'.code NOT IN ("'.implode('","', $restrictedCourses).'")';
5069
            $visibilityCondition .= ' OR '.$courseTableAlias.'.code IN ("'.implode('","', $allowedCoursesToCurrentUser).'"))';
5070
        }
5071
5072
        // Check if course have users denied to see it in the catalogue, then show only if current user is not denied to see it
5073
        $restrictedCourses = self::getCatalogueCourseList(false);
5074
        $notAllowedCoursesToCurrentUser = self::getCatalogueCourseList(false, $currentUserId);
5075
        if (!empty($restrictedCourses)) {
5076
            $visibilityCondition .= ' AND ('.$courseTableAlias.'.code NOT IN ("'.implode('","', $restrictedCourses).'")';
5077
            $visibilityCondition .= ' OR '.$courseTableAlias.'.code NOT IN ("'.implode('","', $notAllowedCoursesToCurrentUser).'"))';
5078
        }
5079
5080
        return $visibilityCondition;
5081
    }
5082
5083
    /**
5084
     * Return a link to go to the course, validating the visibility of the
5085
     * course and the user status.
5086
     *
5087
     * @param int $uid User ID
5088
     * @param array Course details array
5089
     * @param array  List of courses to which the user is subscribed (if not provided, will be generated)
5090
     *
5091
     * @return mixed 'enter' for a link to go to the course or 'register' for a link to subscribe, or false if no access
5092
     */
5093
    public static function get_access_link_by_user($uid, $course, $user_courses = [])
5094
    {
5095
        if (empty($uid) || empty($course)) {
5096
            return false;
5097
        }
5098
5099
        if (empty($user_courses)) {
5100
            // get the array of courses to which the user is subscribed
5101
            $user_courses = self::get_courses_list_by_user_id($uid);
5102
            foreach ($user_courses as $k => $v) {
5103
                $user_courses[$k] = $v['real_id'];
5104
            }
5105
        }
5106
5107
        if (!isset($course['real_id']) && empty($course['real_id'])) {
5108
            $course = api_get_course_info($course['code']);
5109
        }
5110
5111
        if (COURSE_VISIBILITY_HIDDEN == $course['visibility']) {
5112
            return [];
5113
        }
5114
5115
        $is_admin = api_is_platform_admin_by_id($uid);
5116
        $options = [];
5117
        // Register button
5118
        if (!api_is_anonymous($uid) &&
5119
            (
5120
            (COURSE_VISIBILITY_OPEN_WORLD == $course['visibility'] || COURSE_VISIBILITY_OPEN_PLATFORM == $course['visibility'])
5121
                //$course['visibility'] == COURSE_VISIBILITY_REGISTERED && $course['subscribe'] == SUBSCRIBE_ALLOWED
5122
            ) &&
5123
            SUBSCRIBE_ALLOWED == $course['subscribe'] &&
5124
            (!in_array($course['real_id'], $user_courses) || empty($user_courses))
5125
        ) {
5126
            $options[] = 'register';
5127
        }
5128
5129
        // Go To Course button (only if admin, if course public or if student already subscribed)
5130
        if ($is_admin ||
5131
            COURSE_VISIBILITY_OPEN_WORLD == $course['visibility'] && empty($course['registration_code']) ||
5132
            (api_user_is_login($uid) && COURSE_VISIBILITY_OPEN_PLATFORM == $course['visibility'] && empty($course['registration_code'])) ||
5133
            (in_array($course['real_id'], $user_courses) && COURSE_VISIBILITY_CLOSED != $course['visibility'])
5134
        ) {
5135
            $options[] = 'enter';
5136
        }
5137
5138
        if ($is_admin ||
5139
            COURSE_VISIBILITY_OPEN_WORLD == $course['visibility'] && empty($course['registration_code']) ||
5140
            (api_user_is_login($uid) && COURSE_VISIBILITY_OPEN_PLATFORM == $course['visibility'] && empty($course['registration_code'])) ||
5141
            (in_array($course['real_id'], $user_courses) && COURSE_VISIBILITY_CLOSED != $course['visibility'])
5142
        ) {
5143
            $options[] = 'enter';
5144
        }
5145
5146
        if (COURSE_VISIBILITY_HIDDEN != $course['visibility'] &&
5147
            empty($course['registration_code']) &&
5148
            UNSUBSCRIBE_ALLOWED == $course['unsubscribe'] &&
5149
            api_user_is_login($uid) &&
5150
            in_array($course['real_id'], $user_courses)
5151
        ) {
5152
            $options[] = 'unsubscribe';
5153
        }
5154
5155
        return $options;
5156
    }
5157
5158
    /**
5159
     * @param array          $courseInfo
5160
     * @param array          $teachers
5161
     * @param bool           $deleteTeachersNotInList
5162
     * @param bool           $editTeacherInSessions
5163
     * @param bool           $deleteSessionTeacherNotInList
5164
     * @param array          $teacherBackup
5165
     * @param Monolog\Logger $logger
5166
     *
5167
     * @return false|null
5168
     */
5169
    public static function updateTeachers(
5170
        $courseInfo,
5171
        $teachers,
5172
        $deleteTeachersNotInList = true,
5173
        $editTeacherInSessions = false,
5174
        $deleteSessionTeacherNotInList = false,
5175
        $teacherBackup = [],
5176
        $logger = null
5177
    ) {
5178
        if (!is_array($teachers)) {
5179
            $teachers = [$teachers];
5180
        }
5181
5182
        if (empty($courseInfo) || !isset($courseInfo['real_id'])) {
5183
            return false;
5184
        }
5185
5186
        $teachers = array_filter($teachers);
5187
        $courseId = $courseInfo['real_id'];
5188
        $course_code = $courseInfo['code'];
5189
5190
        $course_user_table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5191
        $alreadyAddedTeachers = self::get_teacher_list_from_course_code($course_code);
5192
5193
        if ($deleteTeachersNotInList) {
5194
            // Delete only teacher relations that doesn't match the selected teachers
5195
            $cond = null;
5196
            if (count($teachers) > 0) {
5197
                foreach ($teachers as $key) {
5198
                    $key = Database::escape_string($key);
5199
                    $cond .= " AND user_id <> '".$key."'";
5200
                }
5201
            }
5202
5203
            // Recover user categories
5204
            $sql = "SELECT * FROM $course_user_table
5205
                    WHERE c_id = $courseId AND status = 1 AND relation_type = 0 ".$cond;
5206
            $result = Database::query($sql);
5207
            if (Database::num_rows($result)) {
5208
                $teachersToDelete = Database::store_result($result, 'ASSOC');
5209
                foreach ($teachersToDelete as $data) {
5210
                    $userId = $data['user_id'];
5211
                    $teacherBackup[$userId][$course_code] = $data;
5212
                }
5213
            }
5214
5215
            $sql = "DELETE FROM $course_user_table
5216
                    WHERE c_id = $courseId AND status = 1 AND relation_type = 0 ".$cond;
5217
5218
            Database::query($sql);
5219
        }
5220
5221
        if (count($teachers) > 0) {
5222
            foreach ($teachers as $userId) {
5223
                $userId = intval($userId);
5224
                // We check if the teacher is already subscribed in this course
5225
                $sql = "SELECT 1 FROM $course_user_table
5226
                        WHERE user_id = $userId AND c_id = $courseId";
5227
                $result = Database::query($sql);
5228
                if (Database::num_rows($result)) {
5229
                    $sql = "UPDATE $course_user_table
5230
                            SET status = 1
5231
                            WHERE c_id = $courseId AND user_id = $userId ";
5232
                } else {
5233
                    $userCourseCategory = '0';
5234
                    if (isset($teacherBackup[$userId]) &&
5235
                        isset($teacherBackup[$userId][$course_code])
5236
                    ) {
5237
                        $courseUserData = $teacherBackup[$userId][$course_code];
5238
                        $userCourseCategory = $courseUserData['user_course_cat'];
5239
                        if ($logger) {
5240
                            $logger->addInfo("Recovering user_course_cat: $userCourseCategory");
5241
                        }
5242
                    }
5243
5244
                    $sql = "INSERT INTO $course_user_table SET
5245
                            c_id = $courseId,
5246
                            user_id = $userId,
5247
                            status = 1,
5248
                            is_tutor = 0,
5249
                            sort = 0,
5250
                            relation_type = 0,
5251
                            user_course_cat = $userCourseCategory
5252
                    ";
5253
                }
5254
                Database::query($sql);
5255
            }
5256
        }
5257
5258
        if ($editTeacherInSessions) {
5259
            $sessions = SessionManager::get_session_by_course($courseId);
5260
            if (!empty($sessions)) {
5261
                if ($logger) {
5262
                    $logger->addInfo("Edit teachers in sessions");
5263
                }
5264
                foreach ($sessions as $session) {
5265
                    $sessionId = $session['id'];
5266
                    // Remove old and add new
5267
                    if ($deleteSessionTeacherNotInList) {
5268
                        foreach ($teachers as $userId) {
5269
                            if ($logger) {
5270
                                $logger->addInfo("Set coach #$userId in session #$sessionId of course #$courseId ");
5271
                            }
5272
                            SessionManager::set_coach_to_course_session(
5273
                                $userId,
5274
                                $sessionId,
5275
                                $courseId
5276
                            );
5277
                        }
5278
5279
                        $teachersToDelete = [];
5280
                        if (!empty($alreadyAddedTeachers)) {
5281
                            $teachersToDelete = array_diff(array_keys($alreadyAddedTeachers), $teachers);
5282
                        }
5283
5284
                        if (!empty($teachersToDelete)) {
5285
                            foreach ($teachersToDelete as $userId) {
5286
                                if ($logger) {
5287
                                    $logger->addInfo("Delete coach #$userId in session #$sessionId of course #$courseId ");
5288
                                }
5289
                                SessionManager::set_coach_to_course_session(
5290
                                    $userId,
5291
                                    $sessionId,
5292
                                    $courseId,
5293
                                    true
5294
                                );
5295
                            }
5296
                        }
5297
                    } else {
5298
                        // Add new teachers only
5299
                        foreach ($teachers as $userId) {
5300
                            if ($logger) {
5301
                                $logger->addInfo("Add coach #$userId in session #$sessionId of course #$courseId ");
5302
                            }
5303
                            SessionManager::set_coach_to_course_session(
5304
                                $userId,
5305
                                $sessionId,
5306
                                $courseId
5307
                            );
5308
                        }
5309
                    }
5310
                }
5311
            }
5312
        }
5313
    }
5314
5315
    /**
5316
     * Course available settings variables see c_course_setting table.
5317
     *
5318
     * @return array
5319
     */
5320
    public static function getCourseSettingVariables(AppPlugin $appPlugin)
5321
    {
5322
        $pluginCourseSettings = $appPlugin->getAllPluginCourseSettings();
5323
        $courseSettings = [
5324
            // Get allow_learning_path_theme from table
5325
            'allow_learning_path_theme',
5326
            // Get allow_open_chat_window from table
5327
            'allow_open_chat_window',
5328
            'allow_public_certificates',
5329
            // Get allow_user_edit_agenda from table
5330
            'allow_user_edit_agenda',
5331
            // Get allow_user_edit_announcement from table
5332
            'allow_user_edit_announcement',
5333
            // Get allow_user_image_forum from table
5334
            'allow_user_image_forum',
5335
            //Get allow show user list
5336
            'allow_user_view_user_list',
5337
            // Get course_theme from table
5338
            'course_theme',
5339
            //Get allow show user list
5340
            'display_info_advance_inside_homecourse',
5341
            'documents_default_visibility',
5342
            // Get send_mail_setting (work)from table
5343
            'email_alert_manager_on_new_doc',
5344
            // Get send_mail_setting (work)from table
5345
            'email_alert_manager_on_new_quiz',
5346
            // Get send_mail_setting (dropbox) from table
5347
            'email_alert_on_new_doc_dropbox',
5348
            'email_alert_students_on_new_homework',
5349
            // Get send_mail_setting (auth)from table
5350
            'email_alert_to_teacher_on_new_user_in_course',
5351
            'enable_lp_auto_launch',
5352
            'enable_exercise_auto_launch',
5353
            'enable_document_auto_launch',
5354
            'pdf_export_watermark_text',
5355
            'show_system_folders',
5356
            'exercise_invisible_in_session',
5357
            'enable_forum_auto_launch',
5358
            'show_course_in_user_language',
5359
            'email_to_teachers_on_new_work_feedback',
5360
            'student_delete_own_publication',
5361
            'hide_forum_notifications',
5362
            'quiz_question_limit_per_day',
5363
            'subscribe_users_to_forum_notifications',
5364
        ];
5365
5366
        $courseModels = ExerciseLib::getScoreModels();
5367
        if (!empty($courseModels)) {
5368
            $courseSettings[] = 'score_model_id';
5369
        }
5370
5371
        $allowLPReturnLink = api_get_setting('allow_lp_return_link');
5372
        if ('true' === $allowLPReturnLink) {
5373
            $courseSettings[] = 'lp_return_link';
5374
        }
5375
5376
        if (!empty($pluginCourseSettings)) {
5377
            $courseSettings = array_merge(
5378
                $courseSettings,
5379
                $pluginCourseSettings
5380
            );
5381
        }
5382
5383
        return $courseSettings;
5384
    }
5385
5386
    /**
5387
     * @param string       $variable
5388
     * @param string|array $value
5389
     * @param int          $courseId
5390
     *
5391
     * @return bool
5392
     */
5393
    public static function saveCourseConfigurationSetting(AppPlugin $appPlugin, $variable, $value, $courseId)
5394
    {
5395
        $settingList = self::getCourseSettingVariables($appPlugin);
5396
5397
        if (!in_array($variable, $settingList)) {
5398
            return false;
5399
        }
5400
5401
        $courseSettingTable = Database::get_course_table(TABLE_COURSE_SETTING);
5402
5403
        if (is_array($value)) {
5404
            $value = implode(',', $value);
5405
        }
5406
5407
        if (self::hasCourseSetting($variable, $courseId)) {
5408
            // Update
5409
            Database::update(
5410
                $courseSettingTable,
5411
                ['value' => $value],
5412
                ['variable = ? AND c_id = ?' => [$variable, $courseId]]
5413
            );
5414
        } else {
5415
            // Create
5416
            Database::insert(
5417
                $courseSettingTable,
5418
                [
5419
                    'title' => $variable,
5420
                    'value' => $value,
5421
                    'c_id' => $courseId,
5422
                    'variable' => $variable,
5423
                ]
5424
            );
5425
        }
5426
5427
        return true;
5428
    }
5429
5430
    /**
5431
     * Check if course setting exists.
5432
     *
5433
     * @param string $variable
5434
     * @param int    $courseId
5435
     *
5436
     * @return bool
5437
     */
5438
    public static function hasCourseSetting($variable, $courseId)
5439
    {
5440
        $courseSetting = Database::get_course_table(TABLE_COURSE_SETTING);
5441
        $courseId = (int) $courseId;
5442
        $variable = Database::escape_string($variable);
5443
        $sql = "SELECT variable FROM $courseSetting
5444
                WHERE c_id = $courseId AND variable = '$variable'";
5445
        $result = Database::query($sql);
5446
5447
        return Database::num_rows($result) > 0;
5448
    }
5449
5450
    /**
5451
     * Get information from the track_e_course_access table.
5452
     *
5453
     * @param int    $courseId
5454
     * @param int    $sessionId
5455
     * @param string $startDate
5456
     * @param string $endDate
5457
     *
5458
     * @return array
5459
     */
5460
    public static function getCourseAccessPerCourseAndSession(
5461
        $courseId,
5462
        $sessionId,
5463
        $startDate,
5464
        $endDate
5465
    ) {
5466
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
5467
        $courseId = (int) $courseId;
5468
        $sessionId = (int) $sessionId;
5469
        $startDate = Database::escape_string($startDate);
5470
        $endDate = Database::escape_string($endDate);
5471
5472
        $sql = "SELECT * FROM $table
5473
                WHERE
5474
                    c_id = $courseId AND
5475
                    session_id = $sessionId AND
5476
                    login_course_date BETWEEN '$startDate' AND '$endDate'
5477
                ";
5478
5479
        $result = Database::query($sql);
5480
5481
        return Database::store_result($result);
5482
    }
5483
5484
    /**
5485
     * Get login information from the track_e_course_access table, for any
5486
     * course in the given session.
5487
     *
5488
     * @param int $sessionId
5489
     * @param int $userId
5490
     *
5491
     * @return array
5492
     */
5493
    public static function getFirstCourseAccessPerSessionAndUser($sessionId, $userId)
5494
    {
5495
        $sessionId = (int) $sessionId;
5496
        $userId = (int) $userId;
5497
5498
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
5499
        $sql = "SELECT * FROM $table
5500
                WHERE session_id = $sessionId AND user_id = $userId
5501
                ORDER BY login_course_date ASC
5502
                LIMIT 1";
5503
5504
        $result = Database::query($sql);
5505
        $courseAccess = [];
5506
        if (Database::num_rows($result)) {
5507
            $courseAccess = Database::fetch_array($result, 'ASSOC');
5508
        }
5509
5510
        return $courseAccess;
5511
    }
5512
5513
    /**
5514
     * @param int  $courseId
5515
     * @param int  $sessionId
5516
     * @param bool $getAllSessions
5517
     *
5518
     * @return mixed
5519
     */
5520
    public static function getCountForum(
5521
        $courseId,
5522
        $sessionId = 0,
5523
        $getAllSessions = false
5524
    ) {
5525
        $forum = Database::get_course_table(TABLE_FORUM);
5526
        if ($getAllSessions) {
5527
            $sql = "SELECT count(*) as count
5528
                    FROM $forum f
5529
                    WHERE f.c_id = %s";
5530
        } else {
5531
            $sql = "SELECT count(*) as count
5532
                    FROM $forum f
5533
                    WHERE f.c_id = %s and f.session_id = %s";
5534
        }
5535
5536
        $sql = sprintf($sql, intval($courseId), intval($sessionId));
5537
        $result = Database::query($sql);
5538
        $row = Database::fetch_array($result);
5539
5540
        return $row['count'];
5541
    }
5542
5543
    /**
5544
     * @param int $userId
5545
     * @param int $courseId
5546
     * @param int $sessionId
5547
     *
5548
     * @return mixed
5549
     */
5550
    public static function getCountPostInForumPerUser(
5551
        $userId,
5552
        $courseId,
5553
        $sessionId = 0
5554
    ) {
5555
        $forum = Database::get_course_table(TABLE_FORUM);
5556
        $forum_post = Database::get_course_table(TABLE_FORUM_POST);
5557
5558
        $sql = "SELECT count(distinct post_id) as count
5559
                FROM $forum_post p
5560
                INNER JOIN $forum f
5561
                ON f.forum_id = p.forum_id AND f.c_id = p.c_id
5562
                WHERE p.poster_id = %s and f.session_id = %s and p.c_id = %s";
5563
5564
        $sql = sprintf(
5565
            $sql,
5566
            intval($userId),
5567
            intval($sessionId),
5568
            intval($courseId)
5569
        );
5570
5571
        $result = Database::query($sql);
5572
        $row = Database::fetch_array($result);
5573
5574
        return $row['count'];
5575
    }
5576
5577
    /**
5578
     * @param int $userId
5579
     * @param int $courseId
5580
     * @param int $sessionId
5581
     *
5582
     * @return mixed
5583
     */
5584
    public static function getCountForumPerUser(
5585
        $userId,
5586
        $courseId,
5587
        $sessionId = 0
5588
    ) {
5589
        $forum = Database::get_course_table(TABLE_FORUM);
5590
        $forum_post = Database::get_course_table(TABLE_FORUM_POST);
5591
5592
        $sql = "SELECT count(distinct f.forum_id) as count
5593
                FROM $forum_post p
5594
                INNER JOIN $forum f
5595
                ON f.forum_id = p.forum_id AND f.c_id = p.c_id
5596
                WHERE p.poster_id = %s and f.session_id = %s and p.c_id = %s";
5597
5598
        $sql = sprintf(
5599
            $sql,
5600
            intval($userId),
5601
            intval($sessionId),
5602
            intval($courseId)
5603
        );
5604
5605
        $result = Database::query($sql);
5606
        $row = Database::fetch_array($result);
5607
5608
        return $row['count'];
5609
    }
5610
5611
    /**
5612
     * Returns the course name from a given code.
5613
     *
5614
     * @param string $code
5615
     *
5616
     * @return string
5617
     */
5618
    public static function getCourseNameFromCode($code)
5619
    {
5620
        $tbl_main_categories = Database::get_main_table(TABLE_MAIN_COURSE);
5621
        $code = Database::escape_string($code);
5622
        $sql = "SELECT title
5623
                FROM $tbl_main_categories
5624
                WHERE code = '$code'";
5625
        $result = Database::query($sql);
5626
        if ($col = Database::fetch_array($result)) {
5627
            return $col['title'];
5628
        }
5629
    }
5630
5631
    /**
5632
     * Generates a course code from a course title.
5633
     *
5634
     * @todo Such a function might be useful in other places too. It might be moved in the CourseManager class.
5635
     * @todo the function might be upgraded for avoiding code duplications (currently,
5636
     * it might suggest a code that is already in use)
5637
     *
5638
     * @param string $title A course title
5639
     *
5640
     * @return string A proposed course code
5641
     *                +
5642
     * @assert (null,null) === false
5643
     * @assert ('ABC_DEF', null) === 'ABCDEF'
5644
     * @assert ('ABC09*^[%A', null) === 'ABC09A'
5645
     */
5646
    public static function generate_course_code($title)
5647
    {
5648
        return substr(
5649
            preg_replace('/[^A-Z0-9]/', '', strtoupper(api_replace_dangerous_char($title))),
5650
            0,
5651
            self::MAX_COURSE_LENGTH_CODE
5652
        );
5653
    }
5654
5655
    /**
5656
     * this function gets all the users of the course,
5657
     * including users from linked courses.
5658
     *
5659
     * @param $filterByActive
5660
     *
5661
     * @return array
5662
     */
5663
    public static function getCourseUsers($filterByActive = null)
5664
    {
5665
        // This would return only the users from real courses:
5666
        $userList = self::get_user_list_from_course_code(
5667
            api_get_course_id(),
5668
            api_get_session_id(),
5669
            null,
5670
            null,
5671
            null,
5672
            null,
5673
            false,
5674
            false,
5675
            [],
5676
            [],
5677
            [],
5678
            $filterByActive
5679
        );
5680
5681
        return $userList;
5682
    }
5683
5684
    /**
5685
     * this function gets all the groups of the course,
5686
     * not including linked courses.
5687
     */
5688
    public static function getCourseGroups()
5689
    {
5690
        $sessionId = api_get_session_id();
5691
        if (0 != $sessionId) {
5692
            $groupList = self::get_group_list_of_course(
5693
                api_get_course_id(),
5694
                $sessionId,
5695
                1
5696
            );
5697
        } else {
5698
            $groupList = self::get_group_list_of_course(
5699
                api_get_course_id(),
5700
                0,
5701
                1
5702
            );
5703
        }
5704
5705
        return $groupList;
5706
    }
5707
5708
    /**
5709
     * @param FormValidator $form
5710
     * @param array         $alreadySelected
5711
     *
5712
     * @return HTML_QuickForm_element
5713
     */
5714
    public static function addUserGroupMultiSelect(&$form, $alreadySelected)
5715
    {
5716
        $userList = self::getCourseUsers(true);
5717
        $groupList = self::getCourseGroups();
5718
5719
        $array = self::buildSelectOptions(
5720
            $groupList,
5721
            $userList,
5722
            $alreadySelected
5723
        );
5724
5725
        $result = [];
5726
        foreach ($array as $content) {
5727
            $result[$content['value']] = $content['content'];
5728
        }
5729
5730
        return $form->addElement(
5731
            'advmultiselect',
5732
            'users',
5733
            get_lang('Users'),
5734
            $result,
5735
            ['select_all_checkbox' => true]
5736
        );
5737
    }
5738
5739
    /**
5740
     * This function separates the users from the groups
5741
     * users have a value USER:XXX (with XXX the groups id have a value
5742
     *  GROUP:YYY (with YYY the group id).
5743
     *
5744
     * @param array $to Array of strings that define the type and id of each destination
5745
     *
5746
     * @return array Array of groups and users (each an array of IDs)
5747
     */
5748
    public static function separateUsersGroups($to)
5749
    {
5750
        $groupList = [];
5751
        $userList = [];
5752
5753
        foreach ($to as $to_item) {
5754
            if (!empty($to_item)) {
5755
                $parts = explode(':', $to_item);
5756
                $type = isset($parts[0]) ? $parts[0] : '';
5757
                $id = isset($parts[1]) ? $parts[1] : '';
5758
5759
                switch ($type) {
5760
                    case 'GROUP':
5761
                        $groupList[] = (int) $id;
5762
                        break;
5763
                    case 'USER':
5764
                        $userList[] = (int) $id;
5765
                        break;
5766
                }
5767
            }
5768
        }
5769
5770
        $send_to['groups'] = $groupList;
5771
        $send_to['users'] = $userList;
5772
5773
        return $send_to;
5774
    }
5775
5776
    /**
5777
     * Shows the form for sending a message to a specific group or user.
5778
     *
5779
     * @param FormValidator $form
5780
     * @param array         $groupInfo
5781
     * @param array         $to
5782
     *
5783
     * @return HTML_QuickForm_element
5784
     */
5785
    public static function addGroupMultiSelect($form, $groupInfo, $to = [])
5786
    {
5787
        $groupUsers = GroupManager::get_subscribed_users($groupInfo);
5788
        $array = self::buildSelectOptions([$groupInfo], $groupUsers, $to);
5789
5790
        $result = [];
5791
        foreach ($array as $content) {
5792
            $result[$content['value']] = $content['content'];
5793
        }
5794
5795
        return $form->addElement('advmultiselect', 'users', get_lang('Users'), $result);
5796
    }
5797
5798
    /**
5799
     * this function shows the form for sending a message to a specific group or user.
5800
     *
5801
     * @param array $groupList
5802
     * @param array $userList
5803
     * @param array $alreadySelected
5804
     *
5805
     * @return array
5806
     */
5807
    public static function buildSelectOptions(
5808
        $groupList = [],
5809
        $userList = [],
5810
        $alreadySelected = []
5811
    ) {
5812
        if (empty($alreadySelected)) {
5813
            $alreadySelected = [];
5814
        }
5815
5816
        $result = [];
5817
        // adding the groups to the select form
5818
        if ($groupList) {
5819
            foreach ($groupList as $thisGroup) {
5820
                $groupId = $thisGroup['iid'];
5821
                if (is_array($alreadySelected)) {
5822
                    if (!in_array(
5823
                        "GROUP:".$groupId,
5824
                        $alreadySelected
5825
                    )
5826
                    ) {
5827
                        $userCount = isset($thisGroup['userNb']) ? $thisGroup['userNb'] : 0;
5828
                        if (empty($userCount)) {
5829
                            $userCount = isset($thisGroup['count_users']) ? $thisGroup['count_users'] : 0;
5830
                        }
5831
                        // $alreadySelected is the array containing the groups (and users) that are already selected
5832
                        $user_label = ($userCount > 0) ? get_lang('Users') : get_lang('user');
5833
                        $user_disabled = ($userCount > 0) ? "" : "disabled=disabled";
5834
                        $result[] = [
5835
                            'disabled' => $user_disabled,
5836
                            'value' => "GROUP:".$groupId,
5837
                            // The space before "G" is needed in order to advmultiselect.php js puts groups first
5838
                            'content' => " G: ".$thisGroup['name']." - ".$userCount." ".$user_label,
5839
                        ];
5840
                    }
5841
                }
5842
            }
5843
        }
5844
5845
        // adding the individual users to the select form
5846
        if ($userList) {
5847
            foreach ($userList as $user) {
5848
                if (is_array($alreadySelected)) {
5849
                    if (!in_array(
5850
                        "USER:".$user['user_id'],
5851
                        $alreadySelected
5852
                    )
5853
                    ) {
5854
                        // $alreadySelected is the array containing the users (and groups) that are already selected
5855
                        $result[] = [
5856
                            'value' => "USER:".$user['user_id'],
5857
                            'content' => api_get_person_name($user['firstname'], $user['lastname']),
5858
                        ];
5859
                    }
5860
                }
5861
            }
5862
        }
5863
5864
        return $result;
5865
    }
5866
5867
    /**
5868
     * @return array a list (array) of all courses
5869
     */
5870
    public static function get_course_list()
5871
    {
5872
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
5873
5874
        return Database::store_result(Database::query("SELECT *, id as real_id FROM $table"));
5875
    }
5876
5877
    /**
5878
     * Returns course code from a given gradebook category's id.
5879
     *
5880
     * @param int  Category ID
5881
     *
5882
     * @return string Course code
5883
     */
5884
    public static function get_course_by_category($category_id)
5885
    {
5886
        $category_id = (int) $category_id;
5887
        $sql = 'SELECT c_id FROM '.Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY).'
5888
                WHERE id='.$category_id;
5889
        $info = Database::fetch_array(Database::query($sql), 'ASSOC');
5890
5891
        return $info ? $info['c_id'] : false;
5892
    }
5893
5894
    /**
5895
     * This function gets all the courses that are not in a session.
5896
     *
5897
     * @param date Start date
5898
     * @param date End date
5899
     * @param bool $includeClosed Whether to include closed and hidden courses
5900
     *
5901
     * @return array Not-in-session courses
5902
     */
5903
    public static function getCoursesWithoutSession(
5904
        $startDate = null,
5905
        $endDate = null,
5906
        $includeClosed = false
5907
    ) {
5908
        $dateConditional = ($startDate && $endDate) ?
5909
            " WHERE session_id IN (SELECT id FROM ".Database::get_main_table(TABLE_MAIN_SESSION).
5910
            " WHERE access_start_date = '$startDate' AND access_end_date = '$endDate')" : null;
5911
        $visibility = ($includeClosed ? '' : 'visibility NOT IN (0, 4) AND ');
5912
5913
        $sql = "SELECT id, code, title
5914
                FROM ".Database::get_main_table(TABLE_MAIN_COURSE)."
5915
                WHERE $visibility code NOT IN (
5916
                    SELECT DISTINCT course_code
5917
                    FROM ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE).$dateConditional."
5918
                )
5919
                ORDER BY id";
5920
5921
        $result = Database::query($sql);
5922
        $courses = [];
5923
        while ($row = Database::fetch_array($result)) {
5924
            $courses[] = $row;
5925
        }
5926
5927
        return $courses;
5928
    }
5929
5930
    /**
5931
     * Get list of courses based on users of a group for a group admin.
5932
     *
5933
     * @param int $userId The user id
5934
     *
5935
     * @return array
5936
     */
5937
    public static function getCoursesFollowedByGroupAdmin($userId)
5938
    {
5939
        $coursesList = [];
5940
        $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
5941
        $courseUserTable = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5942
        $userGroup = new UserGroup();
5943
        $userIdList = $userGroup->getGroupUsersByUser($userId);
5944
5945
        if (empty($userIdList)) {
5946
            return [];
5947
        }
5948
5949
        $sql = "SELECT DISTINCT(c.id), c.title
5950
                FROM $courseTable c
5951
                INNER JOIN $courseUserTable cru ON c.id = cru.c_id
5952
                WHERE (
5953
                    cru.user_id IN (".implode(', ', $userIdList).")
5954
                    AND cru.relation_type = 0
5955
                )";
5956
5957
        if (api_is_multiple_url_enabled()) {
5958
            $courseAccessUrlTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
5959
            $accessUrlId = api_get_current_access_url_id();
5960
5961
            if (-1 != $accessUrlId) {
5962
                $sql = "SELECT DISTINCT(c.id), c.title
5963
                        FROM $courseTable c
5964
                        INNER JOIN $courseUserTable cru ON c.id = cru.c_id
5965
                        INNER JOIN $courseAccessUrlTable crau ON c.id = crau.c_id
5966
                        WHERE crau.access_url_id = $accessUrlId
5967
                            AND (
5968
                            cru.id_user IN (".implode(', ', $userIdList).") AND
5969
                            cru.relation_type = 0
5970
                        )";
5971
            }
5972
        }
5973
5974
        $result = Database::query($sql);
5975
        while ($row = Database::fetch_assoc($result)) {
5976
            $coursesList[] = $row;
5977
        }
5978
5979
        return $coursesList;
5980
    }
5981
5982
    /**
5983
     * Direct course link see #5299.
5984
     *
5985
     * You can send to your students an URL like this
5986
     * http://chamilodev.beeznest.com/main/auth/inscription.php?c=ABC&e=3
5987
     * Where "c" is the course code and "e" is the exercise Id, after a successful
5988
     * registration the user will be sent to the course or exercise
5989
     *
5990
     * @param array $form_data
5991
     *
5992
     * @return array
5993
     */
5994
    public static function redirectToCourse($form_data)
5995
    {
5996
        $course_code_redirect = Session::read('course_redirect');
5997
        $_user = api_get_user_info();
5998
        $userId = api_get_user_id();
5999
6000
        if (!empty($course_code_redirect)) {
6001
            $course_info = api_get_course_info($course_code_redirect);
6002
            if (!empty($course_info)) {
6003
                if (in_array(
6004
                    $course_info['visibility'],
6005
                    [COURSE_VISIBILITY_OPEN_PLATFORM, COURSE_VISIBILITY_OPEN_WORLD]
6006
                )
6007
                ) {
6008
                    if (self::is_user_subscribed_in_course($userId, $course_info['code'])) {
6009
                        $form_data['action'] = $course_info['course_public_url'];
6010
                        $form_data['message'] = sprintf(get_lang('You have been registered to course %s'), $course_info['title']);
6011
                        $form_data['button'] = Display::button(
6012
                            'next',
6013
                            get_lang('Go to the course', null, $_user['language']),
6014
                            ['class' => 'btn btn-primary btn-large']
6015
                        );
6016
6017
                        $exercise_redirect = (int) Session::read('exercise_redirect');
6018
                        // Specify the course id as the current context does not
6019
                        // hold a global $_course array
6020
                        $objExercise = new Exercise($course_info['real_id']);
6021
                        $result = $objExercise->read($exercise_redirect);
6022
6023
                        if (!empty($exercise_redirect) && !empty($result)) {
6024
                            $form_data['action'] = api_get_path(WEB_CODE_PATH).
6025
                                'exercise/overview.php?exerciseId='.$exercise_redirect.'&cid='.$course_info['real_id'];
6026
                            $form_data['message'] .= '<br />'.get_lang('Go to the test');
6027
                            $form_data['button'] = Display::button(
6028
                                'next',
6029
                                get_lang('Go', null, $_user['language']),
6030
                                ['class' => 'btn btn-primary btn-large']
6031
                            );
6032
                        }
6033
6034
                        if (!empty($form_data['action'])) {
6035
                            header('Location: '.$form_data['action']);
6036
                            exit;
6037
                        }
6038
                    }
6039
                }
6040
            }
6041
        }
6042
6043
        return $form_data;
6044
    }
6045
6046
    /**
6047
     * Return tab of params to display a course title in the My Courses tab
6048
     * Check visibility, right, and notification icons, and load_dirs option
6049
     * get html course params.
6050
     *
6051
     * @param $courseId
6052
     * @param bool $loadDirs
6053
     *
6054
     * @return array with keys ['right_actions'] ['teachers'] ['notifications']
6055
     */
6056
    public static function getCourseParamsForDisplay($courseId, $loadDirs = false)
6057
    {
6058
        $userId = api_get_user_id();
6059
        $courseId = intval($courseId);
6060
        // Table definitions
6061
        $TABLECOURS = Database::get_main_table(TABLE_MAIN_COURSE);
6062
        $TABLECOURSUSER = Database::get_main_table(TABLE_MAIN_COURSE_USER);
6063
        $TABLE_ACCESS_URL_REL_COURSE = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
6064
        $current_url_id = api_get_current_access_url_id();
6065
6066
        // Get course list auto-register
6067
        $special_course_list = self::get_special_course_list();
6068
6069
        $without_special_courses = '';
6070
        if (!empty($special_course_list)) {
6071
            $without_special_courses = ' AND course.id NOT IN ("'.implode('","', $special_course_list).'")';
6072
        }
6073
6074
        //AND course_rel_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
6075
        $sql = "SELECT
6076
                    course.id,
6077
                    course.title,
6078
                    course.code,
6079
                    course.subscribe subscr,
6080
                    course.unsubscribe unsubscr,
6081
                    course_rel_user.status status,
6082
                    course_rel_user.sort sort,
6083
                    course_rel_user.user_course_cat user_course_cat
6084
                FROM
6085
                $TABLECOURS course
6086
                INNER JOIN $TABLECOURSUSER course_rel_user
6087
                ON (course.id = course_rel_user.c_id)
6088
                INNER JOIN $TABLE_ACCESS_URL_REL_COURSE url
6089
                ON (url.c_id = course.id)
6090
                WHERE
6091
                    course.id = $courseId AND
6092
                    course_rel_user.user_id = $userId
6093
                    $without_special_courses
6094
                ";
6095
6096
        // If multiple URL access mode is enabled, only fetch courses
6097
        // corresponding to the current URL.
6098
        if (api_get_multiple_access_url() && -1 != $current_url_id) {
6099
            $sql .= " AND url.c_id = course.id AND access_url_id = $current_url_id";
6100
        }
6101
        // Use user's classification for courses (if any).
6102
        $sql .= " ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
6103
6104
        $result = Database::query($sql);
6105
6106
        // Browse through all courses. We can only have one course because
6107
        // of the  course.id=".intval($courseId) in sql query
6108
        $course = Database::fetch_array($result);
6109
        $course_info = api_get_course_info_by_id($courseId);
6110
        if (empty($course_info)) {
6111
            return '';
6112
        }
6113
6114
        //$course['id_session'] = null;
6115
        $course_info['id_session'] = null;
6116
        $course_info['status'] = $course['status'];
6117
6118
        // For each course, get if there is any notification icon to show
6119
        // (something that would have changed since the user's last visit).
6120
        $show_notification = !api_get_configuration_value('hide_course_notification')
6121
            ? Display::show_notification($course_info)
6122
            : '';
6123
6124
        // New code displaying the user's status in respect to this course.
6125
        $status_icon = Display::return_icon(
6126
            'blackboard.png',
6127
            $course_info['title'],
6128
            [],
6129
            ICON_SIZE_LARGE
6130
        );
6131
6132
        $params = [];
6133
        $params['right_actions'] = '';
6134
6135
        if (api_is_platform_admin()) {
6136
            if ($loadDirs) {
6137
                $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>';
6138
                $params['right_actions'] .= '<a href="'.api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cid='.$course['real_id'].'">'.
6139
                    Display::return_icon('edit.png', get_lang('Edit'), ['align' => 'absmiddle'], ICON_SIZE_SMALL).
6140
                    '</a>';
6141
                $params['right_actions'] .= Display::div(
6142
                    '',
6143
                    [
6144
                        'id' => 'document_result_'.$course_info['real_id'].'_0',
6145
                        'class' => 'document_preview_container',
6146
                    ]
6147
                );
6148
            } else {
6149
                $params['right_actions'] .=
6150
                    '<a class="btn btn-default btn-sm" title="'.get_lang('Edit').'" href="'.api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cid='.$course['real_id'].'">'.
6151
                    Display::returnFontAwesomeIcon('pencil').'</a>';
6152
            }
6153
        } else {
6154
            if (COURSE_VISIBILITY_CLOSED != $course_info['visibility']) {
6155
                if ($loadDirs) {
6156
                    $params['right_actions'] .= '<a id="document_preview_'.$course_info['real_id'].'_0" class="document_preview" href="javascript:void(0);">'.
6157
                        Display::return_icon('folder.png', get_lang('Documents'), ['align' => 'absmiddle'], ICON_SIZE_SMALL).'</a>';
6158
                    $params['right_actions'] .= Display::div(
6159
                        '',
6160
                        [
6161
                            'id' => 'document_result_'.$course_info['real_id'].'_0',
6162
                            'class' => 'document_preview_container',
6163
                        ]
6164
                    );
6165
                } else {
6166
                    if (COURSEMANAGER == $course_info['status']) {
6167
                        $params['right_actions'] .= '<a
6168
                            class="btn btn-default btn-sm" title="'.get_lang('Edit').'" href="'.api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cid='.$course['real_id'].'">'.
6169
                            Display::returnFontAwesomeIcon('pencil').'</a>';
6170
                    }
6171
                }
6172
            }
6173
        }
6174
6175
        $course_title_url = '';
6176
        if (COURSE_VISIBILITY_CLOSED != $course_info['visibility'] || COURSEMANAGER == $course['status']) {
6177
            $course_title_url = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/?id_session=0';
6178
            $course_title = Display::url($course_info['title'], $course_title_url);
6179
        } else {
6180
            $course_title = $course_info['title'].' '.Display::tag(
6181
                'span',
6182
                get_lang('(the course is currently closed)'),
6183
                ['class' => 'item_closed']
6184
            );
6185
        }
6186
6187
        // Start displaying the course block itself
6188
        if ('true' === api_get_setting('display_coursecode_in_courselist')) {
6189
            $course_title .= ' ('.$course_info['visual_code'].') ';
6190
        }
6191
        $teachers = '';
6192
        if ('true' === api_get_setting('display_teacher_in_courselist')) {
6193
            $teachers = self::getTeacherListFromCourseCodeToString(
6194
                $course['code'],
6195
                self::USER_SEPARATOR,
6196
                true
6197
            );
6198
        }
6199
        $params['link'] = $course_title_url;
6200
        $params['icon'] = $status_icon;
6201
        $params['title'] = $course_title;
6202
        $params['teachers'] = $teachers;
6203
        if (COURSE_VISIBILITY_CLOSED != $course_info['visibility']) {
6204
            $params['notifications'] = $show_notification;
6205
        }
6206
6207
        return $params;
6208
    }
6209
6210
    /**
6211
     * Get the course id based on the original id and field name in the extra fields.
6212
     * Returns 0 if course was not found.
6213
     *
6214
     * @param string $original_course_id_value Original course id
6215
     * @param string $original_course_id_name  Original field name
6216
     *
6217
     * @return int Course id
6218
     */
6219
    public static function get_course_id_from_original_id($original_course_id_value, $original_course_id_name)
6220
    {
6221
        $extraFieldValue = new ExtraFieldValue('course');
6222
        $value = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
6223
            $original_course_id_name,
6224
            $original_course_id_value
6225
        );
6226
6227
        if ($value) {
6228
            return $value['item_id'];
6229
        }
6230
6231
        return 0;
6232
    }
6233
6234
    /**
6235
     * Helper function to create a default gradebook (if necessary) upon course creation.
6236
     *
6237
     * @param int    $modelId    The gradebook model ID
6238
     * @param string $courseCode Course code
6239
     */
6240
    public static function createDefaultGradebook($modelId, $courseCode)
6241
    {
6242
        if ('true' === api_get_setting('gradebook_enable_grade_model')) {
6243
            //Create gradebook_category for the new course and add
6244
            // a gradebook model for the course
6245
            if (isset($modelId) &&
6246
                !empty($modelId) &&
6247
                '-1' != $modelId
6248
            ) {
6249
                GradebookUtils::create_default_course_gradebook(
6250
                    $courseCode,
6251
                    $modelId
6252
                );
6253
            }
6254
        }
6255
    }
6256
6257
    /**
6258
     * Helper function to check if there is a course template and, if so, to
6259
     * copy the template as basis for the new course.
6260
     *
6261
     * @param string $courseCode     Course code
6262
     * @param int    $courseTemplate 0 if no course template is defined
6263
     */
6264
    public static function useTemplateAsBasisIfRequired($courseCode, $courseTemplate)
6265
    {
6266
        $template = api_get_setting('course_creation_use_template');
6267
        $teacherCanSelectCourseTemplate = 'true' === api_get_setting('teacher_can_select_course_template');
6268
        $courseTemplate = isset($courseTemplate) ? intval($courseTemplate) : 0;
6269
6270
        $useTemplate = false;
6271
6272
        if ($teacherCanSelectCourseTemplate && $courseTemplate) {
6273
            $useTemplate = true;
6274
            $originCourse = api_get_course_info_by_id($courseTemplate);
6275
        } elseif (!empty($template)) {
6276
            $useTemplate = true;
6277
            $originCourse = api_get_course_info_by_id($template);
6278
        }
6279
6280
        if ($useTemplate) {
6281
            // Include the necessary libraries to generate a course copy
6282
            // Call the course copy object
6283
            $originCourse['official_code'] = $originCourse['code'];
6284
            $cb = new CourseBuilder(null, $originCourse);
6285
            $course = $cb->build(null, $originCourse['code']);
6286
            $cr = new CourseRestorer($course);
6287
            $cr->set_file_option();
6288
            $cr->restore($courseCode);
6289
        }
6290
    }
6291
6292
    /**
6293
     * Helper method to get the number of users defined with a specific course extra field.
6294
     *
6295
     * @param string $name                 Field title
6296
     * @param string $tableExtraFields     The extra fields table name
6297
     * @param string $tableUserFieldValues The user extra field value table name
6298
     *
6299
     * @return int The number of users with this extra field with a specific value
6300
     */
6301
    public static function getCountRegisteredUsersWithCourseExtraField(
6302
        $name,
6303
        $tableExtraFields = '',
6304
        $tableUserFieldValues = ''
6305
    ) {
6306
        if (empty($tableExtraFields)) {
6307
            $tableExtraFields = Database::get_main_table(TABLE_EXTRA_FIELD);
6308
        }
6309
        if (empty($tableUserFieldValues)) {
6310
            $tableUserFieldValues = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
6311
        }
6312
6313
        $registered_users_with_extra_field = 0;
6314
        if (!empty($name) && '-' != $name) {
6315
            $extraFieldType = EntityExtraField::COURSE_FIELD_TYPE;
6316
            $name = Database::escape_string($name);
6317
            $sql = "SELECT count(v.item_id) as count
6318
                    FROM $tableUserFieldValues v
6319
                    INNER JOIN $tableExtraFields f
6320
                    ON (f.id = v.field_id)
6321
                    WHERE value = '$name' AND extra_field_type = $extraFieldType";
6322
            $result_count = Database::query($sql);
6323
            if (Database::num_rows($result_count)) {
6324
                $row_count = Database::fetch_array($result_count);
6325
                $registered_users_with_extra_field = $row_count['count'];
6326
            }
6327
        }
6328
6329
        return $registered_users_with_extra_field;
6330
    }
6331
6332
    /**
6333
     * Get the course categories form a course list.
6334
     *
6335
     * @return array
6336
     */
6337
    public static function getCourseCategoriesFromCourseList(array $courseList)
6338
    {
6339
        $allCategories = array_column($courseList, 'category');
6340
        $categories = array_unique($allCategories);
6341
6342
        sort($categories);
6343
6344
        return $categories;
6345
    }
6346
6347
    /**
6348
     * Display the description button of a course in the course catalog.
6349
     *
6350
     * @param array $course
6351
     *
6352
     * @return string HTML string
6353
     */
6354
    public static function returnDescriptionButton($course)
6355
    {
6356
        if (empty($course)) {
6357
            return '';
6358
        }
6359
6360
        if ('true' == api_get_setting('show_courses_descriptions_in_catalog')) {
6361
            $title = $course['title'];
6362
            $url = api_get_path(WEB_CODE_PATH).'inc/ajax/course_home.ajax.php?a=show_course_information&code='.$course['code'];
6363
            $html = Display::url(
6364
                Display::returnFontAwesomeIcon('info-circle', 'lg'),
6365
                $url,
6366
                [
6367
                    'class' => 'ajax btn btn-light btn-sm',
6368
                    'data-title' => $title,
6369
                    'title' => get_lang('Description'),
6370
                    'aria-label' => get_lang('Description'),
6371
                    'data-size' => 'lg',
6372
                ]
6373
            );
6374
6375
            return $html;
6376
        }
6377
6378
        return '';
6379
    }
6380
6381
    /**
6382
     * @return int
6383
     */
6384
    public static function getCountOpenCourses()
6385
    {
6386
        $visibility = [
6387
            COURSE_VISIBILITY_REGISTERED,
6388
            COURSE_VISIBILITY_OPEN_PLATFORM,
6389
            COURSE_VISIBILITY_OPEN_WORLD,
6390
        ];
6391
6392
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
6393
        $sql = "SELECT count(id) count
6394
                FROM $table
6395
                WHERE visibility IN (".implode(',', $visibility).")";
6396
        $result = Database::query($sql);
6397
        $row = Database::fetch_array($result);
6398
6399
        return (int) $row['count'];
6400
    }
6401
6402
    /**
6403
     * @return int
6404
     */
6405
    public static function getCountExercisesFromOpenCourse()
6406
    {
6407
        $visibility = [
6408
            COURSE_VISIBILITY_REGISTERED,
6409
            COURSE_VISIBILITY_OPEN_PLATFORM,
6410
            COURSE_VISIBILITY_OPEN_WORLD,
6411
        ];
6412
6413
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
6414
        $tableExercise = Database::get_course_table(TABLE_QUIZ_TEST);
6415
        $sql = "SELECT count(e.iid) count
6416
                FROM $table c INNER JOIN $tableExercise e
6417
                ON (c.id = e.c_id)
6418
                WHERE e.active <> -1 AND visibility IN (".implode(',', $visibility).")";
6419
        $result = Database::query($sql);
6420
        $row = Database::fetch_array($result);
6421
6422
        return (int) $row['count'];
6423
    }
6424
6425
    /**
6426
     * @param ToolChain $toolList
6427
     */
6428
    public static function setToolList($toolList)
6429
    {
6430
        self::$toolList = $toolList;
6431
    }
6432
6433
    /**
6434
     * @return ToolChain
6435
     */
6436
    public static function getToolList()
6437
    {
6438
        return self::$toolList;
6439
    }
6440
6441
    /**
6442
     * Check if a specific access-url-related setting is a problem or not.
6443
     *
6444
     * @param array  $_configuration The $_configuration array
6445
     * @param int    $accessUrlId    The access URL ID
6446
     * @param string $param
6447
     * @param string $msgLabel
6448
     *
6449
     * @return bool|string
6450
     */
6451
    private static function checkCreateCourseAccessUrlParam($_configuration, $accessUrlId, $param, $msgLabel)
6452
    {
6453
        if (isset($_configuration[$accessUrlId][$param]) && $_configuration[$accessUrlId][$param] > 0) {
6454
            $num = self::count_courses($accessUrlId);
6455
            if ($num >= $_configuration[$accessUrlId][$param]) {
6456
                api_warn_hosting_contact($param);
6457
6458
                Display::addFlash(
6459
                    Display::return_message($msgLabel)
6460
                );
6461
            }
6462
        }
6463
6464
        return false;
6465
    }
6466
6467
    /**
6468
     * Fill course with all necessary items.
6469
     *
6470
     * @param array $courseInfo Course info array
6471
     * @param array $params     Parameters from the course creation form
6472
     * @param int   $authorId
6473
     */
6474
    private static function fillCourse($courseInfo, $params, $authorId = 0)
6475
    {
6476
        $authorId = empty($authorId) ? api_get_user_id() : (int) $authorId;
6477
6478
        AddCourse::fillCourse(
6479
            $courseInfo,
6480
            $params['exemplary_content'],
6481
            $authorId
6482
        );
6483
6484
        if (isset($params['gradebook_model_id'])) {
6485
            self::createDefaultGradebook(
6486
                $params['gradebook_model_id'],
6487
                $courseInfo['code']
6488
            );
6489
        }
6490
6491
        // If parameter defined, copy the contents from a specific
6492
        // template course into this new course
6493
        if (isset($params['course_template'])) {
6494
            self::useTemplateAsBasisIfRequired(
6495
                $courseInfo['id'],
6496
                $params['course_template']
6497
            );
6498
        }
6499
        $params['course_code'] = $courseInfo['code'];
6500
        $params['item_id'] = $courseInfo['real_id'];
6501
6502
        $courseFieldValue = new ExtraFieldValue('course');
6503
        $courseFieldValue->saveFieldValues($params);
6504
    }
6505
}
6506