Completed
Push — master ( 182694...823694 )
by Julito
92:43 queued 58:19
created

CourseManager::course_item_html()   F

Complexity

Conditions 13
Paths 768

Size

Total Lines 64
Code Lines 48

Duplication

Lines 5
Ratio 7.81 %

Importance

Changes 0
Metric Value
cc 13
eloc 48
nc 768
nop 2
dl 5
loc 64
rs 3.125
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 View Code Duplication
        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 View Code Duplication
        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
     * Builds the course block in user_portal.php
3482
     * @todo use Twig
3483
     * @param array $params
3484
     * @param bool|false $is_sub_content
3485
     * @return string
3486
     */
3487
    public static function course_item_html($params, $is_sub_content = false)
3488
    {
3489
        $html = '';
3490
        $class = "panel panel-default";
3491
        if ($is_sub_content) {
3492
            $class = "course_item";
3493
        }
3494
        $html .= '<div class="' . $class . '">';
3495
        $html .= '<div class="panel-body">';
3496
        $html .= '<div class="course-items">';
3497
        $html .= ' <div class="row">';
3498
        $html .= '<div class="col-md-2">';
3499
        if (!empty($params['link'])) {
3500
            $html .= '<a class="thumbnail" href="' . $params['link'] . '">';
3501
            $html .= $params['icon'];
3502
            $html .= '</a>';
3503
        } else {
3504
            $html .= '<div class="thumbnail">';
3505
            $html .= $params['icon'];
3506
            $html .= '</div>';
3507
        }
3508
        $html .= '</div>';
3509
        $notifications = isset($params['notifications']) ? $params['notifications'] : '';
3510
        $param_class = isset($params['class']) ? $params['class'] : '';
3511
        $params['right_actions'] = isset($params['right_actions']) ? $params['right_actions'] : '';
3512
3513
        $html .= '<div class="col-md-10 ' . $param_class . '">';
3514
        $html .= '<div class="pull-right">' . $params['right_actions'] . '</div>';
3515
        $html .= '<h4 class="course-items-title">' . $params['title'] . $notifications . '</h4> ';
3516
3517
        if (isset($params['show_description'], $params['description']) && $params['show_description'] == 1) {
3518
            $html .= '<p class="description-session">' . $params['description'] . '</p>';
3519
        }
3520
        if (!empty($params['subtitle'])) {
3521
            $html .= '<div class="subtitle-session">' . $params['subtitle'] . '</div>';
3522
        }
3523 View Code Duplication
        if (!empty($params['teachers'])) {
3524
            $html .= '<h5 class="course-items-session">' .
3525
                    Display::return_icon('teacher.png', get_lang('Teacher'), array(), ICON_SIZE_TINY) .
3526
                $params['teachers'] . '</h5>';
3527
        }
3528
        if (!empty($params['coaches'])) {
3529
            $coaches = '';
3530
            if (is_array($params['coaches'])) {
3531
                foreach ($params['coaches'] as $coach) {
3532
                    $coaches .= $coach['full_name'];
3533
                }
3534
            }
3535
            $html .= '<h5 class="course-items-session">' .
3536
                Display::return_icon('teacher.png', get_lang('Coach'), array(), ICON_SIZE_TINY) .
3537
                $coaches .
3538
                '</h5>';
3539
        }
3540
3541
        $html .= '</div>';
3542
        $html .= '</div>';
3543
3544
        $html .= '</div>';
3545
3546
        $html .= '</div>';
3547
        $html .= '</div>';
3548
3549
        return $html;
3550
    }
3551
3552
    /**
3553
     * @param $courses
3554
     * @return string
3555
     */
3556
    public function parseCourseListData($courses)
3557
    {
3558
        $html = '';
3559
        foreach ($courses as $course) {
3560
            $html .= self::course_item_html($course, true);
3561
        }
3562
3563
        return $html;
3564
    }
3565
3566
    /**
3567
     * @param string $main_content
3568
     * @param string $sub_content
3569
     * @param string $sub_sub_content
3570
     * @return string
3571
     */
3572
    public static function course_item_parent($main_content, $sub_content, $sub_sub_content = null)
3573
    {
3574
        return '<div class="panel panel-default">' . $main_content . $sub_content . $sub_sub_content . '</div>';
3575
    }
3576
3577
    /**
3578
     * @param $params
3579
     * @param bool|false $is_sub_content
3580
     * @return string
3581
     */
3582
    public static function session_items_html($params, $is_sub_content = false)
3583
    {
3584
        $html = '';
3585
        $html .= '<div class="row">';
3586
        $html .= '<div class="col-md-2">';
3587
        if (!empty($params['link'])){
3588
            $html .= '<a class="thumbnail" href="'.$params['link'].'">';
3589
            $html .= $params['icon'];
3590
            $html .= '</a>';
3591
        }else{
3592
            $html .= $params['icon'];
3593
        }
3594
        $html .= '</div>';
3595
        $html .= '<div class="col-md-10">';
3596
        $html .= $params['title'];
3597
        $html .= $params['coaches'];
3598
        $html .= '</div>';
3599
        $html .= '</div>';
3600
3601
        return $html;
3602
    }
3603
3604
    /**
3605
     * Display special courses (and only these) as several HTML divs of class userportal-course-item
3606
     *
3607
     * Special courses are courses that stick on top of the list and are "auto-registerable"
3608
     * in the sense that any user clicking them is registered as a student
3609
     * @param int       User id
3610
     * @param bool      Whether to show the document quick-loader or not
3611
     * @return string
3612
     */
3613
    public static function returnSpecialCourses($user_id, $load_dirs = false)
3614
    {
3615
        $user_id = intval($user_id);
3616
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
3617
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
3618
3619
        $special_course_list = self::get_special_course_list();
3620
3621
        $with_special_courses = '';
3622
        if (!empty($special_course_list)) {
3623
            $with_special_courses = ' course.code IN ("' . implode('","', $special_course_list) . '")';
3624
        }
3625
3626
        $courseList = [];
3627
        if (!empty($with_special_courses)) {
3628
            $sql = "SELECT
3629
                        course.id,
3630
                        course.code,
3631
                        course.subscribe subscr,
3632
                        course.unsubscribe unsubscr,
3633
                        course_rel_user.status status,
3634
                        course_rel_user.sort sort,
3635
                        course_rel_user.user_course_cat user_course_cat,
3636
                        course_rel_user.user_id
3637
                    FROM $tbl_course course
3638
                    LEFT JOIN $tbl_course_user course_rel_user
3639
                    ON course.id = course_rel_user.c_id AND course_rel_user.user_id = '$user_id'
3640
                    WHERE $with_special_courses group by course.code";
3641
3642
            $rs_special_course = Database::query($sql);
3643
            $number_of_courses = Database::num_rows($rs_special_course);
3644
            $showCustomIcon = api_get_setting('course_images_in_courses_list');
3645
3646
            if ($number_of_courses > 0) {
3647
                while ($course = Database::fetch_array($rs_special_course)) {
3648
                    $course_info = api_get_course_info($course['code']);
3649
                    if ($course_info['visibility'] == COURSE_VISIBILITY_HIDDEN) {
3650
                        continue;
3651
                    }
3652
3653
                    $params = [];
3654
                    // Get notifications.
3655
                    $course_info['id_session'] = null;
3656
                    $course_info['status'] = $course['status'];
3657
                    $show_notification = Display::show_notification($course_info);
3658
3659
                    if (empty($course['user_id'])) {
3660
                        $course['status'] = STUDENT;
3661
                    }
3662
3663
                    $params['edit_actions'] = '';
3664
                    $params['document'] = '';
3665
                    if (api_is_platform_admin()) {
3666
                        $params['edit_actions'] .= api_get_path(WEB_CODE_PATH) . 'course_info/infocours.php?cidReq=' . $course['code'];
3667
                        if ($load_dirs) {
3668
                            $params['document'] = '<a id="document_preview_' . $course_info['real_id'] . '_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3669
                               . Display::returnFontAwesomeIcon('folder-open') . '</a>';
3670
                            $params['document'] .= Display::div('', ['id' => 'document_result_' . $course_info['real_id'] . '_0', 'class' => 'document_preview_container']);
3671
                        }
3672
                    }else{
3673
                        if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED && $load_dirs) {
3674
                            $params['document'] = '<a id="document_preview_' . $course_info['real_id'] . '_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3675
                               . Display::returnFontAwesomeIcon('folder-open') . '</a>';
3676
                            $params['document'] .= Display::div('', ['id' => 'document_result_' . $course_info['real_id'] . '_0', 'class' => 'document_preview_container']);
3677
                        }
3678
                    }
3679
3680
                    $params['visibility'] = $course_info['visibility'];
3681
                    $params['status'] = $course_info['status'];
3682
                    $params['category'] = $course_info['categoryName'];
3683
                    $params['icon'] = Display::return_icon('drawing-pin.png',null, null, ICON_SIZE_LARGE, null);
3684
3685 View Code Duplication
                    if (api_get_setting('display_coursecode_in_courselist') == 'true') {
3686
                        $params['code_course']  = '(' . $course_info['visual_code'] . ')';
3687
                    }
3688
3689
                    $params['title'] = $course_info['title'];
3690
                    $params['link'] = $course_info['course_public_url'].'?id_session=0&autoreg=1';
3691
                    if (api_get_setting('display_teacher_in_courselist') === 'true') {
3692
                        $params['teachers'] = CourseManager::getTeachersFromCourseByCode($course['code']);
3693
                    }
3694
3695
                    if ($showCustomIcon === 'true') {
3696
                        $params['thumbnails'] = $course_info['course_image'];
3697
                        $params['image'] = $course_info['course_image_large'];
3698
                    }
3699
3700
                    if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
3701
                        $params['notifications'] = $show_notification;
3702
                    }
3703
3704
                    $params['is_special_course'] = true;
3705
3706
                    $courseList[] = $params;
3707
3708
                }
3709
            }
3710
        }
3711
3712
    return $courseList;
3713
}
3714
3715
    /**
3716
     * Display courses (without special courses) as several HTML divs
3717
     * of course categories, as class userportal-catalog-item.
3718
     * @uses displayCoursesInCategory() to display the courses themselves
3719
     * @param int        user id
3720
     * @param bool      Whether to show the document quick-loader or not
3721
     * @param integer $user_id
3722
     * @return string
3723
     */
3724
    public static function returnCourses($user_id, $load_dirs = false)
3725
    {
3726
        $user_id = intval($user_id);
3727
        if (empty($user_id)) {
3728
            $user_id = api_get_user_id();
3729
        }
3730
        // Step 1: We get all the categories of the user
3731
        $table = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
3732
        $sql = "SELECT id, title FROM $table
3733
                WHERE user_id = '" . $user_id . "'
3734
                ORDER BY sort ASC";
3735
        $result = Database::query($sql);
3736
        $listItems = [
3737
            'in_category' => [],
3738
            'not_category' => []
3739
        ];
3740
3741
        while ($row = Database::fetch_array($result)) {
3742
            // We simply display the title of the category.
3743
            $courseInCategory = self:: returnCoursesCategories(
3744
                $row['id'],
3745
                $load_dirs
3746
            );
3747
3748
            $params = [
3749
                'id_category' => $row ['id'],
3750
                'title_category' => $row['title'],
3751
                'courses' => $courseInCategory
3752
            ];
3753
            $listItems['in_category'][] = $params;
3754
        }
3755
3756
        // Step 2: We display the course without a user category.
3757
        $coursesNotCategory = self::returnCoursesWithoutCategories(0, $load_dirs);
3758
        if ($coursesNotCategory) {
3759
            $listItems['not_category'] = $coursesNotCategory;
3760
        }
3761
3762
        return $listItems;
3763
    }
3764
3765
    /**
3766
     *  Display courses inside a category (without special courses) as HTML dics of
3767
     *  class userportal-course-item.
3768
     * @param int      User category id
3769
     * @param bool      Whether to show the document quick-loader or not
3770
     * @return string
3771
     */
3772
    public static function returnCoursesCategories($user_category_id, $load_dirs = false)
3773
    {
3774
        $user_id = api_get_user_id();
3775
        // Table definitions
3776
        $TABLECOURS = Database:: get_main_table(TABLE_MAIN_COURSE);
3777
        $TABLECOURSUSER = Database:: get_main_table(TABLE_MAIN_COURSE_USER);
3778
        $TABLE_ACCESS_URL_REL_COURSE = Database:: get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
3779
        $current_url_id = api_get_current_access_url_id();
3780
3781
        // Get course list auto-register
3782
        $special_course_list = self::get_special_course_list();
3783
3784
        $without_special_courses = '';
3785
        if (!empty($special_course_list)) {
3786
            $without_special_courses = ' AND course.code NOT IN ("' . implode('","', $special_course_list) . '")';
3787
        }
3788
3789
        //AND course_rel_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
3790
        $sql = "SELECT
3791
                course.id,
3792
                course.title,
3793
                course.code,
3794
                course.subscribe subscr,
3795
                course.unsubscribe unsubscr,
3796
                course_rel_user.status status,
3797
                course_rel_user.sort sort,
3798
                course_rel_user.user_course_cat user_course_cat
3799
                FROM $TABLECOURS course,
3800
                     $TABLECOURSUSER course_rel_user,
3801
                     $TABLE_ACCESS_URL_REL_COURSE url
3802
                WHERE
3803
                    course.id = course_rel_user.c_id AND
3804
                    url.c_id = course.id AND
3805
                    course_rel_user.user_id = '" . $user_id . "' AND
3806
                    course_rel_user.user_course_cat = '" . $user_category_id . "'
3807
                    $without_special_courses ";
3808
3809
        // If multiple URL access mode is enabled, only fetch courses
3810
        // corresponding to the current URL.
3811
        if (api_get_multiple_access_url() && $current_url_id != -1) {
3812
            $sql .= " AND url.c_id = course.id AND access_url_id='" . $current_url_id . "'";
3813
        }
3814
        // Use user's classification for courses (if any).
3815
        $sql .= " ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
3816
3817
        $result = Database::query($sql);
3818
3819
        $courseList = array();
3820
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
3821
        // Browse through all courses.
3822
        while ($course = Database::fetch_array($result)) {
3823
            $course_info = api_get_course_info($course['code']);
3824
            if (isset($course_info['visibility']) &&
3825
                $course_info['visibility'] == COURSE_VISIBILITY_HIDDEN
3826
            ) {
3827
                continue;
3828
            }
3829
            $course_info['id_session'] = null;
3830
            $course_info['status'] = $course['status'];
3831
3832
            // For each course, get if there is any notification icon to show
3833
            // (something that would have changed since the user's last visit).
3834
            $showNotification = Display::show_notification($course_info);
3835
            $iconName = basename($course_info['course_image']);
3836
3837
            if ($showCustomIcon === 'true' && $iconName != 'course.png') {
3838
                $params['thumbnails'] = $course_info['course_image'];
3839
                $params['image'] = $course_info['course_image_large'];
3840
            }
3841
3842
            $params = array();
3843
3844
            $thumbnails = null;
3845
            $image = null;
3846
3847 View Code Duplication
            if ($showCustomIcon === 'true' && $iconName != 'course.png') {
3848
                $thumbnails = $course_info['course_image'];
3849
                $image = $course_info['course_image_large'];
3850
            }else{
3851
                $image = Display::return_icon('session_default.png', null, null, null,null, true);
3852
            }
3853
3854
            $params['course_id'] = $course['id'];
3855
            $params['edit_actions'] = '';
3856
            $params['document'] = '';
3857 View Code Duplication
            if (api_is_platform_admin()) {
3858
                $params['edit_actions'] .= api_get_path(WEB_CODE_PATH) . 'course_info/infocours.php?cidReq=' . $course['code'];
3859
                if($load_dirs){
3860
                    $params['document'] = '<a id="document_preview_' . $course_info['real_id'] . '_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3861
                               . Display::returnFontAwesomeIcon('folder-open') . '</a>';
3862
                    $params['document'] .= Display::div('', array('id' => 'document_result_' . $course_info['real_id'] . '_0', 'class' => 'document_preview_container'));
3863
                }
3864
            }
3865
            if ($load_dirs) {
3866
                $params['document'] = '<a id="document_preview_' . $course_info['real_id'] . '_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3867
                    . Display::returnFontAwesomeIcon('folder-open') . '</a>';
3868
                $params['document'] .= Display::div('', array('id' => 'document_result_' . $course_info['real_id'] . '_0', 'class' => 'document_preview_container'));
3869
            }
3870
3871
            $courseUrl = api_get_path(WEB_COURSE_PATH) . $course_info['path'] . '/index.php?id_session=0';
3872
3873
            if (api_get_setting('display_teacher_in_courselist') === 'true') {
3874
                $teachers = CourseManager::getTeachersFromCourseByCode($course['code']);
3875
            }
3876
3877
            $params['status'] = $course['status'];
3878
3879 View Code Duplication
            if (api_get_setting('display_coursecode_in_courselist') == 'true') {
3880
                $params['code_course'] = '(' . $course_info['visual_code'] . ') ';
3881
            }
3882
3883
            $params['visibility'] = $course_info['visibility'];
3884
            $params['link'] = $courseUrl;
3885
            $params['thumbnails'] = $thumbnails;
3886
            $params['image'] = $image;
3887
            $params['title'] = $course_info['title'];
3888
            $params['category'] = $course_info['categoryName'];
3889
            $params['teachers'] = $teachers;
3890
3891
            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
3892
                $params['notifications'] = $showNotification;
3893
            }
3894
3895
            $courseList[] = $params;
3896
        }
