Completed
Push — master ( 395485...bbad3a )
by Julito
43:12
created

CourseManager::get_coachs_from_course_to_string()   C

Complexity

Conditions 7
Paths 6

Size

Total Lines 45
Code Lines 31

Duplication

Lines 42
Ratio 93.33 %

Importance

Changes 0
Metric Value
cc 7
eloc 31
nc 6
nop 5
dl 42
loc 45
rs 6.7272
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt*/
3
4
use Chamilo\CoreBundle\Entity\ExtraField as EntityExtraField;
5
use ChamiloSession as Session;
6
//use Chamilo\CourseBundle\Manager\SettingsManager;
7
use Chamilo\CourseBundle\ToolChain;
8
use Chamilo\CoreBundle\Entity\Course;
9
use Chamilo\CourseBundle\Component\CourseCopy\CourseBuilder;
10
use Chamilo\CourseBundle\Component\CourseCopy\CourseRestorer;
11
use Chamilo\CourseBundle\Manager\SettingsManager;
12
13
/**
14
 * Class CourseManager
15
 *
16
 * This is the course library for Chamilo.
17
 *
18
 * All main course functions should be placed here.
19
 *
20
 * Many functions of this library deal with providing support for
21
 * virtual/linked/combined courses (this was already used in several universities
22
 * but not available in standard Chamilo).
23
 *
24
 * There are probably some places left with the wrong code.
25
 *
26
 * @package chamilo.library
27
 */
28
class CourseManager
29
{
30
    const MAX_COURSE_LENGTH_CODE = 40;
31
    /** This constant is used to show separate user names in the course
32
     * list (userportal), footer, etc */
33
    const USER_SEPARATOR = ' |';
34
    const COURSE_FIELD_TYPE_CHECKBOX = 10;
35
    public $columns = array();
36
    public static $em;
37
    private static $manager;
38
    public static $toolList;
39
    public static $courseSettingsManager;
40
41
     /**
42
     * @param \Doctrine\ORM\EntityManager
43
     */
44
    public static function setEntityManager($em)
45
    {
46
        self::$em = $em;
47
    }
48
49
    /**
50
     * @return \Doctrine\ORM\EntityManager
51
     */
52
    public static function getEntityManager()
53
    {
54
        return self::$em;
55
    }
56
57
    /**
58
     * @return Chamilo\CoreBundle\Entity\CourseManager
59
     */
60
    public static function setCourseManager($manager)
61
    {
62
        self::$manager = $manager;
63
    }
64
65
    /**
66
     * @return SettingsManager
67
     */
68
    public static function getCourseSettingsManager()
69
    {
70
        return self::$courseSettingsManager;
71
    }
72
73
    /**
74
     * @param SettingsManager $courseSettingsManager
75
     */
76
    public static function setCourseSettingsManager($courseSettingsManager)
77
    {
78
        self::$courseSettingsManager = $courseSettingsManager;
79
    }
80
81
    /**
82
     * @return Chamilo\CoreBundle\Entity\Manager\CourseManager
83
     */
84
    public static function getManager()
85
    {
86
        return self::$manager;
87
    }
88
89
    /**
90
     * Creates a course
91
     * @param   array $params columns in the main.course table
92
     *
93
     * @return  mixed  false if the course was not created, array with the course info
94
     */
95
    public static function create_course($params, $authorId = 0)
96
    {
97
        global $_configuration;
98
        // Check portal limits
99
        $access_url_id = 1;
100
        if (api_get_multiple_access_url()) {
101
            $access_url_id = api_get_current_access_url_id();
102
        }
103
104
        $authorId = empty($authorId) ? api_get_user_id() : (int) $authorId;
105
106
        if (isset($_configuration[$access_url_id]) && is_array($_configuration[$access_url_id])) {
107
            $return = self::checkCreateCourseAccessUrlParam(
108
                $_configuration,
109
                $access_url_id,
110
                'hosting_limit_courses',
111
                'PortalCoursesLimitReached'
112
            );
113
            if ($return != false) {
114
                return $return;
115
            }
116
            $return = self::checkCreateCourseAccessUrlParam(
117
                $_configuration,
118
                $access_url_id,
119
                'hosting_limit_active_courses',
120
                'PortalActiveCoursesLimitReached'
121
            );
122
            if ($return != false) {
123
                return $return;
124
            }
125
        }
126
127
        if (empty($params['title'])) {
128
            return false;
129
        }
130
131
        if (empty($params['wanted_code'])) {
132
            $params['wanted_code'] = $params['title'];
133
            // Check whether the requested course code has already been occupied.
134
            $substring = api_substr($params['title'], 0, self::MAX_COURSE_LENGTH_CODE);
135
            if ($substring === false || empty($substring)) {
136
                return false;
137
            } else {
138
                $params['wanted_code'] = CourseManager::generate_course_code($substring);
139
            }
140
        }
141
142
        // Create the course keys
143
        $keys = AddCourse::define_course_keys($params['wanted_code']);
144
145
        $params['exemplary_content'] = isset($params['exemplary_content']) ? $params['exemplary_content'] : false;
146
147
        if (count($keys)) {
148
            $params['code'] = $keys['currentCourseCode'];
149
            $params['visual_code'] = $keys['currentCourseId'];
150
            $params['directory'] = $keys['currentCourseRepository'];
151
152
            $course_info = api_get_course_info($params['code']);
153
154
            if (empty($course_info)) {
155
                $course_id = AddCourse::register_course($params);
156
                $course_info = api_get_course_info_by_id($course_id);
157
158
                if (!empty($course_info)) {
159
                    self::fillCourse($course_info, $params, $authorId);
160
161
                    return $course_info;
162
                }
163
            }
164
        }
165
166
        return false;
167
    }
168
169
    /**
170
     * Returns all the information of a given course code
171
     * @param string $course_code , the course code
172
     * @return array with all the fields of the course table
173
     * @author Patrick Cool <[email protected]>, Ghent University
174
     * @assert ('') === false
175
     */
176
    public static function get_course_information($course_code)
177
    {
178
        return Database::fetch_array(
179
            Database::query(
0 ignored issues
show
Bug introduced by
It seems like \Database::query('SELECT...g($course_code) . '\'') can be null; however, fetch_array() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
180
                "SELECT *, id as real_id FROM " . Database::get_main_table(TABLE_MAIN_COURSE) . "
181
                WHERE code='" . Database::escape_string($course_code) . "'"), 'ASSOC'
182
        );
183
    }
184
185
    /**
186
     * Returns a list of courses. Should work with quickform syntax
187
     * @param    integer $from Offset (from the 7th = '6'). Optional.
188
     * @param    integer $howmany Number of results we want. Optional.
189
     * @param    int $orderby The column we want to order it by. Optional, defaults to first column.
190
     * @param    string $orderdirection The direction of the order (ASC or DESC). Optional, defaults to ASC.
191
     * @param    int $visibility The visibility of the course, or all by default.
192
     * @param    string $startwith If defined, only return results for which the course *title* begins with this string
193
     * @param    string $urlId The Access URL ID, if using multiple URLs
194
     * @param    bool $alsoSearchCode An extension option to indicate that we also want to search for course codes (not *only* titles)
195
     * @param    array $conditionsLike
196
     * @return array
197
     */
198
    public static function get_courses_list(
199
        $from = 0,
200
        $howmany = 0,
201
        $orderby = 1,
202
        $orderdirection = 'ASC',
203
        $visibility = -1,
204
        $startwith = '',
205
        $urlId = null,
206
        $alsoSearchCode = false,
207
        $conditionsLike = array()
208
    ) {
209
        $sql = "SELECT course.* FROM " . Database::get_main_table(TABLE_MAIN_COURSE) . " course ";
210
211
        if (!empty($urlId)) {
212
            $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
213
            $sql .= " INNER JOIN $table url ON (url.c_id = course.id) ";
214
        }
215
216
        if (!empty($startwith)) {
217
            $sql .= "WHERE (title LIKE '" . Database::escape_string($startwith) . "%' ";
218
            if ($alsoSearchCode) {
219
                $sql .= "OR code LIKE '" . Database::escape_string($startwith) . "%' ";
220
            }
221
            $sql .= ') ';
222 View Code Duplication
            if ($visibility !== -1 && $visibility == strval(intval($visibility))) {
223
                $sql .= " AND visibility = $visibility ";
224
            }
225 View Code Duplication
        } else {
226
            $sql .= "WHERE 1 ";
227
            if ($visibility !== -1 && $visibility == strval(intval($visibility))) {
228
                $sql .= " AND visibility = $visibility ";
229
            }
230
        }
231
232
        if (!empty($urlId)) {
233
            $urlId = intval($urlId);
234
            $sql .= " AND access_url_id= $urlId";
235
        }
236
237
        $allowedFields = array(
238
            'title',
239
            'code'
240
        );
241
242
        if (count($conditionsLike) > 0) {
243
            $sql .= ' AND ';
244
            $temp_conditions = array();
245
            foreach ($conditionsLike as $field => $value) {
246
                if (!in_array($field, $allowedFields)) {
247
                    continue;
248
                }
249
                $field = Database::escape_string($field);
250
                $value = Database::escape_string($value);
251
                $simple_like = false;
252 View Code Duplication
                if ($simple_like) {
253
                    $temp_conditions[] = $field . " LIKE '$value%'";
254
                } else {
255
                    $temp_conditions[] = $field . ' LIKE \'%' . $value . '%\'';
256
                }
257
            }
258
            $condition = ' AND ';
259
            if (!empty($temp_conditions)) {
260
                $sql .= implode(' ' . $condition . ' ', $temp_conditions);
261
            }
262
        }
263
264
        if (!empty($orderby)) {
265
            $sql .= " ORDER BY " . Database::escape_string($orderby) . " ";
266
        } else {
267
            $sql .= " ORDER BY 1 ";
268
        }
269
270
        if (!in_array($orderdirection, array('ASC', 'DESC'))) {
271
            $sql .= 'ASC';
272
        } else {
273
            $sql .= ($orderdirection == 'ASC' ? 'ASC' : 'DESC');
274
        }
275
276
        if (!empty($howmany) && is_int($howmany) and $howmany > 0) {
277
            $sql .= ' LIMIT ' . Database::escape_string($howmany);
278
        } else {
279
            $sql .= ' LIMIT 1000000'; //virtually no limit
280
        }
281
        if (!empty($from)) {
282
            $from = intval($from);
283
            $sql .= ' OFFSET ' . intval($from);
284
        } else {
285
            $sql .= ' OFFSET 0';
286
        }
287
288
        $data = [];
289
        $res = Database::query($sql);
290
        if (Database::num_rows($res) > 0) {
291
            while ($row = Database::fetch_array($res, 'ASSOC')) {
292
                $data[] = $row;
293
            }
294
        }
295
296
        return $data;
297
    }
298
299
    /**
300
     * Returns the status of a user in a course, which is COURSEMANAGER or STUDENT.
301
     * @param   int $userId
302
     * @param   int $courseId
303
     *
304
     * @return int|bool the status of the user in that course (or false if the user is not in that course)
305
     */
306
    public static function getUserInCourseStatus($userId, $courseId)
307
    {
308
        $courseId = (int) $courseId;
309
        if (empty($courseId)) {
310
            return false;
311
        }
312
313
        $result = Database::fetch_array(
314
            Database::query(
0 ignored issues
show
Bug introduced by
It seems like \Database::query('SELECT... = " . intval($userId)) can be null; however, fetch_array() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
315
                "SELECT status FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER) . "
316
                WHERE
317
                    c_id  = $courseId AND
318
                    user_id = " . intval($userId)
319
            )
320
        );
321
322
        return $result['status'];
323
    }
324
325
    /**
326
     * @param int $userId
327
     * @param int $courseId
328
     *
329
     * @return mixed
330
     */
331 View Code Duplication
    public static function getUserCourseInfo($userId, $courseId)
332
    {
333
334
        $result = Database::fetch_array(
335
            Database::query("
0 ignored issues
show
Bug introduced by
It seems like \Database::query(' ... = ' . intval($userId)) can be null; however, fetch_array() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
336
                SELECT * FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER) . "
337
                WHERE
338
                    c_id  = '" . intval($courseId). "' AND
339
                    user_id = " . intval($userId)
340
            )
341
        );
342
343
        return $result;
344
    }
345
346
    /**
347
     * @param int  $userId
348
     * @param int  $courseId
349
     * @param bool $isTutor
350
     *
351
     * @return bool
352
     */
353
    public static function updateUserCourseTutor($userId, $courseId, $isTutor)
354
    {
355
        $table = Database::escape_string(TABLE_MAIN_COURSE_USER);
356
357
        $courseId = intval($courseId);
358
        $isTutor = intval($isTutor);
359
360
        $sql = "UPDATE $table SET is_tutor = '".$isTutor."'
361
			    WHERE
362
				    user_id = '".$userId."' AND
363
				    c_id = '".$courseId."'";
364
365
        $result = Database::query($sql);
366
367
        if (Database::affected_rows($result) > 0) {
368
            return true;
369
        } else {
370
            return false;
371
        }
372
    }
373
374
    /**
375
     * @param int $user_id
376
     * @param int $courseId
377
     *
378
     * @return mixed
379
     */
380 View Code Duplication
    public static function get_tutor_in_course_status($user_id, $courseId)
381
    {
382
        $result = Database::fetch_array(
383
            Database::query("
0 ignored issues
show
Bug introduced by
It seems like \Database::query(' ...= ' . intval($user_id)) can be null; however, fetch_array() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
384
                SELECT is_tutor
385
                FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER) . "
386
                WHERE
387
                    c_id = '" . Database::escape_string($courseId) . "' AND
388
                    user_id = " . intval($user_id)
389
            )
390
        );
391
392
        return $result['is_tutor'];
393
    }
394
395
    /**
396
     * Unsubscribe one or more users from a course
397
     *
398
     * @param   mixed   user_id or an array with user ids
399
     * @param   string  course code
400
     * @param   int     session id
401
     * @assert ('', '') === false
402
     *
403
     */
404
    public static function unsubscribe_user($user_id, $course_code, $session_id = 0)
405
    {
406
        if (!is_array($user_id)) {
407
            $user_id = array($user_id);
408
        }
409
410
        if (count($user_id) == 0) {
411
            return;
412
        }
413
414
        if (!empty($session_id)) {
415
            $session_id = intval($session_id);
416
        } else {
417
            $session_id = api_get_session_id();
418
        }
419
420
        $user_list = array();
421
422
        // Cleaning the $user_id variable
423
        if (is_array($user_id)) {
424
            $new_user_id_list = array();
425
            foreach ($user_id as $my_user_id) {
426
                $new_user_id_list[] = intval($my_user_id);
427
            }
428
            $new_user_id_list = array_filter($new_user_id_list);
429
            $user_list = $new_user_id_list;
430
            $user_ids = implode(',', $new_user_id_list);
431
        } else {
432
            $user_ids = intval($user_id);
433
            $user_list[] = $user_id;
434
        }
435
436
        $course_info = api_get_course_info($course_code);
437
        $course_id = $course_info['real_id'];
438
439
        // Unsubscribe user from all groups in the course.
440
        $sql = "DELETE FROM " . Database::get_course_table(TABLE_GROUP_USER) . "
441
                WHERE c_id = $course_id AND user_id IN (" . $user_ids . ")";
442
        Database::query($sql);
443
        $sql = "DELETE FROM " . Database::get_course_table(TABLE_GROUP_TUTOR) . "
444
                WHERE c_id = $course_id AND user_id IN (" . $user_ids . ")";
445
        Database::query($sql);
446
447
        // Erase user student publications (works) in the course - by André Boivin
448
449
        if (!empty($user_list)) {
450
            require_once api_get_path(SYS_CODE_PATH) . 'work/work.lib.php';
451
            foreach ($user_list as $userId) {
452
                // Getting all work from user
453
                $workList = getWorkPerUser($userId);
454
                if (!empty($workList)) {
455
                    foreach ($workList as $work) {
456
                        $work = $work['work'];
457
                        // Getting user results
458
                        if (!empty($work->user_results)) {
459
                            foreach ($work->user_results as $workSent) {
460
                                deleteWorkItem($workSent['id'], $course_info);
461
                            }
462
                        }
463
                    }
464
                }
465
            }
466
        }
467
468
        // Unsubscribe user from all blogs in the course.
469
        Database::query("DELETE FROM " . Database::get_course_table(TABLE_BLOGS_REL_USER) . " WHERE c_id = $course_id AND  user_id IN (" . $user_ids . ")");
470
        Database::query("DELETE FROM " . Database::get_course_table(TABLE_BLOGS_TASKS_REL_USER) . " WHERE c_id = $course_id AND  user_id IN (" . $user_ids . ")");
471
472
        // Deleting users in forum_notification and mailqueue course tables
473
        $sql = "DELETE FROM  " . Database::get_course_table(TABLE_FORUM_NOTIFICATION) . "
474
                WHERE c_id = $course_id AND user_id IN (" . $user_ids . ")";
475
        Database::query($sql);
476
477
        $sql = "DELETE FROM " . Database::get_course_table(TABLE_FORUM_MAIL_QUEUE) . "
478
                WHERE c_id = $course_id AND user_id IN (" . $user_ids . ")";
479
        Database::query($sql);
480
481
        // Unsubscribe user from the course.
482
        if (!empty($session_id)) {
483
484
            // Delete in table session_rel_course_rel_user
485
            $sql = "DELETE FROM " . Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER) . "
486
                    WHERE
487
                        session_id ='" . $session_id . "' AND
488
                        c_id = '" . $course_id . "' AND
489
                        user_id IN ($user_ids)";
490
            Database::query($sql);
491
492
            foreach ($user_list as $uid) {
493
                // check if a user is register in the session with other course
494
                $sql = "SELECT user_id FROM " . Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER) . "
495
                        WHERE session_id='$session_id' AND user_id='$uid'";
496
                $rs = Database::query($sql);
497
498
                if (Database::num_rows($rs) == 0) {
499
                    // Delete in table session_rel_user
500
                    $sql = "DELETE FROM " . Database::get_main_table(TABLE_MAIN_SESSION_USER) . "
501
                            WHERE
502
                                session_id ='" . $session_id . "' AND
503
                                user_id = '$uid' AND
504
                                relation_type<>" . SESSION_RELATION_TYPE_RRHH . "";
505
                    Database::query($sql);
506
                }
507
            }
508
509
            // Update the table session
510
            $sql = "SELECT COUNT(*) FROM " . Database::get_main_table(TABLE_MAIN_SESSION_USER) . "
511
                    WHERE session_id = '" . $session_id . "' AND relation_type <> " . SESSION_RELATION_TYPE_RRHH;
512
            $row = Database::fetch_array(Database::query($sql));
0 ignored issues
show
Bug introduced by
It seems like \Database::query($sql) can be null; however, fetch_array() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
513
            $count = $row[0];
514
            // number of users by session
515
            $sql = "UPDATE " . Database::get_main_table(TABLE_MAIN_SESSION) . " SET nbr_users = '$count'
516
                    WHERE id = '" . $session_id . "'";
517
            Database::query($sql);
518
519
            // Update the table session_rel_course
520
            $sql = "SELECT COUNT(*) FROM " . Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER) . "
521
                    WHERE session_id = '$session_id' AND c_id = '$course_id' AND status<>2";
522
            $row = Database::fetch_array(@Database::query($sql));
523
            $count = $row[0];
524
525
            // number of users by session and course
526
            $sql = "UPDATE " . Database::get_main_table(TABLE_MAIN_SESSION_COURSE) . "
527
                    SET nbr_users = '$count'
528
                    WHERE session_id = '$session_id' AND c_id = '$course_id'";
529
            Database::query($sql);
530
531
        } else {
532
            $sql = "DELETE FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER) . "
533
                    WHERE
534
                        user_id IN (" . $user_ids . ") AND
535
                        relation_type<>" . COURSE_RELATION_TYPE_RRHH . " AND
536
                        c_id = '" . $course_id . "'";
537
            Database::query($sql);
538
539
            // add event to system log
540
            $user_id = api_get_user_id();
541
542
            Event::addEvent(
543
                LOG_UNSUBSCRIBE_USER_FROM_COURSE,
544
                LOG_COURSE_CODE,
545
                $course_code,
546
                api_get_utc_datetime(),
0 ignored issues
show
Bug introduced by
It seems like api_get_utc_datetime() can also be of type object<DateTime>; however, Event::addEvent() does only seem to accept string|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
547
                $user_id
548
            );
549
550
            foreach ($user_list as $userId) {
551
                $userInfo = api_get_user_info($userId);
552
                Event::addEvent(
553
                    LOG_UNSUBSCRIBE_USER_FROM_COURSE,
554
                    LOG_USER_OBJECT,
555
                    $userInfo,
556
                    api_get_utc_datetime(),
0 ignored issues
show
Bug introduced by
It seems like api_get_utc_datetime() can also be of type object<DateTime>; however, Event::addEvent() does only seem to accept string|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
557
                    $user_id
558
                );
559
            }
560
        }
561
    }
562
563
    /**
564
     * Subscribe a user to a course. No checks are performed here to see if
565
     * course subscription is allowed.
566
     * @param   int     User ID
567
     * @param   string  Course code
568
     * @param   int     Status (STUDENT, COURSEMANAGER, COURSE_ADMIN, NORMAL_COURSE_MEMBER)
569
     * @return  bool    True on success, false on failure
570
     * @see add_user_to_course
571
     * @assert ('', '') === false
572
     */
