Completed
Push — master ( 73cb1f...8d952e )
by Julito
33:13
created

CourseManager::displayCourses()   F

Complexity

Conditions 22
Paths 4144

Size

Total Lines 153
Code Lines 81

Duplication

Lines 37
Ratio 24.18 %

Importance

Changes 0
Metric Value
cc 22
eloc 81
nc 4144
nop 6
dl 37
loc 153
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
/* For licensing terms, see /license.txt*/
3
4
use Chamilo\CoreBundle\Entity\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
12
/**
13
 * Class CourseManager
14
 *
15
 * This is the course library for Chamilo.
16
 *
17
 * All main course functions should be placed here.
18
 *
19
 * Many functions of this library deal with providing support for
20
 * virtual/linked/combined courses (this was already used in several universities
21
 * but not available in standard Chamilo).
22
 *
23
 * There are probably some places left with the wrong code.
24
 *
25
 * @package chamilo.library
26
 */
27
class CourseManager
28
{
29
    const MAX_COURSE_LENGTH_CODE = 40;
30
    /** This constant is used to show separate user names in the course
31
     * list (userportal), footer, etc */
32
    const USER_SEPARATOR = ' |';
33
    const COURSE_FIELD_TYPE_CHECKBOX = 10;
34
    public $columns = array();
35
    public static $em;
36
    private static $manager;
37
    public static $toolList;
38
    public static $courseSettingsManager;
39
40
     /**
41
     * @param \Doctrine\ORM\EntityManager
42
     */
43
    public static function setEntityManager($em)
44
    {
45
        self::$em = $em;
46
    }
47
48
    /**
49
     * @return \Doctrine\ORM\EntityManager
50
     */
51
    public static function getEntityManager()
52
    {
53
        return self::$em;
54
    }
55
56
    /**
57
     * @return Chamilo\CoreBundle\Entity\CourseManager
58
     */
59
    public static function setCourseManager($manager)
60
    {
61
        self::$manager = $manager;
62
    }
63
64
    /**
65
     * @return SettingsManager
66
     */
67
    public static function getCourseSettingsManager()
68
    {
69
        return self::$courseSettingsManager;
70
    }
71
72
    /**
73
     * @param SettingsManager $courseSettingsManager
74
     */
75
    public static function setCourseSettingsManager($courseSettingsManager)
76
    {
77
        self::$courseSettingsManager = $courseSettingsManager;
78
    }
79
80
    /**
81
     * @return Chamilo\CoreBundle\Entity\Manager\CourseManager
82
     */
83
    public static function getManager()
84
    {
85
        return self::$manager;
86
    }
87
88
    /**
89
     * Creates a course
90
     * @param   array $params columns in the main.course table
91
     *
92
     * @return  mixed  false if the course was not created, array with the course info
93
     */
94
    public static function create_course($params, $authorId = 0)
95
    {
96
        global $_configuration;
97
        // Check portal limits
98
        $access_url_id = 1;
99
        if (api_get_multiple_access_url()) {
100
            $access_url_id = api_get_current_access_url_id();
101
        }
102
103
        $authorId = empty($authorId) ? api_get_user_id() : (int) $authorId;
104
105
        if (isset($_configuration[$access_url_id]) && is_array($_configuration[$access_url_id])) {
106
            $return = self::checkCreateCourseAccessUrlParam(
107
                $_configuration,
108
                $access_url_id,
109
                'hosting_limit_courses',
110
                'PortalCoursesLimitReached'
111
            );
112
            if ($return != false) {
113
                return $return;
114
            }
115
            $return = self::checkCreateCourseAccessUrlParam(
116
                $_configuration,
117
                $access_url_id,
118
                'hosting_limit_active_courses',
119
                'PortalActiveCoursesLimitReached'
120
            );
121
            if ($return != false) {
122
                return $return;
123
            }
124
        }
125
126
        if (empty($params['title'])) {
127
            return false;
128
        }
129
130
        if (empty($params['wanted_code'])) {
131
            $params['wanted_code'] = $params['title'];
132
            // Check whether the requested course code has already been occupied.
133
            $substring = api_substr($params['title'], 0, self::MAX_COURSE_LENGTH_CODE);
134
            if ($substring === false || empty($substring)) {
135
                return false;
136
            } else {
137
                $params['wanted_code'] = CourseManager::generate_course_code($substring);
138
            }
139
        }
140
141
        // Create the course keys
142
        $keys = AddCourse::define_course_keys($params['wanted_code']);
143
144
        $params['exemplary_content'] = isset($params['exemplary_content']) ? $params['exemplary_content'] : false;
145
146
        if (count($keys)) {
147
            $params['code'] = $keys['currentCourseCode'];
148
            $params['visual_code'] = $keys['currentCourseId'];
149
            $params['directory'] = $keys['currentCourseRepository'];
150
151
            $course_info = api_get_course_info($params['code']);
152
153
            if (empty($course_info)) {
154
                $course_id = AddCourse::register_course($params);
155
                $course_info = api_get_course_info_by_id($course_id);
156
157
                if (!empty($course_info)) {
158
                    self::fillCourse($course_info, $params, $authorId);
159
160
                    return $course_info;
161
                }
162
            }
163
        }
164
165
        return false;
166
    }
167
168
    /**
169
     * Returns all the information of a given course code
170
     * @param string $course_code , the course code
171
     * @return array with all the fields of the course table
172
     * @author Patrick Cool <[email protected]>, Ghent University
173
     * @assert ('') === false
174
     */
175 View Code Duplication
    public static function get_course_information($course_code)
176
    {
177
        return Database::fetch_array(
178
            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...
179
                "SELECT *, id as real_id FROM " . Database::get_main_table(TABLE_MAIN_COURSE) . "
180
                WHERE code='" . Database::escape_string($course_code) . "'"), 'ASSOC'
181
        );
182
    }
183
184
    /**
185
     * Returns a list of courses. Should work with quickform syntax
186
     * @param    integer $from Offset (from the 7th = '6'). Optional.
187
     * @param    integer $howmany Number of results we want. Optional.
188
     * @param    int $orderby The column we want to order it by. Optional, defaults to first column.
189
     * @param    string $orderdirection The direction of the order (ASC or DESC). Optional, defaults to ASC.
190
     * @param    int $visibility The visibility of the course, or all by default.
191
     * @param    string $startwith If defined, only return results for which the course *title* begins with this string
192
     * @param    string $urlId The Access URL ID, if using multiple URLs
193
     * @param    bool $alsoSearchCode An extension option to indicate that we also want to search for course codes (not *only* titles)
194
     * @param    array $conditionsLike
195
     * @return array
196
     */
197
    public static function get_courses_list(
198
        $from = 0,
199
        $howmany = 0,
200
        $orderby = 1,
201
        $orderdirection = 'ASC',
202
        $visibility = -1,
203
        $startwith = '',
204
        $urlId = null,
205
        $alsoSearchCode = false,
206
        $conditionsLike = array()
207
    ) {
208
        $sql = "SELECT course.* FROM " . Database::get_main_table(TABLE_MAIN_COURSE) . " course ";
209
210
        if (!empty($urlId)) {
211
            $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
212
            $sql .= " INNER JOIN $table url ON (url.c_id = course.id) ";
213
        }
214
215
        if (!empty($startwith)) {
216
            $sql .= "WHERE (title LIKE '" . Database::escape_string($startwith) . "%' ";
217
            if ($alsoSearchCode) {
218
                $sql .= "OR code LIKE '" . Database::escape_string($startwith) . "%' ";
219
            }
220
            $sql .= ') ';
221 View Code Duplication
            if ($visibility !== -1 && $visibility == strval(intval($visibility))) {
222
                $sql .= " AND visibility = $visibility ";
223
            }
224 View Code Duplication
        } else {
225
            $sql .= "WHERE 1 ";
226
            if ($visibility !== -1 && $visibility == strval(intval($visibility))) {
227
                $sql .= " AND visibility = $visibility ";
228
            }
229
        }
230
231
        if (!empty($urlId)) {
232
            $urlId = intval($urlId);
233
            $sql .= " AND access_url_id= $urlId";
234
        }
235
236
        $allowedFields = array(
237
            'title',
238
            'code'
239
        );
240
241
        if (count($conditionsLike) > 0) {
242
            $sql .= ' AND ';
243
            $temp_conditions = array();
244
            foreach ($conditionsLike as $field => $value) {
245
                if (!in_array($field, $allowedFields)) {
246
                    continue;
247
                }
248
                $field = Database::escape_string($field);
249
                $value = Database::escape_string($value);
250
                $simple_like = false;
251 View Code Duplication
                if ($simple_like) {
252
                    $temp_conditions[] = $field . " LIKE '$value%'";
253
                } else {
254
                    $temp_conditions[] = $field . ' LIKE \'%' . $value . '%\'';
255
                }
256
            }
257
            $condition = ' AND ';
258
            if (!empty($temp_conditions)) {
259
                $sql .= implode(' ' . $condition . ' ', $temp_conditions);
260
            }
261
        }
262
263
        if (!empty($orderby)) {
264
            $sql .= " ORDER BY " . Database::escape_string($orderby) . " ";
265
        } else {
266
            $sql .= " ORDER BY 1 ";
267
        }
268
269
        if (!in_array($orderdirection, array('ASC', 'DESC'))) {
270
            $sql .= 'ASC';
271
        } else {
272
            $sql .= ($orderdirection == 'ASC' ? 'ASC' : 'DESC');
273
        }
274
275
        if (!empty($howmany) && is_int($howmany) and $howmany > 0) {
276
            $sql .= ' LIMIT ' . Database::escape_string($howmany);
277
        } else {
278
            $sql .= ' LIMIT 1000000'; //virtually no limit
279
        }
280
        if (!empty($from)) {
281
            $from = intval($from);
282
            $sql .= ' OFFSET ' . intval($from);
283
        } else {
284
            $sql .= ' OFFSET 0';
285
        }
286
287
        $data = [];
288
        $res = Database::query($sql);
289
        if (Database::num_rows($res) > 0) {
290
            while ($row = Database::fetch_array($res, 'ASSOC')) {
291
                $data[] = $row;
292
            }
293
        }
294
295
        return $data;
296
    }
297
298
    /**
299
     * Returns the access settings of the course:
300
     * which visibility;
301
     * whether subscribing is allowed;
302
     * whether unsubscribing is allowed.
303
     *
304
     * @param string $course_code , the course code
305
     * @todo for more consistency: use course_info call from database API
306
     * @return array with int fields "visibility", "subscribe", "unsubscribe"
307
     * @assert ('') === false
308
     */
309 View Code Duplication
    public static function get_access_settings($course_code)
310
    {
311
        return Database::fetch_array(
312
            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...
313
                "SELECT visibility, subscribe, unsubscribe
314
                FROM " . Database::get_main_table(TABLE_MAIN_COURSE) . "
315
                WHERE code = '" . Database::escape_string($course_code) . "'"
316
            )
317
        );
318
    }
319
320
    /**
321
     * Returns the status of a user in a course, which is COURSEMANAGER or STUDENT.
322
     * @param   int $user_id
323
     * @param   string $course_code
324
     *
325
     * @return int|bool the status of the user in that course (or false if the user is not in that course)
326
     */
327 View Code Duplication
    public static function get_user_in_course_status($user_id, $course_code)
328
    {
329
        $courseInfo = api_get_course_info($course_code);
330
        $courseId = $courseInfo['real_id'];
331
        if (empty($courseId)) {
332
            return false;
333
        }
334
        $result = Database::fetch_array(
335
            Database::query(
0 ignored issues
show
Bug introduced by
It seems like \Database::query('SELECT...= " . 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...
336
                "SELECT status FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER) . "
337
                WHERE
338
                    c_id  = $courseId AND
339
                    user_id = " . intval($user_id)
340
            )
341
        );
342
343
        return $result['status'];
344
    }
345
346
    /**
347
     * @param int $userId
348
     * @param int $courseId
349
     *
350
     * @return mixed
351
     */
352 View Code Duplication
    public static function getUserCourseInfo($userId, $courseId)
353
    {
354
355
        $result = Database::fetch_array(
356
            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...
357
                SELECT * FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER) . "
358
                WHERE
359
                    c_id  = '" . intval($courseId). "' AND
360
                    user_id = " . intval($userId)
361
            )
362
        );
363
364
        return $result;
365
    }
366
367
    /**
368
     * @param int  $userId
369
     * @param int  $courseId
370
     * @param bool $isTutor
371
     *
372
     * @return bool
373
     */
374
    public static function updateUserCourseTutor($userId, $courseId, $isTutor)
375
    {
376
        $table = Database::escape_string(TABLE_MAIN_COURSE_USER);
377
378
        $courseId = intval($courseId);
379
        $isTutor = intval($isTutor);
380
381
        $sql = "UPDATE $table SET is_tutor = '".$isTutor."'
382
			    WHERE
383
				    user_id = '".$userId."' AND
384
				    c_id = '".$courseId."'";
385
386
        $result = Database::query($sql);
387
388
        if (Database::affected_rows($result) > 0) {
389
            return true;
390
        } else {
391
            return false;
392
        }
393
    }
394
395
    /**
396
     * @param int $user_id
397
     * @param int $courseId
398
     *
399
     * @return mixed
400
     */
401 View Code Duplication
    public static function get_tutor_in_course_status($user_id, $courseId)
402
    {
403
        $result = Database::fetch_array(
404
            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...
405
                SELECT is_tutor
406
                FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER) . "
407
                WHERE
408
                    c_id = '" . Database::escape_string($courseId) . "' AND
409
                    user_id = " . intval($user_id)
410
            )
411
        );
412
413
        return $result['is_tutor'];
414
    }
415
416
    /**
417
     * Unsubscribe one or more users from a course
418
     *
419
     * @param   mixed   user_id or an array with user ids
420
     * @param   string  course code
421
     * @param   int     session id
422
     * @assert ('', '') === false
423
     *
424
     */
425
    public static function unsubscribe_user($user_id, $course_code, $session_id = 0)
426
    {
427
        if (!is_array($user_id)) {
428
            $user_id = array($user_id);
429
        }
430
431
        if (count($user_id) == 0) {
432
            return;
433
        }
434
435
        if (!empty($session_id)) {
436
            $session_id = intval($session_id);
437
        } else {
438
            $session_id = api_get_session_id();
439
        }
440
441
        $user_list = array();
442
443
        // Cleaning the $user_id variable
444
        if (is_array($user_id)) {
445
            $new_user_id_list = array();
446
            foreach ($user_id as $my_user_id) {
447
                $new_user_id_list[] = intval($my_user_id);
448
            }
449
            $new_user_id_list = array_filter($new_user_id_list);
450
            $user_list = $new_user_id_list;
451
            $user_ids = implode(',', $new_user_id_list);
452
        } else {
453
            $user_ids = intval($user_id);
454
            $user_list[] = $user_id;
455
        }
456
457
        $course_info = api_get_course_info($course_code);
458
        $course_id = $course_info['real_id'];
459
460
        // Unsubscribe user from all groups in the course.
461
        $sql = "DELETE FROM " . Database::get_course_table(TABLE_GROUP_USER) . "
462
                WHERE c_id = $course_id AND user_id IN (" . $user_ids . ")";
463
        Database::query($sql);
464
        $sql = "DELETE FROM " . Database::get_course_table(TABLE_GROUP_TUTOR) . "
465
                WHERE c_id = $course_id AND user_id IN (" . $user_ids . ")";
466
        Database::query($sql);
467
468
        // Erase user student publications (works) in the course - by André Boivin
469
470
        if (!empty($user_list)) {
471
            require_once api_get_path(SYS_CODE_PATH) . 'work/work.lib.php';
472
            foreach ($user_list as $userId) {
473
                // Getting all work from user
474
                $workList = getWorkPerUser($userId);
475
                if (!empty($workList)) {
476
                    foreach ($workList as $work) {
477
                        $work = $work['work'];
478
                        // Getting user results
479
                        if (!empty($work->user_results)) {
480
                            foreach ($work->user_results as $workSent) {
481
                                deleteWorkItem($workSent['id'], $course_info);
482
                            }
483
                        }
484
                    }
485
                }
486
            }
487
        }
488
489
        // Unsubscribe user from all blogs in the course.
490
        Database::query("DELETE FROM " . Database::get_course_table(TABLE_BLOGS_REL_USER) . " WHERE c_id = $course_id AND  user_id IN (" . $user_ids . ")");
491
        Database::query("DELETE FROM " . Database::get_course_table(TABLE_BLOGS_TASKS_REL_USER) . " WHERE c_id = $course_id AND  user_id IN (" . $user_ids . ")");
492
493
        // Deleting users in forum_notification and mailqueue course tables
494
        $sql = "DELETE FROM  " . Database::get_course_table(TABLE_FORUM_NOTIFICATION) . "
495
                WHERE c_id = $course_id AND user_id IN (" . $user_ids . ")";
496
        Database::query($sql);
497
498
        $sql = "DELETE FROM " . Database::get_course_table(TABLE_FORUM_MAIL_QUEUE) . "
499
                WHERE c_id = $course_id AND user_id IN (" . $user_ids . ")";
500
        Database::query($sql);
501
502
        // Unsubscribe user from the course.
503
        if (!empty($session_id)) {
504
505
            // Delete in table session_rel_course_rel_user
506
            $sql = "DELETE FROM " . Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER) . "
507
                    WHERE
508
                        session_id ='" . $session_id . "' AND
509
                        c_id = '" . $course_id . "' AND
510
                        user_id IN ($user_ids)";
511
            Database::query($sql);
512
513
            foreach ($user_list as $uid) {
514
                // check if a user is register in the session with other course
515
                $sql = "SELECT user_id FROM " . Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER) . "
516
                        WHERE session_id='$session_id' AND user_id='$uid'";
517
                $rs = Database::query($sql);
518
519
                if (Database::num_rows($rs) == 0) {
520
                    // Delete in table session_rel_user
521
                    $sql = "DELETE FROM " . Database::get_main_table(TABLE_MAIN_SESSION_USER) . "
522
                            WHERE
523
                                session_id ='" . $session_id . "' AND
524
                                user_id = '$uid' AND
525
                                relation_type<>" . SESSION_RELATION_TYPE_RRHH . "";
526
                    Database::query($sql);
527
                }
528
            }
529
530
            // Update the table session
531
            $sql = "SELECT COUNT(*) FROM " . Database::get_main_table(TABLE_MAIN_SESSION_USER) . "
532
                    WHERE session_id = '" . $session_id . "' AND relation_type <> " . SESSION_RELATION_TYPE_RRHH;
533
            $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...
534
            $count = $row[0];
535
            // number of users by session
536
            $sql = "UPDATE " . Database::get_main_table(TABLE_MAIN_SESSION) . " SET nbr_users = '$count'
537
                    WHERE id = '" . $session_id . "'";
538
            Database::query($sql);
539
540
            // Update the table session_rel_course
541
            $sql = "SELECT COUNT(*) FROM " . Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER) . "
542
                    WHERE session_id = '$session_id' AND c_id = '$course_id' AND status<>2";
543
            $row = Database::fetch_array(@Database::query($sql));
544
            $count = $row[0];
545
546
            // number of users by session and course
547
            $sql = "UPDATE " . Database::get_main_table(TABLE_MAIN_SESSION_COURSE) . "
548
                    SET nbr_users = '$count'
549
                    WHERE session_id = '$session_id' AND c_id = '$course_id'";
550
            Database::query($sql);
551
552
        } else {
553
            $sql = "DELETE FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER) . "
554
                    WHERE
555
                        user_id IN (" . $user_ids . ") AND
556
                        relation_type<>" . COURSE_RELATION_TYPE_RRHH . " AND
557
                        c_id = '" . $course_id . "'";
558
            Database::query($sql);
559
560
            // add event to system log
561
            $user_id = api_get_user_id();
562
563
            Event::addEvent(
564
                LOG_UNSUBSCRIBE_USER_FROM_COURSE,
565
                LOG_COURSE_CODE,
566
                $course_code,
567
                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...
568
                $user_id
569
            );
570
571
            foreach ($user_list as $userId) {
572
                $userInfo = api_get_user_info($userId);
573
                Event::addEvent(
574
                    LOG_UNSUBSCRIBE_USER_FROM_COURSE,
575
                    LOG_USER_OBJECT,
576
                    $userInfo,
577
                    api_get_utc_datetime(),
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...
578
                    $user_id
579
                );
580
            }
581
        }
582
    }
583
584
    /**
585
     * Subscribe a user to a course. No checks are performed here to see if
586
     * course subscription is allowed.
587
     * @param   int     User ID
588
     * @param   string  Course code
589
     * @param   int     Status (STUDENT, COURSEMANAGER, COURSE_ADMIN, NORMAL_COURSE_MEMBER)
590
     * @return  bool    True on success, false on failure
591
     * @see add_user_to_course
592
     * @assert ('', '') === false
593
     */
594
    public static function subscribe_user(
595
        $user_id,
596
        $course_code,
597
        $status = STUDENT,
598
        $session_id = 0,
599
        $userCourseCategoryId = 0
600
    ) {
601
        if ($user_id != strval(intval($user_id))) {
602
            return false; //detected possible SQL injection
603
        }
604
605
        $course_code = Database::escape_string($course_code);
606
        $courseInfo = api_get_course_info($course_code);
607
        $courseId = $courseInfo['real_id'];
608
        $courseCode = $courseInfo['code'];
609
610
        $userCourseCategoryId = intval($userCourseCategoryId);
611
612
        if (empty($user_id) || empty ($course_code)) {
613
            return false;
614
        }
615
616
        if (!empty($session_id)) {
617
            $session_id = intval($session_id);
618
        } else {
619
            $session_id = api_get_session_id();
620
        }
621
622
        $status = ($status == STUDENT || $status == COURSEMANAGER) ? $status : STUDENT;
623
        //$role_id = ($status == COURSEMANAGER) ? COURSE_ADMIN : NORMAL_COURSE_MEMBER;
624
625
        // A preliminary check whether the user has bben already registered on the platform.
626
        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...
627
                "SELECT status FROM " . Database::get_main_table(TABLE_MAIN_USER) . "
628
                WHERE user_id = '$user_id' ")) == 0
629
        ) {
630
            return false; // The user has not been registered to the platform.
631
        }
632
633
        // Check whether the user has not been already subscribed to the course.
634
635 View Code Duplication
        if (empty($session_id)) {
636
            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...
637
                    SELECT * FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER) . "
638
                    WHERE user_id = '$user_id' AND relation_type<>" . COURSE_RELATION_TYPE_RRHH . " AND c_id = '$courseId'")) > 0
639
            ) {
640
                // The user has been already subscribed to the course.
641
                return false;
642
            }
643
        }
644
645
        if (!empty($session_id)) {
646
            SessionManager::subscribe_users_to_session_course(array($user_id), $session_id, $courseCode);
647
        } else {
648
            CourseManager::add_user_to_course($user_id, $courseCode, $status);
649
650
            // Add event to the system log
651
            Event::addEvent(
652
                LOG_SUBSCRIBE_USER_TO_COURSE,
653
                LOG_COURSE_CODE,
654
                $course_code,
655
                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...
656
                api_get_user_id()
657
            );
658
659
            $user_info = api_get_user_info($user_id);
660
            Event::addEvent(
661
                LOG_SUBSCRIBE_USER_TO_COURSE,
662
                LOG_USER_OBJECT,
663
                $user_info,
664
                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...
665
                api_get_user_id()
666
            );
667
        }
668
669
        return true;
670
    }
671
672
    /**
673
     * Get the course id based on the original id and field name in the
674
     * extra fields. Returns 0 if course was not found
675
     *
676
     * @param string $original_course_id_value
677
     * @param string $original_course_id_name
678
     * @return int Course id
679
     *
680
     * @assert ('', '') === false
681
     */
682
    public static function get_course_code_from_original_id($original_course_id_value, $original_course_id_name)
683
    {
684
        $t_cfv = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
685
        $table_field = Database::get_main_table(TABLE_EXTRA_FIELD);
686
        $extraFieldType = EntityExtraField::COURSE_FIELD_TYPE;
687
688
        $original_course_id_value = Database::escape_string($original_course_id_value);
689
        $original_course_id_name = Database::escape_string($original_course_id_name);
690
691
        $sql = "SELECT item_id
692
                FROM $table_field cf
693
                INNER JOIN $t_cfv cfv
694
                ON cfv.field_id=cf.id
695
                WHERE
696
                    variable = '$original_course_id_name' AND
697
                    value = '$original_course_id_value' AND
698
                    cf.extra_field_type = $extraFieldType
699
                ";
700
        $res = Database::query($sql);
701
        $row = Database::fetch_object($res);
702
        if ($row) {
703
            return $row->item_id;
704
        } else {
705
            return 0;
706
        }
707
    }
708
709
    /**
710
     * Gets the course code from the course id. Returns null if course id was not found
711
     *
712
     * @param int $id Course id
713
     * @return string Course code
714
     * @assert ('') === false
715
     */
716
    public static function get_course_code_from_course_id($id)
717
    {
718
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
719
        $id = intval($id);
720
        $sql = "SELECT code FROM $table WHERE id = '$id' ";
721
        $res = Database::query($sql);
722
        $row = Database::fetch_object($res);
723
        if ($row) {
724
            return $row->code;
725
        } else {
726
            return null;
727
        }
728
    }
729
730
    /**
731
     * Subscribe a user $user_id to a course defined by $courseCode.
732
     * @author Hugues Peeters
733
     * @author Roan Embrechts
734
     *
735
     * @param  int $user_id the id of the user
736
     * @param  string $courseCode the course code
737
     * @param  int $status (optional) The user's status in the course
738
     * @param  int The user category in which this subscription will be classified
739
     *
740
     * @return false|string true if subscription succeeds, boolean false otherwise.
741
     * @assert ('', '') === false
742
     */
743
    public static function add_user_to_course($user_id, $courseCode, $status = STUDENT, $userCourseCategoryId = 0)
744
    {
745
        $debug = false;
746
        $user_table = Database::get_main_table(TABLE_MAIN_USER);
747
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
748
        $course_user_table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
749
750
        $status = ($status == STUDENT || $status == COURSEMANAGER) ? $status : STUDENT;
751 View Code Duplication
        if (empty($user_id) || empty($courseCode) || ($user_id != strval(intval($user_id)))) {
752
            return false;
753
        }
754
755
        $courseCode = Database::escape_string($courseCode);
756
        $courseInfo = api_get_course_info($courseCode);
757
        $courseId = $courseInfo['real_id'];
758
759
        // Check in advance whether the user has already been registered on the platform.
760
        $sql = "SELECT status FROM " . $user_table . " WHERE user_id = $user_id ";
761 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...
762
            if ($debug) {
763
                error_log('The user has not been registered to the platform');
764
            }
765
            return false; // The user has not been registered to the platform.
766
        }
767
768
        // Check whether the user has already been subscribed to this course.
769
        $sql = "SELECT * FROM $course_user_table
770
                WHERE
771
                    user_id = $user_id AND
772
                    relation_type <> " . COURSE_RELATION_TYPE_RRHH . " AND
773
                    c_id = $courseId";
774 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...
775
            if ($debug) {
776
                error_log('The user has been already subscribed to the course');
777
            }
778
            return false; // The user has been subscribed to the course.
779
        }
780
781
        if (!api_is_course_admin()) {
782
            // Check in advance whether subscription is allowed or not for this course.
783
            $sql = "SELECT code, visibility FROM $course_table
784
                    WHERE id = $courseId AND subscribe = '" . SUBSCRIBE_NOT_ALLOWED . "'";
785 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...
786
                if ($debug) {
787
                    error_log('Subscription is not allowed for this course');
788
                }
789
                return false; // Subscription is not allowed for this course.
790
            }
791
        }
792
793
        // Ok, subscribe the user.
794
        $max_sort = api_max_sort_value('0', $user_id);
795
        $params = [
796
            'c_id' => $courseId,
797
            'user_id' => $user_id,
798
            'status' => $status,
799
            'sort' => $max_sort + 1,
800
            'relation_type' => 0,
801
            'user_course_cat' => $userCourseCategoryId
802
        ];
803
        $insertId = Database::insert($course_user_table, $params);
804
805
        return $insertId;
806
    }
807
808
    /**
809
     * Add the user $userId visibility to the course $courseCode in the catalogue.
810
     * @author David Nos (https://github.com/dnos)
811
     *
812
     * @param  int $userId the id of the user
813
     * @param  string $courseCode the course code
814
     * @param  int $visible (optional) The course visibility in the catalogue to the user (1=visible, 0=invisible)
815
     *
816
     * @return boolean true if added succesfully, false otherwise.
817
     */
818
    public static function addUserVisibilityToCourseInCatalogue($userId, $courseCode, $visible = 1)
819
    {
820
        $debug = false;
821
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
822
        $courseUserTable = Database::get_main_table(TABLE_MAIN_COURSE_CATALOGUE_USER);
823
824 View Code Duplication
        if (empty($userId) || empty($courseCode) || ($userId != strval(intval($userId)))) {
825
            return false;
826
        }
827
828
        $courseCode = Database::escape_string($courseCode);
829
        $courseInfo = api_get_course_info($courseCode);
830
        $courseId = $courseInfo['real_id'];
831
832
        // Check in advance whether the user has already been registered on the platform.
833
        $sql = "SELECT status FROM " . $userTable . " WHERE user_id = $userId ";
834
        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...
835
            if ($debug) {
836
                error_log('The user has not been registered to the platform');
837
            }
838
            return false; // The user has not been registered to the platform.
839
        }
840
841
        // Check whether the user has already been registered to the course visibility in the catalogue.
842
        $sql = "SELECT * FROM $courseUserTable
843
                WHERE
844
                    user_id = $userId AND
845
                    visible = " . $visible . " AND
846
                    c_id = $courseId";
847
        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...
848
            if ($debug) {
849
                error_log('The user has been already registered to the course visibility in the catalogue');
850
            }
851
            return true; // The visibility of the user to the course in the catalogue does already exist.
852
        }
853
854
        // Register the user visibility to course in catalogue.
855
        $params = [
856
            'user_id' => $userId,
857
            'c_id' => $courseId,
858
            'visible' => $visible
859
        ];
860
        $insertId = Database::insert($courseUserTable, $params);
861
862
        return $insertId;
863
    }
864
865
866
    /**
867
     * Remove the user $userId visibility to the course $courseCode in the catalogue.
868
     * @author David Nos (https://github.com/dnos)
869
     *
870
     * @param  int $userId the id of the user
871
     * @param  string $courseCode the course code
872
     * @param  int $visible (optional) The course visibility in the catalogue to the user (1=visible, 0=invisible)
873
     *
874
     * @return boolean true if removed succesfully or register not found, false otherwise.
875
     */
876
    public static function removeUserVisibilityToCourseInCatalogue($userId, $courseCode, $visible = 1)