3897
3898
        return $courseList;
3899
    }
3900
3901
    /**
3902
     *  Display courses inside a category (without special courses) as HTML dics of
3903
     *  class userportal-course-item.
3904
     * @param int      User category id
3905
     * @param bool      Whether to show the document quick-loader or not
3906
     * @return string
3907
     */
3908
    public static function returnCoursesWithoutCategories($user_category_id, $load_dirs = false)
3909
    {
3910
        $user_id = api_get_user_id();
3911
        // Table definitions
3912
        $TABLECOURS = Database:: get_main_table(TABLE_MAIN_COURSE);
3913
        $TABLECOURSUSER = Database:: get_main_table(TABLE_MAIN_COURSE_USER);
3914
        $TABLE_ACCESS_URL_REL_COURSE = Database:: get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
3915
        $current_url_id = api_get_current_access_url_id();
3916
        $courseList = [];
3917
3918
        // Get course list auto-register
3919
        $special_course_list = self::get_special_course_list();
3920
3921
        $without_special_courses = '';
3922
        if (!empty($special_course_list)) {
3923
            $without_special_courses = ' AND course.code NOT IN ("' . implode('","', $special_course_list) . '")';
3924
        }
3925
3926
        //AND course_rel_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
3927
        $sql = "SELECT
3928
                course.id,
3929
                course.title,
3930
                course.code,
3931
                course.subscribe subscr,
3932
                course.unsubscribe unsubscr,
3933
                course_rel_user.status status,
3934
                course_rel_user.sort sort,
3935
                course_rel_user.user_course_cat user_course_cat
3936
                FROM $TABLECOURS course,
3937
                     $TABLECOURSUSER course_rel_user,
3938
                     $TABLE_ACCESS_URL_REL_COURSE url
3939
                WHERE
3940
                    course.id = course_rel_user.c_id AND
3941
                    url.c_id = course.id AND
3942
                    course_rel_user.user_id = '" . $user_id . "' AND
3943
                    course_rel_user.user_course_cat = '" . $user_category_id . "'
3944
                    $without_special_courses ";
3945
3946
        // If multiple URL access mode is enabled, only fetch courses
3947
        // corresponding to the current URL.
3948
        if (api_get_multiple_access_url() && $current_url_id != -1) {
3949
            $sql .= " AND url.c_id = course.id AND access_url_id='" . $current_url_id . "'";
3950
        }
3951
        // Use user's classification for courses (if any).
3952
        $sql .= " ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
3953
        $result = Database::query($sql);
3954
3955
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
3956
        // Browse through all courses.
3957
        while ($course = Database::fetch_array($result)) {
3958
            $course_info = api_get_course_info($course['code']);
3959
            if (isset($course_info['visibility']) &&
3960
                $course_info['visibility'] == COURSE_VISIBILITY_HIDDEN
3961
            ) {
3962
                continue;
3963
            }
3964
            $course_info['id_session'] = null;
3965
            $course_info['status'] = $course['status'];
3966
3967
            // For each course, get if there is any notification icon to show
3968
            // (something that would have changed since the user's last visit).
3969
            $showNotification = Display::show_notification($course_info);
3970
3971
            $thumbnails = null;
3972
            $image = null;
3973
3974
            $iconName = basename($course_info['course_image']);
3975 View Code Duplication
            if ($showCustomIcon === 'true' && $iconName != 'course.png') {
3976
                $thumbnails = $course_info['course_image'];
3977
                $image = $course_info['course_image_large'];
3978
            }else{
3979
                $image = Display::return_icon('session_default.png', null, null, null,null, true);
3980
            }
3981
3982
            $params = array();
3983
            $params['edit_actions'] = '';
3984
            $params['document'] = '';
3985 View Code Duplication
            if (api_is_platform_admin()) {
3986
                $params['edit_actions'] .= api_get_path(WEB_CODE_PATH) . 'course_info/infocours.php?cidReq=' . $course['code'];
3987
                if($load_dirs){
3988
                    $params['document'] = '<a id="document_preview_' . $course_info['real_id'] . '_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3989
                               . Display::returnFontAwesomeIcon('folder-open') . '</a>';
3990
                    $params['document'] .= Display::div('', array('id' => 'document_result_' . $course_info['real_id'] . '_0', 'class' => 'document_preview_container'));
3991
                }
3992
            }
3993
            if ($load_dirs) {
3994
                $params['document'] = '<a id="document_preview_' . $course_info['real_id'] . '_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3995
                    . Display::returnFontAwesomeIcon('folder-open') . '</a>';
3996
                $params['document'] .= Display::div('', array('id' => 'document_result_' . $course_info['real_id'] . '_0', 'class' => 'document_preview_container'));
3997
            }
3998
3999
            $course_title_url = api_get_path(WEB_COURSE_PATH) . $course_info['path'] . '/index.php?id_session=0';
4000
4001
            $teachers = '';
4002
4003
            if (api_get_setting('display_teacher_in_courselist') === 'true') {
4004
                $teachers = CourseManager::getTeachersFromCourseByCode($course['code']);
4005
            }
4006
            $params['status'] = $course['status'];
4007
4008 View Code Duplication
            if (api_get_setting('display_coursecode_in_courselist') == 'true') {
4009
                $params['code_course'] = '(' . $course_info['visual_code'] . ') ';
4010
            }
4011
4012
            $params['visibility'] = $course_info['visibility'];
4013
            $params['link'] = $course_title_url;
4014
            $params['thumbnails'] = $thumbnails;
4015
            $params['image'] = $image;
4016
            $params['title'] = $course_info['title'];
4017
            $params['category'] = $course_info['categoryName'];
4018
            $params['teachers'] = $teachers;
4019
4020
            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
4021
                $params['notifications'] = $showNotification;
4022
            }
4023
4024
            $courseList[] = $params;
4025
4026
        }
4027
4028
        return $courseList;
4029
    }
4030
4031
    /**
4032
     * Retrieves the user defined course categories
4033
     * @param string $userId
4034
     * @return array containing all the titles of the user defined courses with the id as key of the array
4035
     */
4036 View Code Duplication
    public static function get_user_course_categories($userId = '')
4037
    {
4038
        if ($userId == '') {
4039
            $realUserId = api_get_user_id();
4040
        } else {
4041
            $realUserId = $userId;
4042
        }
4043
4044
        $output = array();
4045
        $table_category = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
4046
        $sql = "SELECT * FROM $table_category WHERE user_id = '".intval($realUserId)."'";
4047
        $result = Database::query($sql);
4048
        while ($row = Database::fetch_array($result)) {
4049
            $output[$row['id']] = $row['title'];
4050
        }
4051
        return $output;
4052
    }
4053
4054
    /**
4055
     * Return an array the user_category id and title for the course $courseId for user $userId
4056
     * @param $userId
4057
     * @param $courseId
4058
     * @return array
4059
     */
4060 View Code Duplication
    public static function getUserCourseCategoryForCourse($userId, $courseId)
4061
    {
4062
        $tblCourseRelUser = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4063
        $tblUserCategory = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
4064
        $courseId = intval($courseId);
4065
        $userId = intval($userId);
4066
4067
        $sql = "SELECT user_course_cat, title
4068
                FROM $tblCourseRelUser cru
4069
                LEFT JOIN $tblUserCategory ucc
4070
                ON cru.user_course_cat = ucc.id
4071
                WHERE
4072
                    cru.user_id = $userId AND c_id= $courseId ";
4073
4074
        $res = Database::query($sql);
4075
4076
        $result = array();
4077
        if (Database::num_rows($res) > 0) {
4078
            $data = Database::fetch_assoc($res);
4079
            $result[] = $data['user_course_cat'];
4080
            $result[] = $data['title'];
4081
        }
4082
        return $result;
4083
    }
4084
4085
    /**
4086
     * Get the course id based on the original id and field name in the extra fields.
4087
     * Returns 0 if course was not found
4088
     *
4089
     * @param string $value Original course code
4090
     * @param string $variable Original field name
4091
     * @return int Course id
4092
     */
4093
    public static function getCourseInfoFromOriginalId($value, $variable)
4094
    {
4095
        $extraFieldValue = new ExtraFieldValue('course');
4096
        $result = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
4097
            $variable,
4098
            $value
4099
        );
4100
4101
        if (!empty($result)) {
4102
            $courseInfo = api_get_course_info_by_id($result['item_id']);
4103
            return $courseInfo;
4104
        }
4105
4106
        return 0;
4107
    }
4108
4109
    /**
4110
     * Display code for one specific course a logged in user is subscribed to.
4111
     * Shows a link to the course, what's new icons...
4112
     *
4113
     * $my_course['d'] - course directory
4114
     * $my_course['i'] - course title
4115
     * $my_course['c'] - visual course code
4116
     * $my_course['k']  - system course code
4117
     *
4118
     * @param   array       Course details
4119
     * @param   integer     Session ID
4120
     * @param   string      CSS class to apply to course entry
4121
     * @param   boolean     Whether the session is supposedly accessible now
4122
     * (not in the case it has passed and is in invisible/unaccessible mode)
4123
     * @param bool      Whether to show the document quick-loader or not
4124
     * @return  string      The HTML to be printed for the course entry
4125
     *
4126
     * @version 1.0.3
4127
     * @todo refactor into different functions for database calls | logic | display
4128
     * @todo replace single-character $my_course['d'] indices
4129
     * @todo move code for what's new icons to a separate function to clear things up
4130
     * @todo add a parameter user_id so that it is possible to show the
4131
     * courselist of other users (=generalisation).
4132
     * This will prevent having to write a new function for this.
4133
     */
4134
    public static function get_logged_user_course_html(
4135
        $course,
4136
        $session_id = 0,
4137
        $class = 'courses',
4138
        $session_accessible = true,
4139
        $load_dirs = false
4140
    ) {
4141
        $entityManager = Database::getManager();
4142
        $user_id = api_get_user_id();
4143
        $course_info = api_get_course_info_by_id($course['real_id']);
4144
        $status_course = CourseManager::get_user_in_course_status($user_id, $course_info['code']);
4145
        $course_info['status'] = empty($session_id) ? $status_course : STUDENT;
4146
        $course_info['id_session'] = $session_id;
4147
        $objUser = $entityManager->find('ChamiloUserBundle:User', $user_id);
4148
        $objCourse = $entityManager->find('ChamiloCoreBundle:Course', $course['real_id']);
4149
        $objSession = $entityManager->find('ChamiloCoreBundle:Session', $session_id);
4150
        $now = date('Y-m-d h:i:s');
4151
4152
        // Table definitions
4153
        $main_user_table = Database:: get_main_table(TABLE_MAIN_USER);
4154
        $tbl_session = Database:: get_main_table(TABLE_MAIN_SESSION);
4155
        $tbl_session_category = Database:: get_main_table(TABLE_MAIN_SESSION_CATEGORY);
4156
4157
        $course_access_settings = CourseManager::get_access_settings($course_info['code']);
4158
        $course_visibility = $course_access_settings['visibility'];
4159
4160
        if ($course_visibility == COURSE_VISIBILITY_HIDDEN) {
4161
            return '';
4162
        }
4163
4164
        $user_in_course_status = CourseManager::get_user_in_course_status(
4165
            api_get_user_id(),
4166
            $course_info['code']
4167
        );
4168
4169
        $is_coach = api_is_coach($course_info['id_session'], $course_info['real_id']);
4170
4171
        // Display course entry.
4172
        // Show a hyperlink to the course, unless the course is closed and user is not course admin.
4173
        $session_url = '';
4174
4175
        $params = array();
4176
        $params['icon'] = Display::return_icon(
4177
            'blackboard_blue.png',
4178
            null,
4179
            array(),
4180
            ICON_SIZE_LARGE,
4181
            null,
4182
            true
4183
        );
4184
4185
        // Display the "what's new" icons
4186
        $notifications = '';
4187
        if ($course_visibility != COURSE_VISIBILITY_CLOSED && $course_visibility != COURSE_VISIBILITY_HIDDEN) {
4188
            $notifications .= Display:: show_notification($course_info);
4189
        }
4190
4191
        if ($session_accessible) {
4192
            if ($course_visibility != COURSE_VISIBILITY_CLOSED ||
4193
                $user_in_course_status == COURSEMANAGER
4194
            ) {
4195
                if (empty($course_info['id_session'])) {
4196
                    $course_info['id_session'] = 0;
4197
                }
4198
4199
                $sessionCourseAvailable = false;
4200
                $sessionCourseStatus = api_get_session_visibility($session_id, $course_info['real_id']);
4201
4202
                if (in_array($sessionCourseStatus,
4203
                    array(SESSION_VISIBLE_READ_ONLY, SESSION_VISIBLE, SESSION_AVAILABLE))) {
4204
                    $sessionCourseAvailable = true;
4205
                }
4206
4207
                if ($user_in_course_status == COURSEMANAGER || $sessionCourseAvailable) {
4208
                    $session_url = $course_info['course_public_url'] . '?id_session=' . $course_info['id_session'];
4209
                    $session_title = '<a href="' . $session_url. '">'. $course_info['name'] . '</a>'.$notifications;
4210
                } else {
4211
                    $session_title = $course_info['name'];
4212
                }
4213
4214
            } else {
4215
                $session_title =
4216
                    $course_info['name'] . ' ' .
4217
                    Display::tag('span', get_lang('CourseClosed'), array('class' => 'item_closed'));
4218
            }
4219
        } else {
4220
            $session_title = $course_info['name'];
4221
        }
4222
4223
        $thumbnails = null;
4224
        $image = null;
4225
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
4226
        $iconName = basename($course_info['course_image']);
4227
4228 View Code Duplication
        if ($showCustomIcon === 'true' && $iconName != 'course.png') {
4229
            $thumbnails = $course_info['course_image'];
4230
            $image = $course_info['course_image_large'];
4231
        }else{
4232
            $image = Display::return_icon('session_default.png', null, null, null,null, true);
4233
        }
4234
        $params['thumbnails'] = $thumbnails;
4235
        $params['image'] = $image;
4236
        $params['link'] = $session_url;
4237
        $params['title'] = $session_title;
4238
        $params['edit_actions'] = '';
4239
        $params['document'] = '';
4240
4241
        if ($course_visibility != COURSE_VISIBILITY_CLOSED &&
4242
            $course_visibility != COURSE_VISIBILITY_HIDDEN
4243
        ) {
4244
            if (api_is_platform_admin()) {
4245
                $params['edit_actions'] .= api_get_path(WEB_CODE_PATH) . 'course_info/infocours.php?cidReq=' . $course_info['code'];
4246
            if ($load_dirs) {
4247
                $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);">' .
4248
                    Display::returnFontAwesomeIcon('folder-open') . '</a>';
4249
                $params['document'] .= Display::div('', array(
4250
                    'id' => 'document_result_' . $course_info['real_id'] . '_' . $course_info['id_session'],
4251
                    'class' => 'document_preview_container'
4252
                ));
4253
            }
4254
        }
4255
        }