573
    public static function subscribe_user(
574
        $user_id,
575
        $course_code,
576
        $status = STUDENT,
577
        $session_id = 0,
578
        $userCourseCategoryId = 0
579
    ) {
580
        if ($user_id != strval(intval($user_id))) {
581
            return false; //detected possible SQL injection
582
        }
583
584
        $course_code = Database::escape_string($course_code);
585
        $courseInfo = api_get_course_info($course_code);
586
        $courseId = $courseInfo['real_id'];
587
        $courseCode = $courseInfo['code'];
588
589
        $userCourseCategoryId = intval($userCourseCategoryId);
590
591
        if (empty($user_id) || empty ($course_code)) {
592
            return false;
593
        }
594
595
        if (!empty($session_id)) {
596
            $session_id = intval($session_id);
597
        } else {
598
            $session_id = api_get_session_id();
599
        }
600
601
        $status = ($status == STUDENT || $status == COURSEMANAGER) ? $status : STUDENT;
602
        //$role_id = ($status == COURSEMANAGER) ? COURSE_ADMIN : NORMAL_COURSE_MEMBER;
603
604
        // A preliminary check whether the user has bben already registered on the platform.
605
        if (Database::num_rows(Database::query(
0 ignored issues
show
Bug introduced by
It seems like \Database::query('SELECT...er_id = '{$user_id}' ") can be null; however, num_rows() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
606
                "SELECT status FROM " . Database::get_main_table(TABLE_MAIN_USER) . "
607
                WHERE user_id = '$user_id' ")) == 0
608
        ) {
609
            return false; // The user has not been registered to the platform.
610
        }
611
612
        // Check whether the user has not been already subscribed to the course.
613
614 View Code Duplication
        if (empty($session_id)) {
615
            if (Database::num_rows(Database::query("
0 ignored issues
show
Bug introduced by
It seems like \Database::query(' ... c_id = '{$courseId}'") can be null; however, num_rows() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
616
                    SELECT * FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER) . "
617
                    WHERE user_id = '$user_id' AND relation_type<>" . COURSE_RELATION_TYPE_RRHH . " AND c_id = '$courseId'")) > 0
618
            ) {
619
                // The user has been already subscribed to the course.
620
                return false;
621
            }
622
        }
623
624
        if (!empty($session_id)) {
625
            SessionManager::subscribe_users_to_session_course(array($user_id), $session_id, $courseCode);
626
        } else {
627
            CourseManager::add_user_to_course($user_id, $courseCode, $status);
628
629
            // Add event to the system log
630
            Event::addEvent(
631
                LOG_SUBSCRIBE_USER_TO_COURSE,
632
                LOG_COURSE_CODE,
633
                $course_code,
634
                api_get_utc_datetime(),
0 ignored issues
show
Bug introduced by
It seems like api_get_utc_datetime() can also be of type object<DateTime>; however, Event::addEvent() does only seem to accept string|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
635
                api_get_user_id()
636
            );
637
638
            $user_info = api_get_user_info($user_id);
639
            Event::addEvent(
640
                LOG_SUBSCRIBE_USER_TO_COURSE,
641
                LOG_USER_OBJECT,
642
                $user_info,
643
                api_get_utc_datetime(),
0 ignored issues
show
Bug introduced by
It seems like api_get_utc_datetime() can also be of type object<DateTime>; however, Event::addEvent() does only seem to accept string|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
644
                api_get_user_id()
645
            );
646
        }
647
648
        return true;
649
    }
650
651
    /**
652
     * Get the course id based on the original id and field name in the
653
     * extra fields. Returns 0 if course was not found
654
     *
655
     * @param string $original_course_id_value
656
     * @param string $original_course_id_name
657
     * @return int Course id
658
     *
659
     * @assert ('', '') === false
660
     */
661
    public static function get_course_code_from_original_id($original_course_id_value, $original_course_id_name)
662
    {
663
        $t_cfv = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
664
        $table_field = Database::get_main_table(TABLE_EXTRA_FIELD);
665
        $extraFieldType = EntityExtraField::COURSE_FIELD_TYPE;
666
667
        $original_course_id_value = Database::escape_string($original_course_id_value);
668
        $original_course_id_name = Database::escape_string($original_course_id_name);
669
670
        $sql = "SELECT item_id
671
                FROM $table_field cf
672
                INNER JOIN $t_cfv cfv
673
                ON cfv.field_id=cf.id
674
                WHERE
675
                    variable = '$original_course_id_name' AND
676
                    value = '$original_course_id_value' AND
677
                    cf.extra_field_type = $extraFieldType
678
                ";
679
        $res = Database::query($sql);
680
        $row = Database::fetch_object($res);
681
        if ($row) {
682
            return $row->item_id;
683
        } else {
684
            return 0;
685
        }
686
    }
687
688
    /**
689
     * Gets the course code from the course id. Returns null if course id was not found
690
     *
691
     * @param int $id Course id
692
     * @return string Course code
693
     * @assert ('') === false
694
     */
695
    public static function get_course_code_from_course_id($id)
696
    {
697
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
698
        $id = intval($id);
699
        $sql = "SELECT code FROM $table WHERE id = '$id' ";
700
        $res = Database::query($sql);
701
        $row = Database::fetch_object($res);
702
        if ($row) {
703
            return $row->code;
704
        } else {
705
            return null;
706
        }
707
    }
708
709
    /**
710
     * Subscribe a user $user_id to a course defined by $courseCode.
711
     * @author Hugues Peeters
712
     * @author Roan Embrechts
713
     *
714
     * @param  int $user_id the id of the user
715
     * @param  string $courseCode the course code
716
     * @param  int $status (optional) The user's status in the course
717
     * @param  int The user category in which this subscription will be classified
718
     *
719
     * @return false|string true if subscription succeeds, boolean false otherwise.
720
     * @assert ('', '') === false
721
     */
722
    public static function add_user_to_course(
723
        $user_id,
724
        $courseCode,
725
        $status = STUDENT,
726
        $userCourseCategoryId = 0
727
    ) {
728
        $debug = false;
729
        $user_table = Database::get_main_table(TABLE_MAIN_USER);
730
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
731
        $course_user_table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
732
733
        $status = ($status == STUDENT || $status == COURSEMANAGER) ? $status : STUDENT;
734 View Code Duplication
        if (empty($user_id) || empty($courseCode) || ($user_id != strval(intval($user_id)))) {
735
            return false;
736
        }
737
738
        $courseCode = Database::escape_string($courseCode);
739
        $courseInfo = api_get_course_info($courseCode);
740
        $courseId = $courseInfo['real_id'];
741
742
        // Check in advance whether the user has already been registered on the platform.
743
        $sql = "SELECT status FROM " . $user_table . " WHERE user_id = $user_id ";
744 View Code Duplication
        if (Database::num_rows(Database::query($sql)) == 0) {
0 ignored issues
show
Bug introduced by
It seems like \Database::query($sql) can be null; however, num_rows() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
745
            if ($debug) {
746
                error_log('The user has not been registered to the platform');
747
            }
748
            return false; // The user has not been registered to the platform.
749
        }
750
751
        // Check whether the user has already been subscribed to this course.
752
        $sql = "SELECT * FROM $course_user_table
753
                WHERE
754
                    user_id = $user_id AND
755
                    relation_type <> " . COURSE_RELATION_TYPE_RRHH . " AND
756
                    c_id = $courseId";
757 View Code Duplication
        if (Database::num_rows(Database::query($sql)) > 0) {
0 ignored issues
show
Bug introduced by
It seems like \Database::query($sql) can be null; however, num_rows() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
758
            if ($debug) {
759
                error_log('The user has been already subscribed to the course');
760
            }
761
            return false; // The user has been subscribed to the course.
762
        }
763
764
        if (!api_is_course_admin()) {
765
            // Check in advance whether subscription is allowed or not for this course.
766
            $sql = "SELECT code, visibility FROM $course_table
767
                    WHERE id = $courseId AND subscribe = '" . SUBSCRIBE_NOT_ALLOWED . "'";
768 View Code Duplication
            if (Database::num_rows(Database::query($sql)) > 0) {
0 ignored issues
show
Bug introduced by
It seems like \Database::query($sql) can be null; however, num_rows() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
769
                if ($debug) {
770
                    error_log('Subscription is not allowed for this course');
771
                }
772
                return false; // Subscription is not allowed for this course.
773
            }
774
        }
775
776
        // Ok, subscribe the user.
777
        $max_sort = api_max_sort_value('0', $user_id);
778
        $params = [
779
            'c_id' => $courseId,
780
            'user_id' => $user_id,
781
            'status' => $status,
782
            'sort' => $max_sort + 1,
783
            'relation_type' => 0,
784
            'user_course_cat' => $userCourseCategoryId
785
        ];
786
        $insertId = Database::insert($course_user_table, $params);
787
788
        return $insertId;
789
    }
790
791
    /**
792
     * Add the user $userId visibility to the course $courseCode in the catalogue.
793
     * @author David Nos (https://github.com/dnos)
794
     *
795
     * @param  int $userId the id of the user
796
     * @param  string $courseCode the course code
797
     * @param  int $visible (optional) The course visibility in the catalogue to the user (1=visible, 0=invisible)
798
     *
799
     * @return boolean true if added succesfully, false otherwise.
800
     */
801
    public static function addUserVisibilityToCourseInCatalogue($userId, $courseCode, $visible = 1)
802
    {
803
        $debug = false;
804
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
805
        $courseUserTable = Database::get_main_table(TABLE_MAIN_COURSE_CATALOGUE_USER);
806
807 View Code Duplication
        if (empty($userId) || empty($courseCode) || ($userId != strval(intval($userId)))) {
808
            return false;
809
        }
810
811
        $courseCode = Database::escape_string($courseCode);
812
        $courseInfo = api_get_course_info($courseCode);
813
        $courseId = $courseInfo['real_id'];
814
815
        // Check in advance whether the user has already been registered on the platform.
816
        $sql = "SELECT status FROM " . $userTable . " WHERE user_id = $userId ";
817
        if (Database::num_rows(Database::query($sql)) == 0) {
0 ignored issues
show
Bug introduced by
It seems like \Database::query($sql) can be null; however, num_rows() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
818
            if ($debug) {
819
                error_log('The user has not been registered to the platform');
820
            }
821
            return false; // The user has not been registered to the platform.
822
        }
823
824
        // Check whether the user has already been registered to the course visibility in the catalogue.
825
        $sql = "SELECT * FROM $courseUserTable
826
                WHERE
827
                    user_id = $userId AND
828
                    visible = " . $visible . " AND
829
                    c_id = $courseId";
830
        if (Database::num_rows(Database::query($sql)) > 0) {
0 ignored issues
show
Bug introduced by
It seems like \Database::query($sql) can be null; however, num_rows() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
831
            if ($debug) {
832
                error_log('The user has been already registered to the course visibility in the catalogue');
833
            }
834
            return true; // The visibility of the user to the course in the catalogue does already exist.
835
        }
836
837
        // Register the user visibility to course in catalogue.
838
        $params = [
839
            'user_id' => $userId,
840
            'c_id' => $courseId,
841
            'visible' => $visible
842
        ];
843
        $insertId = Database::insert($courseUserTable, $params);
844
845
        return $insertId;
846
    }
847
848
849
    /**
850
     * Remove the user $userId visibility to the course $courseCode in the catalogue.
851
     * @author David Nos (https://github.com/dnos)
852
     *
853
     * @param  int $userId the id of the user
854
     * @param  string $courseCode the course code
855
     * @param  int $visible (optional) The course visibility in the catalogue to the user (1=visible, 0=invisible)
856
     *
857
     * @return boolean true if removed succesfully or register not found, false otherwise.
858
     */
859
    public static function removeUserVisibilityToCourseInCatalogue($userId, $courseCode, $visible = 1)
860
    {
861
        $courseUserTable = Database::get_main_table(TABLE_MAIN_COURSE_CATALOGUE_USER);
862
863 View Code Duplication
        if (empty($userId) || empty($courseCode) || ($userId != strval(intval($userId)))) {
864
            return false;
865
        }
866
867
        $courseCode = Database::escape_string($courseCode);
868
        $courseInfo = api_get_course_info($courseCode);
869
        $courseId = $courseInfo['real_id'];
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) {
0 ignored issues
show
Bug introduced by
It seems like \Database::query($sql) can be null; however, num_rows() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
878
            $cond = array(
879
                'user_id = ? AND c_id = ? AND visible = ? ' => array(
880
                    $userId,
881
                    $courseId,
882
                    $visible
883
                )
884
            );
885
            return Database::delete($courseUserTable, $cond);
886
        } else {
887
            return true; // Register does not exist
888
        }
889
    }
890
891
    /**
892
     * @return boolean if there already are one or more courses
893
     *  with the same code OR visual_code (visualcode), false otherwise
894
     */
895
    public static function course_code_exists($wanted_course_code)
896
    {
897
        $wanted_course_code = Database::escape_string($wanted_course_code);
898
        $sql = "SELECT COUNT(*) as number
899
                FROM " . Database::get_main_table(TABLE_MAIN_COURSE) . "
900
                WHERE code = '$wanted_course_code' OR visual_code = '$wanted_course_code'";
901
        $result = Database::fetch_array(Database::query($sql));
0 ignored issues
show
Bug introduced by
It seems like \Database::query($sql) can be null; however, fetch_array() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
902
903
        return $result['number'] > 0;
904
    }
905
906
    /**
907
     * Get course list as coach
908
     *
909
     * @param int $user_id
910
     * @param bool $include_courses_in_sessions
911
     * @return array Course list
912
     *
913
     **/
914
    public static function get_course_list_as_coach($user_id, $include_courses_in_sessions = false)
915
    {
916
        // 1. Getting courses as teacher (No session)
917
        $courses_temp = CourseManager::get_course_list_of_user_as_course_admin($user_id);
918
        $courseList = array();
919
920
        if (!empty($courses_temp)) {
921
            foreach ($courses_temp as $course_item) {
922
                $courseList[0][$course_item['code']] = $course_item['code'];
923
            }
924
        }
925
926
        //2. Include courses in sessions
927
        if ($include_courses_in_sessions) {
928
            $sessions = Tracking::get_sessions_coached_by_user($user_id);
929
930
            if (!empty($sessions)) {
931
                foreach ($sessions as $session_item) {
932
                    $courses = Tracking:: get_courses_followed_by_coach($user_id, $session_item['id']);
933
                    if (is_array($courses)) {
934
                        foreach ($courses as $course_item) {
935
                            $courseList[$session_item['id']][$course_item] = $course_item;
936
                        }
937
                    }
938
                }
939
            }
940
        }
941
942
        return $courseList;
943
    }
944
945
    /**
946
     * @param int $user_id
947
     * @param bool $include_sessions
948
     * @return array
949
     */
950
    public static function get_user_list_from_courses_as_coach($user_id, $include_sessions = true)
951
    {
952
        $students_in_courses = array();
953
        $sessions = CourseManager::get_course_list_as_coach($user_id, true);
954
955
        if (!empty($sessions)) {
956
            foreach ($sessions as $session_id => $courses) {
957
                if (!$include_sessions) {
958
                    if (!empty($session_id)) {
959
                        continue;
960
                    }
961
                }
962
                if (empty($session_id)) {
963
                    foreach ($courses as $course_code) {
964
                        $students_in_course = CourseManager::get_user_list_from_course_code($course_code);
965
966
                        foreach ($students_in_course as $user_item) {
0 ignored issues
show
Bug introduced by
The expression $students_in_course of type array|integer is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
967
                            //Only students
968
                            if ($user_item['status_rel'] == STUDENT) {
969
                                $students_in_courses[$user_item['user_id']] = $user_item['user_id'];
970
                            }
971
                        }
972
                    }
973
                } else {
974
                    $students_in_course = SessionManager::get_users_by_session($session_id, '0');
975
                    if (is_array($students_in_course)) {
976
                        foreach ($students_in_course as $user_item) {
977
                            $students_in_courses[$user_item['user_id']] = $user_item['user_id'];
978
                        }
979
                    }
980
                }
981
            }
982
        }
983
984
        $students = Tracking:: get_student_followed_by_coach($user_id);
985
        if (!empty($students_in_courses)) {
986
            if (!empty($students)) {
987
                $students = array_merge($students, $students_in_courses);
988
            } else {
989
                $students = $students_in_courses;
990
            }
991
        }
992
993
        if (!empty($students)) {
994
            $students = array_unique($students);
995
        }
996
        return $students;
997
    }
998
999
    /**
1000
     * @param int $user_id
1001
     * @param string $startsWith Optional
1002
     * @return array An array with the course info of all the courses (real and virtual)
1003
     * of which the current user is course admin.
1004
     */
1005
    public static function get_course_list_of_user_as_course_admin($user_id, $startsWith = null)
1006
    {
1007
        if ($user_id != strval(intval($user_id))) {
1008
            return array();
1009
        }
1010
1011
        // Definitions database tables and variables
1012
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
1013
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1014
        $user_id = intval($user_id);
1015
        $data = array();
1016
1017
        $sql = "SELECT
1018
                    course.code,
1019
                    course.title,
1020
                    course.id,
1021
                    course.id as real_id,
1022
                    course.category_code
1023
                FROM $tbl_course_user as course_rel_user
1024
                INNER JOIN $tbl_course as course
1025
                ON course.id = course_rel_user.c_id
1026
                WHERE
1027
                    course_rel_user.user_id='$user_id' AND
1028
                    course_rel_user.status='1'
1029
        ";
1030
1031 View Code Duplication
        if (api_get_multiple_access_url()) {
1032
            $tbl_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
1033
            $access_url_id = api_get_current_access_url_id();
1034
            if ($access_url_id != -1) {
1035
                $sql = "
1036
                    SELECT
1037
                        course.code,
1038
                        course.title,
1039
                        course.id,
1040
                        course.id as real_id
1041
                    FROM $tbl_course_user as course_rel_user
1042
                    INNER JOIN $tbl_course as course
1043
                    ON course.id = course_rel_user.c_id
1044
                    INNER JOIN $tbl_course_rel_access_url course_rel_url
1045
                    ON (course_rel_url.c_id = course.id)
1046
                    WHERE
1047
                        access_url_id = $access_url_id  AND
1048
                        course_rel_user.user_id = '$user_id' AND
1049
                        course_rel_user.status = '1'
1050
                ";
1051
            }
1052
        }
1053
1054
        if (!empty($startsWith)) {
1055
            $startsWith = Database::escape_string($startsWith);
1056
1057
            $sql .= " AND (course.title LIKE '$startsWith%' OR course.code LIKE '$startsWith%')";
1058
        }
1059
1060
        $sql .= ' ORDER BY course.title';
1061
1062
        $result_nb_cours = Database::query($sql);
1063
        if (Database::num_rows($result_nb_cours) > 0) {
1064
            while ($row = Database::fetch_array($result_nb_cours, 'ASSOC')) {
1065
                $data[$row['id']] = $row;
1066
            }
1067
        }
1068
1069
        return $data;
1070
    }
1071
1072
    /**
1073
     * @param int $userId
1074
     * @param array $courseInfo
1075
     * @return boolean|null
1076
     */
1077
    public static function isUserSubscribedInCourseAsDrh($userId, $courseInfo)
1078
    {
1079
        $userId = intval($userId);
1080
1081
        if (!api_is_drh()) {
1082
            return false;
1083
        }
1084
1085
        if (empty($courseInfo) || empty($userId)) {
1086
            return false;
1087
        }
1088
1089
        $courseId = intval($courseInfo['real_id']);
1090
        $table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1091
1092
        $sql = "SELECT * FROM $table
1093
                WHERE
1094
                    user_id = $userId AND
1095
                    relation_type = " . COURSE_RELATION_TYPE_RRHH . " AND
1096
                    c_id = $courseId";
1097
1098
        $result = Database::fetch_array(Database::query($sql));
0 ignored issues
show
Bug introduced by
It seems like \Database::query($sql) can be null; however, fetch_array() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
1099
1100
        if (!empty($result)) {
1101
            // The user has been registered in this course.
1102
            return true;
1103
        }
1104
    }
1105
1106
    /**
1107
     * Check if user is subscribed inside a course
1108
     * @param  int $user_id
1109
     * @param  string $course_code , if this parameter is null, it'll check for all courses
1110
     * @param  bool $in_a_session True for checking inside sessions too, by default is not checked
1111
     * @return bool   $session_id true if the user is registered in the course, false otherwise
1112
     */
1113
    public static function is_user_subscribed_in_course(
1114
        $user_id,
1115
        $course_code = null,
1116
        $in_a_session = false,
1117
        $session_id = null
1118
    ) {
1119
        $user_id = intval($user_id);
1120
1121
        if (empty($session_id)) {
1122
            $session_id = api_get_session_id();
1123
        } else {
1124
            $session_id = intval($session_id);
1125
        }
1126
1127
        $condition_course = '';
1128
        if (isset($course_code)) {
1129
            $courseInfo = api_get_course_info($course_code);
1130
            if (empty($courseInfo)) {
1131
                return false;
1132
            }
1133
            $courseId = $courseInfo['real_id'];
1134
            $condition_course = ' AND c_id = ' . $courseId;
1135
        }
1136
1137
        $sql = "SELECT * FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER) . "
1138
                WHERE
1139
                    user_id = $user_id AND
1140
                    relation_type<>" . COURSE_RELATION_TYPE_RRHH . "
1141
                    $condition_course ";
1142
1143
        $result = Database::fetch_array(Database::query($sql));
0 ignored issues
show
Bug introduced by
It seems like \Database::query($sql) can be null; however, fetch_array() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
1144
1145
        if (!empty($result)) {
1146
            // The user has been registered in this course.
1147
            return true;
1148
        }
1149
1150
        if (!$in_a_session) {
1151
            // The user has not been registered in this course.
1152
            return false;
1153
        }
1154
1155
        $tableSessionCourseUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
1156
        $sql = 'SELECT 1 FROM ' . $tableSessionCourseUser .
1157
            ' WHERE user_id = ' . $user_id . ' ' . $condition_course;
1158
        if (Database::num_rows(Database::query($sql)) > 0) {
0 ignored issues
show
Bug introduced by
It seems like \Database::query($sql) can be null; however, num_rows() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
1159
            return true;
1160
        }
1161
1162
        $sql = 'SELECT 1 FROM ' . $tableSessionCourseUser .
1163
            ' WHERE user_id = ' . $user_id . ' AND status=2 ' . $condition_course;
1164
        if (Database::num_rows(Database::query($sql)) > 0) {
0 ignored issues
show
Bug introduced by
It seems like \Database::query($sql) can be null; however, num_rows() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
1165
            return true;
1166
        }
1167
1168
        $sql = 'SELECT 1 FROM ' . Database::get_main_table(TABLE_MAIN_SESSION) .
1169
            ' WHERE id = ' . $session_id . ' AND id_coach=' . $user_id;
1170
1171
        if (Database::num_rows(Database::query($sql)) > 0) {
0 ignored issues
show
Bug introduced by
It seems like \Database::query($sql) can be null; however, num_rows() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
1172
            return true;
1173
        }
1174
1175
        return false;
1176
    }
1177
1178
    /**
1179
     *    Is the user a teacher in the given course?
1180
     *
1181
     * @param integer $user_id , the id (int) of the user
1182
     * @param $course_code , the course code
1183
     *
1184
     * @return boolean if the user is a teacher in the course, false otherwise
1185
     */
1186
    public static function is_course_teacher($user_id, $course_code)
1187
    {
1188
        if ($user_id != strval(intval($user_id))) {
1189
            return false;
1190
        }
1191
1192
        $courseInfo = api_get_course_info($course_code);
1193
        $courseId = $courseInfo['real_id'];
1194
1195
        $result = Database::query(
1196
            'SELECT status FROM ' . Database::get_main_table(TABLE_MAIN_COURSE_USER) .
1197
            ' WHERE c_id = ' . $courseId . ' AND user_id = ' . $user_id . ''
1198
        );
1199
1200
        if (Database::num_rows($result) > 0) {
1201
            return Database::result($result, 0, 'status') == 1;
1202
        }
1203
1204
        return false;
1205
    }
1206
1207
    /**
1208
     *    Is the user subscribed in the real course or linked courses?
1209
     *
1210
     * @param int the id of the user
1211
     * @param int $courseId
1212
     * @deprecated linked_courses definition doesn't exists
1213
     * @return boolean if the user is registered in the real course or linked courses, false otherwise
1214
     */
1215
    public static function is_user_subscribed_in_real_or_linked_course($user_id, $courseId, $session_id = '')
1216
    {
1217
        if ($user_id != strval(intval($user_id))) {
1218
            return false;
1219
        }
1220
1221
        $courseId = intval($courseId);
1222
1223
        if ($session_id == '') {
1224
            $result = Database::fetch_array(
1225
                Database::query(
0 ignored issues
show
Bug introduced by
It seems like \Database::query('SELECT...e.id = '{$courseId}')") can be null; however, fetch_array() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
1226
                    "SELECT *
1227
                    FROM " . Database::get_main_table(TABLE_MAIN_COURSE) . " course
1228
                    LEFT JOIN " . Database::get_main_table(TABLE_MAIN_COURSE_USER) . " course_user
1229
                    ON course.id = course_user.c_id
1230
                    WHERE
1231
                        course_user.user_id = '$user_id' AND
1232
                        course_user.relation_type<>" . COURSE_RELATION_TYPE_RRHH . " AND
1233
                        ( course.id = '$courseId')"
1234
                )
1235
            );
1236
            return !empty($result);
1237
        }
1238
1239
        $session_id = intval($session_id);
1240
1241
        // From here we trust session id.
1242
        // Is he/she subscribed to the session's course?
1243
1244
        // A user?
1245 View Code Duplication
        if (Database::num_rows(Database::query("SELECT user_id
0 ignored issues
show
Bug introduced by
It seems like \Database::query('SELECT...user_id ='{$user_id}'") can be null; however, num_rows() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
1246
                FROM " . Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER) . "
1247
                WHERE session_id='" . $session_id . "'
1248
                AND user_id ='$user_id'"))
1249
        ) {
1250
            return true;
1251
        }
1252
1253
        // A course coach?
1254 View Code Duplication
        if (Database::num_rows(Database::query("SELECT user_id
0 ignored issues
show
Bug introduced by
It seems like \Database::query('SELECT...D c_id ='{$courseId}'") can be null; however, num_rows() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
1255
                FROM " . Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER) . "
1256
                WHERE session_id='" . $session_id . "'
1257
                AND user_id = '$user_id' AND status = 2
1258
                AND c_id ='$courseId'"))
1259
        ) {
1260
            return true;
1261
        }
1262
1263
        // A session coach?
1264 View Code Duplication
        if (Database::num_rows(Database::query("SELECT id_coach
0 ignored issues
show
Bug introduced by
It seems like \Database::query('SELECT...id_coach='{$user_id}'") can be null; however, num_rows() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
1265
                FROM " . Database::get_main_table(TABLE_MAIN_SESSION) . " AS session
1266
                WHERE session.id='" . $session_id . "'
1267
                AND id_coach='$user_id'"))
1268
        ) {
1269
            return true;
1270
        }
1271
1272
        return false;
1273
    }
1274
1275
    /**
1276
     * Return user info array of all users registered in a course
1277
     * This only returns the users that are registered in this actual course, not linked courses.
1278
     * @param string $course_code
1279
     * @param int $session_id
1280
     * @param string $limit
1281
     * @param string $order_by the field to order the users by.
1282
     * Valid values are 'lastname', 'firstname', 'username', 'email', 'official_code' OR a part of a SQL statement
1283
     * that starts with ORDER BY ...
1284
     * @param integer|null $filter_by_status if using the session_id: 0 or 2 (student, coach),
1285
     * if using session_id = 0 STUDENT or COURSEMANAGER
1286
     * @param boolean|null $return_count
1287
     * @param bool $add_reports
1288
     * @param bool $resumed_report
1289
     * @param array $extra_field
1290
     * @param array $courseCodeList
1291
     * @param array $userIdList
1292
     * @param string $filterByActive
1293
     * @param array $sessionIdList
1294
     * @return array|int
1295
     */
1296
    public static function get_user_list_from_course_code(
1297
        $course_code = null,
1298
        $session_id = 0,
1299
        $limit = null,
1300
        $order_by = null,
1301
        $filter_by_status = null,
1302
        $return_count = null,
1303
        $add_reports = false,
1304
        $resumed_report = false,
1305
        $extra_field = array(),
1306
        $courseCodeList = array(),
1307
        $userIdList = array(),
1308
        $filterByActive = null,
1309
        $sessionIdList = array()
1310
    ) {
1311
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1312
        $sessionTable = Database::get_main_table(TABLE_MAIN_SESSION);
1313
1314
        $session_id = intval($session_id);
1315
        $course_code = Database::escape_string($course_code);
1316
        $courseInfo = api_get_course_info($course_code);
1317
        $courseId = 0;
1318
        if (!empty($courseInfo)) {
1319
            $courseId = $courseInfo['real_id'];
1320
        }
1321
1322
        $where = array();
1323
        if (empty($order_by)) {
1324
            $order_by = 'user.lastname, user.firstname';
1325
            if (api_is_western_name_order()) {
1326
                $order_by = 'user.firstname, user.lastname';
1327
            }
1328
        }
1329
1330
        // if the $order_by does not contain 'ORDER BY'
1331
        // we have to check if it is a valid field that can be sorted on
1332
        if (!strstr($order_by, 'ORDER BY')) {
1333
            if (!empty($order_by)) {
1334
                $order_by = 'ORDER BY ' . $order_by;
1335
            } else {
1336
                $order_by = '';
1337
            }
1338
        }
1339
1340
        $filter_by_status_condition = null;
1341
1342
        if (!empty($session_id) || !empty($sessionIdList)) {
1343
            $sql = 'SELECT DISTINCT
1344
                        user.user_id,
1345
                        user.email,
1346
                        session_course_user.status as status_session,
1347
                        session_id,
1348
                        user.*,
1349
                        course.*,
1350
                        session.name as session_name
1351
                    ';
1352
            if ($return_count) {
1353
                $sql = " SELECT COUNT(user.user_id) as count";
1354
            }
1355
1356
            $sessionCondition = " session_course_user.session_id = $session_id";
1357
            if (!empty($sessionIdList)) {
1358
                $sessionIdListTostring = implode("','", array_map('intval', $sessionIdList));
1359
                $sessionCondition = " session_course_user.session_id IN ('$sessionIdListTostring') ";
1360
            }
1361
1362
            $courseCondition = " course.id = $courseId";
1363
            if (!empty($courseCodeList)) {
1364
                $courseCodeListForSession = array_map(array('Database', 'escape_string'), $courseCodeList);
1365
                $courseCodeListForSession = implode('","', $courseCodeListForSession);
1366
                $courseCondition = ' course.code IN ("' . $courseCodeListForSession . '")  ';
1367
            }
1368
1369
            $sql .= ' FROM ' . Database::get_main_table(TABLE_MAIN_USER) . ' as user ';
1370
            $sql .= " LEFT JOIN ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER) . " as session_course_user
1371
                      ON
1372
                        user.id = session_course_user.user_id AND
1373
                        $sessionCondition
1374
                        INNER JOIN $course_table course 
1375
                        ON session_course_user.c_id = course.id AND
1376
                        $courseCondition
1377
                        INNER JOIN $sessionTable session 
1378
                        ON session_course_user.session_id = session.id
1379
                   ";
1380
            $where[] = ' session_course_user.c_id IS NOT NULL ';
1381
1382
            // 2 = coach
1383
            // 0 = student
1384
            if (isset($filter_by_status)) {
1385
                $filter_by_status = intval($filter_by_status);
1386
                $filter_by_status_condition = " session_course_user.status = $filter_by_status AND ";
1387
            }
1388
        } else {
1389
            if ($return_count) {
1390
                $sql = " SELECT COUNT(*) as count";
1391
            } else {
1392
                if (empty($course_code)) {
1393
                    $sql = 'SELECT DISTINCT
1394
                                course.title,
1395
                                course.code,
1396
                                course_rel_user.status as status_rel,
1397
                                user.id as user_id,
1398
                                user.email,
1399
                                course_rel_user.is_tutor,
1400
                                user.*  ';
1401
                } else {
1402
                    $sql = 'SELECT DISTINCT
1403
                                course_rel_user.status as status_rel,
1404
                                user.id as user_id,
1405
                                user.email,
1406
                                course_rel_user.is_tutor,
1407
                                user.*  ';
1408
                }
1409
            }
1410
1411
            $sql .= ' FROM ' . Database::get_main_table(TABLE_MAIN_USER) . ' as user '
1412
                  . ' LEFT JOIN ' . Database::get_main_table(TABLE_MAIN_COURSE_USER) . ' as course_rel_user
1413
                      ON 
1414
                        user.id = course_rel_user.user_id AND
1415
                        course_rel_user.relation_type <> ' . COURSE_RELATION_TYPE_RRHH . '  '
1416
                  . " INNER JOIN $course_table course ON course_rel_user.c_id = course.id ";
1417
1418
            if (!empty($course_code)) {
1419
                $sql .= ' AND course_rel_user.c_id = "' . $courseId . '"';
1420
            }
1421
            $where[] = ' course_rel_user.c_id IS NOT NULL ';
1422
1423
            if (isset($filter_by_status) && is_numeric($filter_by_status)) {
1424
                $filter_by_status = intval($filter_by_status);
1425
                $filter_by_status_condition = " course_rel_user.status = $filter_by_status AND ";
1426
            }
1427
        }
1428
1429
        $multiple_access_url = api_get_multiple_access_url();
1430
        if ($multiple_access_url) {
1431
            $sql .= ' LEFT JOIN ' . Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER) . ' au
1432
                      ON (au.user_id = user.id) ';
1433
        }
1434
1435
        $extraFieldWasAdded = false;
1436
        if ($return_count && $resumed_report) {
1437
            foreach ($extra_field as $extraField) {
1438
                $extraFieldInfo = UserManager::get_extra_field_information_by_name($extraField);
1439
                if (!empty($extraFieldInfo)) {
1440
                    $fieldValuesTable = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
1441
                    $sql .= ' LEFT JOIN '.$fieldValuesTable.' as ufv
1442
                            ON (
1443
                                user.id = ufv.item_id AND
1444
                                (field_id = '.$extraFieldInfo['id'].' OR field_id IS NULL)
1445
                            )';
1446
                    $extraFieldWasAdded = true;
1447
                }
1448
            }
1449
        }
1450
1451
        $sql .= ' WHERE ' . $filter_by_status_condition . ' ' . implode(' OR ', $where);
1452
1453
        if ($multiple_access_url) {
1454
            $current_access_url_id = api_get_current_access_url_id();
1455
            $sql .= " AND (access_url_id =  $current_access_url_id ) ";
1456
        }
1457
1458
        if ($return_count && $resumed_report && $extraFieldWasAdded) {
1459
            $sql .= ' AND field_id IS NOT NULL GROUP BY value ';
1460
        }
1461
1462
        if (!empty($courseCodeList)) {
1463
            $courseCodeList = array_map(array('Database', 'escape_string'), $courseCodeList);
1464
            $courseCodeList = implode('","', $courseCodeList);
1465
            if (empty($sessionIdList)) {
1466
                $sql .= ' AND course.code IN ("'.$courseCodeList.'")';
1467
            }
1468
        }
1469
1470 View Code Duplication
        if (!empty($userIdList)) {
1471
            $userIdList = array_map('intval', $userIdList);
1472
            $userIdList = implode('","', $userIdList);
1473
            $sql .= ' AND user.id IN ("' . $userIdList . '")';
1474
        }
1475
1476
        if (isset($filterByActive)) {
1477
            $filterByActive = intval($filterByActive);
1478
            $sql .= ' AND user.active = ' . $filterByActive;
1479
        }
1480
1481
        $sql .= ' ' . $order_by . ' ' . $limit;
1482
1483
        $rs = Database::query($sql);
1484
        $users = array();
1485
1486
        $extra_fields = UserManager::get_extra_fields(0, 100, null, null, true, true);
1487
1488
        $counter = 1;
1489
        $count_rows = Database::num_rows($rs);
1490
1491
        if ($return_count && $resumed_report) {
1492
            return $count_rows;
1493
        }
1494
1495
        $table_user_field_value = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
1496
        $tableExtraField = Database::get_main_table(TABLE_EXTRA_FIELD);
1497
        if ($count_rows) {
1498
            while ($user = Database::fetch_array($rs)) {
1499
                if ($return_count) {
1500
                    return $user['count'];
1501
                }
1502
                $report_info = array();
1503
1504
                $user_info = $user;
1505
                $user_info['status'] = $user['status'];
1506
1507
                if (isset($user['is_tutor'])) {
1508
                    $user_info['is_tutor'] = $user['is_tutor'];
1509
                }
1510
1511
                if (!empty($session_id)) {
1512
                    $user_info['status_session'] = $user['status_session'];
1513
                }
1514
1515
                $sessionId = isset($user['session_id']) ? $user['session_id'] : 0;
1516
                $course_code = isset($user['code']) ? $user['code'] : null;
1517
1518
                if ($add_reports) {
1519
                    if ($resumed_report) {
1520
                        $extra = array();
1521
1522
                        if (!empty($extra_fields)) {
1523
                            foreach ($extra_fields as $extra) {
1524
                                if (in_array($extra['1'], $extra_field)) {
1525
                                    $user_data = UserManager::get_extra_user_data_by_field(
1526
                                        $user['user_id'],
1527
                                        $extra['1']
1528
                                    );
1529
                                    break;
1530
                                }
1531
                            }
1532
                        }
1533
1534
                        $row_key = '-1';
1535
                        $name = '-';
1536
1537
                        if (!empty($extra)) {
1538
                            if (!empty($user_data[$extra['1']])) {
1539
                                $row_key = $user_data[$extra['1']];
1540
                                $name = $user_data[$extra['1']];
1541
                                $users[$row_key]['extra_'.$extra['1']] = $name;
1542
                            }
1543
                        }
1544
1545
                        $users[$row_key]['training_hours'] += Tracking::get_time_spent_on_the_course(
1546
                            $user['user_id'],
1547
                            $courseId,
1548
                            $sessionId
1549
                        );
1550
1551
                        $users[$row_key]['count_users'] += $counter;
1552
1553
                        $registered_users_with_extra_field = CourseManager::getCountRegisteredUsersWithCourseExtraField(
1554
                            $name,
1555
                            $tableExtraField,
1556
                            $table_user_field_value
1557
                        );
1558
1559
                        $users[$row_key]['count_users_registered'] = $registered_users_with_extra_field;
1560
                        $users[$row_key]['average_hours_per_user'] = $users[$row_key]['training_hours'] / $users[$row_key]['count_users'];
1561
1562
                        $category = Category:: load(
1563
                            null,
1564
                            null,
1565
                            $course_code,
1566
                            null,
1567
                            null,
1568
                            $sessionId
1569
                        );
1570
1571
                        if (!isset($users[$row_key]['count_certificates'])) {
1572
                            $users[$row_key]['count_certificates'] = 0;
1573
                        }
1574
1575
                        if (isset($category[0]) && $category[0]->is_certificate_available($user['user_id'])) {
1576
                            $users[$row_key]['count_certificates']++;
1577
                        }
1578
1579
                        foreach ($extra_fields as $extra) {
1580
                            if ($extra['1'] == 'ruc') {
1581
                                continue;
1582
                            }
1583
1584
                            if (!isset($users[$row_key][$extra['1']])) {
1585
                                $user_data = UserManager::get_extra_user_data_by_field($user['user_id'], $extra['1']);
1586
                                if (!empty($user_data[$extra['1']])) {
1587
                                    $users[$row_key][$extra['1']] = $user_data[$extra['1']];
1588
                                }
1589
                            }
1590
                        }
1591
                    } else {
1592
                        $sessionName = !empty($sessionId) ? ' - '.$user['session_name'] : '';
1593
                        $report_info['course'] = $user['title'].$sessionName;
1594
                        $report_info['user'] = api_get_person_name($user['firstname'], $user['lastname']);
1595
                        $report_info['email'] = $user['email'];
1596
                        $report_info['time'] = api_time_to_hms(
1597
                            Tracking::get_time_spent_on_the_course(
1598
                                $user['user_id'],
1599
                                $courseId,
1600
                                $sessionId
1601
                            )
1602
                        );
1603
1604
                        $category = Category:: load(
1605
                            null,
1606
                            null,
1607
                            $course_code,
1608
                            null,
1609
                            null,
1610
                            $sessionId
1611
                        );
1612
1613
                        $report_info['certificate'] = Display::label(get_lang('No'));
1614
                        if (isset($category[0]) && $category[0]->is_certificate_available($user['user_id'])) {
1615
                            $report_info['certificate'] = Display::label(get_lang('Yes'), 'success');
1616
                        }
1617
1618
                        $progress = intval(
1619
                            Tracking::get_avg_student_progress(
1620
                                $user['user_id'],
1621
                                $course_code,
1622
                                array(),
1623
                                $sessionId
1624
                            )
1625
                        );
1626
                        $report_info['progress_100'] = $progress == 100 ? Display::label(get_lang('Yes'), 'success') : Display::label(get_lang('No'));
1627
                        $report_info['progress'] = $progress . "%";
1628
1629
                        foreach ($extra_fields as $extra) {
1630
                            $user_data = UserManager::get_extra_user_data_by_field($user['user_id'], $extra['1']);
1631
                            $report_info[$extra['1']] = $user_data[$extra['1']];
1632
                        }
1633
                        $report_info['user_id'] = $user['user_id'];
1634
                        $users[] = $report_info;
1635
                    }
1636
                } else {
1637
                    $users[$user['user_id']] = $user_info;
1638
                }
1639
            }
1640
        }
1641
1642
        return $users;
1643
    }
1644
1645
    /**
1646
     * @param bool $resumed_report
1647
     * @param array $extra_field
1648
     * @param array $courseCodeList
1649
     * @param array $userIdList
1650
     * @param array $sessionIdList
1651
     * @return array|int
1652
     */
1653
    public static function get_count_user_list_from_course_code(
1654
        $resumed_report = false,
1655
        $extra_field = array(),
1656
        $courseCodeList = array(),
1657
        $userIdList = array(),
1658
        $sessionIdList = array()
1659
    ) {
1660
        return self::get_user_list_from_course_code(
1661
            null,
1662
            0,
1663
            null,
1664
            null,
1665
            null,
1666
            true,
1667
            false,
1668
            $resumed_report,
1669
            $extra_field,
1670
            $courseCodeList,
1671
            $userIdList,
1672
            null,
1673
            $sessionIdList
1674
        );
1675
    }
1676
1677
    /**
1678
     * Gets subscribed users in a course or in a course/session
1679
     *
1680
     * @param   string $course_code
1681
     * @param   int $session_id
1682
     * @return  int
1683
     */
1684
    public static function get_users_count_in_course(
1685
        $course_code,
1686
        $session_id = 0,
1687
        $status = null
1688
    ) {
1689
        // variable initialisation
1690
        $session_id = intval($session_id);
1691
        $course_code = Database::escape_string($course_code);
1692
1693
        $courseInfo = api_get_course_info($course_code);
1694
        $courseId = $courseInfo['real_id'];
1695
1696
        $sql = 'SELECT DISTINCT count(user.id) as count  
1697
                FROM ' . Database::get_main_table(TABLE_MAIN_USER) . ' as user ';
1698
        $where = array();
1699
        if (!empty($session_id)) {
1700
            $sql .= ' LEFT JOIN ' . Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER) . ' as session_course_user
1701
                      ON
1702
                        user.user_id = session_course_user.user_id AND
1703
                        session_course_user.c_id = "' . $courseId . '" AND
1704
                        session_course_user.session_id  = ' . $session_id;
1705
1706
            $where[] = ' session_course_user.c_id IS NOT NULL ';
1707
        } else {
1708
            $sql .= ' LEFT JOIN ' . Database::get_main_table(TABLE_MAIN_COURSE_USER) . ' as course_rel_user
1709
                        ON
1710
                            user.user_id = course_rel_user.user_id AND
1711
                            course_rel_user.relation_type<>' . COURSE_RELATION_TYPE_RRHH . ' AND
1712
                            course_rel_user.c_id = ' . $courseId ;
1713
            $where[] = ' course_rel_user.c_id IS NOT NULL ';
1714
        }
1715
1716
        $multiple_access_url = api_get_multiple_access_url();
1717
        if ($multiple_access_url) {
1718
            $sql .= ' LEFT JOIN ' . Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER) . '  au
1719
                      ON (au.user_id = user.user_id) ';
1720
        }
1721
1722
        $sql .= ' WHERE ' . implode(' OR ', $where);
1723
1724
        if ($multiple_access_url) {
1725
            $current_access_url_id = api_get_current_access_url_id();
1726
            $sql .= " AND (access_url_id =  $current_access_url_id ) ";
1727
        }
1728
        $rs = Database::query($sql);
1729
        $count = 0;
1730
        if (Database::num_rows($rs)) {
1731
            $user = Database::fetch_array($rs);
1732
            $count = $user['count'];
1733
        }
1734
1735
        return $count;
1736
    }
1737
1738
    /**
1739
     * Get a list of coaches of a course and a session
1740
     * @param   string  $course_code
1741
     * @param   int     $session_id
1742
     * @param   bool $addGeneralCoach
1743
     * @return  array   List of users
1744
     */
1745
    public static function get_coach_list_from_course_code($course_code, $session_id, $addGeneralCoach = true)
1746
    {
1747
        if (empty($course_code) || empty($session_id)) {
1748
            return array();
1749
        }
1750
1751
        $course_code = Database::escape_string($course_code);
1752
        $courseInfo = api_get_course_info($course_code);
1753
        $courseId = $courseInfo['real_id'];
1754
1755
        $session_id = intval($session_id);
1756
        $users = array();
1757
1758
        // We get the coach for the given course in a given session.
1759
        $sql = 'SELECT user_id FROM ' . Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER) .
1760
               ' WHERE session_id ="' . $session_id . '" AND c_id="' . $courseId . '" AND status = 2';
1761
        $rs = Database::query($sql);
1762
        while ($user = Database::fetch_array($rs)) {
1763
            $userInfo = api_get_user_info($user['user_id']);
1764
            if ($userInfo) {
1765
                $users[$user['user_id']] = $userInfo;
1766
            }
1767
        }
1768
1769
        if ($addGeneralCoach) {
1770
            $table = Database::get_main_table(TABLE_MAIN_SESSION);
1771
            // We get the session coach.
1772
            $sql = 'SELECT id_coach FROM '.$table.' WHERE id='.$session_id;
1773
            $rs = Database::query($sql);
1774
            $session_id_coach = Database::result($rs, 0, 'id_coach');
1775
            $userInfo = api_get_user_info($session_id_coach);
1776
            if ($userInfo) {
1777
                $users[$session_id_coach] = $userInfo;
1778
            }
1779
        }
1780
1781
        return $users;
1782
    }
1783
1784
    /**
1785
     *  Return user info array of all users registered in a course
1786
     *  This only returns the users that are registered in this actual course, not linked courses.
1787
     *
1788
     * @param string $course_code
1789
     * @param boolean $with_session
1790
     * @param integer $session_id
1791
     * @param string $date_from
1792
     * @param string $date_to
1793
     * @param boolean $includeInvitedUsers Whether include the invited users
1794
     * @param int $groupId
1795
     * @return array with user id
1796
     */
1797
    public static function get_student_list_from_course_code(
1798
        $course_code,
1799
        $with_session = false,
1800
        $session_id = 0,
1801
        $date_from = null,
1802
        $date_to = null,
1803
        $includeInvitedUsers = true,
1804
        $groupId = 0
1805
    ) {
1806
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
1807
        $session_id = intval($session_id);
1808
        $course_code = Database::escape_string($course_code);
1809
        $courseInfo = api_get_course_info($course_code);
1810
        $courseId = $courseInfo['real_id'];
1811
        $students = array();
1812
1813
        if ($session_id == 0) {
1814
            if (empty($groupId)) {
1815
                // students directly subscribed to the course
1816
                $sql = "SELECT *
1817
                        FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)." cu
1818
                        INNER JOIN $userTable u
1819
                        ON cu.user_id = u.user_id
1820
                        WHERE c_id = '$courseId' AND cu.status = ".STUDENT;
1821
1822
                if (!$includeInvitedUsers) {
1823
                    $sql .= " AND u.status != ".INVITEE;
1824
                }
1825
                $rs = Database::query($sql);
1826
                while ($student = Database::fetch_array($rs)) {
1827
                    $students[$student['user_id']] = $student;
1828
                }
1829
            } else {
1830
                $students = GroupManager::get_users(
1831
                    $groupId,
1832
                    false,
1833
                    null,
1834
                    null,
1835
                    false,
1836
                    $courseInfo['real_id']
1837
                );
1838
                $students = array_flip($students);
1839
            }
1840
        }
1841
1842
        // students subscribed to the course through a session
1843
        if ($with_session) {
1844
            $joinSession = "";
1845
            //Session creation date
1846
            if (!empty($date_from) && !empty($date_to)) {
1847
                $joinSession = "INNER JOIN " . Database::get_main_table(TABLE_MAIN_SESSION) . " s";
1848
            }
1849
1850
            $sql_query = "SELECT *
1851
                          FROM " . Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER) . " scu
1852
                          $joinSession
1853
                          INNER JOIN $userTable u ON scu.user_id = u.user_id
1854
                          WHERE scu.c_id = '$courseId' AND scu.status <> 2";
1855
1856
            if (!empty($date_from) && !empty($date_to)) {
1857
                $date_from = Database::escape_string($date_from);
1858
                $date_to = Database::escape_string($date_to);
1859
                $sql_query .= " AND s.access_start_date >= '$date_from' AND s.access_end_date <= '$date_to'";
1860
            }
1861
1862
            if ($session_id != 0) {
1863
                $sql_query .= ' AND scu.session_id = ' . $session_id;
1864
            }
1865
1866
            if (!$includeInvitedUsers) {
1867
                $sql_query .= " AND u.status != " . INVITEE;
1868
            }
1869
1870
            $rs = Database::query($sql_query);
1871
            while ($student = Database::fetch_array($rs)) {
1872
                $students[$student['user_id']] = $student;
1873
            }
1874
        }
1875
1876
        return $students;
1877
    }
1878
1879
    /**
1880
     * Return user info array of all teacher-users registered in a course
1881
     * This only returns the users that are registered in this actual course, not linked courses.
1882
     *
1883
     * @param string $course_code
1884
     * @return array with user id
1885
     */
1886
    public static function get_teacher_list_from_course_code($course_code)
1887
    {
1888
        $courseInfo = api_get_course_info($course_code);
1889
        $courseId = $courseInfo['real_id'];
1890
        if (empty($courseId)) {
1891
            return false;
1892
        }
1893
1894
        $sql = "SELECT DISTINCT
1895
                    u.id as user_id,
1896
                    u.lastname,
1897
                    u.firstname,
1898
                    u.email,
1899
                    u.username,
1900
                    u.status
1901
                FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER) . " cu
1902
                INNER JOIN " . Database::get_main_table(TABLE_MAIN_USER) . " u
1903
                ON (cu.user_id = u.id)
1904
                WHERE
1905
                    cu.c_id = $courseId AND
1906
                    cu.status = 1 ";
1907
        $rs = Database::query($sql);
1908
        $teachers = array();
1909
        while ($teacher = Database::fetch_array($rs)) {
1910
            $teachers[$teacher['user_id']] = $teacher;
1911
        }
1912
1913
        return $teachers;
1914
    }
1915
1916
    /**
1917
     * Return user info array of all teacher-users registered in a course
1918
     * This only returns the users that are registered in this actual course, not linked courses.
1919
     *
1920
     * @param int $courseId
1921
     * @param bool $loadAvatars
1922
     *
1923
     * @return array with user id
1924
     */
1925
    public static function getTeachersFromCourse($courseId, $loadAvatars = true)
1926
    {
1927
        $courseId = (int) $courseId;
1928
1929
        if (empty($courseId)) {
1930
            return false;
1931
        }
1932
1933
        $sql = "SELECT DISTINCT
1934
                    u.id as user_id,
1935
                    u.lastname,
1936
                    u.firstname,
1937
                    u.email,
1938
                    u.username,
1939
                    u.status
1940
                FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER) . " cu
1941
                INNER JOIN " . Database::get_main_table(TABLE_MAIN_USER) . " u
1942
                ON (cu.user_id = u.id)
1943
                WHERE
1944
                    cu.c_id = $courseId AND
1945
                    cu.status = 1 ";
1946
        $rs = Database::query($sql);
1947
        $listTeachers = array();
1948
        $teachers = array();
1949
        $url = api_get_path(WEB_AJAX_PATH) . 'user_manager.ajax.php?a=get_user_popup';
1950
        while ($teacher = Database::fetch_array($rs)) {
1951
            $teachers['id'] = $teacher['user_id'];
1952
            $teachers['lastname'] = $teacher['lastname'];
1953
            $teachers['firstname'] = $teacher['firstname'];
1954
            $teachers['email'] = $teacher['email'];
1955
            $teachers['username'] = $teacher['username'];
1956
            $teachers['status'] = $teacher['status'];
1957
            $teachers['avatar'] = '';
1958
            if ($loadAvatars) {
1959
                $userPicture = UserManager::getUserPicture($teacher['user_id'], USER_IMAGE_SIZE_SMALL);
1960
                $teachers['avatar'] = $userPicture;
1961
            }
1962
            $teachers['url'] = $url.'&user_id='. $teacher['user_id'];
1963
            $listTeachers[] = $teachers;
1964
        }
1965
1966
        return $listTeachers;
1967
    }
1968
1969
    /**
1970
     * Returns a string list of teachers assigned to the given course
1971
     * @param string $course_code
1972
     * @param string $separator between teachers names
1973
     * @param bool $add_link_to_profile Whether to add a link to the teacher's profile
1974
     * @return string List of teachers teaching the course
1975
     */
1976 View Code Duplication
    public static function get_teacher_list_from_course_code_to_string(
1977
        $course_code,
1978
        $separator = self::USER_SEPARATOR,
1979
        $add_link_to_profile = false,
1980
        $orderList = false
1981
    ) {
1982
        $teacher_list = self::get_teacher_list_from_course_code($course_code);
1983
        $html = '';
1984
        $list = array();
1985
        if (!empty($teacher_list)) {
1986
            foreach ($teacher_list as $teacher) {
1987
                $teacher_name = api_get_person_name(
1988
                    $teacher['firstname'],
1989
                    $teacher['lastname']
1990
                );
1991
                if ($add_link_to_profile) {
1992
                    $url = api_get_path(WEB_AJAX_PATH) . 'user_manager.ajax.php?a=get_user_popup&user_id=' . $teacher['user_id'];
1993
                    $teacher_name = Display::url(
1994
                        $teacher_name,
1995
                        $url,
1996
                        [
1997
                            'class' => 'ajax',
1998
                            'data-title' => $teacher_name
1999
                        ]
2000
                    );
2001
                }
2002
                $list[] = $teacher_name;
2003
            }
2004
2005
            if (!empty($list)) {
2006
                if ($orderList === true) {
2007
                    $html .= '<ul class="user-teacher">';
2008
                    foreach ($list as $teacher){
2009
                        $html .= Display::tag('li', Display::return_icon('teacher.png', $teacher, null, ICON_SIZE_TINY) . ' ' . $teacher);
2010
                    }
2011
                    $html .= '</ul>';
2012
                } else {
2013
                    $html .= array_to_string($list, $separator);
2014
                }
2015
            }
2016
        }
2017
2018
        return $html;
2019
    }
2020
2021
    /**
2022
     * This function returns information about coachs from a course in session
2023
     * @param int $session_id
2024
     * @param int $courseId
2025
     *
2026
     * @return array containing user_id, lastname, firstname, username
2027
     */
2028
    public static function get_coachs_from_course($session_id = 0, $courseId = 0)
2029
    {
2030
        if (!empty($session_id)) {
2031
            $session_id = intval($session_id);
2032
        } else {
2033
            $session_id = api_get_session_id();
2034
        }
2035
2036
        if (!empty($courseId)) {
2037
            $courseId = intval($courseId);
2038
        } else {
2039
            $courseId = api_get_course_int_id();
2040
        }
2041
2042
        $tbl_user = Database:: get_main_table(TABLE_MAIN_USER);
2043
        $tbl_session_course_user = Database:: get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2044
2045
        $sql = "SELECT DISTINCT 
2046
                    u.user_id,
2047
                    u.lastname,
2048
                    u.firstname,
2049
                    u.username
2050
                FROM $tbl_user u 
2051
                INNER JOIN $tbl_session_course_user scu
2052
                ON (u.user_id = scu.user_id)
2053
                WHERE
2054
                    scu.session_id = '$session_id' AND
2055
                    scu.c_id = '$courseId' AND
2056
                    scu.status = 2";
2057
        $rs = Database::query($sql);
2058
2059
        $coaches = array();
2060
        if (Database::num_rows($rs) > 0) {
2061 View Code Duplication
            while ($row = Database::fetch_array($rs)) {
2062
                $completeName = api_get_person_name($row['firstname'], $row['lastname']);
2063
                $coaches[] = $row + ['full_name' => $completeName];
2064
            }
2065
        }
2066
2067
        return $coaches;
2068
    }
2069
2070
    /**
2071
     * @param int $session_id
2072
     * @param int $courseId
2073
     * @param string $separator
2074
     * @param bool $add_link_to_profile
2075
     * @return string
2076
     */
2077 View Code Duplication
    public static function get_coachs_from_course_to_string(
2078
        $session_id = 0,
2079
        $courseId = 0,
2080
        $separator = self::USER_SEPARATOR,
2081
        $add_link_to_profile = false,
2082
        $orderList = false
2083
    ) {
2084
        $coachList = self::get_coachs_from_course($session_id, $courseId);
2085
        $course_coachs = array();
2086
        if (!empty($coachList)) {
2087
            foreach ($coachList as $coach_course) {
2088
                $coach_name = $coach_course['full_name'];
2089
                if ($add_link_to_profile) {
2090
                    $url = api_get_path(WEB_AJAX_PATH) . 'user_manager.ajax.php?a=get_user_popup&user_id=' . $coach_course['user_id'];
2091
                    $coach_name = Display::url(
2092
                        $coach_name,
2093
                        $url,
2094
                        [
2095
                            'class' => 'ajax',
2096
                            'data-title' => $coach_name
2097
                        ]
2098
                    );
2099
                }
2100
                $course_coachs[] = $coach_name;
2101
            }
2102
        }
2103
2104
        $html = '';
2105
        if (!empty($course_coachs)) {
2106
            if ($orderList === true) {
2107
                $html .= '<ul class="user-coachs">';
2108
                foreach ($course_coachs as $coachs) {
2109
                    $html .= Display::tag(
2110
                        'li',
2111
                        Display::return_icon('teacher.png', $coachs, null, ICON_SIZE_TINY) . ' ' . $coachs
2112
                    );
2113
                }
2114
                $html .= '</ul>';
2115
            } else {
2116
                $html = array_to_string($course_coachs, $separator);
2117
            }
2118
        }
2119
2120
        return $html;
2121
    }
2122
2123
    /**
2124
     * Return user info array of all users registered in the specified course
2125
     * this includes the users of the course itself and the users of all linked courses.
2126
     *
2127
     * @param string $course_code
2128
     * @param bool $with_sessions
2129
     * @param int $session_id
2130
     * @return array with user info
2131
     */
2132
    public static function get_real_and_linked_user_list($course_code, $with_sessions = true, $session_id = 0)
2133
    {
2134
        $list = array();
2135
        $userList = self::get_user_list_from_course_code($course_code, $session_id);
2136
        foreach ($userList as $user) {
0 ignored issues
show
Bug introduced by
The expression $userList of type array|integer is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
2137
            $list[] = $user;
2138
        }
2139
2140
        return $list;
2141
    }
2142
2143
    /**
2144
     * Get the list of groups from the course
2145
     * @param   string $course_code
2146
     * @param   int $session_id Session ID (optional)
2147
     * @param   integer $in_get_empty_group get empty groups (optional)
2148
     * @return  array   List of groups info
2149
     */
2150
    public static function get_group_list_of_course($course_code, $session_id = 0, $in_get_empty_group = 0)
2151
    {
2152
        $course_info = api_get_course_info($course_code);
2153
2154
        if (empty($course_info)) {
2155
            return array();
2156
        }
2157
        $course_id = $course_info['real_id'];
2158
2159
        if (empty($course_id)) {
2160
            return array();
2161
        }
2162
2163
        $group_list = array();
2164
        $session_id != 0 ? $session_condition = ' WHERE g.session_id IN(1,' . intval($session_id) . ')' : $session_condition = ' WHERE g.session_id = 0';
2165
2166
        if ($in_get_empty_group == 0) {
2167
            // get only groups that are not empty
2168
            $sql = "SELECT DISTINCT g.id, g.iid, g.name
2169
                    FROM " . Database::get_course_table(TABLE_GROUP) . " AS g
2170
                    INNER JOIN " . Database::get_course_table(TABLE_GROUP_USER) . " gu
2171
                    ON (g.id = gu.group_id AND g.c_id = $course_id AND gu.c_id = $course_id)
2172
                    $session_condition
2173
                    ORDER BY g.name";
2174
        } else {
2175
            // get all groups even if they are empty
2176
            $sql = "SELECT g.id, g.name, g.iid 
2177
                    FROM " . Database::get_course_table(TABLE_GROUP) . " AS g
2178
                    $session_condition
2179
                    AND c_id = $course_id";
2180
        }
2181
        $result = Database::query($sql);
2182
2183
        while ($group_data = Database::fetch_array($result)) {
2184
            $group_data['userNb'] = GroupManager::number_of_students($group_data['iid'], $course_id);
2185
            $group_list[$group_data['id']] = $group_data;
2186
        }
2187
        return $group_list;
2188
    }
2189
2190
    /**
2191
     * Delete a course
2192
     * This function deletes a whole course-area from the platform. When the
2193
     * given course is a virtual course, the database and directory will not be
2194
     * deleted.
2195
     * When the given course is a real course, also all virtual courses refering
2196
     * to the given course will be deleted.
2197
     * Considering the fact that we remove all traces of the course in the main
2198
     * database, it makes sense to remove all tracking as well (if stats databases exist)
2199
     * so that a new course created with this code would not use the remains of an older
2200
     * course.
2201
     *
2202
     * @param string The code of the course to delete
2203
     * @param string $code
2204
     * @todo When deleting a virtual course: unsubscribe users from that virtual
2205
     * course from the groups in the real course if they are not subscribed in
2206
     * that real course.
2207
     * @todo Remove globals
2208
     */
2209
    public static function delete_course($code)
2210
    {
2211
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
2212
        $table_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2213
        $table_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2214
        $table_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2215
        $table_course_survey = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY);
2216
        $table_course_survey_question = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION);
2217
        $table_course_survey_question_option = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
2218
        $table_course_rel_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2219
2220
        $table_stats_hotpots = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTPOTATOES);
2221
        $table_stats_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
2222
        $table_stats_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
2223
        $table_stats_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS);
2224
        $table_stats_lastaccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
2225
        $table_stats_course_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
2226
        $table_stats_online = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ONLINE);
2227
        $table_stats_default = Database::get_main_table(TABLE_STATISTIC_TRACK_E_DEFAULT);
2228
        $table_stats_downloads = Database::get_main_table(TABLE_STATISTIC_TRACK_E_DOWNLOADS);
2229
        $table_stats_links = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LINKS);
2230
        $table_stats_uploads = Database::get_main_table(TABLE_STATISTIC_TRACK_E_UPLOADS);
2231
2232
        $codeFiltered = Database::escape_string($code);
2233
        $sql = "SELECT * FROM $table_course WHERE code='" . $codeFiltered . "'";
2234
        $res = Database::query($sql);
2235
2236
        if (Database::num_rows($res) == 0) {
2237
            return;
2238
        }
2239
2240
        $sql = "SELECT * FROM $table_course
2241
                WHERE code = '" . $codeFiltered . "'";
2242
        $res = Database::query($sql);
2243
        $course = Database::fetch_array($res);
2244
        $courseId = $course['id'];
2245
2246
        $count = 0;
2247
        if (api_is_multiple_url_enabled()) {
2248
            $url_id = 1;
2249
            if (api_get_current_access_url_id() != -1) {
2250
                $url_id = api_get_current_access_url_id();
2251
            }
2252
            UrlManager::delete_url_rel_course($courseId, $url_id);
2253
            $count = UrlManager::getCountUrlRelCourse($courseId);
2254
        }
2255
2256
        if ($count == 0) {
2257
            self::create_database_dump($code);
2258
2259
            $course_tables = AddCourse::get_course_tables();
2260
2261
            // Cleaning group categories
2262
            $groupCategories = GroupManager::get_categories($course['code']);
2263
2264
            if (!empty($groupCategories)) {
2265
                foreach ($groupCategories as $category) {
2266
                    GroupManager::delete_category($category['id'], $course['code']);
2267
                }
2268
            }
2269
2270
            // Cleaning groups
2271
            $groups = GroupManager::get_groups($courseId);
2272
            if (!empty($groups)) {
2273
                $groupList = array_column($groups, 'iid');
2274
                foreach ($groupList as $groupId) {
2275
                    GroupManager::delete_groups($groupId, $course['code']);
2276
                }
2277
2278
            }
2279
2280
            // Cleaning c_x tables
2281
            if (!empty($courseId)) {
2282
                foreach ($course_tables as $table) {
2283
                    $table = Database::get_course_table($table);
2284
                    $sql = "DELETE FROM $table WHERE c_id = $courseId ";
2285
                    Database::query($sql);
2286
                }
2287
            }
2288
2289
            $course_dir = api_get_path(SYS_COURSE_PATH) . $course['directory'];
2290
            $archive_dir = api_get_path(SYS_ARCHIVE_PATH) . $course['directory'] . '_' . time();
2291
            if (is_dir($course_dir)) {
2292
                rename($course_dir, $archive_dir);
2293
            }
2294
2295
            // Unsubscribe all users from the course
2296
            $sql = "DELETE FROM $table_course_user WHERE c_id='" . $courseId . "'";
2297
            Database::query($sql);
2298
            // Delete the course from the sessions tables
2299
            $sql = "DELETE FROM $table_session_course WHERE c_id='" . $courseId . "'";
2300
            Database::query($sql);
2301
            $sql = "DELETE FROM $table_session_course_user WHERE c_id='" . $courseId . "'";
2302
            Database::query($sql);
2303
2304
            // Delete from Course - URL
2305
            $sql = "DELETE FROM $table_course_rel_url WHERE c_id = '" . $courseId. "'";
2306
            Database::query($sql);
2307
2308
            $sql = 'SELECT survey_id FROM ' . $table_course_survey . ' WHERE course_code="' . $codeFiltered . '"';
2309
            $result_surveys = Database::query($sql);
2310 View Code Duplication
            while ($surveys = Database::fetch_array($result_surveys)) {
2311
                $survey_id = $surveys[0];
2312
                $sql = 'DELETE FROM ' . $table_course_survey_question . ' WHERE survey_id="' . $survey_id . '"';
2313
                Database::query($sql);
2314
                $sql = 'DELETE FROM ' . $table_course_survey_question_option . ' WHERE survey_id="' . $survey_id . '"';
2315
                Database::query($sql);
2316
                $sql = 'DELETE FROM ' . $table_course_survey . ' WHERE survey_id="' . $survey_id . '"';
2317
                Database::query($sql);
2318
            }
2319
2320
            // Delete the course from the stats tables
2321
            $sql = "DELETE FROM $table_stats_hotpots WHERE c_id = $courseId";
2322
            Database::query($sql);
2323
            $sql = "DELETE FROM $table_stats_attempt WHERE c_id = $courseId";
2324
            Database::query($sql);
2325
            $sql = "DELETE FROM $table_stats_exercises WHERE c_id = $courseId";
2326
            Database::query($sql);
2327
            $sql = "DELETE FROM $table_stats_access WHERE c_id = $courseId";
2328
            Database::query($sql);
2329
            $sql = "DELETE FROM $table_stats_lastaccess WHERE c_id = $courseId";
2330
            Database::query($sql);
2331
            $sql = "DELETE FROM $table_stats_course_access WHERE c_id = $courseId";
2332
            Database::query($sql);
2333
            $sql = "DELETE FROM $table_stats_online WHERE c_id = $courseId";
2334
            Database::query($sql);
2335
            // Do not delete rows from track_e_default as these include course
2336
            // creation and other important things that do not take much space
2337
            // but give information on the course history
2338
            //$sql = "DELETE FROM $table_stats_default WHERE c_id = $courseId";
2339
            //Database::query($sql);
2340
            $sql = "DELETE FROM $table_stats_downloads WHERE c_id = $courseId";
2341
            Database::query($sql);
2342
            $sql = "DELETE FROM $table_stats_links WHERE c_id = $courseId";
2343
            Database::query($sql);
2344
            $sql = "DELETE FROM $table_stats_uploads WHERE c_id = $courseId";
2345
            Database::query($sql);
2346
2347
            // Update ticket
2348
            $ticket = Database::get_main_table(TABLE_TICKET_TICKET);
2349
            $sql = "UPDATE $ticket SET course_id = NULL WHERE course_id = $courseId";
2350
            Database::query($sql);
2351
2352
            // Skills
2353
            $table = Database::get_main_table(TABLE_MAIN_SKILL_REL_USER);
2354
            $sql = "DELETE FROM $table WHERE course_id = $courseId";
2355
            Database::query($sql);
2356
2357
            Category::deleteCategoryFromCourse($courseId);
2358
2359
            // Delete the course from the database
2360
            $sql = "DELETE FROM $table_course WHERE code = '" . $codeFiltered . "'";
2361
            Database::query($sql);
2362
2363
            // delete extra course fields
2364
            $extraFieldValues = new ExtraFieldValue('course');
2365
            $extraFieldValues->deleteValuesByItem($courseId);
2366
2367
            // Add event to system log
2368
            $user_id = api_get_user_id();
2369
            Event::addEvent(
2370
                LOG_COURSE_DELETE,
2371
                LOG_COURSE_CODE,
2372
                $code,
2373
                api_get_utc_datetime(),
0 ignored issues
show
Bug introduced by
It seems like api_get_utc_datetime() can also be of type object<DateTime>; however, Event::addEvent() does only seem to accept string|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
2374
                $user_id,
2375
                $courseId
2376
            );
2377
        }
2378
    }
2379
2380
    /**
2381
     * Creates a file called mysql_dump.sql in the course folder
2382
     * @param string $course_code The code of the course
2383
     * @todo Implementation for single database
2384
     */
2385
    public static function create_database_dump($course_code)
2386
    {
2387
        $sql_dump = '';
2388
        $course_code = Database::escape_string($course_code);
2389
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
2390
        $sql = "SELECT * FROM $table_course WHERE code = '$course_code'";
2391
        $res = Database::query($sql);
2392
        $course = Database::fetch_array($res);
2393
2394
        $course_tables = AddCourse::get_course_tables();
2395
2396
        if (!empty($course['id'])) {
2397
            //Cleaning c_x tables
2398
            foreach ($course_tables as $table) {
2399
                $table = Database::get_course_table($table);
2400
                $sql = "SELECT * FROM $table WHERE c_id = {$course['id']} ";
2401
                $res_table = Database::query($sql);
2402
2403
                while ($row = Database::fetch_array($res_table, 'ASSOC')) {
2404
                    $row_to_save = array();
2405
                    foreach ($row as $key => $value) {
2406
                        $row_to_save[$key] = $key . "='" . Database::escape_string($row[$key]) . "'";
2407
                    }
2408
                    $sql_dump .= "\nINSERT INTO $table SET " . implode(', ', $row_to_save) . ';';
2409
                }
2410
            }
2411
        }
2412
2413
        if (is_dir(api_get_path(SYS_COURSE_PATH) . $course['directory'])) {
2414
            $file_name = api_get_path(SYS_COURSE_PATH) . $course['directory'] . '/mysql_dump.sql';
2415
            $handle = fopen($file_name, 'a+');
2416
            if ($handle !== false) {
2417
                fwrite($handle, $sql_dump);
2418
                fclose($handle);
2419
            } else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

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

These else branches can be removed.

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

could be turned into

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

This is much more concise to read.

Loading history...
2420
                //TODO trigger exception in a try-catch
2421
            }
2422
        }
2423
    }
