Passed
Push — 1.11.x ( a83aa6...c231b6 )
by Julito
14:28
created

CourseManager::getCoursesFollowedByUser()   F

Complexity

Conditions 14
Paths 480

Size

Total Lines 107
Code Lines 64

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 14
eloc 64
nc 480
nop 10
dl 0
loc 107
rs 2.8222
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

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