4256
4257
        if (api_get_setting('display_coursecode_in_courselist') === 'true') {
4258
            $session_title .= ' (' . $course_info['visual_code'] . ') ';
4259
        }
4260
4261
        if (api_get_setting('display_teacher_in_courselist') === 'true') {
4262
            $teacher_list = CourseManager::getTeachersFromCourseByCode(
4263
                $course_info['code']
4264
            );
4265
4266
            $course_coachs = self::get_coachs_from_course(
4267
                $course_info['id_session'],
4268
                $course_info['real_id']
4269
            );
4270
            $params['teachers'] = $teacher_list;
4271
4272
            if (($course_info['status'] == STUDENT && !empty($course_info['id_session'])) ||
4273
                ($is_coach && $course_info['status'] != COURSEMANAGER)
4274
            ) {
4275
                $params['coaches'] = $course_coachs;
4276
            }
4277
        }
4278
4279
        $session_title .= isset($course['special_course']) ? ' ' .
4280
                          Display::return_icon('klipper.png', get_lang('CourseAutoRegister')) : '';
4281
4282
        $params['title'] = $session_title;
4283
        $params['extra'] = '';
4284
4285
        $html = $params;
4286
4287
        $session_category_id = null;
4288
        if (1) {
4289
            $session = '';
4290
            $active = false;
4291
            if (!empty($course_info['id_session'])) {
4292
4293
                // Request for the name of the general coach
4294
                $sql = 'SELECT lastname, firstname,sc.name
4295
                        FROM ' . $tbl_session . ' ts
4296
                        LEFT JOIN ' . $main_user_table . ' tu
4297
                        ON ts.id_coach = tu.user_id
4298
                        INNER JOIN ' . $tbl_session_category . ' sc
4299
                        ON ts.session_category_id = sc.id
4300
                        WHERE ts.id=' . (int)$course_info['id_session'] . '
4301
                        LIMIT 1';
4302
4303
                $rs = Database::query($sql);
4304
                $sessioncoach = Database::store_result($rs);
4305
                $sessioncoach = $sessioncoach ? $sessioncoach[0] : null;
4306
4307
                $session = api_get_session_info($course_info['id_session']);
4308
                $session_category_id = CourseManager::get_session_category_id_by_session_id($course_info['id_session']);
4309
                $session['category'] = $sessioncoach['name'];
4310
                if (
4311
                    $session['access_start_date'] == '0000-00-00 00:00:00' || empty($session['access_start_date']) ||
4312
                    $session['access_start_date'] == '0000-00-00'
4313
                ) {
4314
                    //$session['dates'] = get_lang('WithoutTimeLimits');
4315
                    $session['dates'] = '';
4316 View Code Duplication
                    if (api_get_setting('show_session_coach') === 'true') {
4317
                        $session['coach'] = get_lang('GeneralCoach') . ': ' . api_get_person_name($sessioncoach['firstname'],
4318
                                $sessioncoach['lastname']);
4319
                    }
4320
                    $active = true;
4321
                } else {
4322
                    $session ['dates'] = ' - ' . get_lang('From') . ' ' . $session['access_start_date'] . ' ' . get_lang('To') . ' ' . $session['access_end_date'];
4323 View Code Duplication
                    if (api_get_setting('show_session_coach') === 'true') {
4324
                        $session['coach'] = get_lang('GeneralCoach') . ': ' . api_get_person_name($sessioncoach['firstname'],
4325
                                $sessioncoach['lastname']);
4326
                    }
4327
                    $date_start = $session['access_start_date'];
4328
                    $date_end = $session['access_end_date'];
4329
4330
                    $active = !$date_end ? ($date_start <= $now) : ($date_start <= $now && $date_end >= $now);
4331
                }
4332
            }
4333
            $user_course_category = '';
4334
            if (isset($course_info['user_course_cat'])) {
4335
                $user_course_category = $course_info['user_course_cat'];
4336
            }
4337
            $output = array(
4338
                $user_course_category,
4339
                $html,
4340
                $course_info['id_session'],
4341
                $session,
4342
                'active' => $active,
4343
                'session_category_id' => $session_category_id
4344
            );
4345
4346
            if (api_get_setting('allow_skills_tool') === 'true') {
4347
                $skill = $entityManager
4348
                    ->getRepository('ChamiloCoreBundle:Skill')
4349
                    ->getLastByUser($objUser, $objCourse, $objSession);
4350
4351
                $output['skill'] = null;
4352
4353
                if ($skill) {
4354
                    $output['skill']['name'] = $skill->getName();
4355
                    $output['skill']['icon'] = $skill->getIcon();
4356
                }
4357
            }
4358
        } else {
4359
            $output = array($course_info['user_course_cat'], $html);
4360
        }
4361
        return $output;
4362
    }
4363
4364
    /**
4365
     *
4366
     * @param    string    source course code
4367
     * @param     int        source session id
4368
     * @param    string    destination course code
4369
     * @param     int        destination session id
4370
     * @param integer $source_session_id
4371
     * @param integer $destination_session_id
4372
     * @return  bool
4373
     */
4374
    public static function copy_course(
4375
        $source_course_code,
4376
        $source_session_id,
4377
        $destination_course_code,
4378
        $destination_session_id,
4379
        $params = array()
4380
    ) {
4381
        $course_info = api_get_course_info($source_course_code);
4382
4383
        if (!empty($course_info)) {
4384
            $cb = new CourseBuilder('', $course_info);
4385
            $course = $cb->build($source_session_id, $source_course_code, true);
4386
            $course_restorer = new CourseRestorer($course);
4387
            $course_restorer->skip_content = $params;
4388
            $course_restorer->restore($destination_course_code, $destination_session_id, true, true);
4389
            return true;
4390
        }
4391
        return false;
4392
    }
4393
4394
    /**
4395
     * A simpler version of the copy_course, the function creates an empty course with an autogenerated course code
4396
     *
4397
     * @param    string    new course title
4398
     * @param    string    source course code
4399
     * @param     int        source session id
4400
     * @param     int        destination session id
4401
     * @param    bool    new copied tools (Exercises and LPs)will be set to invisible by default?
4402
     * @param string $new_title
4403
     *
4404
     * @return     array
4405
     */
4406
    public static function copy_course_simple(
4407
        $new_title,
4408
        $source_course_code,
4409
        $source_session_id = 0,
4410
        $destination_session_id = 0,
4411
        $params = array()
4412
    ) {
4413
        $source_course_info = api_get_course_info($source_course_code);
4414
        if (!empty($source_course_info)) {
4415
            $new_course_code = self::generate_nice_next_course_code($source_course_code);
4416
            if ($new_course_code) {
4417
                $new_course_info = self::create_course($new_title, $new_course_code, false);
4418
                if (!empty($new_course_info['code'])) {
4419
                    $result = self::copy_course($source_course_code, $source_session_id, $new_course_info['code'],
4420
                        $destination_session_id, $params);
4421
                    if ($result) {
4422
                        return $new_course_info;
4423
                    }
4424
                }
4425
            }
4426
        }
4427
4428
        return false;
4429
    }
4430
4431
    /**
4432
     * Creates a new course code based in a given code
4433
     *
4434
     * @param string    wanted code
4435
     * <code>    $wanted_code = 'curse' if there are in the DB codes like curse1 curse2 the function will return: course3</code>
4436
     * if the course code doest not exist in the DB the same course code will be returned
4437
     * @return string    wanted unused code
4438
     */
4439 View Code Duplication
    public static function generate_nice_next_course_code($wanted_code)
4440
    {
4441
        $course_code_ok = !self::course_code_exists($wanted_code);
4442
        if (!$course_code_ok) {
4443
            $wanted_code = CourseManager::generate_course_code($wanted_code);
4444
            $table = Database::get_main_table(TABLE_MAIN_COURSE);
4445
            $wanted_code = Database::escape_string($wanted_code);
4446
            $sql = "SELECT count(*) as count
4447
                    FROM $table
4448
                    WHERE code LIKE '$wanted_code%'";
4449
            $result = Database::query($sql);
4450
            if (Database::num_rows($result) > 0) {
4451
                $row = Database::fetch_array($result);
4452
                $count = $row['count'] + 1;
4453
                $wanted_code = $wanted_code . '_' . $count;
4454
                $result = api_get_course_info($wanted_code);
4455
                if (empty($result)) {
4456
                    return $wanted_code;
4457
                }
4458
            }
4459
4460
            return false;
4461
        }
4462
4463
        return $wanted_code;
4464
    }
4465
4466
    /**
4467
     * Gets the status of the users agreement in a course course-session
4468
     *
4469
     * @param int $user_id
4470
     * @param string $course_code
4471
     * @param int $session_id
4472
     * @return boolean
4473
     */
4474
    public static function is_user_accepted_legal($user_id, $course_code, $session_id = null)
4475
    {
4476
        $user_id = intval($user_id);
4477
        $course_code = Database::escape_string($course_code);
4478
        $session_id = intval($session_id);
4479
4480
        $courseInfo = api_get_course_info($course_code);
4481
        $courseId = $courseInfo['real_id'];
4482
4483
        // Course legal
4484
        $enabled = api_get_plugin_setting('courselegal', 'tool_enable');
4485
4486 View Code Duplication
        if ($enabled == 'true') {
4487
            require_once api_get_path(SYS_PLUGIN_PATH) . 'courselegal/config.php';
4488
            $plugin = CourseLegalPlugin::create();
4489
            return $plugin->isUserAcceptedLegal($user_id, $course_code, $session_id);
4490
        }
4491
4492
        if (empty($session_id)) {
4493
            $table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4494
            $sql = "SELECT legal_agreement FROM $table
4495
                    WHERE user_id = $user_id AND c_id = $courseId ";
4496
            $result = Database::query($sql);
4497
            if (Database::num_rows($result) > 0) {
4498
                $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...
4499
                if ($result['legal_agreement'] == 1) {
4500
                    return true;
4501
                }
4502
            }
4503
            return false;
4504
        } else {
4505
            $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4506
            $sql = "SELECT legal_agreement FROM $table
4507
                    WHERE user_id = $user_id AND c_id = $courseId AND session_id = $session_id";
4508
            $result = Database::query($sql);
4509
            if (Database::num_rows($result) > 0) {
4510
                $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...
4511
                if ($result['legal_agreement'] == 1) {
4512
                    return true;
4513
                }
4514
            }
4515
            return false;
4516
        }
4517
    }
4518
4519
    /**
4520
     * Saves the user-course legal agreement
4521
     * @param   int user id
4522
     * @param   string course code
4523
     * @param   int session id
4524
     * @return mixed
4525
     */
4526
    public static function save_user_legal($user_id, $course_code, $session_id = null)
4527
    {
4528
        // Course plugin legal
4529
        $enabled = api_get_plugin_setting('courselegal', 'tool_enable');
4530
4531 View Code Duplication
        if ($enabled == 'true') {
4532
            require_once api_get_path(SYS_PLUGIN_PATH) . 'courselegal/config.php';
4533
            $plugin = CourseLegalPlugin::create();
4534
            return $plugin->saveUserLegal($user_id, $course_code, $session_id);
4535
        }
4536
4537
        $user_id = intval($user_id);
4538
        $course_code = Database::escape_string($course_code);
4539
        $session_id = intval($session_id);
4540
4541
        $courseInfo = api_get_course_info($course_code);
4542
        $courseId = $courseInfo['real_id'];
4543
4544
        if (empty($session_id)) {
4545
            $table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4546
            $sql = "UPDATE $table SET legal_agreement = '1'
4547
                    WHERE user_id = $user_id AND c_id  = $courseId ";
4548
            Database::query($sql);
4549
        } else {
4550
            $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4551
            $sql = "UPDATE  $table SET legal_agreement = '1'
4552
                    WHERE user_id = $user_id AND c_id = $courseId AND session_id = $session_id";
4553
            Database::query($sql);
4554
        }
4555
    }
4556
4557
    /**
4558
     * @param int $user_id
4559
     * @param int $course_id
4560
     * @param int $session_id
4561
     * @param int $url_id
4562
     * @return bool
4563
     */
4564
    public static function get_user_course_vote($user_id, $course_id, $session_id = null, $url_id = null)
4565
    {
4566
        $table_user_course_vote = Database::get_main_table(TABLE_MAIN_USER_REL_COURSE_VOTE);
4567
4568
        $session_id = !isset($session_id) ? api_get_session_id() : intval($session_id);
4569
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4570
        $user_id = intval($user_id);
4571
4572
        if (empty($user_id)) {
4573
            return false;
4574
        }
4575
4576
        $params = array(
4577
            'user_id' => $user_id,
4578
            'c_id' => $course_id,
4579
            'session_id' => $session_id,
4580
            'url_id' => $url_id
4581
        );
4582
4583
        $result = Database::select(
4584
            'vote',
4585
            $table_user_course_vote,
4586
            array(
4587
                'where' => array(
4588
                    'user_id = ? AND c_id = ? AND session_id = ? AND url_id = ?' => $params
4589
                )
4590
            ),
4591
            'first'
4592
        );
4593
        if (!empty($result)) {
4594
            return $result['vote'];
4595
        }
4596
        return false;
4597
    }