2424
2425
    /**
2426
     * Sort courses for a specific user ??
2427
     * @param   int     User ID
2428
     * @param   string  Course code
2429
     * @param integer $user_id
2430
     * @return  int     Minimum course order
2431
     * @todo Review documentation
2432
     */
2433
    public static function userCourseSort($user_id, $course_code)
2434
    {
2435
        if ($user_id != strval(intval($user_id))) {
2436
            return false;
2437
        }
2438
2439
        $course_code = Database::escape_string($course_code);
2440
        $TABLECOURSE = Database::get_main_table(TABLE_MAIN_COURSE);
2441
        $TABLECOURSUSER = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2442
2443
        $course_title = Database::result(Database::query('SELECT title FROM ' . $TABLECOURSE . ' WHERE code="' . $course_code . '"'),
0 ignored issues
show
Bug introduced by
It seems like \Database::query('SELECT...' . $course_code . '"') can be null; however, result() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
2444
            0, 0);
2445
2446
        $sql = 'SELECT course.code as code, course.title as title, cu.sort as sort
2447
                FROM ' . $TABLECOURSUSER . ' as cu, ' . $TABLECOURSE . ' as course
2448
                WHERE   course.id = cu.c_id AND user_id = "' . $user_id . '" AND
2449
                        cu.relation_type<>' . COURSE_RELATION_TYPE_RRHH . ' AND
2450
                        user_course_cat = 0
2451
                ORDER BY cu.sort';
2452
        $result = Database::query($sql);
2453
2454
        $course_title_precedent = '';
2455
        $counter = 0;
2456
        $course_found = false;
2457
        $course_sort = 1;
2458
2459
        if (Database::num_rows($result) > 0) {
2460
            while ($courses = Database::fetch_array($result)) {
2461
                if ($course_title_precedent == '') {
2462
                    $course_title_precedent = $courses['title'];
2463
                }
2464
                if (api_strcasecmp($course_title_precedent, $course_title) < 0) {
2465
                    $course_found = true;
2466
                    $course_sort = $courses['sort'];
2467
                    if ($counter == 0) {
2468
                        $sql = 'UPDATE ' . $TABLECOURSUSER . '
2469
                                SET sort = sort+1
2470
                                WHERE
2471
                                    user_id= "' . $user_id . '" AND
2472
                                    relation_type<>' . COURSE_RELATION_TYPE_RRHH . '
2473
                                    AND user_course_cat="0"
2474
                                    AND sort > "' . $course_sort . '"';
2475
                        $course_sort++;
2476
                    } else {
2477
                        $sql = 'UPDATE ' . $TABLECOURSUSER . ' SET sort = sort+1
2478
                                WHERE
2479
                                    user_id= "' . $user_id . '" AND
2480
                                    relation_type<>' . COURSE_RELATION_TYPE_RRHH . ' AND
2481
                                    user_course_cat="0" AND
2482
                                    sort >= "' . $course_sort . '"';
2483
                    }
2484
                    Database::query($sql);
2485
                    break;
2486
2487
                } else {
2488
                    $course_title_precedent = $courses['title'];
2489
                }
2490
                $counter++;
2491
            }
2492
2493
            // We must register the course in the beginning of the list
2494
            if (!$course_found) {
2495
                $course_sort = Database::result(Database::query('SELECT min(sort) as min_sort FROM ' . $TABLECOURSUSER . ' WHERE user_id="' . $user_id . '" AND user_course_cat="0"'),
0 ignored issues
show
Bug introduced by
It seems like \Database::query('SELECT...D user_course_cat="0"') can be null; however, result() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
2496
                    0, 0);
2497
                Database::query('UPDATE ' . $TABLECOURSUSER . ' SET sort = sort+1 WHERE user_id= "' . $user_id . '" AND user_course_cat="0"');
2498
            }
2499
        }
2500
        return $course_sort;
2501
    }