877
    {
878
        $courseUserTable = Database::get_main_table(TABLE_MAIN_COURSE_CATALOGUE_USER);
879
880 View Code Duplication
        if (empty($userId) || empty($courseCode) || ($userId != strval(intval($userId)))) {
881
            return false;
882
        }
883
884
        $courseCode = Database::escape_string($courseCode);
885
        $courseInfo = api_get_course_info($courseCode);
886
        $courseId = $courseInfo['real_id'];
887
888
        // Check whether the user has already been registered to the course visibility in the catalogue.
889
        $sql = "SELECT * FROM $courseUserTable
890
                WHERE
891
                    user_id = $userId AND
892
                    visible = " . $visible . " AND
893
                    c_id = $courseId";
894
        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...
895
            $cond = array(
896
                'user_id = ? AND c_id = ? AND visible = ? ' => array(
897
                    $userId,
898
                    $courseId,
899
                    $visible
900
                )
901
            );
902
            return Database::delete($courseUserTable, $cond);
903
        } else {
904
            return true; // Register does not exist
905
        }
906
    }
907
908
909
    /**
910
     *    Checks wether a parameter exists.
911
     *    If it doesn't, the function displays an error message.
912
     *
913
     * @return boolean if parameter is set and not empty, false otherwise
914
     * @todo move function to better place, main_api ?
915
     */
916
    public static function check_parameter($parameter, $error_message)
917
    {
918
        if (empty($parameter)) {
919
            Display::display_normal_message($error_message);
0 ignored issues
show
Deprecated Code introduced by
The method Display::display_normal_message() has been deprecated with message: use Display::addFlash with Display::return_message($message, 'normal');

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
920
            return false;
921
        }
922
        return true;
923
    }
924
925
    /**
926
     *    Lets the script die when a parameter check fails.
927
     * @todo move function to better place, main_api ?
928
     */
929
    public static function check_parameter_or_fail($parameter, $error_message)
930
    {
931
        if (!self::check_parameter($parameter, $error_message)) {
932
            die();
933
        }
934
    }
935
936
    /**
937
     * @return boolean if there already are one or more courses
938
     *  with the same code OR visual_code (visualcode), false otherwise
939
     */
940
    public static function course_code_exists($wanted_course_code)
941
    {
942
        $wanted_course_code = Database::escape_string($wanted_course_code);
943
        $sql = "SELECT COUNT(*) as number
944
                FROM " . Database::get_main_table(TABLE_MAIN_COURSE) . "
945
                WHERE code = '$wanted_course_code' OR visual_code = '$wanted_course_code'";
946
        $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...
947
948
        return $result['number'] > 0;
949
    }
950
951
    /**
952
     * Get course list as coach
953
     *
954
     * @param int $user_id
955
     * @param bool $include_courses_in_sessions
956
     * @return array Course list
957
     *
958
     **/
959
    public static function get_course_list_as_coach($user_id, $include_courses_in_sessions = false)
960
    {
961
        // 1. Getting courses as teacher (No session)
962
        $courses_temp = CourseManager::get_course_list_of_user_as_course_admin($user_id);
963
        $courseList = array();
964
965
        if (!empty($courses_temp)) {
966
            foreach ($courses_temp as $course_item) {
967
                $courseList[0][$course_item['code']] = $course_item['code'];
968
            }
969
        }
970
971
        //2. Include courses in sessions
972
        if ($include_courses_in_sessions) {
973
            $sessions = Tracking::get_sessions_coached_by_user($user_id);
974
975
            if (!empty($sessions)) {
976
                foreach ($sessions as $session_item) {
977
                    $courses = Tracking:: get_courses_followed_by_coach($user_id, $session_item['id']);
978
                    if (is_array($courses)) {
979
                        foreach ($courses as $course_item) {
980
                            $courseList[$session_item['id']][$course_item] = $course_item;
981
                        }
982
                    }
983
                }
984
            }
985
        }
986
987
        return $courseList;
988
    }
989
990
    /**
991
     * @param int $user_id
992
     * @param bool $include_sessions
993
     * @return array
994
     */
995
    public static function get_user_list_from_courses_as_coach($user_id, $include_sessions = true)
996
    {
997
        $students_in_courses = array();
998
        $sessions = CourseManager::get_course_list_as_coach($user_id, true);
999
1000
        if (!empty($sessions)) {
1001
            foreach ($sessions as $session_id => $courses) {
1002
                if (!$include_sessions) {
1003
                    if (!empty($session_id)) {
1004
                        continue;
1005
                    }
1006
                }
1007
                if (empty($session_id)) {
1008
                    foreach ($courses as $course_code) {
1009
                        $students_in_course = CourseManager::get_user_list_from_course_code($course_code);
1010
1011
                        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...
1012
                            //Only students
1013
                            if ($user_item['status_rel'] == STUDENT) {
1014
                                $students_in_courses[$user_item['user_id']] = $user_item['user_id'];
1015
                            }
1016
                        }
1017
                    }
1018
                } else {
1019
                    $students_in_course = SessionManager::get_users_by_session($session_id, '0');
1020
                    if (is_array($students_in_course)) {
1021
                        foreach ($students_in_course as $user_item) {
1022
                            $students_in_courses[$user_item['user_id']] = $user_item['user_id'];
1023
                        }
1024
                    }
1025
                }
1026
            }
1027
        }
1028
1029
        $students = Tracking:: get_student_followed_by_coach($user_id);
1030
        if (!empty($students_in_courses)) {
1031
            if (!empty($students)) {
1032
                $students = array_merge($students, $students_in_courses);
1033
            } else {
1034
                $students = $students_in_courses;
1035
            }
1036
        }
1037
1038
        if (!empty($students)) {
1039
            $students = array_unique($students);
1040
        }
1041
        return $students;
1042
    }
1043
1044
    /**
1045
     * @param int $user_id
1046
     * @param string $startsWith Optional
1047
     * @return array An array with the course info of all the courses (real and virtual)
1048
     * of which the current user is course admin.
1049
     */
1050
    public static function get_course_list_of_user_as_course_admin($user_id, $startsWith = null)
1051
    {
1052
        if ($user_id != strval(intval($user_id))) {
1053
            return array();
1054
        }
1055
1056
        // Definitions database tables and variables
1057
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
1058
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1059
        $user_id = intval($user_id);
1060
        $data = array();
1061
1062
        $sql = "SELECT
1063
                    course.code,
1064
                    course.title,
1065
                    course.id,
1066
                    course.id as real_id,
1067
                    course.category_code
1068
                FROM $tbl_course_user as course_rel_user
1069
                INNER JOIN $tbl_course as course
1070
                ON course.id = course_rel_user.c_id
1071
                WHERE
1072
                    course_rel_user.user_id='$user_id' AND
1073
                    course_rel_user.status='1'
1074
        ";
1075
1076 View Code Duplication
        if (api_get_multiple_access_url()) {
1077
            $tbl_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
1078
            $access_url_id = api_get_current_access_url_id();
1079
            if ($access_url_id != -1) {
1080
                $sql = "
1081
                    SELECT
1082
                        course.code,
1083
                        course.title,
1084
                        course.id,
1085
                        course.id as real_id
1086
                    FROM $tbl_course_user as course_rel_user
1087
                    INNER JOIN $tbl_course as course
1088
                    ON course.id = course_rel_user.c_id
1089
                    INNER JOIN $tbl_course_rel_access_url course_rel_url
1090
                    ON (course_rel_url.c_id = course.id)
1091
                    WHERE
1092
                        access_url_id = $access_url_id  AND
1093
                        course_rel_user.user_id = '$user_id' AND
1094
                        course_rel_user.status = '1'
1095
                ";
1096
            }
1097
        }
1098
1099
        if (!empty($startsWith)) {
1100
            $startsWith = Database::escape_string($startsWith);
1101
1102
            $sql .= " AND (course.title LIKE '$startsWith%' OR course.code LIKE '$startsWith%')";
1103
        }
1104
1105
        $sql .= ' ORDER BY course.title';
1106
1107
        $result_nb_cours = Database::query($sql);
1108
        if (Database::num_rows($result_nb_cours) > 0) {
1109
            while ($row = Database::fetch_array($result_nb_cours, 'ASSOC')) {
1110
                $data[$row['id']] = $row;
1111
            }
1112
        }
1113
1114
        return $data;
1115
    }
1116
1117
    /**
1118
     * @param int $userId
1119
     * @param array $courseInfo
1120
     * @return boolean|null
1121
     */
1122
    public static function isUserSubscribedInCourseAsDrh($userId, $courseInfo)
1123
    {
1124
        $userId = intval($userId);
1125
1126
        if (!api_is_drh()) {
1127
            return false;
1128
        }
1129
1130
        if (empty($courseInfo) || empty($userId)) {
1131
            return false;
1132
        }
1133
1134
        $courseId = intval($courseInfo['real_id']);
1135
        $table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1136
1137
        $sql = "SELECT * FROM $table
1138
                WHERE
1139
                    user_id = $userId AND
1140
                    relation_type = " . COURSE_RELATION_TYPE_RRHH . " AND
1141
                    c_id = $courseId";
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
1151
    /**
1152
     * Check if user is subscribed inside a course
1153
     * @param  int $user_id
1154
     * @param  string $course_code , if this parameter is null, it'll check for all courses
1155
     * @param  bool $in_a_session True for checking inside sessions too, by default is not checked
1156
     * @return bool   $session_id true if the user is registered in the course, false otherwise
1157
     */
1158
    public static function is_user_subscribed_in_course(
1159
        $user_id,
1160
        $course_code = null,
1161
        $in_a_session = false,
1162
        $session_id = null
1163
    ) {
1164
        $user_id = intval($user_id);
1165
1166
        if (empty($session_id)) {
1167
            $session_id = api_get_session_id();
1168
        } else {
1169
            $session_id = intval($session_id);
1170
        }
1171
1172
        $condition_course = '';
1173
        if (isset($course_code)) {
1174
            $courseInfo = api_get_course_info($course_code);
1175
            if (empty($courseInfo)) {
1176
                return false;
1177
            }
1178
            $courseId = $courseInfo['real_id'];
1179
            $condition_course = ' AND c_id = ' . $courseId;
1180
        }
1181
1182
        $sql = "SELECT * FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER) . "
1183
                WHERE
1184
                    user_id = $user_id AND
1185
                    relation_type<>" . COURSE_RELATION_TYPE_RRHH . "
1186
                    $condition_course ";
1187
1188
        $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...
1189
1190
        if (!empty($result)) {
1191
            // The user has been registered in this course.
1192
            return true;
1193
        }
1194
1195
        if (!$in_a_session) {
1196
            // The user has not been registered in this course.
1197
            return false;
1198
        }
1199
1200
        $tableSessionCourseUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
1201
        $sql = 'SELECT 1 FROM ' . $tableSessionCourseUser .
1202
            ' WHERE user_id = ' . $user_id . ' ' . $condition_course;
1203
        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...
1204
            return true;
1205
        }
1206
1207
        $sql = 'SELECT 1 FROM ' . $tableSessionCourseUser .
1208
            ' WHERE user_id = ' . $user_id . ' AND status=2 ' . $condition_course;
1209
        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...
1210
            return true;
1211
        }
1212
1213
        $sql = 'SELECT 1 FROM ' . Database::get_main_table(TABLE_MAIN_SESSION) .
1214
            ' WHERE id = ' . $session_id . ' AND id_coach=' . $user_id;
1215
1216
        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...
1217
            return true;
1218
        }
1219
1220
        return false;
1221
    }
1222
1223
    /**
1224
     *    Is the user a teacher in the given course?
1225
     *
1226
     * @param integer $user_id , the id (int) of the user
1227
     * @param $course_code , the course code
1228
     *
1229
     * @return boolean if the user is a teacher in the course, false otherwise
1230
     */
1231
    public static function is_course_teacher($user_id, $course_code)
1232
    {
1233
        if ($user_id != strval(intval($user_id))) {
1234
            return false;
1235
        }
1236
1237
        $courseInfo = api_get_course_info($course_code);
1238
        $courseId = $courseInfo['real_id'];
1239
1240
        $result = Database::query(
1241
            'SELECT status FROM ' . Database::get_main_table(TABLE_MAIN_COURSE_USER) .
1242
            ' WHERE c_id = ' . $courseId . ' AND user_id = ' . $user_id . ''
1243
        );
1244
1245
        if (Database::num_rows($result) > 0) {
1246
            return Database::result($result, 0, 'status') == 1;
1247
        }
1248
1249
        return false;
1250
    }
1251
1252
    /**
1253
     *    Is the user subscribed in the real course or linked courses?
1254
     *
1255
     * @param int the id of the user
1256
     * @param int $courseId
1257
     * @deprecated linked_courses definition doesn't exists
1258
     * @return boolean if the user is registered in the real course or linked courses, false otherwise
1259
     */
1260
    public static function is_user_subscribed_in_real_or_linked_course($user_id, $courseId, $session_id = '')
1261
    {
1262
        if ($user_id != strval(intval($user_id))) {
1263
            return false;
1264
        }
1265
1266
        $courseId = intval($courseId);
1267
1268
        if ($session_id == '') {
1269
            $result = Database::fetch_array(
1270
                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...
1271
                    "SELECT *
1272
                    FROM " . Database::get_main_table(TABLE_MAIN_COURSE) . " course
1273
                    LEFT JOIN " . Database::get_main_table(TABLE_MAIN_COURSE_USER) . " course_user
1274
                    ON course.id = course_user.c_id
1275
                    WHERE
1276
                        course_user.user_id = '$user_id' AND
1277
                        course_user.relation_type<>" . COURSE_RELATION_TYPE_RRHH . " AND
1278
                        ( course.id = '$courseId')"
1279
                )
1280
            );
1281
            return !empty($result);
1282
        }
1283
1284
        $session_id = intval($session_id);
1285
1286
        // From here we trust session id.
1287
        // Is he/she subscribed to the session's course?
1288
1289
        // A user?
1290 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...
1291
                FROM " . Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER) . "
1292
                WHERE session_id='" . $session_id . "'
1293
                AND user_id ='$user_id'"))
1294
        ) {
1295
            return true;
1296
        }
1297
1298
        // A course coach?
1299 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...
1300
                FROM " . Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER) . "
1301
                WHERE session_id='" . $session_id . "'
1302
                AND user_id = '$user_id' AND status = 2
1303
                AND c_id ='$courseId'"))
1304
        ) {
1305
            return true;
1306
        }
1307
1308
        // A session coach?
1309 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...
1310
                FROM " . Database::get_main_table(TABLE_MAIN_SESSION) . " AS session
1311
                WHERE session.id='" . $session_id . "'
1312
                AND id_coach='$user_id'"))
1313
        ) {
1314
            return true;
1315
        }
1316
1317
        return false;
1318
    }
1319
1320
    /**
1321
     * Return user info array of all users registered in a course
1322
     * This only returns the users that are registered in this actual course, not linked courses.
1323
     * @param string $course_code
1324
     * @param int $session_id
1325
     * @param string $limit
1326
     * @param string $order_by the field to order the users by.
1327
     * Valid values are 'lastname', 'firstname', 'username', 'email', 'official_code' OR a part of a SQL statement
1328
     * that starts with ORDER BY ...
1329
     * @param integer|null $filter_by_status if using the session_id: 0 or 2 (student, coach),
1330
     * if using session_id = 0 STUDENT or COURSEMANAGER
1331
     * @param boolean|null $return_count
1332
     * @param bool $add_reports
1333
     * @param bool $resumed_report
1334
     * @param array $extra_field
1335
     * @param array $courseCodeList
1336
     * @param array $userIdList
1337
     * @param string $filterByActive
1338
     * @param array $sessionIdList
1339
     * @return array|int
1340
     */
1341
    public static function get_user_list_from_course_code(
1342
        $course_code = null,
1343
        $session_id = 0,
1344
        $limit = null,
1345
        $order_by = null,
1346
        $filter_by_status = null,
1347
        $return_count = null,
1348
        $add_reports = false,
1349
        $resumed_report = false,
1350
        $extra_field = array(),
1351
        $courseCodeList = array(),
1352
        $userIdList = array(),
1353
        $filterByActive = null,
1354
        $sessionIdList = array()
1355
    ) {
1356
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1357
        $sessionTable = Database::get_main_table(TABLE_MAIN_SESSION);
1358
1359
        $session_id = intval($session_id);
1360
        $course_code = Database::escape_string($course_code);
1361
        $courseInfo = api_get_course_info($course_code);
1362
        $courseId = 0;
1363
        if (!empty($courseInfo)) {
1364
            $courseId = $courseInfo['real_id'];
1365
        }
1366
1367
        $where = array();
1368
        if (empty($order_by)) {
1369
            $order_by = 'user.lastname, user.firstname';
1370
            if (api_is_western_name_order()) {
1371
                $order_by = 'user.firstname, user.lastname';
1372
            }
1373
        }
1374
1375
        // if the $order_by does not contain 'ORDER BY'
1376
        // we have to check if it is a valid field that can be sorted on
1377
        if (!strstr($order_by, 'ORDER BY')) {
1378
            if (!empty($order_by)) {
1379
                $order_by = 'ORDER BY ' . $order_by;
1380
            } else {
1381
                $order_by = '';
1382
            }
1383
        }
1384
1385
        $filter_by_status_condition = null;
1386
1387
        if (!empty($session_id) || !empty($sessionIdList)) {
1388
            $sql = 'SELECT DISTINCT
1389
                        user.user_id,
1390
                        user.email,
1391
                        session_course_user.status as status_session,
1392
                        session_id,
1393
                        user.*,
1394
                        course.*,
1395
                        session.name as session_name
1396
                    ';
1397
            if ($return_count) {
1398
                $sql = " SELECT COUNT(user.user_id) as count";
1399
            }
1400
1401
            $sessionCondition = " session_course_user.session_id = $session_id";
1402
            if (!empty($sessionIdList)) {
1403
                $sessionIdListTostring = implode("','", array_map('intval', $sessionIdList));
1404
                $sessionCondition = " session_course_user.session_id IN ('$sessionIdListTostring') ";
1405
            }
1406
1407
            $courseCondition = " course.id = $courseId";
1408
            if (!empty($courseCodeList)) {
1409
                $courseCodeListForSession = array_map(array('Database', 'escape_string'), $courseCodeList);
1410
                $courseCodeListForSession = implode('","', $courseCodeListForSession);
1411
                $courseCondition = ' course.code IN ("' . $courseCodeListForSession . '")  ';
1412
            }
1413
1414
            $sql .= ' FROM ' . Database::get_main_table(TABLE_MAIN_USER) . ' as user ';
1415
            $sql .= " LEFT JOIN ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER) . " as session_course_user
1416
                      ON
1417
                        user.id = session_course_user.user_id AND
1418
                        $sessionCondition
1419
                        INNER JOIN $course_table course 
1420
                        ON session_course_user.c_id = course.id AND
1421
                        $courseCondition
1422
                        INNER JOIN $sessionTable session 
1423
                        ON session_course_user.session_id = session.id
1424
                   ";
1425
            $where[] = ' session_course_user.c_id IS NOT NULL ';
1426
1427
            // 2 = coach
1428
            // 0 = student
1429
            if (isset($filter_by_status)) {
1430
                $filter_by_status = intval($filter_by_status);
1431
                $filter_by_status_condition = " session_course_user.status = $filter_by_status AND ";
1432
            }
1433
        } else {
1434
            if ($return_count) {
1435
                $sql = " SELECT COUNT(*) as count";
1436
            } else {
1437
                if (empty($course_code)) {
1438
                    $sql = 'SELECT DISTINCT
1439
                                course.title,
1440
                                course.code,
1441
                                course_rel_user.status as status_rel,
1442
                                user.id as user_id,
1443
                                user.email,
1444
                                course_rel_user.is_tutor,
1445
                                user.*  ';
1446
                } else {
1447
                    $sql = 'SELECT DISTINCT
1448
                                course_rel_user.status as status_rel,
1449
                                user.id as user_id,
1450
                                user.email,
1451
                                course_rel_user.is_tutor,
1452
                                user.*  ';
1453
                }
1454
            }
1455
1456
            $sql .= ' FROM ' . Database::get_main_table(TABLE_MAIN_USER) . ' as user '
1457
                  . ' LEFT JOIN ' . Database::get_main_table(TABLE_MAIN_COURSE_USER) . ' as course_rel_user
1458
                      ON 
1459
                        user.id = course_rel_user.user_id AND
1460
                        course_rel_user.relation_type <> ' . COURSE_RELATION_TYPE_RRHH . '  '
1461
                  . " INNER JOIN $course_table course ON course_rel_user.c_id = course.id ";
1462
1463
            if (!empty($course_code)) {
1464
                $sql .= ' AND course_rel_user.c_id = "' . $courseId . '"';
1465
            }
1466
            $where[] = ' course_rel_user.c_id IS NOT NULL ';
1467
1468
            if (isset($filter_by_status) && is_numeric($filter_by_status)) {
1469
                $filter_by_status = intval($filter_by_status);
1470
                $filter_by_status_condition = " course_rel_user.status = $filter_by_status AND ";
1471
            }
1472
        }
1473
1474
        $multiple_access_url = api_get_multiple_access_url();
1475
        if ($multiple_access_url) {
1476
            $sql .= ' LEFT JOIN ' . Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER) . ' au
1477
                      ON (au.user_id = user.id) ';
1478
        }
1479
1480
        $extraFieldWasAdded = false;
1481
        if ($return_count && $resumed_report) {
1482
            foreach ($extra_field as $extraField) {
1483
                $extraFieldInfo = UserManager::get_extra_field_information_by_name($extraField);
1484
                if (!empty($extraFieldInfo)) {
1485
                    $fieldValuesTable = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
1486
                    $sql .= ' LEFT JOIN '.$fieldValuesTable.' as ufv
1487
                            ON (
1488
                                user.id = ufv.item_id AND
1489
                                (field_id = '.$extraFieldInfo['id'].' OR field_id IS NULL)
1490
                            )';
1491
                    $extraFieldWasAdded = true;
1492
                }
1493
            }
1494
        }
1495
1496
        $sql .= ' WHERE ' . $filter_by_status_condition . ' ' . implode(' OR ', $where);
1497
1498
        if ($multiple_access_url) {
1499
            $current_access_url_id = api_get_current_access_url_id();
1500
            $sql .= " AND (access_url_id =  $current_access_url_id ) ";
1501
        }
1502
1503
        if ($return_count && $resumed_report && $extraFieldWasAdded) {
1504
            $sql .= ' AND field_id IS NOT NULL GROUP BY value ';
1505
        }
1506
1507
        if (!empty($courseCodeList)) {
1508
            $courseCodeList = array_map(array('Database', 'escape_string'), $courseCodeList);
1509
            $courseCodeList = implode('","', $courseCodeList);
1510
            if (empty($sessionIdList)) {
1511
                $sql .= ' AND course.code IN ("'.$courseCodeList.'")';
1512
            }
1513
        }
1514
1515 View Code Duplication
        if (!empty($userIdList)) {
1516
            $userIdList = array_map('intval', $userIdList);
1517
            $userIdList = implode('","', $userIdList);
1518
            $sql .= ' AND user.id IN ("' . $userIdList . '")';
1519
        }
1520
1521
        if (isset($filterByActive)) {
1522
            $filterByActive = intval($filterByActive);
1523
            $sql .= ' AND user.active = ' . $filterByActive;
1524
        }
1525
1526
        $sql .= ' ' . $order_by . ' ' . $limit;
1527
1528
        $rs = Database::query($sql);
1529
        $users = array();
1530
1531
        $extra_fields = UserManager::get_extra_fields(0, 100, null, null, true, true);
1532
1533
        $counter = 1;
1534
        $count_rows = Database::num_rows($rs);
1535
1536
        if ($return_count && $resumed_report) {
1537
            return $count_rows;
1538
        }
1539
1540
        $table_user_field_value = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
1541
        $tableExtraField = Database::get_main_table(TABLE_EXTRA_FIELD);
1542
        if ($count_rows) {
1543
            while ($user = Database::fetch_array($rs)) {
1544
                if ($return_count) {
1545
                    return $user['count'];
1546
                }
1547
                $report_info = array();
1548
1549
                $user_info = $user;
1550
                $user_info['status'] = $user['status'];
1551
1552
                if (isset($user['is_tutor'])) {
1553
                    $user_info['is_tutor'] = $user['is_tutor'];
1554
                }
1555
1556
                if (!empty($session_id)) {
1557
                    $user_info['status_session'] = $user['status_session'];
1558
                }
1559
1560
                $sessionId = isset($user['session_id']) ? $user['session_id'] : 0;
1561
                $course_code = isset($user['code']) ? $user['code'] : null;
1562
1563
                if ($add_reports) {
1564
                    if ($resumed_report) {
1565
                        $extra = array();
1566
1567
                        if (!empty($extra_fields)) {
1568
                            foreach ($extra_fields as $extra) {
1569
                                if (in_array($extra['1'], $extra_field)) {
1570
                                    $user_data = UserManager::get_extra_user_data_by_field(
1571
                                        $user['user_id'],
1572
                                        $extra['1']
1573
                                    );
1574
                                    break;
1575
                                }
1576
                            }
1577
                        }
1578
1579
                        $row_key = '-1';
1580
                        $name = '-';
1581
1582
                        if (!empty($extra)) {
1583
                            if (!empty($user_data[$extra['1']])) {
1584
                                $row_key = $user_data[$extra['1']];
1585
                                $name = $user_data[$extra['1']];
1586
                                $users[$row_key]['extra_'.$extra['1']] = $name;
1587
                            }
1588
                        }
1589
1590
                        $users[$row_key]['training_hours'] += Tracking::get_time_spent_on_the_course(
1591
                            $user['user_id'],
1592
                            $courseId,
1593
                            $sessionId
1594
                        );
1595
1596
                        $users[$row_key]['count_users'] += $counter;
1597
1598
                        $registered_users_with_extra_field = CourseManager::getCountRegisteredUsersWithCourseExtraField(
1599
                            $name,
1600
                            $tableExtraField,
1601
                            $table_user_field_value
1602
                        );
1603
1604
                        $users[$row_key]['count_users_registered'] = $registered_users_with_extra_field;
1605
                        $users[$row_key]['average_hours_per_user'] = $users[$row_key]['training_hours'] / $users[$row_key]['count_users'];
1606
1607
                        $category = Category:: load(
1608
                            null,
1609
                            null,
1610
                            $course_code,
1611
                            null,
1612
                            null,
1613
                            $sessionId
1614
                        );
1615
1616
                        if (!isset($users[$row_key]['count_certificates'])) {
1617
                            $users[$row_key]['count_certificates'] = 0;
1618
                        }
1619
1620
                        if (isset($category[0]) && $category[0]->is_certificate_available($user['user_id'])) {
1621
                            $users[$row_key]['count_certificates']++;
1622
                        }
1623
1624
                        foreach ($extra_fields as $extra) {
1625
                            if ($extra['1'] == 'ruc') {
1626
                                continue;
1627
                            }
1628
1629
                            if (!isset($users[$row_key][$extra['1']])) {
1630
                                $user_data = UserManager::get_extra_user_data_by_field($user['user_id'], $extra['1']);
1631
                                if (!empty($user_data[$extra['1']])) {
1632
                                    $users[$row_key][$extra['1']] = $user_data[$extra['1']];
1633
                                }
1634
                            }
1635
                        }
1636
                    } else {
1637
                        $sessionName = !empty($sessionId) ? ' - '.$user['session_name'] : '';
1638
                        $report_info['course'] = $user['title'].$sessionName;
1639
                        $report_info['user'] = api_get_person_name($user['firstname'], $user['lastname']);
1640
                        $report_info['email'] = $user['email'];
1641
                        $report_info['time'] = api_time_to_hms(
1642
                            Tracking::get_time_spent_on_the_course(
1643
                                $user['user_id'],
1644
                                $courseId,
1645
                                $sessionId
1646
                            )
1647
                        );
1648
1649
                        $category = Category:: load(
1650
                            null,
1651
                            null,
1652
                            $course_code,
1653
                            null,
1654
                            null,
1655
                            $sessionId
1656
                        );
1657
1658
                        $report_info['certificate'] = Display::label(get_lang('No'));
1659
                        if (isset($category[0]) && $category[0]->is_certificate_available($user['user_id'])) {
1660
                            $report_info['certificate'] = Display::label(get_lang('Yes'), 'success');
1661
                        }
1662
1663
                        $progress = intval(
1664
                            Tracking::get_avg_student_progress(
1665
                                $user['user_id'],
1666
                                $course_code,
1667
                                array(),
1668
                                $sessionId
1669
                            )
1670
                        );
1671
                        $report_info['progress_100'] = $progress == 100 ? Display::label(get_lang('Yes'), 'success') : Display::label(get_lang('No'));
1672
                        $report_info['progress'] = $progress . "%";
1673
1674
                        foreach ($extra_fields as $extra) {
1675
                            $user_data = UserManager::get_extra_user_data_by_field($user['user_id'], $extra['1']);
1676
                            $report_info[$extra['1']] = $user_data[$extra['1']];
1677
                        }
1678
                        $report_info['user_id'] = $user['user_id'];
1679
                        $users[] = $report_info;
1680
                    }
1681
                } else {
1682
                    $users[$user['user_id']] = $user_info;
1683
                }
1684
            }
1685
        }
1686
1687
        return $users;
1688
    }
1689
1690
    /**
1691
     * @param bool $resumed_report
1692
     * @param array $extra_field
1693
     * @param array $courseCodeList
1694
     * @param array $userIdList
1695
     * @param array $sessionIdList
1696
     * @return array|int
1697
     */
1698
    public static function get_count_user_list_from_course_code(
1699
        $resumed_report = false,
1700
        $extra_field = array(),
1701
        $courseCodeList = array(),
1702
        $userIdList = array(),
1703
        $sessionIdList = array()
1704
    ) {
1705
        return self::get_user_list_from_course_code(
1706
            null,
1707
            0,
1708
            null,
1709
            null,
1710
            null,
1711
            true,
1712
            false,
1713
            $resumed_report,
1714
            $extra_field,
1715
            $courseCodeList,
1716
            $userIdList,
1717
            null,
1718
            $sessionIdList
1719
        );
1720
    }
1721
1722
    /**
1723
     * Gets subscribed users in a course or in a course/session
1724
     *
1725
     * @param   string $course_code
1726
     * @param   int $session_id
1727
     * @return  int
1728
     */