4598
4599
    /**
4600
     * @param int $course_id
4601
     * @param int $session_id
4602
     * @param int $url_id
4603
     * @return array
4604
     */
4605
    public static function get_course_ranking($course_id, $session_id = null, $url_id = null)
4606
    {
4607
        $table_course_ranking = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
4608
4609
        $session_id = !isset($session_id) ? api_get_session_id() : intval($session_id);
4610
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4611
        $now = api_get_utc_datetime();
4612
4613
        $params = array(
4614
            'c_id' => $course_id,
4615
            'session_id' => $session_id,
4616
            'url_id' => $url_id,
4617
            'creation_date' => $now,
4618
        );
4619
4620
        $result = Database::select(
4621
            'c_id, accesses, total_score, users',
4622
            $table_course_ranking,
4623
            array('where' => array('c_id = ? AND session_id = ? AND url_id = ?' => $params)),
4624
            'first'
4625
        );
4626
4627
        $point_average_in_percentage = 0;
4628
        $point_average_in_star = 0;
4629
        $users_who_voted = 0;
4630
4631
        if (!empty($result['users'])) {
4632
            $users_who_voted = $result['users'];
4633
            $point_average_in_percentage = round($result['total_score'] / $result['users'] * 100 / 5, 2);
4634
            $point_average_in_star = round($result['total_score'] / $result['users'], 1);
4635
        }
4636
4637
        $result['user_vote'] = false;
4638
4639
        if (!api_is_anonymous()) {
4640
            $result['user_vote'] = self::get_user_course_vote(api_get_user_id(), $course_id, $session_id, $url_id);
4641
        }
4642
4643
        $result['point_average'] = $point_average_in_percentage;
4644
        $result['point_average_star'] = $point_average_in_star;
4645
        $result['users_who_voted'] = $users_who_voted;
4646
4647
        return $result;
4648
    }
4649
4650
    /**
4651
     *
4652
     * Updates the course ranking
4653
     * @param int   course id
4654
     * @param int   session id
4655
     * @param id    url id
4656
     * @param integer $session_id
4657
     * @return array
4658
     **/
4659
    public static function update_course_ranking(
4660
        $course_id = null,
4661
        $session_id = null,
4662
        $url_id = null,
4663
        $points_to_add = null,
4664
        $add_access = true,
4665
        $add_user = true
4666
    ) {
4667
        // Course catalog stats modifications see #4191
4668
        $table_course_ranking = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
4669
4670
        $now = api_get_utc_datetime();
4671
4672
        $course_id = empty($course_id) ? api_get_course_int_id() : intval($course_id);
4673
        $session_id = !isset($session_id) ? api_get_session_id() : intval($session_id);
4674
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4675
4676
        $params = array(
4677
            'c_id' => $course_id,
4678
            'session_id' => $session_id,
4679
            'url_id' => $url_id,
4680
            'creation_date' => $now,
4681
            'total_score' => 0,
4682
            'users' => 0
4683
        );
4684
4685
        $result = Database::select(
4686
            'id, accesses, total_score, users',
4687
            $table_course_ranking,
4688
            array('where' => array('c_id = ? AND session_id = ? AND url_id = ?' => $params)),
4689
            'first'
4690
        );
4691
4692
        // Problem here every time we load the courses/XXXX/index.php course home page we update the access
4693
4694
        if (empty($result)) {
4695
            if ($add_access) {
4696
                $params['accesses'] = 1;
4697
            }
4698
            //The votes and users are empty
4699
            if (isset($points_to_add) && !empty($points_to_add)) {
4700
                $params['total_score'] = intval($points_to_add);
4701
            }
4702
            if ($add_user) {
4703
                $params['users'] = 1;
4704
            }
4705
            $result = Database::insert($table_course_ranking, $params);
4706
        } else {
4707
            $my_params = array();
4708
4709
            if ($add_access) {
4710
                $my_params['accesses'] = intval($result['accesses']) + 1;
4711
            }
4712
            if (isset($points_to_add) && !empty($points_to_add)) {
4713
                $my_params['total_score'] = $result['total_score'] + $points_to_add;
4714
            }
4715
            if ($add_user) {
4716
                $my_params['users'] = $result['users'] + 1;
4717
            }
4718
4719
            if (!empty($my_params)) {
4720
                $result = Database::update(
4721
                    $table_course_ranking,
4722
                    $my_params,
4723
                    array('c_id = ? AND session_id = ? AND url_id = ?' => $params)
4724
                );
4725
            }
4726
        }
4727
4728
        return $result;
4729
    }
4730
4731
    /**
4732
     * Add user vote to a course
4733
     *
4734
     * @param   int user id
4735
     * @param   int vote [1..5]
4736
     * @param   int course id
4737
     * @param   int session id
4738
     * @param   int url id (access_url_id)
4739
     * @return    false|string 'added', 'updated' or 'nothing'
4740
     */
4741
    public static function add_course_vote($user_id, $vote, $course_id, $session_id = null, $url_id = null)
4742
    {
4743
        $table_user_course_vote = Database::get_main_table(TABLE_MAIN_USER_REL_COURSE_VOTE);
4744
        $course_id = empty($course_id) ? api_get_course_int_id() : intval($course_id);
4745
4746
        if (empty($course_id) || empty($user_id)) {
4747
            return false;
4748
        }
4749
4750
        if (!in_array($vote, array(1, 2, 3, 4, 5))) {
4751
            return false;
4752
        }
4753
4754
        $session_id = !isset($session_id) ? api_get_session_id() : intval($session_id);
4755
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4756
        $vote = intval($vote);
4757
4758
        $params = array(
4759
            'user_id' => intval($user_id),
4760
            'c_id' => $course_id,
4761
            'session_id' => $session_id,
4762
            'url_id' => $url_id,
4763
            'vote' => $vote
4764
        );
4765
4766
        $action_done = 'nothing';
4767
4768
        $result = Database::select(
4769
            'id, vote',
4770
            $table_user_course_vote,
4771
            array('where' => array('user_id = ? AND c_id = ? AND session_id = ? AND url_id = ?' => $params)),
4772
            'first'
4773
        );
4774
4775
        if (empty($result)) {
4776
            Database::insert($table_user_course_vote, $params);
4777
            $points_to_add = $vote;
4778
            $add_user = true;
4779
            $action_done = 'added';
4780
        } else {
4781
            $my_params = array('vote' => $vote);
4782
            $points_to_add = $vote - $result['vote'];
4783
            $add_user = false;
4784
4785
            Database::update(
4786
                $table_user_course_vote,
4787
                $my_params,
4788
                array('user_id = ? AND c_id = ? AND session_id = ? AND url_id = ?' => $params)
4789
            );
4790
            $action_done = 'updated';
4791
        }
4792
4793
        // Current points
4794
        if (!empty($points_to_add)) {
4795
            self::update_course_ranking(
4796
                $course_id,
4797
                $session_id,
4798
                $url_id,
4799
                $points_to_add,
4800
                false,
4801
                $add_user
4802
            );
4803
        }
4804
        return $action_done;
4805
    }
4806
4807
    /**
4808
     * Remove course ranking + user votes
4809
     *
4810
     * @param int $course_id
4811
     * @param int $session_id
4812
     * @param int $url_id
4813
     *
4814
     */
4815
    public static function remove_course_ranking($course_id, $session_id, $url_id = null)
4816
    {
4817
        $table_course_ranking = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
4818
        $table_user_course_vote = Database::get_main_table(TABLE_MAIN_USER_REL_COURSE_VOTE);
4819
4820
        if (!empty($course_id) && isset($session_id)) {
4821
            $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4822
            $params = array(
4823
                'c_id' => $course_id,
4824
                'session_id' => $session_id,
4825
                'url_id' => $url_id,
4826
            );
4827
            Database::delete($table_course_ranking, array('c_id = ? AND session_id = ? AND url_id = ?' => $params));
4828
            Database::delete($table_user_course_vote, array('c_id = ? AND session_id = ? AND url_id = ?' => $params));
4829
        }
4830
    }
4831
4832
    /**
4833
     * Returns an array with the hottest courses
4834
     * @param   int $days number of days
4835
     * @param   int $limit number of hottest courses
4836
     * @return array
4837
     */
4838
    public static function return_hot_courses($days = 30, $limit = 6)
4839
    {
4840
        if (api_is_invitee()) {
4841
            return array();
4842
        }
4843
4844
        $limit = intval($limit);
4845
4846
        // Getting my courses
4847
        $my_course_list = CourseManager::get_courses_list_by_user_id(api_get_user_id());
4848
4849
        $my_course_code_list = array();
4850
        foreach ($my_course_list as $course) {
4851
            $my_course_code_list[$course['real_id']] = $course['real_id'];
4852
        }
4853
4854
        if (api_is_drh()) {
4855
            $courses = CourseManager::get_courses_followed_by_drh(api_get_user_id());
4856
            foreach ($courses as $course) {
4857
                $my_course_code_list[$course['real_id']] = $course['real_id'];
4858
            }
4859
        }
4860
4861
        $table_course_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
4862
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
4863
        $table_course_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
4864
4865
        //$table_course_access table uses the now() and interval ...
4866
        $now = api_get_utc_datetime(time());
4867
        $sql = "SELECT COUNT(course_access_id) course_count, a.c_id, visibility
4868
                FROM $table_course c
4869
                INNER JOIN $table_course_access a
4870
                ON (c.id = a.c_id)
4871
                INNER JOIN $table_course_url u
4872
                ON u.c_id = c.id
4873
                WHERE
4874
                    u.access_url_id = " . api_get_current_access_url_id() . " AND
4875
                    login_course_date <= '$now' AND
4876
                    login_course_date > DATE_SUB('$now', INTERVAL $days DAY) AND
4877
                    visibility <> '" . COURSE_VISIBILITY_CLOSED . "' AND visibility <> '" . COURSE_VISIBILITY_HIDDEN . "'
4878
                GROUP BY a.c_id
4879
                ORDER BY course_count DESC
4880
                LIMIT $limit
4881
            ";
4882
4883
        $result = Database::query($sql);
4884
        $courses = array();
4885
4886
        if (Database::num_rows($result)) {
4887
            $courses = Database::store_result($result, 'ASSOC');
4888
            $courses = self::process_hot_course_item($courses, $my_course_code_list);
4889
        }
4890
4891
        return $courses;
4892
    }
4893
4894
    /**
4895
     * @param array $courses
4896
     * @param array $my_course_code_list
4897
     * @return mixed
4898
     */
4899
    public static function process_hot_course_item($courses, $my_course_code_list = array())
4900
    {
4901
        $hotCourses = [];
4902
4903
        $ajax_url = api_get_path(WEB_AJAX_PATH) . 'course.ajax.php?a=add_course_vote';
4904
4905
        $stok = Security::get_existing_token();
4906
4907
        $user_id = api_get_user_id();
4908
4909
        foreach ($courses as $courseId) {
4910
            $course_info = api_get_course_info_by_id($courseId['c_id']);
4911
            $courseCode = $course_info['code'];
4912
            $categoryCode = !empty($course_info['categoryCode']) ? $course_info['categoryCode'] : "";
4913
            $my_course = $course_info;
4914
            $my_course['go_to_course_button'] = '';
4915
            $my_course['register_button'] = '';
4916
4917
            $access_link = self::get_access_link_by_user(
4918
                api_get_user_id(),
4919
                $course_info,
4920
                $my_course_code_list
4921
            );
4922
4923
            $user_registerd_in_course = CourseManager::is_user_subscribed_in_course($user_id, $course_info['code']);
4924
            $user_registerd_in_course_as_teacher = CourseManager::is_course_teacher($user_id, $course_info['code']);
4925
            $user_registerd_in_course_as_student = ($user_registerd_in_course && !$user_registerd_in_course_as_teacher);
4926
4927
            // if user registered as student
4928
            if ($user_registerd_in_course_as_student) {
4929
                $icon = '<em class="fa fa-graduation-cap"></em>';
4930
                $title = get_lang("AlreadyRegisteredToCourse");
4931
                $my_course['already_register_as'] = Display::tag(
4932
                    'button',
4933
                    $icon,
4934
                    array('id' => 'register', 'class' => 'btn btn-default btn-sm', 'title' => $title)
4935
                );
4936
            } elseif ($user_registerd_in_course_as_teacher) {
4937
                // if user registered as teacher
4938
                $icon = '<em class="fa fa-suitcase"></em>';
4939
                $title = get_lang("YouAreATeacherOfThisCourse");
4940
                $my_course['already_register_as'] = Display::tag(
4941
                    'button',
4942
                    $icon,
4943
                    array('id' => 'register', 'class' => 'btn btn-default btn-sm', 'title' => $title)
4944
                );
4945
            }
4946
4947
            //Course visibility
4948 View Code Duplication
            if ($access_link && in_array('register', $access_link)) {
4949
                $my_course['register_button'] = Display::url(
4950
                    Display::returnFontAwesomeIcon('sign-in'),
4951
                    api_get_path(WEB_COURSE_PATH) . $course_info['path'] . '/index.php?action=subscribe&sec_token=' . $stok,
4952
                    array('class' => 'btn btn-success btn-sm', 'title' => get_lang('Subscribe')));
4953
            }
4954
4955 View Code Duplication
            if ($access_link && in_array('enter',
4956
                    $access_link) || $course_info['visibility'] == COURSE_VISIBILITY_OPEN_WORLD
4957
            ) {
4958
                $my_course['go_to_course_button'] = Display::url(
4959
                    Display::returnFontAwesomeIcon('share'),
4960
                    api_get_path(WEB_COURSE_PATH) . $course_info['path'] . '/index.php',
4961
                    array('class' => 'btn btn-default btn-sm', 'title' => get_lang('GoToCourse')));
4962
            }
4963
4964
            if ($access_link && in_array('unsubscribe', $access_link)) {
4965
                $my_course['unsubscribe_button'] = Display::url(
4966
                    Display::returnFontAwesomeIcon('sign-out'),
4967
                    api_get_path(WEB_CODE_PATH) . 'auth/courses.php?action=unsubscribe&unsubscribe=' . $courseCode . '&sec_token=' . $stok . '&category_code=' . $categoryCode,
4968
                    array('class' => 'btn btn-danger btn-sm', 'title' => get_lang('Unreg')));
4969
            }
4970
4971
            // start buycourse validation
4972
            // display the course price and buy button if the buycourses plugin is enabled and this course is configured
4973
            $plugin = BuyCoursesPlugin::create();
4974
            $isThisCourseInSale = $plugin->buyCoursesForGridCatalogVerificator($course_info['real_id'], BuyCoursesPlugin::PRODUCT_TYPE_COURSE);
4975
            if ($isThisCourseInSale) {
4976
                // set the price label
4977
                $my_course['price'] = $isThisCourseInSale['html'];
4978
                // set the Buy button instead register.
4979
                if ($isThisCourseInSale['verificator'] && !empty($my_course['register_button'])) {
4980
                    $my_course['register_button'] = $plugin->returnBuyCourseButton($course_info['real_id'], BuyCoursesPlugin::PRODUCT_TYPE_COURSE);
4981
                }
4982
            }
4983
            // end buycourse validation
4984
4985
            //Description
4986
            $my_course['description_button'] = '';
4987
            /* if ($course_info['visibility'] == COURSE_VISIBILITY_OPEN_WORLD || in_array($course_info['real_id'],
4988
                    $my_course_code_list)
4989
            ) { */
4990
                $my_course['description_button'] = Display::url(
4991
                    Display::returnFontAwesomeIcon('info-circle'),
4992
                    api_get_path(WEB_AJAX_PATH) . 'course_home.ajax.php?a=show_course_information&code=' . $course_info['code'],
4993
                    [
4994
                        'class' => 'btn btn-default btn-sm ajax',
4995
                        'data-title' => get_lang('Description'),
4996
                        'title' => get_lang('Description')
4997
                    ]
4998
                );
4999
            //}
5000
            /* get_lang('Description') */
5001
            $my_course['teachers'] = CourseManager::getTeachersFromCourseByCode($course_info['code']);
5002
            $point_info = self::get_course_ranking($course_info['real_id'], 0);
5003
            $my_course['rating_html'] = Display::return_rating_system('star_' . $course_info['real_id'],
5004
                $ajax_url . '&course_id=' . $course_info['real_id'], $point_info);
5005
5006
            $hotCourses[] = $my_course;
5007
        }
5008
        return $hotCourses;
5009
    }