2502
2503
    /**
2504
     * check if course exists
2505
     * @param string $course_code
2506
     * @return integer if exists, false else
2507
     */
2508 View Code Duplication
    public static function course_exists($course_code)
2509
    {
2510
        $sql = 'SELECT 1 FROM ' . Database::get_main_table(TABLE_MAIN_COURSE) . '
2511
                WHERE code="' . Database::escape_string($course_code) . '"';
2512
2513
        return Database::num_rows(Database::query($sql));
0 ignored issues
show
Bug introduced by
It seems like \Database::query($sql) can be null; however, num_rows() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
2514
    }
2515
2516
    /**
2517
     * Send an email to tutor after the auth-suscription of a student in your course
2518
     * @author Carlos Vargas <[email protected]>, Dokeos Latino
2519
     * @param  int $user_id the id of the user
2520
     * @param  string $courseId the course code
2521
     * @param  bool $send_to_tutor_also
2522
     * @return false|null we return the message that is displayed when the action is successful
2523
     */
2524
    public static function email_to_tutor($user_id, $courseId, $send_to_tutor_also = false)
2525
    {
2526
        if ($user_id != strval(intval($user_id))) {
2527
            return false;
2528
        }
2529
        $courseId = intval($courseId);
2530
        $information = api_get_course_info_by_id($courseId);
2531
        $course_code = $information['code'];
2532
2533
        $student = api_get_user_info($user_id);
2534
2535
        $name_course = $information['title'];
2536
        $sql = "SELECT * FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER) . " 
2537
                WHERE c_id ='" . $courseId . "'";
2538
2539
        // TODO: Ivan: This is a mistake, please, have a look at it. Intention here is diffcult to be guessed.
2540
        //if ($send_to_tutor_also = true)
2541
        // Proposed change:
2542
        if ($send_to_tutor_also) {
2543
            $sql .= " AND is_tutor=1";
2544
        } else {
2545
            $sql .= " AND status=1";
2546
        }
2547
2548
        $result = Database::query($sql);
2549
        while ($row = Database::fetch_array($result)) {
2550
            $tutor = api_get_user_info($row['user_id']);
2551
            $emailto = $tutor['email'];
2552
            $emailsubject = get_lang('NewUserInTheCourse') . ': ' . $name_course;
2553
            $emailbody = get_lang('Dear') . ': ' . api_get_person_name($tutor['firstname'], $tutor['lastname']) . "\n";
2554
            $emailbody .= get_lang('MessageNewUserInTheCourse') . ': ' . $name_course . "\n";
2555
            $emailbody .= get_lang('UserName') . ': ' . $student['username'] . "\n";
2556
            if (api_is_western_name_order()) {
2557
                $emailbody .= get_lang('FirstName') . ': ' . $student['firstname'] . "\n";
2558
                $emailbody .= get_lang('LastName') . ': ' . $student['lastname'] . "\n";
2559
            } else {
2560
                $emailbody .= get_lang('LastName') . ': ' . $student['lastname'] . "\n";
2561
                $emailbody .= get_lang('FirstName') . ': ' . $student['firstname'] . "\n";
2562
            }
2563
            $emailbody .= get_lang('Email') . ': <a href="mailto:' . $student['email'] . '">' . $student['email'] ."</a>\n\n";
2564
            $recipient_name = api_get_person_name($tutor['firstname'], $tutor['lastname'], null,
2565
                PERSON_NAME_EMAIL_ADDRESS);
2566
            $sender_name = api_get_person_name(api_get_setting('administratorName'),
2567
                api_get_setting('administratorSurname'), null, PERSON_NAME_EMAIL_ADDRESS);
2568
            $email_admin = api_get_setting('emailAdministrator');
2569
2570
            $additionalParameters = array(
2571
                'smsType' => SmsPlugin::NEW_USER_SUBSCRIBED_COURSE,
2572
                'userId' => $tutor['user_id'],
2573
                'userUsername' => $student['username'],
2574
                'courseCode' => $course_code
2575
            );
2576
            api_mail_html(
2577
                $recipient_name,
2578
                $emailto,
2579
                $emailsubject,
2580
                $emailbody,
2581
                $sender_name,
2582
                $email_admin,
2583
                null,
2584
                null,
2585
                null,
2586
                $additionalParameters
2587
            );
2588
        }
2589
    }
2590
2591
    /**
2592
     * @return array
2593
     */
2594
    public static function get_special_course_list()
2595
    {
2596
        $courseTable = Database:: get_main_table(TABLE_MAIN_COURSE);
2597
        $tbl_course_field = Database:: get_main_table(TABLE_EXTRA_FIELD);
2598
        $tbl_course_field_value = Database:: get_main_table(TABLE_EXTRA_FIELD_VALUES);
2599
2600
        //we filter the courses from the URL
2601
        $join_access_url = $where_access_url = '';
2602 View Code Duplication
        if (api_get_multiple_access_url()) {
2603
            $access_url_id = api_get_current_access_url_id();
2604
            if ($access_url_id != -1) {
2605
                $tbl_url_course = Database:: get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2606
                $join_access_url = "LEFT JOIN $tbl_url_course url_rel_course
2607
                                    ON url_rel_course.c_id = tcfv.item_id ";
2608
                $where_access_url = " AND access_url_id = $access_url_id ";
2609
            }
2610
        }
2611
2612
        $extraFieldType = EntityExtraField::COURSE_FIELD_TYPE;
2613
2614
        // get course list auto-register
2615
        $sql = "SELECT DISTINCT(c.id)
2616
                FROM $tbl_course_field_value tcfv
2617
                INNER JOIN $tbl_course_field tcf
2618
                ON tcfv.field_id =  tcf.id $join_access_url
2619
                INNER JOIN $courseTable c
2620
                ON (c.id = tcfv.item_id)
2621
                WHERE
2622
                    tcf.extra_field_type = $extraFieldType AND
2623
                    tcf.variable = 'special_course' AND
2624
                    tcfv.value = 1  $where_access_url";
2625
2626
        $result = Database::query($sql);
2627
        $courseList = array();
2628
2629
        if (Database::num_rows($result) > 0) {
2630
            while ($row = Database::fetch_array($result)) {
2631
                $courseList[] = $row['id'];
2632
            }
2633
        }
2634
2635
        return $courseList;
2636
    }
2637
2638
    /**
2639
     * Get the course codes that have been restricted in the catalogue, and if byUserId is set
2640
     * then the courses that the user is allowed or not to see in catalogue
2641
     *
2642
     * @param boolean $allowed Either if the courses have some users that are or are not allowed to see in catalogue
2643
     * @param boolean $byUserId if the courses are or are not allowed to see to the user
2644
     * @return array Course codes allowed or not to see in catalogue by some user or the user
2645
     */
2646
    public static function getCatalogueCourseList($allowed = true, $byUserId = -1)
2647
    {
2648
        $courseTable = Database:: get_main_table(TABLE_MAIN_COURSE);
2649
        $tblCourseRelUserCatalogue = Database:: get_main_table(TABLE_MAIN_COURSE_CATALOGUE_USER);
2650
        $visibility = $allowed ? 1 : 0;
2651
2652
        // Restriction by user id
2653
        $currentUserRestriction = "";
2654
        if ($byUserId > 0) {
2655
            $byUserId = (int) $byUserId;
2656
            $currentUserRestriction = " AND tcruc.user_id = $byUserId ";
2657
        }
2658
2659
        //we filter the courses from the URL
2660
        $joinAccessUrl = '';
2661
        $whereAccessUrl = '';
2662 View Code Duplication
        if (api_get_multiple_access_url()) {
2663
            $accessUrlId = api_get_current_access_url_id();
2664
            if ($accessUrlId != -1) {
2665
                $tblUrlCourse = Database:: get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2666
                $joinAccessUrl = "LEFT JOIN $tblUrlCourse url_rel_course
2667
                                    ON url_rel_course.c_id = c.id ";
2668
                $whereAccessUrl = " AND access_url_id = $accessUrlId ";
2669
            }
2670
        }
2671
2672
        // get course list auto-register
2673
        $sql = "SELECT DISTINCT(c.code)
2674
                FROM $tblCourseRelUserCatalogue tcruc
2675
                INNER JOIN $courseTable c
2676
                ON (c.id = tcruc.c_id) $joinAccessUrl
2677
                WHERE tcruc.visible = $visibility $currentUserRestriction $whereAccessUrl";
2678
2679
        $result = Database::query($sql);
2680
        $courseList = array();
2681
2682
        if (Database::num_rows($result) > 0) {
2683
            while ($resultRow = Database::fetch_array($result)) {
2684
                $courseList[] = $resultRow['code'];
2685
            }
2686
        }
2687
2688
        return $courseList;
2689
    }
2690
2691
    /**
2692
     * Get list of courses for a given user
2693
     * @param int $user_id
2694
     * @param boolean $include_sessions Whether to include courses from session or not
2695
     * @param boolean $adminGetsAllCourses If the user is platform admin,
2696
     * whether he gets all the courses or just his. Note: This does *not* include all sessions
2697
     * @return array    List of codes and db name
2698
     * @author isaac flores paz
2699
     */
2700
    public static function get_courses_list_by_user_id($user_id, $include_sessions = false, $adminGetsAllCourses = false)
2701
    {
2702
        $user_id = intval($user_id);
2703
        $course_list = array();
2704
        $codes = array();
2705
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
2706
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2707
        $tbl_user_course_category = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
2708
        $special_course_list = self::get_special_course_list();
2709
2710
        if ($adminGetsAllCourses && UserManager::is_admin($user_id)) {
2711
            // get the whole courses list
2712
            $sql = "SELECT DISTINCT(course.code), course.id as real_id
2713
                    FROM $tbl_course course";
2714
        } else {
2715
            $with_special_courses = $without_special_courses = '';
2716
            if (!empty($special_course_list)) {
2717
                $sc_string = '"' . implode('","', $special_course_list) . '"';
2718
                $with_special_courses = ' course.id IN (' . $sc_string . ')';
2719
                $without_special_courses = ' AND course.id NOT IN (' . $sc_string . ')';
2720
            }
2721
2722 View Code Duplication
            if (!empty($with_special_courses)) {
2723
                $sql = "SELECT DISTINCT(course.code), course.id as real_id
2724
                        FROM $tbl_course_user  course_rel_user
2725
                        LEFT JOIN $tbl_course  course
2726
                        ON course.id = course_rel_user.c_id
2727
                        LEFT JOIN $tbl_user_course_category user_course_category
2728
                        ON course_rel_user.user_course_cat = user_course_category.id
2729
                        WHERE  $with_special_courses
2730
                        GROUP BY course.code
2731
                        ORDER BY user_course_category.sort, course.title, course_rel_user.sort ASC
2732
2733
                    ";
2734
                //
2735
                $rs_special_course = Database::query($sql);
2736
                if (Database::num_rows($rs_special_course) > 0) {
2737
                    while ($result_row = Database::fetch_array($rs_special_course)) {
2738
                        $result_row['special_course'] = 1;
2739
                        $course_list[] = $result_row;
2740
                        $codes[] = $result_row['real_id'];
2741
                    }
2742
                }
2743
            }
2744
2745
            // get course list not auto-register. Use Distinct to avoid multiple
2746
            // entries when a course is assigned to a HRD (DRH) as watcher
2747
            $sql = "SELECT DISTINCT(course.code), course.id as real_id
2748
                    FROM $tbl_course course
2749
                    INNER JOIN $tbl_course_user cru ON course.id = cru.c_id
2750
                    WHERE cru.user_id='$user_id' $without_special_courses";
2751
        }
2752
        $result = Database::query($sql);
2753
2754
        if (Database::num_rows($result)) {
2755
            while ($row = Database::fetch_array($result, 'ASSOC')) {
2756
                $course_list[] = $row;
2757
                $codes[] = $row['real_id'];
2758
            }
2759
        }
2760
2761
        if ($include_sessions === true) {
2762
            $sql = "SELECT DISTINCT(c.code), c.id as real_id
2763
                    FROM " . Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER) . " s,
2764
                    " . Database::get_main_table(TABLE_MAIN_COURSE) . " c
2765
                    WHERE user_id = $user_id AND s.c_id = c.id";
2766
            $r = Database::query($sql);
2767
            while ($row = Database::fetch_array($r, 'ASSOC')) {
2768
                if (!in_array($row['real_id'], $codes)) {
2769
                    $course_list[] = $row;
2770
                }
2771
            }
2772
        }
2773
2774
        return $course_list;
2775
    }
2776
2777
    /**
2778
     * Get course ID from a given course directory name
2779
     * @param   string  $path Course directory (without any slash)
2780
     *
2781
     * @return  string  Course code, or false if not found
2782
     */
2783
    public static function get_course_id_from_path($path)