1729
    public static function get_users_count_in_course(
1730
        $course_code,
1731
        $session_id = 0,
1732
        $status = null
1733
    ) {
1734
        // variable initialisation
1735
        $session_id = intval($session_id);
1736
        $course_code = Database::escape_string($course_code);
1737
1738
        $courseInfo = api_get_course_info($course_code);
1739
        $courseId = $courseInfo['real_id'];
1740
1741
        $sql = 'SELECT DISTINCT count(*) as count  FROM ' . Database::get_main_table(TABLE_MAIN_USER) . ' as user ';
1742
        $where = array();
1743
        if (!empty($session_id)) {
1744
            $sql .= ' LEFT JOIN ' . Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER) . ' as session_course_user
1745
                      ON
1746
                        user.user_id = session_course_user.user_id AND
1747
                        session_course_user.c_id = "' . $courseId . '" AND
1748
                        session_course_user.session_id  = ' . $session_id;
1749
1750
            $where[] = ' session_course_user.c_id IS NOT NULL ';
1751
        } else {
1752
            $sql .= ' LEFT JOIN ' . Database::get_main_table(TABLE_MAIN_COURSE_USER) . ' as course_rel_user
1753
                        ON
1754
                            user.user_id = course_rel_user.user_id AND
1755
                            course_rel_user.relation_type<>' . COURSE_RELATION_TYPE_RRHH . ' AND
1756
                            course_rel_user.c_id = ' . $courseId ;
1757
            $where[] = ' course_rel_user.c_id IS NOT NULL ';
1758
        }
1759
1760
        $multiple_access_url = api_get_multiple_access_url();
1761
        if ($multiple_access_url) {
1762
            $sql .= ' LEFT JOIN ' . Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER) . '  au
1763
                      ON (au.user_id = user.user_id) ';
1764
        }
1765
1766
        $sql .= ' WHERE ' . implode(' OR ', $where);
1767
1768
        if ($multiple_access_url) {
1769
            $current_access_url_id = api_get_current_access_url_id();
1770
            $sql .= " AND (access_url_id =  $current_access_url_id ) ";
1771
        }
1772
        $rs = Database::query($sql);
1773
        $count = 0;
1774
        if (Database::num_rows($rs)) {
1775
            $user = Database::fetch_array($rs);
1776
            $count = $user['count'];
1777
        }
1778
1779
        return $count;
1780
    }
1781
1782
    /**
1783
     * Get a list of coaches of a course and a session
1784
     * @param   string  Course code
1785
     * @param   int     Session ID
1786
     * @param   bool $addGeneralCoach
1787
     * @return  array   List of users
1788
     */
1789
    public static function get_coach_list_from_course_code($course_code, $session_id, $addGeneralCoach = true)
1790
    {
1791
        if (empty($course_code) || empty($session_id)) {
1792
            return array();
1793
        }
1794
1795
        $course_code = Database::escape_string($course_code);
1796
        $courseInfo = api_get_course_info($course_code);
1797
        $courseId = $courseInfo['real_id'];
1798
1799
        $session_id = intval($session_id);
1800
        $users = array();
1801
1802
        // We get the coach for the given course in a given session.
1803
        $sql = 'SELECT user_id FROM ' . Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER) .
1804
               ' WHERE session_id ="' . $session_id . '" AND c_id="' . $courseId . '" AND status = 2';
1805
        $rs = Database::query($sql);
1806
        while ($user = Database::fetch_array($rs)) {
1807
            $userInfo = api_get_user_info($user['user_id']);
1808
            if ($userInfo) {
1809
                $users[$user['user_id']] = $userInfo;
1810
            }
1811
        }
1812
1813
        if ($addGeneralCoach) {
1814
            $table = Database::get_main_table(TABLE_MAIN_SESSION);
1815
            // We get the session coach.
1816
            $sql = 'SELECT id_coach FROM '.$table.' WHERE id='.$session_id;
1817
            $rs = Database::query($sql);
1818
            $session_id_coach = Database::result($rs, 0, 'id_coach');
1819
            $userInfo = api_get_user_info($session_id_coach);
1820
            if ($userInfo) {
1821
                $users[$session_id_coach] = $userInfo;
1822
            }
1823
        }
1824
1825
        return $users;
1826
    }
1827
1828
    /**
1829
     *  Return user info array of all users registered in a course
1830
     *  This only returns the users that are registered in this actual course, not linked courses.
1831
     *
1832
     * @param string $course_code
1833
     * @param boolean $with_session
1834
     * @param integer $session_id
1835
     * @param string $date_from
1836
     * @param string $date_to
1837
     * @param boolean $includeInvitedUsers Whether include the invited users
1838
     * @param int $groupId
1839
     * @return array with user id
1840
     */
1841
    public static function get_student_list_from_course_code(
1842
        $course_code,
1843
        $with_session = false,
1844
        $session_id = 0,
1845
        $date_from = null,
1846
        $date_to = null,
1847
        $includeInvitedUsers = true,
1848
        $groupId = 0
1849
    ) {
1850
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
1851
        $session_id = intval($session_id);
1852
        $course_code = Database::escape_string($course_code);
1853
        $courseInfo = api_get_course_info($course_code);
1854
        $courseId = $courseInfo['real_id'];
1855
        $students = array();
1856
1857
        if ($session_id == 0) {
1858
            if (empty($groupId)) {
1859
                // students directly subscribed to the course
1860
                $sql = "SELECT *
1861
                        FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)." cu
1862
                        INNER JOIN $userTable u
1863
                        ON cu.user_id = u.user_id
1864
                        WHERE c_id = '$courseId' AND cu.status = ".STUDENT;
1865
1866
                if (!$includeInvitedUsers) {
1867
                    $sql .= " AND u.status != ".INVITEE;
1868
                }
1869
                $rs = Database::query($sql);
1870
                while ($student = Database::fetch_array($rs)) {
1871
                    $students[$student['user_id']] = $student;
1872
                }
1873
            } else {
1874
                $students = GroupManager::get_users(
1875
                    $groupId,
1876
                    false,
1877
                    null,
1878
                    null,
1879
                    false,
1880
                    $courseInfo['real_id']
1881
                );
1882
                $students = array_flip($students);
1883
            }
1884
        }
1885
1886
        // students subscribed to the course through a session
1887
        if ($with_session) {
1888
1889
            $joinSession = "";
1890
            //Session creation date
1891
            if (!empty($date_from) && !empty($date_to)) {
1892
                $joinSession = "INNER JOIN " . Database::get_main_table(TABLE_MAIN_SESSION) . " s";
1893
            }
1894
1895
            $sql_query = "SELECT *
1896
                          FROM " . Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER) . " scu
1897
                          $joinSession
1898
                          INNER JOIN $userTable u ON scu.user_id = u.user_id
1899
                          WHERE scu.c_id = '$courseId' AND scu.status <> 2";
1900
1901
            if (!empty($date_from) && !empty($date_to)) {
1902
                $date_from = Database::escape_string($date_from);
1903
                $date_to = Database::escape_string($date_to);
1904
                $sql_query .= " AND s.access_start_date >= '$date_from' AND s.access_end_date <= '$date_to'";
1905
            }
1906
1907
            if ($session_id != 0) {
1908
                $sql_query .= ' AND scu.session_id = ' . $session_id;
1909
            }
1910
1911
            if (!$includeInvitedUsers) {
1912
                $sql_query .= " AND u.status != " . INVITEE;
1913
            }
1914
1915
            $rs = Database::query($sql_query);
1916
            while ($student = Database::fetch_array($rs)) {
1917
                $students[$student['user_id']] = $student;
1918
            }
1919
        }
1920
1921
        return $students;
1922
    }
1923
1924
    /**
1925
     * Return user info array of all teacher-users registered in a course
1926
     * This only returns the users that are registered in this actual course, not linked courses.
1927
     *
1928
     * @param string $course_code
1929
     * @return array with user id
1930
     */
1931
    public static function get_teacher_list_from_course_code($course_code)
1932
    {
1933
        $courseInfo = api_get_course_info($course_code);
1934
        $courseId = $courseInfo['real_id'];
1935
        if (empty($courseId)) {
1936
            return false;
1937
        }
1938
1939
        $sql = "SELECT DISTINCT
1940
                    u.id as user_id,
1941
                    u.lastname,
1942
                    u.firstname,
1943
                    u.email,
1944
                    u.username,
1945
                    u.status
1946
                FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER) . " cu
1947
                INNER JOIN " . Database::get_main_table(TABLE_MAIN_USER) . " u
1948
                ON (cu.user_id = u.id)
1949
                WHERE
1950
                    cu.c_id = $courseId AND
1951
                    cu.status = 1 ";
1952
        $rs = Database::query($sql);
1953
        $teachers = array();
1954
        while ($teacher = Database::fetch_array($rs)) {
1955
            $teachers[$teacher['user_id']] = $teacher;
1956
        }
1957
1958
        return $teachers;
1959
    }
1960
1961
1962
    /**
1963
     * Return user info array of all teacher-users registered in a course
1964
     * This only returns the users that are registered in this actual course, not linked courses.
1965
     *
1966
     * @param string $course_code
1967
     * @return array with user id
1968
     */
1969
    public static function getTeachersFromCourseByCode($course_code)
1970
    {
1971
        $courseInfo = api_get_course_info($course_code);
1972
        $courseId = $courseInfo['real_id'];
1973
        if (empty($courseId)) {
1974
            return false;
1975
        }
1976
1977
        $sql = "SELECT DISTINCT
1978
                    u.id as user_id,
1979
                    u.lastname,
1980
                    u.firstname,
1981
                    u.email,
1982
                    u.username,
1983
                    u.status
1984
                FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER) . " cu
1985
                INNER JOIN " . Database::get_main_table(TABLE_MAIN_USER) . " u
1986
                ON (cu.user_id = u.id)
1987
                WHERE
1988
                    cu.c_id = $courseId AND
1989
                    cu.status = 1 ";
1990
        $rs = Database::query($sql);
1991
        $listTeachers = array();
1992
        $teachers = array();
1993
        while ($teacher = Database::fetch_array($rs)) {
1994
            $userPicture = UserManager::getUserPicture($teacher['user_id'], USER_IMAGE_SIZE_SMALL);
1995
            $teachers['id'] = $teacher['user_id'];
1996
            $teachers['lastname'] = $teacher['lastname'];
1997
            $teachers['firstname'] = $teacher['firstname'];
1998
            $teachers['email'] = $teacher['email'];
1999
            $teachers['username'] = $teacher['username'];
2000
            $teachers['status'] = $teacher['status'];
2001
            $teachers['avatar'] = $userPicture;
2002
            $teachers['url'] = api_get_path(WEB_AJAX_PATH) . 'user_manager.ajax.php?a=get_user_popup&user_id=' . $teacher['user_id'];
2003
            $listTeachers[]=$teachers;
2004
        }
2005
        return $listTeachers;
2006
    }
2007
2008
    /**
2009
     * Returns a string list of teachers assigned to the given course
2010
     * @param string $course_code
2011
     * @param string $separator between teachers names
2012
     * @param bool $add_link_to_profile Whether to add a link to the teacher's profile
2013
     * @return string List of teachers teaching the course
2014
     */
2015
    public static function get_teacher_list_from_course_code_to_string(
2016
        $course_code,
2017
        $separator = self::USER_SEPARATOR,
2018
        $add_link_to_profile = false,
2019
        $orderList = false
2020
    ) {
2021
        $teacher_list = self::get_teacher_list_from_course_code($course_code);
2022
        $html = '';
2023
        $list = array();
2024
        if (!empty($teacher_list)) {
2025 View Code Duplication
            foreach ($teacher_list as $teacher) {
2026
                $teacher_name = api_get_person_name(
2027
                    $teacher['firstname'],
2028
                    $teacher['lastname']
2029
                );
2030
                if ($add_link_to_profile) {
2031
                    $url = api_get_path(WEB_AJAX_PATH) . 'user_manager.ajax.php?a=get_user_popup&user_id=' . $teacher['user_id'];
2032
                    $teacher_name = Display::url(
2033
                        $teacher_name,
2034
                        $url,
2035
                        [
2036
                            'class' => 'ajax',
2037
                            'data-title' => $teacher_name
2038
                        ]
2039
                    );
2040
                }
2041
                $list[] = $teacher_name;
2042
            }
2043
2044 View Code Duplication
            if (!empty($list)) {
2045
                if ($orderList === true){
2046
                    $html .= '<ul class="user-teacher">';
2047
                    foreach ($list as $teacher){
2048
                        $html .= Display::tag('li', Display::return_icon('teacher.png', $teacher, null, ICON_SIZE_TINY) . ' ' . $teacher);
2049
                    }
2050
                    $html .= '</ul>';
2051
                } else {
2052
                    $html .= array_to_string($list, $separator);
2053
                }
2054
            }
2055
        }
2056
2057
        return $html;
2058
    }
2059
2060
    /**
2061
     * This function returns information about coachs from a course in session
2062
     * @param int $session_id
2063
     * @param int $courseId
2064
     *
2065
     * @return array    - array containing user_id, lastname, firstname, username
2066
     *
2067
     */
2068
    public static function get_coachs_from_course($session_id = 0, $courseId = '')
2069
    {
2070
        if (!empty($session_id)) {
2071
            $session_id = intval($session_id);
2072
        } else {
2073
            $session_id = api_get_session_id();
2074
        }
2075
2076
        if (!empty($courseId)) {
2077
            $courseId = intval($courseId);
2078
        } else {
2079
            $courseId = api_get_course_int_id();
2080
        }
2081
2082
        $tbl_user = Database:: get_main_table(TABLE_MAIN_USER);
2083
        $tbl_session_course_user = Database:: get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2084
        $coaches = array();
2085
2086
        $sql = "SELECT DISTINCT u.user_id,u.lastname,u.firstname,u.username
2087
                FROM $tbl_user u, $tbl_session_course_user scu
2088
                WHERE
2089
                    u.user_id = scu.user_id AND
2090
                    scu.session_id = '$session_id' AND
2091
                    scu.c_id = '$courseId' AND
2092
                    scu.status = 2";
2093
        $rs = Database::query($sql);
2094
2095
        if (Database::num_rows($rs) > 0) {
2096 View Code Duplication
            while ($row = Database::fetch_array($rs)) {
2097
                $completeName = api_get_person_name($row['firstname'], $row['lastname']);
2098
2099
                $coaches[] = $row + ['full_name' => $completeName];
2100
            }
2101
2102
            return $coaches;
2103
        } else {
2104
2105
            return false;
2106
        }
2107
    }
2108
2109
    /**
2110
     * @param int $session_id
2111
     * @param int $courseId
2112
     * @param string $separator
2113
     * @param bool $add_link_to_profile
2114
     * @return string
2115
     */
2116
    public static function get_coachs_from_course_to_string(
2117
        $session_id = 0,
2118
        $courseId = null,
2119
        $separator = self::USER_SEPARATOR,
2120
        $add_link_to_profile = false,
2121
        $orderList = false
2122
    ) {
2123
        $coachs_course = self::get_coachs_from_course($session_id, $courseId);
2124
        $course_coachs = array();
2125
        $html = '';
2126
        if (is_array($coachs_course)) {
2127 View Code Duplication
            foreach ($coachs_course as $coach_course) {
2128
                $coach_name = api_get_person_name($coach_course['firstname'], $coach_course['lastname']);
2129
                if ($add_link_to_profile) {
2130
                    $url = api_get_path(WEB_AJAX_PATH) . 'user_manager.ajax.php?a=get_user_popup&user_id=' . $coach_course['user_id'];
2131
                    $coach_name = Display::url(
2132
                        $coach_name,
2133
                        $url,
2134
                        [
2135
                            'class' => 'ajax',
2136
                            'data-title' => $coach_name
2137
                        ]
2138
                    );
2139
                }
2140
                $course_coachs[] = $coach_name;
2141
            }
2142
        }
2143
        $coaches_to_string = null;
2144
2145 View Code Duplication
        if (!empty($course_coachs)) {
2146
            if ($orderList === true){
2147
                $html .= '<ul class="user-coachs">';
2148
                    foreach ($course_coachs as $coachs){
2149
                        $html .= Display::tag('li', Display::return_icon('teacher.png', $coachs, null, ICON_SIZE_TINY) . ' ' . $coachs);
2150
                    }
2151
                $html .= '</ul>';
2152
            } else {
2153
                $coaches_to_string = array_to_string($course_coachs, $separator);
2154
            }
2155
2156
        }
2157
2158
        return $html;
2159
    }
2160
2161
    /**
2162
     * Return user info array of all users registered in the specified course
2163
     * this includes the users of the course itself and the users of all linked courses.
2164
     *
2165
     * @param string $course_code
2166
     * @param bool $with_sessions
2167
     * @param int $session_id
2168
     * @return array with user info
2169
     */
2170
    public static function get_real_and_linked_user_list($course_code, $with_sessions = true, $session_id = 0)
2171
    {
2172
        $complete_user_list = array();
2173
2174
        //get users from real course
2175
        $user_list = self::get_user_list_from_course_code($course_code, $session_id);
2176
        foreach ($user_list as $this_user) {
0 ignored issues
show
Bug introduced by
The expression $user_list 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...
2177
            $complete_user_list[] = $this_user;
2178
        }
2179
2180
        return $complete_user_list;
2181
    }
2182
2183
    /**
2184
     * Get the list of groups from the course
2185
     * @param   string $course_code
2186
     * @param   int $session_id Session ID (optional)
2187
     * @param   integer $in_get_empty_group get empty groups (optional)
2188
     * @return  array   List of groups info
2189
     */
2190
    public static function get_group_list_of_course($course_code, $session_id = 0, $in_get_empty_group = 0)
2191
    {
2192
        $course_info = api_get_course_info($course_code);
2193
2194
        if (empty($course_info)) {
2195
            return array();
2196
        }
2197
        $course_id = $course_info['real_id'];
2198
2199
        if (empty($course_id)) {
2200
            return array();
2201
        }
2202
2203
        $group_list = array();
2204
        $session_id != 0 ? $session_condition = ' WHERE g.session_id IN(1,' . intval($session_id) . ')' : $session_condition = ' WHERE g.session_id = 0';
2205
2206
        if ($in_get_empty_group == 0) {
2207
            // get only groups that are not empty
2208
            $sql = "SELECT DISTINCT g.id, g.iid, g.name
2209
                    FROM " . Database::get_course_table(TABLE_GROUP) . " AS g
2210
                    INNER JOIN " . Database::get_course_table(TABLE_GROUP_USER) . " gu
2211
                    ON (g.id = gu.group_id AND g.c_id = $course_id AND gu.c_id = $course_id)
2212
                    $session_condition
2213
                    ORDER BY g.name";
2214
        } else {
2215
            // get all groups even if they are empty
2216
            $sql = "SELECT g.id, g.name, g.iid 
2217
                    FROM " . Database::get_course_table(TABLE_GROUP) . " AS g
2218
                    $session_condition
2219
                    AND c_id = $course_id";
2220
        }
2221
        $result = Database::query($sql);
2222
2223
        while ($group_data = Database::fetch_array($result)) {
2224
            $group_data['userNb'] = GroupManager::number_of_students($group_data['iid'], $course_id);
2225
            $group_list[$group_data['id']] = $group_data;
2226
        }
2227
        return $group_list;
2228
    }
2229
2230
    /**
2231
     * Delete a course
2232
     * This function deletes a whole course-area from the platform. When the
2233
     * given course is a virtual course, the database and directory will not be
2234
     * deleted.
2235
     * When the given course is a real course, also all virtual courses refering
2236
     * to the given course will be deleted.
2237
     * Considering the fact that we remove all traces of the course in the main
2238
     * database, it makes sense to remove all tracking as well (if stats databases exist)
2239
     * so that a new course created with this code would not use the remains of an older
2240
     * course.
2241
     *
2242
     * @param string The code of the course to delete
2243
     * @param string $code
2244
     * @todo When deleting a virtual course: unsubscribe users from that virtual
2245
     * course from the groups in the real course if they are not subscribed in
2246
     * that real course.
2247
     * @todo Remove globals
2248
     */
2249
    public static function delete_course($code)
2250
    {
2251
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
2252
        $table_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2253
        $table_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2254
        $table_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2255
        $table_course_survey = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY);
2256
        $table_course_survey_question = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION);
2257
        $table_course_survey_question_option = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
2258
        $table_course_rel_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2259
2260
        $table_stats_hotpots = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTPOTATOES);
2261
        $table_stats_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
2262
        $table_stats_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
2263
        $table_stats_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS);
2264
        $table_stats_lastaccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
2265
        $table_stats_course_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
2266
        $table_stats_online = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ONLINE);
2267
        $table_stats_default = Database::get_main_table(TABLE_STATISTIC_TRACK_E_DEFAULT);
2268
        $table_stats_downloads = Database::get_main_table(TABLE_STATISTIC_TRACK_E_DOWNLOADS);
2269
        $table_stats_links = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LINKS);
2270
        $table_stats_uploads = Database::get_main_table(TABLE_STATISTIC_TRACK_E_UPLOADS);
2271
2272
        $codeFiltered = Database::escape_string($code);
2273
        $sql = "SELECT * FROM $table_course WHERE code='" . $codeFiltered . "'";
2274
        $res = Database::query($sql);
2275
2276
        if (Database::num_rows($res) == 0) {
2277
            return;
2278
        }
2279
2280
        $sql = "SELECT * FROM $table_course
2281
                WHERE code = '" . $codeFiltered . "'";
2282
        $res = Database::query($sql);
2283
        $course = Database::fetch_array($res);
2284
        $courseId = $course['id'];
2285
2286
        $count = 0;
2287
        if (api_is_multiple_url_enabled()) {
2288
            $url_id = 1;
2289
            if (api_get_current_access_url_id() != -1) {
2290
                $url_id = api_get_current_access_url_id();
2291
            }
2292
            UrlManager::delete_url_rel_course($courseId, $url_id);
2293
            $count = UrlManager::getCountUrlRelCourse($courseId);
2294
        }
2295
2296
        if ($count == 0) {
2297
            self::create_database_dump($code);
2298
2299
            $course_tables = AddCourse::get_course_tables();
2300
2301
            // Cleaning group categories
2302
            $groupCategories = GroupManager::get_categories($course['code']);
2303
2304
            if (!empty($groupCategories)) {
2305
                foreach ($groupCategories as $category) {
2306
                    GroupManager::delete_category($category['id'], $course['code']);
2307
                }
2308
            }
2309
2310
            // Cleaning groups
2311
            $groups = GroupManager::get_groups($courseId);
2312
            if (!empty($groups)) {
2313
                $groupList = array_column($groups, 'iid');
2314
                foreach ($groupList as $groupId) {
2315
                    GroupManager::delete_groups($groupId, $course['code']);
2316
                }
2317
2318
            }
2319
2320
            // Cleaning c_x tables
2321
            if (!empty($courseId)) {
2322
                foreach ($course_tables as $table) {
2323
                    $table = Database::get_course_table($table);
2324
                    $sql = "DELETE FROM $table WHERE c_id = $courseId ";
2325
                    Database::query($sql);
2326
                }
2327
            }
2328
2329
            $course_dir = api_get_path(SYS_COURSE_PATH) . $course['directory'];
2330
            $archive_dir = api_get_path(SYS_ARCHIVE_PATH) . $course['directory'] . '_' . time();
2331
            if (is_dir($course_dir)) {
2332
                rename($course_dir, $archive_dir);
2333
            }
2334
2335
            // Unsubscribe all users from the course
2336
            $sql = "DELETE FROM $table_course_user WHERE c_id='" . $courseId . "'";
2337
            Database::query($sql);
2338
            // Delete the course from the sessions tables
2339
            $sql = "DELETE FROM $table_session_course WHERE c_id='" . $courseId . "'";
2340
            Database::query($sql);
2341
            $sql = "DELETE FROM $table_session_course_user WHERE c_id='" . $courseId . "'";
2342
            Database::query($sql);
2343
2344
            // Delete from Course - URL
2345
            $sql = "DELETE FROM $table_course_rel_url WHERE c_id = '" . $courseId. "'";
2346
            Database::query($sql);
2347
2348
            $sql = 'SELECT survey_id FROM ' . $table_course_survey . ' WHERE course_code="' . $codeFiltered . '"';
2349
            $result_surveys = Database::query($sql);
2350 View Code Duplication
            while ($surveys = Database::fetch_array($result_surveys)) {
2351
                $survey_id = $surveys[0];
2352
                $sql = 'DELETE FROM ' . $table_course_survey_question . ' WHERE survey_id="' . $survey_id . '"';
2353
                Database::query($sql);
2354
                $sql = 'DELETE FROM ' . $table_course_survey_question_option . ' WHERE survey_id="' . $survey_id . '"';
2355
                Database::query($sql);
2356
                $sql = 'DELETE FROM ' . $table_course_survey . ' WHERE survey_id="' . $survey_id . '"';
2357
                Database::query($sql);
2358
            }
2359
2360
            // Delete the course from the stats tables
2361
2362
            $sql = "DELETE FROM $table_stats_hotpots WHERE c_id = $courseId";
2363
            Database::query($sql);
2364
            $sql = "DELETE FROM $table_stats_attempt WHERE c_id = $courseId";
2365
            Database::query($sql);
2366
            $sql = "DELETE FROM $table_stats_exercises WHERE c_id = $courseId";
2367
            Database::query($sql);
2368
            $sql = "DELETE FROM $table_stats_access WHERE c_id = $courseId";
2369
            Database::query($sql);
2370
            $sql = "DELETE FROM $table_stats_lastaccess WHERE c_id = $courseId";
2371
            Database::query($sql);
2372
            $sql = "DELETE FROM $table_stats_course_access WHERE c_id = $courseId";
2373
            Database::query($sql);
2374
            $sql = "DELETE FROM $table_stats_online WHERE c_id = $courseId";
2375
            Database::query($sql);
2376
            // Do not delete rows from track_e_default as these include course
2377
            // creation and other important things that do not take much space
2378
            // but give information on the course history
2379
            //$sql = "DELETE FROM $table_stats_default WHERE c_id = $courseId";
2380
            //Database::query($sql);
2381
            $sql = "DELETE FROM $table_stats_downloads WHERE c_id = $courseId";
2382
            Database::query($sql);
2383
            $sql = "DELETE FROM $table_stats_links WHERE c_id = $courseId";
2384
            Database::query($sql);
2385
            $sql = "DELETE FROM $table_stats_uploads WHERE c_id = $courseId";
2386
            Database::query($sql);
2387
2388
            // Update ticket
2389
            $ticket = Database::get_main_table(TABLE_TICKET_TICKET);
2390
            $sql = "UPDATE $ticket SET course_id = NULL WHERE course_id = $courseId";
2391
            Database::query($sql);
2392
2393
            // Skills
2394
            $table = Database::get_main_table(TABLE_MAIN_SKILL_REL_USER);
2395
            $sql = "DELETE FROM $table WHERE course_id = $courseId";
2396
            Database::query($sql);
2397
2398
            // Delete the course from the database
2399
            $sql = "DELETE FROM $table_course WHERE code = '" . $codeFiltered . "'";
2400
            Database::query($sql);
2401
2402
            // delete extra course fields
2403
            $extraFieldValues = new ExtraFieldValue('course');
2404
            $extraFieldValues->deleteValuesByItem($courseId);
2405
2406
            // Add event to system log
2407
            $user_id = api_get_user_id();
2408
            Event::addEvent(
2409
                LOG_COURSE_DELETE,
2410
                LOG_COURSE_CODE,
2411
                $code,
2412
                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...
2413
                $user_id,
2414
                $courseId
2415
            );
2416
        }
2417
    }
2418
2419
    /**
2420
     * Creates a file called mysql_dump.sql in the course folder
2421
     * @param $course_code The code of the course
2422
     * @todo Implementation for single database
2423
     */
2424
    public static function create_database_dump($course_code)
2425
    {
2426
        $sql_dump = '';
2427
        $course_code = Database::escape_string($course_code);
2428
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
2429
        $sql = "SELECT * FROM $table_course WHERE code = '$course_code'";
2430
        $res = Database::query($sql);
2431
        $course = Database::fetch_array($res);
2432
2433
        $course_tables = AddCourse::get_course_tables();
2434
2435
        if (!empty($course['id'])) {
2436
            //Cleaning c_x tables
2437
            foreach ($course_tables as $table) {
2438
                $table = Database::get_course_table($table);
2439
                $sql = "SELECT * FROM $table WHERE c_id = {$course['id']} ";
2440
                $res_table = Database::query($sql);
2441
2442
                while ($row = Database::fetch_array($res_table, 'ASSOC')) {
2443
                    $row_to_save = array();
2444
                    foreach ($row as $key => $value) {
2445
                        $row_to_save[$key] = $key . "='" . Database::escape_string($row[$key]) . "'";
2446
                    }
2447
                    $sql_dump .= "\nINSERT INTO $table SET " . implode(', ', $row_to_save) . ';';
2448
                }
2449
            }
2450
        }
2451
2452
        if (is_dir(api_get_path(SYS_COURSE_PATH) . $course['directory'])) {
2453
            $file_name = api_get_path(SYS_COURSE_PATH) . $course['directory'] . '/mysql_dump.sql';
2454
            $handle = fopen($file_name, 'a+');
2455
            if ($handle !== false) {
2456
                fwrite($handle, $sql_dump);
2457
                fclose($handle);
2458
            } 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...
2459
                //TODO trigger exception in a try-catch
2460
            }
2461
        }
2462
    }
2463
2464
    /**
2465
     * Sort courses for a specific user ??
2466
     * @param   int     User ID
2467
     * @param   string  Course code
2468
     * @param integer $user_id
2469
     * @return  int     Minimum course order
2470
     * @todo Review documentation
2471
     */
2472
    public static function userCourseSort($user_id, $course_code)
2473
    {
2474
        if ($user_id != strval(intval($user_id))) {
2475
            return false;
2476
        }
2477
2478
        $course_code = Database::escape_string($course_code);
2479
        $TABLECOURSE = Database::get_main_table(TABLE_MAIN_COURSE);
2480
        $TABLECOURSUSER = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2481
2482
        $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...
2483
            0, 0);
2484
2485
        $sql = 'SELECT course.code as code, course.title as title, cu.sort as sort
2486
                FROM ' . $TABLECOURSUSER . ' as cu, ' . $TABLECOURSE . ' as course
2487
                WHERE   course.id = cu.c_id AND user_id = "' . $user_id . '" AND
2488
                        cu.relation_type<>' . COURSE_RELATION_TYPE_RRHH . ' AND
2489
                        user_course_cat = 0
2490
                ORDER BY cu.sort';
2491
        $result = Database::query($sql);
2492
2493
        $course_title_precedent = '';
2494
        $counter = 0;
2495
        $course_found = false;
2496
        $course_sort = 1;