5010
5011
    /**
5012
     * @param int $limit
5013
     * @return array
5014
     */
5015
    public static function return_most_accessed_courses($limit = 5)
5016
    {
5017
        $table_course_ranking = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
5018
        $params['url_id'] = api_get_current_access_url_id();
5019
5020
        $result = Database::select(
5021
            'c_id, accesses, total_score, users',
5022
            $table_course_ranking,
5023
            array('where' => array('url_id = ?' => $params), 'order' => 'accesses DESC', 'limit' => $limit),
5024
            'all',
5025
            true
5026
        );
5027
        return $result;
5028
    }
5029
5030
    /**
5031
     * Get courses count
5032
     * @param int Access URL ID (optional)
5033
     * @param int $visibility
5034
     * @param integer $access_url_id
5035
     *
5036
     * @return int Number of courses
5037
     */
5038
    public static function count_courses($access_url_id = null, $visibility = null)
5039
    {
5040
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
5041
        $table_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
5042
        $sql = "SELECT count(c.id) FROM $table_course c";
5043
        if (!empty($access_url_id) && $access_url_id == intval($access_url_id)) {
5044
            $sql .= ", $table_course_rel_access_url u
5045
                    WHERE c.id = u.c_id AND u.access_url_id = $access_url_id";
5046
            if (!empty($visibility)) {
5047
                $visibility = intval($visibility);
5048
                $sql .= " AND visibility = $visibility ";
5049
            }
5050
        } else {
5051
            if (!empty($visibility)) {
5052
                $visibility = intval($visibility);
5053
                $sql .= " WHERE visibility = $visibility ";
5054
            }
5055
        }
5056
5057
        $res = Database::query($sql);
5058
        $row = Database::fetch_row($res);
5059
5060
        return $row[0];
5061
    }
5062
5063
    /**
5064
     * Get active courses count.
5065
     * Active = all courses except the ones with hidden visibility.
5066
     *
5067
     * @param int $urlId Access URL ID (optional)
5068
     * @return int Number of courses
5069
     */
5070
    public static function countActiveCourses($urlId = null)
5071
    {
5072
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
5073
        $table_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
5074
        $sql = "SELECT count(id) FROM $table_course c";
5075
        if (!empty($urlId) && $urlId == intval($urlId)) {
5076
            $sql .= ", $table_course_rel_access_url u
5077
                    WHERE
5078
                        c.id = u.c_id AND
5079
                        u.access_url_id = $urlId AND
5080
                        visibility <> " . COURSE_VISIBILITY_HIDDEN;
5081
        } else {
5082
            $sql .= " WHERE visibility <> " . COURSE_VISIBILITY_HIDDEN;
5083
        }
5084
        $res = Database::query($sql);
5085
        $row = Database::fetch_row($res);
5086
        return $row[0];
5087
    }
5088
5089
    /**
5090
     * Returns the SQL conditions to filter course only visible by the user in the catalogue
5091
     *
5092
     * @param $courseTableAlias Alias of the course table
5093
     * @return string SQL conditions
5094
     */
5095
    public static function getCourseVisibilitySQLCondition($courseTableAlias) {
5096
        $visibilityCondition = '';
5097
        $hidePrivate = api_get_setting('course_catalog_hide_private');
5098
        if ($hidePrivate === 'true') {
5099
            $visibilityCondition = ' AND '.$courseTableAlias.'.visibility <> 1';
5100
        }
5101
5102
        // Check if course have users allowed to see it in the catalogue, then show only if current user is allowed to see it
5103
        $currentUserId = api_get_user_id();
5104
        $restrictedCourses = self::getCatalogueCourseList(true);
5105
        $allowedCoursesToCurrentUser = self::getCatalogueCourseList(true, $currentUserId);
5106 View Code Duplication
        if (!empty($restrictedCourses)) {
5107
            $visibilityCondition .= ' AND ('.$courseTableAlias.'.code NOT IN ("' . implode('","', $restrictedCourses) . '")';
5108
            $visibilityCondition .= ' OR '.$courseTableAlias.'.code IN ("' . implode('","', $allowedCoursesToCurrentUser) . '"))';
5109
        }
5110
5111
        // Check if course have users denied to see it in the catalogue, then show only if current user is not denied to see it
5112
        $restrictedCourses = self::getCatalogueCourseList(false);
5113
        $notAllowedCoursesToCurrentUser = self::getCatalogueCourseList(false, $currentUserId);
5114 View Code Duplication
        if (!empty($restrictedCourses)) {
5115
            $visibilityCondition .= ' AND ('.$courseTableAlias.'.code NOT IN ("' . implode('","', $restrictedCourses) . '")';
5116
            $visibilityCondition .= ' OR '.$courseTableAlias.'.code NOT IN ("' . implode('","', $notAllowedCoursesToCurrentUser) . '"))';
5117
        }
5118
5119
        return $visibilityCondition;
5120
    }
5121
5122
    /**
5123
     * Get available le courses count
5124
     * @param int Access URL ID (optional)
5125
     * @param integer $accessUrlId
5126
     * @return int Number of courses
5127
     */
5128
    public static function countAvailableCourses($accessUrlId = null)
5129
    {
5130
        $tableCourse = Database::get_main_table(TABLE_MAIN_COURSE);
5131
        $tableCourseRelAccessUrl = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
5132
        $specialCourseList = self::get_special_course_list();
5133
5134
        $withoutSpecialCourses = '';
5135
        if (!empty($specialCourseList)) {
5136
            $withoutSpecialCourses = ' AND c.code NOT IN ("' . implode('","', $specialCourseList) . '")';
5137
        }
5138
5139
        $visibilityCondition = self::getCourseVisibilitySQLCondition('c');
5140
5141
        if (!empty($accessUrlId) && $accessUrlId == intval($accessUrlId)) {
5142
            $sql = "SELECT count(c.id) FROM $tableCourse c, $tableCourseRelAccessUrl u
5143
                    WHERE
5144
                        c.id = u.c_id AND
5145
                        u.access_url_id = $accessUrlId AND
5146
                        c.visibility != 0 AND
5147
                        c.visibility != 4
5148
                        $withoutSpecialCourses
5149
                        $visibilityCondition
5150
                    ";
5151
        }
5152
        $res = Database::query($sql);
5153
        $row = Database::fetch_row($res);
5154
5155
        return $row[0];
5156
    }
5157
5158
    /**
5159
     * Return a link to go to the course, validating the visibility of the
5160
     * course and the user status
5161
     * @param int User ID
5162
     * @param array Course details array
5163
     * @param array  List of courses to which the user is subscribed (if not provided, will be generated)
5164
     * @param integer $uid
5165
     * @return mixed 'enter' for a link to go to the course or 'register' for a link to subscribe, or false if no access
5166
     */
5167
    static function get_access_link_by_user($uid, $course, $user_courses = array())
5168
    {
5169
        if (empty($uid) or empty($course)) {
5170
            return false;
5171
        }
5172
5173
        if (empty($user_courses)) {
5174
            // get the array of courses to which the user is subscribed
5175
            $user_courses = CourseManager::get_courses_list_by_user_id($uid);
5176
            foreach ($user_courses as $k => $v) {
5177
                $user_courses[$k] = $v['real_id'];
5178
            }
5179
        }
5180
5181
        if (!isset($course['real_id']) && empty($course['real_id'])) {
5182
            $course = api_get_course_info($course['code']);
5183
        }
5184
5185
        if ($course['visibility'] == COURSE_VISIBILITY_HIDDEN) {
5186
            return array();
5187
        }
5188
5189
        $is_admin = api_is_platform_admin_by_id($uid);
5190
        $options = array();
5191
        // Register button
5192
        if (!api_is_anonymous($uid) &&
5193
            (
5194
            ($course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD || $course['visibility'] == COURSE_VISIBILITY_OPEN_PLATFORM)
5195
                //$course['visibility'] == COURSE_VISIBILITY_REGISTERED && $course['subscribe'] == SUBSCRIBE_ALLOWED
5196
            ) &&
5197
            $course['subscribe'] == SUBSCRIBE_ALLOWED &&
5198
            (!in_array($course['real_id'], $user_courses) || empty($user_courses))
5199
        ) {
5200
            $options[] = 'register';
5201
        }
5202
5203
        // Go To Course button (only if admin, if course public or if student already subscribed)
5204 View Code Duplication
        if ($is_admin ||
5205
            $course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD && empty($course['registration_code']) ||
5206
            (api_user_is_login($uid) && $course['visibility'] == COURSE_VISIBILITY_OPEN_PLATFORM && empty($course['registration_code'])) ||
5207
            (in_array($course['real_id'], $user_courses) && $course['visibility'] != COURSE_VISIBILITY_CLOSED)
5208
        ) {
5209
            $options[] = 'enter';
5210
        }
5211
5212 View Code Duplication
        if ($is_admin ||
5213
            $course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD && empty($course['registration_code']) ||
5214
            (api_user_is_login($uid) && $course['visibility'] == COURSE_VISIBILITY_OPEN_PLATFORM && empty($course['registration_code'])) ||
5215
            (in_array($course['real_id'], $user_courses) && $course['visibility'] != COURSE_VISIBILITY_CLOSED)
5216
        ) {
5217
            $options[] = 'enter';
5218
        }
5219
5220
        if ($course['visibility'] != COURSE_VISIBILITY_HIDDEN && empty($course['registration_code']) && $course['unsubscribe'] == UNSUBSCRIBE_ALLOWED && api_user_is_login($uid) && (in_array($course['real_id'],
5221
                $user_courses))
5222
        ) {
5223
            $options[] = 'unsubscribe';
5224
        }
5225
5226
        return $options;
5227
    }
5228
5229
    /**
5230
     * @param array $courseInfo
5231
     * @param array $teachers
5232
     * @param bool $deleteTeachersNotInList
5233
     * @param bool $editTeacherInSessions
5234
     * @param bool $deleteSessionTeacherNotInList
5235
     * @return false|null
5236
     */
5237
    public static function updateTeachers(
5238
        $courseInfo,
5239
        $teachers,
5240
        $deleteTeachersNotInList = true,
5241
        $editTeacherInSessions = false,
5242
        $deleteSessionTeacherNotInList = false,
5243
        $teacherBackup = array()
5244
    ) {
5245
        if (empty($teachers)) {
5246
            return false;
5247
        }
5248
5249
        if (!is_array($teachers)) {
5250
            $teachers = array($teachers);
5251
        }
5252
5253
        if (empty($courseInfo) || !isset($courseInfo['real_id'])) {
5254
            return false;
5255
        }
5256
5257
        $courseId = $courseInfo['real_id'];
5258
        $course_code = $courseInfo['code'];
5259
5260
        $course_user_table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5261
        $alreadyAddedTeachers = CourseManager::get_teacher_list_from_course_code($course_code);
5262
5263
        if ($deleteTeachersNotInList) {
5264
5265
            // Delete only teacher relations that doesn't match the selected teachers
5266
            $cond = null;
5267
            if (count($teachers) > 0) {
5268
                foreach ($teachers as $key) {
5269
                    $key = Database::escape_string($key);
5270
                    $cond .= " AND user_id <> '" . $key . "'";
5271
                }
5272
            }
5273
5274
            $sql = 'DELETE FROM ' . $course_user_table . '
5275
                    WHERE c_id ="' . $courseId . '" AND status="1" AND relation_type = 0 ' . $cond;
5276
            Database::query($sql);
5277
        }
5278
5279
        if (count($teachers) > 0) {
5280
            foreach ($teachers as $userId) {
5281
                $userId = intval($userId);
5282
                // We check if the teacher is already subscribed in this course
5283
                $sql = 'SELECT 1 FROM ' . $course_user_table . '
5284
                        WHERE user_id = "' . $userId . '" AND c_id = "' . $courseId . '" ';
5285
                $result = Database::query($sql);
5286
                if (Database::num_rows($result)) {
5287
                    $sql = 'UPDATE ' . $course_user_table . ' SET status = "1"
5288
                            WHERE c_id = "' . $courseId . '" AND user_id = "' . $userId . '"  ';
5289
                } else {
5290
                    $userCourseCategory = '0';
5291 View Code Duplication
                    if (isset($teacherBackup[$userId]) &&
5292
                        isset($teacherBackup[$userId][$course_code])
5293
                    ) {
5294
                        $courseUserData = $teacherBackup[$userId][$course_code];
5295
                        $userCourseCategory = $courseUserData['user_course_cat'];
5296
                    }
5297
5298
                    $sql = "INSERT INTO " . $course_user_table . " SET
5299
                            c_id = " . $courseId . ",
5300
                            user_id = " . $userId . ",
5301
                            status = '1',
5302
                            is_tutor = '0',
5303
                            sort = '0',
5304
                            relation_type = '0',
5305
                            user_course_cat = '$userCourseCategory'
5306
                    ";
5307
                }
5308
                Database::query($sql);
5309
            }
5310
        }
5311
5312
        if ($editTeacherInSessions) {
5313
            $sessions = SessionManager::get_session_by_course($courseId);
5314
5315
            if (!empty($sessions)) {
5316
                foreach ($sessions as $session) {
5317
                    // Remove old and add new
5318
                    if ($deleteSessionTeacherNotInList) {
5319
                        foreach ($teachers as $userId) {
5320
                            SessionManager::set_coach_to_course_session(
5321
                                $userId,
5322
                                $session['id'],
5323
                                $courseId
5324
                            );
5325
                        }
5326
5327
                        $teachersToDelete = array();
5328
                        if (!empty($alreadyAddedTeachers)) {
5329
                            $teachersToDelete = array_diff(array_keys($alreadyAddedTeachers), $teachers);
5330
                        }
5331
5332
                        if (!empty($teachersToDelete)) {
5333
                            foreach ($teachersToDelete as $userId) {
5334
                                SessionManager::set_coach_to_course_session(
5335
                                    $userId,
5336
                                    $session['id'],
5337
                                    $courseId,
5338
                                    true
5339
                                );
5340
                            }
5341
                        }
5342
                    } else {
5343
                        // Add new teachers only
5344
                        foreach ($teachers as $userId) {
5345
                            SessionManager::set_coach_to_course_session(
5346
                                $userId,
5347
                                $session['id'],
5348
                                $courseId
5349
                            );
5350
                        }
5351
                    }
5352
                }
5353
            }
5354
        }
5355
    }