2784
    {
2785
        $path = Database::escape_string(str_replace('.', '', str_replace('/', '', $path)));
2786
        $res = Database::query("SELECT code FROM " . Database::get_main_table(TABLE_MAIN_COURSE) . "
2787
                WHERE directory LIKE BINARY '$path'");
2788
        if ($res === false) {
2789
            return false;
2790
        }
2791
        if (Database::num_rows($res) != 1) {
2792
            return false;
2793
        }
2794
        $row = Database::fetch_array($res);
2795
2796
        return $row['code'];
2797
    }
2798
2799
    /**
2800
     * Get course code(s) from visual code
2801
     * @deprecated
2802
     * @param   string  Visual code
2803
     * @return  array   List of codes for the given visual code
2804
     */
2805
    public static function get_courses_info_from_visual_code($code)
2806
    {
2807
        $result = array();
2808
        $sql_result = Database::query("SELECT * FROM " . Database::get_main_table(TABLE_MAIN_COURSE) . "
2809
                WHERE visual_code = '" . Database::escape_string($code) . "'");
2810
        while ($virtual_course = Database::fetch_array($sql_result)) {
2811
            $result[] = $virtual_course;
2812
        }
2813
        return $result;
2814
    }
2815
2816
    /**
2817
     * Get emails of tutors to course
2818
     * @param int $courseId
2819
     * @return array List of emails of tutors to course
2820
     *
2821
     * @author Carlos Vargas <[email protected]>, Dokeos Latino
2822
     * */
2823
    public static function get_emails_of_tutors_to_course($courseId)
2824
    {
2825
        $list = array();
2826
        $res = Database::query("SELECT user_id FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER) . "
2827
                WHERE c_id ='" . intval($courseId) . "' AND status=1");
2828
        while ($list_users = Database::fetch_array($res)) {
2829
            $result = Database::query("SELECT * FROM " . Database::get_main_table(TABLE_MAIN_USER) . "
2830
                    WHERE user_id=" . $list_users['user_id']);
2831 View Code Duplication
            while ($row_user = Database::fetch_array($result)) {
2832
                $name_teacher = api_get_person_name($row_user['firstname'], $row_user['lastname']);
2833
                $list[] = array($row_user['email'] => $name_teacher);
2834
            }
2835
        }
2836
        return $list;
2837
    }
2838
2839
    /**
2840
     * Get coaches emails by session
2841
     * @param int session id
2842
     * @param int $courseId
2843
     * @param integer $session_id
2844
     * @return array  array(email => name_tutor)  by coach
2845
     * @author Carlos Vargas <[email protected]>
2846
     */
2847
    public static function get_email_of_tutor_to_session($session_id, $courseId)
2848
    {
2849
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2850
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
2851
        $coachs_emails = array();
2852
2853
        $courseId = intval($courseId);
2854
        $session_id = intval($session_id);
2855
2856
        $sql = "SELECT user_id
2857
                FROM $tbl_session_course_user
2858
                WHERE
2859
                    session_id = '$session_id' AND
2860
                    c_id = '$courseId' AND
2861
                    status = 2
2862
                ";
2863
        $rs = Database::query($sql);
2864
2865
        if (Database::num_rows($rs) > 0) {
2866
2867
            $user_ids = array();
2868
            while ($row = Database::fetch_array($rs)) {
2869
                $user_ids[] = $row['user_id'];
2870
            }
2871
2872
            $sql = "SELECT firstname, lastname, email FROM $tbl_user
2873
                    WHERE user_id IN (" . implode(",", $user_ids) . ")";
2874
            $rs_user = Database::query($sql);
2875
2876
            while ($row_emails = Database::fetch_array($rs_user)) {
2877
                $mail_tutor = array(
2878
                    'email' => $row_emails['email'],
2879
                    'complete_name' => api_get_person_name($row_emails['firstname'], $row_emails['lastname'])
2880
                );
2881
                $coachs_emails[] = $mail_tutor;
2882
            }
2883
        }
2884
        return $coachs_emails;
2885
    }
2886
2887
    /**
2888
     * Creates a new extra field for a given course
2889
     * @param    string    Field's internal variable name
2890
     * @param    int        Field's type
2891
     * @param    string    Field's language var name
2892
     * @param integer $fieldType
2893
     * @param string $default
2894
     * @return boolean     new extra field id
2895
     */
2896
    public static function create_course_extra_field($variable, $fieldType, $displayText, $default)
2897
    {
2898
        $extraField = new ExtraField('course');
2899
        $params = [
2900
            'variable' => $variable,
2901
            'field_type' => $fieldType,
2902
            'display_text' => $displayText,
2903
            'default_value' => $default
2904
        ];
2905
2906
        return $extraField->save($params);
2907
    }
2908
2909
    /**
2910
     * Updates course attribute. Note that you need to check that your
2911
     * attribute is valid before you use this function
2912
     *
2913
     * @param int $id Course id
2914
     * @param string $name Attribute name
2915
     * @param string $value Attribute value
2916
     *
2917
     * @return Doctrine\DBAL\Driver\Statement|null True if attribute was successfully updated,
2918
     * false if course was not found or attribute name is invalid
2919
     */
2920
    public static function update_attribute($id, $name, $value)
2921
    {
2922
        $id = (int)$id;
2923
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
2924
        $sql = "UPDATE $table SET $name = '" . Database::escape_string($value) . "'
2925
                WHERE id = '$id'";
2926
2927
        return Database::query($sql);
2928
    }
2929
2930
    /**
2931
     * Update course attributes. Will only update attributes with a non-empty value.
2932
     * Note that you NEED to check that your attributes are valid before using this function
2933
     *
2934
     * @param int Course id
2935
     * @param array Associative array with field names as keys and field values as values
2936
     * @return Doctrine\DBAL\Driver\Statement|null True if update was successful, false otherwise
2937
     */
2938
    public static function update_attributes($id, $attributes)
2939
    {
2940
        $id = (int)$id;
2941
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
2942
        $sql = "UPDATE $table SET ";
2943
        $i = 0;
2944
        foreach ($attributes as $name => $value) {
2945
            if ($value != '') {
2946
                if ($i > 0) {
2947
                    $sql .= ", ";
2948
                }
2949
                $sql .= " $name = '" . Database::escape_string($value) . "'";
2950
                $i++;
2951
            }
2952
        }
2953
        $sql .= " WHERE id = '$id'";
2954
2955
        return Database::query($sql);
2956
    }
2957
2958
    /**
2959
     * Update an extra field value for a given course
2960
     * @param    integer    Course ID
2961
     * @param    string    Field variable name
2962
     * @param    string    Field value
2963
     * @return    boolean|null    true if field updated, false otherwise
2964
     */
2965
    public static function update_course_extra_field_value($course_code, $variable, $value = '')
2966
    {
2967
        $courseInfo = api_get_course_info($course_code);
2968
        $courseId = $courseInfo['real_id'];
2969
2970
        $extraFieldValues = new ExtraFieldValue('course');
2971
        $params = [
2972
            'item_id' => $courseId,
2973
            'variable' => $variable,
2974
            'value' => $value
2975
        ];
2976
2977
        return $extraFieldValues->save($params);
2978
    }
2979
2980
    /**
2981
     * @param int $session_id
2982
     * @return mixed
2983
     */
2984
    public static function get_session_category_id_by_session_id($session_id)
2985
    {
2986
        if (empty($session_id)) {
2987
            return [];
2988
        }
2989
2990
        $sql = 'SELECT sc.id session_category
2991
                FROM ' . Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY) . ' sc
2992
                INNER JOIN ' . Database::get_main_table(TABLE_MAIN_SESSION) . ' s
2993
                ON sc.id = s.session_category_id 
2994
                WHERE s.id="' . intval($session_id) . '"';
2995
2996
        return Database::result(
2997
            Database::query($sql),
0 ignored issues
show
Bug introduced by
It seems like \Database::query($sql) can be null; however, result() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
2998
            0,
2999
            'session_category'
3000
        );
3001
    }
3002
3003
    /**
3004
     * Gets the value of a course extra field. Returns null if it was not found
3005
     *
3006
     * @param string $variable Name of the extra field
3007
     * @param string $code Course code
3008
     *
3009
     * @return string Value
3010
     */
3011
    public static function get_course_extra_field_value($variable, $code)
3012
    {
3013
        $courseInfo = api_get_course_info($code);
3014
        $courseId = $courseInfo['real_id'];
3015
3016
        $extraFieldValues = new ExtraFieldValue('course');
3017
        $result = $extraFieldValues->get_values_by_handler_and_field_variable($courseId, $variable);
3018
        if (!empty($result['value'])) {
3019
            return $result['value'];
3020
        }
3021
3022
        return null;
3023
    }
3024
3025
    /**
3026
     * Lists details of the course description
3027
     * @param array        The course description
3028
     * @param string    The encoding
3029
     * @param bool        If true is displayed if false is hidden
3030
     * @return string     The course description in html
3031
     */
3032
    public static function get_details_course_description_html($descriptions, $charset, $action_show = true)
3033
    {
3034
        $data = null;
3035
        if (isset($descriptions) && count($descriptions) > 0) {
3036
            foreach ($descriptions as $description) {
3037
                $data .= '<div class="sectiontitle">';
3038
                if (api_is_allowed_to_edit() && $action_show) {
3039
                    //delete
3040
                    $data .= '<a href="' . api_get_self() . '?' . api_get_cidreq() . '&action=delete&description_id=' . $description->id . '" onclick="javascript:if(!confirm(\'' . addslashes(api_htmlentities(get_lang('ConfirmYourChoice'),
3041
                                ENT_QUOTES, $charset)) . '\')) return false;">';
3042
                    $data .= Display::return_icon('delete.gif', get_lang('Delete'),
3043
                        array('style' => 'vertical-align:middle;float:right;'));
3044
                    $data .= '</a> ';
3045
                    //edit
3046
                    $data .= '<a href="' . api_get_self() . '?' . api_get_cidreq() . '&description_id=' . $description->id . '">';
3047
                    $data .= Display::return_icon('edit.png', get_lang('Edit'),
3048
                        array('style' => 'vertical-align:middle;float:right; padding-right:4px;'), ICON_SIZE_SMALL);
3049
                    $data .= '</a> ';
3050
                }
3051
                $data .= $description->title;
3052
                $data .= '</div>';
3053
                $data .= '<div class="sectioncomment">';
3054
                $data .= $description->content;
3055
                $data .= '</div>';
3056
            }
3057
        } else {
3058
            $data .= '<em>' . get_lang('ThisCourseDescriptionIsEmpty') . '</em>';
3059
        }
3060
3061
        return $data;
3062
    }
3063
3064
    /**
3065
     * Returns the details of a course category
3066
     *
3067
     * @param string Category code
3068
     * @return array Course category
3069
     */
3070 View Code Duplication
    public static function get_course_category($code)
3071
    {
3072
        $table_categories = Database::get_main_table(TABLE_MAIN_CATEGORY);
3073
        $code = Database::escape_string($code);
3074
        $sql = "SELECT * FROM $table_categories WHERE code = '$code'";
3075
        return Database::fetch_array(Database::query($sql));
0 ignored issues
show
Bug introduced by
It seems like \Database::query($sql) can be null; however, fetch_array() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
3076
    }
3077
3078
    /**
3079
     * Returns the details of a course category
3080
     *
3081
     * @param string Category code
3082
     * @return array Course category
3083
     */
3084
    public static function getCategoriesList()
3085
    {
3086
        $table_categories = Database::get_main_table(TABLE_MAIN_CATEGORY);
3087
        $sql = "SELECT * FROM $table_categories";
3088
        $result = Database::query($sql);
3089
        $category = array();
3090 View Code Duplication
        while ($row = Database::fetch_array($result, 'ASSOC')) {
3091
            $category[$row['code']] = $row['name'];
3092
        }
3093
        return $category;
3094
    }
3095
3096
    /**
3097
     *  Get count rows of a table inside a course database
3098
     * @param  string $table   The table of which the rows should be counted
3099
     * @param  int $session_id       optionally count rows by session id
3100
     * @return int $course_id    The number of rows in the given table.
3101
     *
3102
     * @deprecated
3103
     */
3104
    public static function count_rows_course_table($table, $session_id = '', $course_id = 0)
3105
    {
3106
        $condition_session = '';
3107
        if ($session_id !== '') {
3108
            $session_id = intval($session_id);
3109
            $condition_session = " AND session_id = '$session_id' ";
3110
        }
3111
        if (!empty($course_id)) {
3112
            $course_id = intval($course_id);
3113
        } else {
3114
            $course_id = api_get_course_int_id();
3115
        }
3116
        $condition_session .= " AND c_id = '$course_id' ";
3117
3118
        $sql = "SELECT COUNT(*) AS n FROM $table WHERE 1=1 $condition_session ";
3119
        $rs = Database::query($sql);
3120
        $row = Database::fetch_row($rs);
3121
        return $row[0];
3122
    }
3123
3124
    /**
3125
     * Subscribes courses to human resource manager (Dashboard feature)
3126
     * @param    int   $hr_manager_id      Human Resource Manager id
3127
     * @param    array $courses_list       Courses code
3128
     * @return int
3129
     **/
3130
    public static function subscribeCoursesToDrhManager($hr_manager_id, $courses_list)
3131
    {
3132
        $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
3133
        $tbl_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
3134
3135
        $hr_manager_id = intval($hr_manager_id);
3136
        $affected_rows = 0;
3137
3138
        //Deleting assigned courses to hrm_id
3139
        if (api_is_multiple_url_enabled()) {
3140
            $sql = "SELECT s.c_id FROM $tbl_course_rel_user s
3141
                    INNER JOIN $tbl_course_rel_access_url a
3142
                    ON (a.c_id = s.c_id)
3143
                    WHERE
3144
                        user_id = $hr_manager_id AND
3145
                        relation_type=" . COURSE_RELATION_TYPE_RRHH . " AND
3146
                        access_url_id = " . api_get_current_access_url_id() . "";
3147
        } else {
3148
            $sql = "SELECT c_id FROM $tbl_course_rel_user
3149
                    WHERE user_id = $hr_manager_id AND relation_type=" . COURSE_RELATION_TYPE_RRHH . " ";
3150
        }
3151
        $result = Database::query($sql);
3152 View Code Duplication
        if (Database::num_rows($result) > 0) {
3153
            while ($row = Database::fetch_array($result)) {
3154
                $sql = "DELETE FROM $tbl_course_rel_user
3155
                        WHERE
3156
                            c_id = '{$row['c_id']}' AND
3157
                            user_id = $hr_manager_id AND
3158
                            relation_type=" . COURSE_RELATION_TYPE_RRHH . " ";
3159
                Database::query($sql);
3160
            }
3161
        }
3162
3163
        // inserting new courses list
3164
        if (is_array($courses_list)) {
3165
            foreach ($courses_list as $course_code) {
3166
                $courseInfo = api_get_course_info($course_code);
3167
                $courseId = $courseInfo['real_id'];
3168
                $sql = "INSERT IGNORE INTO $tbl_course_rel_user(c_id, user_id, status, relation_type)
3169
                        VALUES($courseId, $hr_manager_id, '" . DRH . "', '" . COURSE_RELATION_TYPE_RRHH . "')";
3170
                $result = Database::query($sql);
3171
                if (Database::affected_rows($result)) {
3172
                    $affected_rows++;
3173
                }
3174
            }
3175
        }
3176
3177
        return $affected_rows;
3178
    }
3179
3180
    /**
3181
     * get courses followed by human resources manager
3182
     * @param int $user_id
3183
     * @param int $from
3184
     * @param int $limit
3185
     * @param string $column
3186
     * @param string $direction
3187
     * @return array    courses
3188
     */
3189
    public static function get_courses_followed_by_drh(
3190
        $user_id,
3191
        $status = DRH,
3192
        $from = null,
3193
        $limit = null,
3194
        $column = null,
3195
        $direction = null,
3196
        $getCount = false
3197
    ) {
3198
        return self::getCoursesFollowedByUser(
3199
            $user_id,
3200
            $status,
3201
            $from,
3202
            $limit,
3203
            $column,
3204
            $direction,
3205
            $getCount
3206
        );
3207
    }
3208
3209
    /**
3210
     * get courses followed by user
3211
     * @param   int $user_id
3212
     * @param   int $status
3213
     * @param   int $from
3214
     * @param   int $limit
3215
     * @param   string $column
3216
     * @param   string $direction
3217
     * @param   boolean $getCount
3218
     * @param   string $keyword
3219
     * @param   int $sessionId
3220
     * @param   boolean $showAllAssignedCourses
3221
     * @return  array   courses
3222
     */
3223
    public static function getCoursesFollowedByUser(
3224
        $user_id,
3225
        $status = null,
3226
        $from = null,
3227
        $limit = null,
3228
        $column = null,
3229
        $direction = null,
3230
        $getCount = false,
3231
        $keyword = null,
3232
        $sessionId = null,
3233
        $showAllAssignedCourses = false
3234
    ) {
3235
        // Database Table Definitions
3236
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
3237
        $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
3238
        $tbl_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
3239
        $sessionId = intval($sessionId);
3240
        $user_id = intval($user_id);
3241
        $select = "SELECT DISTINCT *, c.id as real_id ";
3242
3243
        if ($getCount) {
3244
            $select = "SELECT COUNT(DISTINCT c.id) as count";
3245
        }
3246
3247
        $whereConditions = null;
3248
        switch ($status) {
3249
            case COURSEMANAGER:
3250
                $whereConditions .= " AND cru.user_id = '$user_id'";
3251
                if (!$showAllAssignedCourses) {
3252
                    $whereConditions .= " AND status = " . COURSEMANAGER;
3253
                } else {
3254
                    $whereConditions .= " AND relation_type = " . COURSE_RELATION_TYPE_COURSE_MANAGER;
3255
                }
3256
                break;
3257
            case DRH:
3258
                $whereConditions .= " AND
3259
                    cru.user_id = '$user_id' AND
3260
                    status = " . DRH . " AND
3261
                    relation_type = '" . COURSE_RELATION_TYPE_RRHH . "'
3262
                ";
3263
                break;
3264
        }
3265
3266
        $keywordCondition = null;
3267
        if (!empty($keyword)) {
3268
            $keyword = Database::escape_string($keyword);
3269
            $keywordCondition = " AND (c.code LIKE '%$keyword%' OR c.title LIKE '%$keyword%' ) ";
3270
        }
3271
3272
        $orderBy = null;
3273
        $extraInnerJoin = null;
3274
3275
        if (!empty($sessionId)) {
3276
            if (!empty($sessionId)) {
3277
                $courseList = SessionManager::get_course_list_by_session_id(
3278
                    $sessionId
3279
                );
3280
                if (!empty($courseList)) {
3281
                    $courseListToString = implode("','", array_keys($courseList));
3282
                    $whereConditions .= " AND c.id IN ('" . $courseListToString . "')";
3283
                }
3284
                $tableSessionRelCourse = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
3285
                $orderBy = ' ORDER BY position';
3286
                $extraInnerJoin = " INNER JOIN $tableSessionRelCourse src
3287
                                    ON (c.id = src.c_id AND session_id = $sessionId) ";
3288
            }
3289
        }
3290
3291
        $whereConditions .= $keywordCondition;
3292
        $sql = "$select
3293
                FROM $tbl_course c
3294
                    INNER JOIN $tbl_course_rel_user cru ON (cru.c_id = c.id)
3295
                    INNER JOIN $tbl_course_rel_access_url a ON (a.c_id = c.id)
3296
                    $extraInnerJoin
3297
                WHERE
3298
                    access_url_id = " . api_get_current_access_url_id() . "
3299
                    $whereConditions
3300
                $orderBy
3301
                ";
3302 View Code Duplication
        if (isset($from) && isset($limit)) {
3303
            $from = intval($from);
3304
            $limit = intval($limit);
3305
            $sql .= " LIMIT $from, $limit";
3306
        }
3307
3308
        $result = Database::query($sql);
3309
3310
        if ($getCount) {
3311
            $row = Database::fetch_array($result);
3312
            return $row['count'];
3313
        }
3314
3315
        $courses = array();
3316
        if (Database::num_rows($result) > 0) {
3317
            while ($row = Database::fetch_array($result)) {
3318
                $courses[$row['code']] = $row;
3319
            }
3320
        }
3321
3322
        return $courses;
3323
    }
3324
3325
    /**
3326
     * check if a course is special (autoregister)
3327
     * @param int $courseId
3328
     * @return bool
3329
     */
3330
    public static function isSpecialCourse($courseId)
3331
    {
3332
        $extraFieldValue = new ExtraFieldValue('course');
3333
        $result = $extraFieldValue->get_values_by_handler_and_field_variable(
3334
            $courseId,
3335
            'special_course'
3336
        );
3337
3338
        if (!empty($result)) {
3339
            if ($result['value'] == 1) {
3340
                return true;
3341
            }
3342
        }
3343
3344
        return false;
3345
    }
3346
3347
    /**
3348
     * Update course picture
3349
     * @param   string  Course code
3350
     * @param   string  File name
3351
     * @param   string  The full system name of the image from which course picture will be created.
3352
     * @param   string $cropParameters Optional string that contents "x,y,width,height" of a cropped image format
3353
     * @return  bool    Returns the resulting. In case of internal error or negative validation returns FALSE.
3354
     */
3355
    public static function update_course_picture($course_code, $filename, $source_file = null, $cropParameters = null)
3356
    {
3357
        $course_info = api_get_course_info($course_code);
3358
        // course path
3359
        $store_path = api_get_path(SYS_COURSE_PATH) . $course_info['path'];
3360
        // image name for courses
3361
        $course_image = $store_path . '/course-pic.png';
3362
        $course_medium_image = $store_path . '/course-pic85x85.png';
3363
3364
        if (file_exists($course_image)) {
3365
            unlink($course_image);
3366
        }
3367
        if (file_exists($course_medium_image)) {
3368
            unlink($course_medium_image);
3369
        }
3370
3371
        //Crop the image to adjust 4:3 ratio
3372
        $image = new Image($source_file);
3373
        $image->crop($cropParameters);
3374
3375
        //Resize the images in two formats
3376
        $medium = new Image($source_file);
3377
        $medium->resize(85);
3378
        $medium->send_image($course_medium_image, -1, 'png');
3379
        $normal = new Image($source_file);
3380
        $normal->resize(400);
3381
        $normal->send_image($course_image, -1, 'png');
3382
3383
        $result = $medium && $normal;
3384
3385
        return $result ? $result : false;
3386
    }
3387
3388
    /**
3389
     * Deletes the course picture
3390
     * @param string $courseCode
3391
     */
3392
    public static function deleteCoursePicture($courseCode)
3393
    {
3394
        $course_info = api_get_course_info($courseCode);
3395
        // course path
3396
        $storePath = api_get_path(SYS_COURSE_PATH) . $course_info['path'];
3397
        // image name for courses
3398
        $courseImage = $storePath . '/course-pic.png';
3399
        $courseMediumImage = $storePath . '/course-pic85x85.png';
3400
        $courseSmallImage = $storePath . '/course-pic32.png';
3401
3402
        if (file_exists($courseImage)) {
3403
            unlink($courseImage);
3404
        }
3405
        if (file_exists($courseMediumImage)) {
3406
            unlink($courseMediumImage);
3407
        }
3408
        if (file_exists($courseSmallImage)) {
3409
            unlink($courseSmallImage);
3410
        }
3411
    }
3412
3413
    /**
3414
     * Builds the course block in user_portal.php
3415
     * @todo use Twig
3416
     *
3417
     * @param array $params
3418
     * @return string
3419
     */
3420
    public static function course_item_html_no_icon($params)
3421
    {
3422
        $html = '<div class="course_item">';
3423
        $html .= '<div class="row">';
3424
        $html .= '<div class="col-md-7">';
3425
3426
        $notifications = isset($params['notifications']) ? $params['notifications'] : null;
3427
3428
        $html .= '<h3>' . $params['title'] . $notifications . '</h3> ';
3429
3430
        if (isset($params['description'])) {
3431
            $html .= '<p>' . $params['description'] . '</p>';
3432
        }
3433
        if (!empty($params['subtitle'])) {
3434
            $html .= '<small>' . $params['subtitle'] . '</small>';
3435
        }
3436 View Code Duplication
        if (!empty($params['teachers'])) {
3437
            $html .= '<h5 class="teacher">' . Display::return_icon('teacher.png', get_lang('Teacher'), array(),
3438
                    ICON_SIZE_TINY) . $params['teachers'] . '</h5>';
3439
        }
3440 View Code Duplication
        if (!empty($params['coaches'])) {
3441
            $html .= '<h5 class="teacher">' . Display::return_icon('teacher.png', get_lang('Coach'), array(),
3442
                    ICON_SIZE_TINY) . $params['coaches'] . '</h5>';
3443
        }
3444
3445
        $html .= '</div>';
3446
        $params['right_actions'] = isset($params['right_actions']) ? $params['right_actions'] : null;
3447
        $html .= '<div class="pull-right course-box-actions">' . $params['right_actions'] . '</div>';
3448
        $html .= '</div>';
3449
        $html .= '</div>';
3450
3451
        return $html;
3452
    }
3453
3454
     /**
3455
     * Builds the course block in user_portal.php
3456
     * @todo use Twig
3457
     * @param array $params
3458
     * @param bool|false $is_sub_content
3459
     * @return string
3460
     */
3461
    public static function course_item_html($params, $is_sub_content = false)
3462
    {
3463
        $html = '';
3464
        $class = "panel panel-default";
3465
        if ($is_sub_content) {
3466
            $class = "course_item";
3467
        }
3468
        $html .= '<div class="' . $class . '">';
3469
        $html .= '<div class="panel-body">';
3470
        $html .= '<div class="course-items">';
3471
        $html .= ' <div class="row">';
3472
        $html .= '<div class="col-md-2">';
3473
        if (!empty($params['link'])) {
3474
            $html .= '<a class="thumbnail" href="' . $params['link'] . '">';
3475
            $html .= $params['icon'];
3476
            $html .= '</a>';
3477
        } else {
3478
            $html .= '<div class="thumbnail">';
3479
            $html .= $params['icon'];
3480
            $html .= '</div>';
3481
        }
3482
        $html .= '</div>';
3483
        $notifications = isset($params['notifications']) ? $params['notifications'] : '';
3484
        $param_class = isset($params['class']) ? $params['class'] : '';
3485
        $params['right_actions'] = isset($params['right_actions']) ? $params['right_actions'] : '';
3486
3487
        $html .= '<div class="col-md-10 ' . $param_class . '">';
3488
        $html .= '<div class="pull-right">' . $params['right_actions'] . '</div>';
3489
        $html .= '<h4 class="course-items-title">' . $params['title'] . $notifications . '</h4> ';
3490
3491
        if (isset($params['show_description'], $params['description']) && $params['show_description'] == 1) {
3492
            $html .= '<p class="description-session">' . $params['description'] . '</p>';
3493
        }
3494
        if (!empty($params['subtitle'])) {
3495
            $html .= '<div class="subtitle-session">' . $params['subtitle'] . '</div>';
3496
        }
3497 View Code Duplication
        if (!empty($params['teachers'])) {
3498
            $teachers = $params['teachers'];
3499
            $html .= '<h5 class="course-items-session">' .
3500
                    Display::return_icon('teacher.png', get_lang('Teacher'), array(), ICON_SIZE_TINY) .
3501
                $teachers.'</h5>';
3502
        }
3503
        if (!empty($params['coaches'])) {
3504
            $coaches = '';
3505
            if (is_array($params['coaches'])) {
3506
                foreach ($params['coaches'] as $coach) {
3507
                    $coaches .= $coach['full_name'];
3508
                }
3509
            }
3510
            $html .= '<h5 class="course-items-session">' .
3511
                Display::return_icon('teacher.png', get_lang('Coach'), array(), ICON_SIZE_TINY) .
3512
                $coaches .
3513
                '</h5>';
3514
        }
3515
3516
        $html .= '</div>';
3517
        $html .= '</div>';
3518
3519
        $html .= '</div>';
3520
3521
        $html .= '</div>';
3522
        $html .= '</div>';
3523
3524
        return $html;
3525
    }
3526
3527
    /**
3528
     * @param $courses
3529
     * @return string
3530
     */
3531
    public function parseCourseListData($courses)
3532
    {
3533
        $html = '';
3534
        foreach ($courses as $course) {
3535
            $html .= self::course_item_html($course, true);
3536
        }
3537
3538
        return $html;
3539
    }
3540
3541
    /**
3542
     * @param string $main_content
3543
     * @param string $sub_content
3544
     * @param string $sub_sub_content
3545
     * @return string
3546
     */
3547
    public static function course_item_parent($main_content, $sub_content, $sub_sub_content = null)
3548
    {
3549
        return '<div class="panel panel-default">' . $main_content . $sub_content . $sub_sub_content . '</div>';
3550
    }
3551
3552
    /**
3553
     * @param $params
3554
     * @param bool|false $is_sub_content
3555
     * @return string
3556
     */
3557
    public static function session_items_html($params, $is_sub_content = false)
3558
    {
3559
        $html = '';
3560
        $html .= '<div class="row">';
3561
        $html .= '<div class="col-md-2">';
3562
        if (!empty($params['link'])){
3563
            $html .= '<a class="thumbnail" href="'.$params['link'].'">';
3564
            $html .= $params['icon'];
3565
            $html .= '</a>';
3566
        }else{
3567
            $html .= $params['icon'];
3568
        }
3569
        $html .= '</div>';
3570
        $html .= '<div class="col-md-10">';
3571
        $html .= $params['title'];
3572
        $html .= $params['coaches'];
3573
        $html .= '</div>';
3574
        $html .= '</div>';
3575
3576
        return $html;
3577
    }
3578
3579
    /**
3580
     * Display special courses (and only these) as several HTML divs of class userportal-course-item
3581
     *
3582
     * Special courses are courses that stick on top of the list and are "auto-registerable"
3583
     * in the sense that any user clicking them is registered as a student
3584
     * @param int       $user_id User id
3585
     * @param bool      $load_dirs Whether to show the document quick-loader or not
3586
     * @return string
3587
     */
3588
    public static function returnSpecialCourses($user_id, $load_dirs = false)
3589
    {
3590
        $user_id = intval($user_id);
3591
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
3592
        $specialCourseList = self::get_special_course_list();
3593
3594
        if (empty($specialCourseList)) {
3595
            return [];
3596
        }
3597
3598
        $sql = "SELECT
3599
                id,
3600
                code,
3601
                subscribe subscr,
3602
                unsubscribe unsubscr
3603
            FROM $table                      
3604
            WHERE 
3605
                id IN ('".implode("','", $specialCourseList)."')
3606
            GROUP BY code";
3607
3608
        $rs_special_course = Database::query($sql);
3609
        $number_of_courses = Database::num_rows($rs_special_course);
3610
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
3611
3612
        $courseList = [];
3613
        if ($number_of_courses > 0) {
3614
            while ($course = Database::fetch_array($rs_special_course)) {
3615
                $course_info = api_get_course_info($course['code']);
3616
                $courseId = $course_info['real_id'];
3617
                if ($course_info['visibility'] == COURSE_VISIBILITY_HIDDEN) {
3618
                    continue;
3619
                }
3620
3621
                $params = [];
3622
                // Get notifications.
3623
                $course_info['id_session'] = null;
3624
                $courseUserInfo = CourseManager::getUserCourseInfo($user_id, $courseId);
3625
3626
                if (empty($courseUserInfo)) {
3627
                    $course_info['status'] = STUDENT;
3628
                } else {
3629
                    $course_info['status'] = $courseUserInfo['status'];
3630
                }
3631
                $show_notification = Display::show_notification($course_info);
3632
                $params['edit_actions'] = '';
3633
                $params['document'] = '';
3634
                if (api_is_platform_admin()) {
3635
                    $params['edit_actions'] .= api_get_path(WEB_CODE_PATH) . 'course_info/infocours.php?cidReq=' . $course['code'];
3636
                    if ($load_dirs) {
3637
                    $params['document'] = '<a id="document_preview_' . $courseId . '_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3638
                           . Display::returnFontAwesomeIcon('folder-open') . '</a>';
3639
                    $params['document'] .= Display::div('', ['id' => 'document_result_' . $courseId . '_0', 'class' => 'document_preview_container']);
3640
                    }
3641
                } else {
3642
                    if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED && $load_dirs) {
3643
                    $params['document'] = '<a id="document_preview_' . $courseId . '_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3644
                           . Display::returnFontAwesomeIcon('folder-open') . '</a>';
3645
                    $params['document'] .= Display::div('', ['id' => 'document_result_' . $courseId . '_0', 'class' => 'document_preview_container']);
3646
                    }
3647
                }
3648
3649
                $params['visibility'] = $course_info['visibility'];
3650
                $params['status'] = $course_info['status'];
3651
                $params['category'] = $course_info['categoryName'];
3652
                $params['icon'] = Display::return_icon('drawing-pin.png',null, null, ICON_SIZE_LARGE, null);
3653
3654 View Code Duplication
                if (api_get_setting('display_coursecode_in_courselist') == 'true') {
3655
                    $params['code_course']  = '(' . $course_info['visual_code'] . ')';
3656
                }
3657
3658
                $params['title'] = $course_info['title'];
3659
                $params['link'] = $course_info['course_public_url'].'?id_session=0&autoreg=1';
3660
                if (api_get_setting('display_teacher_in_courselist') === 'true') {
3661
                $params['teachers'] = CourseManager::getTeachersFromCourse($courseId, false);
3662
                }
3663
3664
                if ($showCustomIcon === 'true') {
3665
                    $params['thumbnails'] = $course_info['course_image'];
3666
                    $params['image'] = $course_info['course_image_large'];
3667
                }
3668
3669
                if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
3670
                    $params['notifications'] = $show_notification;
3671
                }
3672
3673
                $params['is_special_course'] = true;
3674
                $courseList[] = $params;
3675
            }
3676
        }
3677
3678
        return $courseList;
3679
    }
3680
3681
    /**
3682
     * Display courses (without special courses) as several HTML divs
3683
     * of course categories, as class userportal-catalog-item.
3684
     * @uses displayCoursesInCategory() to display the courses themselves
3685
     * @param int $user_id
3686
     * @param bool  $load_dirs Whether to show the document quick-loader or not
3687
     * @param integer $user_id
3688
     * @return string
3689
     */
3690
    public static function returnCourses($user_id, $load_dirs = false)
3691
    {
3692
        $user_id = intval($user_id);
3693
        if (empty($user_id)) {
3694
            $user_id = api_get_user_id();
3695
        }
3696
        // Step 1: We get all the categories of the user
3697
        $table = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
3698
        $sql = "SELECT id, title FROM $table
3699
                WHERE user_id = '" . $user_id . "'
3700
                ORDER BY sort ASC";
3701
3702
        $result = Database::query($sql);
3703
        $listItems = [
3704
            'in_category' => [],
3705
            'not_category' => []
3706
        ];
3707
        while ($row = Database::fetch_array($result)) {
3708
            // We simply display the title of the category.
3709
            $courseInCategory = self::returnCoursesCategories(
3710
                $row['id'],
3711
                $load_dirs
3712
            );
3713
3714
            $params = [
3715
                'id_category' => $row ['id'],
3716
                'title_category' => $row['title'],
3717
                'courses' => $courseInCategory
3718
            ];
3719
            $listItems['in_category'][] = $params;
3720
        }
3721
3722
        // Step 2: We display the course without a user category.
3723
        $coursesNotCategory = self::returnCoursesCategories(0, $load_dirs);
3724
3725
        if ($coursesNotCategory) {
3726
            $listItems['not_category'] = $coursesNotCategory;
3727
        }
3728
3729
        return $listItems;
3730
    }
3731
3732
    /**
3733
     *  Display courses inside a category (without special courses) as HTML dics of
3734
     *  class userportal-course-item.
3735
     * @param int      $user_category_id User category id
3736
     * @param bool     $load_dirs Whether to show the document quick-loader or not
3737
     * @return string
3738
     */
3739
    public static function returnCoursesCategories($user_category_id, $load_dirs = false)
3740
    {
3741
        $user_id = api_get_user_id();
3742
        // Table definitions
3743
        $TABLECOURS = Database:: get_main_table(TABLE_MAIN_COURSE);
3744
        $TABLECOURSUSER = Database:: get_main_table(TABLE_MAIN_COURSE_USER);
3745
        $TABLE_ACCESS_URL_REL_COURSE = Database:: get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
3746
        $current_url_id = api_get_current_access_url_id();
3747
3748
        // Get course list auto-register
3749
        $special_course_list = self::get_special_course_list();
3750
3751
        $without_special_courses = '';
3752
        if (!empty($special_course_list)) {
3753
            $without_special_courses = ' AND course.id NOT IN ("' . implode('","', $special_course_list) . '")';
3754
        }
3755
3756
        $sql = "SELECT
3757
                    course.id,
3758
                    course_rel_user.status status
3759
                FROM $TABLECOURS course 
3760
                INNER JOIN $TABLECOURSUSER course_rel_user
3761
                ON (course.id = course_rel_user.c_id)
3762
                INNER JOIN $TABLE_ACCESS_URL_REL_COURSE url
3763
                ON (url.c_id = course.id)
3764
                WHERE
3765
                    course_rel_user.user_id = '" . $user_id . "' AND
3766
                    course_rel_user.user_course_cat = '" . $user_category_id . "'
3767
                    $without_special_courses ";
3768
3769
        // If multiple URL access mode is enabled, only fetch courses
3770
        // corresponding to the current URL.
3771
        if (api_get_multiple_access_url() && $current_url_id != -1) {
3772
            $sql .= " AND url.c_id = course.id AND access_url_id='" . $current_url_id . "'";
3773
        }
3774
        // Use user's classification for courses (if any).
3775
        $sql .= " ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
3776
3777
        $result = Database::query($sql);
3778
3779
        $courseList = array();
3780
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
3781
        // Browse through all courses.
3782
        while ($row = Database::fetch_array($result)) {
3783
            $course_info = api_get_course_info_by_id($row['id']);
3784
            if (isset($course_info['visibility']) &&
3785
                $course_info['visibility'] == COURSE_VISIBILITY_HIDDEN
3786
            ) {
3787
                continue;
3788
            }
3789
            $course_info['id_session'] = null;
3790
            $course_info['status'] = $row['status'];
3791
            // For each course, get if there is any notification icon to show
3792
            // (something that would have changed since the user's last visit).
3793
            $showNotification = Display::show_notification($course_info);
3794
            $iconName = basename($course_info['course_image']);
3795
3796
            $params = array();
3797
            if ($showCustomIcon === 'true' && $iconName != 'course.png') {
3798
                $params['thumbnails'] = $course_info['course_image'];
3799
                $params['image'] = $course_info['course_image_large'];
3800
            }
3801
3802
            $thumbnails = null;
3803
            $image = null;
3804
3805 View Code Duplication
            if ($showCustomIcon === 'true' && $iconName != 'course.png') {
3806
                $thumbnails = $course_info['course_image'];
3807
                $image = $course_info['course_image_large'];
3808
            }else{
3809
                $image = Display::return_icon('session_default.png', null, null, null,null, true);
3810
            }
3811
3812
            $params['course_id'] = $course_info['real_id'];
3813
            $params['edit_actions'] = '';
3814
            $params['document'] = '';
3815 View Code Duplication
            if (api_is_platform_admin()) {
3816
                $params['edit_actions'] .= api_get_path(WEB_CODE_PATH) . 'course_info/infocours.php?cidReq=' . $course_info['code'];
3817
                if ($load_dirs) {
3818
                    $params['document'] = '<a id="document_preview_' . $course_info['real_id'] . '_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3819
                               . Display::returnFontAwesomeIcon('folder-open') . '</a>';
3820
                    $params['document'] .= Display::div('', array('id' => 'document_result_' . $course_info['real_id'] . '_0', 'class' => 'document_preview_container'));
3821
                }
3822
            }
3823
            if ($load_dirs) {
3824
                $params['document'] = '<a id="document_preview_' . $course_info['real_id'] . '_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3825
                    . Display::returnFontAwesomeIcon('folder-open') . '</a>';
3826
                $params['document'] .= Display::div('', array('id' => 'document_result_' . $course_info['real_id'] . '_0', 'class' => 'document_preview_container'));
3827
            }
3828
3829
            $courseUrl = api_get_path(WEB_COURSE_PATH) . $course_info['path'] . '/index.php?id_session=0';
3830
            $teachers = [];
3831
            if (api_get_setting('display_teacher_in_courselist') === 'true') {
3832
                $teachers = CourseManager::getTeachersFromCourse($course_info['real_id'], false);
3833
            }
3834
3835
            $params['status'] = $row['status'];
3836 View Code Duplication
            if (api_get_setting('display_coursecode_in_courselist') == 'true') {
3837
                $params['code_course'] = '(' . $course_info['visual_code'] . ') ';
3838
            }
3839
3840
            $params['visibility'] = $course_info['visibility'];
3841
            $params['link'] = $courseUrl;
3842
            $params['thumbnails'] = $thumbnails;
3843
            $params['image'] = $image;
3844
            $params['title'] = $course_info['title'];
3845
            $params['category'] = $course_info['categoryName'];
3846
            $params['teachers'] = $teachers;
3847
3848
            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
3849
                $params['notifications'] = $showNotification;
3850
            }
3851
3852
            $courseList[] = $params;
3853
        }
3854
3855
        return $courseList;
3856
    }
3857
3858
    /**
3859
     *  Display courses inside a category (without special courses) as HTML dics of
3860
     *  class userportal-course-item.
3861
     * @deprecated use self::returnCoursesCategories(0);
3862
     * @param int      User category id
3863
     * @param bool      Whether to show the document quick-loader or not
3864
     * @return string
3865
     */
3866
    public static function returnCoursesWithoutCategories($user_category_id, $load_dirs = false)
3867
    {
3868
        $user_id = api_get_user_id();
3869
        // Table definitions
3870
        $TABLECOURS = Database:: get_main_table(TABLE_MAIN_COURSE);
3871
        $TABLECOURSUSER = Database:: get_main_table(TABLE_MAIN_COURSE_USER);
3872
        $TABLE_ACCESS_URL_REL_COURSE = Database:: get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
3873
        $current_url_id = api_get_current_access_url_id();
3874
        $courseList = [];
3875
3876
        // Get course list auto-register
3877
        $special_course_list = self::get_special_course_list();
3878
3879
        $without_special_courses = '';
3880
        if (!empty($special_course_list)) {
3881
            $without_special_courses = ' AND course.id NOT IN ("' . implode('","', $special_course_list) . '")';
3882
        }
3883
3884
        $sql = "SELECT
3885
                    course.id,
3886
                    course.title,
3887
                    course.code,
3888
                    course.subscribe subscr,
3889
                    course.unsubscribe unsubscr,
3890
                    course_rel_user.status status,
3891
                    course_rel_user.sort sort,
3892
                    course_rel_user.user_course_cat user_course_cat
3893
                FROM $TABLECOURS course 
3894
                INNER JOIN $TABLECOURSUSER course_rel_user
3895
                ON (course.id = course_rel_user.c_id)
3896
                INNER JOIN $TABLE_ACCESS_URL_REL_COURSE url
3897
                ON (url.c_id = course.id)
3898
                WHERE
3899
                    course_rel_user.user_id = '" . $user_id . "' AND
3900
                    course_rel_user.user_course_cat = '" . $user_category_id . "'
3901
                    $without_special_courses ";
3902
3903
        // If multiple URL access mode is enabled, only fetch courses
3904
        // corresponding to the current URL.
3905
        if (api_get_multiple_access_url() && $current_url_id != -1) {
3906
            $sql .= " AND url.c_id = course.id AND access_url_id='" . $current_url_id . "'";
3907
        }
3908
        // Use user's classification for courses (if any).
3909
        $sql .= " ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
3910
        $result = Database::query($sql);
3911
3912
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
3913
        // Browse through all courses.
3914
        while ($row = Database::fetch_array($result)) {
3915
            $course_info = api_get_course_info($row['code']);
3916
            if (isset($course_info['visibility']) &&
3917
                $course_info['visibility'] == COURSE_VISIBILITY_HIDDEN
3918
            ) {
3919
                continue;
3920
            }
3921
            $course_info['id_session'] = null;
3922
            $course_info['status'] = $row['status'];
3923
3924
            // For each course, get if there is any notification icon to show
3925
            // (something that would have changed since the user's last visit).
3926
            $showNotification = Display::show_notification($course_info);
3927
3928
            $thumbnails = null;
3929
            $image = null;
3930
3931
            $iconName = basename($course_info['course_image']);
3932 View Code Duplication
            if ($showCustomIcon === 'true' && $iconName != 'course.png') {
3933
                $thumbnails = $course_info['course_image'];
3934
                $image = $course_info['course_image_large'];
3935
            }else{
3936
                $image = Display::return_icon('session_default.png', null, null, null,null, true);
3937
            }
3938
3939
            $params = array();
3940
            $params['edit_actions'] = '';
3941
            $params['document'] = '';
3942 View Code Duplication
            if (api_is_platform_admin()) {
3943
                $params['edit_actions'] .= api_get_path(WEB_CODE_PATH) . 'course_info/infocours.php?cidReq=' . $course_info['code'];
3944
                if($load_dirs){
3945
                    $params['document'] = '<a id="document_preview_' . $course_info['real_id'] . '_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3946
                               . Display::returnFontAwesomeIcon('folder-open') . '</a>';
3947
                    $params['document'] .= Display::div('', array('id' => 'document_result_' . $course_info['real_id'] . '_0', 'class' => 'document_preview_container'));
3948
                }
3949
            }
3950
            if ($load_dirs) {
3951
                $params['document'] = '<a id="document_preview_' . $course_info['real_id'] . '_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3952
                    . Display::returnFontAwesomeIcon('folder-open') . '</a>';
3953
                $params['document'] .= Display::div('', array('id' => 'document_result_' . $course_info['real_id'] . '_0', 'class' => 'document_preview_container'));
3954
            }
3955
3956
            $course_title_url = api_get_path(WEB_COURSE_PATH) . $course_info['path'] . '/index.php?id_session=0';
3957
3958
            $teachers = [];
3959
            if (api_get_setting('display_teacher_in_courselist') === 'true') {
3960
                $teachers = CourseManager::getTeachersFromCourse($course_info['real_id'], false);
3961
            }
3962
            $params['status'] = $row['status'];
3963
3964 View Code Duplication
            if (api_get_setting('display_coursecode_in_courselist') == 'true') {
3965
                $params['code_course'] = '(' . $course_info['visual_code'] . ') ';
3966
            }
3967
3968
            $params['visibility'] = $course_info['visibility'];
3969
            $params['link'] = $course_title_url;
3970
            $params['thumbnails'] = $thumbnails;
3971
            $params['image'] = $image;
3972
            $params['title'] = $course_info['title'];
3973
            $params['category'] = $course_info['categoryName'];
3974
            $params['teachers'] = $teachers;
3975
3976
            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
3977
                $params['notifications'] = $showNotification;
3978
            }
3979
3980
            $courseList[] = $params;
3981
        }
3982
3983
        return $courseList;
3984
    }
3985
3986
    /**
3987
     * Retrieves the user defined course categories
3988
     * @param string $userId
3989
     * @return array containing all the titles of the user defined courses with the id as key of the array
3990
     */
3991 View Code Duplication
    public static function get_user_course_categories($userId = '')
3992
    {
3993
        if ($userId == '') {
3994
            $realUserId = api_get_user_id();
3995
        } else {
3996
            $realUserId = $userId;
3997
        }
3998
3999
        $output = array();
4000
        $table_category = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
4001
        $sql = "SELECT * FROM $table_category 
4002
                WHERE user_id = '".intval($realUserId)."'";
4003
        $result = Database::query($sql);
4004
        while ($row = Database::fetch_array($result)) {
4005
            $output[$row['id']] = $row['title'];
4006
        }
4007
        return $output;
4008
    }
4009
4010
    /**
4011
     * Return an array the user_category id and title for the course $courseId for user $userId
4012
     * @param $userId
4013
     * @param $courseId
4014
     * @return array
4015
     */
4016 View Code Duplication
    public static function getUserCourseCategoryForCourse($userId, $courseId)
4017
    {
4018
        $tblCourseRelUser = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4019
        $tblUserCategory = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
4020
        $courseId = intval($courseId);
4021
        $userId = intval($userId);
4022
4023
        $sql = "SELECT user_course_cat, title
4024
                FROM $tblCourseRelUser cru
4025
                LEFT JOIN $tblUserCategory ucc
4026
                ON cru.user_course_cat = ucc.id
4027
                WHERE
4028
                    cru.user_id = $userId AND c_id= $courseId ";
4029
4030
        $res = Database::query($sql);
4031
4032
        $result = array();
4033
        if (Database::num_rows($res) > 0) {
4034
            $data = Database::fetch_assoc($res);
4035
            $result[] = $data['user_course_cat'];
4036
            $result[] = $data['title'];
4037
        }
4038
        return $result;
4039
    }
4040
4041
    /**
4042
     * Get the course id based on the original id and field name in the extra fields.
4043
     * Returns 0 if course was not found
4044
     *
4045
     * @param string $value Original course code
4046
     * @param string $variable Original field name
4047
     * @return array
4048
     */
4049
    public static function getCourseInfoFromOriginalId($value, $variable)
4050
    {
4051
        $extraFieldValue = new ExtraFieldValue('course');
4052
        $result = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
4053
            $variable,
4054
            $value
4055
        );