2497
2498
        if (Database::num_rows($result) > 0) {
2499
            while ($courses = Database::fetch_array($result)) {
2500
                if ($course_title_precedent == '') {
2501
                    $course_title_precedent = $courses['title'];
2502
                }
2503
                if (api_strcasecmp($course_title_precedent, $course_title) < 0) {
2504
                    $course_found = true;
2505
                    $course_sort = $courses['sort'];
2506
                    if ($counter == 0) {
2507
                        $sql = 'UPDATE ' . $TABLECOURSUSER . '
2508
                                SET sort = sort+1
2509
                                WHERE
2510
                                    user_id= "' . $user_id . '" AND
2511
                                    relation_type<>' . COURSE_RELATION_TYPE_RRHH . '
2512
                                    AND user_course_cat="0"
2513
                                    AND sort > "' . $course_sort . '"';
2514
                        $course_sort++;
2515
                    } else {
2516
                        $sql = 'UPDATE ' . $TABLECOURSUSER . ' SET sort = sort+1
2517
                                WHERE
2518
                                    user_id= "' . $user_id . '" AND
2519
                                    relation_type<>' . COURSE_RELATION_TYPE_RRHH . ' AND
2520
                                    user_course_cat="0" AND
2521
                                    sort >= "' . $course_sort . '"';
2522
                    }
2523
                    Database::query($sql);
2524
                    break;
2525
2526
                } else {
2527
                    $course_title_precedent = $courses['title'];
2528
                }
2529
                $counter++;
2530
            }
2531
2532
            // We must register the course in the beginning of the list
2533
            if (!$course_found) {
2534
                $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...
2535
                    0, 0);
2536
                Database::query('UPDATE ' . $TABLECOURSUSER . ' SET sort = sort+1 WHERE user_id= "' . $user_id . '" AND user_course_cat="0"');
2537
            }
2538
        }
2539
        return $course_sort;
2540
    }
2541
2542
    /**
2543
     * check if course exists
2544
     * @param string $course_code
2545
     * @return integer if exists, false else
2546
     */
2547 View Code Duplication
    public static function course_exists($course_code)
2548
    {
2549
        $sql = 'SELECT 1 FROM ' . Database::get_main_table(TABLE_MAIN_COURSE) . '
2550
                WHERE code="' . Database::escape_string($course_code) . '"';
2551
2552
        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...
2553
    }
2554
2555
    /**
2556
     * Send an email to tutor after the auth-suscription of a student in your course
2557
     * @author Carlos Vargas <[email protected]>, Dokeos Latino
2558
     * @param  int $user_id the id of the user
2559
     * @param  string $courseId the course code
2560
     * @param  bool $send_to_tutor_also
2561
     * @return false|null we return the message that is displayed when the action is successful
2562
     */
2563
    public static function email_to_tutor($user_id, $courseId, $send_to_tutor_also = false)
2564
    {
2565
        if ($user_id != strval(intval($user_id))) {
2566
            return false;
2567
        }
2568
        $courseId = intval($courseId);
2569
        $information = api_get_course_info_by_id($courseId);
2570
        $course_code = $information['code'];
2571
2572
        $student = api_get_user_info($user_id);
2573
2574
        $name_course = $information['title'];
2575
        $sql = "SELECT * FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER) . " 
2576
                WHERE c_id ='" . $courseId . "'";
2577
2578
        // TODO: Ivan: This is a mistake, please, have a look at it. Intention here is diffcult to be guessed.
2579
        //if ($send_to_tutor_also = true)
2580
        // Proposed change:
2581
        if ($send_to_tutor_also) {
2582
            $sql .= " AND is_tutor=1";
2583
        } else {
2584
            $sql .= " AND status=1";
2585
        }
2586
2587
        $result = Database::query($sql);
2588
        while ($row = Database::fetch_array($result)) {
2589
            $tutor = api_get_user_info($row['user_id']);
2590
            $emailto = $tutor['email'];
2591
            $emailsubject = get_lang('NewUserInTheCourse') . ': ' . $name_course;
2592
            $emailbody = get_lang('Dear') . ': ' . api_get_person_name($tutor['firstname'], $tutor['lastname']) . "\n";
2593
            $emailbody .= get_lang('MessageNewUserInTheCourse') . ': ' . $name_course . "\n";
2594
            $emailbody .= get_lang('UserName') . ': ' . $student['username'] . "\n";
2595
            if (api_is_western_name_order()) {
2596
                $emailbody .= get_lang('FirstName') . ': ' . $student['firstname'] . "\n";
2597
                $emailbody .= get_lang('LastName') . ': ' . $student['lastname'] . "\n";
2598
            } else {
2599
                $emailbody .= get_lang('LastName') . ': ' . $student['lastname'] . "\n";
2600
                $emailbody .= get_lang('FirstName') . ': ' . $student['firstname'] . "\n";
2601
            }
2602
            $emailbody .= get_lang('Email') . ': <a href="mailto:' . $student['email'] . '">' . $student['email'] ."</a>\n\n";
2603
            $recipient_name = api_get_person_name($tutor['firstname'], $tutor['lastname'], null,
2604
                PERSON_NAME_EMAIL_ADDRESS);
2605
            $sender_name = api_get_person_name(api_get_setting('administratorName'),
2606
                api_get_setting('administratorSurname'), null, PERSON_NAME_EMAIL_ADDRESS);
2607
            $email_admin = api_get_setting('emailAdministrator');
2608
2609
            $additionalParameters = array(
2610
                'smsType' => SmsPlugin::NEW_USER_SUBSCRIBED_COURSE,
2611
                'userId' => $tutor['user_id'],
2612
                'userUsername' => $student['username'],
2613
                'courseCode' => $course_code
2614
            );
2615
            api_mail_html(
2616
                $recipient_name,
2617
                $emailto,
2618
                $emailsubject,
2619
                $emailbody,
2620
                $sender_name,
2621
                $email_admin,
2622
                null,
2623
                null,
2624
                null,
2625
                $additionalParameters
2626
            );
2627
        }
2628
    }
2629
2630
    /**
2631
     * @return array
2632
     */
2633
    public static function get_special_course_list()
2634
    {
2635
        $courseTable = Database:: get_main_table(TABLE_MAIN_COURSE);
2636
        $tbl_course_field = Database:: get_main_table(TABLE_EXTRA_FIELD);
2637
        $tbl_course_field_value = Database:: get_main_table(TABLE_EXTRA_FIELD_VALUES);
2638
2639
        //we filter the courses from the URL
2640
        $join_access_url = $where_access_url = '';
2641 View Code Duplication
        if (api_get_multiple_access_url()) {
2642
            $access_url_id = api_get_current_access_url_id();
2643
            if ($access_url_id != -1) {
2644
                $tbl_url_course = Database:: get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2645
                $join_access_url = "LEFT JOIN $tbl_url_course url_rel_course
2646
                                    ON url_rel_course.c_id = tcfv.item_id ";
2647
                $where_access_url = " AND access_url_id = $access_url_id ";
2648
            }
2649
        }
2650
2651
        $extraFieldType = EntityExtraField::COURSE_FIELD_TYPE;
2652
2653
        // get course list auto-register
2654
        $sql = "SELECT DISTINCT(c.code)
2655
                FROM $tbl_course_field_value tcfv
2656
                INNER JOIN $tbl_course_field tcf
2657
                ON tcfv.field_id =  tcf.id $join_access_url
2658
                INNER JOIN $courseTable c
2659
                ON (c.id = tcfv.item_id)
2660
                WHERE
2661
                    tcf.extra_field_type = $extraFieldType AND
2662
                    tcf.variable = 'special_course' AND
2663
                    tcfv.value = 1  $where_access_url";
2664
2665
        $result = Database::query($sql);
2666
        $courseList = array();
2667
2668
        if (Database::num_rows($result) > 0) {
2669
            while ($result_row = Database::fetch_array($result)) {
2670
                $courseList[] = $result_row['code'];
2671
            }
2672
        }
2673
2674
        return $courseList;
2675
    }
2676
2677
    /**
2678
     * Get the course codes that have been restricted in the catalogue, and if byUserId is set
2679
     * then the courses that the user is allowed or not to see in catalogue
2680
     *
2681
     * @param boolean allowed Either if the courses have some users that are or are not allowed to see in catalogue
2682
     * @param boolean byUserId if the courses are or are not allowed to see to the user
2683
     * @return array Course codes allowed or not to see in catalogue by some user or the user
2684
     */
2685
    public static function getCatalogueCourseList($allowed = true, $byUserId = -1)
2686
    {
2687
        $courseTable = Database:: get_main_table(TABLE_MAIN_COURSE);
2688
        $tblCourseRelUserCatalogue = Database:: get_main_table(TABLE_MAIN_COURSE_CATALOGUE_USER);
2689
        $visibility = ($allowed?1:0);
2690
2691
        // Restriction by user id
2692
        $currentUserRestriction = "";
2693
        if ($byUserId > 0) {
2694
            $currentUserRestriction = " AND tcruc.user_id = $byUserId ";
2695
        }
2696
2697
        //we filter the courses from the URL
2698
        $joinAccessUrl = '';
2699
        $whereAccessUrl = '';
2700 View Code Duplication
        if (api_get_multiple_access_url()) {
2701
            $accessUrlId = api_get_current_access_url_id();
2702
            if ($accessUrlId != -1) {
2703
                $tblUrlCourse = Database:: get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2704
                $joinAccessUrl = "LEFT JOIN $tblUrlCourse url_rel_course
2705
                                    ON url_rel_course.c_id = c.id ";
2706
                $whereAccessUrl = " AND access_url_id = $accessUrlId ";
2707
            }
2708
        }
2709
2710
        // get course list auto-register
2711
        $sql = "SELECT DISTINCT(c.code)
2712
                FROM $tblCourseRelUserCatalogue tcruc
2713
                INNER JOIN $courseTable c
2714
                ON (c.id = tcruc.c_id) $joinAccessUrl
2715
                WHERE tcruc.visible = $visibility $currentUserRestriction $whereAccessUrl";
2716
2717
        $result = Database::query($sql);
2718
        $courseList = array();
2719
2720
        if (Database::num_rows($result) > 0) {
2721
            while ($resultRow = Database::fetch_array($result)) {
2722
                $courseList[] = $resultRow['code'];
2723
            }
2724
        }
2725
2726
        return $courseList;
2727
    }
2728
2729
    /**
2730
     * Get list of courses for a given user
2731
     * @param int $user_id
2732
     * @param boolean $include_sessions Whether to include courses from session or not
2733
     * @param boolean $adminGetsAllCourses If the user is platform admin,
2734
     * whether he gets all the courses or just his. Note: This does *not* include all sessions
2735
     * @return array    List of codes and db name
2736
     * @author isaac flores paz
2737
     */
2738
    public static function get_courses_list_by_user_id($user_id, $include_sessions = false, $adminGetsAllCourses = false)
2739
    {
2740
        $user_id = intval($user_id);
2741
        $course_list = array();
2742
        $codes = array();
2743
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
2744
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2745
        $tbl_user_course_category = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
2746
        $special_course_list = self::get_special_course_list();
2747
2748
        if ($adminGetsAllCourses && UserManager::is_admin($user_id)) {
2749
            // get the whole courses list
2750
            $sql = "SELECT DISTINCT(course.code), course.id as real_id
2751
                    FROM $tbl_course course";
2752
        } else {
2753
2754
            $with_special_courses = $without_special_courses = '';
2755
            if (!empty($special_course_list)) {
2756
                $sc_string = '"' . implode('","', $special_course_list) . '"';
2757
                $with_special_courses = ' course.code IN (' . $sc_string . ')';
2758
                $without_special_courses = ' AND course.code NOT IN (' . $sc_string . ')';
2759
            }
2760
2761 View Code Duplication
            if (!empty($with_special_courses)) {
2762
                $sql = "SELECT DISTINCT(course.code), course.id as real_id
2763
                        FROM $tbl_course_user  course_rel_user
2764
                        LEFT JOIN $tbl_course  course
2765
                        ON course.id = course_rel_user.c_id
2766
                        LEFT JOIN $tbl_user_course_category user_course_category
2767
                        ON course_rel_user.user_course_cat = user_course_category.id
2768
                        WHERE  $with_special_courses
2769
                        GROUP BY course.code
2770
                        ORDER BY user_course_category.sort, course.title, course_rel_user.sort ASC
2771
2772
                    ";
2773
                //
2774
                $rs_special_course = Database::query($sql);
2775
                if (Database::num_rows($rs_special_course) > 0) {
2776
                    while ($result_row = Database::fetch_array($rs_special_course)) {
2777
                        $result_row['special_course'] = 1;
2778
                        $course_list[] = $result_row;
2779
                        $codes[] = $result_row['real_id'];
2780
                    }
2781
                }
2782
            }
2783
2784
            // get course list not auto-register. Use Distinct to avoid multiple
2785
            // entries when a course is assigned to a HRD (DRH) as watcher
2786
            $sql = "SELECT DISTINCT(course.code), course.id as real_id
2787
                    FROM $tbl_course course
2788
                    INNER JOIN $tbl_course_user cru ON course.id = cru.c_id
2789
                    WHERE cru.user_id='$user_id' $without_special_courses";
2790
        }
2791
        $result = Database::query($sql);
2792
2793
        if (Database::num_rows($result)) {
2794
            while ($row = Database::fetch_array($result, 'ASSOC')) {
2795
                $course_list[] = $row;
2796
                $codes[] = $row['real_id'];
2797
            }
2798
        }
2799
2800
        if ($include_sessions === true) {
2801
            $sql = "SELECT DISTINCT(c.code), c.id as real_id
2802
                    FROM " . Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER) . " s,
2803
                    " . Database::get_main_table(TABLE_MAIN_COURSE) . " c
2804
                    WHERE user_id = $user_id AND s.c_id = c.id";
2805
            $r = Database::query($sql);
2806
            while ($row = Database::fetch_array($r, 'ASSOC')) {
2807
                if (!in_array($row['real_id'], $codes)) {
2808
                    $course_list[] = $row;
2809
                }
2810
            }
2811
        }
2812
2813
        return $course_list;
2814
    }
2815
2816
    /**
2817
     * Get course ID from a given course directory name
2818
     * @param   string  Course directory (without any slash)
2819
     * @return  string  Course code, or false if not found
2820
     */
2821
    public static function get_course_id_from_path($path)