5356
5357
    /**
5358
     * Course available settings variables see c_course_setting table
5359
     * @param AppPlugin $appPlugin
5360
     * @return array
5361
     */
5362
    public static function getCourseSettingVariables(AppPlugin $appPlugin)
5363
    {
5364
        $pluginCourseSettings = $appPlugin->getAllPluginCourseSettings();
5365
        $courseSettings = array(
5366
            // Get allow_learning_path_theme from table
5367
            'allow_learning_path_theme',
5368
            // Get allow_open_chat_window from table
5369
            'allow_open_chat_window',
5370
            'allow_public_certificates',
5371
            // Get allow_user_edit_agenda from table
5372
            'allow_user_edit_agenda',
5373
            // Get allow_user_edit_announcement from table
5374
            'allow_user_edit_announcement',
5375
            // Get allow_user_image_forum from table
5376
            'allow_user_image_forum',
5377
            //Get allow show user list
5378
            'allow_user_view_user_list',
5379
            // Get course_theme from table
5380
            'course_theme',
5381
            //Get allow show user list
5382
            'display_info_advance_inside_homecourse',
5383
            'documents_default_visibility',
5384
            // Get send_mail_setting (work)from table
5385
            'email_alert_manager_on_new_doc',
5386
            // Get send_mail_setting (work)from table
5387
            'email_alert_manager_on_new_quiz',
5388
            // Get send_mail_setting (dropbox) from table
5389
            'email_alert_on_new_doc_dropbox',
5390
            'email_alert_students_on_new_homework',
5391
            // Get send_mail_setting (auth)from table
5392
            'email_alert_to_teacher_on_new_user_in_course',
5393
            'enable_lp_auto_launch',
5394
            'pdf_export_watermark_text',
5395
            'show_system_folders',
5396
            'exercise_invisible_in_session',
5397
            'enable_forum_auto_launch',
5398
            'show_course_in_user_language'
5399
        );
5400
5401
        $allowLPReturnLink = api_get_setting('allow_lp_return_link');
5402
        if ($allowLPReturnLink === 'true') {
5403
            $courseSettings[] = 'lp_return_link';
5404
        }
5405
5406
        if (!empty($pluginCourseSettings)) {
5407
            $courseSettings = array_merge(
5408
                $courseSettings,
5409
                $pluginCourseSettings
5410
            );
5411
        }
5412
5413
        return $courseSettings;
5414
    }
5415
5416
    /**
5417
     * @param AppPlugin $appPlugin
5418
     * @param string $variable
5419
     * @param string $value
5420
     * @param int $courseId
5421
     * @return bool
5422
     */
5423
    public static function saveCourseConfigurationSetting(AppPlugin $appPlugin, $variable, $value, $courseId)
5424
    {
5425
        $settingList = self::getCourseSettingVariables($appPlugin);
5426
5427
        if (!in_array($variable, $settingList)) {
5428
5429
            return false;
5430
        }
5431
5432
        $courseSettingTable = Database::get_course_table(TABLE_COURSE_SETTING);
5433
        if (self::hasCourseSetting($variable, $courseId)) {
5434
            // Update
5435
            Database::update(
5436
                $courseSettingTable,
5437
                array('value' => $value),
5438
                array('variable = ? AND c_id = ?' => array($variable, $courseId))
5439
            );
5440
        } else {
5441
            // Create
5442
            Database::insert(
5443
                $courseSettingTable,
5444
                ['title' => $variable, 'value' => $value, 'c_id' => $courseId, 'variable' => $variable]
5445
            );
5446
        }
5447
        return true;
5448
    }
5449
5450
    /**
5451
     * Check if course setting exists
5452
     * @param string $variable
5453
     * @param int $courseId
5454
     * @return bool
5455
     */
5456 View Code Duplication
    public static function hasCourseSetting($variable, $courseId)
5457
    {
5458
        $courseSetting = Database::get_course_table(TABLE_COURSE_SETTING);
5459
        $courseId = intval($courseId);
5460
        $variable = Database::escape_string($variable);
5461
        $sql = "SELECT variable FROM $courseSetting
5462
                WHERE c_id = $courseId AND variable = '$variable'";
5463
        $result = Database::query($sql);
5464
5465
        return Database::num_rows($result) > 0;
5466
    }
5467
5468
    /**
5469
     * Get information from the track_e_course_access table
5470
     * @param int $sessionId
5471
     * @param int $userId
5472
     * @return array
5473
     */
5474 View Code Duplication
    public static function getCourseAccessPerSessionAndUser($sessionId, $userId, $limit = null)
5475
    {
5476
        $table = Database:: get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
5477
5478
        $sessionId = intval($sessionId);
5479
        $userId = intval($userId);
5480
5481
        $sql = "SELECT * FROM $table
5482
                WHERE session_id = $sessionId AND user_id = $userId";
5483
5484
        if (!empty($limit)) {
5485
            $limit = intval($limit);
5486
            $sql .= " LIMIT $limit";
5487
        }
5488
        $result = Database::query($sql);
5489
5490
        return Database::store_result($result);
5491
    }
5492
5493
    /**
5494
     * Get information from the track_e_course_access table
5495
     * @param int $courseId
5496
     * @param int $sessionId
5497
     * @param string $startDate
5498
     * @param string $endDate
5499
     * @return array
5500
     */
5501
    public static function getCourseAccessPerCourseAndSession(
5502
        $courseId,
5503
        $sessionId,
5504
        $startDate,
5505
        $endDate
5506
    ) {
5507
        $table = Database:: get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
5508
        $courseId = intval($courseId);
5509
        $sessionId = intval($sessionId);
5510
        $startDate = Database::escape_string($startDate);
5511
        $endDate = Database::escape_string($endDate);
5512
5513
        $sql = "SELECT * FROM $table
5514
                WHERE
5515
                    c_id = $courseId AND
5516
                    session_id = $sessionId AND
5517
                    login_course_date BETWEEN '$startDate' AND '$endDate'
5518
                ";
5519
5520
        $result = Database::query($sql);
5521
5522
        return Database::store_result($result);
5523
    }
5524
5525
    /**
5526
     * Get login information from the track_e_course_access table, for any
5527
     * course in the given session
5528
     * @param int $sessionId
5529
     * @param int $userId
5530
     * @return array
5531
     */
5532
    public static function getFirstCourseAccessPerSessionAndUser($sessionId, $userId)
5533
    {
5534
        $sessionId = intval($sessionId);
5535
        $userId = intval($userId);
5536
5537
        $table = Database:: get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
5538
        $sql = "SELECT * FROM $table
5539
                WHERE session_id = $sessionId AND user_id = $userId
5540
                ORDER BY login_course_date ASC
5541
                LIMIT 1";
5542
5543
        $result = Database::query($sql);
5544
        $courseAccess = array();
5545
        if (Database::num_rows($result)) {
5546
            $courseAccess = Database::fetch_array($result, 'ASSOC');
5547
        }
5548
        return $courseAccess;
5549
    }
5550
5551
    /**
5552
     * @param int $courseId
5553
     * @param int $sessionId
5554
     * @param bool $getAllSessions
5555
     * @return mixed
5556
     */
5557
    public static function getCountForum(
5558
        $courseId,
5559
        $sessionId = 0,
5560
        $getAllSessions = false
5561
    ) {
5562
        $forum = Database::get_course_table(TABLE_FORUM);
5563
        if ($getAllSessions) {
5564
            $sql = "SELECT count(*) as count
5565
                    FROM $forum f
5566
                    WHERE f.c_id = %s";
5567
        } else {
5568
            $sql = "SELECT count(*) as count
5569
                    FROM $forum f
5570
                    WHERE f.c_id = %s and f.session_id = %s";
5571
        }
5572
5573
        $sql = sprintf($sql, intval($courseId), intval($sessionId));
5574
        $result = Database::query($sql);
5575
        $row = Database::fetch_array($result);
5576
5577
        return $row['count'];
5578
    }
5579
5580
    /**
5581
     * @param int $userId
5582
     * @param int $courseId
5583
     * @param int $sessionId
5584
     * @return mixed
5585
     */
5586
    public static function getCountPostInForumPerUser(
5587
        $userId,
5588
        $courseId,
5589
        $sessionId = 0
5590
    ) {
5591
        $forum = Database::get_course_table(TABLE_FORUM);
5592
        $forum_post = Database::get_course_table(TABLE_FORUM_POST);
5593
5594
        $sql = "SELECT count(distinct post_id) as count
5595
                FROM $forum_post p
5596
                INNER JOIN $forum f
5597
                ON f.forum_id = p.forum_id AND f.c_id = p.c_id
5598
                WHERE p.poster_id = %s and f.session_id = %s and p.c_id = %s";
5599
5600
        $sql = sprintf(
5601
            $sql,
5602
            intval($userId),
5603
            intval($sessionId),
5604
            intval($courseId)
5605
        );
5606
5607
        $result = Database::query($sql);
5608
        $row = Database::fetch_array($result);
5609
        return $row['count'];
5610
    }
5611
5612
    /**
5613
     * @param int $userId
5614
     * @param int $courseId
5615
     * @param int $sessionId
5616
     * @return mixed
5617
     */
5618
    public static function getCountForumPerUser(
5619
        $userId,
5620
        $courseId,
5621
        $sessionId = 0
5622
    ) {
5623
        $forum = Database::get_course_table(TABLE_FORUM);
5624
        $forum_post = Database::get_course_table(TABLE_FORUM_POST);
5625
5626
        $sql = "SELECT count(distinct f.forum_id) as count
5627
                FROM $forum_post p
5628
                INNER JOIN $forum f
5629
                ON f.forum_id = p.forum_id AND f.c_id = p.c_id
5630
                WHERE p.poster_id = %s and f.session_id = %s and p.c_id = %s";
5631
5632
        $sql = sprintf(
5633
            $sql,
5634
            intval($userId),
5635
            intval($sessionId),
5636
            intval($courseId)
5637
        );
5638
5639
        $result = Database::query($sql);
5640
        $row = Database::fetch_array($result);
5641
        return $row['count'];
5642
    }
5643
5644
    /**
5645
     * Returns the course name from a given code
5646
     * @param string $code
5647
     */
5648 View Code Duplication
    public static function getCourseNameFromCode($code)
5649
    {
5650
        $tbl_main_categories = Database:: get_main_table(TABLE_MAIN_COURSE);
5651
        $sql = 'SELECT title
5652
                FROM ' . $tbl_main_categories . '
5653
                WHERE code = "' . Database::escape_string($code) . '"';
5654
        $result = Database::query($sql);
5655
        if ($col = Database::fetch_array($result)) {
5656
            return $col['title'];
5657
        }
5658
    }
5659
5660
    /**
5661
     * Generates a course code from a course title
5662
     * @todo Such a function might be useful in other places too. It might be moved in the CourseManager class.
5663
     * @todo the function might be upgraded for avoiding code duplications (currently, it might suggest a code that is already in use)
5664
     * @param string $title A course title
5665
     * @return string A proposed course code
5666
     * +
5667
     * @assert (null,null) === false
5668
     * @assert ('ABC_DEF', null) === 'ABCDEF'
5669
     * @assert ('ABC09*^[%A', null) === 'ABC09A'
5670
     */
5671
    public static function generate_course_code($title)
5672
    {
5673
        return substr(
5674
            preg_replace('/[^A-Z0-9]/', '', strtoupper(api_replace_dangerous_char($title))),
5675
            0,
5676
            CourseManager::MAX_COURSE_LENGTH_CODE
5677
        );
5678
    }
5679
5680
    /**
5681
     * @param $courseId
5682
     * @return array
5683
     */
5684
    public static function getCourseSettings($courseId)
5685
    {
5686
        $settingTable = Database::get_course_table(TABLE_COURSE_SETTING);
5687
        $courseId = intval($courseId);
5688
        $sql = "SELECT * FROM $settingTable WHERE c_id = $courseId";
5689
        $result = Database::query($sql);
5690
        $settings = array();
5691
        if (Database::num_rows($result)) {
5692
            while ($row = Database::fetch_array($result, 'ASSOC')) {
5693
                $settings[$row['variable']] = $row;
5694
            }
5695
        }
5696
        return $settings;
5697
    }
5698
5699
    /**
5700
     * this function gets all the users of the course,
5701
     * including users from linked courses
5702
     */
5703 View Code Duplication
    public static function getCourseUsers()
5704
    {
5705
        //this would return only the users from real courses:
5706
        $session_id = api_get_session_id();
5707
        if ($session_id != 0) {
5708
            $user_list = self::get_real_and_linked_user_list(api_get_course_id(), true, $session_id);
5709
        } else {
5710
            $user_list = self::get_real_and_linked_user_list(api_get_course_id(), false, 0);
5711
        }
5712
5713
        return $user_list;
5714
    }
5715
5716
    /**
5717
     * this function gets all the groups of the course,
5718
     * not including linked courses
5719
     */
5720 View Code Duplication
    public static function getCourseGroups()
5721
    {
5722
        $session_id = api_get_session_id();
5723
        if ($session_id != 0) {
5724
            $new_group_list = self::get_group_list_of_course(api_get_course_id(), $session_id, 1);
5725
        } else {
5726
            $new_group_list = self::get_group_list_of_course(api_get_course_id(), 0, 1);
5727
        }
5728
5729
        return $new_group_list;
5730
    }
5731
5732
    /**
5733
     * @param FormValidator $form
5734
     * @param array $to_already_selected
5735
     *
5736
     * @return HTML_QuickForm_element
5737
     */
5738 View Code Duplication
    public static function addUserGroupMultiSelect(&$form, $to_already_selected)
5739
    {
5740
        $user_list = self::getCourseUsers();
5741
        $group_list = self::getCourseGroups();
5742
        $array = self::buildSelectOptions($group_list, $user_list, $to_already_selected);
5743
5744
        $result = array();
5745
        foreach ($array as $content) {
5746
            $result[$content['value']] = $content['content'];
5747
        }
5748
5749
        return $form->addElement(
5750
            'advmultiselect',
5751
            'users',
5752
            get_lang('Users'),
5753
            $result,
5754
            array('select_all_checkbox' => true)
5755
        );
5756
    }
5757
5758
    /**
5759
     * This function separates the users from the groups
5760
     * users have a value USER:XXX (with XXX the groups id have a value
5761
     *  GROUP:YYY (with YYY the group id)
5762
     * @param  array $to Array of strings that define the type and id of each destination
5763
     * @return array Array of groups and users (each an array of IDs)
5764
     */