4056
4057
        if (!empty($result)) {
4058
            $courseInfo = api_get_course_info_by_id($result['item_id']);
4059
            return $courseInfo;
4060
        }
4061
4062
        return [];
4063
    }
4064
4065
    /**
4066
     * Display code for one specific course a logged in user is subscribed to.
4067
     * Shows a link to the course, what's new icons...
4068
     *
4069
     * $my_course['d'] - course directory
4070
     * $my_course['i'] - course title
4071
     * $my_course['c'] - visual course code
4072
     * $my_course['k']  - system course code
4073
     *
4074
     * @param   array       Course details
4075
     * @param   integer     Session ID
4076
     * @param   string      CSS class to apply to course entry
4077
     * @param   boolean     Whether the session is supposedly accessible now
4078
     * (not in the case it has passed and is in invisible/unaccessible mode)
4079
     * @param bool      Whether to show the document quick-loader or not
4080
     * @return  string      The HTML to be printed for the course entry
4081
     *
4082
     * @version 1.0.3
4083
     * @todo refactor into different functions for database calls | logic | display
4084
     * @todo replace single-character $my_course['d'] indices
4085
     * @todo move code for what's new icons to a separate function to clear things up
4086
     * @todo add a parameter user_id so that it is possible to show the
4087
     * courselist of other users (=generalisation).
4088
     * This will prevent having to write a new function for this.
4089
     */
4090
    public static function get_logged_user_course_html(
4091
        $course,
4092
        $session_id = 0,
4093
        $class = 'courses',
4094
        $session_accessible = true,
4095
        $load_dirs = false
4096
    ) {
4097
        $now = date('Y-m-d h:i:s');
4098
        $user_id = api_get_user_id();
4099
        $course_info = api_get_course_info_by_id($course['real_id']);
4100
        $course_visibility = $course_info['visibility'];
4101
4102
        if ($course_visibility == COURSE_VISIBILITY_HIDDEN) {
4103
            return '';
4104
        }
4105
4106
        $userInCourseStatus = CourseManager::getUserInCourseStatus(
4107
            $user_id,
4108
            $course_info['real_id']
4109
        );
4110
4111
        $course_info['status'] = empty($session_id) ? $userInCourseStatus : STUDENT;
4112
        $course_info['id_session'] = $session_id;
4113
4114
        $is_coach = api_is_coach($session_id, $course_info['real_id']);
4115
4116
        // Display course entry.
4117
        // Show a hyperlink to the course, unless the course is closed and user is not course admin.
4118
        $session_url = '';
4119
        $params = array();
4120
        $params['icon'] = Display::return_icon(
4121
            'blackboard_blue.png',
4122
            null,
4123
            array(),
4124
            ICON_SIZE_LARGE,
4125
            null,
4126
            true
4127
        );
4128
4129
        // Display the "what's new" icons
4130
        $notifications = '';
4131
        if ($course_visibility != COURSE_VISIBILITY_CLOSED &&
4132
            $course_visibility != COURSE_VISIBILITY_HIDDEN
4133
        ) {
4134
            $notifications .= Display::show_notification($course_info);
4135
        }
4136
4137
        if ($session_accessible) {
4138
            if ($course_visibility != COURSE_VISIBILITY_CLOSED ||
4139
                $userInCourseStatus == COURSEMANAGER
4140
            ) {
4141
                if (empty($course_info['id_session'])) {
4142
                    $course_info['id_session'] = 0;
4143
                }
4144
4145
                $sessionCourseAvailable = false;
4146
                $sessionCourseStatus = api_get_session_visibility($session_id, $course_info['real_id']);
4147
4148
                if (in_array($sessionCourseStatus,
4149
                    array(SESSION_VISIBLE_READ_ONLY, SESSION_VISIBLE, SESSION_AVAILABLE))) {
4150
                    $sessionCourseAvailable = true;
4151
                }
4152
4153
                if ($userInCourseStatus == COURSEMANAGER || $sessionCourseAvailable) {
4154
                    $session_url = $course_info['course_public_url'] . '?id_session=' . $course_info['id_session'];
4155
                    $session_title = '<a href="' . $session_url. '">'. $course_info['name'] . '</a>'.$notifications;
4156
                } else {
4157
                    $session_title = $course_info['name'];
4158
                }
4159
4160
            } else {
4161
                $session_title =
4162
                    $course_info['name'] . ' ' .
4163
                    Display::tag('span', get_lang('CourseClosed'), array('class' => 'item_closed'));
4164
            }
4165
        } else {
4166
            $session_title = $course_info['name'];
4167
        }
4168
4169
        $thumbnails = null;
4170
        $image = null;
4171
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
4172
        $iconName = basename($course_info['course_image']);
4173
4174 View Code Duplication
        if ($showCustomIcon === 'true' && $iconName != 'course.png') {
4175
            $thumbnails = $course_info['course_image'];
4176
            $image = $course_info['course_image_large'];
4177
        } else {
4178
            $image = Display::return_icon('session_default.png', null, null, null,null, true);
4179
        }
4180
        $params['thumbnails'] = $thumbnails;
4181
        $params['image'] = $image;
4182
        $params['link'] = $session_url;
4183
        $params['title'] = $session_title;
4184
        $params['edit_actions'] = '';
4185
        $params['document'] = '';
4186
4187
        if ($course_visibility != COURSE_VISIBILITY_CLOSED &&
4188
            $course_visibility != COURSE_VISIBILITY_HIDDEN
4189
        ) {
4190
            if (api_is_platform_admin()) {
4191
                $params['edit_actions'] .= api_get_path(WEB_CODE_PATH) . 'course_info/infocours.php?cidReq=' . $course_info['code'];
4192
                if ($load_dirs) {
4193
                    $params['document'] .= '<a id="document_preview_' . $course_info['real_id'] . '_' . $course_info['id_session'] . '" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">' .
4194
                        Display::returnFontAwesomeIcon('folder-open') . '</a>';
4195
                    $params['document'] .= Display::div('', array(
4196
                        'id' => 'document_result_' . $course_info['real_id'] . '_' . $course_info['id_session'],
4197
                        'class' => 'document_preview_container'
4198
                    ));
4199
                }
4200
            }
4201
        }
4202
4203
        if (api_get_setting('display_coursecode_in_courselist') === 'true') {
4204
            $session_title .= ' (' . $course_info['visual_code'] . ') ';
4205
        }
4206
4207
        if (api_get_setting('display_teacher_in_courselist') === 'true') {
4208
            $teacher_list = CourseManager::getTeachersFromCourse(
4209
                $course_info['real_id'],
4210
                false
4211
            );
4212
4213
            $course_coachs = self::get_coachs_from_course(
4214
                $course_info['id_session'],
4215
                $course_info['real_id']
4216
            );
4217
            $params['teachers'] = $teacher_list;
4218
4219
            if (($course_info['status'] == STUDENT && !empty($course_info['id_session'])) ||
4220
                ($is_coach && $course_info['status'] != COURSEMANAGER)
4221
            ) {
4222
                $params['coaches'] = $course_coachs;
4223
            }
4224
        }
4225
4226
        $session_title .= isset($course['special_course']) ? ' ' .
4227
                          Display::return_icon('klipper.png', get_lang('CourseAutoRegister')) : '';
4228
4229
        $params['title'] = $session_title;
4230
        $params['extra'] = '';
4231
        $html = $params;
4232
4233
        $session_category_id = null;
4234
        if (1) {
4235
            $session = '';
4236
            $active = false;
4237
            if (!empty($course_info['id_session'])) {
4238
                $session = api_get_session_info($course_info['id_session']);
4239
                $sessionCoachName = '';
4240
                if (!empty($session['id_coach'])) {
4241
                    $coachInfo = api_get_user_info($session['id_coach']);
4242
                    $sessionCoachName = $coachInfo['complete_name'];
4243
                }
4244
4245
                $session_category_id = CourseManager::get_session_category_id_by_session_id($course_info['id_session']);
4246
4247
                if (
4248
                    $session['access_start_date'] == '0000-00-00 00:00:00' || empty($session['access_start_date']) ||
4249
                    $session['access_start_date'] == '0000-00-00'
4250
                ) {
4251
                    $session['dates'] = '';
4252 View Code Duplication
                    if (api_get_setting('show_session_coach') === 'true') {
4253
                        $session['coach'] = get_lang('GeneralCoach') . ': ' . $sessionCoachName;
4254
                    }
4255
                    $active = true;
4256
                } else {
4257
                    $session ['dates'] = ' - ' . get_lang('From') . ' ' . $session['access_start_date'] . ' ' . get_lang('To') . ' ' . $session['access_end_date'];
4258 View Code Duplication
                    if (api_get_setting('show_session_coach') === 'true') {
4259
                        $session['coach'] = get_lang('GeneralCoach') . ': ' . $sessionCoachName;
4260
                    }
4261
                    $date_start = $session['access_start_date'];
4262
                    $date_end = $session['access_end_date'];
4263
                    $active = !$date_end ? ($date_start <= $now) : ($date_start <= $now && $date_end >= $now);
4264
                }
4265
            }
4266
            $user_course_category = '';
4267
            if (isset($course_info['user_course_cat'])) {
4268
                $user_course_category = $course_info['user_course_cat'];
4269
            }
4270
            $output = array(
4271
                $user_course_category,
4272
                $html,
4273
                $course_info['id_session'],
4274
                $session,
4275
                'active' => $active,
4276
                'session_category_id' => $session_category_id
4277
            );
4278
4279
            if (api_get_setting('allow_skills_tool') === 'true') {
4280
                $entityManager = Database::getManager();
4281
                $objUser = $entityManager->find('ChamiloUserBundle:User', $user_id);
4282
                $objCourse = $entityManager->find('ChamiloCoreBundle:Course', $course['real_id']);
4283
                $objSession = $entityManager->find('ChamiloCoreBundle:Session', $session_id);
4284
4285
                $skill = $entityManager
4286
                    ->getRepository('ChamiloCoreBundle:Skill')
4287
                    ->getLastByUser($objUser, $objCourse, $objSession);
4288
4289
                $output['skill'] = null;
4290
4291
                if ($skill) {
4292
                    $output['skill']['name'] = $skill->getName();
4293
                    $output['skill']['icon'] = $skill->getIcon();
4294
                }
4295
            }
4296
        } else {
4297
            $output = array($course_info['user_course_cat'], $html);
4298
        }
4299
4300
        return $output;
4301
    }
4302
4303
    /**
4304
     *
4305
     * @param    string    source course code
4306
     * @param     int        source session id
4307
     * @param    string    destination course code
4308
     * @param     int        destination session id
4309
     * @param integer $source_session_id
4310
     * @param integer $destination_session_id
4311
     * @return  bool
4312
     */
4313
    public static function copy_course(
4314
        $source_course_code,
4315
        $source_session_id,
4316
        $destination_course_code,
4317
        $destination_session_id,
4318
        $params = array()
4319
    ) {
4320
        $course_info = api_get_course_info($source_course_code);
4321
4322
        if (!empty($course_info)) {
4323
            $cb = new CourseBuilder('', $course_info);
4324
            $course = $cb->build($source_session_id, $source_course_code, true);
4325
            $course_restorer = new CourseRestorer($course);
4326
            $course_restorer->skip_content = $params;
4327
            $course_restorer->restore($destination_course_code, $destination_session_id, true, true);
4328
            return true;
4329
        }
4330
        return false;
4331
    }
4332
4333
    /**
4334
     * A simpler version of the copy_course, the function creates an empty course with an autogenerated course code
4335
     *
4336
     * @param    string    new course title
4337
     * @param    string    source course code
4338
     * @param     int        source session id
4339
     * @param     int        destination session id
4340
     * @param    bool    new copied tools (Exercises and LPs)will be set to invisible by default?
4341
     * @param string $new_title
4342
     *
4343
     * @return     array
4344
     */
4345
    public static function copy_course_simple(
4346
        $new_title,
4347
        $source_course_code,
4348
        $source_session_id = 0,
4349
        $destination_session_id = 0,
4350
        $params = array()
4351
    ) {
4352
        $source_course_info = api_get_course_info($source_course_code);
4353
        if (!empty($source_course_info)) {
4354
            $new_course_code = self::generate_nice_next_course_code($source_course_code);
4355
            if ($new_course_code) {
4356
                $new_course_info = self::create_course($new_title, $new_course_code, false);
4357
                if (!empty($new_course_info['code'])) {
4358
                    $result = self::copy_course($source_course_code, $source_session_id, $new_course_info['code'],
4359
                        $destination_session_id, $params);
4360
                    if ($result) {
4361
                        return $new_course_info;
4362
                    }
4363
                }
4364
            }
4365
        }
4366
4367
        return false;
4368
    }
4369
4370
    /**
4371
     * Creates a new course code based in a given code
4372
     *
4373
     * @param string    wanted code
4374
     * <code>    $wanted_code = 'curse' if there are in the DB codes like curse1 curse2 the function will return: course3</code>
4375
     * if the course code doest not exist in the DB the same course code will be returned
4376
     * @return string    wanted unused code
4377
     */
4378 View Code Duplication
    public static function generate_nice_next_course_code($wanted_code)
4379
    {
4380
        $course_code_ok = !self::course_code_exists($wanted_code);
4381
        if (!$course_code_ok) {
4382
            $wanted_code = CourseManager::generate_course_code($wanted_code);
4383
            $table = Database::get_main_table(TABLE_MAIN_COURSE);
4384
            $wanted_code = Database::escape_string($wanted_code);
4385
            $sql = "SELECT count(id) as count
4386
                    FROM $table
4387
                    WHERE code LIKE '$wanted_code%'";
4388
            $result = Database::query($sql);
4389
            if (Database::num_rows($result) > 0) {
4390
                $row = Database::fetch_array($result);
4391
                $count = $row['count'] + 1;
4392
                $wanted_code = $wanted_code . '_' . $count;
4393
                $result = api_get_course_info($wanted_code);
4394
                if (empty($result)) {
4395
                    return $wanted_code;
4396
                }
4397
            }
4398
4399
            return false;
4400
        }
4401
4402
        return $wanted_code;
4403
    }
4404
4405
    /**
4406
     * Gets the status of the users agreement in a course course-session
4407
     *
4408
     * @param int $user_id
4409
     * @param string $course_code
4410
     * @param int $session_id
4411
     * @return boolean
4412
     */
4413
    public static function is_user_accepted_legal($user_id, $course_code, $session_id = null)
4414
    {
4415
        $user_id = intval($user_id);
4416
        $course_code = Database::escape_string($course_code);
4417
        $session_id = intval($session_id);
4418
4419
        $courseInfo = api_get_course_info($course_code);
4420
        $courseId = $courseInfo['real_id'];
4421
4422
        // Course legal
4423
        $enabled = api_get_plugin_setting('courselegal', 'tool_enable');
4424
4425 View Code Duplication
        if ($enabled == 'true') {
4426
            require_once api_get_path(SYS_PLUGIN_PATH) . 'courselegal/config.php';
4427
            $plugin = CourseLegalPlugin::create();
4428
            return $plugin->isUserAcceptedLegal($user_id, $course_code, $session_id);
4429
        }
4430
4431
        if (empty($session_id)) {
4432
            $table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4433
            $sql = "SELECT legal_agreement FROM $table
4434
                    WHERE user_id = $user_id AND c_id = $courseId ";
4435
            $result = Database::query($sql);
4436
            if (Database::num_rows($result) > 0) {
4437
                $result = Database::fetch_array($result);
0 ignored issues
show
Bug introduced by
It seems like $result can be null; however, fetch_array() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
4438
                if ($result['legal_agreement'] == 1) {
4439
                    return true;
4440
                }
4441
            }
4442
            return false;
4443
        } else {
4444
            $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4445
            $sql = "SELECT legal_agreement FROM $table
4446
                    WHERE user_id = $user_id AND c_id = $courseId AND session_id = $session_id";
4447
            $result = Database::query($sql);
4448
            if (Database::num_rows($result) > 0) {
4449
                $result = Database::fetch_array($result);
0 ignored issues
show
Bug introduced by
It seems like $result can be null; however, fetch_array() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
4450
                if ($result['legal_agreement'] == 1) {
4451
                    return true;
4452
                }
4453
            }
4454
            return false;
4455
        }
4456
    }
4457
4458
    /**
4459
     * Saves the user-course legal agreement
4460
     * @param   int user id
4461
     * @param   string course code
4462
     * @param   int session id
4463
     * @return mixed
4464
     */
4465
    public static function save_user_legal($user_id, $course_code, $session_id = null)
4466
    {
4467
        // Course plugin legal
4468
        $enabled = api_get_plugin_setting('courselegal', 'tool_enable');
4469
4470 View Code Duplication
        if ($enabled == 'true') {
4471
            require_once api_get_path(SYS_PLUGIN_PATH) . 'courselegal/config.php';
4472
            $plugin = CourseLegalPlugin::create();
4473
            return $plugin->saveUserLegal($user_id, $course_code, $session_id);
4474
        }
4475
4476
        $user_id = intval($user_id);
4477
        $course_code = Database::escape_string($course_code);
4478
        $session_id = intval($session_id);
4479
4480
        $courseInfo = api_get_course_info($course_code);
4481
        $courseId = $courseInfo['real_id'];
4482
4483
        if (empty($session_id)) {
4484
            $table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4485
            $sql = "UPDATE $table SET legal_agreement = '1'
4486
                    WHERE user_id = $user_id AND c_id  = $courseId ";
4487
            Database::query($sql);
4488
        } else {
4489
            $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4490
            $sql = "UPDATE  $table SET legal_agreement = '1'
4491
                    WHERE user_id = $user_id AND c_id = $courseId AND session_id = $session_id";
4492
            Database::query($sql);
4493
        }
4494
    }
4495
4496
    /**
4497
     * @param int $user_id
4498
     * @param int $course_id
4499
     * @param int $session_id
4500
     * @param int $url_id
4501
     * @return bool
4502
     */
4503
    public static function get_user_course_vote($user_id, $course_id, $session_id = null, $url_id = null)
4504
    {
4505
        $table_user_course_vote = Database::get_main_table(TABLE_MAIN_USER_REL_COURSE_VOTE);
4506
4507
        $session_id = !isset($session_id) ? api_get_session_id() : intval($session_id);
4508
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4509
        $user_id = intval($user_id);
4510
4511
        if (empty($user_id)) {
4512
            return false;
4513
        }
4514
4515
        $params = array(
4516
            'user_id' => $user_id,
4517
            'c_id' => $course_id,
4518
            'session_id' => $session_id,
4519
            'url_id' => $url_id
4520
        );
4521
4522
        $result = Database::select(
4523
            'vote',
4524
            $table_user_course_vote,
4525
            array(
4526
                'where' => array(
4527
                    'user_id = ? AND c_id = ? AND session_id = ? AND url_id = ?' => $params
4528
                )
4529
            ),
4530
            'first'
4531
        );
4532
        if (!empty($result)) {
4533
            return $result['vote'];
4534
        }
4535
        return false;
4536
    }
4537
4538
    /**
4539
     * @param int $course_id
4540
     * @param int $session_id
4541
     * @param int $url_id
4542
     * @return array
4543
     */
4544
    public static function get_course_ranking($course_id, $session_id = null, $url_id = null)
4545
    {
4546
        $table_course_ranking = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
4547
4548
        $session_id = !isset($session_id) ? api_get_session_id() : intval($session_id);
4549
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4550
        $now = api_get_utc_datetime();
4551
4552
        $params = array(
4553
            'c_id' => $course_id,
4554
            'session_id' => $session_id,
4555
            'url_id' => $url_id,
4556
            'creation_date' => $now,
4557
        );
4558
4559
        $result = Database::select(
4560
            'c_id, accesses, total_score, users',
4561
            $table_course_ranking,
4562
            array('where' => array('c_id = ? AND session_id = ? AND url_id = ?' => $params)),
4563
            'first'
4564
        );
4565
4566
        $point_average_in_percentage = 0;
4567
        $point_average_in_star = 0;
4568
        $users_who_voted = 0;
4569
4570
        if (!empty($result['users'])) {
4571
            $users_who_voted = $result['users'];
4572
            $point_average_in_percentage = round($result['total_score'] / $result['users'] * 100 / 5, 2);
4573
            $point_average_in_star = round($result['total_score'] / $result['users'], 1);
4574
        }
4575
4576
        $result['user_vote'] = false;
4577
4578
        if (!api_is_anonymous()) {
4579
            $result['user_vote'] = self::get_user_course_vote(api_get_user_id(), $course_id, $session_id, $url_id);
4580
        }
4581
4582
        $result['point_average'] = $point_average_in_percentage;
4583
        $result['point_average_star'] = $point_average_in_star;
4584
        $result['users_who_voted'] = $users_who_voted;
4585
4586
        return $result;
4587
    }
4588
4589
    /**
4590
     *
4591
     * Updates the course ranking
4592
     * @param int   course id
4593
     * @param int   session id
4594
     * @param id    url id
4595
     * @param integer $session_id
4596
     * @return array
4597
     **/
4598
    public static function update_course_ranking(
4599
        $course_id = null,
4600
        $session_id = null,
4601
        $url_id = null,
4602
        $points_to_add = null,
4603
        $add_access = true,
4604
        $add_user = true
4605
    ) {
4606
        // Course catalog stats modifications see #4191
4607
        $table_course_ranking = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
4608
4609
        $now = api_get_utc_datetime();
4610
4611
        $course_id = empty($course_id) ? api_get_course_int_id() : intval($course_id);
4612
        $session_id = !isset($session_id) ? api_get_session_id() : intval($session_id);
4613
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4614
4615
        $params = array(
4616
            'c_id' => $course_id,
4617
            'session_id' => $session_id,
4618
            'url_id' => $url_id,
4619
            'creation_date' => $now,
4620
            'total_score' => 0,
4621
            'users' => 0
4622
        );
4623
4624
        $result = Database::select(
4625
            'id, accesses, total_score, users',
4626
            $table_course_ranking,
4627
            array('where' => array('c_id = ? AND session_id = ? AND url_id = ?' => $params)),
4628
            'first'
4629
        );
4630
4631
        // Problem here every time we load the courses/XXXX/index.php course home page we update the access
4632
4633
        if (empty($result)) {
4634
            if ($add_access) {
4635
                $params['accesses'] = 1;
4636
            }
4637
            //The votes and users are empty
4638
            if (isset($points_to_add) && !empty($points_to_add)) {
4639
                $params['total_score'] = intval($points_to_add);
4640
            }
4641
            if ($add_user) {
4642
                $params['users'] = 1;
4643
            }
4644
            $result = Database::insert($table_course_ranking, $params);
4645
        } else {
4646
            $my_params = array();
4647
4648
            if ($add_access) {
4649
                $my_params['accesses'] = intval($result['accesses']) + 1;
4650
            }
4651
            if (isset($points_to_add) && !empty($points_to_add)) {
4652
                $my_params['total_score'] = $result['total_score'] + $points_to_add;
4653
            }
4654
            if ($add_user) {
4655
                $my_params['users'] = $result['users'] + 1;
4656
            }
4657
4658
            if (!empty($my_params)) {
4659
                $result = Database::update(
4660
                    $table_course_ranking,
4661
                    $my_params,
4662
                    array('c_id = ? AND session_id = ? AND url_id = ?' => $params)
4663
                );
4664
            }
4665
        }
4666
4667
        return $result;
4668
    }
4669
4670
    /**
4671
     * Add user vote to a course
4672
     *
4673
     * @param   int user id
4674
     * @param   int vote [1..5]
4675
     * @param   int course id
4676
     * @param   int session id
4677
     * @param   int url id (access_url_id)
4678
     * @return    false|string 'added', 'updated' or 'nothing'
4679
     */
4680
    public static function add_course_vote($user_id, $vote, $course_id, $session_id = null, $url_id = null)
4681
    {
4682
        $table_user_course_vote = Database::get_main_table(TABLE_MAIN_USER_REL_COURSE_VOTE);
4683
        $course_id = empty($course_id) ? api_get_course_int_id() : intval($course_id);
4684
4685
        if (empty($course_id) || empty($user_id)) {
4686
            return false;
4687
        }
4688
4689
        if (!in_array($vote, array(1, 2, 3, 4, 5))) {
4690
            return false;
4691
        }
4692
4693
        $session_id = !isset($session_id) ? api_get_session_id() : intval($session_id);
4694
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4695
        $vote = intval($vote);
4696
4697
        $params = array(
4698
            'user_id' => intval($user_id),
4699
            'c_id' => $course_id,
4700
            'session_id' => $session_id,
4701
            'url_id' => $url_id,
4702
            'vote' => $vote
4703
        );
4704
4705
        $action_done = 'nothing';
4706
4707
        $result = Database::select(
4708
            'id, vote',
4709
            $table_user_course_vote,
4710
            array('where' => array('user_id = ? AND c_id = ? AND session_id = ? AND url_id = ?' => $params)),
4711
            'first'
4712
        );
4713
4714
        if (empty($result)) {
4715
            Database::insert($table_user_course_vote, $params);
4716
            $points_to_add = $vote;
4717
            $add_user = true;
4718
            $action_done = 'added';
4719
        } else {
4720
            $my_params = array('vote' => $vote);
4721
            $points_to_add = $vote - $result['vote'];
4722
            $add_user = false;
4723
4724
            Database::update(
4725
                $table_user_course_vote,
4726
                $my_params,
4727
                array('user_id = ? AND c_id = ? AND session_id = ? AND url_id = ?' => $params)
4728
            );
4729
            $action_done = 'updated';
4730
        }
4731
4732
        // Current points
4733
        if (!empty($points_to_add)) {
4734
            self::update_course_ranking(
4735
                $course_id,
4736
                $session_id,
4737
                $url_id,
4738
                $points_to_add,
4739
                false,
4740
                $add_user
4741
            );
4742
        }
4743
        return $action_done;
4744
    }
4745
4746
    /**
4747
     * Remove course ranking + user votes
4748
     *
4749
     * @param int $course_id
4750
     * @param int $session_id
4751
     * @param int $url_id
4752
     *
4753
     */
4754
    public static function remove_course_ranking($course_id, $session_id, $url_id = null)
4755
    {
4756
        $table_course_ranking = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
4757
        $table_user_course_vote = Database::get_main_table(TABLE_MAIN_USER_REL_COURSE_VOTE);
4758
4759
        if (!empty($course_id) && isset($session_id)) {
4760
            $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4761
            $params = array(
4762
                'c_id' => $course_id,
4763
                'session_id' => $session_id,
4764
                'url_id' => $url_id,
4765
            );
4766
            Database::delete($table_course_ranking, array('c_id = ? AND session_id = ? AND url_id = ?' => $params));
4767
            Database::delete($table_user_course_vote, array('c_id = ? AND session_id = ? AND url_id = ?' => $params));
4768
        }
4769
    }
4770
4771
    /**
4772
     * Returns an array with the hottest courses
4773
     * @param   int $days number of days
4774
     * @param   int $limit number of hottest courses
4775
     * @return array
4776
     */
4777
    public static function return_hot_courses($days = 30, $limit = 6)
4778
    {
4779
        if (api_is_invitee()) {
4780
            return array();
4781
        }
4782
4783
        $limit = intval($limit);
4784
4785
        // Getting my courses
4786
        $my_course_list = CourseManager::get_courses_list_by_user_id(api_get_user_id());
4787
4788
        $my_course_code_list = array();
4789
        foreach ($my_course_list as $course) {
4790
            $my_course_code_list[$course['real_id']] = $course['real_id'];
4791
        }
4792
4793
        if (api_is_drh()) {
4794
            $courses = CourseManager::get_courses_followed_by_drh(api_get_user_id());
4795
            foreach ($courses as $course) {
4796
                $my_course_code_list[$course['real_id']] = $course['real_id'];
4797
            }
4798
        }
4799
4800
        $table_course_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
4801
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
4802
        $table_course_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
4803
4804
        //$table_course_access table uses the now() and interval ...
4805
        $now = api_get_utc_datetime(time());
4806
        $sql = "SELECT COUNT(course_access_id) course_count, a.c_id, visibility
4807
                FROM $table_course c
4808
                INNER JOIN $table_course_access a
4809
                ON (c.id = a.c_id)
4810
                INNER JOIN $table_course_url u
4811
                ON u.c_id = c.id
4812
                WHERE
4813
                    u.access_url_id = " . api_get_current_access_url_id() . " AND
4814
                    login_course_date <= '$now' AND
4815
                    login_course_date > DATE_SUB('$now', INTERVAL $days DAY) AND
4816
                    visibility <> '" . COURSE_VISIBILITY_CLOSED . "' AND visibility <> '" . COURSE_VISIBILITY_HIDDEN . "'
4817
                GROUP BY a.c_id
4818
                ORDER BY course_count DESC
4819
                LIMIT $limit
4820
            ";
4821
4822
        $result = Database::query($sql);
4823
        $courses = array();
4824
4825
        if (Database::num_rows($result)) {
4826
            $courses = Database::store_result($result, 'ASSOC');
4827
            $courses = self::process_hot_course_item($courses, $my_course_code_list);
4828
        }
4829
4830
        return $courses;
4831
    }
4832
4833
    /**
4834
     * @param array $courses
4835
     * @param array $my_course_code_list
4836
     * @return mixed
4837
     */
4838
    public static function process_hot_course_item($courses, $my_course_code_list = array())