2822
    {
2823
        $path = Database::escape_string(str_replace('.', '', str_replace('/', '', $path)));
2824
        $res = Database::query("SELECT code FROM " . Database::get_main_table(TABLE_MAIN_COURSE) . "
2825
                WHERE directory LIKE BINARY '$path'");
2826
        if ($res === false) {
2827
            return false;
2828
        }
2829
        if (Database::num_rows($res) != 1) {
2830
            return false;
2831
        }
2832
        $row = Database::fetch_array($res);
2833
2834
        return $row['code'];
2835
    }
2836
2837
    /**
2838
     * Get course code(s) from visual code
2839
     * @deprecated
2840
     * @param   string  Visual code
2841
     * @return  array   List of codes for the given visual code
2842
     */
2843
    public static function get_courses_info_from_visual_code($code)
2844
    {
2845
        $result = array();
2846
        $sql_result = Database::query("SELECT * FROM " . Database::get_main_table(TABLE_MAIN_COURSE) . "
2847
                WHERE visual_code = '" . Database::escape_string($code) . "'");
2848
        while ($virtual_course = Database::fetch_array($sql_result)) {
2849
            $result[] = $virtual_course;
2850
        }
2851
        return $result;
2852
    }
2853
2854
    /**
2855
     * Get emails of tutors to course
2856
     * @param string Visual code
2857
     * @param integer $courseId
2858
     * @return array List of emails of tutors to course
2859
     * @author @author Carlos Vargas <[email protected]>, Dokeos Latino
2860
     * */
2861
    public static function get_emails_of_tutors_to_course($courseId)
2862
    {
2863
        $list = array();
2864
        $res = Database::query("SELECT user_id FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER) . "
2865
                WHERE c_id ='" . intval($courseId) . "' AND status=1");
2866
        while ($list_users = Database::fetch_array($res)) {
2867
            $result = Database::query("SELECT * FROM " . Database::get_main_table(TABLE_MAIN_USER) . "
2868
                    WHERE user_id=" . $list_users['user_id']);
2869 View Code Duplication
            while ($row_user = Database::fetch_array($result)) {
2870
                $name_teacher = api_get_person_name($row_user['firstname'], $row_user['lastname']);
2871
                $list[] = array($row_user['email'] => $name_teacher);
2872
            }
2873
        }
2874
        return $list;
2875
    }
2876
2877
    /**
2878
     * Get coaches emails by session
2879
     * @param int session id
2880
     * @param int $courseId
2881
     * @param integer $session_id
2882
     * @return array  array(email => name_tutor)  by coach
2883
     * @author Carlos Vargas <[email protected]>
2884
     */
2885
    public static function get_email_of_tutor_to_session($session_id, $courseId)
2886
    {
2887
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2888
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
2889
        $coachs_emails = array();
2890
2891
        $courseId = intval($courseId);
2892
        $session_id = intval($session_id);
2893
2894
        $sql = "SELECT user_id
2895
                FROM $tbl_session_course_user
2896
                WHERE
2897
                    session_id = '$session_id' AND
2898
                    c_id = '$courseId' AND
2899
                    status = 2
2900
                ";
2901
        $rs = Database::query($sql);
2902
2903
        if (Database::num_rows($rs) > 0) {
2904
2905
            $user_ids = array();
2906
            while ($row = Database::fetch_array($rs)) {
2907
                $user_ids[] = $row['user_id'];
2908
            }
2909
2910
            $sql = "SELECT firstname, lastname, email FROM $tbl_user
2911
                    WHERE user_id IN (" . implode(",", $user_ids) . ")";
2912
            $rs_user = Database::query($sql);
2913
2914
            while ($row_emails = Database::fetch_array($rs_user)) {
2915
                $mail_tutor = array(
2916
                    'email' => $row_emails['email'],
2917
                    'complete_name' => api_get_person_name($row_emails['firstname'], $row_emails['lastname'])
2918
                );
2919
                $coachs_emails[] = $mail_tutor;
2920
            }
2921
        }
2922
        return $coachs_emails;
2923
    }
2924
2925
    /**
2926
     * Creates a new extra field for a given course
2927
     * @param    string    Field's internal variable name
2928
     * @param    int        Field's type
2929
     * @param    string    Field's language var name
2930
     * @param integer $fieldType
2931
     * @param string $default
2932
     * @return boolean     new extra field id
2933
     */
2934
    public static function create_course_extra_field($variable, $fieldType, $displayText, $default)
2935
    {
2936
        $extraField = new ExtraField('course');
2937
        $params = [
2938
            'variable' => $variable,
2939
            'field_type' => $fieldType,
2940
            'display_text' => $displayText,
2941
            'default_value' => $default
2942
        ];
2943
2944
        return $extraField->save($params);
2945
    }
2946
2947
    /**
2948
     * Updates course attribute. Note that you need to check that your
2949
     * attribute is valid before you use this function
2950
     *
2951
     * @param int Course id
2952
     * @param string Attribute name
2953
     * @param string Attribute value
2954
     * @return Doctrine\DBAL\Driver\Statement|null True if attribute was successfully updated,
2955
     * false if course was not found or attribute name is invalid
2956
     */
2957
    public static function update_attribute($id, $name, $value)
2958
    {
2959
        $id = (int)$id;
2960
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
2961
        $sql = "UPDATE $table SET $name = '" . Database::escape_string($value) . "'
2962
                WHERE id = '$id'";
2963
2964
        return Database::query($sql);
2965
    }
2966
2967
    /**
2968
     * Update course attributes. Will only update attributes with a non-empty value.
2969
     * Note that you NEED to check that your attributes are valid before using this function
2970
     *
2971
     * @param int Course id
2972
     * @param array Associative array with field names as keys and field values as values
2973
     * @return Doctrine\DBAL\Driver\Statement|null True if update was successful, false otherwise
2974
     */
2975
    public static function update_attributes($id, $attributes)
2976
    {
2977
        $id = (int)$id;
2978
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
2979
        $sql = "UPDATE $table SET ";
2980
        $i = 0;
2981
        foreach ($attributes as $name => $value) {
2982
            if ($value != '') {
2983
                if ($i > 0) {
2984
                    $sql .= ", ";
2985
                }
2986
                $sql .= " $name = '" . Database::escape_string($value) . "'";
2987
                $i++;
2988
            }
2989
        }
2990
        $sql .= " WHERE id = '$id'";
2991
2992
        return Database::query($sql);
2993
    }
2994
2995
    /**
2996
     * Update an extra field value for a given course
2997
     * @param    integer    Course ID
2998
     * @param    string    Field variable name
2999
     * @param    string    Field value
3000
     * @return    boolean|null    true if field updated, false otherwise
3001
     */
3002
    public static function update_course_extra_field_value($course_code, $variable, $value = '')
3003
    {
3004
        $courseInfo = api_get_course_info($course_code);
3005
        $courseId = $courseInfo['real_id'];
3006
3007
        $extraFieldValues = new ExtraFieldValue('course');
3008
        $params = [
3009
            'item_id' => $courseId,
3010
            'variable' => $variable,
3011
            'value' => $value
3012
        ];
3013
3014
        return $extraFieldValues->save($params);
3015
    }
3016
3017
    /**
3018
     * @param int $session_id
3019
     * @return mixed
3020
     */
3021
    public static function get_session_category_id_by_session_id($session_id)
3022
    {
3023
        return Database::result(
3024
            Database::query('SELECT  sc.id session_category
0 ignored issues
show
Bug introduced by
It seems like \Database::query('SELECT...ing($session_id) . '"') 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...
3025
                FROM ' . Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY) . ' sc
3026
                INNER JOIN ' . Database::get_main_table(TABLE_MAIN_SESSION) . ' s
3027
                ON sc.id=s.session_category_id WHERE s.id="' . Database::escape_string($session_id) . '"'),
3028
            0,
3029
            'session_category'
3030
        );
3031
    }
3032
3033
    /**
3034
     * Gets the value of a course extra field. Returns null if it was not found
3035
     *
3036
     * @param string Name of the extra field
3037
     * @param string Course code
3038
     *
3039
     * @return string Value
3040
     */
3041
    public static function get_course_extra_field_value($variable, $code)
3042
    {
3043
        $courseInfo = api_get_course_info($code);
3044
        $courseId = $courseInfo['real_id'];
3045
3046
        $extraFieldValues = new ExtraFieldValue('course');
3047
        $result = $extraFieldValues->get_values_by_handler_and_field_variable($courseId, $variable);
3048
        if (!empty($result['value'])) {
3049
            return $result['value'];
3050
        }
3051
3052
        return null;
3053
    }
3054
3055
    /**
3056
     * Lists details of the course description
3057
     * @param array        The course description
3058
     * @param string    The encoding
3059
     * @param bool        If true is displayed if false is hidden
3060
     * @return string     The course description in html
3061
     */
3062
    public static function get_details_course_description_html($descriptions, $charset, $action_show = true)
3063
    {
3064
        $data = null;
3065
        if (isset($descriptions) && count($descriptions) > 0) {
3066
            foreach ($descriptions as $description) {
3067
                $data .= '<div class="sectiontitle">';
3068
                if (api_is_allowed_to_edit() && $action_show) {
3069
                    //delete
3070
                    $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'),
3071
                                ENT_QUOTES, $charset)) . '\')) return false;">';
3072
                    $data .= Display::return_icon('delete.gif', get_lang('Delete'),
3073
                        array('style' => 'vertical-align:middle;float:right;'));
3074
                    $data .= '</a> ';
3075
                    //edit
3076
                    $data .= '<a href="' . api_get_self() . '?' . api_get_cidreq() . '&description_id=' . $description->id . '">';
3077
                    $data .= Display::return_icon('edit.png', get_lang('Edit'),
3078
                        array('style' => 'vertical-align:middle;float:right; padding-right:4px;'), ICON_SIZE_SMALL);
3079
                    $data .= '</a> ';
3080
                }
3081
                $data .= $description->title;
3082
                $data .= '</div>';
3083
                $data .= '<div class="sectioncomment">';
3084
                $data .= $description->content;
3085
                $data .= '</div>';
3086
            }
3087
        } else {
3088
            $data .= '<em>' . get_lang('ThisCourseDescriptionIsEmpty') . '</em>';
3089
        }
3090
3091
        return $data;
3092
    }
3093
3094
    /**
3095
     * Returns the details of a course category
3096
     *
3097
     * @param string Category code
3098
     * @return array Course category
3099
     */
3100
    public static function get_course_category($code)
3101
    {
3102
        $table_categories = Database::get_main_table(TABLE_MAIN_CATEGORY);
3103
        $sql = "SELECT * FROM $table_categories WHERE code = '$code';";
3104
        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...
3105
    }
3106
3107
    /**
3108
     * Returns the details of a course category
3109
     *
3110
     * @param string Category code
3111
     * @return array Course category
3112
     */
3113
    public static function getCategoriesList()
3114
    {
3115
        $table_categories = Database::get_main_table(TABLE_MAIN_CATEGORY);
3116
        $sql = "SELECT * FROM $table_categories";
3117
        $result = Database::query($sql);
3118
        $category = array();
3119 View Code Duplication
        while ($row = Database::fetch_array($result, 'ASSOC')) {
3120
            $category[$row['code']] = $row['name'];
3121
        }
3122
        return $category;
3123
    }
3124
3125
    /**
3126
     *  Get count rows of a table inside a course database
3127
     * @param  string $table   The table of which the rows should be counted
3128
     * @param  int $session_id       optionally count rows by session id
3129
     * @return int $course_id    The number of rows in the given table.
3130
     * @deprecated
3131
     */
3132
    public static function count_rows_course_table($table, $session_id = '', $course_id = null)
3133
    {
3134
        $condition_session = '';
3135
        if ($session_id !== '') {
3136
            $session_id = intval($session_id);
3137
            $condition_session = " AND session_id = '$session_id' ";
3138
        }
3139
        if (!empty($course_id)) {
3140
            $course_id = intval($course_id);
3141
        } else {
3142
            $course_id = api_get_course_int_id();
3143
        }
3144
        $condition_session .= " AND c_id = '$course_id' ";
3145
3146
        $sql = "SELECT COUNT(*) AS n FROM $table WHERE 1=1 $condition_session ";
3147
        $rs = Database::query($sql);
3148
        $row = Database::fetch_row($rs);
3149
        return $row[0];
3150
    }
3151
3152
    /**
3153
     * Subscribes courses to human resource manager (Dashboard feature)
3154
     * @param    int   $hr_manager_id      Human Resource Manager id
3155
     * @param    array $courses_list       Courses code
3156
     * @return int
3157
     **/
3158
    public static function subscribeCoursesToDrhManager($hr_manager_id, $courses_list)
3159
    {
3160
        $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
3161
        $tbl_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
3162
3163
        $hr_manager_id = intval($hr_manager_id);
3164
        $affected_rows = 0;
3165
3166
        //Deleting assigned courses to hrm_id
3167
        if (api_is_multiple_url_enabled()) {
3168
            $sql = "SELECT s.c_id FROM $tbl_course_rel_user s
3169
                    INNER JOIN $tbl_course_rel_access_url a
3170
                    ON (a.c_id = s.c_id)
3171
                    WHERE
3172
                        user_id = $hr_manager_id AND
3173
                        relation_type=" . COURSE_RELATION_TYPE_RRHH . " AND
3174
                        access_url_id = " . api_get_current_access_url_id() . "";
3175
        } else {
3176
            $sql = "SELECT c_id FROM $tbl_course_rel_user
3177
                    WHERE user_id = $hr_manager_id AND relation_type=" . COURSE_RELATION_TYPE_RRHH . " ";
3178
        }
3179
        $result = Database::query($sql);
3180 View Code Duplication
        if (Database::num_rows($result) > 0) {
3181
            while ($row = Database::fetch_array($result)) {
3182
                $sql = "DELETE FROM $tbl_course_rel_user
3183
                        WHERE
3184
                            c_id = '{$row['c_id']}' AND
3185
                            user_id = $hr_manager_id AND
3186
                            relation_type=" . COURSE_RELATION_TYPE_RRHH . " ";
3187
                Database::query($sql);
3188
            }
3189
        }
3190
3191
        // inserting new courses list
3192
        if (is_array($courses_list)) {
3193
            foreach ($courses_list as $course_code) {
3194
                $courseInfo = api_get_course_info($course_code);
3195
                $courseId = $courseInfo['real_id'];
3196
                $sql = "INSERT IGNORE INTO $tbl_course_rel_user(c_id, user_id, status, relation_type)
3197
                        VALUES($courseId, $hr_manager_id, '" . DRH . "', '" . COURSE_RELATION_TYPE_RRHH . "')";
3198
                $result = Database::query($sql);
3199
                if (Database::affected_rows($result)) {
3200
                    $affected_rows++;
3201
                }
3202
            }
3203
        }
3204
3205
        return $affected_rows;
3206
    }
3207
3208
    /**
3209
     * get courses followed by human resources manager
3210
     * @param int $user_id
3211
     * @param int $from
3212
     * @param int $limit
3213
     * @param string $column
3214
     * @param string $direction
3215
     * @return array    courses
3216
     */
3217
    public static function get_courses_followed_by_drh(
3218
        $user_id,
3219
        $status = DRH,
3220
        $from = null,
3221
        $limit = null,
3222
        $column = null,
3223
        $direction = null,
3224
        $getCount = false
3225
    ) {
3226
        return self::getCoursesFollowedByUser(
3227
            $user_id,
3228
            $status,
3229
            $from,
3230
            $limit,
3231
            $column,
3232
            $direction,
3233
            $getCount
3234
        );
3235
    }
3236
3237
    /**
3238
     * get courses followed by user
3239
     * @param   int $user_id
3240
     * @param   int $status
3241
     * @param   int $from
3242
     * @param   int $limit
3243
     * @param   string $column
3244
     * @param   string $direction
3245
     * @param   boolean $getCount
3246
     * @param   string $keyword
3247
     * @param   int $sessionId
3248
     * @param   boolean $showAllAssignedCourses
3249
     * @return  array   courses
3250
     */
3251
    public static function getCoursesFollowedByUser(
3252
        $user_id,
3253
        $status = null,
3254
        $from = null,
3255
        $limit = null,
3256
        $column = null,
3257
        $direction = null,
3258
        $getCount = false,
3259
        $keyword = null,
3260
        $sessionId = null,
3261
        $showAllAssignedCourses = false
3262
    ) {
3263
        // Database Table Definitions
3264
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
3265
        $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
3266
        $tbl_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
3267
        $sessionId = intval($sessionId);
3268
        $user_id = intval($user_id);
3269
        $select = "SELECT DISTINCT *, c.id as real_id ";
3270
3271
        if ($getCount) {
3272
            $select = "SELECT COUNT(DISTINCT c.id) as count";
3273
        }
3274
3275
        $whereConditions = null;
3276
        switch ($status) {
3277
            case COURSEMANAGER:
3278
                $whereConditions .= " AND cru.user_id = '$user_id'";
3279
                if (!$showAllAssignedCourses) {
3280
                    $whereConditions .= " AND status = " . COURSEMANAGER;
3281
                } else {
3282
                    $whereConditions .= " AND relation_type = " . COURSE_RELATION_TYPE_COURSE_MANAGER;
3283
                }
3284
                break;
3285
            case DRH:
3286
                $whereConditions .= " AND
3287
                    cru.user_id = '$user_id' AND
3288
                    status = " . DRH . " AND
3289
                    relation_type = '" . COURSE_RELATION_TYPE_RRHH . "'
3290
                ";
3291
                break;
3292
        }
3293
3294
        $keywordCondition = null;
3295
        if (!empty($keyword)) {
3296
            $keyword = Database::escape_string($keyword);
3297
            $keywordCondition = " AND (c.code LIKE '%$keyword%' OR c.title LIKE '%$keyword%' ) ";
3298
        }
3299
3300
        $orderBy = null;
3301
        $extraInnerJoin = null;
3302
3303
        if (!empty($sessionId)) {
3304
            if (!empty($sessionId)) {
3305
                $courseList = SessionManager::get_course_list_by_session_id(
3306
                    $sessionId
3307
                );
3308
                if (!empty($courseList)) {
3309
                    $courseListToString = implode("','", array_keys($courseList));
3310
                    $whereConditions .= " AND c.id IN ('" . $courseListToString . "')";
3311
                }
3312
                $tableSessionRelCourse = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
3313
                $orderBy = ' ORDER BY position';
3314
                $extraInnerJoin = " INNER JOIN $tableSessionRelCourse src
3315
                                    ON (c.id = src.c_id AND session_id = $sessionId) ";
3316
            }
3317
        }
3318
3319
        $whereConditions .= $keywordCondition;
3320
        $sql = "$select
3321
                FROM $tbl_course c
3322
                    INNER JOIN $tbl_course_rel_user cru ON (cru.c_id = c.id)
3323
                    INNER JOIN $tbl_course_rel_access_url a ON (a.c_id = c.id)
3324
                    $extraInnerJoin
3325
                WHERE
3326
                    access_url_id = " . api_get_current_access_url_id() . "
3327
                    $whereConditions
3328
                $orderBy
3329
                ";
3330 View Code Duplication
        if (isset($from) && isset($limit)) {
3331
            $from = intval($from);
3332
            $limit = intval($limit);
3333
            $sql .= " LIMIT $from, $limit";
3334
        }
3335
3336
        $result = Database::query($sql);
3337
3338
        if ($getCount) {
3339
            $row = Database::fetch_array($result);
3340
            return $row['count'];
3341
        }
3342
3343
        $courses = array();
3344
        if (Database::num_rows($result) > 0) {
3345
            while ($row = Database::fetch_array($result)) {
3346
                $courses[$row['code']] = $row;
3347
            }
3348
        }
3349
        return $courses;
3350
    }
3351
3352
    /**
3353
     * check if a course is special (autoregister)
3354
     * @param int $courseId
3355
     * @return bool
3356
     */
3357
    public static function isSpecialCourse($courseId)
3358
    {
3359
        $extraFieldValue = new ExtraFieldValue('course');
3360
        $result = $extraFieldValue->get_values_by_handler_and_field_variable(
3361
            $courseId,
3362
            'special_course'
3363
        );
3364
3365
        if (!empty($result)) {
3366
            if ($result['value'] == 1) {
3367
                return true;
3368
            }
3369
        }
3370
3371
        return false;
3372
    }
3373
3374
    /**
3375
     * Update course picture
3376
     * @param   string  Course code
3377
     * @param   string  File name
3378
     * @param   string  The full system name of the image from which course picture will be created.
3379
     * @param   string $cropParameters Optional string that contents "x,y,width,height" of a cropped image format
3380
     * @return  bool    Returns the resulting. In case of internal error or negative validation returns FALSE.
3381
     */
3382
    public static function update_course_picture($course_code, $filename, $source_file = null, $cropParameters = null)
3383
    {
3384
        $course_info = api_get_course_info($course_code);
3385
        // course path
3386
        $store_path = api_get_path(SYS_COURSE_PATH) . $course_info['path'];
3387
        // image name for courses
3388
        $course_image = $store_path . '/course-pic.png';
3389
        $course_medium_image = $store_path . '/course-pic85x85.png';
3390
3391
        if (file_exists($course_image)) {
3392
            unlink($course_image);
3393
        }
3394
        if (file_exists($course_medium_image)) {
3395
            unlink($course_medium_image);
3396
        }
3397
3398
        //Crop the image to adjust 4:3 ratio
3399
        $image = new Image($source_file);
3400
        $image->crop($cropParameters);
3401
3402
        //Resize the images in two formats
3403
        $medium = new Image($source_file);
3404
        $medium->resize(85);
3405
        $medium->send_image($course_medium_image, -1, 'png');
3406
        $normal = new Image($source_file);
3407
        $normal->resize(400);
3408
        $normal->send_image($course_image, -1, 'png');
3409
3410
        $result = $medium && $normal;
3411
3412
        return $result ? $result : false;
3413
    }
3414
3415
    /**
3416
     * Deletes the course picture
3417
     * @param string $courseCode
3418
     */
3419
    public static function deleteCoursePicture($courseCode)
3420
    {
3421
        $course_info = api_get_course_info($courseCode);
3422
        // course path
3423
        $storePath = api_get_path(SYS_COURSE_PATH) . $course_info['path'];
3424
        // image name for courses
3425
        $courseImage = $storePath . '/course-pic.png';
3426
        $courseMediumImage = $storePath . '/course-pic85x85.png';
3427
        $courseSmallImage = $storePath . '/course-pic32.png';
3428
3429
        if (file_exists($courseImage)) {
3430
            unlink($courseImage);
3431
        }
3432
        if (file_exists($courseMediumImage)) {
3433
            unlink($courseMediumImage);
3434
        }
3435
        if (file_exists($courseSmallImage)) {
3436
            unlink($courseSmallImage);
3437
        }
3438
    }
3439
3440
    /**
3441
     * Builds the course block in user_portal.php
3442
     * @todo use Twig
3443
     *
3444
     * @param array $params
3445
     * @return string
3446
     */
3447
    public static function course_item_html_no_icon($params)
3448
    {
3449
        $html = '<div class="course_item">';
3450
        $html .= '<div class="row">';
3451
        $html .= '<div class="col-md-7">';
3452
3453
        $notifications = isset($params['notifications']) ? $params['notifications'] : null;
3454
3455
        $html .= '<h3>' . $params['title'] . $notifications . '</h3> ';
3456
3457
        if (isset($params['description'])) {
3458
            $html .= '<p>' . $params['description'] . '</p>';
3459
        }
3460
        if (!empty($params['subtitle'])) {
3461
            $html .= '<small>' . $params['subtitle'] . '</small>';
3462
        }
3463
        if (!empty($params['teachers'])) {
3464
            $html .= '<h5 class="teacher">' . Display::return_icon('teacher.png', get_lang('Teacher'), array(),
3465
                    ICON_SIZE_TINY) . $params['teachers'] . '</h5>';
3466
        }
3467
        if (!empty($params['coaches'])) {
3468
            $html .= '<h5 class="teacher">' . Display::return_icon('teacher.png', get_lang('Coach'), array(),
3469
                    ICON_SIZE_TINY) . $params['coaches'] . '</h5>';
3470
        }
3471
3472
        $html .= '</div>';
3473
        $params['right_actions'] = isset($params['right_actions']) ? $params['right_actions'] : null;
3474
        $html .= '<div class="pull-right course-box-actions">' . $params['right_actions'] . '</div>';
3475
        $html .= '</div>';
3476
        $html .= '</div>';
3477
        return $html;
3478
    }
3479
3480
    /**
3481
     * @param $params
3482
     * @param bool|false $is_sub_content
3483
     * @return string
3484
     */
3485
    public static function session_items_html($params, $is_sub_content = false)
3486
    {
3487
        $html = '';
3488
        $html .= '<div class="row">';
3489
        $html .= '<div class="col-md-2">';
3490
        if (!empty($params['link'])){
3491
            $html .= '<a class="thumbnail" href="'.$params['link'].'">';
3492
            $html .= $params['icon'];
3493
            $html .= '</a>';
3494
        }else{
3495
            $html .= $params['icon'];
3496
        }
3497
        $html .= '</div>';
3498
        $html .= '<div class="col-md-10">';
3499
        $html .= $params['title'];
3500
        $html .= $params['coaches'];
3501
        $html .= '</div>';
3502
        $html .= '</div>';
3503
3504
        return $html;
3505
    }
3506
3507
    /**
3508
     * Display special courses (and only these) as several HTML divs of class userportal-course-item
3509
     *
3510
     * Special courses are courses that stick on top of the list and are "auto-registerable"
3511
     * in the sense that any user clicking them is registered as a student
3512
     * @param int       User id
3513
     * @param bool      Whether to show the document quick-loader or not
3514
     * @return string
3515
     */
3516
    public static function returnSpecialCourses($user_id, $load_dirs = false)
3517
    {
3518
        $user_id = intval($user_id);
3519
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
3520
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
3521
3522
        $special_course_list = self::get_special_course_list();
3523
3524
        $with_special_courses = '';
3525
        if (!empty($special_course_list)) {
3526
            $with_special_courses = ' course.code IN ("' . implode('","', $special_course_list) . '")';
3527
        }
3528
3529
        $courseList = [];
3530
        if (!empty($with_special_courses)) {
3531
            $sql = "SELECT
3532
                        course.id,
3533
                        course.code,
3534
                        course.subscribe subscr,
3535
                        course.unsubscribe unsubscr,
3536
                        course_rel_user.status status,
3537
                        course_rel_user.sort sort,
3538
                        course_rel_user.user_course_cat user_course_cat,
3539
                        course_rel_user.user_id
3540
                    FROM $tbl_course course
3541
                    LEFT JOIN $tbl_course_user course_rel_user
3542
                    ON course.id = course_rel_user.c_id AND course_rel_user.user_id = '$user_id'
3543
                    WHERE $with_special_courses group by course.code";
3544
3545
            $rs_special_course = Database::query($sql);
3546
            $number_of_courses = Database::num_rows($rs_special_course);
3547
            $showCustomIcon = api_get_setting('course_images_in_courses_list');
3548
3549
            if ($number_of_courses > 0) {
3550
                while ($course = Database::fetch_array($rs_special_course)) {
3551
                    $course_info = api_get_course_info($course['code']);
3552
                    if ($course_info['visibility'] == COURSE_VISIBILITY_HIDDEN) {
3553
                        continue;
3554
                    }
3555
3556
                    $params = [];
3557
                    // Get notifications.
3558
                    $course_info['id_session'] = null;
3559
                    $course_info['status'] = $course['status'];
3560
                    $show_notification = Display::show_notification($course_info);
3561
3562
                    if (empty($course['user_id'])) {
3563
                        $course['status'] = STUDENT;
3564
                    }
3565
3566
                    $params['edit_actions'] = '';
3567
                    $params['document'] = '';
3568
                    if (api_is_platform_admin()) {
3569
                        $params['edit_actions'] .= api_get_path(WEB_CODE_PATH) . 'course_info/infocours.php?cidReq=' . $course['code'];
3570
                        if ($load_dirs) {
3571
                            $params['document'] = '<a id="document_preview_' . $course_info['real_id'] . '_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3572
                               . Display::returnFontAwesomeIcon('folder-open') . '</a>';
3573
                            $params['document'] .= Display::div('', ['id' => 'document_result_' . $course_info['real_id'] . '_0', 'class' => 'document_preview_container']);
3574
                        }
3575
                    }else{
3576
                        if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED && $load_dirs) {
3577
                            $params['document'] = '<a id="document_preview_' . $course_info['real_id'] . '_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3578
                               . Display::returnFontAwesomeIcon('folder-open') . '</a>';
3579
                            $params['document'] .= Display::div('', ['id' => 'document_result_' . $course_info['real_id'] . '_0', 'class' => 'document_preview_container']);
3580
                        }
3581
                    }
3582
3583
                    $params['visibility'] = $course_info['visibility'];
3584
                    $params['status'] = $course_info['status'];
3585
                    $params['category'] = $course_info['categoryName'];
3586
                    $params['icon'] = Display::return_icon('drawing-pin.png',null, null, ICON_SIZE_LARGE, null);
3587
3588 View Code Duplication
                    if (api_get_setting('display_coursecode_in_courselist') == 'true') {
3589
                        $params['code_course']  = '(' . $course_info['visual_code'] . ')';
3590
                    }
3591
3592
                    $params['title'] = $course_info['title'];
3593
                    $params['link'] = $course_info['course_public_url'].'?id_session=0&autoreg=1';
3594
                    if (api_get_setting('display_teacher_in_courselist') === 'true') {
3595
                        $params['teachers'] = CourseManager::getTeachersFromCourseByCode($course['code']);
3596
                    }
3597
3598
                    if ($showCustomIcon === 'true') {
3599
                        $params['thumbnails'] = $course_info['course_image'];
3600
                        $params['image'] = $course_info['course_image_large'];
3601
                    }
3602
3603
                    if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
3604
                        $params['notifications'] = $show_notification;
3605
                    }
3606
3607
                    $params['is_special_course'] = true;
3608
3609
                    $courseList[] = $params;
3610
3611
                }
3612
            }
3613
        }
3614
3615
    return $courseList;
3616
}
3617
3618
    /**
3619
     * Display courses (without special courses) as several HTML divs
3620
     * of course categories, as class userportal-catalog-item.
3621
     * @uses displayCoursesInCategory() to display the courses themselves
3622
     * @param int        user id
3623
     * @param bool      Whether to show the document quick-loader or not
3624
     * @param integer $user_id
3625
     * @return string
3626
     */
3627
    public static function returnCourses($user_id, $load_dirs = false)
3628
    {
3629
        $user_id = intval($user_id);
3630
        if (empty($user_id)) {
3631
            $user_id = api_get_user_id();
3632
        }
3633
        // Step 1: We get all the categories of the user
3634
        $table = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
3635
        $sql = "SELECT id, title FROM $table
3636
                WHERE user_id = '" . $user_id . "'
3637
                ORDER BY sort ASC";
3638
        $result = Database::query($sql);
3639
        $listItems = [
3640
            'in_category' => [],
3641
            'not_category' => []
3642
        ];
3643
3644
        while ($row = Database::fetch_array($result)) {
3645
            // We simply display the title of the category.
3646
            $courseInCategory = self:: returnCoursesCategories(
3647
                $row['id'],
3648
                $load_dirs
3649
            );
3650
3651
            $params = [
3652
                'id_category' => $row ['id'],
3653
                'title_category' => $row['title'],
3654
                'courses' => $courseInCategory
3655
            ];
3656
            $listItems['in_category'][] = $params;
3657
        }
3658
3659
        // Step 2: We display the course without a user category.
3660
        $coursesNotCategory = self::returnCoursesWithoutCategories(0, $load_dirs);
3661
        if ($coursesNotCategory) {
3662
            $listItems['not_category'] = $coursesNotCategory;
3663
        }
3664
3665
        return $listItems;
3666
    }
3667
3668
    /**
3669
     *  Display courses inside a category (without special courses) as HTML dics of
3670
     *  class userportal-course-item.
3671
     * @param int      User category id
3672
     * @param bool      Whether to show the document quick-loader or not
3673
     * @return string
3674
     */
3675
    public static function returnCoursesCategories($user_category_id, $load_dirs = false)
3676
    {
3677
        $user_id = api_get_user_id();
3678
        // Table definitions
3679
        $TABLECOURS = Database:: get_main_table(TABLE_MAIN_COURSE);
3680
        $TABLECOURSUSER = Database:: get_main_table(TABLE_MAIN_COURSE_USER);
3681
        $TABLE_ACCESS_URL_REL_COURSE = Database:: get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
3682
        $current_url_id = api_get_current_access_url_id();
3683
3684
        // Get course list auto-register
3685
        $special_course_list = self::get_special_course_list();
3686
3687
        $without_special_courses = '';
3688
        if (!empty($special_course_list)) {
3689
            $without_special_courses = ' AND course.code NOT IN ("' . implode('","', $special_course_list) . '")';
3690
        }
3691
3692
        //AND course_rel_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
3693
        $sql = "SELECT
3694
                course.id,
3695
                course.title,
3696
                course.code,
3697
                course.subscribe subscr,
3698
                course.unsubscribe unsubscr,
3699
                course_rel_user.status status,
3700
                course_rel_user.sort sort,
3701
                course_rel_user.user_course_cat user_course_cat
3702
                FROM $TABLECOURS course,
3703
                     $TABLECOURSUSER course_rel_user,
3704
                     $TABLE_ACCESS_URL_REL_COURSE url
3705
                WHERE
3706
                    course.id = course_rel_user.c_id AND
3707
                    url.c_id = course.id AND
3708
                    course_rel_user.user_id = '" . $user_id . "' AND
3709
                    course_rel_user.user_course_cat = '" . $user_category_id . "'
3710
                    $without_special_courses ";
3711
3712
        // If multiple URL access mode is enabled, only fetch courses
3713
        // corresponding to the current URL.
3714
        if (api_get_multiple_access_url() && $current_url_id != -1) {
3715
            $sql .= " AND url.c_id = course.id AND access_url_id='" . $current_url_id . "'";
3716
        }
3717
        // Use user's classification for courses (if any).
3718
        $sql .= " ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
3719
3720
        $result = Database::query($sql);
3721
3722
        $courseList = array();
3723
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
3724
        // Browse through all courses.
3725
        while ($course = Database::fetch_array($result)) {
3726
            $course_info = api_get_course_info($course['code']);
3727
            if (isset($course_info['visibility']) &&
3728
                $course_info['visibility'] == COURSE_VISIBILITY_HIDDEN
3729
            ) {
3730
                continue;
3731
            }
3732
            $course_info['id_session'] = null;
3733
            $course_info['status'] = $course['status'];
3734
3735
            // For each course, get if there is any notification icon to show
3736
            // (something that would have changed since the user's last visit).
3737
            $showNotification = Display::show_notification($course_info);
3738
            $iconName = basename($course_info['course_image']);
3739
3740
            if ($showCustomIcon === 'true' && $iconName != 'course.png') {
3741
                $params['thumbnails'] = $course_info['course_image'];
3742
                $params['image'] = $course_info['course_image_large'];
3743
            }
3744
3745
            $params = array();
3746
3747
            $thumbnails = null;
3748
            $image = null;
3749
3750 View Code Duplication
            if ($showCustomIcon === 'true' && $iconName != 'course.png') {
3751
                $thumbnails = $course_info['course_image'];
3752
                $image = $course_info['course_image_large'];
3753
            }else{
3754
                $image = Display::return_icon('session_default.png', null, null, null,null, true);
3755
            }
3756
3757
            $params['course_id'] = $course['id'];
3758
            $params['edit_actions'] = '';
3759
            $params['document'] = '';
3760 View Code Duplication
            if (api_is_platform_admin()) {
3761
                $params['edit_actions'] .= api_get_path(WEB_CODE_PATH) . 'course_info/infocours.php?cidReq=' . $course['code'];
3762
                if($load_dirs){
3763
                    $params['document'] = '<a id="document_preview_' . $course_info['real_id'] . '_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3764
                               . Display::returnFontAwesomeIcon('folder-open') . '</a>';
3765
                    $params['document'] .= Display::div('', array('id' => 'document_result_' . $course_info['real_id'] . '_0', 'class' => 'document_preview_container'));
3766
                }
3767
            }
3768
            if ($load_dirs) {
3769
                $params['document'] = '<a id="document_preview_' . $course_info['real_id'] . '_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3770
                    . Display::returnFontAwesomeIcon('folder-open') . '</a>';
3771
                $params['document'] .= Display::div('', array('id' => 'document_result_' . $course_info['real_id'] . '_0', 'class' => 'document_preview_container'));
3772
            }
3773
3774
            $courseUrl = api_get_path(WEB_COURSE_PATH) . $course_info['path'] . '/index.php?id_session=0';
3775
3776
            if (api_get_setting('display_teacher_in_courselist') === 'true') {
3777
                $teachers = CourseManager::getTeachersFromCourseByCode($course['code']);
3778
            }
3779
3780
            $params['status'] = $course['status'];
3781
3782 View Code Duplication
            if (api_get_setting('display_coursecode_in_courselist') == 'true') {
3783
                $params['code_course'] = '(' . $course_info['visual_code'] . ') ';
3784
            }
3785
3786
            $params['visibility'] = $course_info['visibility'];
3787
            $params['link'] = $courseUrl;
3788
            $params['thumbnails'] = $thumbnails;
3789
            $params['image'] = $image;
3790
            $params['title'] = $course_info['title'];
3791
            $params['category'] = $course_info['categoryName'];
3792
            $params['teachers'] = $teachers;
3793
3794
            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
3795
                $params['notifications'] = $showNotification;
3796
            }
3797
3798
            $courseList[] = $params;
3799
        }
3800
3801
        return $courseList;
3802
    }
3803
3804
    /**
3805
     *  Display courses inside a category (without special courses) as HTML dics of
3806
     *  class userportal-course-item.
3807
     * @param int      User category id
3808
     * @param bool      Whether to show the document quick-loader or not
3809
     * @return string
3810
     */
3811
    public static function returnCoursesWithoutCategories($user_category_id, $load_dirs = false)
3812
    {
3813
        $user_id = api_get_user_id();
3814
        // Table definitions
3815
        $TABLECOURS = Database:: get_main_table(TABLE_MAIN_COURSE);
3816
        $TABLECOURSUSER = Database:: get_main_table(TABLE_MAIN_COURSE_USER);
3817
        $TABLE_ACCESS_URL_REL_COURSE = Database:: get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
3818
        $current_url_id = api_get_current_access_url_id();
3819
        $courseList = [];
3820
3821
        // Get course list auto-register
3822
        $special_course_list = self::get_special_course_list();
3823
3824
        $without_special_courses = '';
3825
        if (!empty($special_course_list)) {
3826
            $without_special_courses = ' AND course.code NOT IN ("' . implode('","', $special_course_list) . '")';
3827
        }
3828
3829
        //AND course_rel_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
3830
        $sql = "SELECT
3831
                course.id,
3832
                course.title,
3833
                course.code,
3834
                course.subscribe subscr,
3835
                course.unsubscribe unsubscr,
3836
                course_rel_user.status status,
3837
                course_rel_user.sort sort,
3838
                course_rel_user.user_course_cat user_course_cat
3839
                FROM $TABLECOURS course,
3840
                     $TABLECOURSUSER course_rel_user,
3841
                     $TABLE_ACCESS_URL_REL_COURSE url
3842
                WHERE
3843
                    course.id = course_rel_user.c_id AND
3844
                    url.c_id = course.id AND
3845
                    course_rel_user.user_id = '" . $user_id . "' AND
3846
                    course_rel_user.user_course_cat = '" . $user_category_id . "'
3847
                    $without_special_courses ";
3848
3849
        // If multiple URL access mode is enabled, only fetch courses
3850
        // corresponding to the current URL.
3851
        if (api_get_multiple_access_url() && $current_url_id != -1) {
3852
            $sql .= " AND url.c_id = course.id AND access_url_id='" . $current_url_id . "'";
3853
        }
3854
        // Use user's classification for courses (if any).
3855
        $sql .= " ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
3856
        $result = Database::query($sql);
3857
3858
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
3859
        // Browse through all courses.
3860
        while ($course = Database::fetch_array($result)) {
3861
            $course_info = api_get_course_info($course['code']);
3862
            if (isset($course_info['visibility']) &&
3863
                $course_info['visibility'] == COURSE_VISIBILITY_HIDDEN
3864
            ) {
3865
                continue;
3866
            }
3867
            $course_info['id_session'] = null;
3868
            $course_info['status'] = $course['status'];
3869
3870
            // For each course, get if there is any notification icon to show
3871
            // (something that would have changed since the user's last visit).
3872
            $showNotification = Display::show_notification($course_info);
3873
3874
            $thumbnails = null;
3875
            $image = null;
3876
3877
            $iconName = basename($course_info['course_image']);
3878 View Code Duplication
            if ($showCustomIcon === 'true' && $iconName != 'course.png') {
3879
                $thumbnails = $course_info['course_image'];
3880
                $image = $course_info['course_image_large'];
3881
            }else{
3882
                $image = Display::return_icon('session_default.png', null, null, null,null, true);
3883
            }
3884
3885
            $params = array();
3886
            $params['edit_actions'] = '';
3887
            $params['document'] = '';
3888 View Code Duplication
            if (api_is_platform_admin()) {
3889
                $params['edit_actions'] .= api_get_path(WEB_CODE_PATH) . 'course_info/infocours.php?cidReq=' . $course['code'];
3890
                if($load_dirs){
3891
                    $params['document'] = '<a id="document_preview_' . $course_info['real_id'] . '_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3892
                               . Display::returnFontAwesomeIcon('folder-open') . '</a>';
3893
                    $params['document'] .= Display::div('', array('id' => 'document_result_' . $course_info['real_id'] . '_0', 'class' => 'document_preview_container'));
3894
                }
3895
            }
3896
            if ($load_dirs) {
3897
                $params['document'] = '<a id="document_preview_' . $course_info['real_id'] . '_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3898
                    . Display::returnFontAwesomeIcon('folder-open') . '</a>';
3899
                $params['document'] .= Display::div('', array('id' => 'document_result_' . $course_info['real_id'] . '_0', 'class' => 'document_preview_container'));
3900
            }
3901
3902
            $course_title_url = api_get_path(WEB_COURSE_PATH) . $course_info['path'] . '/index.php?id_session=0';
3903
3904
            $teachers = '';
3905
3906
            if (api_get_setting('display_teacher_in_courselist') === 'true') {
3907
                $teachers = CourseManager::getTeachersFromCourseByCode($course['code']);
3908
            }
3909
            $params['status'] = $course['status'];
3910
3911 View Code Duplication
            if (api_get_setting('display_coursecode_in_courselist') == 'true') {
3912
                $params['code_course'] = '(' . $course_info['visual_code'] . ') ';
3913
            }
3914
3915
            $params['visibility'] = $course_info['visibility'];
3916
            $params['link'] = $course_title_url;
3917
            $params['thumbnails'] = $thumbnails;
3918
            $params['image'] = $image;
3919
            $params['title'] = $course_info['title'];
3920
            $params['category'] = $course_info['categoryName'];
3921
            $params['teachers'] = $teachers;
3922
3923
            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
3924
                $params['notifications'] = $showNotification;
3925
            }
3926
3927
            $courseList[] = $params;
3928
3929
        }
3930
3931
        return $courseList;
3932
    }
3933
3934
    /**
3935
     * Retrieves the user defined course categories
3936
     * @param string $userId
3937
     * @return array containing all the titles of the user defined courses with the id as key of the array
3938
     */
3939 View Code Duplication
    public static function get_user_course_categories($userId = '')
3940
    {
3941
        if ($userId == '') {
3942
            $realUserId = api_get_user_id();
3943
        } else {
3944
            $realUserId = $userId;
3945
        }
3946
3947
        $output = array();
3948
        $table_category = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
3949
        $sql = "SELECT * FROM $table_category WHERE user_id = '".intval($realUserId)."'";
3950
        $result = Database::query($sql);
3951
        while ($row = Database::fetch_array($result)) {
3952
            $output[$row['id']] = $row['title'];
3953
        }
3954
        return $output;
3955
    }
3956
3957
    /**
3958
     * Return an array the user_category id and title for the course $courseId for user $userId
3959
     * @param $userId
3960
     * @param $courseId
3961
     * @return array
3962
     */
3963 View Code Duplication
    public static function getUserCourseCategoryForCourse($userId, $courseId)
3964
    {
3965
        $tblCourseRelUser = Database::get_main_table(TABLE_MAIN_COURSE_USER);
3966
        $tblUserCategory = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
3967
        $courseId = intval($courseId);
3968
        $userId = intval($userId);
3969
3970
        $sql = "SELECT user_course_cat, title
3971
                FROM $tblCourseRelUser cru
3972
                LEFT JOIN $tblUserCategory ucc
3973
                ON cru.user_course_cat = ucc.id
3974
                WHERE
3975
                    cru.user_id = $userId AND c_id= $courseId ";
3976
3977
        $res = Database::query($sql);
3978
3979
        $result = array();
3980
        if (Database::num_rows($res) > 0) {
3981
            $data = Database::fetch_assoc($res);
3982
            $result[] = $data['user_course_cat'];
3983
            $result[] = $data['title'];
3984
        }
3985
        return $result;
3986
    }
3987
3988
    /**
3989
     * Get the course id based on the original id and field name in the extra fields.
3990
     * Returns 0 if course was not found
3991
     *
3992
     * @param string $value Original course code
3993
     * @param string $variable Original field name
3994
     * @return int Course id
3995
     */
3996
    public static function getCourseInfoFromOriginalId($value, $variable)
3997
    {
3998
        $extraFieldValue = new ExtraFieldValue('course');
3999
        $result = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
4000
            $variable,
4001
            $value
4002
        );
4003
4004
        if (!empty($result)) {
4005
            $courseInfo = api_get_course_info_by_id($result['item_id']);
4006
            return $courseInfo;
4007
        }
4008
4009
        return 0;
4010
    }
4011
4012
    /**
4013
     * Display code for one specific course a logged in user is subscribed to.
4014
     * Shows a link to the course, what's new icons...
4015
     *
4016
     * $my_course['d'] - course directory
4017
     * $my_course['i'] - course title
4018
     * $my_course['c'] - visual course code
4019
     * $my_course['k']  - system course code
4020
     *
4021
     * @param   array       Course details
4022
     * @param   integer     Session ID
4023
     * @param   string      CSS class to apply to course entry
4024
     * @param   boolean     Whether the session is supposedly accessible now
4025
     * (not in the case it has passed and is in invisible/unaccessible mode)
4026
     * @param bool      Whether to show the document quick-loader or not
4027
     * @return  string      The HTML to be printed for the course entry
4028
     *
4029
     * @version 1.0.3
4030
     * @todo refactor into different functions for database calls | logic | display
4031
     * @todo replace single-character $my_course['d'] indices
4032
     * @todo move code for what's new icons to a separate function to clear things up
4033
     * @todo add a parameter user_id so that it is possible to show the
4034
     * courselist of other users (=generalisation).
4035
     * This will prevent having to write a new function for this.
4036
     */