5765
    public static function separateUsersGroups($to)
5766
    {
5767
        $grouplist = array();
5768
        $userlist = array();
5769
5770
        foreach ($to as $to_item) {
5771
            if (!empty($to_item)) {
5772
                $parts = explode(':', $to_item);
5773
                $type = isset($parts[0]) ? $parts[0] : '';
5774
                $id = isset($parts[1]) ? $parts[1] : '';
5775
5776
                switch ($type) {
5777
                    case 'GROUP':
5778
                        $grouplist[] = intval($id);
5779
                        break;
5780
                    case 'USER':
5781
                        $userlist[] = intval($id);
5782
                        break;
5783
                }
5784
            }
5785
        }
5786
5787
        $send_to['groups'] = $grouplist;
5788
        $send_to['users'] = $userlist;
5789
5790
        return $send_to;
5791
    }
5792
5793
    /**
5794
     * Shows the form for sending a message to a specific group or user.
5795
     * @param FormValidator $form
5796
     * @param int $group_id iid
5797
     * @param array $to
5798
     */
5799 View Code Duplication
    public static function addGroupMultiSelect($form, $group_id, $to = array())
5800
    {
5801
        $group_users = GroupManager::get_subscribed_users($group_id);
5802
        $array = self::buildSelectOptions(null, $group_users, $to);
5803
5804
        $result = array();
5805
        foreach ($array as $content) {
5806
            $result[$content['value']] = $content['content'];
5807
        }
5808
5809
        return $form->addElement('advmultiselect', 'users', get_lang('Users'), $result);
5810
    }
5811
5812
    /**
5813
     * this function shows the form for sending a message to a specific group or user.
5814
     * @param array $group_list
5815
     * @param array $user_list
5816
     * @param array $to_already_selected
5817
     * @return array
5818
     */
5819
    public static function buildSelectOptions(
5820
        $group_list = array(),
5821
        $user_list = array(),
5822
        $to_already_selected = array()
5823
    ) {
5824
        if (empty($to_already_selected)) {
5825
            $to_already_selected = array();
5826
        }
5827
5828
        $result = array();
5829
        // adding the groups to the select form
5830
        if ($group_list) {
5831
            foreach ($group_list as $this_group) {
5832
                if (is_array($to_already_selected)) {
5833
                    if (!in_array(
5834
                        "GROUP:" . $this_group['id'],
5835
                        $to_already_selected
5836
                    )
5837
                    ) { // $to_already_selected is the array containing the groups (and users) that are already selected
5838
                        $user_label = ($this_group['userNb'] > 0) ? get_lang('Users') : get_lang('LowerCaseUser');
5839
                        $user_disabled = ($this_group['userNb'] > 0) ? "" : "disabled=disabled";
5840
                        $result[] = array(
5841
                            'disabled' => $user_disabled,
5842
                            'value' => "GROUP:" . $this_group['id'],
5843
                            'content' => "G: " . $this_group['name'] . " - " . $this_group['userNb'] . " " . $user_label
5844
                        );
5845
                    }
5846
                }
5847
            }
5848
        }
5849
5850
        // adding the individual users to the select form
5851
        if ($user_list) {
5852
            foreach ($user_list as $user) {
5853
                if (is_array($to_already_selected)) {
5854
                    if (!in_array(
5855
                        "USER:" . $user['user_id'],
5856
                        $to_already_selected
5857
                    )
5858
                    ) { // $to_already_selected is the array containing the users (and groups) that are already selected
5859
5860
                        $result[] = array(
5861
                            'value' => "USER:" . $user['user_id'],
5862
                            'content' => api_get_person_name($user['firstname'], $user['lastname'])
5863
                        );
5864
                    }
5865
                }
5866
            }
5867
        }
5868
5869
        return $result;
5870
    }
5871
5872
    /**
5873
     * @return array a list (array) of all courses.
5874
     */
5875
    public static function get_course_list()
5876
    {
5877
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
5878
        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...
5879
    }
5880
5881
    /**
5882
     * Returns course code from a given gradebook category's id
5883
     * @param int  Category ID
5884
     * @return string  Course code
5885
     */
5886 View Code Duplication
    public static function get_course_by_category($category_id)
5887
    {
5888
        $category_id = intval($category_id);
5889
        $info = Database::fetch_array(
5890
            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...
5891
            WHERE id=' . $category_id), 'ASSOC'
5892
        );
5893
        return $info ? $info['course_code'] : false;
5894
    }
5895
5896
    /**
5897
     * This function gets all the courses that are not in a session
5898
     * @param date Start date
5899
     * @param date End date
5900
     * @param   bool    $includeClosed Whether to include closed and hidden courses
5901
     * @return array Not-in-session courses
5902
     */
5903
    public static function getCoursesWithoutSession($startDate = null, $endDate = null, $includeClosed = false)
5904
    {
5905
        $dateConditional = ($startDate && $endDate) ?
5906
            " WHERE session_id IN (SELECT id FROM " . Database::get_main_table(TABLE_MAIN_SESSION) .
5907
            " WHERE access_start_date = '$startDate' AND access_end_date = '$endDate')" :
5908
            null;
5909
        $visibility = ($includeClosed ? '' : 'visibility NOT IN (0, 4) AND ');
5910
5911
        $query = "SELECT id, code, title
5912
                FROM " . Database::get_main_table(TABLE_MAIN_COURSE). "
5913
                WHERE $visibility code NOT IN (
5914
                    SELECT DISTINCT course_code FROM " . Database::get_main_table(TABLE_MAIN_SESSION_COURSE) . $dateConditional . ")
5915
                ORDER BY id";
5916
5917
        $result = Database::query($query);
5918
        $courses = array();
5919
        while ($row = Database::fetch_array($result)) {
5920
            $courses[] = $row;
5921
        }
5922
        return $courses;
5923
    }
5924
5925
    /**
5926
     * Get list of courses based on users of a group for a group admin
5927
     * @param int $userId The user id
5928
     * @return array
5929
     */
5930 View Code Duplication
    public static function getCoursesFollowedByGroupAdmin($userId)
5931
    {
5932
        $coursesList = [];
5933
5934
        $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
5935
        $courseUserTable = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5936
        $userGroup = new UserGroup();
5937
        $userIdList = $userGroup->getGroupUsersByUser($userId);
5938
5939
        if (empty($userIdList)) {
5940
            return [];
5941
        }
5942
5943
        $sql = "SELECT DISTINCT(c.id), c.title
5944
                FROM $courseTable c
5945
                INNER JOIN $courseUserTable cru ON c.id = cru.c_id
5946
                WHERE (
5947
                    cru.user_id IN (" . implode(', ', $userIdList) . ")
5948
                    AND cru.relation_type = 0
5949
                )";
5950
5951
        if (api_is_multiple_url_enabled()) {
5952
            $courseAccessUrlTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
5953
            $accessUrlId = api_get_current_access_url_id();
5954
5955
            if ($accessUrlId != -1) {
5956
                $sql = "SELECT DISTINCT(c.id), c.title
5957
                        FROM $courseTable c
5958
                        INNER JOIN $courseUserTable cru ON c.id = cru.c_id
5959
                        INNER JOIN $courseAccessUrlTable crau ON c.id = crau.c_id
5960
                        WHERE crau.access_url_id = $accessUrlId
5961
                            AND (
5962
                            cru.id_user IN (" . implode(', ', $userIdList) . ") AND
5963
                            cru.relation_type = 0
5964
                        )";
5965
            }
5966
        }
5967
5968
        $result = Database::query($sql);
5969
5970
        while ($row = Database::fetch_assoc($result)) {
5971
            $coursesList[] = $row;
5972
        }
5973
5974
        return $coursesList;
5975
    }
5976
5977
    /**
5978
     * Direct course link see #5299
5979
     *
5980
     * You can send to your students an URL like this
5981
     * http://chamilodev.beeznest.com/main/auth/inscription.php?c=ABC&e=3
5982
     * Where "c" is the course code and "e" is the exercise Id, after a successful
5983
     * registration the user will be sent to the course or exercise
5984
     *
5985
     */
5986
    public static function redirectToCourse($form_data)
5987
    {
5988
        $course_code_redirect = Session::read('course_redirect');
5989
        $_user = api_get_user_info();
5990
        $user_id = api_get_user_id();
5991
5992
        if (!empty($course_code_redirect)) {
5993
            $course_info = api_get_course_info($course_code_redirect);
5994
            if (!empty($course_info)) {
5995
                if (in_array($course_info['visibility'],
5996
                    array(COURSE_VISIBILITY_OPEN_PLATFORM, COURSE_VISIBILITY_OPEN_WORLD))
5997
                ) {
5998
                    if (CourseManager::is_user_subscribed_in_course($user_id, $course_info['code'])) {
5999
6000
                        $form_data['action'] = $course_info['course_public_url'];
6001
                        $form_data['message'] = sprintf(get_lang('YouHaveBeenRegisteredToCourseX'), $course_info['title']);
6002
                        $form_data['button'] = Display::button(
6003
                            'next',
6004
                            get_lang('GoToCourse', null, $_user['language']),
6005
                            array('class' => 'btn btn-primary btn-large')
6006
                        );
6007
6008
                        $exercise_redirect = intval(Session::read('exercise_redirect'));
6009
                        // Specify the course id as the current context does not
6010
                        // hold a global $_course array
6011
                        $objExercise = new Exercise($course_info['real_id']);
6012
                        $result = $objExercise->read($exercise_redirect);
6013
6014
                        if (!empty($exercise_redirect) && !empty($result)) {
6015
                            $form_data['action'] = api_get_path(WEB_CODE_PATH) . 'exercise/overview.php?exerciseId='.$exercise_redirect.'&cidReq='.$course_info['code'];
6016
                            $form_data['message'] .= '<br />'.get_lang('YouCanAccessTheExercise');
6017
                            $form_data['button'] = Display::button(
6018
                                'next',
6019
                                get_lang('Go', null, $_user['language']),
6020
                                array('class' => 'btn btn-primary btn-large')
6021
                            );
6022
                        }
6023
6024
                        if (!empty($form_data['action'])) {
6025
                            header('Location: '.$form_data['action']);
6026
                            exit;
6027
                        }
6028
                    }
6029
                }
6030
            }
6031
        }
6032
6033
        return $form_data;
6034
    }
6035
6036
    /**
6037
     * return html code for displaying a course title in the standard view (not the Session view)
6038
     * @param $courseId
6039
     * @param bool $loadDirs
6040
     * @return string
6041
     */
6042
    public static function displayCourseHtml($courseId, $loadDirs = false)
6043
    {
6044
        $params = self::getCourseParamsForDisplay($courseId, $loadDirs);
6045
        $html = self::course_item_html($params, false);
0 ignored issues
show
Bug introduced by
It seems like $params defined by self::getCourseParamsFor...y($courseId, $loadDirs) on line 6044 can also be of type string; however, CourseManager::course_item_html() does only seem to accept array, maybe add an additional type check?

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

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

    return array();
}

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

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

Loading history...
6046
6047
        return $html;
6048
    }
6049
6050
    /**
6051
     * Return tab of params to display a course title in the My Courses tab
6052
     * Check visibility, right, and notification icons, and load_dirs option
6053
     * @param $courseId
6054
     * @param bool $loadDirs
6055
     * @return array
6056
     */
6057
    public static function getCourseParamsForDisplay($courseId, $loadDirs = false)
6058
    {
6059
        $user_id = api_get_user_id();
6060
        // Table definitions
6061
        $TABLECOURS = Database :: get_main_table(TABLE_MAIN_COURSE);
6062
        $TABLECOURSUSER = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
6063
        $TABLE_ACCESS_URL_REL_COURSE = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
6064
        $current_url_id = api_get_current_access_url_id();
6065
6066
        // Get course list auto-register
6067
        $special_course_list = self::get_special_course_list();
6068
6069
        $without_special_courses = '';
6070
        if (!empty($special_course_list)) {
6071
            $without_special_courses = ' AND course.code NOT IN ("'.implode('","',$special_course_list).'")';
6072
        }
6073
6074
        //AND course_rel_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
6075
        $sql = "SELECT 
6076
                    course.id, 
6077
                    course.title, 
6078
                    course.code, 
6079
                    course.subscribe subscr, 
6080
                    course.unsubscribe unsubscr, 
6081
                    course_rel_user.status status,
6082
                    course_rel_user.sort sort, 
6083
                    course_rel_user.user_course_cat user_course_cat
6084
                FROM
6085
                $TABLECOURS course,
6086
                $TABLECOURSUSER course_rel_user, 
6087
                $TABLE_ACCESS_URL_REL_COURSE url
6088
                WHERE
6089
                    course.id=".intval($courseId)." AND
6090
                    course.id = course_rel_user.c_id AND
6091
                    url.c_id = course.id AND
6092
                    course_rel_user.user_id = ".intval($user_id)."
6093
                    $without_special_courses
6094
                ";
6095
6096
        // If multiple URL access mode is enabled, only fetch courses
6097
        // corresponding to the current URL.
6098
        if (api_get_multiple_access_url() && $current_url_id != -1) {
6099
            $sql .= " AND url.course_code=course.code AND access_url_id=".intval($current_url_id);
6100
        }
6101
        // Use user's classification for courses (if any).
6102
        $sql .= " ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
6103
6104
        $result = Database::query($sql);
6105
6106
        // Browse through all courses. We can only have one course because
6107
        // of the  course.id=".intval($courseId) in sql query
6108
        $course = Database::fetch_array($result);
6109
        $course_info = api_get_course_info_by_id($courseId);
6110
        if (empty($course_info)) {
6111
            return '';
6112
        }
6113
6114
        //$course['id_session'] = null;
6115
        $course_info['id_session'] = null;
6116
        $course_info['status'] = $course['status'];
6117
6118
        // For each course, get if there is any notification icon to show
6119
        // (something that would have changed since the user's last visit).
6120
        $show_notification = Display::show_notification($course_info);
6121
6122
        // New code displaying the user's status in respect to this course.
6123
        $status_icon = Display::return_icon(
6124
            'blackboard.png',
6125
            $course_info['title'],
6126
            array(),
6127
            ICON_SIZE_LARGE
6128
        );
6129
6130
        $params = array();
6131
        $params['right_actions'] = '';
6132
6133
        if (api_is_platform_admin()) {
6134 View Code Duplication
            if ($loadDirs) {
6135
                $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>';
6136
                $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>';
6137
                $params['right_actions'] .= Display::div('', array('id' => 'document_result_'.$course_info['real_id'].'_0', 'class'=>'document_preview_container'));
6138
            } else {
6139
                $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>';
6140
            }
6141
6142
            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...
6143
                //echo Display::return_icon('teachers.gif', get_lang('Status').': '.get_lang('Teacher'), array('style'=>'width: 11px; height: 11px;'));
6144
            }
6145
        } else {
6146
            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
6147 View Code Duplication
                if ($loadDirs) {
6148
                    $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>';
6149
                    $params['right_actions'] .= Display::div('', array('id' => 'document_result_'.$course_info['real_id'].'_0', 'class'=>'document_preview_container'));
6150
                } else {
6151
                    if ($course_info['status'] == COURSEMANAGER) {
6152
                        $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>';
6153
                    }
6154
                }
6155
            }