4839
    {
4840
        $hotCourses = [];
4841
        $ajax_url = api_get_path(WEB_AJAX_PATH) . 'course.ajax.php?a=add_course_vote';
4842
        $stok = Security::get_existing_token();
4843
        $user_id = api_get_user_id();
4844
4845
        foreach ($courses as $courseId) {
4846
            $course_info = api_get_course_info_by_id($courseId['c_id']);
4847
            $courseCode = $course_info['code'];
4848
            $categoryCode = !empty($course_info['categoryCode']) ? $course_info['categoryCode'] : "";
4849
            $my_course = $course_info;
4850
            $my_course['go_to_course_button'] = '';
4851
            $my_course['register_button'] = '';
4852
4853
            $access_link = self::get_access_link_by_user(
4854
                api_get_user_id(),
4855
                $course_info,
4856
                $my_course_code_list
4857
            );
4858
4859
            $user_registerd_in_course = CourseManager::is_user_subscribed_in_course($user_id, $courseCode);
4860
            $user_registerd_in_course_as_teacher = CourseManager::is_course_teacher($user_id, $courseCode);
4861
            $user_registerd_in_course_as_student = ($user_registerd_in_course && !$user_registerd_in_course_as_teacher);
4862
4863
            // if user registered as student
4864
            if ($user_registerd_in_course_as_student) {
4865
                $icon = '<em class="fa fa-graduation-cap"></em>';
4866
                $title = get_lang("AlreadyRegisteredToCourse");
4867
                $my_course['already_register_as'] = Display::tag(
4868
                    'button',
4869
                    $icon,
4870
                    array('id' => 'register', 'class' => 'btn btn-default btn-sm', 'title' => $title)
4871
                );
4872
            } elseif ($user_registerd_in_course_as_teacher) {
4873
                // if user registered as teacher
4874
                $icon = '<em class="fa fa-suitcase"></em>';
4875
                $title = get_lang("YouAreATeacherOfThisCourse");
4876
                $my_course['already_register_as'] = Display::tag(
4877
                    'button',
4878
                    $icon,
4879
                    array('id' => 'register', 'class' => 'btn btn-default btn-sm', 'title' => $title)
4880
                );
4881
            }
4882
4883
            //Course visibility
4884 View Code Duplication
            if ($access_link && in_array('register', $access_link)) {
4885
                $my_course['register_button'] = Display::url(
4886
                    Display::returnFontAwesomeIcon('sign-in'),
4887
                    api_get_path(WEB_COURSE_PATH) . $course_info['path'] . '/index.php?action=subscribe&sec_token=' . $stok,
4888
                    array('class' => 'btn btn-success btn-sm', 'title' => get_lang('Subscribe')));
4889
            }
4890
4891 View Code Duplication
            if ($access_link && in_array('enter',
4892
                    $access_link) || $course_info['visibility'] == COURSE_VISIBILITY_OPEN_WORLD
4893
            ) {
4894
                $my_course['go_to_course_button'] = Display::url(
4895
                    Display::returnFontAwesomeIcon('share'),
4896
                    api_get_path(WEB_COURSE_PATH) . $course_info['path'] . '/index.php',
4897
                    array('class' => 'btn btn-default btn-sm', 'title' => get_lang('GoToCourse')));
4898
            }
4899
4900
            if ($access_link && in_array('unsubscribe', $access_link)) {
4901
                $my_course['unsubscribe_button'] = Display::url(
4902
                    Display::returnFontAwesomeIcon('sign-out'),
4903
                    api_get_path(WEB_CODE_PATH) . 'auth/courses.php?action=unsubscribe&unsubscribe=' . $courseCode . '&sec_token=' . $stok . '&category_code=' . $categoryCode,
4904
                    array('class' => 'btn btn-danger btn-sm', 'title' => get_lang('Unreg')));
4905
            }
4906
4907
            // start buycourse validation
4908
            // display the course price and buy button if the buycourses plugin is enabled and this course is configured
4909
            $plugin = BuyCoursesPlugin::create();
4910
            $isThisCourseInSale = $plugin->buyCoursesForGridCatalogVerificator($course_info['real_id'], BuyCoursesPlugin::PRODUCT_TYPE_COURSE);
4911
            if ($isThisCourseInSale) {
4912
                // set the price label
4913
                $my_course['price'] = $isThisCourseInSale['html'];
4914
                // set the Buy button instead register.
4915
                if ($isThisCourseInSale['verificator'] && !empty($my_course['register_button'])) {
4916
                    $my_course['register_button'] = $plugin->returnBuyCourseButton($course_info['real_id'], BuyCoursesPlugin::PRODUCT_TYPE_COURSE);
4917
                }
4918
            }
4919
            // end buycourse validation
4920
4921
            //Description
4922
            $my_course['description_button'] = '';
4923
            /* if ($course_info['visibility'] == COURSE_VISIBILITY_OPEN_WORLD || in_array($course_info['real_id'],
4924
                    $my_course_code_list)
4925
            ) { */
4926
                $my_course['description_button'] = Display::url(
4927
                    Display::returnFontAwesomeIcon('info-circle'),
4928
                    api_get_path(WEB_AJAX_PATH) . 'course_home.ajax.php?a=show_course_information&code=' . $course_info['code'],
4929
                    [
4930
                        'class' => 'btn btn-default btn-sm ajax',
4931
                        'data-title' => get_lang('Description'),
4932
                        'title' => get_lang('Description')
4933
                    ]
4934
                );
4935
            //}
4936
            /* get_lang('Description') */
4937
            $my_course['teachers'] = CourseManager::getTeachersFromCourse($course_info['real_id'], false);
4938
            $point_info = self::get_course_ranking($course_info['real_id'], 0);
4939
            $my_course['rating_html'] = Display::return_rating_system('star_' . $course_info['real_id'],
4940
                $ajax_url . '&course_id=' . $course_info['real_id'], $point_info);
4941
4942
            $hotCourses[] = $my_course;
4943
        }
4944
4945
        return $hotCourses;
4946
    }
4947
4948
    /**
4949
     * @param int $limit
4950
     * @return array
4951
     */
4952
    public static function return_most_accessed_courses($limit = 5)
4953
    {
4954
        $table_course_ranking = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
4955
        $params['url_id'] = api_get_current_access_url_id();
4956
4957
        $result = Database::select(
4958
            'c_id, accesses, total_score, users',
4959
            $table_course_ranking,
4960
            array('where' => array('url_id = ?' => $params), 'order' => 'accesses DESC', 'limit' => $limit),
4961
            'all',
4962
            true
4963
        );
4964
4965
        return $result;
4966
    }
4967
4968
    /**
4969
     * Get courses count
4970
     * @param int Access URL ID (optional)
4971
     * @param int $visibility
4972
     * @param integer $access_url_id
4973
     *
4974
     * @return int Number of courses
4975
     */
4976
    public static function count_courses($access_url_id = null, $visibility = null)
4977
    {
4978
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
4979
        $table_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
4980
        $sql = "SELECT count(c.id) FROM $table_course c";
4981
        if (!empty($access_url_id) && $access_url_id == intval($access_url_id)) {
4982
            $sql .= ", $table_course_rel_access_url u
4983
                    WHERE c.id = u.c_id AND u.access_url_id = $access_url_id";
4984
            if (!empty($visibility)) {
4985
                $visibility = intval($visibility);
4986
                $sql .= " AND visibility = $visibility ";
4987
            }
4988
        } else {
4989
            if (!empty($visibility)) {
4990
                $visibility = intval($visibility);
4991
                $sql .= " WHERE visibility = $visibility ";
4992
            }
4993
        }
4994
4995
        $res = Database::query($sql);
4996
        $row = Database::fetch_row($res);
4997
4998
        return $row[0];
4999
    }
5000
5001
    /**
5002
     * Get active courses count.
5003
     * Active = all courses except the ones with hidden visibility.
5004
     *
5005
     * @param int $urlId Access URL ID (optional)
5006
     * @return int Number of courses
5007
     */
5008
    public static function countActiveCourses($urlId = null)
5009
    {
5010
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
5011
        $table_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
5012
        $sql = "SELECT count(id) FROM $table_course c";
5013
        if (!empty($urlId) && $urlId == intval($urlId)) {
5014
            $sql .= ", $table_course_rel_access_url u
5015
                    WHERE
5016
                        c.id = u.c_id AND
5017
                        u.access_url_id = $urlId AND
5018
                        visibility <> " . COURSE_VISIBILITY_HIDDEN;
5019
        } else {
5020
            $sql .= " WHERE visibility <> " . COURSE_VISIBILITY_HIDDEN;
5021
        }
5022
        $res = Database::query($sql);
5023
        $row = Database::fetch_row($res);
5024
        return $row[0];
5025
    }
5026
5027
    /**
5028
     * Returns the SQL conditions to filter course only visible by the user in the catalogue
5029
     *
5030
     * @param $courseTableAlias Alias of the course table
5031
     * @return string SQL conditions
5032
     */
5033
    public static function getCourseVisibilitySQLCondition($courseTableAlias) {
5034
        $visibilityCondition = '';
5035
        $hidePrivate = api_get_setting('course_catalog_hide_private');
5036
        if ($hidePrivate === 'true') {
5037
            $visibilityCondition = ' AND '.$courseTableAlias.'.visibility <> 1';
5038
        }
5039
5040
        // Check if course have users allowed to see it in the catalogue, then show only if current user is allowed to see it
5041
        $currentUserId = api_get_user_id();
5042
        $restrictedCourses = self::getCatalogueCourseList(true);
5043
        $allowedCoursesToCurrentUser = self::getCatalogueCourseList(true, $currentUserId);
5044 View Code Duplication
        if (!empty($restrictedCourses)) {
5045
            $visibilityCondition .= ' AND ('.$courseTableAlias.'.code NOT IN ("' . implode('","', $restrictedCourses) . '")';
5046
            $visibilityCondition .= ' OR '.$courseTableAlias.'.code IN ("' . implode('","', $allowedCoursesToCurrentUser) . '"))';
5047
        }
5048
5049
        // Check if course have users denied to see it in the catalogue, then show only if current user is not denied to see it
5050
        $restrictedCourses = self::getCatalogueCourseList(false);
5051
        $notAllowedCoursesToCurrentUser = self::getCatalogueCourseList(false, $currentUserId);
5052 View Code Duplication
        if (!empty($restrictedCourses)) {
5053
            $visibilityCondition .= ' AND ('.$courseTableAlias.'.code NOT IN ("' . implode('","', $restrictedCourses) . '")';
5054
            $visibilityCondition .= ' OR '.$courseTableAlias.'.code NOT IN ("' . implode('","', $notAllowedCoursesToCurrentUser) . '"))';
5055
        }
5056
5057
        return $visibilityCondition;
5058
    }
5059
5060
    /**
5061
     * Get available le courses count
5062
     * @param int Access URL ID (optional)
5063
     * @param integer $accessUrlId
5064
     * @return int Number of courses
5065
     */
5066
    public static function countAvailableCourses($accessUrlId = null)
5067
    {
5068
        $tableCourse = Database::get_main_table(TABLE_MAIN_COURSE);
5069
        $tableCourseRelAccessUrl = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
5070
        $specialCourseList = self::get_special_course_list();
5071
5072
        $withoutSpecialCourses = '';
5073
        if (!empty($specialCourseList)) {
5074
            $withoutSpecialCourses = ' AND c.id NOT IN ("' . implode('","', $specialCourseList) . '")';
5075
        }
5076
5077
        $visibilityCondition = self::getCourseVisibilitySQLCondition('c');
5078
5079
        if (!empty($accessUrlId) && $accessUrlId == intval($accessUrlId)) {
5080
            $sql = "SELECT count(c.id) FROM $tableCourse c, $tableCourseRelAccessUrl u
5081
                    WHERE
5082
                        c.id = u.c_id AND
5083
                        u.access_url_id = $accessUrlId AND
5084
                        c.visibility != 0 AND
5085
                        c.visibility != 4
5086
                        $withoutSpecialCourses
5087
                        $visibilityCondition
5088
                    ";
5089
        }
5090
        $res = Database::query($sql);
5091
        $row = Database::fetch_row($res);
5092
5093
        return $row[0];
5094
    }
5095
5096
    /**
5097
     * Return a link to go to the course, validating the visibility of the
5098
     * course and the user status
5099
     * @param int User ID
5100
     * @param array Course details array
5101
     * @param array  List of courses to which the user is subscribed (if not provided, will be generated)
5102
     * @param integer $uid
5103
     * @return mixed 'enter' for a link to go to the course or 'register' for a link to subscribe, or false if no access
5104
     */
5105
    static function get_access_link_by_user($uid, $course, $user_courses = array())
5106
    {
5107
        if (empty($uid) or empty($course)) {
5108
            return false;
5109
        }
5110
5111
        if (empty($user_courses)) {
5112
            // get the array of courses to which the user is subscribed
5113
            $user_courses = CourseManager::get_courses_list_by_user_id($uid);
5114
            foreach ($user_courses as $k => $v) {
5115
                $user_courses[$k] = $v['real_id'];
5116
            }
5117
        }
5118
5119
        if (!isset($course['real_id']) && empty($course['real_id'])) {
5120
            $course = api_get_course_info($course['code']);
5121
        }
5122
5123
        if ($course['visibility'] == COURSE_VISIBILITY_HIDDEN) {
5124
            return array();
5125
        }
5126
5127
        $is_admin = api_is_platform_admin_by_id($uid);
5128
        $options = array();
5129
        // Register button
5130
        if (!api_is_anonymous($uid) &&
5131
            (
5132
            ($course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD || $course['visibility'] == COURSE_VISIBILITY_OPEN_PLATFORM)
5133
                //$course['visibility'] == COURSE_VISIBILITY_REGISTERED && $course['subscribe'] == SUBSCRIBE_ALLOWED
5134
            ) &&
5135
            $course['subscribe'] == SUBSCRIBE_ALLOWED &&
5136
            (!in_array($course['real_id'], $user_courses) || empty($user_courses))
5137
        ) {
5138
            $options[] = 'register';
5139
        }
5140
5141
        // Go To Course button (only if admin, if course public or if student already subscribed)
5142 View Code Duplication
        if ($is_admin ||
5143
            $course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD && empty($course['registration_code']) ||
5144
            (api_user_is_login($uid) && $course['visibility'] == COURSE_VISIBILITY_OPEN_PLATFORM && empty($course['registration_code'])) ||
5145
            (in_array($course['real_id'], $user_courses) && $course['visibility'] != COURSE_VISIBILITY_CLOSED)
5146
        ) {
5147
            $options[] = 'enter';
5148
        }
5149
5150 View Code Duplication
        if ($is_admin ||
5151
            $course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD && empty($course['registration_code']) ||
5152
            (api_user_is_login($uid) && $course['visibility'] == COURSE_VISIBILITY_OPEN_PLATFORM && empty($course['registration_code'])) ||
5153
            (in_array($course['real_id'], $user_courses) && $course['visibility'] != COURSE_VISIBILITY_CLOSED)
5154
        ) {
5155
            $options[] = 'enter';
5156
        }
5157
5158
        if ($course['visibility'] != COURSE_VISIBILITY_HIDDEN && empty($course['registration_code']) && $course['unsubscribe'] == UNSUBSCRIBE_ALLOWED && api_user_is_login($uid) && (in_array($course['real_id'],
5159
                $user_courses))
5160
        ) {
5161
            $options[] = 'unsubscribe';
5162
        }
5163
5164
        return $options;
5165
    }
5166
5167
    /**
5168
     * @param array $courseInfo
5169
     * @param array $teachers
5170
     * @param bool $deleteTeachersNotInList
5171
     * @param bool $editTeacherInSessions
5172
     * @param bool $deleteSessionTeacherNotInList
5173
     * @param array $teacherBackup
5174
     *
5175
     * @return false|null
5176
     */
5177
    public static function updateTeachers(
5178
        $courseInfo,
5179
        $teachers,
5180
        $deleteTeachersNotInList = true,
5181
        $editTeacherInSessions = false,
5182
        $deleteSessionTeacherNotInList = false,
5183
        $teacherBackup = array()
5184
    ) {
5185
        if (!is_array($teachers)) {
5186
            $teachers = array($teachers);
5187
        }
5188
5189
        if (empty($courseInfo) || !isset($courseInfo['real_id'])) {
5190
            return false;
5191
        }
5192
5193
        $teachers = array_filter($teachers);
5194
        $courseId = $courseInfo['real_id'];
5195
        $course_code = $courseInfo['code'];
5196
5197
        $course_user_table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5198
        $alreadyAddedTeachers = CourseManager::get_teacher_list_from_course_code($course_code);
5199
5200
        if ($deleteTeachersNotInList) {
5201
            // Delete only teacher relations that doesn't match the selected teachers
5202
            $cond = null;
5203
            if (count($teachers) > 0) {
5204
                foreach ($teachers as $key) {
5205
                    $key = Database::escape_string($key);
5206
                    $cond .= " AND user_id <> '" . $key . "'";
5207
                }
5208
            }
5209
5210
            // Recover user categories
5211
            $sql = 'SELECT * FROM ' . $course_user_table . '
5212
                    WHERE c_id ="' . $courseId . '" AND status="1" AND relation_type = 0 ' . $cond;
5213
            $result = Database::query($sql);
5214
            if (Database::num_rows($result)) {
5215
                $teachersToDelete = Database::store_result($result, 'ASSOC');
5216
                foreach ($teachersToDelete as $data) {
5217
                    $userId = $data['user_id'];
5218
                    $teacherBackup[$userId][$course_code] = $data;
5219
                }
5220
            }
5221
5222
            $sql = 'DELETE FROM ' . $course_user_table . '
5223
                    WHERE c_id ="' . $courseId . '" AND status="1" AND relation_type = 0 ' . $cond;
5224
5225
            Database::query($sql);
5226
        }
5227
5228
        if (count($teachers) > 0) {
5229
            foreach ($teachers as $userId) {
5230
                $userId = intval($userId);
5231
                // We check if the teacher is already subscribed in this course
5232
                $sql = 'SELECT 1 FROM ' . $course_user_table . '
5233
                        WHERE user_id = "' . $userId . '" AND c_id = "' . $courseId . '" ';
5234
                $result = Database::query($sql);
5235
                if (Database::num_rows($result)) {
5236
                    $sql = 'UPDATE ' . $course_user_table . ' 
5237
                            SET status = "1"
5238
                            WHERE c_id = "' . $courseId . '" AND user_id = "' . $userId . '"  ';
5239
                } else {
5240
                    $userCourseCategory = '0';
5241 View Code Duplication
                    if (isset($teacherBackup[$userId]) &&
5242
                        isset($teacherBackup[$userId][$course_code])
5243
                    ) {
5244
                        $courseUserData = $teacherBackup[$userId][$course_code];
5245
                        $userCourseCategory = $courseUserData['user_course_cat'];
5246
                    }
5247
5248
                    $sql = "INSERT INTO " . $course_user_table . " SET
5249
                            c_id = " . $courseId . ",
5250
                            user_id = " . $userId . ",
5251
                            status = '1',
5252
                            is_tutor = '0',
5253
                            sort = '0',
5254
                            relation_type = '0',
5255
                            user_course_cat = '$userCourseCategory'
5256
                    ";
5257
                }
5258
                Database::query($sql);
5259
            }
5260
        }
5261
5262
        if ($editTeacherInSessions) {
5263
            $sessions = SessionManager::get_session_by_course($courseId);
5264
5265
            if (!empty($sessions)) {
5266
                foreach ($sessions as $session) {
5267
                    // Remove old and add new
5268
                    if ($deleteSessionTeacherNotInList) {
5269
                        foreach ($teachers as $userId) {
5270
                            SessionManager::set_coach_to_course_session(
5271
                                $userId,
5272
                                $session['id'],
5273
                                $courseId
5274
                            );
5275
                        }
5276
5277
                        $teachersToDelete = array();
5278
                        if (!empty($alreadyAddedTeachers)) {
5279
                            $teachersToDelete = array_diff(array_keys($alreadyAddedTeachers), $teachers);
5280
                        }
5281
5282
                        if (!empty($teachersToDelete)) {
5283
                            foreach ($teachersToDelete as $userId) {
5284
                                SessionManager::set_coach_to_course_session(
5285
                                    $userId,
5286
                                    $session['id'],
5287
                                    $courseId,
5288
                                    true
5289
                                );
5290
                            }
5291
                        }
5292
                    } else {
5293
                        // Add new teachers only
5294
                        foreach ($teachers as $userId) {
5295
                            SessionManager::set_coach_to_course_session(
5296
                                $userId,
5297
                                $session['id'],
5298
                                $courseId
5299
                            );
5300
                        }
5301
                    }
5302
                }
5303
            }
5304
        }
5305
    }
5306
5307
    /**
5308
     * Course available settings variables see c_course_setting table
5309
     * @param AppPlugin $appPlugin
5310
     * @return array
5311
     */
5312
    public static function getCourseSettingVariables(AppPlugin $appPlugin)
5313
    {
5314
        $pluginCourseSettings = $appPlugin->getAllPluginCourseSettings();
5315
        $courseSettings = array(
5316
            // Get allow_learning_path_theme from table
5317
            'allow_learning_path_theme',
5318
            // Get allow_open_chat_window from table
5319
            'allow_open_chat_window',
5320
            'allow_public_certificates',
5321
            // Get allow_user_edit_agenda from table
5322
            'allow_user_edit_agenda',
5323
            // Get allow_user_edit_announcement from table
5324
            'allow_user_edit_announcement',
5325
            // Get allow_user_image_forum from table
5326
            'allow_user_image_forum',
5327
            //Get allow show user list
5328
            'allow_user_view_user_list',
5329
            // Get course_theme from table
5330
            'course_theme',
5331
            //Get allow show user list
5332
            'display_info_advance_inside_homecourse',
5333
            'documents_default_visibility',
5334
            // Get send_mail_setting (work)from table
5335
            'email_alert_manager_on_new_doc',
5336
            // Get send_mail_setting (work)from table
5337
            'email_alert_manager_on_new_quiz',
5338
            // Get send_mail_setting (dropbox) from table
5339
            'email_alert_on_new_doc_dropbox',
5340
            'email_alert_students_on_new_homework',
5341
            // Get send_mail_setting (auth)from table
5342
            'email_alert_to_teacher_on_new_user_in_course',
5343
            'enable_lp_auto_launch',
5344
            'pdf_export_watermark_text',
5345
            'show_system_folders',
5346
            'exercise_invisible_in_session',
5347
            'enable_forum_auto_launch',
5348
            'show_course_in_user_language'
5349
        );
5350
5351
        $allowLPReturnLink = api_get_setting('allow_lp_return_link');
5352
        if ($allowLPReturnLink === 'true') {
5353
            $courseSettings[] = 'lp_return_link';
5354
        }
5355
5356
        if (!empty($pluginCourseSettings)) {
5357
            $courseSettings = array_merge(
5358
                $courseSettings,
5359
                $pluginCourseSettings
5360
            );
5361
        }
5362
5363
        return $courseSettings;
5364
    }
5365
5366
    /**
5367
     * @param AppPlugin $appPlugin
5368
     * @param string $variable
5369
     * @param string $value
5370
     * @param int $courseId
5371
     * @return bool
5372
     */
5373
    public static function saveCourseConfigurationSetting(AppPlugin $appPlugin, $variable, $value, $courseId)
5374
    {
5375
        $settingList = self::getCourseSettingVariables($appPlugin);
5376
5377
        if (!in_array($variable, $settingList)) {
5378
5379
            return false;
5380
        }
5381
5382
        $courseSettingTable = Database::get_course_table(TABLE_COURSE_SETTING);
5383
        if (self::hasCourseSetting($variable, $courseId)) {
5384
            // Update
5385
            Database::update(
5386
                $courseSettingTable,
5387
                array('value' => $value),
5388
                array('variable = ? AND c_id = ?' => array($variable, $courseId))
5389
            );
5390
        } else {
5391
            // Create
5392
            Database::insert(
5393
                $courseSettingTable,
5394
                ['title' => $variable, 'value' => $value, 'c_id' => $courseId, 'variable' => $variable]
5395
            );
5396
        }
5397
        return true;
5398
    }
5399
5400
    /**
5401
     * Check if course setting exists
5402
     * @param string $variable
5403
     * @param int $courseId
5404
     * @return bool
5405
     */
5406 View Code Duplication
    public static function hasCourseSetting($variable, $courseId)
5407
    {
5408
        $courseSetting = Database::get_course_table(TABLE_COURSE_SETTING);
5409
        $courseId = intval($courseId);
5410
        $variable = Database::escape_string($variable);
5411
        $sql = "SELECT variable FROM $courseSetting
5412
                WHERE c_id = $courseId AND variable = '$variable'";
5413
        $result = Database::query($sql);
5414
5415
        return Database::num_rows($result) > 0;
5416
    }
5417
5418
    /**
5419
     * Get information from the track_e_course_access table
5420
     * @param int $sessionId
5421
     * @param int $userId
5422
     * @return array
5423
     */
5424 View Code Duplication
    public static function getCourseAccessPerSessionAndUser($sessionId, $userId, $limit = null)
5425
    {
5426
        $table = Database:: get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
5427
5428
        $sessionId = intval($sessionId);
5429
        $userId = intval($userId);
5430
5431
        $sql = "SELECT * FROM $table
5432
                WHERE session_id = $sessionId AND user_id = $userId";
5433
5434
        if (!empty($limit)) {
5435
            $limit = intval($limit);
5436
            $sql .= " LIMIT $limit";
5437
        }
5438
        $result = Database::query($sql);
5439
5440
        return Database::store_result($result);
5441
    }
5442
5443
    /**
5444
     * Get information from the track_e_course_access table
5445
     * @param int $courseId
5446
     * @param int $sessionId
5447
     * @param string $startDate
5448
     * @param string $endDate
5449
     * @return array
5450
     */
5451
    public static function getCourseAccessPerCourseAndSession(
5452
        $courseId,
5453
        $sessionId,
5454
        $startDate,
5455
        $endDate
5456
    ) {
5457
        $table = Database:: get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
5458
        $courseId = intval($courseId);
5459
        $sessionId = intval($sessionId);
5460
        $startDate = Database::escape_string($startDate);
5461
        $endDate = Database::escape_string($endDate);
5462
5463
        $sql = "SELECT * FROM $table
5464
                WHERE
5465
                    c_id = $courseId AND
5466
                    session_id = $sessionId AND
5467
                    login_course_date BETWEEN '$startDate' AND '$endDate'
5468
                ";
5469
5470
        $result = Database::query($sql);
5471
5472
        return Database::store_result($result);
5473
    }
5474
5475
    /**
5476
     * Get login information from the track_e_course_access table, for any
5477
     * course in the given session
5478
     * @param int $sessionId
5479
     * @param int $userId
5480
     * @return array
5481
     */
5482
    public static function getFirstCourseAccessPerSessionAndUser($sessionId, $userId)
5483
    {
5484
        $sessionId = intval($sessionId);
5485
        $userId = intval($userId);
5486
5487
        $table = Database:: get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
5488
        $sql = "SELECT * FROM $table
5489
                WHERE session_id = $sessionId AND user_id = $userId
5490
                ORDER BY login_course_date ASC
5491
                LIMIT 1";
5492
5493
        $result = Database::query($sql);
5494
        $courseAccess = array();
5495
        if (Database::num_rows($result)) {
5496
            $courseAccess = Database::fetch_array($result, 'ASSOC');
5497
        }
5498
        return $courseAccess;
5499
    }
5500
5501
    /**
5502
     * @param int $courseId
5503
     * @param int $sessionId
5504
     * @param bool $getAllSessions
5505
     * @return mixed
5506
     */
5507
    public static function getCountForum(
5508
        $courseId,
5509
        $sessionId = 0,
5510
        $getAllSessions = false
5511
    ) {
5512
        $forum = Database::get_course_table(TABLE_FORUM);
5513
        if ($getAllSessions) {
5514
            $sql = "SELECT count(*) as count
5515
                    FROM $forum f
5516
                    WHERE f.c_id = %s";
5517
        } else {
5518
            $sql = "SELECT count(*) as count
5519
                    FROM $forum f
5520
                    WHERE f.c_id = %s and f.session_id = %s";
5521
        }
5522
5523
        $sql = sprintf($sql, intval($courseId), intval($sessionId));
5524
        $result = Database::query($sql);
5525
        $row = Database::fetch_array($result);
5526
5527
        return $row['count'];
5528
    }
5529
5530
    /**
5531
     * @param int $userId
5532
     * @param int $courseId
5533
     * @param int $sessionId
5534
     * @return mixed
5535
     */
5536
    public static function getCountPostInForumPerUser(
5537
        $userId,
5538
        $courseId,
5539
        $sessionId = 0
5540
    ) {
5541
        $forum = Database::get_course_table(TABLE_FORUM);
5542
        $forum_post = Database::get_course_table(TABLE_FORUM_POST);
5543
5544
        $sql = "SELECT count(distinct post_id) as count
5545
                FROM $forum_post p
5546
                INNER JOIN $forum f
5547
                ON f.forum_id = p.forum_id AND f.c_id = p.c_id
5548
                WHERE p.poster_id = %s and f.session_id = %s and p.c_id = %s";
5549
5550
        $sql = sprintf(
5551
            $sql,
5552
            intval($userId),
5553
            intval($sessionId),
5554
            intval($courseId)
5555
        );
5556
5557
        $result = Database::query($sql);
5558
        $row = Database::fetch_array($result);
5559
        return $row['count'];
5560
    }
5561
5562
    /**
5563
     * @param int $userId
5564
     * @param int $courseId
5565
     * @param int $sessionId
5566
     * @return mixed
5567
     */
5568
    public static function getCountForumPerUser(
5569
        $userId,
5570
        $courseId,
5571
        $sessionId = 0
5572
    ) {
5573
        $forum = Database::get_course_table(TABLE_FORUM);
5574
        $forum_post = Database::get_course_table(TABLE_FORUM_POST);
5575
5576
        $sql = "SELECT count(distinct f.forum_id) as count
5577
                FROM $forum_post p
5578
                INNER JOIN $forum f
5579
                ON f.forum_id = p.forum_id AND f.c_id = p.c_id
5580
                WHERE p.poster_id = %s and f.session_id = %s and p.c_id = %s";
5581
5582
        $sql = sprintf(
5583
            $sql,
5584
            intval($userId),
5585
            intval($sessionId),
5586
            intval($courseId)
5587
        );
5588
5589
        $result = Database::query($sql);
5590
        $row = Database::fetch_array($result);
5591
        return $row['count'];
5592
    }
5593
5594
    /**
5595
     * Returns the course name from a given code
5596
     * @param string $code
5597
     */
5598 View Code Duplication
    public static function getCourseNameFromCode($code)
5599
    {
5600
        $tbl_main_categories = Database:: get_main_table(TABLE_MAIN_COURSE);
5601
        $sql = 'SELECT title
5602
                FROM ' . $tbl_main_categories . '
5603
                WHERE code = "' . Database::escape_string($code) . '"';
5604
        $result = Database::query($sql);
5605
        if ($col = Database::fetch_array($result)) {
5606
            return $col['title'];
5607
        }
5608
    }
5609
5610
    /**
5611
     * Generates a course code from a course title
5612
     * @todo Such a function might be useful in other places too. It might be moved in the CourseManager class.
5613
     * @todo the function might be upgraded for avoiding code duplications (currently, it might suggest a code that is already in use)
5614
     * @param string $title A course title
5615
     * @return string A proposed course code
5616
     * +
5617
     * @assert (null,null) === false
5618
     * @assert ('ABC_DEF', null) === 'ABCDEF'
5619
     * @assert ('ABC09*^[%A', null) === 'ABC09A'
5620
     */
5621
    public static function generate_course_code($title)
5622
    {
5623
        return substr(
5624
            preg_replace('/[^A-Z0-9]/', '', strtoupper(api_replace_dangerous_char($title))),
5625
            0,
5626
            CourseManager::MAX_COURSE_LENGTH_CODE
5627
        );
5628
    }
5629
5630
    /**
5631
     * @param $courseId
5632
     * @return array
5633
     */
5634
    public static function getCourseSettings($courseId)
5635
    {
5636
        $settingTable = Database::get_course_table(TABLE_COURSE_SETTING);
5637
        $courseId = intval($courseId);
5638
        $sql = "SELECT * FROM $settingTable WHERE c_id = $courseId";
5639
        $result = Database::query($sql);
5640
        $settings = array();
5641
        if (Database::num_rows($result)) {
5642
            while ($row = Database::fetch_array($result, 'ASSOC')) {
5643
                $settings[$row['variable']] = $row;
5644
            }
5645
        }
5646
        return $settings;
5647
    }
5648
5649
    /**
5650
     * this function gets all the users of the course,
5651
     * including users from linked courses
5652
     */
5653 View Code Duplication
    public static function getCourseUsers()
5654
    {
5655
        //this would return only the users from real courses:
5656
        $session_id = api_get_session_id();
5657
        if ($session_id != 0) {
5658
            $user_list = self::get_real_and_linked_user_list(api_get_course_id(), true, $session_id);
5659
        } else {
5660
            $user_list = self::get_real_and_linked_user_list(api_get_course_id(), false, 0);
5661
        }
5662
5663
        return $user_list;
5664
    }
5665
5666
    /**
5667
     * this function gets all the groups of the course,
5668
     * not including linked courses
5669
     */
5670 View Code Duplication
    public static function getCourseGroups()
5671
    {
5672
        $session_id = api_get_session_id();
5673
        if ($session_id != 0) {
5674
            $new_group_list = self::get_group_list_of_course(api_get_course_id(), $session_id, 1);
5675
        } else {
5676
            $new_group_list = self::get_group_list_of_course(api_get_course_id(), 0, 1);
5677
        }
5678
5679
        return $new_group_list;
5680
    }
5681
5682
    /**
5683
     * @param FormValidator $form
5684
     * @param array $to_already_selected
5685
     *
5686
     * @return HTML_QuickForm_element
5687
     */
5688 View Code Duplication
    public static function addUserGroupMultiSelect(&$form, $to_already_selected)
5689
    {
5690
        $user_list = self::getCourseUsers();
5691
        $group_list = self::getCourseGroups();
5692
        $array = self::buildSelectOptions($group_list, $user_list, $to_already_selected);
5693
5694
        $result = array();
5695
        foreach ($array as $content) {
5696
            $result[$content['value']] = $content['content'];
5697
        }
5698
5699
        return $form->addElement(
5700
            'advmultiselect',
5701
            'users',
5702
            get_lang('Users'),
5703
            $result,
5704
            array('select_all_checkbox' => true)
5705
        );
5706
    }