4037
    public static function get_logged_user_course_html(
4038
        $course,
4039
        $session_id = 0,
4040
        $class = 'courses',
4041
        $session_accessible = true,
4042
        $load_dirs = false
4043
    ) {
4044
        $entityManager = Database::getManager();
4045
        $user_id = api_get_user_id();
4046
        $course_info = api_get_course_info_by_id($course['real_id']);
4047
        $status_course = CourseManager::get_user_in_course_status($user_id, $course_info['code']);
4048
        $course_info['status'] = empty($session_id) ? $status_course : STUDENT;
4049
        $course_info['id_session'] = $session_id;
4050
        $objUser = $entityManager->find('ChamiloUserBundle:User', $user_id);
4051
        $objCourse = $entityManager->find('ChamiloCoreBundle:Course', $course['real_id']);
4052
        $objSession = $entityManager->find('ChamiloCoreBundle:Session', $session_id);
4053
        $now = date('Y-m-d h:i:s');
4054
4055
        // Table definitions
4056
        $main_user_table = Database:: get_main_table(TABLE_MAIN_USER);
4057
        $tbl_session = Database:: get_main_table(TABLE_MAIN_SESSION);
4058
        $tbl_session_category = Database:: get_main_table(TABLE_MAIN_SESSION_CATEGORY);
4059
4060
        $course_access_settings = CourseManager::get_access_settings($course_info['code']);
4061
        $course_visibility = $course_access_settings['visibility'];
4062
4063
        if ($course_visibility == COURSE_VISIBILITY_HIDDEN) {
4064
            return '';
4065
        }
4066
4067
        $user_in_course_status = CourseManager::get_user_in_course_status(
4068
            api_get_user_id(),
4069
            $course_info['code']
4070
        );
4071
4072
        $is_coach = api_is_coach($course_info['id_session'], $course_info['real_id']);
4073
4074
        // Display course entry.
4075
        // Show a hyperlink to the course, unless the course is closed and user is not course admin.
4076
        $session_url = '';
4077
4078
        $params = array();
4079
        $params['icon'] = Display::return_icon(
4080
            'blackboard_blue.png',
4081
            null,
4082
            array(),
4083
            ICON_SIZE_LARGE,
4084
            null,
4085
            true
4086
        );
4087
4088
        // Display the "what's new" icons
4089
        $notifications = '';
4090
        if ($course_visibility != COURSE_VISIBILITY_CLOSED && $course_visibility != COURSE_VISIBILITY_HIDDEN) {
4091
            $notifications .= Display:: show_notification($course_info);
4092
        }
4093
4094
        if ($session_accessible) {
4095
            if ($course_visibility != COURSE_VISIBILITY_CLOSED ||
4096
                $user_in_course_status == COURSEMANAGER
4097
            ) {
4098
                if (empty($course_info['id_session'])) {
4099
                    $course_info['id_session'] = 0;
4100
                }
4101
4102
                $sessionCourseAvailable = false;
4103
                $sessionCourseStatus = api_get_session_visibility($session_id, $course_info['real_id']);
4104
4105
                if (in_array($sessionCourseStatus,
4106
                    array(SESSION_VISIBLE_READ_ONLY, SESSION_VISIBLE, SESSION_AVAILABLE))) {
4107
                    $sessionCourseAvailable = true;
4108
                }
4109
4110
                if ($user_in_course_status == COURSEMANAGER || $sessionCourseAvailable) {
4111
                    $session_url = $course_info['course_public_url'] . '?id_session=' . $course_info['id_session'];
4112
                    $session_title = '<a href="' . $session_url. '">'. $course_info['name'] . '</a>'.$notifications;
4113
                } else {
4114
                    $session_title = $course_info['name'];
4115
                }
4116
4117
            } else {
4118
                $session_title =
4119
                    $course_info['name'] . ' ' .
4120
                    Display::tag('span', get_lang('CourseClosed'), array('class' => 'item_closed'));
4121
            }
4122
        } else {
4123
            $session_title = $course_info['name'];
4124
        }
4125
4126
        $thumbnails = null;
4127
        $image = null;
4128
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
4129
        $iconName = basename($course_info['course_image']);
4130
4131 View Code Duplication
        if ($showCustomIcon === 'true' && $iconName != 'course.png') {
4132
            $thumbnails = $course_info['course_image'];
4133
            $image = $course_info['course_image_large'];
4134
        }else{
4135
            $image = Display::return_icon('session_default.png', null, null, null,null, true);
4136
        }
4137
        $params['thumbnails'] = $thumbnails;
4138
        $params['image'] = $image;
4139
        $params['link'] = $session_url;
4140
        $params['title'] = $session_title;
4141
        $params['edit_actions'] = '';
4142
        $params['document'] = '';
4143
4144
        if ($course_visibility != COURSE_VISIBILITY_CLOSED &&
4145
            $course_visibility != COURSE_VISIBILITY_HIDDEN
4146
        ) {
4147
            if (api_is_platform_admin()) {
4148
                $params['edit_actions'] .= api_get_path(WEB_CODE_PATH) . 'course_info/infocours.php?cidReq=' . $course_info['code'];
4149
            if ($load_dirs) {
4150
                $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);">' .
4151
                    Display::returnFontAwesomeIcon('folder-open') . '</a>';
4152
                $params['document'] .= Display::div('', array(
4153
                    'id' => 'document_result_' . $course_info['real_id'] . '_' . $course_info['id_session'],
4154
                    'class' => 'document_preview_container'
4155
                ));
4156
            }
4157
        }
4158
        }
4159
4160
        if (api_get_setting('display_coursecode_in_courselist') === 'true') {
4161
            $session_title .= ' (' . $course_info['visual_code'] . ') ';
4162
        }
4163
4164
        if (api_get_setting('display_teacher_in_courselist') === 'true') {
4165
            $teacher_list = CourseManager::getTeachersFromCourseByCode(
4166
                $course_info['code']
4167
            );
4168
4169
            $course_coachs = self::get_coachs_from_course(
4170
                $course_info['id_session'],
4171
                $course_info['real_id']
4172
            );
4173
            $params['teachers'] = $teacher_list;
4174
4175
            if (($course_info['status'] == STUDENT && !empty($course_info['id_session'])) ||
4176
                ($is_coach && $course_info['status'] != COURSEMANAGER)
4177
            ) {
4178
                $params['coaches'] = $course_coachs;
4179
            }
4180
        }
4181
4182
        $session_title .= isset($course['special_course']) ? ' ' .
4183
                          Display::return_icon('klipper.png', get_lang('CourseAutoRegister')) : '';
4184
4185
        $params['title'] = $session_title;
4186
        $params['extra'] = '';
4187
4188
        $html = $params;
4189
4190
        $session_category_id = null;
4191
        if (1) {
4192
            $session = '';
4193
            $active = false;
4194
            if (!empty($course_info['id_session'])) {
4195
4196
                // Request for the name of the general coach
4197
                $sql = 'SELECT lastname, firstname,sc.name
4198
                        FROM ' . $tbl_session . ' ts
4199
                        LEFT JOIN ' . $main_user_table . ' tu
4200
                        ON ts.id_coach = tu.user_id
4201
                        INNER JOIN ' . $tbl_session_category . ' sc
4202
                        ON ts.session_category_id = sc.id
4203
                        WHERE ts.id=' . (int)$course_info['id_session'] . '
4204
                        LIMIT 1';
4205
4206
                $rs = Database::query($sql);
4207
                $sessioncoach = Database::store_result($rs);
4208
                $sessioncoach = $sessioncoach ? $sessioncoach[0] : null;
4209
4210
                $session = api_get_session_info($course_info['id_session']);
4211
                $session_category_id = CourseManager::get_session_category_id_by_session_id($course_info['id_session']);
4212
                $session['category'] = $sessioncoach['name'];
4213
                if (
4214
                    $session['access_start_date'] == '0000-00-00 00:00:00' || empty($session['access_start_date']) ||
4215
                    $session['access_start_date'] == '0000-00-00'
4216
                ) {
4217
                    //$session['dates'] = get_lang('WithoutTimeLimits');
4218
                    $session['dates'] = '';
4219 View Code Duplication
                    if (api_get_setting('show_session_coach') === 'true') {
4220
                        $session['coach'] = get_lang('GeneralCoach') . ': ' . api_get_person_name($sessioncoach['firstname'],
4221
                                $sessioncoach['lastname']);
4222
                    }
4223
                    $active = true;
4224
                } else {
4225
                    $session ['dates'] = ' - ' . get_lang('From') . ' ' . $session['access_start_date'] . ' ' . get_lang('To') . ' ' . $session['access_end_date'];
4226 View Code Duplication
                    if (api_get_setting('show_session_coach') === 'true') {
4227
                        $session['coach'] = get_lang('GeneralCoach') . ': ' . api_get_person_name($sessioncoach['firstname'],
4228
                                $sessioncoach['lastname']);
4229
                    }
4230
                    $date_start = $session['access_start_date'];
4231
                    $date_end = $session['access_end_date'];
4232
4233
                    $active = !$date_end ? ($date_start <= $now) : ($date_start <= $now && $date_end >= $now);
4234
                }
4235
            }
4236
            $user_course_category = '';
4237
            if (isset($course_info['user_course_cat'])) {
4238
                $user_course_category = $course_info['user_course_cat'];
4239
            }
4240
            $output = array(
4241
                $user_course_category,
4242
                $html,
4243
                $course_info['id_session'],
4244
                $session,
4245
                'active' => $active,
4246
                'session_category_id' => $session_category_id
4247
            );
4248
4249
            if (api_get_setting('allow_skills_tool') === 'true') {
4250
                $skill = $entityManager
4251
                    ->getRepository('ChamiloCoreBundle:Skill')
4252
                    ->getLastByUser($objUser, $objCourse, $objSession);
4253
4254
                $output['skill'] = null;
4255
4256
                if ($skill) {
4257
                    $output['skill']['name'] = $skill->getName();
4258
                    $output['skill']['icon'] = $skill->getIcon();
4259
                }
4260
            }
4261
        } else {
4262
            $output = array($course_info['user_course_cat'], $html);
4263
        }
4264
        return $output;
4265
    }
4266
4267
    /**
4268
     *
4269
     * @param    string    source course code
4270
     * @param     int        source session id
4271
     * @param    string    destination course code
4272
     * @param     int        destination session id
4273
     * @param integer $source_session_id
4274
     * @param integer $destination_session_id
4275
     * @return  bool
4276
     */
4277
    public static function copy_course(
4278
        $source_course_code,
4279
        $source_session_id,
4280
        $destination_course_code,
4281
        $destination_session_id,
4282
        $params = array()
4283
    ) {
4284
        $course_info = api_get_course_info($source_course_code);
4285
4286
        if (!empty($course_info)) {
4287
            $cb = new CourseBuilder('', $course_info);
4288
            $course = $cb->build($source_session_id, $source_course_code, true);
4289
            $course_restorer = new CourseRestorer($course);
4290
            $course_restorer->skip_content = $params;
4291
            $course_restorer->restore($destination_course_code, $destination_session_id, true, true);
4292
            return true;
4293
        }
4294
        return false;
4295
    }
4296
4297
    /**
4298
     * A simpler version of the copy_course, the function creates an empty course with an autogenerated course code
4299
     *
4300
     * @param    string    new course title
4301
     * @param    string    source course code
4302
     * @param     int        source session id
4303
     * @param     int        destination session id
4304
     * @param    bool    new copied tools (Exercises and LPs)will be set to invisible by default?
4305
     * @param string $new_title
4306
     *
4307
     * @return     array
4308
     */
4309
    public static function copy_course_simple(
4310
        $new_title,
4311
        $source_course_code,
4312
        $source_session_id = 0,
4313
        $destination_session_id = 0,
4314
        $params = array()
4315
    ) {
4316
        $source_course_info = api_get_course_info($source_course_code);
4317
        if (!empty($source_course_info)) {
4318
            $new_course_code = self::generate_nice_next_course_code($source_course_code);
4319
            if ($new_course_code) {
4320
                $new_course_info = self::create_course($new_title, $new_course_code, false);
4321
                if (!empty($new_course_info['code'])) {
4322
                    $result = self::copy_course($source_course_code, $source_session_id, $new_course_info['code'],
4323
                        $destination_session_id, $params);
4324
                    if ($result) {
4325
                        return $new_course_info;
4326
                    }
4327
                }
4328
            }
4329
        }
4330
4331
        return false;
4332
    }
4333
4334
    /**
4335
     * Creates a new course code based in a given code
4336
     *
4337
     * @param string    wanted code
4338
     * <code>    $wanted_code = 'curse' if there are in the DB codes like curse1 curse2 the function will return: course3</code>
4339
     * if the course code doest not exist in the DB the same course code will be returned
4340
     * @return string    wanted unused code
4341
     */
4342 View Code Duplication
    public static function generate_nice_next_course_code($wanted_code)
4343
    {
4344
        $course_code_ok = !self::course_code_exists($wanted_code);
4345
        if (!$course_code_ok) {
4346
            $wanted_code = CourseManager::generate_course_code($wanted_code);
4347
            $table = Database::get_main_table(TABLE_MAIN_COURSE);
4348
            $wanted_code = Database::escape_string($wanted_code);
4349
            $sql = "SELECT count(*) as count
4350
                    FROM $table
4351
                    WHERE code LIKE '$wanted_code%'";
4352
            $result = Database::query($sql);
4353
            if (Database::num_rows($result) > 0) {
4354
                $row = Database::fetch_array($result);
4355
                $count = $row['count'] + 1;
4356
                $wanted_code = $wanted_code . '_' . $count;
4357
                $result = api_get_course_info($wanted_code);
4358
                if (empty($result)) {
4359
                    return $wanted_code;
4360
                }
4361
            }
4362
4363
            return false;
4364
        }
4365
4366
        return $wanted_code;
4367
    }
4368
4369
    /**
4370
     * Gets the status of the users agreement in a course course-session
4371
     *
4372
     * @param int $user_id
4373
     * @param string $course_code
4374
     * @param int $session_id
4375
     * @return boolean
4376
     */
4377
    public static function is_user_accepted_legal($user_id, $course_code, $session_id = null)
4378
    {
4379
        $user_id = intval($user_id);
4380
        $course_code = Database::escape_string($course_code);
4381
        $session_id = intval($session_id);
4382
4383
        $courseInfo = api_get_course_info($course_code);
4384
        $courseId = $courseInfo['real_id'];
4385
4386
        // Course legal
4387
        $enabled = api_get_plugin_setting('courselegal', 'tool_enable');
4388
4389 View Code Duplication
        if ($enabled == 'true') {
4390
            require_once api_get_path(SYS_PLUGIN_PATH) . 'courselegal/config.php';
4391
            $plugin = CourseLegalPlugin::create();
4392
            return $plugin->isUserAcceptedLegal($user_id, $course_code, $session_id);
4393
        }
4394
4395
        if (empty($session_id)) {
4396
            $table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4397
            $sql = "SELECT legal_agreement FROM $table
4398
                    WHERE user_id = $user_id AND c_id = $courseId ";
4399
            $result = Database::query($sql);
4400
            if (Database::num_rows($result) > 0) {
4401
                $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...
4402
                if ($result['legal_agreement'] == 1) {
4403
                    return true;
4404
                }
4405
            }
4406
            return false;
4407
        } else {
4408
            $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4409
            $sql = "SELECT legal_agreement FROM $table
4410
                    WHERE user_id = $user_id AND c_id = $courseId AND session_id = $session_id";
4411
            $result = Database::query($sql);
4412
            if (Database::num_rows($result) > 0) {
4413
                $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...
4414
                if ($result['legal_agreement'] == 1) {
4415
                    return true;
4416
                }
4417
            }
4418
            return false;
4419
        }
4420
    }
4421
4422
    /**
4423
     * Saves the user-course legal agreement
4424
     * @param   int user id
4425
     * @param   string course code
4426
     * @param   int session id
4427
     * @return mixed
4428
     */
4429
    public static function save_user_legal($user_id, $course_code, $session_id = null)
4430
    {
4431
        // Course plugin legal
4432
        $enabled = api_get_plugin_setting('courselegal', 'tool_enable');
4433
4434 View Code Duplication
        if ($enabled == 'true') {
4435
            require_once api_get_path(SYS_PLUGIN_PATH) . 'courselegal/config.php';
4436
            $plugin = CourseLegalPlugin::create();
4437
            return $plugin->saveUserLegal($user_id, $course_code, $session_id);
4438
        }
4439
4440
        $user_id = intval($user_id);
4441
        $course_code = Database::escape_string($course_code);
4442
        $session_id = intval($session_id);
4443
4444
        $courseInfo = api_get_course_info($course_code);
4445
        $courseId = $courseInfo['real_id'];
4446
4447
        if (empty($session_id)) {
4448
            $table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4449
            $sql = "UPDATE $table SET legal_agreement = '1'
4450
                    WHERE user_id = $user_id AND c_id  = $courseId ";
4451
            Database::query($sql);
4452
        } else {
4453
            $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4454
            $sql = "UPDATE  $table SET legal_agreement = '1'
4455
                    WHERE user_id = $user_id AND c_id = $courseId AND session_id = $session_id";
4456
            Database::query($sql);
4457
        }
4458
    }
4459
4460
    /**
4461
     * @param int $user_id
4462
     * @param int $course_id
4463
     * @param int $session_id
4464
     * @param int $url_id
4465
     * @return bool
4466
     */
4467
    public static function get_user_course_vote($user_id, $course_id, $session_id = null, $url_id = null)
4468
    {
4469
        $table_user_course_vote = Database::get_main_table(TABLE_MAIN_USER_REL_COURSE_VOTE);
4470
4471
        $session_id = !isset($session_id) ? api_get_session_id() : intval($session_id);
4472
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4473
        $user_id = intval($user_id);
4474
4475
        if (empty($user_id)) {
4476
            return false;
4477
        }
4478
4479
        $params = array(
4480
            'user_id' => $user_id,
4481
            'c_id' => $course_id,
4482
            'session_id' => $session_id,
4483
            'url_id' => $url_id
4484
        );
4485
4486
        $result = Database::select(
4487
            'vote',
4488
            $table_user_course_vote,
4489
            array(
4490
                'where' => array(
4491
                    'user_id = ? AND c_id = ? AND session_id = ? AND url_id = ?' => $params
4492
                )
4493
            ),
4494
            'first'
4495
        );
4496
        if (!empty($result)) {
4497
            return $result['vote'];
4498
        }
4499
        return false;
4500
    }
4501
4502
    /**
4503
     * @param int $course_id
4504
     * @param int $session_id
4505
     * @param int $url_id
4506
     * @return array
4507
     */
4508
    public static function get_course_ranking($course_id, $session_id = null, $url_id = null)
4509
    {
4510
        $table_course_ranking = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
4511
4512
        $session_id = !isset($session_id) ? api_get_session_id() : intval($session_id);
4513
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4514
        $now = api_get_utc_datetime();
4515
4516
        $params = array(
4517
            'c_id' => $course_id,
4518
            'session_id' => $session_id,
4519
            'url_id' => $url_id,
4520
            'creation_date' => $now,
4521
        );
4522
4523
        $result = Database::select(
4524
            'c_id, accesses, total_score, users',
4525
            $table_course_ranking,
4526
            array('where' => array('c_id = ? AND session_id = ? AND url_id = ?' => $params)),
4527
            'first'
4528
        );
4529
4530
        $point_average_in_percentage = 0;
4531
        $point_average_in_star = 0;
4532
        $users_who_voted = 0;
4533
4534
        if (!empty($result['users'])) {
4535
            $users_who_voted = $result['users'];
4536
            $point_average_in_percentage = round($result['total_score'] / $result['users'] * 100 / 5, 2);
4537
            $point_average_in_star = round($result['total_score'] / $result['users'], 1);
4538
        }
4539
4540
        $result['user_vote'] = false;
4541
4542
        if (!api_is_anonymous()) {
4543
            $result['user_vote'] = self::get_user_course_vote(api_get_user_id(), $course_id, $session_id, $url_id);
4544
        }
4545
4546
        $result['point_average'] = $point_average_in_percentage;
4547
        $result['point_average_star'] = $point_average_in_star;
4548
        $result['users_who_voted'] = $users_who_voted;
4549
4550
        return $result;
4551
    }
4552
4553
    /**
4554
     *
4555
     * Updates the course ranking
4556
     * @param int   course id
4557
     * @param int   session id
4558
     * @param id    url id
4559
     * @param integer $session_id
4560
     * @return array
4561
     **/
4562
    public static function update_course_ranking(
4563
        $course_id = null,
4564
        $session_id = null,
4565
        $url_id = null,
4566
        $points_to_add = null,
4567
        $add_access = true,
4568
        $add_user = true
4569
    ) {
4570
        // Course catalog stats modifications see #4191
4571
        $table_course_ranking = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
4572
4573
        $now = api_get_utc_datetime();
4574
4575
        $course_id = empty($course_id) ? api_get_course_int_id() : intval($course_id);
4576
        $session_id = !isset($session_id) ? api_get_session_id() : intval($session_id);
4577
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4578
4579
        $params = array(
4580
            'c_id' => $course_id,
4581
            'session_id' => $session_id,
4582
            'url_id' => $url_id,
4583
            'creation_date' => $now,
4584
            'total_score' => 0,
4585
            'users' => 0
4586
        );
4587
4588
        $result = Database::select(
4589
            'id, accesses, total_score, users',
4590
            $table_course_ranking,
4591
            array('where' => array('c_id = ? AND session_id = ? AND url_id = ?' => $params)),
4592
            'first'
4593
        );
4594
4595
        // Problem here every time we load the courses/XXXX/index.php course home page we update the access
4596
4597
        if (empty($result)) {
4598
            if ($add_access) {
4599
                $params['accesses'] = 1;
4600
            }
4601
            //The votes and users are empty
4602
            if (isset($points_to_add) && !empty($points_to_add)) {
4603
                $params['total_score'] = intval($points_to_add);
4604
            }
4605
            if ($add_user) {
4606
                $params['users'] = 1;
4607
            }
4608
            $result = Database::insert($table_course_ranking, $params);
4609
        } else {
4610
            $my_params = array();
4611
4612
            if ($add_access) {
4613
                $my_params['accesses'] = intval($result['accesses']) + 1;
4614
            }
4615
            if (isset($points_to_add) && !empty($points_to_add)) {
4616
                $my_params['total_score'] = $result['total_score'] + $points_to_add;
4617
            }
4618
            if ($add_user) {
4619
                $my_params['users'] = $result['users'] + 1;
4620
            }
4621
4622
            if (!empty($my_params)) {
4623
                $result = Database::update(
4624
                    $table_course_ranking,
4625
                    $my_params,
4626
                    array('c_id = ? AND session_id = ? AND url_id = ?' => $params)
4627
                );
4628
            }
4629
        }
4630
4631
        return $result;
4632
    }
4633
4634
    /**
4635
     * Add user vote to a course
4636
     *
4637
     * @param   int user id
4638
     * @param   int vote [1..5]
4639
     * @param   int course id
4640
     * @param   int session id
4641
     * @param   int url id (access_url_id)
4642
     * @return    false|string 'added', 'updated' or 'nothing'
4643
     */
4644
    public static function add_course_vote($user_id, $vote, $course_id, $session_id = null, $url_id = null)
4645
    {
4646
        $table_user_course_vote = Database::get_main_table(TABLE_MAIN_USER_REL_COURSE_VOTE);
4647
        $course_id = empty($course_id) ? api_get_course_int_id() : intval($course_id);
4648
4649
        if (empty($course_id) || empty($user_id)) {
4650
            return false;
4651
        }
4652
4653
        if (!in_array($vote, array(1, 2, 3, 4, 5))) {
4654
            return false;
4655
        }
4656
4657
        $session_id = !isset($session_id) ? api_get_session_id() : intval($session_id);
4658
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4659
        $vote = intval($vote);
4660
4661
        $params = array(
4662
            'user_id' => intval($user_id),
4663
            'c_id' => $course_id,
4664
            'session_id' => $session_id,
4665
            'url_id' => $url_id,
4666
            'vote' => $vote
4667
        );
4668
4669
        $action_done = 'nothing';
4670
4671
        $result = Database::select(
4672
            'id, vote',
4673
            $table_user_course_vote,
4674
            array('where' => array('user_id = ? AND c_id = ? AND session_id = ? AND url_id = ?' => $params)),
4675
            'first'
4676
        );
4677
4678
        if (empty($result)) {
4679
            Database::insert($table_user_course_vote, $params);
4680
            $points_to_add = $vote;
4681
            $add_user = true;
4682
            $action_done = 'added';
4683
        } else {
4684
            $my_params = array('vote' => $vote);
4685
            $points_to_add = $vote - $result['vote'];
4686
            $add_user = false;
4687
4688
            Database::update(
4689
                $table_user_course_vote,
4690
                $my_params,
4691
                array('user_id = ? AND c_id = ? AND session_id = ? AND url_id = ?' => $params)
4692
            );
4693
            $action_done = 'updated';
4694
        }
4695
4696
        // Current points
4697
        if (!empty($points_to_add)) {
4698
            self::update_course_ranking(
4699
                $course_id,
4700
                $session_id,
4701
                $url_id,
4702
                $points_to_add,
4703
                false,
4704
                $add_user
4705
            );
4706
        }
4707
        return $action_done;
4708
    }
4709
4710
    /**
4711
     * Remove course ranking + user votes
4712
     *
4713
     * @param int $course_id
4714
     * @param int $session_id
4715
     * @param int $url_id
4716
     *
4717
     */
4718
    public static function remove_course_ranking($course_id, $session_id, $url_id = null)
4719
    {
4720
        $table_course_ranking = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
4721
        $table_user_course_vote = Database::get_main_table(TABLE_MAIN_USER_REL_COURSE_VOTE);
4722
4723
        if (!empty($course_id) && isset($session_id)) {
4724
            $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4725
            $params = array(
4726
                'c_id' => $course_id,
4727
                'session_id' => $session_id,
4728
                'url_id' => $url_id,
4729
            );
4730
            Database::delete($table_course_ranking, array('c_id = ? AND session_id = ? AND url_id = ?' => $params));
4731
            Database::delete($table_user_course_vote, array('c_id = ? AND session_id = ? AND url_id = ?' => $params));
4732
        }
4733
    }
4734
4735
    /**
4736
     * Returns an array with the hottest courses
4737
     * @param   int $days number of days
4738
     * @param   int $limit number of hottest courses
4739
     * @return array
4740
     */
4741
    public static function return_hot_courses($days = 30, $limit = 6)
4742
    {
4743
        if (api_is_invitee()) {
4744
            return array();
4745
        }
4746
4747
        $limit = intval($limit);
4748
4749
        // Getting my courses
4750
        $my_course_list = CourseManager::get_courses_list_by_user_id(api_get_user_id());
4751
4752
        $my_course_code_list = array();
4753
        foreach ($my_course_list as $course) {
4754
            $my_course_code_list[$course['real_id']] = $course['real_id'];
4755
        }
4756
4757
        if (api_is_drh()) {
4758
            $courses = CourseManager::get_courses_followed_by_drh(api_get_user_id());
4759
            foreach ($courses as $course) {
4760
                $my_course_code_list[$course['real_id']] = $course['real_id'];
4761
            }
4762
        }
4763
4764
        $table_course_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
4765
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
4766
        $table_course_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
4767
4768
        //$table_course_access table uses the now() and interval ...
4769
        $now = api_get_utc_datetime(time());
4770
        $sql = "SELECT COUNT(course_access_id) course_count, a.c_id, visibility
4771
                FROM $table_course c
4772
                INNER JOIN $table_course_access a
4773
                ON (c.id = a.c_id)
4774
                INNER JOIN $table_course_url u
4775
                ON u.c_id = c.id
4776
                WHERE
4777
                    u.access_url_id = " . api_get_current_access_url_id() . " AND
4778
                    login_course_date <= '$now' AND
4779
                    login_course_date > DATE_SUB('$now', INTERVAL $days DAY) AND
4780
                    visibility <> '" . COURSE_VISIBILITY_CLOSED . "' AND visibility <> '" . COURSE_VISIBILITY_HIDDEN . "'
4781
                GROUP BY a.c_id
4782
                ORDER BY course_count DESC
4783
                LIMIT $limit
4784
            ";
4785
4786
        $result = Database::query($sql);
4787
        $courses = array();
4788
4789
        if (Database::num_rows($result)) {
4790
            $courses = Database::store_result($result, 'ASSOC');
4791
            $courses = self::process_hot_course_item($courses, $my_course_code_list);
4792
        }
4793
4794
        return $courses;
4795
    }
4796
4797
    /**
4798
     * @param array $courses
4799
     * @param array $my_course_code_list
4800
     * @return mixed
4801
     */
4802
    public static function process_hot_course_item($courses, $my_course_code_list = array())