6156
        }
6157
6158
        $course_title_url = '';
6159 View Code Duplication
        if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED || $course['status'] == COURSEMANAGER) {
6160
            $course_title_url = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/?id_session=0';
6161
            $course_title = Display::url($course_info['title'], $course_title_url);
6162
        } else {
6163
            $course_title = $course_info['title'].' '.Display::tag('span',get_lang('CourseClosed'), array('class'=>'item_closed'));
6164
        }
6165
6166
        // Start displaying the course block itself
6167
        if (api_get_setting('display_coursecode_in_courselist') === 'true') {
6168
            $course_title .= ' ('.$course_info['visual_code'].') ';
6169
        }
6170
        $teachers = '';
6171
        if (api_get_setting('display_teacher_in_courselist') === 'true') {
6172
            $teachers = CourseManager::get_teacher_list_from_course_code_to_string($course['code'], self::USER_SEPARATOR, true);
6173
        }
6174
        $params['link'] = $course_title_url;
6175
        $params['icon'] = $status_icon;
6176
        $params['title'] = $course_title;
6177
        $params['teachers'] = $teachers;
6178
        if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
6179
            $params['notifications'] = $show_notification;
6180
        }
6181
6182
        return $params;
6183
    }
6184
6185
    /**
6186
     * @param int $user_id
6187
     * @param $filter
6188
     * @param bool $load_dirs
6189
     * @param int $getCount
6190
     * @param int $start
6191
     * @param null $maxPerPage
6192
     * @return null|string
6193
     */
6194
    public static function displayCourses($user_id, $filter, $load_dirs, $getCount, $start = null, $maxPerPage = null)
6195
    {
6196
        // Table definitions
6197
        $TABLECOURS                     = Database :: get_main_table(TABLE_MAIN_COURSE);
6198
        $TABLECOURSUSER                 = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
6199
        $TABLE_ACCESS_URL_REL_COURSE    = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
6200
        $current_url_id                 = api_get_current_access_url_id();
6201
6202
        // Get course list auto-register
6203
        $special_course_list            = self::get_special_course_list();
6204
6205
        $without_special_courses = '';
6206
6207
        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...
6208
            //$without_special_courses = ' AND course.code NOT IN ("'.implode('","',$special_course_list).'")';
6209
        }
6210
6211
        $select = " SELECT DISTINCT
6212
                    course.id,
6213
                    course.title,
6214
                    course.code,
6215
                    course.subscribe subscr,
6216
                    course.unsubscribe unsubscr,
6217
                    course_rel_user.status status,
6218
                    course_rel_user.sort sort,
6219
                    course_rel_user.user_course_cat user_course_cat,
6220
                    course.id as real_id
6221
        ";
6222
6223
        $from = "$TABLECOURS course, $TABLECOURSUSER  course_rel_user, $TABLE_ACCESS_URL_REL_COURSE url ";
6224
6225
        $where = "  course.id = course_rel_user.c_id AND
6226
                    url.c_id = course.id AND
6227
                    course_rel_user.user_id = '".$user_id."' AND
6228
                    course_rel_user.user_course_cat = 0
6229
                    ";
6230
6231
        $order = " ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
6232
6233
6234
        if ($getCount) {
6235
            $select = "SELECT count(course.id) as total";
6236
        }
6237
6238
        $sql = "$select FROM $from WHERE $where $without_special_courses ";
6239
6240
        // corresponding to the current URL.
6241
        if (api_get_multiple_access_url() && $current_url_id != -1) {
6242
            $sql .= " AND url.c_id = course.id AND access_url_id='".$current_url_id."'";
6243
        }
6244
6245
        $sql .= $order;
6246
6247 View Code Duplication
        if (isset($start) && isset($maxPerPage)) {
6248
            $start = intval($start);
6249
            $maxPerPage = intval($maxPerPage);
6250
            $limitCondition = " LIMIT $start, $maxPerPage";
6251
            $sql .= $limitCondition;
6252
        }
6253
6254 View Code Duplication
        if ($getCount) {
6255
            $result = Database::query($sql);
6256
            $row = Database::fetch_array($result);
6257
            return $row['total'];
6258
        }
6259
        $result = Database::query($sql);
6260
6261
        $html = null;
6262
        $course_list = array();
6263
6264
        // Browse through all courses.
6265
        while ($course = Database::fetch_array($result)) {
6266
            $course_info = api_get_course_info($course['code']);
6267
            $course_info['id_session'] = null;
6268
            $course_info['status'] = $course['status'];
6269
6270
            //In order to avoid doubles
6271
            if (in_array($course_info['real_id'], $course_list)) {
6272
                continue;
6273
            } else {
6274
                $course_list[] = $course_info['real_id'];
6275
            }
6276
6277
            // For each course, get if there is any notification icon to show
6278
            // (something that would have changed since the user's last visit).
6279
            $show_notification = Display :: show_notification($course_info);
6280
6281
            // New code displaying the user's status in respect to this course.
6282
            $status_icon = Display::return_icon('blackboard.png', $course_info['title'], array(), ICON_SIZE_LARGE);
6283
6284
            $params = array();
6285
            $params['right_actions'] = '';
6286
6287
            if (api_is_platform_admin()) {
6288 View Code Duplication
                if ($load_dirs) {
6289
                    $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>';
6290
                    $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>';
6291
                    $params['right_actions'] .= Display::div('', array('id' => 'document_result_'.$course_info['real_id'].'_0', 'class'=>'document_preview_container'));
6292
                } else {
6293
                    $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>';
6294
                }
6295
6296
                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...
6297
                    //echo Display::return_icon('teachers.gif', get_lang('Status').': '.get_lang('Teacher'), array('style'=>'width: 11px; height: 11px;'));
6298
                }
6299 View Code Duplication
            } else {
6300
                if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
6301
                    if ($load_dirs) {
6302
                        $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>';
6303
                        $params['right_actions'] .= Display::div('', array('id' => 'document_result_'.$course_info['real_id'].'_0', 'class'=>'document_preview_container'));
6304
                    } else {
6305
                        if ($course_info['status'] == COURSEMANAGER) {
6306
                            $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>';
6307
                        }
6308
                    }
6309
                }
6310
            }
6311
6312
            $course_title_url = '';
6313 View Code Duplication
            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED || $course['status'] == COURSEMANAGER) {
6314
                //$course_title_url = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/index.php?id_session=0';
6315
                $course_title_url = api_get_path(WEB_COURSE_PATH).$course_info['code'].'/index.php?id_session=0';
6316
                $course_title = Display::url($course_info['title'], $course_title_url);
6317
            } else {
6318
                $course_title = $course_info['title']." ".Display::tag('span',get_lang('CourseClosed'), array('class'=>'item_closed'));
6319
            }
6320
6321
            // Start displaying the course block itself
6322
            if (api_get_setting('course.display_coursecode_in_courselist') == 'true') {
6323
                $course_title .= ' ('.$course_info['visual_code'].') ';
6324
            }
6325
            $teachers = null;
6326
            if (api_get_setting('course.display_teacher_in_courselist') == 'true') {
6327
                $teachers = $course_info['teacher_list_formatted'];
6328
            }
6329
6330
            $params['link'] = $course_title_url;
6331
            $params['icon'] = $status_icon;
6332
            $params['title'] = $course_title;
6333
            $params['teachers'] = $teachers;
6334
6335
            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
6336
                $params['notifications'] = $show_notification;
6337
            }
6338
6339
            $is_subcontent = true;
6340
            if (empty($user_category_id)) {
6341
                $is_subcontent = false;
6342
            }
6343
            $html .= self::course_item_html($params, $is_subcontent);
6344
        }
6345
        return $html;
6346
    }
6347
6348
    /**
6349
     * Get the course id based on the original id and field name in the extra fields.
6350
     * Returns 0 if course was not found
6351
     *
6352
     * @param string $original_course_id_value Original course id
6353
     * @param string $original_course_id_name Original field name
6354
     * @return int Course id
6355
     */
6356
    public static function get_course_id_from_original_id($original_course_id_value, $original_course_id_name)
6357
    {
6358
        $extraFieldValue = new ExtraFieldValue('course');
6359
        $value = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
6360
            $original_course_id_name,
6361
            $original_course_id_value
6362
        );
6363
6364
        if ($value) {
6365
            return $value['item_id'];
6366
        }
6367
        return 0;
6368
    }
6369
6370
    /**
6371
     * Helper function to create a default gradebook (if necessary) upon course creation
6372
     * @param   int     $modelId    The gradebook model ID
6373
     * @param   string  $courseCode Course code
6374
     * @return  void
6375
     */
6376
    public static function createDefaultGradebook($modelId, $courseCode)
6377
    {
6378
        if (api_get_setting('gradebook_enable_grade_model') === 'true') {
6379
            //Create gradebook_category for the new course and add
6380
            // a gradebook model for the course
6381
            if (isset($modelId) &&
6382
                !empty($modelId) &&
6383
                $modelId != '-1'
6384
            ) {
6385
                GradebookUtils::create_default_course_gradebook(
6386
                    $courseCode,
6387
                    $modelId
6388
                );
6389
            }
6390
        }
6391
    }
6392
6393
    /**
6394
     * Helper function to check if there is a course template and, if so, to
6395
     * copy the template as basis for the new course
6396
     * @param   string  $courseCode   Course code
6397
     * @param   int     $courseTemplate 0 if no course template is defined
6398
     */
6399
    public static function useTemplateAsBasisIfRequired($courseCode, $courseTemplate)
6400
    {
6401
        $template = api_get_setting('course_creation_use_template');
6402
        $teacherCanSelectCourseTemplate = api_get_setting('teacher_can_select_course_template') === 'true';
6403
        $courseTemplate = isset($courseTemplate) ? intval($courseTemplate) : 0;
6404
6405
        $useTemplate = false;
6406
6407
        if ($teacherCanSelectCourseTemplate && $courseTemplate) {
6408
            $useTemplate = true;
6409
            $originCourse = api_get_course_info_by_id($courseTemplate);
6410
        } elseif (!empty($template)) {
6411
            $useTemplate = true;
6412
            $originCourse = api_get_course_info_by_id($template);
6413
        }
6414
6415
        if ($useTemplate) {
6416
            // Include the necessary libraries to generate a course copy
6417
            // Call the course copy object
6418
            $originCourse['official_code'] = $originCourse['code'];
6419
            $cb = new CourseBuilder(null, $originCourse);
6420
            $course = $cb->build(null, $originCourse['code']);
6421
            $cr = new CourseRestorer($course);
6422
            $cr->set_file_option();
6423
            $cr->restore($courseCode);
6424
        }
6425
    }
6426
6427
    /**
6428
     * Helper method to get the number of users defined with a specific course extra field
6429
     * @param   string  $name   Field title
6430
     * @param   string  $tableExtraFields The extra fields table name
6431
     * @param   string  $tableUserFieldValues The user extra field value table name
6432
     * @return  int     The number of users with this extra field with a specific value
6433
     */
6434
    public static function getCountRegisteredUsersWithCourseExtraField($name, $tableExtraFields = '', $tableUserFieldValues = '')
6435
    {
6436
        if (empty($tableExtraFields)) {
6437
            $tableExtraFields = Database::get_main_table(TABLE_EXTRA_FIELD);
6438
        }
6439
        if (empty($tableUserFieldValues)) {
6440
            $tableUserFieldValues = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
6441
        }
6442
6443
        $registered_users_with_extra_field = 0;
6444
6445
        if (!empty($name) && $name != '-') {
6446
            $extraFieldType = EntityExtraField::COURSE_FIELD_TYPE;
6447
            $name = Database::escape_string($name);
6448
            $sql = "SELECT count(v.item_id) as count
6449
                    FROM $tableUserFieldValues v 
6450
                    INNER JOIN $tableExtraFields f
6451
                    ON (f.id = v.field_id)
6452
                    WHERE value = '$name' AND extra_field_type = $extraFieldType";
6453
            $result_count = Database::query($sql);
6454
            if (Database::num_rows($result_count)) {
6455
                $row_count = Database::fetch_array($result_count);
6456
                $registered_users_with_extra_field = $row_count['count'];
6457
            }
6458
        }
6459
6460
        return $registered_users_with_extra_field;
6461
    }
6462
6463
    /**
6464
     * Check if a specific access-url-related setting is a problem or not
6465
     * @param array $_configuration The $_configuration array
6466
     * @param int $accessUrlId The access URL ID
6467
     * @param string $param
6468
     * @param string $msgLabel
6469
     * @return bool|string
6470
     */
6471
    private static function checkCreateCourseAccessUrlParam($_configuration, $accessUrlId, $param, $msgLabel)
6472
    {
6473
        if (isset($_configuration[$accessUrlId][$param]) && $_configuration[$accessUrlId][$param] > 0) {
6474
            $num = self::count_courses($accessUrlId);
6475
            if ($num >= $_configuration[$accessUrlId][$param]) {
6476
                api_warn_hosting_contact($param);
6477
6478
                Display::addFlash(
6479
                    Display::return_message($msgLabel)
6480
                );
6481
            }
6482
        }
6483
        return false;
6484
    }
6485
    /**
6486
     * Fill course with all necessary items
6487
     * @param array $courseInfo Course info array
6488
     * @param array $params Parameters from the course creation form
6489
     * @param int $authorId
6490
     * @return void
6491
     */
6492
    private static function fillCourse($courseInfo, $params, $authorId = 0)
6493
    {
6494
        $authorId = empty($authorId) ? api_get_user_id() : (int) $authorId;
6495
6496
        AddCourse::prepare_course_repository($courseInfo['directory'], $courseInfo['code']);
6497
        AddCourse::fill_db_course(
6498
            $courseInfo['real_id'],
6499
            $courseInfo['directory'],
6500
            $courseInfo['course_language'],
6501
            $params['exemplary_content'],
6502
            $authorId
6503
        );
6504
6505
        if (isset($params['gradebook_model_id'])) {
6506
            CourseManager::createDefaultGradebook($params['gradebook_model_id'], $courseInfo['code']);
6507
        }
6508
        // If parameter defined, copy the contents from a specific
6509
        // template course into this new course
6510
        if (isset($params['course_template'])) {
6511
            CourseManager::useTemplateAsBasisIfRequired($courseInfo['id'], $params['course_template']);
6512
        }
6513
        $params['course_code'] = $courseInfo['code'];
6514
        $params['item_id'] = $courseInfo['real_id'];
6515
6516
        $courseFieldValue = new ExtraFieldValue('course');
6517
        $courseFieldValue->saveFieldValues($params);
6518
    }
6519
6520
    /**
6521
     * @param ToolChain $toolList
6522
     */
6523
    public static function setToolList($toolList)
6524
    {
6525
        self::$toolList = $toolList;
6526
    }
6527
6528
    /**
6529
     * @return ToolChain
6530
     */
6531
    public static function getToolList()
6532
    {
6533
        return self::$toolList;
6534
    }
6535
}
6536