5707
5708
    /**
5709
     * This function separates the users from the groups
5710
     * users have a value USER:XXX (with XXX the groups id have a value
5711
     *  GROUP:YYY (with YYY the group id)
5712
     * @param  array $to Array of strings that define the type and id of each destination
5713
     * @return array Array of groups and users (each an array of IDs)
5714
     */
5715
    public static function separateUsersGroups($to)
5716
    {
5717
        $grouplist = array();
5718
        $userlist = array();
5719
5720
        foreach ($to as $to_item) {
5721
            if (!empty($to_item)) {
5722
                $parts = explode(':', $to_item);
5723
                $type = isset($parts[0]) ? $parts[0] : '';
5724
                $id = isset($parts[1]) ? $parts[1] : '';
5725
5726
                switch ($type) {
5727
                    case 'GROUP':
5728
                        $grouplist[] = intval($id);
5729
                        break;
5730
                    case 'USER':
5731
                        $userlist[] = intval($id);
5732
                        break;
5733
                }
5734
            }
5735
        }
5736
5737
        $send_to['groups'] = $grouplist;
5738
        $send_to['users'] = $userlist;
5739
5740
        return $send_to;
5741
    }
5742
5743
    /**
5744
     * Shows the form for sending a message to a specific group or user.
5745
     * @param FormValidator $form
5746
     * @param int $group_id iid
5747
     * @param array $to
5748
     */
5749 View Code Duplication
    public static function addGroupMultiSelect($form, $group_id, $to = array())
5750
    {
5751
        $group_users = GroupManager::get_subscribed_users($group_id);
5752
        $array = self::buildSelectOptions(null, $group_users, $to);
5753
5754
        $result = array();
5755
        foreach ($array as $content) {
5756
            $result[$content['value']] = $content['content'];
5757
        }
5758
5759
        return $form->addElement('advmultiselect', 'users', get_lang('Users'), $result);
5760
    }
5761
5762
    /**
5763
     * this function shows the form for sending a message to a specific group or user.
5764
     * @param array $group_list
5765
     * @param array $user_list
5766
     * @param array $to_already_selected
5767
     * @return array
5768
     */
5769
    public static function buildSelectOptions(
5770
        $group_list = array(),
5771
        $user_list = array(),
5772
        $to_already_selected = array()
5773
    ) {
5774
        if (empty($to_already_selected)) {
5775
            $to_already_selected = array();
5776
        }
5777
5778
        $result = array();
5779
        // adding the groups to the select form
5780
        if ($group_list) {
5781
            foreach ($group_list as $this_group) {
5782
                if (is_array($to_already_selected)) {
5783
                    if (!in_array(
5784
                        "GROUP:" . $this_group['id'],
5785
                        $to_already_selected
5786
                    )
5787
                    ) { // $to_already_selected is the array containing the groups (and users) that are already selected
5788
                        $user_label = ($this_group['userNb'] > 0) ? get_lang('Users') : get_lang('LowerCaseUser');
5789
                        $user_disabled = ($this_group['userNb'] > 0) ? "" : "disabled=disabled";
5790
                        $result[] = array(
5791
                            'disabled' => $user_disabled,
5792
                            'value' => "GROUP:" . $this_group['id'],
5793
                            'content' => "G: " . $this_group['name'] . " - " . $this_group['userNb'] . " " . $user_label
5794
                        );
5795
                    }
5796
                }
5797
            }
5798
        }
5799
5800
        // adding the individual users to the select form
5801
        if ($user_list) {
5802
            foreach ($user_list as $user) {
5803
                if (is_array($to_already_selected)) {
5804
                    if (!in_array(
5805
                        "USER:" . $user['user_id'],
5806
                        $to_already_selected
5807
                    )
5808
                    ) { // $to_already_selected is the array containing the users (and groups) that are already selected
5809
5810
                        $result[] = array(
5811
                            'value' => "USER:" . $user['user_id'],
5812
                            'content' => api_get_person_name($user['firstname'], $user['lastname'])
5813
                        );
5814
                    }
5815
                }
5816
            }
5817
        }
5818
5819
        return $result;
5820
    }
5821
5822
    /**
5823
     * @return array a list (array) of all courses.
5824
     */
5825
    public static function get_course_list()
5826
    {
5827
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
5828
        return Database::store_result(Database::query("SELECT *, id as real_id FROM $table"));
0 ignored issues
show
Bug introduced by
It seems like \Database::query("SELECT...real_id FROM {$table}") can be null; however, store_result() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
5829
    }
5830
5831
    /**
5832
     * Returns course code from a given gradebook category's id
5833
     * @param int  $category_id
5834
     * @return int course id
5835
     */
5836 View Code Duplication
    public static function get_course_by_category($category_id)
5837
    {
5838
        $category_id = intval($category_id);
5839
        $info = Database::fetch_array(
5840
            Database::query('SELECT c_id FROM ' . Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY) . '
0 ignored issues
show
Bug introduced by
It seems like \Database::query('SELECT...RE id=' . $category_id) can be null; however, fetch_array() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
5841
            WHERE id=' . $category_id), 'ASSOC'
5842
        );
5843
        return $info ? $info['c_id'] : false;
5844
    }
5845
5846
    /**
5847
     * This function gets all the courses that are not in a session
5848
     * @param date Start date
5849
     * @param date End date
5850
     * @param   bool    $includeClosed Whether to include closed and hidden courses
5851
     * @return array Not-in-session courses
5852
     */
5853
    public static function getCoursesWithoutSession($startDate = null, $endDate = null, $includeClosed = false)
5854
    {
5855
        $dateConditional = ($startDate && $endDate) ?
5856
            " WHERE session_id IN (SELECT id FROM " . Database::get_main_table(TABLE_MAIN_SESSION) .
5857
            " WHERE access_start_date = '$startDate' AND access_end_date = '$endDate')" :
5858
            null;
5859
        $visibility = ($includeClosed ? '' : 'visibility NOT IN (0, 4) AND ');
5860
5861
        $query = "SELECT id, code, title
5862
                FROM " . Database::get_main_table(TABLE_MAIN_COURSE). "
5863
                WHERE $visibility code NOT IN (
5864
                    SELECT DISTINCT course_code FROM " . Database::get_main_table(TABLE_MAIN_SESSION_COURSE) . $dateConditional . ")
5865
                ORDER BY id";
5866
5867
        $result = Database::query($query);
5868
        $courses = array();
5869
        while ($row = Database::fetch_array($result)) {
5870
            $courses[] = $row;
5871
        }
5872
        return $courses;
5873
    }
5874
5875
    /**
5876
     * Get list of courses based on users of a group for a group admin
5877
     * @param int $userId The user id
5878
     * @return array
5879
     */
5880 View Code Duplication
    public static function getCoursesFollowedByGroupAdmin($userId)
5881
    {
5882
        $coursesList = [];
5883
5884
        $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
5885
        $courseUserTable = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5886
        $userGroup = new UserGroup();
5887
        $userIdList = $userGroup->getGroupUsersByUser($userId);
5888
5889
        if (empty($userIdList)) {
5890
            return [];
5891
        }
5892
5893
        $sql = "SELECT DISTINCT(c.id), c.title
5894
                FROM $courseTable c
5895
                INNER JOIN $courseUserTable cru ON c.id = cru.c_id
5896
                WHERE (
5897
                    cru.user_id IN (" . implode(', ', $userIdList) . ")
5898
                    AND cru.relation_type = 0
5899
                )";
5900
5901
        if (api_is_multiple_url_enabled()) {
5902
            $courseAccessUrlTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
5903
            $accessUrlId = api_get_current_access_url_id();
5904
5905
            if ($accessUrlId != -1) {
5906
                $sql = "SELECT DISTINCT(c.id), c.title
5907
                        FROM $courseTable c
5908
                        INNER JOIN $courseUserTable cru ON c.id = cru.c_id
5909
                        INNER JOIN $courseAccessUrlTable crau ON c.id = crau.c_id
5910
                        WHERE crau.access_url_id = $accessUrlId
5911
                            AND (
5912
                            cru.id_user IN (" . implode(', ', $userIdList) . ") AND
5913
                            cru.relation_type = 0
5914
                        )";
5915
            }
5916
        }
5917
5918
        $result = Database::query($sql);
5919
5920
        while ($row = Database::fetch_assoc($result)) {
5921
            $coursesList[] = $row;
5922
        }
5923
5924
        return $coursesList;
5925
    }
5926
5927
    /**
5928
     * Direct course link see #5299
5929
     *
5930
     * You can send to your students an URL like this
5931
     * http://chamilodev.beeznest.com/main/auth/inscription.php?c=ABC&e=3
5932
     * Where "c" is the course code and "e" is the exercise Id, after a successful
5933
     * registration the user will be sent to the course or exercise
5934
     *
5935
     */
5936
    public static function redirectToCourse($form_data)
5937
    {
5938
        $course_code_redirect = Session::read('course_redirect');
5939
        $_user = api_get_user_info();
5940
        $user_id = api_get_user_id();
5941
5942
        if (!empty($course_code_redirect)) {
5943
            $course_info = api_get_course_info($course_code_redirect);
5944
            if (!empty($course_info)) {
5945
                if (in_array($course_info['visibility'],
5946
                    array(COURSE_VISIBILITY_OPEN_PLATFORM, COURSE_VISIBILITY_OPEN_WORLD))
5947
                ) {
5948
                    if (CourseManager::is_user_subscribed_in_course($user_id, $course_info['code'])) {
5949
5950
                        $form_data['action'] = $course_info['course_public_url'];
5951
                        $form_data['message'] = sprintf(get_lang('YouHaveBeenRegisteredToCourseX'), $course_info['title']);
5952
                        $form_data['button'] = Display::button(
5953
                            'next',
5954
                            get_lang('GoToCourse', null, $_user['language']),
5955
                            array('class' => 'btn btn-primary btn-large')
5956
                        );
5957
5958
                        $exercise_redirect = intval(Session::read('exercise_redirect'));
5959
                        // Specify the course id as the current context does not
5960
                        // hold a global $_course array
5961
                        $objExercise = new Exercise($course_info['real_id']);
5962
                        $result = $objExercise->read($exercise_redirect);
5963
5964
                        if (!empty($exercise_redirect) && !empty($result)) {
5965
                            $form_data['action'] = api_get_path(WEB_CODE_PATH) . 'exercise/overview.php?exerciseId='.$exercise_redirect.'&cidReq='.$course_info['code'];
5966
                            $form_data['message'] .= '<br />'.get_lang('YouCanAccessTheExercise');
5967
                            $form_data['button'] = Display::button(
5968
                                'next',
5969
                                get_lang('Go', null, $_user['language']),
5970
                                array('class' => 'btn btn-primary btn-large')
5971
                            );
5972
                        }
5973
5974
                        if (!empty($form_data['action'])) {
5975
                            header('Location: '.$form_data['action']);
5976
                            exit;
5977
                        }
5978
                    }
5979
                }
5980
            }
5981
        }
5982
5983
        return $form_data;
5984
    }
5985
5986
    /**
5987
     * return html code for displaying a course title in the standard view (not the Session view)
5988
     * @param $courseId
5989
     * @param bool $loadDirs
5990
     * @return string
5991
     */
5992
    public static function displayCourseHtml($courseId, $loadDirs = false)
5993
    {
5994
        $params = self::getCourseParamsForDisplay($courseId, $loadDirs);
5995
        $html = self::course_item_html($params, false);
0 ignored issues
show
Bug introduced by
It seems like $params defined by self::getCourseParamsFor...y($courseId, $loadDirs) on line 5994 can also be of type string; however, CourseManager::course_item_html() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
5996
5997
        return $html;
5998
    }
5999
6000
    /**
6001
     * Return tab of params to display a course title in the My Courses tab
6002
     * Check visibility, right, and notification icons, and load_dirs option
6003
     * @param $courseId
6004
     * @param bool $loadDirs
6005
     * @return array
6006
     */
6007
    public static function getCourseParamsForDisplay($courseId, $loadDirs = false)
6008
    {
6009
        $user_id = api_get_user_id();
6010
        // Table definitions
6011
        $TABLECOURS = Database :: get_main_table(TABLE_MAIN_COURSE);
6012
        $TABLECOURSUSER = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
6013
        $TABLE_ACCESS_URL_REL_COURSE = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
6014
        $current_url_id = api_get_current_access_url_id();
6015
6016
        // Get course list auto-register
6017
        $special_course_list = self::get_special_course_list();
6018
6019
        $without_special_courses = '';
6020
        if (!empty($special_course_list)) {
6021
            $without_special_courses = ' AND course.id NOT IN ("'.implode('","',$special_course_list).'")';
6022
        }
6023
6024
        //AND course_rel_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
6025
        $sql = "SELECT 
6026
                    course.id, 
6027
                    course.title, 
6028
                    course.code, 
6029
                    course.subscribe subscr, 
6030
                    course.unsubscribe unsubscr, 
6031
                    course_rel_user.status status,
6032
                    course_rel_user.sort sort, 
6033
                    course_rel_user.user_course_cat user_course_cat
6034
                FROM
6035
                $TABLECOURS course,
6036
                $TABLECOURSUSER course_rel_user, 
6037
                $TABLE_ACCESS_URL_REL_COURSE url
6038
                WHERE
6039
                    course.id=".intval($courseId)." AND
6040
                    course.id = course_rel_user.c_id AND
6041
                    url.c_id = course.id AND
6042
                    course_rel_user.user_id = ".intval($user_id)."
6043
                    $without_special_courses
6044
                ";
6045
6046
        // If multiple URL access mode is enabled, only fetch courses
6047
        // corresponding to the current URL.
6048
        if (api_get_multiple_access_url() && $current_url_id != -1) {
6049
            $sql .= " AND url.course_code=course.code AND access_url_id=".intval($current_url_id);
6050
        }
6051
        // Use user's classification for courses (if any).
6052
        $sql .= " ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
6053
6054
        $result = Database::query($sql);
6055
6056
        // Browse through all courses. We can only have one course because
6057
        // of the  course.id=".intval($courseId) in sql query
6058
        $course = Database::fetch_array($result);
6059
        $course_info = api_get_course_info_by_id($courseId);
6060
        if (empty($course_info)) {
6061
            return '';
6062
        }
6063
6064
        //$course['id_session'] = null;
6065
        $course_info['id_session'] = null;
6066
        $course_info['status'] = $course['status'];
6067
6068
        // For each course, get if there is any notification icon to show
6069
        // (something that would have changed since the user's last visit).
6070
        $show_notification = Display::show_notification($course_info);
6071
6072
        // New code displaying the user's status in respect to this course.
6073
        $status_icon = Display::return_icon(
6074
            'blackboard.png',
6075
            $course_info['title'],
6076
            array(),
6077
            ICON_SIZE_LARGE
6078
        );
6079
6080
        $params = array();
6081
        $params['right_actions'] = '';
6082
6083
        if (api_is_platform_admin()) {
6084 View Code Duplication
            if ($loadDirs) {
6085
                $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'), array('align' => 'absmiddle'),ICON_SIZE_SMALL).'</a>';
6086
                $params['right_actions'] .= '<a href="'.api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cidReq='.$course['code'].'">'.Display::return_icon('edit.png', get_lang('Edit'), array('align' => 'absmiddle'),ICON_SIZE_SMALL).'</a>';
6087
                $params['right_actions'] .= Display::div('', array('id' => 'document_result_'.$course_info['real_id'].'_0', 'class'=>'document_preview_container'));
6088
            } else {
6089
                $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'].'">'.Display::returnFontAwesomeIcon('pencil').'</a>';
6090
            }
6091
6092
            if ($course_info['status'] == COURSEMANAGER) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

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

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

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

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
6093
                //echo Display::return_icon('teachers.gif', get_lang('Status').': '.get_lang('Teacher'), array('style'=>'width: 11px; height: 11px;'));
6094
            }
6095
        } else {
6096
            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
6097 View Code Duplication
                if ($loadDirs) {
6098
                    $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'), array('align' => 'absmiddle'),ICON_SIZE_SMALL).'</a>';
6099
                    $params['right_actions'] .= Display::div('', array('id' => 'document_result_'.$course_info['real_id'].'_0', 'class'=>'document_preview_container'));
6100
                } else {
6101
                    if ($course_info['status'] == COURSEMANAGER) {
6102
                        $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'].'">'.Display::returnFontAwesomeIcon('pencil').'</a>';
6103
                    }
6104
                }
6105
            }
6106
        }
6107
6108
        $course_title_url = '';
6109 View Code Duplication
        if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED || $course['status'] == COURSEMANAGER) {
6110
            $course_title_url = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/?id_session=0';
6111
            $course_title = Display::url($course_info['title'], $course_title_url);
6112
        } else {
6113
            $course_title = $course_info['title'].' '.Display::tag('span',get_lang('CourseClosed'), array('class'=>'item_closed'));
6114
        }
6115
6116
        // Start displaying the course block itself
6117
        if (api_get_setting('display_coursecode_in_courselist') === 'true') {
6118
            $course_title .= ' ('.$course_info['visual_code'].') ';
6119
        }
6120
        $teachers = '';
6121
        if (api_get_setting('display_teacher_in_courselist') === 'true') {
6122
            $teachers = CourseManager::get_teacher_list_from_course_code_to_string($course['code'], self::USER_SEPARATOR, true);
6123
        }
6124
        $params['link'] = $course_title_url;
6125
        $params['icon'] = $status_icon;
6126
        $params['title'] = $course_title;
6127
        $params['teachers'] = $teachers;
6128
        if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
6129
            $params['notifications'] = $show_notification;
6130
        }
6131
6132
        return $params;
6133
    }
6134
6135
    /**
6136
     * @param int $user_id
6137
     * @param $filter
6138
     * @param bool $load_dirs
6139
     * @param int $getCount
6140
     * @param int $start
6141
     * @param null $maxPerPage
6142
     * @return null|string
6143
     */
6144
    public static function displayCourses($user_id, $filter, $load_dirs, $getCount, $start = null, $maxPerPage = null)
6145
    {
6146
        // Table definitions
6147
        $TABLECOURS                     = Database :: get_main_table(TABLE_MAIN_COURSE);
6148
        $TABLECOURSUSER                 = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
6149
        $TABLE_ACCESS_URL_REL_COURSE    = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
6150
        $current_url_id                 = api_get_current_access_url_id();
6151
6152
        // Get course list auto-register
6153
        $special_course_list            = self::get_special_course_list();
6154
6155
        $without_special_courses = '';
6156
6157
        if (!empty($special_course_list)) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

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

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

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

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
6158
            //$without_special_courses = ' AND course.code NOT IN ("'.implode('","',$special_course_list).'")';
6159
        }
6160
6161
        $select = " SELECT DISTINCT
6162
                    course.id,
6163
                    course.title,
6164
                    course.code,
6165
                    course.subscribe subscr,
6166
                    course.unsubscribe unsubscr,
6167
                    course_rel_user.status status,
6168
                    course_rel_user.sort sort,
6169
                    course_rel_user.user_course_cat user_course_cat,
6170
                    course.id as real_id
6171
        ";
6172
6173
        $from = "$TABLECOURS course, $TABLECOURSUSER  course_rel_user, $TABLE_ACCESS_URL_REL_COURSE url ";
6174
6175
        $where = "  course.id = course_rel_user.c_id AND
6176
                    url.c_id = course.id AND
6177
                    course_rel_user.user_id = '".$user_id."' AND
6178
                    course_rel_user.user_course_cat = 0
6179
                    ";
6180
6181
        $order = " ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
6182
6183
6184
        if ($getCount) {
6185
            $select = "SELECT count(course.id) as total";
6186
        }
6187
6188
        $sql = "$select FROM $from WHERE $where $without_special_courses ";
6189
6190
        // corresponding to the current URL.
6191
        if (api_get_multiple_access_url() && $current_url_id != -1) {
6192
            $sql .= " AND url.c_id = course.id AND access_url_id='".$current_url_id."'";
6193
        }
6194
6195
        $sql .= $order;
6196
6197 View Code Duplication
        if (isset($start) && isset($maxPerPage)) {
6198
            $start = intval($start);
6199
            $maxPerPage = intval($maxPerPage);
6200
            $limitCondition = " LIMIT $start, $maxPerPage";
6201
            $sql .= $limitCondition;
6202
        }
6203
6204 View Code Duplication
        if ($getCount) {
6205
            $result = Database::query($sql);
6206
            $row = Database::fetch_array($result);
6207
            return $row['total'];
6208
        }
6209
        $result = Database::query($sql);
6210
6211
        $html = null;
6212
        $course_list = array();
6213
6214
        // Browse through all courses.
6215
        while ($course = Database::fetch_array($result)) {
6216
            $course_info = api_get_course_info($course['code']);
6217
            $course_info['id_session'] = null;
6218
            $course_info['status'] = $course['status'];
6219
6220
            //In order to avoid doubles
6221
            if (in_array($course_info['real_id'], $course_list)) {
6222
                continue;
6223
            } else {
6224
                $course_list[] = $course_info['real_id'];
6225
            }
6226
6227
            // For each course, get if there is any notification icon to show
6228
            // (something that would have changed since the user's last visit).
6229
            $show_notification = Display :: show_notification($course_info);
6230
6231
            // New code displaying the user's status in respect to this course.
6232
            $status_icon = Display::return_icon('blackboard.png', $course_info['title'], array(), ICON_SIZE_LARGE);
6233
6234
            $params = array();
6235
            $params['right_actions'] = '';
6236
6237
            if (api_is_platform_admin()) {
6238 View Code Duplication
                if ($load_dirs) {
6239
                    $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'), array('align' => 'absmiddle'),ICON_SIZE_SMALL).'</a>';
6240
                    $params['right_actions'] .= '<a href="'.api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cidReq='.$course['code'].'">'.Display::return_icon('edit.png', get_lang('Edit'), array('align' => 'absmiddle'),ICON_SIZE_SMALL).'</a>';
6241
                    $params['right_actions'] .= Display::div('', array('id' => 'document_result_'.$course_info['real_id'].'_0', 'class'=>'document_preview_container'));
6242
                } else {
6243
                    $params['right_actions'].= '<a href="'.api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cidReq='.$course['code'].'">'.Display::return_icon('edit.png', get_lang('Edit'), array('align' => 'absmiddle'),ICON_SIZE_SMALL).'</a>';
6244
                }
6245
6246
                if ($course_info['status'] == COURSEMANAGER) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

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

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

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

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
6247
                    //echo Display::return_icon('teachers.gif', get_lang('Status').': '.get_lang('Teacher'), array('style'=>'width: 11px; height: 11px;'));
6248
                }
6249 View Code Duplication
            } else {
6250
                if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
6251
                    if ($load_dirs) {
6252
                        $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'), array('align' => 'absmiddle'),ICON_SIZE_SMALL).'</a>';
6253
                        $params['right_actions'] .= Display::div('', array('id' => 'document_result_'.$course_info['real_id'].'_0', 'class'=>'document_preview_container'));
6254
                    } else {
6255
                        if ($course_info['status'] == COURSEMANAGER) {
6256
                            $params['right_actions'].= '<a href="'.api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cidReq='.$course['code'].'">'.Display::return_icon('edit.png', get_lang('Edit'), array('align' => 'absmiddle'),ICON_SIZE_SMALL).'</a>';
6257
                        }
6258
                    }
6259
                }
6260
            }
6261
6262
            $course_title_url = '';
6263 View Code Duplication
            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED || $course['status'] == COURSEMANAGER) {
6264
                //$course_title_url = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/index.php?id_session=0';
6265
                $course_title_url = api_get_path(WEB_COURSE_PATH).$course_info['code'].'/index.php?id_session=0';
6266
                $course_title = Display::url($course_info['title'], $course_title_url);
6267
            } else {
6268
                $course_title = $course_info['title']." ".Display::tag('span',get_lang('CourseClosed'), array('class'=>'item_closed'));
6269
            }
6270
6271
            // Start displaying the course block itself
6272
            if (api_get_setting('course.display_coursecode_in_courselist') == 'true') {
6273
                $course_title .= ' ('.$course_info['visual_code'].') ';
6274
            }
6275
            $teachers = null;
6276
            if (api_get_setting('course.display_teacher_in_courselist') == 'true') {
6277
                $teachers = $course_info['teacher_list_formatted'];
6278
            }
6279
6280
            $params['link'] = $course_title_url;
6281
            $params['icon'] = $status_icon;
6282
            $params['title'] = $course_title;
6283
            $params['teachers'] = $teachers;
6284
6285
            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
6286
                $params['notifications'] = $show_notification;
6287
            }
6288
6289
            $is_subcontent = true;
6290
            if (empty($user_category_id)) {
6291
                $is_subcontent = false;
6292
            }
6293
            $html .= self::course_item_html($params, $is_subcontent);
6294
        }
6295
        return $html;
6296
    }
6297
6298
    /**
6299
     * Get the course id based on the original id and field name in the extra fields.
6300
     * Returns 0 if course was not found
6301
     *
6302
     * @param string $original_course_id_value Original course id
6303
     * @param string $original_course_id_name Original field name
6304
     * @return int Course id
6305
     */
6306
    public static function get_course_id_from_original_id($original_course_id_value, $original_course_id_name)
6307
    {
6308
        $extraFieldValue = new ExtraFieldValue('course');
6309
        $value = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
6310
            $original_course_id_name,
6311
            $original_course_id_value
6312
        );
6313
6314
        if ($value) {
6315
            return $value['item_id'];
6316
        }
6317
        return 0;
6318
    }
6319
6320
    /**
6321
     * Helper function to create a default gradebook (if necessary) upon course creation
6322
     * @param   int     $modelId    The gradebook model ID
6323
     * @param   int  $courseId Course code
6324
     * @return  void
6325
     */
6326
    public static function createDefaultGradebook($modelId, $courseId)
6327
    {
6328
        if (api_get_setting('gradebook_enable_grade_model') === 'true') {
6329
            //Create gradebook_category for the new course and add
6330
            // a gradebook model for the course
6331
            if (isset($modelId) &&
6332
                !empty($modelId) &&
6333
                $modelId != '-1'
6334
            ) {
6335
                GradebookUtils::createDefaultCourseGradebook(
6336
                    $courseId,
6337
                    $modelId
6338
                );
6339
            }
6340
        }
6341
    }
6342
6343
    /**
6344
     * Helper function to check if there is a course template and, if so, to
6345
     * copy the template as basis for the new course
6346
     * @param   string  $courseCode   Course code
6347
     * @param   int     $courseTemplate 0 if no course template is defined
6348
     */
6349
    public static function useTemplateAsBasisIfRequired($courseCode, $courseTemplate)
6350
    {
6351
        $template = api_get_setting('course_creation_use_template');
6352
        $teacherCanSelectCourseTemplate = api_get_setting('teacher_can_select_course_template') === 'true';
6353
        $courseTemplate = isset($courseTemplate) ? intval($courseTemplate) : 0;
6354
6355
        $useTemplate = false;
6356
6357
        if ($teacherCanSelectCourseTemplate && $courseTemplate) {
6358
            $useTemplate = true;
6359
            $originCourse = api_get_course_info_by_id($courseTemplate);
6360
        } elseif (!empty($template)) {
6361
            $useTemplate = true;
6362
            $originCourse = api_get_course_info_by_id($template);
6363
        }
6364
6365
        if ($useTemplate) {
6366
            // Include the necessary libraries to generate a course copy
6367
            // Call the course copy object
6368
            $originCourse['official_code'] = $originCourse['code'];
6369
            $cb = new CourseBuilder(null, $originCourse);
6370
            $course = $cb->build(null, $originCourse['code']);
6371
            $cr = new CourseRestorer($course);
6372
            $cr->set_file_option();
6373
            $cr->restore($courseCode);
6374
        }
6375
    }
6376
6377
    /**
6378
     * Helper method to get the number of users defined with a specific course extra field
6379
     * @param   string  $name   Field title
6380
     * @param   string  $tableExtraFields The extra fields table name
6381
     * @param   string  $tableUserFieldValues The user extra field value table name
6382
     * @return  int     The number of users with this extra field with a specific value
6383
     */
6384
    public static function getCountRegisteredUsersWithCourseExtraField($name, $tableExtraFields = '', $tableUserFieldValues = '')
6385
    {
6386
        if (empty($tableExtraFields)) {
6387
            $tableExtraFields = Database::get_main_table(TABLE_EXTRA_FIELD);
6388
        }
6389
        if (empty($tableUserFieldValues)) {
6390
            $tableUserFieldValues = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
6391
        }
6392
6393
        $registered_users_with_extra_field = 0;
6394
6395
        if (!empty($name) && $name != '-') {
6396
            $extraFieldType = EntityExtraField::COURSE_FIELD_TYPE;
6397
            $name = Database::escape_string($name);
6398
            $sql = "SELECT count(v.item_id) as count
6399
                    FROM $tableUserFieldValues v 
6400
                    INNER JOIN $tableExtraFields f
6401
                    ON (f.id = v.field_id)
6402
                    WHERE value = '$name' AND extra_field_type = $extraFieldType";
6403
            $result_count = Database::query($sql);
6404
            if (Database::num_rows($result_count)) {
6405
                $row_count = Database::fetch_array($result_count);
6406
                $registered_users_with_extra_field = $row_count['count'];
6407
            }
6408
        }
6409
6410
        return $registered_users_with_extra_field;
6411
    }
6412
6413
    /**
6414
     * Check if a specific access-url-related setting is a problem or not
6415
     * @param array $_configuration The $_configuration array
6416
     * @param int $accessUrlId The access URL ID
6417
     * @param string $param
6418
     * @param string $msgLabel
6419
     * @return bool|string
6420
     */
6421
    private static function checkCreateCourseAccessUrlParam($_configuration, $accessUrlId, $param, $msgLabel)
6422
    {
6423
        if (isset($_configuration[$accessUrlId][$param]) && $_configuration[$accessUrlId][$param] > 0) {
6424
            $num = self::count_courses($accessUrlId);
6425
            if ($num >= $_configuration[$accessUrlId][$param]) {
6426
                api_warn_hosting_contact($param);
6427
6428
                Display::addFlash(
6429
                    Display::return_message($msgLabel)
6430
                );
6431
            }
6432
        }
6433
        return false;
6434
    }
6435
    /**
6436
     * Fill course with all necessary items
6437
     * @param array $courseInfo Course info array
6438
     * @param array $params Parameters from the course creation form
6439
     * @param int $authorId
6440
     * @return void
6441
     */
6442
    private static function fillCourse($courseInfo, $params, $authorId = 0)
6443
    {
6444
        $authorId = empty($authorId) ? api_get_user_id() : (int) $authorId;
6445
6446
        AddCourse::prepare_course_repository($courseInfo['directory'], $courseInfo['code']);
6447
        AddCourse::fill_db_course(
6448
            $courseInfo['real_id'],
6449
            $courseInfo['directory'],
6450
            $courseInfo['course_language'],
6451
            $params['exemplary_content'],
6452
            $authorId
6453
        );
6454
6455
        if (isset($params['gradebook_model_id'])) {
6456
            CourseManager::createDefaultGradebook($params['gradebook_model_id'], $courseInfo['real_id']);
6457
        }
6458
        // If parameter defined, copy the contents from a specific
6459
        // template course into this new course
6460
        if (isset($params['course_template'])) {
6461
            CourseManager::useTemplateAsBasisIfRequired($courseInfo['id'], $params['course_template']);
6462
        }
6463
        $params['course_code'] = $courseInfo['code'];
6464
        $params['item_id'] = $courseInfo['real_id'];
6465
6466
        $courseFieldValue = new ExtraFieldValue('course');
6467
        $courseFieldValue->saveFieldValues($params);
6468
    }
6469
6470
    /**
6471
     * @param ToolChain $toolList
6472
     */
6473
    public static function setToolList($toolList)
6474
    {
6475
        self::$toolList = $toolList;
6476
    }
6477
6478
    /**
6479
     * @return ToolChain
6480
     */
6481
    public static function getToolList()
6482
    {
6483
        return self::$toolList;
6484
    }
6485
}
6486