4803
    {
4804
        $hotCourses = [];
4805
4806
        $ajax_url = api_get_path(WEB_AJAX_PATH) . 'course.ajax.php?a=add_course_vote';
4807
4808
        $stok = Security::get_existing_token();
4809
4810
        $user_id = api_get_user_id();
4811
4812
        foreach ($courses as $courseId) {
4813
            $course_info = api_get_course_info_by_id($courseId['c_id']);
4814
            $courseCode = $course_info['code'];
4815
            $categoryCode = !empty($course_info['categoryCode']) ? $course_info['categoryCode'] : "";
4816
            $my_course = $course_info;
4817
            $my_course['go_to_course_button'] = '';
4818
            $my_course['register_button'] = '';
4819
4820
            $access_link = self::get_access_link_by_user(
4821
                api_get_user_id(),
4822
                $course_info,
4823
                $my_course_code_list
4824
            );
4825
4826
            $user_registerd_in_course = CourseManager::is_user_subscribed_in_course($user_id, $course_info['code']);
4827
            $user_registerd_in_course_as_teacher = CourseManager::is_course_teacher($user_id, $course_info['code']);
4828
            $user_registerd_in_course_as_student = ($user_registerd_in_course && !$user_registerd_in_course_as_teacher);
4829
4830
            // if user registered as student
4831
            if ($user_registerd_in_course_as_student) {
4832
                $icon = '<em class="fa fa-graduation-cap"></em>';
4833
                $title = get_lang("AlreadyRegisteredToCourse");
4834
                $my_course['already_register_as'] = Display::tag(
4835
                    'button',
4836
                    $icon,
4837
                    array('id' => 'register', 'class' => 'btn btn-default btn-sm', 'title' => $title)
4838
                );
4839
            } elseif ($user_registerd_in_course_as_teacher) {
4840
                // if user registered as teacher
4841
                $icon = '<em class="fa fa-suitcase"></em>';
4842
                $title = get_lang("YouAreATeacherOfThisCourse");
4843
                $my_course['already_register_as'] = Display::tag(
4844
                    'button',
4845
                    $icon,
4846
                    array('id' => 'register', 'class' => 'btn btn-default btn-sm', 'title' => $title)
4847
                );
4848
            }
4849
4850
            //Course visibility
4851 View Code Duplication
            if ($access_link && in_array('register', $access_link)) {
4852
                $my_course['register_button'] = Display::url(
4853
                    Display::returnFontAwesomeIcon('sign-in'),
4854
                    api_get_path(WEB_COURSE_PATH) . $course_info['path'] . '/index.php?action=subscribe&sec_token=' . $stok,
4855
                    array('class' => 'btn btn-success btn-sm', 'title' => get_lang('Subscribe')));
4856
            }
4857
4858 View Code Duplication
            if ($access_link && in_array('enter',
4859
                    $access_link) || $course_info['visibility'] == COURSE_VISIBILITY_OPEN_WORLD
4860
            ) {
4861
                $my_course['go_to_course_button'] = Display::url(
4862
                    Display::returnFontAwesomeIcon('share'),
4863
                    api_get_path(WEB_COURSE_PATH) . $course_info['path'] . '/index.php',
4864
                    array('class' => 'btn btn-default btn-sm', 'title' => get_lang('GoToCourse')));
4865
            }
4866
4867
            if ($access_link && in_array('unsubscribe', $access_link)) {
4868
                $my_course['unsubscribe_button'] = Display::url(
4869
                    Display::returnFontAwesomeIcon('sign-out'),
4870
                    api_get_path(WEB_CODE_PATH) . 'auth/courses.php?action=unsubscribe&unsubscribe=' . $courseCode . '&sec_token=' . $stok . '&category_code=' . $categoryCode,
4871
                    array('class' => 'btn btn-danger btn-sm', 'title' => get_lang('Unreg')));
4872
            }
4873
4874
            // start buycourse validation
4875
            // display the course price and buy button if the buycourses plugin is enabled and this course is configured
4876
            $plugin = BuyCoursesPlugin::create();
4877
            $isThisCourseInSale = $plugin->buyCoursesForGridCatalogVerificator($course_info['real_id'], BuyCoursesPlugin::PRODUCT_TYPE_COURSE);
4878
            if ($isThisCourseInSale) {
4879
                // set the price label
4880
                $my_course['price'] = $isThisCourseInSale['html'];
4881
                // set the Buy button instead register.
4882
                if ($isThisCourseInSale['verificator'] && !empty($my_course['register_button'])) {
4883
                    $my_course['register_button'] = $plugin->returnBuyCourseButton($course_info['real_id'], BuyCoursesPlugin::PRODUCT_TYPE_COURSE);
4884
                }
4885
            }
4886
            // end buycourse validation
4887
4888
            //Description
4889
            $my_course['description_button'] = '';
4890
            /* if ($course_info['visibility'] == COURSE_VISIBILITY_OPEN_WORLD || in_array($course_info['real_id'],
4891
                    $my_course_code_list)
4892
            ) { */
4893
                $my_course['description_button'] = Display::url(
4894
                    Display::returnFontAwesomeIcon('info-circle'),
4895
                    api_get_path(WEB_AJAX_PATH) . 'course_home.ajax.php?a=show_course_information&code=' . $course_info['code'],
4896
                    [
4897
                        'class' => 'btn btn-default btn-sm ajax',
4898
                        'data-title' => get_lang('Description'),
4899
                        'title' => get_lang('Description')
4900
                    ]
4901
                );
4902
            //}
4903
            /* get_lang('Description') */
4904
            $my_course['teachers'] = CourseManager::getTeachersFromCourseByCode($course_info['code']);
4905
            $point_info = self::get_course_ranking($course_info['real_id'], 0);
4906
            $my_course['rating_html'] = Display::return_rating_system('star_' . $course_info['real_id'],
4907
                $ajax_url . '&course_id=' . $course_info['real_id'], $point_info);
4908
4909
            $hotCourses[] = $my_course;
4910
        }
4911
        return $hotCourses;
4912
    }
4913
4914
    /**
4915
     * @param int $limit
4916
     * @return array
4917
     */
4918
    public static function return_most_accessed_courses($limit = 5)
4919
    {
4920
        $table_course_ranking = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
4921
        $params['url_id'] = api_get_current_access_url_id();
4922
4923
        $result = Database::select(
4924
            'c_id, accesses, total_score, users',
4925
            $table_course_ranking,
4926
            array('where' => array('url_id = ?' => $params), 'order' => 'accesses DESC', 'limit' => $limit),
4927
            'all',
4928
            true
4929
        );
4930
        return $result;
4931
    }
4932
4933
    /**
4934
     * Get courses count
4935
     * @param int Access URL ID (optional)
4936
     * @param int $visibility
4937
     * @param integer $access_url_id
4938
     *
4939
     * @return int Number of courses
4940
     */
4941
    public static function count_courses($access_url_id = null, $visibility = null)
4942
    {
4943
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
4944
        $table_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
4945
        $sql = "SELECT count(c.id) FROM $table_course c";
4946
        if (!empty($access_url_id) && $access_url_id == intval($access_url_id)) {
4947
            $sql .= ", $table_course_rel_access_url u
4948
                    WHERE c.id = u.c_id AND u.access_url_id = $access_url_id";
4949
            if (!empty($visibility)) {
4950
                $visibility = intval($visibility);
4951
                $sql .= " AND visibility = $visibility ";
4952
            }
4953
        } else {
4954
            if (!empty($visibility)) {
4955
                $visibility = intval($visibility);
4956
                $sql .= " WHERE visibility = $visibility ";
4957
            }
4958
        }
4959
4960
        $res = Database::query($sql);
4961
        $row = Database::fetch_row($res);
4962
4963
        return $row[0];
4964
    }
4965
4966
    /**
4967
     * Get active courses count.
4968
     * Active = all courses except the ones with hidden visibility.
4969
     *
4970
     * @param int $urlId Access URL ID (optional)
4971
     * @return int Number of courses
4972
     */
4973
    public static function countActiveCourses($urlId = null)
4974
    {
4975
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
4976
        $table_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
4977
        $sql = "SELECT count(id) FROM $table_course c";
4978
        if (!empty($urlId) && $urlId == intval($urlId)) {
4979
            $sql .= ", $table_course_rel_access_url u
4980
                    WHERE
4981
                        c.id = u.c_id AND
4982
                        u.access_url_id = $urlId AND
4983
                        visibility <> " . COURSE_VISIBILITY_HIDDEN;
4984
        } else {
4985
            $sql .= " WHERE visibility <> " . COURSE_VISIBILITY_HIDDEN;
4986
        }
4987
        $res = Database::query($sql);
4988
        $row = Database::fetch_row($res);
4989
        return $row[0];
4990
    }
4991
4992
    /**
4993
     * Returns the SQL conditions to filter course only visible by the user in the catalogue
4994
     *
4995
     * @param $courseTableAlias Alias of the course table
4996
     * @return string SQL conditions
4997
     */
4998
    public static function getCourseVisibilitySQLCondition($courseTableAlias) {
4999
        $visibilityCondition = '';
5000
        $hidePrivate = api_get_setting('course_catalog_hide_private');
5001
        if ($hidePrivate === 'true') {
5002
            $visibilityCondition = ' AND '.$courseTableAlias.'.visibility <> 1';
5003
        }
5004
5005
        // Check if course have users allowed to see it in the catalogue, then show only if current user is allowed to see it
5006
        $currentUserId = api_get_user_id();
5007
        $restrictedCourses = self::getCatalogueCourseList(true);
5008
        $allowedCoursesToCurrentUser = self::getCatalogueCourseList(true, $currentUserId);
5009 View Code Duplication
        if (!empty($restrictedCourses)) {
5010
            $visibilityCondition .= ' AND ('.$courseTableAlias.'.code NOT IN ("' . implode('","', $restrictedCourses) . '")';
5011
            $visibilityCondition .= ' OR '.$courseTableAlias.'.code IN ("' . implode('","', $allowedCoursesToCurrentUser) . '"))';
5012
        }
5013
5014
        // Check if course have users denied to see it in the catalogue, then show only if current user is not denied to see it
5015
        $restrictedCourses = self::getCatalogueCourseList(false);
5016
        $notAllowedCoursesToCurrentUser = self::getCatalogueCourseList(false, $currentUserId);
5017 View Code Duplication
        if (!empty($restrictedCourses)) {
5018
            $visibilityCondition .= ' AND ('.$courseTableAlias.'.code NOT IN ("' . implode('","', $restrictedCourses) . '")';
5019
            $visibilityCondition .= ' OR '.$courseTableAlias.'.code NOT IN ("' . implode('","', $notAllowedCoursesToCurrentUser) . '"))';
5020
        }
5021
5022
        return $visibilityCondition;
5023
    }
5024
5025
    /**
5026
     * Get available le courses count
5027
     * @param int Access URL ID (optional)
5028
     * @param integer $accessUrlId
5029
     * @return int Number of courses
5030
     */
5031
    public static function countAvailableCourses($accessUrlId = null)
5032
    {
5033
        $tableCourse = Database::get_main_table(TABLE_MAIN_COURSE);
5034
        $tableCourseRelAccessUrl = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
5035
        $specialCourseList = self::get_special_course_list();
5036
5037
        $withoutSpecialCourses = '';
5038
        if (!empty($specialCourseList)) {
5039
            $withoutSpecialCourses = ' AND c.code NOT IN ("' . implode('","', $specialCourseList) . '")';
5040
        }
5041
5042
        $visibilityCondition = self::getCourseVisibilitySQLCondition('c');
5043
5044
        if (!empty($accessUrlId) && $accessUrlId == intval($accessUrlId)) {
5045
            $sql = "SELECT count(c.id) FROM $tableCourse c, $tableCourseRelAccessUrl u
5046
                    WHERE
5047
                        c.id = u.c_id AND
5048
                        u.access_url_id = $accessUrlId AND
5049
                        c.visibility != 0 AND
5050
                        c.visibility != 4
5051
                        $withoutSpecialCourses
5052
                        $visibilityCondition
5053
                    ";
5054
        }
5055
        $res = Database::query($sql);
5056
        $row = Database::fetch_row($res);
5057
5058
        return $row[0];
5059
    }
5060
5061
    /**
5062
     * Return a link to go to the course, validating the visibility of the
5063
     * course and the user status
5064
     * @param int User ID
5065
     * @param array Course details array
5066
     * @param array  List of courses to which the user is subscribed (if not provided, will be generated)
5067
     * @param integer $uid
5068
     * @return mixed 'enter' for a link to go to the course or 'register' for a link to subscribe, or false if no access
5069
     */
5070
    static function get_access_link_by_user($uid, $course, $user_courses = array())
5071
    {
5072
        if (empty($uid) or empty($course)) {
5073
            return false;
5074
        }
5075
5076
        if (empty($user_courses)) {
5077
            // get the array of courses to which the user is subscribed
5078
            $user_courses = CourseManager::get_courses_list_by_user_id($uid);
5079
            foreach ($user_courses as $k => $v) {
5080
                $user_courses[$k] = $v['real_id'];
5081
            }
5082
        }
5083
5084
        if (!isset($course['real_id']) && empty($course['real_id'])) {
5085
            $course = api_get_course_info($course['code']);
5086
        }
5087
5088
        if ($course['visibility'] == COURSE_VISIBILITY_HIDDEN) {
5089
            return array();
5090
        }
5091
5092
        $is_admin = api_is_platform_admin_by_id($uid);
5093
        $options = array();
5094
        // Register button
5095
        if (!api_is_anonymous($uid) &&
5096
            (
5097
            ($course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD || $course['visibility'] == COURSE_VISIBILITY_OPEN_PLATFORM)
5098
                //$course['visibility'] == COURSE_VISIBILITY_REGISTERED && $course['subscribe'] == SUBSCRIBE_ALLOWED
5099
            ) &&
5100
            $course['subscribe'] == SUBSCRIBE_ALLOWED &&
5101
            (!in_array($course['real_id'], $user_courses) || empty($user_courses))
5102
        ) {
5103
            $options[] = 'register';
5104
        }
5105
5106
        // Go To Course button (only if admin, if course public or if student already subscribed)
5107 View Code Duplication
        if ($is_admin ||
5108
            $course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD && empty($course['registration_code']) ||
5109
            (api_user_is_login($uid) && $course['visibility'] == COURSE_VISIBILITY_OPEN_PLATFORM && empty($course['registration_code'])) ||
5110
            (in_array($course['real_id'], $user_courses) && $course['visibility'] != COURSE_VISIBILITY_CLOSED)
5111
        ) {
5112
            $options[] = 'enter';
5113
        }
5114
5115 View Code Duplication
        if ($is_admin ||
5116
            $course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD && empty($course['registration_code']) ||
5117
            (api_user_is_login($uid) && $course['visibility'] == COURSE_VISIBILITY_OPEN_PLATFORM && empty($course['registration_code'])) ||
5118
            (in_array($course['real_id'], $user_courses) && $course['visibility'] != COURSE_VISIBILITY_CLOSED)
5119
        ) {
5120
            $options[] = 'enter';
5121
        }
5122
5123
        if ($course['visibility'] != COURSE_VISIBILITY_HIDDEN && empty($course['registration_code']) && $course['unsubscribe'] == UNSUBSCRIBE_ALLOWED && api_user_is_login($uid) && (in_array($course['real_id'],
5124
                $user_courses))
5125
        ) {
5126
            $options[] = 'unsubscribe';
5127
        }
5128
5129
        return $options;
5130
    }
5131
5132
    /**
5133
     * @param array $courseInfo
5134
     * @param array $teachers
5135
     * @param bool $deleteTeachersNotInList
5136
     * @param bool $editTeacherInSessions
5137
     * @param bool $deleteSessionTeacherNotInList
5138
     * @return false|null
5139
     */
5140
    public static function updateTeachers(
5141
        $courseInfo,
5142
        $teachers,
5143
        $deleteTeachersNotInList = true,
5144
        $editTeacherInSessions = false,
5145
        $deleteSessionTeacherNotInList = false,
5146
        $teacherBackup = array()
5147
    ) {
5148
        if (empty($teachers)) {
5149
            return false;
5150
        }
5151
5152
        if (!is_array($teachers)) {
5153
            $teachers = array($teachers);
5154
        }
5155
5156
        if (empty($courseInfo) || !isset($courseInfo['real_id'])) {
5157
            return false;
5158
        }
5159
5160
        $courseId = $courseInfo['real_id'];
5161
        $course_code = $courseInfo['code'];
5162
5163
        $course_user_table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5164
        $alreadyAddedTeachers = CourseManager::get_teacher_list_from_course_code($course_code);
5165
5166
        if ($deleteTeachersNotInList) {
5167
5168
            // Delete only teacher relations that doesn't match the selected teachers
5169
            $cond = null;
5170
            if (count($teachers) > 0) {
5171
                foreach ($teachers as $key) {
5172
                    $key = Database::escape_string($key);
5173
                    $cond .= " AND user_id <> '" . $key . "'";
5174
                }
5175
            }
5176
5177
            $sql = 'DELETE FROM ' . $course_user_table . '
5178
                    WHERE c_id ="' . $courseId . '" AND status="1" AND relation_type = 0 ' . $cond;
5179
            Database::query($sql);
5180
        }
5181
5182
        if (count($teachers) > 0) {
5183
            foreach ($teachers as $userId) {
5184
                $userId = intval($userId);
5185
                // We check if the teacher is already subscribed in this course
5186
                $sql = 'SELECT 1 FROM ' . $course_user_table . '
5187
                        WHERE user_id = "' . $userId . '" AND c_id = "' . $courseId . '" ';
5188
                $result = Database::query($sql);
5189
                if (Database::num_rows($result)) {
5190
                    $sql = 'UPDATE ' . $course_user_table . ' SET status = "1"
5191
                            WHERE c_id = "' . $courseId . '" AND user_id = "' . $userId . '"  ';
5192
                } else {
5193
                    $userCourseCategory = '0';
5194 View Code Duplication
                    if (isset($teacherBackup[$userId]) &&
5195
                        isset($teacherBackup[$userId][$course_code])
5196
                    ) {
5197
                        $courseUserData = $teacherBackup[$userId][$course_code];
5198
                        $userCourseCategory = $courseUserData['user_course_cat'];
5199
                    }
5200
5201
                    $sql = "INSERT INTO " . $course_user_table . " SET
5202
                            c_id = " . $courseId . ",
5203
                            user_id = " . $userId . ",
5204
                            status = '1',
5205
                            is_tutor = '0',
5206
                            sort = '0',
5207
                            relation_type = '0',
5208
                            user_course_cat = '$userCourseCategory'
5209
                    ";
5210
                }
5211
                Database::query($sql);
5212
            }
5213
        }
5214
5215
        if ($editTeacherInSessions) {
5216
            $sessions = SessionManager::get_session_by_course($courseId);
5217
5218
            if (!empty($sessions)) {
5219
                foreach ($sessions as $session) {
5220
                    // Remove old and add new
5221
                    if ($deleteSessionTeacherNotInList) {
5222
                        foreach ($teachers as $userId) {
5223
                            SessionManager::set_coach_to_course_session(
5224
                                $userId,
5225
                                $session['id'],
5226
                                $courseId
5227
                            );
5228
                        }
5229
5230
                        $teachersToDelete = array();
5231
                        if (!empty($alreadyAddedTeachers)) {
5232
                            $teachersToDelete = array_diff(array_keys($alreadyAddedTeachers), $teachers);
5233
                        }
5234
5235
                        if (!empty($teachersToDelete)) {
5236
                            foreach ($teachersToDelete as $userId) {
5237
                                SessionManager::set_coach_to_course_session(
5238
                                    $userId,
5239
                                    $session['id'],
5240
                                    $courseId,
5241
                                    true
5242
                                );
5243
                            }
5244
                        }
5245
                    } else {
5246
                        // Add new teachers only
5247
                        foreach ($teachers as $userId) {
5248
                            SessionManager::set_coach_to_course_session(
5249
                                $userId,
5250
                                $session['id'],
5251
                                $courseId
5252
                            );
5253
                        }
5254
                    }
5255
                }
5256
            }
5257
        }
5258
    }
5259
5260
    /**
5261
     * Course available settings variables see c_course_setting table
5262
     * @param AppPlugin $appPlugin
5263
     * @return array
5264
     */
5265
    public static function getCourseSettingVariables(AppPlugin $appPlugin)
5266
    {
5267
        $pluginCourseSettings = $appPlugin->getAllPluginCourseSettings();
5268
        $courseSettings = array(
5269
            // Get allow_learning_path_theme from table
5270
            'allow_learning_path_theme',
5271
            // Get allow_open_chat_window from table
5272
            'allow_open_chat_window',
5273
            'allow_public_certificates',
5274
            // Get allow_user_edit_agenda from table
5275
            'allow_user_edit_agenda',
5276
            // Get allow_user_edit_announcement from table
5277
            'allow_user_edit_announcement',
5278
            // Get allow_user_image_forum from table
5279
            'allow_user_image_forum',
5280
            //Get allow show user list
5281
            'allow_user_view_user_list',
5282
            // Get course_theme from table
5283
            'course_theme',
5284
            //Get allow show user list
5285
            'display_info_advance_inside_homecourse',
5286
            'documents_default_visibility',
5287
            // Get send_mail_setting (work)from table
5288
            'email_alert_manager_on_new_doc',
5289
            // Get send_mail_setting (work)from table
5290
            'email_alert_manager_on_new_quiz',
5291
            // Get send_mail_setting (dropbox) from table
5292
            'email_alert_on_new_doc_dropbox',
5293
            'email_alert_students_on_new_homework',
5294
            // Get send_mail_setting (auth)from table
5295
            'email_alert_to_teacher_on_new_user_in_course',
5296
            'enable_lp_auto_launch',
5297
            'pdf_export_watermark_text',
5298
            'show_system_folders',
5299
            'exercise_invisible_in_session',
5300
            'enable_forum_auto_launch',
5301
            'show_course_in_user_language'
5302
        );
5303
5304
        $allowLPReturnLink = api_get_setting('allow_lp_return_link');
5305
        if ($allowLPReturnLink === 'true') {
5306
            $courseSettings[] = 'lp_return_link';
5307
        }
5308
5309
        if (!empty($pluginCourseSettings)) {
5310
            $courseSettings = array_merge(
5311
                $courseSettings,
5312
                $pluginCourseSettings
5313
            );
5314
        }
5315
5316
        return $courseSettings;
5317
    }
5318
5319
    /**
5320
     * @param AppPlugin $appPlugin
5321
     * @param string $variable
5322
     * @param string $value
5323
     * @param int $courseId
5324
     * @return bool
5325
     */
5326
    public static function saveCourseConfigurationSetting(AppPlugin $appPlugin, $variable, $value, $courseId)
5327
    {
5328
        $settingList = self::getCourseSettingVariables($appPlugin);
5329
5330
        if (!in_array($variable, $settingList)) {
5331
5332
            return false;
5333
        }
5334
5335
        $courseSettingTable = Database::get_course_table(TABLE_COURSE_SETTING);
5336
        if (self::hasCourseSetting($variable, $courseId)) {
5337
            // Update
5338
            Database::update(
5339
                $courseSettingTable,
5340
                array('value' => $value),
5341
                array('variable = ? AND c_id = ?' => array($variable, $courseId))
5342
            );
5343
        } else {
5344
            // Create
5345
            Database::insert(
5346
                $courseSettingTable,
5347
                ['title' => $variable, 'value' => $value, 'c_id' => $courseId, 'variable' => $variable]
5348
            );
5349
        }
5350
        return true;
5351
    }
5352
5353
    /**
5354
     * Check if course setting exists
5355
     * @param string $variable
5356
     * @param int $courseId
5357
     * @return bool
5358
     */
5359 View Code Duplication
    public static function hasCourseSetting($variable, $courseId)
5360
    {
5361
        $courseSetting = Database::get_course_table(TABLE_COURSE_SETTING);
5362
        $courseId = intval($courseId);
5363
        $variable = Database::escape_string($variable);
5364
        $sql = "SELECT variable FROM $courseSetting
5365
                WHERE c_id = $courseId AND variable = '$variable'";
5366
        $result = Database::query($sql);
5367
5368
        return Database::num_rows($result) > 0;
5369
    }
5370
5371
    /**
5372
     * Get information from the track_e_course_access table
5373
     * @param int $sessionId
5374
     * @param int $userId
5375
     * @return array
5376
     */
5377 View Code Duplication
    public static function getCourseAccessPerSessionAndUser($sessionId, $userId, $limit = null)
5378
    {
5379
        $table = Database:: get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
5380
5381
        $sessionId = intval($sessionId);
5382
        $userId = intval($userId);
5383
5384
        $sql = "SELECT * FROM $table
5385
                WHERE session_id = $sessionId AND user_id = $userId";
5386
5387
        if (!empty($limit)) {
5388
            $limit = intval($limit);
5389
            $sql .= " LIMIT $limit";
5390
        }
5391
        $result = Database::query($sql);
5392
5393
        return Database::store_result($result);
5394
    }
5395
5396
    /**
5397
     * Get information from the track_e_course_access table
5398
     * @param int $courseId
5399
     * @param int $sessionId
5400
     * @param string $startDate
5401
     * @param string $endDate
5402
     * @return array
5403
     */
5404
    public static function getCourseAccessPerCourseAndSession(
5405
        $courseId,
5406
        $sessionId,
5407
        $startDate,
5408
        $endDate
5409
    ) {
5410
        $table = Database:: get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
5411
        $courseId = intval($courseId);
5412
        $sessionId = intval($sessionId);
5413
        $startDate = Database::escape_string($startDate);
5414
        $endDate = Database::escape_string($endDate);
5415
5416
        $sql = "SELECT * FROM $table
5417
                WHERE
5418
                    c_id = $courseId AND
5419
                    session_id = $sessionId AND
5420
                    login_course_date BETWEEN '$startDate' AND '$endDate'
5421
                ";
5422
5423
        $result = Database::query($sql);
5424
5425
        return Database::store_result($result);
5426
    }
5427
5428
    /**
5429
     * Get login information from the track_e_course_access table, for any
5430
     * course in the given session
5431
     * @param int $sessionId
5432
     * @param int $userId
5433
     * @return array
5434
     */
5435
    public static function getFirstCourseAccessPerSessionAndUser($sessionId, $userId)
5436
    {
5437
        $sessionId = intval($sessionId);
5438
        $userId = intval($userId);
5439
5440
        $table = Database:: get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
5441
        $sql = "SELECT * FROM $table
5442
                WHERE session_id = $sessionId AND user_id = $userId
5443
                ORDER BY login_course_date ASC
5444
                LIMIT 1";
5445
5446
        $result = Database::query($sql);
5447
        $courseAccess = array();
5448
        if (Database::num_rows($result)) {
5449
            $courseAccess = Database::fetch_array($result, 'ASSOC');
5450
        }
5451
        return $courseAccess;
5452
    }
5453
5454
    /**
5455
     * @param int $courseId
5456
     * @param int $sessionId
5457
     * @param bool $getAllSessions
5458
     * @return mixed
5459
     */
5460
    public static function getCountForum(
5461
        $courseId,
5462
        $sessionId = 0,
5463
        $getAllSessions = false
5464
    ) {
5465
        $forum = Database::get_course_table(TABLE_FORUM);
5466
        if ($getAllSessions) {
5467
            $sql = "SELECT count(*) as count
5468
                    FROM $forum f
5469
                    WHERE f.c_id = %s";
5470
        } else {
5471
            $sql = "SELECT count(*) as count
5472
                    FROM $forum f
5473
                    WHERE f.c_id = %s and f.session_id = %s";
5474
        }
5475
5476
        $sql = sprintf($sql, intval($courseId), intval($sessionId));
5477
        $result = Database::query($sql);
5478
        $row = Database::fetch_array($result);
5479
5480
        return $row['count'];
5481
    }
5482
5483
    /**
5484
     * @param int $userId
5485
     * @param int $courseId
5486
     * @param int $sessionId
5487
     * @return mixed
5488
     */
5489
    public static function getCountPostInForumPerUser(
5490
        $userId,
5491
        $courseId,
5492
        $sessionId = 0
5493
    ) {
5494
        $forum = Database::get_course_table(TABLE_FORUM);
5495
        $forum_post = Database::get_course_table(TABLE_FORUM_POST);
5496
5497
        $sql = "SELECT count(distinct post_id) as count
5498
                FROM $forum_post p
5499
                INNER JOIN $forum f
5500
                ON f.forum_id = p.forum_id AND f.c_id = p.c_id
5501
                WHERE p.poster_id = %s and f.session_id = %s and p.c_id = %s";
5502
5503
        $sql = sprintf(
5504
            $sql,
5505
            intval($userId),
5506
            intval($sessionId),
5507
            intval($courseId)
5508
        );
5509
5510
        $result = Database::query($sql);
5511
        $row = Database::fetch_array($result);
5512
        return $row['count'];
5513
    }
5514
5515
    /**
5516
     * @param int $userId
5517
     * @param int $courseId
5518
     * @param int $sessionId
5519
     * @return mixed
5520
     */
5521
    public static function getCountForumPerUser(
5522
        $userId,
5523
        $courseId,
5524
        $sessionId = 0
5525
    ) {
5526
        $forum = Database::get_course_table(TABLE_FORUM);
5527
        $forum_post = Database::get_course_table(TABLE_FORUM_POST);
5528
5529
        $sql = "SELECT count(distinct f.forum_id) as count
5530
                FROM $forum_post p
5531
                INNER JOIN $forum f
5532
                ON f.forum_id = p.forum_id AND f.c_id = p.c_id
5533
                WHERE p.poster_id = %s and f.session_id = %s and p.c_id = %s";
5534
5535
        $sql = sprintf(
5536
            $sql,
5537
            intval($userId),
5538
            intval($sessionId),
5539
            intval($courseId)
5540
        );
5541
5542
        $result = Database::query($sql);
5543
        $row = Database::fetch_array($result);
5544
        return $row['count'];
5545
    }
5546
5547
    /**
5548
     * Returns the course name from a given code
5549
     * @param string $code
5550
     */
5551 View Code Duplication
    public static function getCourseNameFromCode($code)
5552
    {
5553
        $tbl_main_categories = Database:: get_main_table(TABLE_MAIN_COURSE);
5554
        $sql = 'SELECT title
5555
                FROM ' . $tbl_main_categories . '
5556
                WHERE code = "' . Database::escape_string($code) . '"';
5557
        $result = Database::query($sql);
5558
        if ($col = Database::fetch_array($result)) {
5559
            return $col['title'];
5560
        }
5561
    }
5562
5563
    /**
5564
     * Generates a course code from a course title
5565
     * @todo Such a function might be useful in other places too. It might be moved in the CourseManager class.
5566
     * @todo the function might be upgraded for avoiding code duplications (currently, it might suggest a code that is already in use)
5567
     * @param string $title A course title
5568
     * @return string A proposed course code
5569
     * +
5570
     * @assert (null,null) === false
5571
     * @assert ('ABC_DEF', null) === 'ABCDEF'
5572
     * @assert ('ABC09*^[%A', null) === 'ABC09A'
5573
     */
5574
    public static function generate_course_code($title)
5575
    {
5576
        return substr(
5577
            preg_replace('/[^A-Z0-9]/', '', strtoupper(api_replace_dangerous_char($title))),
5578
            0,
5579
            CourseManager::MAX_COURSE_LENGTH_CODE
5580
        );
5581
    }
5582
5583
    /**
5584
     * @param $courseId
5585
     * @return array
5586
     */
5587
    public static function getCourseSettings($courseId)
5588
    {
5589
        $settingTable = Database::get_course_table(TABLE_COURSE_SETTING);
5590
        $courseId = intval($courseId);
5591
        $sql = "SELECT * FROM $settingTable WHERE c_id = $courseId";
5592
        $result = Database::query($sql);
5593
        $settings = array();
5594
        if (Database::num_rows($result)) {
5595
            while ($row = Database::fetch_array($result, 'ASSOC')) {
5596
                $settings[$row['variable']] = $row;
5597
            }
5598
        }
5599
        return $settings;
5600
    }
5601
5602
    /**
5603
     * this function gets all the users of the course,
5604
     * including users from linked courses
5605
     */
5606 View Code Duplication
    public static function getCourseUsers()
5607
    {
5608
        //this would return only the users from real courses:
5609
        $session_id = api_get_session_id();
5610
        if ($session_id != 0) {
5611
            $user_list = self::get_real_and_linked_user_list(api_get_course_id(), true, $session_id);
5612
        } else {
5613
            $user_list = self::get_real_and_linked_user_list(api_get_course_id(), false, 0);
5614
        }
5615
5616
        return $user_list;
5617
    }
5618
5619
    /**
5620
     * this function gets all the groups of the course,
5621
     * not including linked courses
5622
     */
5623 View Code Duplication
    public static function getCourseGroups()
5624
    {
5625
        $session_id = api_get_session_id();
5626
        if ($session_id != 0) {
5627
            $new_group_list = self::get_group_list_of_course(api_get_course_id(), $session_id, 1);
5628
        } else {
5629
            $new_group_list = self::get_group_list_of_course(api_get_course_id(), 0, 1);
5630
        }
5631
5632
        return $new_group_list;
5633
    }
5634
5635
    /**
5636
     * @param FormValidator $form
5637
     * @param array $to_already_selected
5638
     *
5639
     * @return HTML_QuickForm_element
5640
     */
5641 View Code Duplication
    public static function addUserGroupMultiSelect(&$form, $to_already_selected)
5642
    {
5643
        $user_list = self::getCourseUsers();
5644
        $group_list = self::getCourseGroups();
5645
        $array = self::buildSelectOptions($group_list, $user_list, $to_already_selected);
5646
5647
        $result = array();
5648
        foreach ($array as $content) {
5649
            $result[$content['value']] = $content['content'];
5650
        }
5651
5652
        return $form->addElement(
5653
            'advmultiselect',
5654
            'users',
5655
            get_lang('Users'),
5656
            $result,
5657
            array('select_all_checkbox' => true)
5658
        );
5659
    }
5660
5661
    /**
5662
     * This function separates the users from the groups
5663
     * users have a value USER:XXX (with XXX the groups id have a value
5664
     *  GROUP:YYY (with YYY the group id)
5665
     * @param  array $to Array of strings that define the type and id of each destination
5666
     * @return array Array of groups and users (each an array of IDs)
5667
     */
5668
    public static function separateUsersGroups($to)
5669
    {
5670
        $grouplist = array();
5671
        $userlist = array();
5672
5673
        foreach ($to as $to_item) {
5674
            if (!empty($to_item)) {
5675
                $parts = explode(':', $to_item);
5676
                $type = isset($parts[0]) ? $parts[0] : '';
5677
                $id = isset($parts[1]) ? $parts[1] : '';
5678
5679
                switch ($type) {
5680
                    case 'GROUP':
5681
                        $grouplist[] = intval($id);
5682
                        break;
5683
                    case 'USER':
5684
                        $userlist[] = intval($id);
5685
                        break;
5686
                }
5687
            }
5688
        }
5689
5690
        $send_to['groups'] = $grouplist;
5691
        $send_to['users'] = $userlist;
5692
5693
        return $send_to;
5694
    }
5695
5696
    /**
5697
     * Shows the form for sending a message to a specific group or user.
5698
     * @param FormValidator $form
5699
     * @param int $group_id iid
5700
     * @param array $to
5701
     */
5702 View Code Duplication
    public static function addGroupMultiSelect($form, $group_id, $to = array())
5703
    {
5704
        $group_users = GroupManager::get_subscribed_users($group_id);
5705
        $array = self::buildSelectOptions(null, $group_users, $to);
5706
5707
        $result = array();
5708
        foreach ($array as $content) {
5709
            $result[$content['value']] = $content['content'];
5710
        }
5711
5712
        return $form->addElement('advmultiselect', 'users', get_lang('Users'), $result);
5713
    }
5714
5715
    /**
5716
     * this function shows the form for sending a message to a specific group or user.
5717
     * @param array $group_list
5718
     * @param array $user_list
5719
     * @param array $to_already_selected
5720
     * @return array
5721
     */
5722
    public static function buildSelectOptions(
5723
        $group_list = array(),
5724
        $user_list = array(),
5725
        $to_already_selected = array()
5726
    ) {
5727
        if (empty($to_already_selected)) {
5728
            $to_already_selected = array();
5729
        }
5730
5731
        $result = array();
5732
        // adding the groups to the select form
5733
        if ($group_list) {
5734
            foreach ($group_list as $this_group) {
5735
                if (is_array($to_already_selected)) {
5736
                    if (!in_array(
5737
                        "GROUP:" . $this_group['id'],
5738
                        $to_already_selected
5739
                    )
5740
                    ) { // $to_already_selected is the array containing the groups (and users) that are already selected
5741
                        $user_label = ($this_group['userNb'] > 0) ? get_lang('Users') : get_lang('LowerCaseUser');
5742
                        $user_disabled = ($this_group['userNb'] > 0) ? "" : "disabled=disabled";
5743
                        $result[] = array(
5744
                            'disabled' => $user_disabled,
5745
                            'value' => "GROUP:" . $this_group['id'],
5746
                            'content' => "G: " . $this_group['name'] . " - " . $this_group['userNb'] . " " . $user_label
5747
                        );
5748
                    }
5749
                }
5750
            }
5751
        }
5752
5753
        // adding the individual users to the select form
5754
        if ($user_list) {
5755
            foreach ($user_list as $user) {
5756
                if (is_array($to_already_selected)) {
5757
                    if (!in_array(
5758
                        "USER:" . $user['user_id'],
5759
                        $to_already_selected
5760
                    )
5761
                    ) { // $to_already_selected is the array containing the users (and groups) that are already selected
5762
5763
                        $result[] = array(
5764
                            'value' => "USER:" . $user['user_id'],
5765
                            'content' => api_get_person_name($user['firstname'], $user['lastname'])
5766
                        );
5767
                    }
5768
                }
5769
            }
5770
        }
5771
5772
        return $result;
5773
    }
5774
5775
    /**
5776
     * @return array a list (array) of all courses.
5777
     */
5778
    public static function get_course_list()
5779
    {
5780
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
5781
        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...
5782
    }
5783
5784
    /**
5785
     * Returns course code from a given gradebook category's id
5786
     * @param int  Category ID
5787
     * @return string  Course code
5788
     */
5789 View Code Duplication
    public static function get_course_by_category($category_id)
5790
    {
5791
        $category_id = intval($category_id);
5792
        $info = Database::fetch_array(
5793
            Database::query('SELECT course_code 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...
5794
            WHERE id=' . $category_id), 'ASSOC'
5795
        );
5796
        return $info ? $info['course_code'] : false;
5797
    }
5798
5799
    /**
5800
     * This function gets all the courses that are not in a session
5801
     * @param date Start date
5802
     * @param date End date
5803
     * @param   bool    $includeClosed Whether to include closed and hidden courses
5804
     * @return array Not-in-session courses
5805
     */
5806
    public static function getCoursesWithoutSession($startDate = null, $endDate = null, $includeClosed = false)
5807
    {
5808
        $dateConditional = ($startDate && $endDate) ?
5809
            " WHERE session_id IN (SELECT id FROM " . Database::get_main_table(TABLE_MAIN_SESSION) .
5810
            " WHERE access_start_date = '$startDate' AND access_end_date = '$endDate')" :
5811
            null;
5812
        $visibility = ($includeClosed ? '' : 'visibility NOT IN (0, 4) AND ');
5813
5814
        $query = "SELECT id, code, title
5815
                FROM " . Database::get_main_table(TABLE_MAIN_COURSE). "
5816
                WHERE $visibility code NOT IN (
5817
                    SELECT DISTINCT course_code FROM " . Database::get_main_table(TABLE_MAIN_SESSION_COURSE) . $dateConditional . ")
5818
                ORDER BY id";
5819
5820
        $result = Database::query($query);
5821
        $courses = array();
5822
        while ($row = Database::fetch_array($result)) {
5823
            $courses[] = $row;
5824
        }
5825
        return $courses;
5826
    }
5827
5828
    /**
5829
     * Get list of courses based on users of a group for a group admin
5830
     * @param int $userId The user id
5831
     * @return array
5832
     */
5833 View Code Duplication
    public static function getCoursesFollowedByGroupAdmin($userId)
5834
    {
5835
        $coursesList = [];
5836
5837
        $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
5838
        $courseUserTable = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5839
        $userGroup = new UserGroup();
5840
        $userIdList = $userGroup->getGroupUsersByUser($userId);
5841
5842
        if (empty($userIdList)) {
5843
            return [];
5844
        }
5845
5846
        $sql = "SELECT DISTINCT(c.id), c.title
5847
                FROM $courseTable c
5848
                INNER JOIN $courseUserTable cru ON c.id = cru.c_id
5849
                WHERE (
5850
                    cru.user_id IN (" . implode(', ', $userIdList) . ")
5851
                    AND cru.relation_type = 0
5852
                )";
5853
5854
        if (api_is_multiple_url_enabled()) {
5855
            $courseAccessUrlTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
5856
            $accessUrlId = api_get_current_access_url_id();
5857
5858
            if ($accessUrlId != -1) {
5859
                $sql = "SELECT DISTINCT(c.id), c.title
5860
                        FROM $courseTable c
5861
                        INNER JOIN $courseUserTable cru ON c.id = cru.c_id
5862
                        INNER JOIN $courseAccessUrlTable crau ON c.id = crau.c_id
5863
                        WHERE crau.access_url_id = $accessUrlId
5864
                            AND (
5865
                            cru.id_user IN (" . implode(', ', $userIdList) . ") AND
5866
                            cru.relation_type = 0
5867
                        )";
5868
            }
5869
        }
5870
5871
        $result = Database::query($sql);
5872
5873
        while ($row = Database::fetch_assoc($result)) {
5874
            $coursesList[] = $row;
5875
        }
5876
5877
        return $coursesList;
5878
    }
5879
5880
    /**
5881
     * Direct course link see #5299
5882
     *
5883
     * You can send to your students an URL like this
5884
     * http://chamilodev.beeznest.com/main/auth/inscription.php?c=ABC&e=3
5885
     * Where "c" is the course code and "e" is the exercise Id, after a successful
5886
     * registration the user will be sent to the course or exercise
5887
     *
5888
     */
5889
    public static function redirectToCourse($form_data)
5890
    {
5891
        $course_code_redirect = Session::read('course_redirect');
5892
        $_user = api_get_user_info();
5893
        $user_id = api_get_user_id();
5894
5895
        if (!empty($course_code_redirect)) {
5896
            $course_info = api_get_course_info($course_code_redirect);
5897
            if (!empty($course_info)) {
5898
                if (in_array($course_info['visibility'],
5899
                    array(COURSE_VISIBILITY_OPEN_PLATFORM, COURSE_VISIBILITY_OPEN_WORLD))
5900
                ) {
5901
                    if (CourseManager::is_user_subscribed_in_course($user_id, $course_info['code'])) {
5902
5903
                        $form_data['action'] = $course_info['course_public_url'];
5904
                        $form_data['message'] = sprintf(get_lang('YouHaveBeenRegisteredToCourseX'), $course_info['title']);
5905
                        $form_data['button'] = Display::button(
5906
                            'next',
5907
                            get_lang('GoToCourse', null, $_user['language']),
5908
                            array('class' => 'btn btn-primary btn-large')
5909
                        );
5910
5911
                        $exercise_redirect = intval(Session::read('exercise_redirect'));
5912
                        // Specify the course id as the current context does not
5913
                        // hold a global $_course array
5914
                        $objExercise = new Exercise($course_info['real_id']);
5915
                        $result = $objExercise->read($exercise_redirect);
5916
5917
                        if (!empty($exercise_redirect) && !empty($result)) {
5918
                            $form_data['action'] = api_get_path(WEB_CODE_PATH) . 'exercise/overview.php?exerciseId='.$exercise_redirect.'&cidReq='.$course_info['code'];
5919
                            $form_data['message'] .= '<br />'.get_lang('YouCanAccessTheExercise');
5920
                            $form_data['button'] = Display::button(
5921
                                'next',
5922
                                get_lang('Go', null, $_user['language']),
5923
                                array('class' => 'btn btn-primary btn-large')
5924
                            );
5925
                        }
5926
5927
                        if (!empty($form_data['action'])) {
5928
                            header('Location: '.$form_data['action']);
5929
                            exit;
5930
                        }
5931
                    }
5932
                }
5933
            }
5934
        }
5935
5936
        return $form_data;
5937
    }
5938
5939
    /**
5940
     * return html code for displaying a course title in the standard view (not the Session view)
5941
     * @param $courseId
5942
     * @param bool $loadDirs
5943
     * @return string
5944
     */
5945
    public static function displayCourseHtml($courseId, $loadDirs = false)
5946
    {
5947
        $params = self::getCourseParamsForDisplay($courseId, $loadDirs);
5948
        $html = self::course_item_html($params, false);
0 ignored issues
show
Bug introduced by
The method course_item_html() does not exist on CourseManager. Did you maybe mean course_item_html_no_icon()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
5949
5950
        return $html;
5951
    }
5952
5953
    /**
5954
     * Return tab of params to display a course title in the My Courses tab
5955
     * Check visibility, right, and notification icons, and load_dirs option
5956
     * @param $courseId
5957
     * @param bool $loadDirs
5958
     * @return array
5959
     */
5960
    public static function getCourseParamsForDisplay($courseId, $loadDirs = false)
5961
    {
5962
        $user_id = api_get_user_id();
5963
        // Table definitions
5964
        $TABLECOURS = Database :: get_main_table(TABLE_MAIN_COURSE);
5965
        $TABLECOURSUSER = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
5966
        $TABLE_ACCESS_URL_REL_COURSE = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
5967
        $current_url_id = api_get_current_access_url_id();
5968
5969
        // Get course list auto-register
5970
        $special_course_list = self::get_special_course_list();
5971
5972
        $without_special_courses = '';
5973
        if (!empty($special_course_list)) {
5974
            $without_special_courses = ' AND course.code NOT IN ("'.implode('","',$special_course_list).'")';
5975
        }
5976
5977
        //AND course_rel_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
5978
        $sql = "SELECT 
5979
                    course.id, 
5980
                    course.title, 
5981
                    course.code, 
5982
                    course.subscribe subscr, 
5983
                    course.unsubscribe unsubscr, 
5984
                    course_rel_user.status status,
5985
                    course_rel_user.sort sort, 
5986
                    course_rel_user.user_course_cat user_course_cat
5987
                FROM
5988
                $TABLECOURS course,
5989
                $TABLECOURSUSER course_rel_user, 
5990
                $TABLE_ACCESS_URL_REL_COURSE url
5991
                WHERE
5992
                    course.id=".intval($courseId)." AND
5993
                    course.id = course_rel_user.c_id AND
5994
                    url.c_id = course.id AND
5995
                    course_rel_user.user_id = ".intval($user_id)."
5996
                    $without_special_courses
5997
                ";
5998
5999
        // If multiple URL access mode is enabled, only fetch courses
6000
        // corresponding to the current URL.
6001
        if (api_get_multiple_access_url() && $current_url_id != -1) {
6002
            $sql .= " AND url.course_code=course.code AND access_url_id=".intval($current_url_id);
6003
        }
6004
        // Use user's classification for courses (if any).
6005
        $sql .= " ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
6006
6007
        $result = Database::query($sql);
6008
6009
        // Browse through all courses. We can only have one course because
6010
        // of the  course.id=".intval($courseId) in sql query
6011
        $course = Database::fetch_array($result);
6012
        $course_info = api_get_course_info_by_id($courseId);
6013
        if (empty($course_info)) {
6014
            return '';
6015
        }
6016
6017
        //$course['id_session'] = null;
6018
        $course_info['id_session'] = null;
6019
        $course_info['status'] = $course['status'];
6020
6021
        // For each course, get if there is any notification icon to show
6022
        // (something that would have changed since the user's last visit).
6023
        $show_notification = Display::show_notification($course_info);
6024
6025
        // New code displaying the user's status in respect to this course.
6026
        $status_icon = Display::return_icon(
6027
            'blackboard.png',
6028
            $course_info['title'],
6029
            array(),
6030
            ICON_SIZE_LARGE
6031
        );
6032
6033
        $params = array();
6034
        $params['right_actions'] = '';
6035
6036
        if (api_is_platform_admin()) {
6037 View Code Duplication
            if ($loadDirs) {
6038
                $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>';
6039
                $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>';
6040
                $params['right_actions'] .= Display::div('', array('id' => 'document_result_'.$course_info['real_id'].'_0', 'class'=>'document_preview_container'));
6041
            } else {
6042
                $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>';
6043
            }
6044
6045
            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...
6046
                //echo Display::return_icon('teachers.gif', get_lang('Status').': '.get_lang('Teacher'), array('style'=>'width: 11px; height: 11px;'));
6047
            }
6048
        } else {
6049
            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
6050 View Code Duplication
                if ($loadDirs) {
6051
                    $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>';
6052
                    $params['right_actions'] .= Display::div('', array('id' => 'document_result_'.$course_info['real_id'].'_0', 'class'=>'document_preview_container'));
6053
                } else {
6054
                    if ($course_info['status'] == COURSEMANAGER) {
6055
                        $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>';
6056
                    }
6057
                }
6058
            }
6059
        }
6060
6061
        $course_title_url = '';
6062 View Code Duplication
        if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED || $course['status'] == COURSEMANAGER) {
6063
            $course_title_url = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/?id_session=0';
6064
            $course_title = Display::url($course_info['title'], $course_title_url);
6065
        } else {
6066
            $course_title = $course_info['title'].' '.Display::tag('span',get_lang('CourseClosed'), array('class'=>'item_closed'));
6067
        }
6068
6069
        // Start displaying the course block itself
6070
        if (api_get_setting('display_coursecode_in_courselist') === 'true') {
6071
            $course_title .= ' ('.$course_info['visual_code'].') ';
6072
        }
6073
        $teachers = '';
6074
        if (api_get_setting('display_teacher_in_courselist') === 'true') {
6075
            $teachers = CourseManager::get_teacher_list_from_course_code_to_string($course['code'], self::USER_SEPARATOR, true);
6076
        }
6077
        $params['link'] = $course_title_url;
6078
        $params['icon'] = $status_icon;
6079
        $params['title'] = $course_title;
6080
        $params['teachers'] = $teachers;
6081
        if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
6082
            $params['notifications'] = $show_notification;
6083
        }
6084
6085
        return $params;
6086
    }
6087
6088
    /**
6089
     * @param int $user_id
6090
     * @param $filter
6091
     * @param bool $load_dirs
6092
     * @param int $getCount
6093
     * @param int $start
6094
     * @param null $maxPerPage
6095
     * @return null|string
6096
     */
6097
    public static function displayCourses($user_id, $filter, $load_dirs, $getCount, $start = null, $maxPerPage = null)
6098
    {
6099
        // Table definitions
6100
        $TABLECOURS                     = Database :: get_main_table(TABLE_MAIN_COURSE);
6101
        $TABLECOURSUSER                 = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
6102
        $TABLE_ACCESS_URL_REL_COURSE    = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
6103
        $current_url_id                 = api_get_current_access_url_id();
6104
6105
        // Get course list auto-register
6106
        $special_course_list            = self::get_special_course_list();
6107
6108
        $without_special_courses = '';
6109
6110
        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...
6111
            //$without_special_courses = ' AND course.code NOT IN ("'.implode('","',$special_course_list).'")';
6112
        }
6113
6114
        $select = " SELECT DISTINCT
6115
                    course.id,
6116
                    course.title,
6117
                    course.code,
6118
                    course.subscribe subscr,
6119
                    course.unsubscribe unsubscr,
6120
                    course_rel_user.status status,
6121
                    course_rel_user.sort sort,
6122
                    course_rel_user.user_course_cat user_course_cat,
6123
                    course.id as real_id
6124
        ";
6125
6126
        $from = "$TABLECOURS course, $TABLECOURSUSER  course_rel_user, $TABLE_ACCESS_URL_REL_COURSE url ";
6127
6128
        $where = "  course.id = course_rel_user.c_id AND
6129
                    url.c_id = course.id AND
6130
                    course_rel_user.user_id = '".$user_id."' AND
6131
                    course_rel_user.user_course_cat = 0
6132
                    ";
6133
6134
        $order = " ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
6135
6136
6137
        if ($getCount) {
6138
            $select = "SELECT count(course.id) as total";
6139
        }
6140
6141
        $sql = "$select FROM $from WHERE $where $without_special_courses ";
6142
6143
        // corresponding to the current URL.
6144
        if (api_get_multiple_access_url() && $current_url_id != -1) {
6145
            $sql .= " AND url.c_id = course.id AND access_url_id='".$current_url_id."'";
6146
        }
6147
6148
        $sql .= $order;
6149
6150 View Code Duplication
        if (isset($start) && isset($maxPerPage)) {
6151
            $start = intval($start);
6152
            $maxPerPage = intval($maxPerPage);
6153
            $limitCondition = " LIMIT $start, $maxPerPage";
6154
            $sql .= $limitCondition;
6155
        }
6156
6157 View Code Duplication
        if ($getCount) {
6158
            $result = Database::query($sql);
6159
            $row = Database::fetch_array($result);
6160
            return $row['total'];
6161
        }
6162
        $result = Database::query($sql);
6163
6164
        $html = null;
6165
        $course_list = array();
6166
6167
        // Browse through all courses.
6168
        while ($course = Database::fetch_array($result)) {
6169
            $course_info = api_get_course_info($course['code']);
6170
            $course_info['id_session'] = null;
6171
            $course_info['status'] = $course['status'];
6172
6173
            //In order to avoid doubles
6174
            if (in_array($course_info['real_id'], $course_list)) {
6175
                continue;
6176
            } else {
6177
                $course_list[] = $course_info['real_id'];
6178
            }
6179
6180
            // For each course, get if there is any notification icon to show
6181
            // (something that would have changed since the user's last visit).
6182
            $show_notification = Display :: show_notification($course_info);
6183
6184
            // New code displaying the user's status in respect to this course.
6185
            $status_icon = Display::return_icon('blackboard.png', $course_info['title'], array(), ICON_SIZE_LARGE);
6186
6187
            $params = array();
6188
            $params['right_actions'] = '';
6189
6190
            if (api_is_platform_admin()) {
6191 View Code Duplication
                if ($load_dirs) {
6192
                    $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>';
6193
                    $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>';
6194
                    $params['right_actions'] .= Display::div('', array('id' => 'document_result_'.$course_info['real_id'].'_0', 'class'=>'document_preview_container'));
6195
                } else {
6196
                    $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>';
6197
                }
6198
6199
                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...
6200
                    //echo Display::return_icon('teachers.gif', get_lang('Status').': '.get_lang('Teacher'), array('style'=>'width: 11px; height: 11px;'));
6201
                }
6202 View Code Duplication
            } else {
6203
                if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
6204
                    if ($load_dirs) {
6205
                        $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>';
6206
                        $params['right_actions'] .= Display::div('', array('id' => 'document_result_'.$course_info['real_id'].'_0', 'class'=>'document_preview_container'));
6207
                    } else {
6208
                        if ($course_info['status'] == COURSEMANAGER) {
6209
                            $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>';
6210
                        }
6211
                    }
6212
                }
6213
            }
6214
6215
            $course_title_url = '';
6216 View Code Duplication
            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED || $course['status'] == COURSEMANAGER) {
6217
                //$course_title_url = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/index.php?id_session=0';
6218
                $course_title_url = api_get_path(WEB_COURSE_PATH).$course_info['code'].'/index.php?id_session=0';
6219
                $course_title = Display::url($course_info['title'], $course_title_url);
6220
            } else {
6221
                $course_title = $course_info['title']." ".Display::tag('span',get_lang('CourseClosed'), array('class'=>'item_closed'));
6222
            }
6223
6224
            // Start displaying the course block itself
6225
            if (api_get_setting('course.display_coursecode_in_courselist') == 'true') {
6226
                $course_title .= ' ('.$course_info['visual_code'].') ';
6227
            }
6228
            $teachers = null;
6229
            if (api_get_setting('course.display_teacher_in_courselist') == 'true') {
6230
                $teachers = $course_info['teacher_list_formatted'];
6231
            }
6232
6233
            $params['link'] = $course_title_url;
6234
            $params['icon'] = $status_icon;
6235
            $params['title'] = $course_title;
6236
            $params['teachers'] = $teachers;
6237
6238
            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
6239
                $params['notifications'] = $show_notification;
6240
            }
6241
6242
            $is_subcontent = true;
6243
            if (empty($user_category_id)) {
6244
                $is_subcontent = false;
6245
            }
6246
            $html .= self::course_item_html($params, $is_subcontent);
0 ignored issues
show
Bug introduced by
The method course_item_html() does not exist on CourseManager. Did you maybe mean course_item_html_no_icon()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
6247
        }
6248
        return $html;
6249
    }
6250
6251
    /**
6252
     * Get the course id based on the original id and field name in the extra fields.
6253
     * Returns 0 if course was not found
6254
     *
6255
     * @param string $original_course_id_value Original course id
6256
     * @param string $original_course_id_name Original field name
6257
     * @return int Course id
6258
     */
6259
    public static function get_course_id_from_original_id($original_course_id_value, $original_course_id_name)
6260
    {
6261
        $extraFieldValue = new ExtraFieldValue('course');
6262
        $value = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
6263
            $original_course_id_name,
6264
            $original_course_id_value
6265
        );
6266
6267
        if ($value) {
6268
            return $value['item_id'];
6269
        }
6270
        return 0;
6271
    }
6272
6273
    /**
6274
     * Helper function to create a default gradebook (if necessary) upon course creation
6275
     * @param   int     $modelId    The gradebook model ID
6276
     * @param   string  $courseCode Course code
6277
     * @return  void
6278
     */
6279
    public static function createDefaultGradebook($modelId, $courseCode)
6280
    {
6281
        if (api_get_setting('gradebook_enable_grade_model') === 'true') {
6282
            //Create gradebook_category for the new course and add
6283
            // a gradebook model for the course
6284
            if (isset($modelId) &&
6285
                !empty($modelId) &&
6286
                $modelId != '-1'
6287
            ) {
6288
                GradebookUtils::create_default_course_gradebook(
6289
                    $courseCode,
6290
                    $modelId
6291
                );
6292
            }
6293
        }
6294
    }
6295
6296
    /**
6297
     * Helper function to check if there is a course template and, if so, to
6298
     * copy the template as basis for the new course
6299
     * @param   string  $courseCode   Course code
6300
     * @param   int     $courseTemplate 0 if no course template is defined
6301
     */
6302
    public static function useTemplateAsBasisIfRequired($courseCode, $courseTemplate)
6303
    {
6304
        $template = api_get_setting('course_creation_use_template');
6305
        $teacherCanSelectCourseTemplate = api_get_setting('teacher_can_select_course_template') === 'true';
6306
        $courseTemplate = isset($courseTemplate) ? intval($courseTemplate) : 0;
6307
6308
        $useTemplate = false;
6309
6310
        if ($teacherCanSelectCourseTemplate && $courseTemplate) {
6311
            $useTemplate = true;
6312
            $originCourse = api_get_course_info_by_id($courseTemplate);
6313
        } elseif (!empty($template)) {
6314
            $useTemplate = true;
6315
            $originCourse = api_get_course_info_by_id($template);
6316
        }
6317
6318
        if ($useTemplate) {
6319
            // Include the necessary libraries to generate a course copy
6320
            // Call the course copy object
6321
            $originCourse['official_code'] = $originCourse['code'];
6322
            $cb = new CourseBuilder(null, $originCourse);
6323
            $course = $cb->build(null, $originCourse['code']);
6324
            $cr = new CourseRestorer($course);
6325
            $cr->set_file_option();
6326
            $cr->restore($courseCode);
6327
        }
6328
    }
6329
6330
    /**
6331
     * Helper method to get the number of users defined with a specific course extra field
6332
     * @param   string  $name   Field title
6333
     * @param   string  $tableExtraFields The extra fields table name
6334
     * @param   string  $tableUserFieldValues The user extra field value table name
6335
     * @return  int     The number of users with this extra field with a specific value
6336
     */
6337
    public static function getCountRegisteredUsersWithCourseExtraField($name, $tableExtraFields = '', $tableUserFieldValues = '')
6338
    {
6339
        if (empty($tableExtraFields)) {
6340
            $tableExtraFields = Database::get_main_table(TABLE_EXTRA_FIELD);
6341
        }
6342
        if (empty($tableUserFieldValues)) {
6343
            $tableUserFieldValues = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
6344
        }
6345
6346
        $registered_users_with_extra_field = 0;
6347
6348
        if (!empty($name) && $name != '-') {
6349
            $extraFieldType = EntityExtraField::COURSE_FIELD_TYPE;
6350
            $name = Database::escape_string($name);
6351
            $sql = "SELECT count(v.item_id) as count
6352
                    FROM $tableUserFieldValues v 
6353
                    INNER JOIN $tableExtraFields f
6354
                    ON (f.id = v.field_id)
6355
                    WHERE value = '$name' AND extra_field_type = $extraFieldType";
6356
            $result_count = Database::query($sql);
6357
            if (Database::num_rows($result_count)) {
6358
                $row_count = Database::fetch_array($result_count);
6359
                $registered_users_with_extra_field = $row_count['count'];
6360
            }
6361
        }
6362
6363
        return $registered_users_with_extra_field;
6364
    }
6365
6366
    /**
6367
     * Check if a specific access-url-related setting is a problem or not
6368
     * @param array $_configuration The $_configuration array
6369
     * @param int $accessUrlId The access URL ID
6370
     * @param string $param
6371
     * @param string $msgLabel
6372
     * @return bool|string
6373
     */
6374
    private static function checkCreateCourseAccessUrlParam($_configuration, $accessUrlId, $param, $msgLabel)
6375
    {
6376
        if (isset($_configuration[$accessUrlId][$param]) && $_configuration[$accessUrlId][$param] > 0) {
6377
            $num = self::count_courses($accessUrlId);
6378
            if ($num >= $_configuration[$accessUrlId][$param]) {
6379
                api_warn_hosting_contact($param);
6380
6381
                Display::addFlash(
6382
                    Display::return_message($msgLabel)
6383
                );
6384
            }
6385
        }
6386
        return false;
6387
    }
6388
    /**
6389
     * Fill course with all necessary items
6390
     * @param array $courseInfo Course info array
6391
     * @param array $params Parameters from the course creation form
6392
     * @param int $authorId
6393
     * @return void
6394
     */
6395
    private static function fillCourse($courseInfo, $params, $authorId = 0)
6396
    {
6397
        $authorId = empty($authorId) ? api_get_user_id() : (int) $authorId;
6398
6399
        AddCourse::prepare_course_repository($courseInfo['directory'], $courseInfo['code']);
6400
        AddCourse::fill_db_course(
6401
            $courseInfo['real_id'],
6402
            $courseInfo['directory'],
6403
            $courseInfo['course_language'],
6404
            $params['exemplary_content'],
6405
            $authorId
6406
        );
6407
6408
        if (isset($params['gradebook_model_id'])) {
6409
            CourseManager::createDefaultGradebook($params['gradebook_model_id'], $courseInfo['code']);
6410
        }
6411
        // If parameter defined, copy the contents from a specific
6412
        // template course into this new course
6413
        if (isset($params['course_template'])) {
6414
            CourseManager::useTemplateAsBasisIfRequired($courseInfo['id'], $params['course_template']);
6415
        }
6416
        $params['course_code'] = $courseInfo['code'];
6417
        $params['item_id'] = $courseInfo['real_id'];
6418
6419
        $courseFieldValue = new ExtraFieldValue('course');
6420
        $courseFieldValue->saveFieldValues($params);
6421
    }
6422
6423
    /**
6424
     * @param ToolChain $toolList
6425
     */
6426
    public static function setToolList($toolList)
6427
    {
6428
        self::$toolList = $toolList;
6429
    }
6430
6431
    /**
6432
     * @return ToolChain
6433
     */
6434
    public static function getToolList()
6435
    {
6436
        return self::$toolList;
6437
    }
6438
}
6439