Completed
Push — master ( 9b8b24...6e1754 )
by Julito
58:58
created

CourseManager::get_courses_list()   F

Complexity

Conditions 23
Paths 3456

Size

Total Lines 99
Code Lines 60

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 23
eloc 60
nc 3456
nop 9
dl 0
loc 99
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

1
<?php
2
/* For licensing terms, see /license.txt*/
3
4
use Chamilo\CourseBundle\ToolChain;
5
use Chamilo\CoreBundle\Entity\ExtraField as EntityExtraField;
6
use ChamiloSession as Session;
7
use Chamilo\CourseBundle\Component\CourseCopy\CourseBuilder;
8
use Chamilo\CourseBundle\Component\CourseCopy\CourseRestorer;
9
10
/**
11
 * Class CourseManager
12
 *
13
 * This is the course library for Chamilo.
14
 *
15
 * All main course functions should be placed here.
16
 *
17
 * Many functions of this library deal with providing support for
18
 * virtual/linked/combined courses (this was already used in several universities
19
 * but not available in standard Chamilo).
20
 *
21
 * There are probably some places left with the wrong code.
22
 *
23
 * @package chamilo.library
24
 */
25
class CourseManager
26
{
27
    const MAX_COURSE_LENGTH_CODE = 40;
28
    /** This constant is used to show separate user names in the course
29
     * list (userportal), footer, etc */
30
    const USER_SEPARATOR = ' |';
31
    const COURSE_FIELD_TYPE_CHECKBOX = 10;
32
    public $columns = [];
33
    public static $em;
34
    private static $manager;
35
    public static $toolList;
36
    public static $courseSettingsManager;
37
38
    /**
39
     * @param \Doctrine\ORM\EntityManager
40
     */
41
    public static function setEntityManager($em)
42
    {
43
        self::$em = $em;
44
    }
45
46
    /**
47
     * @return \Doctrine\ORM\EntityManager
48
     */
49
    public static function getEntityManager()
50
    {
51
        return self::$em;
52
    }
53
54
    public static function setCourseManager($manager)
55
    {
56
        self::$manager = $manager;
57
    }
58
59
    /**
60
     * @return SettingsManager
61
     */
62
    public static function getCourseSettingsManager()
63
    {
64
        return self::$courseSettingsManager;
65
    }
66
67
    /**
68
     * @param SettingsManager $courseSettingsManager
69
     */
70
    public static function setCourseSettingsManager($courseSettingsManager)
71
    {
72
        self::$courseSettingsManager = $courseSettingsManager;
73
    }
74
75
    /**
76
     * @return Chamilo\CoreBundle\Entity\Manager\CourseManager
77
     */
78
    public static function getManager()
79
    {
80
        return self::$manager;
81
    }
82
83
    /**
84
     * Creates a course
85
     * @param array $params columns in the main.course table
86
     * @param int $authorId
87
     * @return  mixed  false if the course was not created, array with the course info
88
     */
89
    public static function create_course($params, $authorId = 0)
90
    {
91
        global $_configuration;
92
        // Check portal limits
93
        $access_url_id = 1;
94
        if (api_get_multiple_access_url()) {
95
            $access_url_id = api_get_current_access_url_id();
96
        }
97
98
        $authorId = empty($authorId) ? api_get_user_id() : (int) $authorId;
99
100
        if (isset($_configuration[$access_url_id]) && is_array($_configuration[$access_url_id])) {
101
            $return = self::checkCreateCourseAccessUrlParam(
102
                $_configuration,
103
                $access_url_id,
104
                'hosting_limit_courses',
105
                'PortalCoursesLimitReached'
106
            );
107
            if ($return != false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison !== instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
108
                return $return;
109
            }
110
            $return = self::checkCreateCourseAccessUrlParam(
111
                $_configuration,
112
                $access_url_id,
113
                'hosting_limit_active_courses',
114
                'PortalActiveCoursesLimitReached'
115
            );
116
            if ($return != false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison !== instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
117
                return $return;
118
            }
119
        }
120
121
        if (empty($params['title'])) {
122
            return false;
123
        }
124
125
        if (empty($params['wanted_code'])) {
126
            $params['wanted_code'] = $params['title'];
127
            // Check whether the requested course code has already been occupied.
128
            $substring = api_substr($params['title'], 0, self::MAX_COURSE_LENGTH_CODE);
129
            if ($substring === false || empty($substring)) {
130
                return false;
131
            } else {
132
                $params['wanted_code'] = self::generate_course_code($substring);
133
            }
134
        }
135
        // Create the course keys
136
        $keys = AddCourse::define_course_keys($params['wanted_code']);
137
138
        $params['exemplary_content'] = isset($params['exemplary_content']) ? $params['exemplary_content'] : false;
139
140
        if (count($keys)) {
141
            $params['code'] = $keys['currentCourseCode'];
142
            $params['visual_code'] = $keys['currentCourseId'];
143
            $params['directory'] = $keys['currentCourseRepository'];
144
145
            $course_info = api_get_course_info($params['code']);
146
            if (empty($course_info)) {
147
                $course_id = AddCourse::register_course($params);
148
                $course_info = api_get_course_info_by_id($course_id);
149
150
                if (!empty($course_info)) {
151
                    self::fillCourse($course_info, $params, $authorId);
152
153
                    return $course_info;
154
                }
155
            }
156
        }
157
158
        return false;
159
    }
160
161
    /**
162
     * Returns all the information of a given course code
163
     * @param string $course_code , the course code
164
     * @return array with all the fields of the course table
165
     * @deprecated Use api_get_course_info() instead
166
     * @author Patrick Cool <[email protected]>, Ghent University
167
     * @assert ('') === false
168
     */
169
    public static function get_course_information($course_code)
170
    {
171
        return Database::fetch_array(
172
            Database::query(
173
                "SELECT *, id as real_id FROM ".Database::get_main_table(TABLE_MAIN_COURSE)."
174
                WHERE code='" . Database::escape_string($course_code)."'"), 'ASSOC'
175
        );
176
    }
177
178
    /**
179
     * Returns a list of courses. Should work with quickform syntax
180
     * @param    integer $from Offset (from the 7th = '6'). Optional.
181
     * @param    integer $howmany Number of results we want. Optional.
182
     * @param    int $orderby The column we want to order it by. Optional, defaults to first column.
183
     * @param    string $orderdirection The direction of the order (ASC or DESC). Optional, defaults to ASC.
184
     * @param    int $visibility The visibility of the course, or all by default.
185
     * @param    string $startwith If defined, only return results for which the course *title* begins with this string
186
     * @param    string $urlId The Access URL ID, if using multiple URLs
187
     * @param    bool $alsoSearchCode An extension option to indicate that we also want to search for course codes (not *only* titles)
188
     * @param    array $conditionsLike
189
     * @return array
190
     */
191
    public static function get_courses_list(
192
        $from = 0,
193
        $howmany = 0,
194
        $orderby = 1,
195
        $orderdirection = 'ASC',
196
        $visibility = -1,
197
        $startwith = '',
198
        $urlId = null,
199
        $alsoSearchCode = false,
200
        $conditionsLike = array()
201
    ) {
202
        $sql = "SELECT course.* FROM ".Database::get_main_table(TABLE_MAIN_COURSE)." course ";
203
204
        if (!empty($urlId)) {
205
            $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
206
            $sql .= " INNER JOIN $table url ON (url.c_id = course.id) ";
207
        }
208
209
        if (!empty($startwith)) {
210
            $sql .= "WHERE (title LIKE '".Database::escape_string($startwith)."%' ";
211
            if ($alsoSearchCode) {
212
                $sql .= "OR code LIKE '".Database::escape_string($startwith)."%' ";
213
            }
214
            $sql .= ') ';
215
            if ($visibility !== -1 && $visibility == strval(intval($visibility))) {
216
                $sql .= " AND visibility = $visibility ";
217
            }
218
        } else {
219
            $sql .= "WHERE 1 ";
220
            if ($visibility !== -1 && $visibility == strval(intval($visibility))) {
221
                $sql .= " AND visibility = $visibility ";
222
            }
223
        }
224
225
        if (!empty($urlId)) {
226
            $urlId = intval($urlId);
227
            $sql .= " AND access_url_id= $urlId";
228
        }
229
230
        $allowedFields = array(
231
            'title',
232
            'code'
233
        );
234
235
        if (count($conditionsLike) > 0) {
236
            $sql .= ' AND ';
237
            $temp_conditions = array();
238
            foreach ($conditionsLike as $field => $value) {
239
                if (!in_array($field, $allowedFields)) {
240
                    continue;
241
                }
242
                $field = Database::escape_string($field);
243
                $value = Database::escape_string($value);
244
                $simple_like = false;
245
                if ($simple_like) {
246
                    $temp_conditions[] = $field." LIKE '$value%'";
247
                } else {
248
                    $temp_conditions[] = $field.' LIKE \'%'.$value.'%\'';
249
                }
250
            }
251
            $condition = ' AND ';
252
            if (!empty($temp_conditions)) {
253
                $sql .= implode(' '.$condition.' ', $temp_conditions);
254
            }
255
        }
256
257
        if (!empty($orderby)) {
258
            $sql .= " ORDER BY ".Database::escape_string($orderby)." ";
259
        } else {
260
            $sql .= " ORDER BY 1 ";
261
        }
262
263
        if (!in_array($orderdirection, array('ASC', 'DESC'))) {
264
            $sql .= 'ASC';
265
        } else {
266
            $sql .= ($orderdirection == 'ASC' ? 'ASC' : 'DESC');
267
        }
268
269
        if (!empty($howmany) && is_int($howmany) and $howmany > 0) {
270
            $sql .= ' LIMIT '.Database::escape_string($howmany);
271
        } else {
272
            $sql .= ' LIMIT 1000000'; //virtually no limit
273
        }
274
        if (!empty($from)) {
275
            $from = intval($from);
276
            $sql .= ' OFFSET '.intval($from);
277
        } else {
278
            $sql .= ' OFFSET 0';
279
        }
280
281
        $data = [];
282
        $res = Database::query($sql);
283
        if (Database::num_rows($res) > 0) {
284
            while ($row = Database::fetch_array($res, 'ASSOC')) {
285
                $data[] = $row;
286
            }
287
        }
288
289
        return $data;
290
    }
291
292
    /**
293
     * Returns the status of a user in a course, which is COURSEMANAGER or STUDENT.
294
     * @param   int $userId
295
     * @param   int $courseId
296
     *
297
     * @return int|bool the status of the user in that course (or false if the user is not in that course)
298
     */
299
    public static function getUserInCourseStatus($userId, $courseId)
300
    {
301
        $courseId = (int) $courseId;
302
        if (empty($courseId)) {
303
            return false;
304
        }
305
306
        $result = Database::fetch_array(
307
            Database::query(
308
                "SELECT status FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
309
                WHERE
310
                    c_id  = $courseId AND
311
                    user_id = ".intval($userId)
312
            )
313
        );
314
315
        return $result['status'];
316
    }
317
318
    /**
319
     * @param int $userId
320
     * @param int $courseId
321
     *
322
     * @return mixed
323
     */
324
    public static function getUserCourseInfo($userId, $courseId)
325
    {
326
        $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
327
                WHERE
328
                    c_id  = '".intval($courseId)."' AND
329
                    user_id = ".intval($userId);
330
        $result = Database::fetch_array(Database::query($sql));
331
332
        return $result;
333
    }
334
335
    /**
336
     * @param int  $userId
337
     * @param int  $courseId
338
     * @param bool $isTutor
339
     *
340
     * @return bool
341
     */
342
    public static function updateUserCourseTutor($userId, $courseId, $isTutor)
343
    {
344
        $table = Database::escape_string(TABLE_MAIN_COURSE_USER);
345
346
        $courseId = intval($courseId);
347
        $isTutor = intval($isTutor);
348
349
        $sql = "UPDATE $table SET is_tutor = '".$isTutor."'
350
			    WHERE
351
				    user_id = '".$userId."' AND
352
				    c_id = '".$courseId."'";
353
354
        $result = Database::query($sql);
355
356
        if (Database::affected_rows($result) > 0) {
357
            return true;
358
        } else {
359
            return false;
360
        }
361
    }
362
363
    /**
364
     * @param int $user_id
365
     * @param int $courseId
366
     *
367
     * @return mixed
368
     */
369
    public static function get_tutor_in_course_status($user_id, $courseId)
370
    {
371
        $result = Database::fetch_array(
372
            Database::query("
373
                SELECT is_tutor
374
                FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER)."
375
                WHERE
376
                    c_id = '".Database::escape_string($courseId)."' AND
377
                    user_id = ".intval($user_id)
378
            )
379
        );
380
381
        return $result['is_tutor'];
382
    }
383
384
    /**
385
     * Unsubscribe one or more users from a course
386
     *
387
     * @param   mixed   user_id or an array with user ids
388
     * @param   string  course code
389
     * @param   int     session id
390
     * @assert ('', '') === false
391
     *
392
     */
393
    public static function unsubscribe_user($user_id, $course_code, $session_id = 0)
394
    {
395
        if (empty($user_id)) {
396
            return;
397
        }
398
        if (!is_array($user_id)) {
399
            $user_id = array($user_id);
400
        }
401
402
        if (count($user_id) == 0) {
403
            return;
404
        }
405
406
        if (!empty($session_id)) {
407
            $session_id = intval($session_id);
408
        } else {
409
            $session_id = api_get_session_id();
410
        }
411
412
        $userList = array();
413
414
        // Cleaning the $user_id variable
415
        if (is_array($user_id)) {
416
            $new_user_id_list = array();
417
            foreach ($user_id as $my_user_id) {
418
                $new_user_id_list[] = intval($my_user_id);
419
            }
420
            $new_user_id_list = array_filter($new_user_id_list);
421
            $userList = $new_user_id_list;
422
            $user_ids = implode(',', $new_user_id_list);
423
        } else {
424
            $user_ids = intval($user_id);
425
            $userList[] = $user_id;
426
        }
427
428
        $course_info = api_get_course_info($course_code);
429
        $course_id = $course_info['real_id'];
430
431
        // Unsubscribe user from all groups in the course.
432
        $sql = "DELETE FROM ".Database::get_course_table(TABLE_GROUP_USER)."
433
                WHERE c_id = $course_id AND user_id IN (".$user_ids.")";
434
        Database::query($sql);
435
        $sql = "DELETE FROM ".Database::get_course_table(TABLE_GROUP_TUTOR)."
436
                WHERE c_id = $course_id AND user_id IN (".$user_ids.")";
437
        Database::query($sql);
438
439
        // Erase user student publications (works) in the course - by André Boivin
440
441
        if (!empty($userList)) {
442
            require_once api_get_path(SYS_CODE_PATH).'work/work.lib.php';
443
            foreach ($userList as $userId) {
444
                // Getting all work from user
445
                $workList = getWorkPerUser($userId);
446
                if (!empty($workList)) {
447
                    foreach ($workList as $work) {
448
                        $work = $work['work'];
449
                        // Getting user results
450
                        if (!empty($work->user_results)) {
451
                            foreach ($work->user_results as $workSent) {
452
                                deleteWorkItem($workSent['id'], $course_info);
453
                            }
454
                        }
455
                    }
456
                }
457
            }
458
        }
459
460
        // Unsubscribe user from all blogs in the course.
461
        $sql = "DELETE FROM ".Database::get_course_table(TABLE_BLOGS_REL_USER)." 
462
                WHERE c_id = $course_id AND user_id IN (".$user_ids.")";
463
        Database::query($sql);
464
465
        $sql = "DELETE FROM ".Database::get_course_table(TABLE_BLOGS_TASKS_REL_USER)." 
466
                WHERE c_id = $course_id AND user_id IN (".$user_ids.")";
467
        Database::query($sql);
468
469
        // Deleting users in forum_notification and mailqueue course tables
470
        $sql = "DELETE FROM  ".Database::get_course_table(TABLE_FORUM_NOTIFICATION)."
471
                WHERE c_id = $course_id AND user_id IN (".$user_ids.")";
472
        Database::query($sql);
473
474
        $sql = "DELETE FROM ".Database::get_course_table(TABLE_FORUM_MAIL_QUEUE)."
475
                WHERE c_id = $course_id AND user_id IN (".$user_ids.")";
476
        Database::query($sql);
477
478
        // Unsubscribe user from the course.
479
        if (!empty($session_id)) {
480
            // Delete in table session_rel_course_rel_user
481
            $sql = "DELETE FROM ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)."
482
                    WHERE
483
                        session_id ='" . $session_id."' AND
484
                        c_id = '" . $course_id."' AND
485
                        user_id IN ($user_ids)";
486
            Database::query($sql);
487
488
            foreach ($userList as $uid) {
489
                // check if a user is register in the session with other course
490
                $sql = "SELECT user_id FROM ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)."
491
                        WHERE session_id='$session_id' AND user_id='$uid'";
492
                $rs = Database::query($sql);
493
494
                if (Database::num_rows($rs) == 0) {
495
                    // Delete in table session_rel_user
496
                    $sql = "DELETE FROM ".Database::get_main_table(TABLE_MAIN_SESSION_USER)."
497
                            WHERE
498
                                session_id ='" . $session_id."' AND
499
                                user_id = '$uid' AND
500
                                relation_type<>".SESSION_RELATION_TYPE_RRHH."";
501
                    Database::query($sql);
502
                }
503
            }
504
505
            // Update the table session
506
            $sql = "SELECT COUNT(*) FROM ".Database::get_main_table(TABLE_MAIN_SESSION_USER)."
507
                    WHERE session_id = '" . $session_id."' AND relation_type <> ".SESSION_RELATION_TYPE_RRHH;
508
            $row = Database::fetch_array(Database::query($sql));
509
            $count = $row[0];
510
            // number of users by session
511
            $sql = "UPDATE ".Database::get_main_table(TABLE_MAIN_SESSION)." SET nbr_users = '$count'
512
                    WHERE id = '".$session_id."'";
513
            Database::query($sql);
514
515
            // Update the table session_rel_course
516
            $sql = "SELECT COUNT(*) FROM ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)."
517
                    WHERE session_id = '$session_id' AND c_id = '$course_id' AND status<>2";
518
            $row = Database::fetch_array(@Database::query($sql));
519
            $count = $row[0];
520
521
            // number of users by session and course
522
            $sql = "UPDATE ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE)."
523
                    SET nbr_users = '$count'
524
                    WHERE session_id = '$session_id' AND c_id = '$course_id'";
525
            Database::query($sql);
526
527
            Event::addEvent(
528
                LOG_UNSUBSCRIBE_USER_FROM_COURSE,
529
                LOG_COURSE_CODE,
530
                $course_code,
531
                api_get_utc_datetime(),
532
                $user_id,
533
                $course_id,
534
                $session_id
535
            );
536
        } else {
537
            $sql = "DELETE FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
538
                    WHERE
539
                        user_id IN (".$user_ids.") AND
540
                        relation_type <> ".COURSE_RELATION_TYPE_RRHH." AND
541
                        c_id = '".$course_id."'";
542
            Database::query($sql);
543
544
            // add event to system log
545
            $user_id = api_get_user_id();
546
547
            Event::addEvent(
548
                LOG_UNSUBSCRIBE_USER_FROM_COURSE,
549
                LOG_COURSE_CODE,
550
                $course_code,
551
                api_get_utc_datetime(),
552
                $user_id,
553
                $course_id
554
            );
555
556
            foreach ($userList as $userId) {
557
                $userInfo = api_get_user_info($userId);
558
                Event::addEvent(
559
                    LOG_UNSUBSCRIBE_USER_FROM_COURSE,
560
                    LOG_USER_OBJECT,
561
                    $userInfo,
562
                    api_get_utc_datetime(),
563
                    $user_id,
564
                    $course_id
565
                );
566
            }
567
        }
568
    }
569
570
    /**
571
     * Subscribe a user to a course. No checks are performed here to see if
572
     * course subscription is allowed.
573
     * @param   int     $user_id
574
     * @param   string  $course_code
575
     * @param   int     $status (STUDENT, COURSEMANAGER, COURSE_ADMIN, NORMAL_COURSE_MEMBER)
576
     * @param   int $session_id
577
     * @param   int $userCourseCategoryId
578
     *
579
     * @return  bool    True on success, false on failure
580
     * @see add_user_to_course
581
     * @assert ('', '') === false
582
     */
583
    public static function subscribe_user(
584
        $user_id,
585
        $course_code,
586
        $status = STUDENT,
587
        $session_id = 0,
588
        $userCourseCategoryId = 0
589
    ) {
590
        if ($user_id != strval(intval($user_id))) {
591
            return false; //detected possible SQL injection
592
        }
593
594
        $course_code = Database::escape_string($course_code);
595
        $courseInfo = api_get_course_info($course_code);
596
        $courseId = $courseInfo['real_id'];
597
        $courseCode = $courseInfo['code'];
598
        $userCourseCategoryId = intval($userCourseCategoryId);
599
600
        if (empty($user_id) || empty($course_code)) {
601
            return false;
602
        }
603
604
        if (!empty($session_id)) {
605
            $session_id = intval($session_id);
606
        } else {
607
            $session_id = api_get_session_id();
608
        }
609
610
        $status = ($status == STUDENT || $status == COURSEMANAGER) ? $status : STUDENT;
611
612
        // A preliminary check whether the user has bben already registered on the platform.
613
        $sql = "SELECT status FROM ".Database::get_main_table(TABLE_MAIN_USER)."
614
                WHERE user_id = '$user_id' ";
615
        if (Database::num_rows(Database::query($sql)) == 0) {
616
            return false; // The user has not been registered to the platform.
617
        }
618
619
        // Check whether the user has not been already subscribed to the course.
620
        $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."                    
621
                WHERE 
622
                    user_id = '$user_id' AND 
623
                    relation_type <> ".COURSE_RELATION_TYPE_RRHH." AND 
624
                    c_id = $courseId
625
                ";
626
        if (empty($session_id)) {
627
            if (Database::num_rows(Database::query($sql)) > 0) {
628
                // The user has been already subscribed to the course.
629
                return false;
630
            }
631
        }
632
633
        if (!empty($session_id)) {
634
            SessionManager::subscribe_users_to_session_course(
635
                array($user_id),
636
                $session_id,
637
                $courseCode
638
            );
639
            // Add event to the system log
640
            Event::addEvent(
641
                LOG_SUBSCRIBE_USER_TO_COURSE,
642
                LOG_COURSE_CODE,
643
                $course_code,
644
                api_get_utc_datetime(),
645
                api_get_user_id(),
646
                $courseId,
647
                $session_id
648
            );
649
            $user_info = api_get_user_info($user_id);
650
            Event::addEvent(
651
                LOG_SUBSCRIBE_USER_TO_COURSE,
652
                LOG_USER_OBJECT,
653
                $user_info,
654
                api_get_utc_datetime(),
655
                api_get_user_id(),
656
                $courseId,
657
                $session_id
658
            );
659
660
        } else {
661
            self::add_user_to_course(
662
                $user_id,
663
                $courseCode,
664
                $status,
665
                $userCourseCategoryId
666
            );
667
668
            // Add event to the system log
669
            Event::addEvent(
670
                LOG_SUBSCRIBE_USER_TO_COURSE,
671
                LOG_COURSE_CODE,
672
                $course_code,
673
                api_get_utc_datetime(),
674
                api_get_user_id(),
675
                $courseId
676
            );
677
678
            $user_info = api_get_user_info($user_id);
679
            Event::addEvent(
680
                LOG_SUBSCRIBE_USER_TO_COURSE,
681
                LOG_USER_OBJECT,
682
                $user_info,
683
                api_get_utc_datetime(),
684
                api_get_user_id(),
685
                $courseId
686
            );
687
        }
688
689
        return true;
690
    }
691
692
    /**
693
     * Get the course id based on the original id and field name in the
694
     * extra fields. Returns 0 if course was not found
695
     *
696
     * @param string $original_course_id_value
697
     * @param string $original_course_id_name
698
     * @return int Course id
699
     *
700
     * @assert ('', '') === false
701
     */
702
    public static function get_course_code_from_original_id(
703
        $original_course_id_value,
704
        $original_course_id_name
705
    ) {
706
        $t_cfv = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
707
        $table_field = Database::get_main_table(TABLE_EXTRA_FIELD);
708
        $extraFieldType = EntityExtraField::COURSE_FIELD_TYPE;
709
        $original_course_id_value = Database::escape_string($original_course_id_value);
710
        $original_course_id_name = Database::escape_string($original_course_id_name);
711
712
        $sql = "SELECT item_id
713
                FROM $table_field cf
714
                INNER JOIN $t_cfv cfv
715
                ON cfv.field_id=cf.id
716
                WHERE
717
                    variable = '$original_course_id_name' AND
718
                    value = '$original_course_id_value' AND
719
                    cf.extra_field_type = $extraFieldType
720
                ";
721
        $res = Database::query($sql);
722
        $row = Database::fetch_object($res);
723
        if ($row) {
724
            return $row->item_id;
725
        } else {
726
            return 0;
727
        }
728
    }
729
730
    /**
731
     * Gets the course code from the course id. Returns null if course id was not found
732
     *
733
     * @param int $id Course id
734
     * @return string Course code
735
     * @assert ('') === false
736
     */
737
    public static function get_course_code_from_course_id($id)
738
    {
739
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
740
        $id = intval($id);
741
        $sql = "SELECT code FROM $table WHERE id = '$id' ";
742
        $res = Database::query($sql);
743
        $row = Database::fetch_object($res);
744
        if ($row) {
745
            return $row->code;
746
        } else {
747
            return null;
748
        }
749
    }
750
751
    /**
752
     * Subscribe a user $user_id to a course defined by $courseCode.
753
     * @author Hugues Peeters
754
     * @author Roan Embrechts
755
     *
756
     * @param   int $user_id the id of the user
757
     * @param   string $courseCode the course code
758
     * @param   int $status (optional) The user's status in the course
759
     * @param   int $userCourseCategoryId
760
     * @param   int The user category in which this subscription will be classified
761
     *
762
     * @return false|string true if subscription succeeds, boolean false otherwise.
763
     * @assert ('', '') === false
764
     */
765
    public static function add_user_to_course(
766
        $user_id,
767
        $courseCode,
768
        $status = STUDENT,
769
        $userCourseCategoryId = 0
770
    ) {
771
        $debug = false;
772
        $user_table = Database::get_main_table(TABLE_MAIN_USER);
773
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
774
        $course_user_table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
775
776
        $status = ($status == STUDENT || $status == COURSEMANAGER) ? $status : STUDENT;
777
        if (empty($user_id) || empty($courseCode) || ($user_id != strval(intval($user_id)))) {
778
            return false;
779
        }
780
781
        $courseCode = Database::escape_string($courseCode);
782
        $courseInfo = api_get_course_info($courseCode);
783
        $courseId = $courseInfo['real_id'];
784
785
        // Check in advance whether the user has already been registered on the platform.
786
        $sql = "SELECT status FROM ".$user_table." WHERE user_id = $user_id ";
787
        if (Database::num_rows(Database::query($sql)) == 0) {
788
            if ($debug) {
789
                error_log('The user has not been registered to the platform');
790
            }
791
            return false; // The user has not been registered to the platform.
792
        }
793
794
        // Check whether the user has already been subscribed to this course.
795
        $sql = "SELECT * FROM $course_user_table
796
                WHERE
797
                    user_id = $user_id AND
798
                    relation_type <> ".COURSE_RELATION_TYPE_RRHH." AND
799
                    c_id = $courseId";
800
        if (Database::num_rows(Database::query($sql)) > 0) {
801
            if ($debug) {
802
                error_log('The user has been already subscribed to the course');
803
            }
804
            return false; // The user has been subscribed to the course.
805
        }
806
807
        if (!api_is_course_admin()) {
808
            // Check in advance whether subscription is allowed or not for this course.
809
            $sql = "SELECT code, visibility FROM $course_table
810
                    WHERE id = $courseId AND subscribe = '".SUBSCRIBE_NOT_ALLOWED."'";
811
            if (Database::num_rows(Database::query($sql)) > 0) {
812
                if ($debug) {
813
                    error_log('Subscription is not allowed for this course');
814
                }
815
                return false; // Subscription is not allowed for this course.
816
            }
817
        }
818
819
        // Ok, subscribe the user.
820
        $max_sort = api_max_sort_value('0', $user_id);
821
        $params = [
822
            'c_id' => $courseId,
823
            'user_id' => $user_id,
824
            'status' => $status,
825
            'sort' => $max_sort + 1,
826
            'relation_type' => 0,
827
            'user_course_cat' => (int) $userCourseCategoryId
828
        ];
829
        $insertId = Database::insert($course_user_table, $params);
830
831
        return $insertId;
832
    }
833
834
    /**
835
     * Add the user $userId visibility to the course $courseCode in the catalogue.
836
     * @author David Nos (https://github.com/dnos)
837
     *
838
     * @param  int $userId the id of the user
839
     * @param  string $courseCode the course code
840
     * @param  int $visible (optional) The course visibility in the catalogue to the user (1=visible, 0=invisible)
841
     *
842
     * @return boolean true if added succesfully, false otherwise.
843
     */
844
    public static function addUserVisibilityToCourseInCatalogue(
845
        $userId,
846
        $courseCode,
847
        $visible = 1
848
    ) {
849
        $debug = false;
850
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
851
        $courseUserTable = Database::get_main_table(TABLE_MAIN_COURSE_CATALOGUE_USER);
852
        $visible = (int) $visible;
853
        if (empty($userId) || empty($courseCode) || ($userId != strval(intval($userId)))) {
854
            return false;
855
        }
856
857
        $courseCode = Database::escape_string($courseCode);
858
        $courseInfo = api_get_course_info($courseCode);
859
        $courseId = $courseInfo['real_id'];
860
861
        // Check in advance whether the user has already been registered on the platform.
862
        $sql = "SELECT status FROM ".$userTable." WHERE user_id = $userId ";
863
        if (Database::num_rows(Database::query($sql)) == 0) {
864
            if ($debug) {
865
                error_log('The user has not been registered to the platform');
866
            }
867
            return false; // The user has not been registered to the platform.
868
        }
869
870
        // Check whether the user has already been registered to the course visibility in the catalogue.
871
        $sql = "SELECT * FROM $courseUserTable
872
                WHERE
873
                    user_id = $userId AND
874
                    visible = $visible AND
875
                    c_id = $courseId";
876
        if (Database::num_rows(Database::query($sql)) > 0) {
877
            if ($debug) {
878
                error_log('The user has been already registered to the course visibility in the catalogue');
879
            }
880
            return true; // The visibility of the user to the course in the catalogue does already exist.
881
        }
882
883
        // Register the user visibility to course in catalogue.
884
        $params = [
885
            'user_id' => $userId,
886
            'c_id' => $courseId,
887
            'visible' => $visible
888
        ];
889
        $insertId = Database::insert($courseUserTable, $params);
890
891
        return $insertId;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $insertId also could return the type integer which is incompatible with the documented return type boolean.
Loading history...
892
    }
893
894
    /**
895
     * Remove the user $userId visibility to the course $courseCode in the catalogue.
896
     * @author David Nos (https://github.com/dnos)
897
     *
898
     * @param  int $userId the id of the user
899
     * @param  string $courseCode the course code
900
     * @param  int $visible (optional) The course visibility in the catalogue to the user (1=visible, 0=invisible)
901
     *
902
     * @return boolean true if removed succesfully or register not found, false otherwise.
903
     */
904
    public static function removeUserVisibilityToCourseInCatalogue(
905
        $userId,
906
        $courseCode,
907
        $visible = 1
908
    ) {
909
        $courseUserTable = Database::get_main_table(TABLE_MAIN_COURSE_CATALOGUE_USER);
910
911
        if (empty($userId) || empty($courseCode) || ($userId != strval(intval($userId)))) {
912
            return false;
913
        }
914
915
        $courseCode = Database::escape_string($courseCode);
916
        $courseInfo = api_get_course_info($courseCode);
917
        $courseId = $courseInfo['real_id'];
918
919
        // Check whether the user has already been registered to the course visibility in the catalogue.
920
        $sql = "SELECT * FROM $courseUserTable
921
                WHERE
922
                    user_id = $userId AND
923
                    visible = ".$visible." AND
924
                    c_id = $courseId";
925
        if (Database::num_rows(Database::query($sql)) > 0) {
926
            $cond = array(
927
                'user_id = ? AND c_id = ? AND visible = ? ' => array(
928
                    $userId,
929
                    $courseId,
930
                    $visible
931
                )
932
            );
933
            return Database::delete($courseUserTable, $cond);
0 ignored issues
show
Bug Best Practice introduced by
The expression return Database::delete($courseUserTable, $cond) returns the type integer which is incompatible with the documented return type boolean.
Loading history...
934
        } else {
935
            return true; // Register does not exist
936
        }
937
    }
938
939
    /**
940
     * @param string $code
941
     * @return boolean if there already are one or more courses
942
     *  with the same code OR visual_code (visualcode), false otherwise
943
     */
944
    public static function course_code_exists($code)
945
    {
946
        $code = Database::escape_string($code);
947
        $sql = "SELECT COUNT(*) as number
948
                FROM ".Database::get_main_table(TABLE_MAIN_COURSE)."
949
                WHERE code = '$code' OR visual_code = '$code'";
950
        $result = Database::fetch_array(Database::query($sql));
951
952
        return $result['number'] > 0;
953
    }
954
955
    /**
956
     * @param int $user_id
957
     * @param string $startsWith Optional
958
     * @return array An array with the course info of all the courses (real and virtual)
959
     * of which the current user is course admin.
960
     */
961
    public static function get_course_list_of_user_as_course_admin($user_id, $startsWith = '')
962
    {
963
        if ($user_id != strval(intval($user_id))) {
964
            return [];
965
        }
966
967
        // Definitions database tables and variables
968
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
969
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
970
        $user_id = intval($user_id);
971
        $data = [];
972
973
        $sql = "SELECT
974
                    course.code,
975
                    course.title,
976
                    course.id,
977
                    course.id as real_id,
978
                    course.category_code
979
                FROM $tbl_course_user as course_rel_user
980
                INNER JOIN $tbl_course as course
981
                ON course.id = course_rel_user.c_id
982
                WHERE
983
                    course_rel_user.user_id='$user_id' AND
984
                    course_rel_user.status='1'
985
        ";
986
987
        if (api_get_multiple_access_url()) {
988
            $tbl_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
989
            $access_url_id = api_get_current_access_url_id();
990
            if ($access_url_id != -1) {
991
                $sql = "
992
                    SELECT
993
                        course.code,
994
                        course.title,
995
                        course.id,
996
                        course.id as real_id
997
                    FROM $tbl_course_user as course_rel_user
998
                    INNER JOIN $tbl_course as course
999
                    ON course.id = course_rel_user.c_id
1000
                    INNER JOIN $tbl_course_rel_access_url course_rel_url
1001
                    ON (course_rel_url.c_id = course.id)
1002
                    WHERE
1003
                        access_url_id = $access_url_id  AND
1004
                        course_rel_user.user_id = '$user_id' AND
1005
                        course_rel_user.status = '1'
1006
                ";
1007
            }
1008
        }
1009
1010
        if (!empty($startsWith)) {
1011
            $startsWith = Database::escape_string($startsWith);
1012
1013
            $sql .= " AND (course.title LIKE '$startsWith%' OR course.code LIKE '$startsWith%')";
1014
        }
1015
1016
        $sql .= ' ORDER BY course.title';
1017
1018
        $result_nb_cours = Database::query($sql);
1019
        if (Database::num_rows($result_nb_cours) > 0) {
1020
            while ($row = Database::fetch_array($result_nb_cours, 'ASSOC')) {
1021
                $data[$row['id']] = $row;
1022
            }
1023
        }
1024
1025
        return $data;
1026
    }
1027
1028
    /**
1029
     * @param int $userId
1030
     * @param array $courseInfo
1031
     * @return boolean|null
1032
     */
1033
    public static function isUserSubscribedInCourseAsDrh($userId, $courseInfo)
1034
    {
1035
        $userId = intval($userId);
1036
1037
        if (!api_is_drh()) {
1038
            return false;
1039
        }
1040
1041
        if (empty($courseInfo) || empty($userId)) {
1042
            return false;
1043
        }
1044
1045
        $courseId = intval($courseInfo['real_id']);
1046
        $table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1047
1048
        $sql = "SELECT * FROM $table
1049
                WHERE
1050
                    user_id = $userId AND
1051
                    relation_type = ".COURSE_RELATION_TYPE_RRHH." AND
1052
                    c_id = $courseId";
1053
1054
        $result = Database::fetch_array(Database::query($sql));
1055
1056
        if (!empty($result)) {
1057
            // The user has been registered in this course.
1058
            return true;
1059
        }
1060
    }
1061
1062
    /**
1063
     * Check if user is subscribed inside a course
1064
     * @param  int $user_id
1065
     * @param  string $course_code , if this parameter is null, it'll check for all courses
1066
     * @param  bool $in_a_session True for checking inside sessions too, by default is not checked
1067
     * @return bool   $session_id true if the user is registered in the course, false otherwise
1068
     */
1069
    public static function is_user_subscribed_in_course(
1070
        $user_id,
1071
        $course_code = null,
1072
        $in_a_session = false,
1073
        $session_id = 0
1074
    ) {
1075
        $user_id = intval($user_id);
1076
1077
        if (empty($session_id)) {
1078
            $session_id = api_get_session_id();
1079
        } else {
1080
            $session_id = intval($session_id);
1081
        }
1082
1083
        $condition_course = '';
1084
        if (isset($course_code)) {
1085
            $courseInfo = api_get_course_info($course_code);
1086
            if (empty($courseInfo)) {
1087
                return false;
1088
            }
1089
            $courseId = $courseInfo['real_id'];
1090
            $condition_course = ' AND c_id = '.$courseId;
1091
        }
1092
1093
        $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
1094
                WHERE
1095
                    user_id = $user_id AND
1096
                    relation_type<>".COURSE_RELATION_TYPE_RRHH."
1097
                    $condition_course ";
1098
1099
        $result = Database::fetch_array(Database::query($sql));
1100
1101
        if (!empty($result)) {
1102
            // The user has been registered in this course.
1103
            return true;
1104
        }
1105
1106
        if (!$in_a_session) {
1107
            // The user has not been registered in this course.
1108
            return false;
1109
        }
1110
1111
        $tableSessionCourseUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
1112
        $sql = 'SELECT 1 FROM '.$tableSessionCourseUser.
1113
            ' WHERE user_id = '.$user_id.' '.$condition_course;
1114
        if (Database::num_rows(Database::query($sql)) > 0) {
1115
            return true;
1116
        }
1117
1118
        $sql = 'SELECT 1 FROM '.$tableSessionCourseUser.' WHERE user_id = '.$user_id.' AND status=2 '.$condition_course;
1119
        if (Database::num_rows(Database::query($sql)) > 0) {
1120
            return true;
1121
        }
1122
1123
        $sql = 'SELECT 1 FROM '.Database::get_main_table(TABLE_MAIN_SESSION).
1124
            ' WHERE id = '.$session_id.' AND id_coach='.$user_id;
1125
1126
        if (Database::num_rows(Database::query($sql)) > 0) {
1127
            return true;
1128
        }
1129
1130
        return false;
1131
    }
1132
1133
    /**
1134
     * Is the user a teacher in the given course?
1135
     *
1136
     * @param integer $user_id , the id (int) of the user
1137
     * @param string $course_code , the course code
1138
     *
1139
     * @return boolean if the user is a teacher in the course, false otherwise
1140
     */
1141
    public static function is_course_teacher($user_id, $course_code)
1142
    {
1143
        if ($user_id != strval(intval($user_id))) {
1144
            return false;
1145
        }
1146
1147
        $courseInfo = api_get_course_info($course_code);
1148
        if (empty($courseInfo)) {
1149
            return false;
1150
        }
1151
        $courseId = $courseInfo['real_id'];
1152
        $sql = "SELECT status FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
1153
                WHERE c_id = $courseId AND user_id = $user_id ";
1154
        $result = Database::query($sql);
1155
1156
        if (Database::num_rows($result) > 0) {
1157
            return Database::result($result, 0, 'status') == 1;
1158
        }
1159
1160
        return false;
1161
    }
1162
1163
    /**
1164
     *    Is the user subscribed in the real course or linked courses?
1165
     *
1166
     * @param int the id of the user
1167
     * @param int $courseId
1168
     * @deprecated linked_courses definition doesn't exists
1169
     * @return boolean if the user is registered in the real course or linked courses, false otherwise
1170
     */
1171
    public static function is_user_subscribed_in_real_or_linked_course($user_id, $courseId, $session_id = 0)
1172
    {
1173
        if ($user_id != strval(intval($user_id))) {
1174
            return false;
1175
        }
1176
1177
        $courseId = intval($courseId);
1178
        $session_id = intval($session_id);
1179
1180
        if (empty($session_id)) {
1181
            $result = Database::fetch_array(
1182
                Database::query(
1183
                    "SELECT *
1184
                    FROM " . Database::get_main_table(TABLE_MAIN_COURSE)." course
1185
                    LEFT JOIN " . Database::get_main_table(TABLE_MAIN_COURSE_USER)." course_user
1186
                    ON course.id = course_user.c_id
1187
                    WHERE
1188
                        course_user.user_id = '$user_id' AND
1189
                        course_user.relation_type<>".COURSE_RELATION_TYPE_RRHH." AND
1190
                        ( course.id = '$courseId')"
1191
                )
1192
            );
1193
            return !empty($result);
1194
        }
1195
1196
1197
        // From here we trust session id.
1198
        // Is he/she subscribed to the session's course?
1199
        // A user?
1200
        if (Database::num_rows(Database::query("SELECT user_id
1201
                FROM " . Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)."
1202
                WHERE session_id='".$session_id."'
1203
                AND user_id ='$user_id'"))
1204
        ) {
1205
            return true;
1206
        }
1207
1208
        // A course coach?
1209
        if (Database::num_rows(Database::query("SELECT user_id
1210
                FROM ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)."
1211
                WHERE session_id='".$session_id."'
1212
                AND user_id = '$user_id' AND status = 2
1213
                AND c_id = '$courseId'"))
1214
        ) {
1215
            return true;
1216
        }
1217
1218
        // A session coach?
1219
        if (Database::num_rows(Database::query("SELECT id_coach
1220
                FROM " . Database::get_main_table(TABLE_MAIN_SESSION)." AS session
1221
                WHERE session.id='".$session_id."'
1222
                AND id_coach = '$user_id'"))
1223
        ) {
1224
            return true;
1225
        }
1226
1227
        return false;
1228
    }
1229
1230
    /**
1231
     * Return user info array of all users registered in a course
1232
     * This only returns the users that are registered in this actual course, not linked courses.
1233
     * @param string $course_code
1234
     * @param int $session_id
1235
     * @param string $limit
1236
     * @param string $order_by the field to order the users by.
1237
     * Valid values are 'lastname', 'firstname', 'username', 'email', 'official_code' OR a part of a SQL statement
1238
     * that starts with ORDER BY ...
1239
     * @param integer|null $filter_by_status if using the session_id: 0 or 2 (student, coach),
1240
     * if using session_id = 0 STUDENT or COURSEMANAGER
1241
     * @param boolean|null $return_count
1242
     * @param bool $add_reports
1243
     * @param bool $resumed_report
1244
     * @param array $extra_field
1245
     * @param array $courseCodeList
1246
     * @param array $userIdList
1247
     * @param string $filterByActive
1248
     * @param array $sessionIdList
1249
     * @return array|int
1250
     */
1251
    public static function get_user_list_from_course_code(
1252
        $course_code = null,
1253
        $session_id = 0,
1254
        $limit = null,
1255
        $order_by = null,
1256
        $filter_by_status = null,
1257
        $return_count = null,
1258
        $add_reports = false,
1259
        $resumed_report = false,
1260
        $extra_field = array(),
1261
        $courseCodeList = array(),
1262
        $userIdList = array(),
1263
        $filterByActive = null,
1264
        $sessionIdList = array()
1265
    ) {
1266
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
1267
        $sessionTable = Database::get_main_table(TABLE_MAIN_SESSION);
1268
1269
        $session_id = intval($session_id);
1270
        $course_code = Database::escape_string($course_code);
1271
        $courseInfo = api_get_course_info($course_code);
1272
        $courseId = 0;
1273
        if (!empty($courseInfo)) {
1274
            $courseId = $courseInfo['real_id'];
1275
        }
1276
1277
        $where = array();
1278
        if (empty($order_by)) {
1279
            $order_by = 'user.lastname, user.firstname';
1280
            if (api_is_western_name_order()) {
1281
                $order_by = 'user.firstname, user.lastname';
1282
            }
1283
        }
1284
1285
        // if the $order_by does not contain 'ORDER BY'
1286
        // we have to check if it is a valid field that can be sorted on
1287
        if (!strstr($order_by, 'ORDER BY')) {
1288
            if (!empty($order_by)) {
1289
                $order_by = 'ORDER BY '.$order_by;
1290
            } else {
1291
                $order_by = '';
1292
            }
1293
        }
1294
1295
        $filter_by_status_condition = null;
1296
1297
        if (!empty($session_id) || !empty($sessionIdList)) {
1298
            $sql = 'SELECT DISTINCT
1299
                        user.user_id,
1300
                        user.email,
1301
                        session_course_user.status as status_session,
1302
                        session_id,
1303
                        user.*,
1304
                        course.*,
1305
                        session.name as session_name
1306
                    ';
1307
            if ($return_count) {
1308
                $sql = " SELECT COUNT(user.user_id) as count";
1309
            }
1310
1311
            $sessionCondition = " session_course_user.session_id = $session_id";
1312
            if (!empty($sessionIdList)) {
1313
                $sessionIdListTostring = implode("','", array_map('intval', $sessionIdList));
1314
                $sessionCondition = " session_course_user.session_id IN ('$sessionIdListTostring') ";
1315
            }
1316
1317
            $courseCondition = " course.id = $courseId";
1318
            if (!empty($courseCodeList)) {
1319
                $courseCodeListForSession = array_map(array('Database', 'escape_string'), $courseCodeList);
1320
                $courseCodeListForSession = implode('","', $courseCodeListForSession);
1321
                $courseCondition = ' course.code IN ("'.$courseCodeListForSession.'")  ';
1322
            }
1323
1324
            $sql .= ' FROM '.Database::get_main_table(TABLE_MAIN_USER).' as user ';
1325
            $sql .= " LEFT JOIN ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)." as session_course_user
1326
                      ON
1327
                        user.id = session_course_user.user_id AND
1328
                        $sessionCondition
1329
                        INNER JOIN $course_table course 
1330
                        ON session_course_user.c_id = course.id AND
1331
                        $courseCondition
1332
                        INNER JOIN $sessionTable session 
1333
                        ON session_course_user.session_id = session.id
1334
                   ";
1335
            $where[] = ' session_course_user.c_id IS NOT NULL ';
1336
1337
            // 2 = coach
1338
            // 0 = student
1339
            if (isset($filter_by_status)) {
1340
                $filter_by_status = intval($filter_by_status);
1341
                $filter_by_status_condition = " session_course_user.status = $filter_by_status AND ";
1342
            }
1343
        } else {
1344
            if ($return_count) {
1345
                $sql = " SELECT COUNT(*) as count";
1346
            } else {
1347
                if (empty($course_code)) {
1348
                    $sql = 'SELECT DISTINCT
1349
                                course.title,
1350
                                course.code,
1351
                                course_rel_user.status as status_rel,
1352
                                user.id as user_id,
1353
                                user.email,
1354
                                course_rel_user.is_tutor,
1355
                                user.*  ';
1356
                } else {
1357
                    $sql = 'SELECT DISTINCT
1358
                                course_rel_user.status as status_rel,
1359
                                user.id as user_id,
1360
                                user.email,
1361
                                course_rel_user.is_tutor,
1362
                                user.*  ';
1363
                }
1364
            }
1365
1366
            $sql .= ' FROM '.Database::get_main_table(TABLE_MAIN_USER).' as user '
1367
                  . ' LEFT JOIN '.Database::get_main_table(TABLE_MAIN_COURSE_USER).' as course_rel_user
1368
                      ON 
1369
                        user.id = course_rel_user.user_id AND
1370
                        course_rel_user.relation_type <> ' . COURSE_RELATION_TYPE_RRHH.'  '
1371
                  . " INNER JOIN $course_table course ON course_rel_user.c_id = course.id ";
1372
1373
            if (!empty($course_code)) {
1374
                $sql .= ' AND course_rel_user.c_id = "'.$courseId.'"';
1375
            }
1376
            $where[] = ' course_rel_user.c_id IS NOT NULL ';
1377
1378
            if (isset($filter_by_status) && is_numeric($filter_by_status)) {
1379
                $filter_by_status = intval($filter_by_status);
1380
                $filter_by_status_condition = " course_rel_user.status = $filter_by_status AND ";
1381
            }
1382
        }
1383
1384
        $multiple_access_url = api_get_multiple_access_url();
1385
        if ($multiple_access_url) {
1386
            $sql .= ' LEFT JOIN '.Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER).' au
1387
                      ON (au.user_id = user.id) ';
1388
        }
1389
1390
        $extraFieldWasAdded = false;
1391
        if ($return_count && $resumed_report) {
1392
            foreach ($extra_field as $extraField) {
1393
                $extraFieldInfo = UserManager::get_extra_field_information_by_name($extraField);
1394
                if (!empty($extraFieldInfo)) {
1395
                    $fieldValuesTable = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
1396
                    $sql .= ' LEFT JOIN '.$fieldValuesTable.' as ufv
1397
                            ON (
1398
                                user.id = ufv.item_id AND
1399
                                (field_id = '.$extraFieldInfo['id'].' OR field_id IS NULL)
1400
                            )';
1401
                    $extraFieldWasAdded = true;
1402
                }
1403
            }
1404
        }
1405
1406
        $sql .= ' WHERE '.$filter_by_status_condition.' '.implode(' OR ', $where);
1407
1408
        if ($multiple_access_url) {
1409
            $current_access_url_id = api_get_current_access_url_id();
1410
            $sql .= " AND (access_url_id =  $current_access_url_id ) ";
1411
        }
1412
1413
        if ($return_count && $resumed_report && $extraFieldWasAdded) {
1414
            $sql .= ' AND field_id IS NOT NULL GROUP BY value ';
1415
        }
1416
1417
        if (!empty($courseCodeList)) {
1418
            $courseCodeList = array_map(array('Database', 'escape_string'), $courseCodeList);
1419
            $courseCodeList = implode('","', $courseCodeList);
1420
            if (empty($sessionIdList)) {
1421
                $sql .= ' AND course.code IN ("'.$courseCodeList.'")';
1422
            }
1423
        }
1424
1425
        if (!empty($userIdList)) {
1426
            $userIdList = array_map('intval', $userIdList);
1427
            $userIdList = implode('","', $userIdList);
1428
            $sql .= ' AND user.id IN ("'.$userIdList.'")';
1429
        }
1430
1431
        if (isset($filterByActive)) {
1432
            $filterByActive = intval($filterByActive);
1433
            $sql .= ' AND user.active = '.$filterByActive;
1434
        }
1435
1436
        $sql .= ' '.$order_by.' '.$limit;
1437
1438
        $rs = Database::query($sql);
1439
        $users = array();
1440
1441
        $extra_fields = UserManager::get_extra_fields(
1442
            0,
1443
            100,
1444
            null,
1445
            null,
1446
            true,
1447
            true
1448
        );
1449
1450
        $counter = 1;
1451
        $count_rows = Database::num_rows($rs);
1452
1453
        if ($return_count && $resumed_report) {
1454
            return $count_rows;
1455
        }
1456
1457
        $table_user_field_value = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
1458
        $tableExtraField = Database::get_main_table(TABLE_EXTRA_FIELD);
1459
        if ($count_rows) {
1460
            while ($user = Database::fetch_array($rs)) {
1461
                if ($return_count) {
1462
                    return $user['count'];
1463
                }
1464
                $report_info = array();
1465
                $user_info = $user;
1466
                $user_info['status'] = $user['status'];
1467
                if (isset($user['is_tutor'])) {
1468
                    $user_info['is_tutor'] = $user['is_tutor'];
1469
                }
1470
                if (!empty($session_id)) {
1471
                    $user_info['status_session'] = $user['status_session'];
1472
                }
1473
1474
                $sessionId = isset($user['session_id']) ? $user['session_id'] : 0;
1475
                $course_code = isset($user['code']) ? $user['code'] : null;
1476
1477
                if ($add_reports) {
1478
                    if ($resumed_report) {
1479
                        $extra = array();
1480
1481
                        if (!empty($extra_fields)) {
1482
                            foreach ($extra_fields as $extra) {
1483
                                if (in_array($extra['1'], $extra_field)) {
1484
                                    $user_data = UserManager::get_extra_user_data_by_field(
1485
                                        $user['user_id'],
1486
                                        $extra['1']
1487
                                    );
1488
                                    break;
1489
                                }
1490
                            }
1491
                        }
1492
1493
                        $row_key = '-1';
1494
                        $name = '-';
1495
1496
                        if (!empty($extra)) {
1497
                            if (!empty($user_data[$extra['1']])) {
1498
                                $row_key = $user_data[$extra['1']];
1499
                                $name = $user_data[$extra['1']];
1500
                                $users[$row_key]['extra_'.$extra['1']] = $name;
1501
                            }
1502
                        }
1503
1504
                        $users[$row_key]['training_hours'] += Tracking::get_time_spent_on_the_course(
1505
                            $user['user_id'],
1506
                            $courseId,
1507
                            $sessionId
1508
                        );
1509
1510
                        $users[$row_key]['count_users'] += $counter;
1511
1512
                        $registered_users_with_extra_field = self::getCountRegisteredUsersWithCourseExtraField(
1513
                            $name,
1514
                            $tableExtraField,
1515
                            $table_user_field_value
1516
                        );
1517
1518
                        $users[$row_key]['count_users_registered'] = $registered_users_with_extra_field;
1519
                        $users[$row_key]['average_hours_per_user'] = $users[$row_key]['training_hours'] / $users[$row_key]['count_users'];
1520
1521
                        $category = Category:: load(
1522
                            null,
1523
                            null,
1524
                            $course_code,
1525
                            null,
1526
                            null,
1527
                            $sessionId
1528
                        );
1529
1530
                        if (!isset($users[$row_key]['count_certificates'])) {
1531
                            $users[$row_key]['count_certificates'] = 0;
1532
                        }
1533
1534
                        if (isset($category[0]) && $category[0]->is_certificate_available($user['user_id'])) {
1535
                            $users[$row_key]['count_certificates']++;
1536
                        }
1537
1538
                        foreach ($extra_fields as $extra) {
1539
                            if ($extra['1'] == 'ruc') {
1540
                                continue;
1541
                            }
1542
1543
                            if (!isset($users[$row_key][$extra['1']])) {
1544
                                $user_data = UserManager::get_extra_user_data_by_field($user['user_id'], $extra['1']);
1545
                                if (!empty($user_data[$extra['1']])) {
1546
                                    $users[$row_key][$extra['1']] = $user_data[$extra['1']];
1547
                                }
1548
                            }
1549
                        }
1550
                    } else {
1551
                        $sessionName = !empty($sessionId) ? ' - '.$user['session_name'] : '';
1552
                        $report_info['course'] = $user['title'].$sessionName;
1553
                        $report_info['user'] = api_get_person_name($user['firstname'], $user['lastname']);
1554
                        $report_info['email'] = $user['email'];
1555
                        $report_info['time'] = api_time_to_hms(
1556
                            Tracking::get_time_spent_on_the_course(
1557
                                $user['user_id'],
1558
                                $courseId,
1559
                                $sessionId
1560
                            )
1561
                        );
1562
1563
                        $category = Category:: load(
1564
                            null,
1565
                            null,
1566
                            $course_code,
1567
                            null,
1568
                            null,
1569
                            $sessionId
1570
                        );
1571
1572
                        $report_info['certificate'] = Display::label(get_lang('No'));
1573
                        if (isset($category[0]) && $category[0]->is_certificate_available($user['user_id'])) {
1574
                            $report_info['certificate'] = Display::label(get_lang('Yes'), 'success');
1575
                        }
1576
1577
                        $progress = intval(
1578
                            Tracking::get_avg_student_progress(
1579
                                $user['user_id'],
1580
                                $course_code,
1581
                                array(),
1582
                                $sessionId
1583
                            )
1584
                        );
1585
                        $report_info['progress_100'] = $progress == 100 ? Display::label(get_lang('Yes'), 'success') : Display::label(get_lang('No'));
1586
                        $report_info['progress'] = $progress."%";
1587
1588
                        foreach ($extra_fields as $extra) {
1589
                            $user_data = UserManager::get_extra_user_data_by_field($user['user_id'], $extra['1']);
1590
                            $report_info[$extra['1']] = $user_data[$extra['1']];
1591
                        }
1592
                        $report_info['user_id'] = $user['user_id'];
1593
                        $users[] = $report_info;
1594
                    }
1595
                } else {
1596
                    $users[$user['user_id']] = $user_info;
1597
                }
1598
            }
1599
        }
1600
1601
        return $users;
1602
    }
1603
1604
    /**
1605
     * @param bool $resumed_report
1606
     * @param array $extra_field
1607
     * @param array $courseCodeList
1608
     * @param array $userIdList
1609
     * @param array $sessionIdList
1610
     * @return array|int
1611
     */
1612
    public static function get_count_user_list_from_course_code(
1613
        $resumed_report = false,
1614
        $extra_field = array(),
1615
        $courseCodeList = array(),
1616
        $userIdList = array(),
1617
        $sessionIdList = array()
1618
    ) {
1619
        return self::get_user_list_from_course_code(
1620
            null,
1621
            0,
1622
            null,
1623
            null,
1624
            null,
1625
            true,
1626
            false,
1627
            $resumed_report,
1628
            $extra_field,
1629
            $courseCodeList,
1630
            $userIdList,
1631
            null,
1632
            $sessionIdList
1633
        );
1634
    }
1635
1636
    /**
1637
     * Gets subscribed users in a course or in a course/session
1638
     *
1639
     * @param   string $course_code
1640
     * @param   int $session_id
1641
     * @return  int
1642
     */
1643
    public static function get_users_count_in_course(
1644
        $course_code,
1645
        $session_id = 0,
1646
        $status = null
1647
    ) {
1648
        // variable initialisation
1649
        $session_id = intval($session_id);
1650
        $course_code = Database::escape_string($course_code);
1651
        $tblUser = Database::get_main_table(TABLE_MAIN_USER);
1652
        $tblSessionCourseUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
1653
        $tblCourseUser = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1654
        $tblUrlUser = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
1655
1656
        $courseInfo = api_get_course_info($course_code);
1657
        $courseId = $courseInfo['real_id'];
1658
1659
        $sql = "
1660
            SELECT DISTINCT count(user.id) as count  
1661
            FROM $tblUser as user
1662
        ";
1663
        $where = array();
1664
        if (!empty($session_id)) {
1665
            $sql .= "
1666
                LEFT JOIN $tblSessionCourseUser as session_course_user
1667
                    ON user.user_id = session_course_user.user_id
1668
                    AND session_course_user.c_id = $courseId
1669
                    AND session_course_user.session_id = $session_id
1670
            ";
1671
1672
            $where[] = ' session_course_user.c_id IS NOT NULL ';
1673
        } else {
1674
            $sql .= "
1675
                LEFT JOIN $tblCourseUser as course_rel_user
1676
                    ON user.user_id = course_rel_user.user_id
1677
                    AND course_rel_user.relation_type <> ".COURSE_RELATION_TYPE_RRHH."
1678
                    AND course_rel_user.c_id = $courseId
1679
            ";
1680
            $where[] = ' course_rel_user.c_id IS NOT NULL ';
1681
        }
1682
1683
        $multiple_access_url = api_get_multiple_access_url();
1684
        if ($multiple_access_url) {
1685
            $sql .= " LEFT JOIN $tblUrlUser au ON (au.user_id = user.user_id) ";
1686
        }
1687
1688
        $sql .= ' WHERE '.implode(' OR ', $where);
1689
1690
        if ($multiple_access_url) {
1691
            $current_access_url_id = api_get_current_access_url_id();
1692
            $sql .= " AND (access_url_id =  $current_access_url_id ) ";
1693
        }
1694
        $rs = Database::query($sql);
1695
        $count = 0;
1696
        if (Database::num_rows($rs)) {
1697
            $user = Database::fetch_array($rs);
1698
            $count = $user['count'];
1699
        }
1700
1701
        return $count;
1702
    }
1703
1704
    /**
1705
     * Get a list of coaches of a course and a session
1706
     * @param   string  $course_code
1707
     * @param   int     $session_id
1708
     * @param   bool $addGeneralCoach
1709
     * @return  array   List of users
1710
     */
1711
    public static function get_coach_list_from_course_code(
1712
        $course_code,
1713
        $session_id,
1714
        $addGeneralCoach = true
1715
    ) {
1716
        if (empty($course_code) || empty($session_id)) {
1717
            return array();
1718
        }
1719
1720
        $course_code = Database::escape_string($course_code);
1721
        $courseInfo = api_get_course_info($course_code);
1722
        $courseId = $courseInfo['real_id'];
1723
        $session_id = intval($session_id);
1724
        $users = array();
1725
1726
        // We get the coach for the given course in a given session.
1727
        $sql = 'SELECT user_id FROM '.Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER).
1728
               ' WHERE session_id ="'.$session_id.'" AND c_id="'.$courseId.'" AND status = 2';
1729
        $rs = Database::query($sql);
1730
        while ($user = Database::fetch_array($rs)) {
1731
            $userInfo = api_get_user_info($user['user_id']);
1732
            if ($userInfo) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $userInfo of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1733
                $users[$user['user_id']] = $userInfo;
1734
            }
1735
        }
1736
1737
        if ($addGeneralCoach) {
1738
            $table = Database::get_main_table(TABLE_MAIN_SESSION);
1739
            // We get the session coach.
1740
            $sql = 'SELECT id_coach FROM '.$table.' WHERE id='.$session_id;
1741
            $rs = Database::query($sql);
1742
            $session_id_coach = Database::result($rs, 0, 'id_coach');
1743
            $userInfo = api_get_user_info($session_id_coach);
1744
            if ($userInfo) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $userInfo of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1745
                $users[$session_id_coach] = $userInfo;
1746
            }
1747
        }
1748
1749
        return $users;
1750
    }
1751
1752
    /**
1753
     *  Return user info array of all users registered in a course
1754
     *  This only returns the users that are registered in this actual course, not linked courses.
1755
     *
1756
     * @param string $course_code
1757
     * @param boolean $with_session
1758
     * @param integer $session_id
1759
     * @param string $date_from
1760
     * @param string $date_to
1761
     * @param boolean $includeInvitedUsers Whether include the invited users
1762
     * @param int $groupId
1763
     * @return array with user id
1764
     */
1765
    public static function get_student_list_from_course_code(
1766
        $course_code,
1767
        $with_session = false,
1768
        $session_id = 0,
1769
        $date_from = null,
1770
        $date_to = null,
1771
        $includeInvitedUsers = true,
1772
        $groupId = 0
1773
    ) {
1774
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
1775
        $session_id = intval($session_id);
1776
        $course_code = Database::escape_string($course_code);
1777
        $courseInfo = api_get_course_info($course_code);
1778
        $courseId = $courseInfo['real_id'];
1779
        $students = array();
1780
1781
        if ($session_id == 0) {
1782
            if (empty($groupId)) {
1783
                // students directly subscribed to the course
1784
                $sql = "SELECT *
1785
                        FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)." cu
1786
                        INNER JOIN $userTable u
1787
                        ON cu.user_id = u.user_id
1788
                        WHERE c_id = '$courseId' AND cu.status = ".STUDENT;
1789
1790
                if (!$includeInvitedUsers) {
1791
                    $sql .= " AND u.status != ".INVITEE;
1792
                }
1793
                $rs = Database::query($sql);
1794
                while ($student = Database::fetch_array($rs)) {
1795
                    $students[$student['user_id']] = $student;
1796
                }
1797
            } else {
1798
                $students = GroupManager::get_users(
1799
                    $groupId,
1800
                    false,
1801
                    null,
1802
                    null,
1803
                    false,
1804
                    $courseInfo['real_id']
1805
                );
1806
                $students = array_flip($students);
1807
            }
1808
        }
1809
1810
        // students subscribed to the course through a session
1811
        if ($with_session) {
1812
            $joinSession = '';
1813
            //Session creation date
1814
            if (!empty($date_from) && !empty($date_to)) {
1815
                $joinSession = "INNER JOIN ".Database::get_main_table(TABLE_MAIN_SESSION)." s";
1816
            }
1817
1818
            $sql_query = "SELECT *
1819
                          FROM " . Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)." scu
1820
                          $joinSession
1821
                          INNER JOIN $userTable u ON scu.user_id = u.user_id
1822
                          WHERE scu.c_id = '$courseId' AND scu.status <> 2";
1823
1824
            if (!empty($date_from) && !empty($date_to)) {
1825
                $date_from = Database::escape_string($date_from);
1826
                $date_to = Database::escape_string($date_to);
1827
                $sql_query .= " AND s.access_start_date >= '$date_from' AND s.access_end_date <= '$date_to'";
1828
            }
1829
1830
            if ($session_id != 0) {
1831
                $sql_query .= ' AND scu.session_id = '.$session_id;
1832
            }
1833
1834
            if (!$includeInvitedUsers) {
1835
                $sql_query .= " AND u.status != ".INVITEE;
1836
            }
1837
1838
            $rs = Database::query($sql_query);
1839
            while ($student = Database::fetch_array($rs)) {
1840
                $students[$student['user_id']] = $student;
1841
            }
1842
        }
1843
1844
        return $students;
1845
    }
1846
1847
    /**
1848
     * Return user info array of all teacher-users registered in a course
1849
     * This only returns the users that are registered in this actual course, not linked courses.
1850
     *
1851
     * @param string $course_code
1852
     * @return array with user id
1853
     */
1854
    public static function get_teacher_list_from_course_code($course_code)
1855
    {
1856
        $courseInfo = api_get_course_info($course_code);
1857
        $courseId = $courseInfo['real_id'];
1858
        if (empty($courseId)) {
1859
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type array.
Loading history...
1860
        }
1861
1862
        $sql = "SELECT DISTINCT
1863
                    u.id as user_id,
1864
                    u.lastname,
1865
                    u.firstname,
1866
                    u.email,
1867
                    u.username,
1868
                    u.status
1869
                FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER)." cu
1870
                INNER JOIN " . Database::get_main_table(TABLE_MAIN_USER)." u
1871
                ON (cu.user_id = u.id)
1872
                WHERE
1873
                    cu.c_id = $courseId AND
1874
                    cu.status = 1 ";
1875
        $rs = Database::query($sql);
1876
        $teachers = array();
1877
        while ($teacher = Database::fetch_array($rs)) {
1878
            $teachers[$teacher['user_id']] = $teacher;
1879
        }
1880
1881
        return $teachers;
1882
    }
1883
1884
    /**
1885
     * Return user info array of all teacher-users registered in a course
1886
     * This only returns the users that are registered in this actual course, not linked courses.
1887
     *
1888
     * @param int $courseId
1889
     * @param bool $loadAvatars
1890
     *
1891
     * @return array with user id
1892
     */
1893
    public static function getTeachersFromCourse($courseId, $loadAvatars = true)
1894
    {
1895
        $courseId = (int) $courseId;
1896
1897
        if (empty($courseId)) {
1898
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type array.
Loading history...
1899
        }
1900
1901
        $sql = "SELECT DISTINCT
1902
                    u.id as user_id,
1903
                    u.lastname,
1904
                    u.firstname,
1905
                    u.email,
1906
                    u.username,
1907
                    u.status
1908
                FROM " . Database::get_main_table(TABLE_MAIN_COURSE_USER)." cu
1909
                INNER JOIN " . Database::get_main_table(TABLE_MAIN_USER)." u
1910
                ON (cu.user_id = u.id)
1911
                WHERE
1912
                    cu.c_id = $courseId AND
1913
                    cu.status = 1 ";
1914
        $rs = Database::query($sql);
1915
        $listTeachers = array();
1916
        $teachers = array();
1917
        $url = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&course_id='.$courseId;
1918
        while ($teacher = Database::fetch_array($rs)) {
1919
            $teachers['id'] = $teacher['user_id'];
1920
            $teachers['lastname'] = $teacher['lastname'];
1921
            $teachers['firstname'] = $teacher['firstname'];
1922
            $teachers['email'] = $teacher['email'];
1923
            $teachers['username'] = $teacher['username'];
1924
            $teachers['status'] = $teacher['status'];
1925
            $teachers['fullname'] = api_get_person_name($teacher['firstname'], $teacher['lastname']);
1926
            $teachers['avatar'] = '';
1927
            if ($loadAvatars) {
1928
                $userPicture = UserManager::getUserPicture($teacher['user_id'], USER_IMAGE_SIZE_SMALL);
1929
                $teachers['avatar'] = $userPicture;
1930
            }
1931
            $teachers['url'] = $url.'&user_id='.$teacher['user_id'];
1932
            $listTeachers[] = $teachers;
1933
        }
1934
1935
        return $listTeachers;
1936
    }
1937
1938
    /**
1939
     * Returns a string list of teachers assigned to the given course
1940
     * @param string $course_code
1941
     * @param string $separator between teachers names
1942
     * @param bool $add_link_to_profile Whether to add a link to the teacher's profile
1943
     * @param bool $orderList
1944
     * @return string List of teachers teaching the course
1945
     */
1946
    public static function getTeacherListFromCourseCodeToString(
1947
        $course_code,
1948
        $separator = self::USER_SEPARATOR,
1949
        $add_link_to_profile = false,
1950
        $orderList = false
1951
    ) {
1952
        $teacher_list = self::get_teacher_list_from_course_code($course_code);
1953
        $html = '';
1954
        $list = array();
1955
        if (!empty($teacher_list)) {
1956
            foreach ($teacher_list as $teacher) {
1957
                $teacher_name = api_get_person_name(
1958
                    $teacher['firstname'],
1959
                    $teacher['lastname']
1960
                );
1961
                if ($add_link_to_profile) {
1962
                    $url = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&user_id='.$teacher['user_id'];
1963
                    $teacher_name = Display::url(
1964
                        $teacher_name,
1965
                        $url,
1966
                        [
1967
                            'class' => 'ajax',
1968
                            'data-title' => $teacher_name
1969
                        ]
1970
                    );
1971
                }
1972
                $list[] = $teacher_name;
1973
            }
1974
1975
            if (!empty($list)) {
1976
                if ($orderList === true) {
1977
                    $html .= '<ul class="user-teacher">';
1978
                    foreach ($list as $teacher) {
1979
                        $html .= '<li>';
1980
                        $html .= Display::return_icon('teacher.png', '', null, ICON_SIZE_TINY);
1981
                        $html .= ' '.$teacher;
1982
                        $html .= '</li>';
1983
                    }
1984
                    $html .= '</ul>';
1985
                } else {
1986
                    $html .= array_to_string($list, $separator);
1987
                }
1988
            }
1989
        }
1990
1991
        return $html;
1992
    }
1993
1994
    /**
1995
     * This function returns information about coachs from a course in session
1996
     * @param int $session_id
1997
     * @param int $courseId
1998
     *
1999
     * @return array containing user_id, lastname, firstname, username
2000
     */
2001
    public static function get_coachs_from_course($session_id = 0, $courseId = 0)
2002
    {
2003
        if (!empty($session_id)) {
2004
            $session_id = intval($session_id);
2005
        } else {
2006
            $session_id = api_get_session_id();
2007
        }
2008
2009
        if (!empty($courseId)) {
2010
            $courseId = intval($courseId);
2011
        } else {
2012
            $courseId = api_get_course_int_id();
2013
        }
2014
2015
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
2016
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2017
2018
        $sql = "SELECT DISTINCT 
2019
                    u.user_id,
2020
                    u.lastname,
2021
                    u.firstname,
2022
                    u.username
2023
                FROM $tbl_user u 
2024
                INNER JOIN $tbl_session_course_user scu
2025
                ON (u.user_id = scu.user_id)
2026
                WHERE
2027
                    scu.session_id = '$session_id' AND
2028
                    scu.c_id = '$courseId' AND
2029
                    scu.status = 2";
2030
        $rs = Database::query($sql);
2031
2032
        $coaches = array();
2033
        if (Database::num_rows($rs) > 0) {
2034
            while ($row = Database::fetch_array($rs)) {
2035
                $completeName = api_get_person_name($row['firstname'], $row['lastname']);
2036
                $coaches[] = $row + ['full_name' => $completeName];
2037
            }
2038
        }
2039
2040
        return $coaches;
2041
    }
2042
2043
    /**
2044
     * @param int $session_id
2045
     * @param int $courseId
2046
     * @param string $separator
2047
     * @param bool $add_link_to_profile
2048
     * @param bool $orderList
2049
     * @return string
2050
     */
2051
    public static function get_coachs_from_course_to_string(
2052
        $session_id = 0,
2053
        $courseId = 0,
2054
        $separator = self::USER_SEPARATOR,
2055
        $add_link_to_profile = false,
2056
        $orderList = false
2057
    ) {
2058
        $coachList = self::get_coachs_from_course($session_id, $courseId);
2059
        $course_coachs = array();
2060
        if (!empty($coachList)) {
2061
            foreach ($coachList as $coach_course) {
2062
                $coach_name = $coach_course['full_name'];
2063
                if ($add_link_to_profile) {
2064
                    $url = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&user_id='.$coach_course['user_id'].'&course_id='.$courseId.'&session_id='.$session_id;
2065
                    $coach_name = Display::url(
2066
                        $coach_name,
2067
                        $url,
2068
                        [
2069
                            'class' => 'ajax',
2070
                            'data-title' => $coach_name
2071
                        ]
2072
                    );
2073
                }
2074
                $course_coachs[] = $coach_name;
2075
            }
2076
        }
2077
2078
        $html = '';
2079
        if (!empty($course_coachs)) {
2080
            if ($orderList === true) {
2081
                $html .= '<ul class="user-coachs">';
2082
                foreach ($course_coachs as $coachs) {
2083
                    $html .= Display::tag(
2084
                        'li',
2085
                        Display::return_icon(
2086
                            'teacher.png',
2087
                            $coachs,
2088
                            null,
2089
                            ICON_SIZE_TINY
2090
                        ).' '.$coachs
2091
                    );
2092
                }
2093
                $html .= '</ul>';
2094
            } else {
2095
                $html = array_to_string($course_coachs, $separator);
2096
            }
2097
        }
2098
2099
        return $html;
2100
    }
2101
2102
    /**
2103
     * Get the list of groups from the course
2104
     * @param   string $course_code
2105
     * @param   int $session_id Session ID (optional)
2106
     * @param   integer $in_get_empty_group get empty groups (optional)
2107
     * @return  array   List of groups info
2108
     */
2109
    public static function get_group_list_of_course(
2110
        $course_code,
2111
        $session_id = 0,
2112
        $in_get_empty_group = 0
2113
    ) {
2114
        $course_info = api_get_course_info($course_code);
2115
2116
        if (empty($course_info)) {
2117
            return array();
2118
        }
2119
        $course_id = $course_info['real_id'];
2120
2121
        if (empty($course_id)) {
2122
            return array();
2123
        }
2124
2125
        $group_list = array();
2126
        $session_id != 0 ? $session_condition = ' WHERE g.session_id IN(1,'.intval($session_id).')' : $session_condition = ' WHERE g.session_id = 0';
2127
2128
        if ($in_get_empty_group == 0) {
2129
            // get only groups that are not empty
2130
            $sql = "SELECT DISTINCT g.id, g.iid, g.name
2131
                    FROM ".Database::get_course_table(TABLE_GROUP)." AS g
2132
                    INNER JOIN ".Database::get_course_table(TABLE_GROUP_USER)." gu
2133
                    ON (g.id = gu.group_id AND g.c_id = $course_id AND gu.c_id = $course_id)
2134
                    $session_condition
2135
                    ORDER BY g.name";
2136
        } else {
2137
            // get all groups even if they are empty
2138
            $sql = "SELECT g.id, g.name, g.iid 
2139
                    FROM ".Database::get_course_table(TABLE_GROUP)." AS g
2140
                    $session_condition
2141
                    AND c_id = $course_id";
2142
        }
2143
        $result = Database::query($sql);
2144
2145
        while ($group_data = Database::fetch_array($result)) {
2146
            $group_data['userNb'] = GroupManager::number_of_students($group_data['id'], $course_id);
2147
            $group_list[$group_data['id']] = $group_data;
2148
        }
2149
        return $group_list;
2150
    }
2151
2152
    /**
2153
     * Delete a course
2154
     * This function deletes a whole course-area from the platform. When the
2155
     * given course is a virtual course, the database and directory will not be
2156
     * deleted.
2157
     * When the given course is a real course, also all virtual courses refering
2158
     * to the given course will be deleted.
2159
     * Considering the fact that we remove all traces of the course in the main
2160
     * database, it makes sense to remove all tracking as well (if stats databases exist)
2161
     * so that a new course created with this code would not use the remains of an older
2162
     * course.
2163
     *
2164
     * @param string $code The code of the course to delete
2165
     * @todo When deleting a virtual course: unsubscribe users from that virtual
2166
     * course from the groups in the real course if they are not subscribed in
2167
     * that real course.
2168
     */
2169
    public static function delete_course($code)
2170
    {
2171
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
2172
        $table_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2173
        $table_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2174
        $table_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2175
        $table_course_survey = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY);
2176
        $table_course_survey_question = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION);
2177
        $table_course_survey_question_option = Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION);
2178
        $table_course_rel_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2179
2180
        $table_stats_hotpots = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTPOTATOES);
2181
        $table_stats_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
2182
        $table_stats_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
2183
        $table_stats_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS);
2184
        $table_stats_lastaccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
2185
        $table_stats_course_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
2186
        $table_stats_online = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ONLINE);
2187
        $table_stats_default = Database::get_main_table(TABLE_STATISTIC_TRACK_E_DEFAULT);
2188
        $table_stats_downloads = Database::get_main_table(TABLE_STATISTIC_TRACK_E_DOWNLOADS);
2189
        $table_stats_links = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LINKS);
2190
        $table_stats_uploads = Database::get_main_table(TABLE_STATISTIC_TRACK_E_UPLOADS);
2191
2192
        $codeFiltered = Database::escape_string($code);
2193
        $sql = "SELECT * FROM $table_course WHERE code='".$codeFiltered."'";
2194
        $res = Database::query($sql);
2195
2196
        if (Database::num_rows($res) == 0) {
2197
            return;
2198
        }
2199
2200
        $sql = "SELECT * FROM $table_course
2201
                WHERE code = '".$codeFiltered."'";
2202
        $res = Database::query($sql);
2203
        $course = Database::fetch_array($res);
2204
        $courseId = $course['id'];
2205
2206
        $count = 0;
2207
        if (api_is_multiple_url_enabled()) {
2208
            $url_id = 1;
2209
            if (api_get_current_access_url_id() != -1) {
2210
                $url_id = api_get_current_access_url_id();
2211
            }
2212
            UrlManager::delete_url_rel_course($courseId, $url_id);
2213
            $count = UrlManager::getCountUrlRelCourse($courseId);
2214
        }
2215
2216
        if ($count == 0) {
2217
            self::create_database_dump($code);
2218
2219
            $course_tables = AddCourse::get_course_tables();
2220
2221
            // Cleaning group categories
2222
            $groupCategories = GroupManager::get_categories($course['code']);
2223
2224
            if (!empty($groupCategories)) {
2225
                foreach ($groupCategories as $category) {
2226
                    GroupManager::delete_category($category['id'], $course['code']);
2227
                }
2228
            }
2229
2230
            // Cleaning groups
2231
            $groups = GroupManager::get_groups($courseId);
2232
            if (!empty($groups)) {
2233
                foreach ($groups as $group) {
2234
                    GroupManager::delete_groups($group, $course['code']);
2235
                }
2236
            }
2237
2238
            // Cleaning c_x tables
2239
            if (!empty($courseId)) {
2240
                foreach ($course_tables as $table) {
2241
                    $table = Database::get_course_table($table);
2242
                    $sql = "DELETE FROM $table WHERE c_id = $courseId ";
2243
                    Database::query($sql);
2244
                }
2245
            }
2246
2247
            $course_dir = api_get_path(SYS_COURSE_PATH).$course['directory'];
2248
            $archive_dir = api_get_path(SYS_ARCHIVE_PATH).$course['directory'].'_'.time();
2249
            if (is_dir($course_dir)) {
2250
                rename($course_dir, $archive_dir);
2251
            }
2252
2253
            // Unsubscribe all users from the course
2254
            $sql = "DELETE FROM $table_course_user WHERE c_id='".$courseId."'";
2255
            Database::query($sql);
2256
            // Delete the course from the sessions tables
2257
            $sql = "DELETE FROM $table_session_course WHERE c_id='".$courseId."'";
2258
            Database::query($sql);
2259
            $sql = "DELETE FROM $table_session_course_user WHERE c_id='".$courseId."'";
2260
            Database::query($sql);
2261
2262
            // Delete from Course - URL
2263
            $sql = "DELETE FROM $table_course_rel_url WHERE c_id = '".$courseId."'";
2264
            Database::query($sql);
2265
2266
            $sql = 'SELECT survey_id FROM '.$table_course_survey.' WHERE course_code="'.$codeFiltered.'"';
2267
            $result_surveys = Database::query($sql);
2268
            while ($surveys = Database::fetch_array($result_surveys)) {
2269
                $survey_id = $surveys[0];
2270
                $sql = 'DELETE FROM '.$table_course_survey_question.' WHERE survey_id="'.$survey_id.'"';
2271
                Database::query($sql);
2272
                $sql = 'DELETE FROM '.$table_course_survey_question_option.' WHERE survey_id="'.$survey_id.'"';
2273
                Database::query($sql);
2274
                $sql = 'DELETE FROM '.$table_course_survey.' WHERE survey_id="'.$survey_id.'"';
2275
                Database::query($sql);
2276
            }
2277
2278
            // Delete the course from the stats tables
2279
            $sql = "DELETE FROM $table_stats_hotpots WHERE c_id = $courseId";
2280
            Database::query($sql);
2281
            $sql = "DELETE FROM $table_stats_attempt WHERE c_id = $courseId";
2282
            Database::query($sql);
2283
            $sql = "DELETE FROM $table_stats_exercises WHERE c_id = $courseId";
2284
            Database::query($sql);
2285
            $sql = "DELETE FROM $table_stats_access WHERE c_id = $courseId";
2286
            Database::query($sql);
2287
            $sql = "DELETE FROM $table_stats_lastaccess WHERE c_id = $courseId";
2288
            Database::query($sql);
2289
            $sql = "DELETE FROM $table_stats_course_access WHERE c_id = $courseId";
2290
            Database::query($sql);
2291
            $sql = "DELETE FROM $table_stats_online WHERE c_id = $courseId";
2292
            Database::query($sql);
2293
            // Do not delete rows from track_e_default as these include course
2294
            // creation and other important things that do not take much space
2295
            // but give information on the course history
2296
            //$sql = "DELETE FROM $table_stats_default WHERE c_id = $courseId";
2297
            //Database::query($sql);
2298
            $sql = "DELETE FROM $table_stats_downloads WHERE c_id = $courseId";
2299
            Database::query($sql);
2300
            $sql = "DELETE FROM $table_stats_links WHERE c_id = $courseId";
2301
            Database::query($sql);
2302
            $sql = "DELETE FROM $table_stats_uploads WHERE c_id = $courseId";
2303
            Database::query($sql);
2304
2305
            // Update ticket
2306
            $table = Database::get_main_table(TABLE_TICKET_TICKET);
2307
            $sql = "UPDATE $table SET course_id = NULL WHERE course_id = $courseId";
2308
            Database::query($sql);
2309
2310
            // Class
2311
            $table = Database::get_main_table(TABLE_USERGROUP_REL_COURSE);
2312
            $sql = "DELETE FROM $table
2313
                    WHERE course_id = $courseId";
2314
            Database::query($sql);
2315
2316
            // Skills
2317
            $table = Database::get_main_table(TABLE_MAIN_SKILL_REL_USER);
2318
            $argumentation = Database::escape_string(sprintf(get_lang('SkillFromCourseXDeletedSinceThen'), $course['code']));
2319
            $sql = "UPDATE $table SET course_id = NULL, session_id = NULL, argumentation = '$argumentation' WHERE course_id = $courseId";
2320
            Database::query($sql);
2321
2322
            // Delete the course from the database
2323
            $sql = "DELETE FROM $table_course WHERE code = '".$codeFiltered."'";
2324
            Database::query($sql);
2325
2326
            // delete extra course fields
2327
            $extraFieldValues = new ExtraFieldValue('course');
2328
            $extraFieldValues->deleteValuesByItem($courseId);
2329
2330
            // Add event to system log
2331
            Event::addEvent(
2332
                LOG_COURSE_DELETE,
2333
                LOG_COURSE_CODE,
2334
                $code,
2335
                api_get_utc_datetime(),
2336
                api_get_user_id(),
2337
                $courseId
2338
            );
2339
        }
2340
    }
2341
2342
    /**
2343
     * Creates a file called mysql_dump.sql in the course folder
2344
     * @param string $course_code The code of the course
2345
     * @todo Implementation for single database
2346
     */
2347
    public static function create_database_dump($course_code)
2348
    {
2349
        $sql_dump = '';
2350
        $course_code = Database::escape_string($course_code);
2351
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
2352
        $sql = "SELECT * FROM $table_course WHERE code = '$course_code'";
2353
        $res = Database::query($sql);
2354
        $course = Database::fetch_array($res);
2355
2356
        $course_tables = AddCourse::get_course_tables();
2357
2358
        if (!empty($course['id'])) {
2359
            //Cleaning c_x tables
2360
            foreach ($course_tables as $table) {
2361
                $table = Database::get_course_table($table);
2362
                $sql = "SELECT * FROM $table WHERE c_id = {$course['id']} ";
2363
                $res_table = Database::query($sql);
2364
2365
                while ($row = Database::fetch_array($res_table, 'ASSOC')) {
2366
                    $row_to_save = array();
2367
                    foreach ($row as $key => $value) {
2368
                        $row_to_save[$key] = $key."='".Database::escape_string($row[$key])."'";
2369
                    }
2370
                    $sql_dump .= "\nINSERT INTO $table SET ".implode(', ', $row_to_save).';';
2371
                }
2372
            }
2373
        }
2374
2375
        if (is_dir(api_get_path(SYS_COURSE_PATH).$course['directory'])) {
2376
            $file_name = api_get_path(SYS_COURSE_PATH).$course['directory'].'/mysql_dump.sql';
2377
            $handle = fopen($file_name, 'a+');
2378
            if ($handle !== false) {
2379
                fwrite($handle, $sql_dump);
2380
                fclose($handle);
2381
            } 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...
2382
                //TODO trigger exception in a try-catch
2383
            }
2384
        }
2385
    }
2386
2387
    /**
2388
     * Sort courses for a specific user ??
2389
     * @param   int    $user_id User ID
2390
     * @param   string  $course_code Course code
2391
     * @return  int     Minimum course order
2392
     * @todo Review documentation
2393
     */
2394
    public static function userCourseSort($user_id, $course_code)
2395
    {
2396
        if ($user_id != strval(intval($user_id))) {
2397
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type integer.
Loading history...
2398
        }
2399
2400
        $course_code = Database::escape_string($course_code);
2401
        $TABLECOURSE = Database::get_main_table(TABLE_MAIN_COURSE);
2402
        $TABLECOURSUSER = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2403
2404
        $course_title = Database::result(
2405
            Database::query(
2406
                'SELECT title FROM '.$TABLECOURSE.' WHERE code="'.$course_code.'"'
2407
            ),
2408
            0,
2409
            0
2410
        );
2411
2412
        $sql = 'SELECT course.code as code, course.title as title, cu.sort as sort
2413
                FROM '.$TABLECOURSUSER.' as cu, '.$TABLECOURSE.' as course
2414
                WHERE   course.id = cu.c_id AND user_id = "' . $user_id.'" AND
2415
                        cu.relation_type<>' . COURSE_RELATION_TYPE_RRHH.' AND
2416
                        user_course_cat = 0
2417
                ORDER BY cu.sort';
2418
        $result = Database::query($sql);
2419
2420
        $course_title_precedent = '';
2421
        $counter = 0;
2422
        $course_found = false;
2423
        $course_sort = 1;
2424
2425
        if (Database::num_rows($result) > 0) {
2426
            while ($courses = Database::fetch_array($result)) {
2427
                if ($course_title_precedent == '') {
2428
                    $course_title_precedent = $courses['title'];
2429
                }
2430
                if (api_strcasecmp($course_title_precedent, $course_title) < 0) {
2431
                    $course_found = true;
2432
                    $course_sort = $courses['sort'];
2433
                    if ($counter == 0) {
2434
                        $sql = 'UPDATE '.$TABLECOURSUSER.'
2435
                                SET sort = sort+1
2436
                                WHERE
2437
                                    user_id= "' . $user_id.'" AND
2438
                                    relation_type<>' . COURSE_RELATION_TYPE_RRHH.'
2439
                                    AND user_course_cat="0"
2440
                                    AND sort > "' . $course_sort.'"';
2441
                        $course_sort++;
2442
                    } else {
2443
                        $sql = 'UPDATE '.$TABLECOURSUSER.' SET sort = sort+1
2444
                                WHERE
2445
                                    user_id= "' . $user_id.'" AND
2446
                                    relation_type<>' . COURSE_RELATION_TYPE_RRHH.' AND
2447
                                    user_course_cat="0" AND
2448
                                    sort >= "' . $course_sort.'"';
2449
                    }
2450
                    Database::query($sql);
2451
                    break;
2452
2453
                } else {
2454
                    $course_title_precedent = $courses['title'];
2455
                }
2456
                $counter++;
2457
            }
2458
2459
            // We must register the course in the beginning of the list
2460
            if (!$course_found) {
2461
                $course_sort = Database::result(
2462
                    Database::query(
2463
                        'SELECT min(sort) as min_sort FROM '.$TABLECOURSUSER.' WHERE user_id="'.$user_id.'" AND user_course_cat="0"'
2464
                    ),
2465
                    0,
2466
                    0
2467
                );
2468
                Database::query('UPDATE '.$TABLECOURSUSER.' SET sort = sort+1 WHERE user_id= "'.$user_id.'" AND user_course_cat="0"');
2469
            }
2470
        }
2471
        return $course_sort;
2472
    }
2473
2474
    /**
2475
     * check if course exists
2476
     * @param string $course_code
2477
     * @return integer if exists, false else
2478
     */
2479
    public static function course_exists($course_code)
2480
    {
2481
        $sql = 'SELECT 1 FROM '.Database::get_main_table(TABLE_MAIN_COURSE).'
2482
                WHERE code="'.Database::escape_string($course_code).'"';
2483
2484
        return Database::num_rows(Database::query($sql));
2485
    }
2486
2487
    /**
2488
     * Send an email to tutor after the auth-suscription of a student in your course
2489
     * @author Carlos Vargas <[email protected]>, Dokeos Latino
2490
     * @param  int $user_id the id of the user
2491
     * @param  string $courseId the course code
2492
     * @param  bool $send_to_tutor_also
2493
     * @return false|null we return the message that is displayed when the action is successful
2494
     */
2495
    public static function email_to_tutor($user_id, $courseId, $send_to_tutor_also = false)
2496
    {
2497
        if ($user_id != strval(intval($user_id))) {
2498
            return false;
2499
        }
2500
        $courseId = intval($courseId);
2501
        $information = api_get_course_info_by_id($courseId);
2502
        $course_code = $information['code'];
2503
        $student = api_get_user_info($user_id);
2504
2505
        $name_course = $information['title'];
2506
        $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)." 
2507
                WHERE c_id ='" . $courseId."'";
2508
2509
        // TODO: Ivan: This is a mistake, please, have a look at it. Intention here is diffcult to be guessed.
2510
        //if ($send_to_tutor_also = true)
2511
        // Proposed change:
2512
        if ($send_to_tutor_also) {
2513
            $sql .= " AND is_tutor=1";
2514
        } else {
2515
            $sql .= " AND status=1";
2516
        }
2517
2518
        $result = Database::query($sql);
2519
        while ($row = Database::fetch_array($result)) {
2520
            $tutor = api_get_user_info($row['user_id']);
2521
            $emailto = $tutor['email'];
2522
            $emailsubject = get_lang('NewUserInTheCourse').': '.$name_course;
2523
            $emailbody = get_lang('Dear').': '.api_get_person_name($tutor['firstname'], $tutor['lastname'])."\n";
2524
            $emailbody .= get_lang('MessageNewUserInTheCourse').': '.$name_course."\n";
2525
            $emailbody .= get_lang('UserName').': '.$student['username']."\n";
2526
            if (api_is_western_name_order()) {
2527
                $emailbody .= get_lang('FirstName').': '.$student['firstname']."\n";
2528
                $emailbody .= get_lang('LastName').': '.$student['lastname']."\n";
2529
            } else {
2530
                $emailbody .= get_lang('LastName').': '.$student['lastname']."\n";
2531
                $emailbody .= get_lang('FirstName').': '.$student['firstname']."\n";
2532
            }
2533
            $emailbody .= get_lang('Email').': <a href="mailto:'.$student['email'].'">'.$student['email']."</a>\n\n";
2534
            $recipient_name = api_get_person_name(
2535
                $tutor['firstname'],
2536
                $tutor['lastname'],
2537
                null,
2538
                PERSON_NAME_EMAIL_ADDRESS
2539
            );
2540
            $sender_name = api_get_person_name(api_get_setting('administratorName'),
2541
                api_get_setting('administratorSurname'), null, PERSON_NAME_EMAIL_ADDRESS);
2542
            $email_admin = api_get_setting('emailAdministrator');
2543
2544
            $additionalParameters = array(
2545
                'smsType' => SmsPlugin::NEW_USER_SUBSCRIBED_COURSE,
2546
                'userId' => $tutor['user_id'],
2547
                'userUsername' => $student['username'],
2548
                'courseCode' => $course_code
2549
            );
2550
            api_mail_html(
2551
                $recipient_name,
2552
                $emailto,
2553
                $emailsubject,
2554
                $emailbody,
2555
                $sender_name,
2556
                $email_admin,
2557
                null,
2558
                null,
2559
                null,
2560
                $additionalParameters
2561
            );
2562
        }
2563
    }
2564
2565
    /**
2566
     * @return array
2567
     */
2568
    public static function get_special_course_list()
2569
    {
2570
        $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
2571
        $tbl_course_field = Database::get_main_table(TABLE_EXTRA_FIELD);
2572
        $tbl_course_field_value = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
2573
2574
        //we filter the courses from the URL
2575
        $join_access_url = $where_access_url = '';
2576
        if (api_get_multiple_access_url()) {
2577
            $access_url_id = api_get_current_access_url_id();
2578
            if ($access_url_id != -1) {
2579
                $tbl_url_course = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2580
                $join_access_url = "LEFT JOIN $tbl_url_course url_rel_course
2581
                                    ON url_rel_course.c_id = tcfv.item_id ";
2582
                $where_access_url = " AND access_url_id = $access_url_id ";
2583
            }
2584
        }
2585
2586
        $extraFieldType = EntityExtraField::COURSE_FIELD_TYPE;
2587
2588
        // get course list auto-register
2589
        $sql = "SELECT DISTINCT(c.id)
2590
                FROM $tbl_course_field_value tcfv
2591
                INNER JOIN $tbl_course_field tcf
2592
                ON tcfv.field_id =  tcf.id $join_access_url
2593
                INNER JOIN $courseTable c
2594
                ON (c.id = tcfv.item_id)
2595
                WHERE
2596
                    tcf.extra_field_type = $extraFieldType AND
2597
                    tcf.variable = 'special_course' AND
2598
                    tcfv.value = 1  $where_access_url";
2599
2600
        $result = Database::query($sql);
2601
        $courseList = array();
2602
2603
        if (Database::num_rows($result) > 0) {
2604
            while ($row = Database::fetch_array($result)) {
2605
                $courseList[] = $row['id'];
2606
            }
2607
        }
2608
2609
        return $courseList;
2610
    }
2611
2612
    /**
2613
     * Get the course codes that have been restricted in the catalogue, and if byUserId is set
2614
     * then the courses that the user is allowed or not to see in catalogue
2615
     *
2616
     * @param bool $allowed Either if the courses have some users that are or are not allowed to see in catalogue
2617
     * @param int $byUserId if the courses are or are not allowed to see to the user
2618
     * @return array Course codes allowed or not to see in catalogue by some user or the user
2619
     */
2620
    public static function getCatalogueCourseList($allowed = true, $byUserId = -1)
2621
    {
2622
        $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
2623
        $tblCourseRelUserCatalogue = Database::get_main_table(TABLE_MAIN_COURSE_CATALOGUE_USER);
2624
        $visibility = $allowed ? 1 : 0;
2625
2626
        // Restriction by user id
2627
        $currentUserRestriction = '';
2628
        if ($byUserId > 0) {
2629
            $byUserId = (int) $byUserId;
2630
            $currentUserRestriction = " AND tcruc.user_id = $byUserId ";
2631
        }
2632
2633
        //we filter the courses from the URL
2634
        $joinAccessUrl = '';
2635
        $whereAccessUrl = '';
2636
        if (api_get_multiple_access_url()) {
2637
            $accessUrlId = api_get_current_access_url_id();
2638
            if ($accessUrlId != -1) {
2639
                $tblUrlCourse = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2640
                $joinAccessUrl = "LEFT JOIN $tblUrlCourse url_rel_course
2641
                                  ON url_rel_course.c_id = c.id ";
2642
                $whereAccessUrl = " AND access_url_id = $accessUrlId ";
2643
            }
2644
        }
2645
2646
        // get course list auto-register
2647
        $sql = "SELECT DISTINCT(c.code)
2648
                FROM $tblCourseRelUserCatalogue tcruc
2649
                INNER JOIN $courseTable c
2650
                ON (c.id = tcruc.c_id) $joinAccessUrl
2651
                WHERE tcruc.visible = $visibility $currentUserRestriction $whereAccessUrl";
2652
2653
        $result = Database::query($sql);
2654
        $courseList = array();
2655
2656
        if (Database::num_rows($result) > 0) {
2657
            while ($resultRow = Database::fetch_array($result)) {
2658
                $courseList[] = $resultRow['code'];
2659
            }
2660
        }
2661
2662
        return $courseList;
2663
    }
2664
2665
    /**
2666
     * Get list of courses for a given user
2667
     *
2668
     * @param int $user_id
2669
     * @param boolean $include_sessions Whether to include courses from session or not
2670
     * @param boolean $adminGetsAllCourses If the user is platform admin,
2671
     * whether he gets all the courses or just his. Note: This does *not* include all sessions
2672
     * @param bool $loadSpecialCourses
2673
     * @param array $skipCourseList List of course ids to skip
2674
     * @param bool $useUserLanguageFilterIfAvailable
2675
     * @param bool $showCoursesSessionWithDifferentKey
2676
     * @return array List of codes and db name
2677
     * @author isaac flores paz
2678
     */
2679
    public static function get_courses_list_by_user_id(
2680
        $user_id,
2681
        $include_sessions = false,
2682
        $adminGetsAllCourses = false,
2683
        $loadSpecialCourses = true,
2684
        $skipCourseList = [],
2685
        $useUserLanguageFilterIfAvailable = true,
2686
        $showCoursesSessionWithDifferentKey = false
2687
    ) {
2688
        $user_id = intval($user_id);
2689
        $urlId = api_get_current_access_url_id();
2690
        $course_list = array();
2691
        $codes = array();
2692
2693
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
2694
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2695
        $tbl_user_course_category = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
2696
        $tableCourseUrl = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
2697
2698
        $languageCondition = '';
2699
        $onlyInUserLanguage = api_get_configuration_value('my_courses_show_courses_in_user_language_only');
2700
        if ($useUserLanguageFilterIfAvailable && $onlyInUserLanguage) {
2701
            $userInfo = api_get_user_info(api_get_user_id());
2702
            if (!empty($userInfo['language'])) {
2703
                $languageCondition = " AND course.course_language = '".$userInfo['language']."' ";
2704
            }
2705
        }
2706
2707
        if ($adminGetsAllCourses && UserManager::is_admin($user_id)) {
2708
            // get the whole courses list
2709
            $sql = "SELECT DISTINCT(course.code), course.id as real_id, course.title
2710
                    FROM $tbl_course course 
2711
                    INNER JOIN $tableCourseUrl url 
2712
                    ON (course.id = url.c_id)
2713
                    WHERE 
2714
                        url.access_url_id = $urlId     
2715
                        $languageCondition 
2716
                ";
2717
        } else {
2718
            $withSpecialCourses = $withoutSpecialCourses = '';
2719
2720
            if ($loadSpecialCourses) {
2721
                $specialCourseList = self::get_special_course_list();
2722
2723
                if (!empty($specialCourseList)) {
2724
                    $specialCourseToString = '"'.implode('","', $specialCourseList).'"';
2725
                    $withSpecialCourses = ' AND course.id IN ('.$specialCourseToString.')';
2726
                    $withoutSpecialCourses = ' AND course.id NOT IN ('.$specialCourseToString.')';
2727
                }
2728
2729
                if (!empty($withSpecialCourses)) {
2730
                    $sql = "SELECT DISTINCT (course.code), 
2731
                            course.id as real_id,
2732
                            course.category_code AS category,
2733
                            course.title
2734
                            FROM $tbl_course_user course_rel_user
2735
                            LEFT JOIN $tbl_course course
2736
                            ON course.id = course_rel_user.c_id
2737
                            LEFT JOIN $tbl_user_course_category user_course_category
2738
                            ON course_rel_user.user_course_cat = user_course_category.id
2739
                            INNER JOIN $tableCourseUrl url 
2740
                            ON (course.id = url.c_id)  
2741
                            WHERE url.access_url_id = $urlId 
2742
                            $withSpecialCourses
2743
                            $languageCondition                        
2744
                            GROUP BY course.code
2745
                            ORDER BY user_course_category.sort, course.title, course_rel_user.sort ASC
2746
                    ";
2747
                    $result = Database::query($sql);
2748
                    if (Database::num_rows($result) > 0) {
2749
                        while ($result_row = Database::fetch_array($result, 'ASSOC')) {
2750
                            $result_row['special_course'] = 1;
2751
                            $course_list[] = $result_row;
2752
                            $codes[] = $result_row['real_id'];
2753
                        }
2754
                    }
2755
                }
2756
            }
2757
2758
            // get course list not auto-register. Use Distinct to avoid multiple
2759
            // entries when a course is assigned to a HRD (DRH) as watcher
2760
            $sql = "SELECT 
2761
                        DISTINCT(course.code), 
2762
                        course.id as real_id, 
2763
                        course.category_code AS category,
2764
                        course.title
2765
                    FROM $tbl_course course
2766
                    INNER JOIN $tbl_course_user cru 
2767
                    ON (course.id = cru.c_id)
2768
                    INNER JOIN $tableCourseUrl url 
2769
                    ON (course.id = url.c_id) 
2770
                    WHERE 
2771
                        url.access_url_id = $urlId AND 
2772
                        cru.user_id = '$user_id' 
2773
                        $withoutSpecialCourses
2774
                        $languageCondition
2775
                    ORDER BY course.title
2776
                    ";
2777
        }
2778
        $result = Database::query($sql);
2779
2780
        if (Database::num_rows($result)) {
2781
            while ($row = Database::fetch_array($result, 'ASSOC')) {
2782
                if (!empty($skipCourseList)) {
2783
                    if (in_array($row['real_id'], $skipCourseList)) {
2784
                        continue;
2785
                    }
2786
                }
2787
                $course_list[] = $row;
2788
                $codes[] = $row['real_id'];
2789
            }
2790
        }
2791
2792
        if ($include_sessions === true) {
2793
            $sql = "SELECT DISTINCT (c.code), 
2794
                        c.id as real_id, 
2795
                        c.category_code AS category,
2796
                        s.id as session_id,
2797
                        s.name as session_name
2798
                    FROM ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)." scu                     
2799
                    INNER JOIN $tbl_course c
2800
                    ON (scu.c_id = c.id)
2801
                    INNER JOIN ".Database::get_main_table(TABLE_MAIN_SESSION)." s
2802
                    ON (s.id = scu.session_id)
2803
                    WHERE user_id = $user_id ";
2804
            $r = Database::query($sql);
2805
            while ($row = Database::fetch_array($r, 'ASSOC')) {
2806
                if (!empty($skipCourseList)) {
2807
                    if (in_array($row['real_id'], $skipCourseList)) {
2808
                        continue;
2809
                    }
2810
                }
2811
2812
                if ($showCoursesSessionWithDifferentKey) {
2813
                    $course_list[] = $row;
2814
                } else {
2815
                    if (!in_array($row['real_id'], $codes)) {
2816
                        $course_list[] = $row;
2817
                    }
2818
                }
2819
            }
2820
        }
2821
2822
        return $course_list;
2823
    }
2824
2825
    /**
2826
     * Get course ID from a given course directory name
2827
     * @param   string  $path Course directory (without any slash)
2828
     *
2829
     * @return  string  Course code, or false if not found
2830
     */
2831
    public static function getCourseCodeFromDirectory($path)
2832
    {
2833
        $path = Database::escape_string(str_replace('.', '', str_replace('/', '', $path)));
2834
        $res = Database::query("SELECT code FROM ".Database::get_main_table(TABLE_MAIN_COURSE)."
2835
                WHERE directory LIKE BINARY '$path'");
2836
        if ($res === false) {
2837
            return false;
2838
        }
2839
        if (Database::num_rows($res) != 1) {
2840
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type string.
Loading history...
2841
        }
2842
        $row = Database::fetch_array($res);
2843
2844
        return $row['code'];
2845
    }
2846
2847
    /**
2848
     * Get course code(s) from visual code
2849
     * @deprecated
2850
     * @param   string  Visual code
2851
     * @return  array   List of codes for the given visual code
2852
     */
2853
    public static function get_courses_info_from_visual_code($code)
2854
    {
2855
        $result = array();
2856
        $sql_result = Database::query("SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE)."
2857
                WHERE visual_code = '" . Database::escape_string($code)."'");
2858
        while ($virtual_course = Database::fetch_array($sql_result)) {
2859
            $result[] = $virtual_course;
2860
        }
2861
        return $result;
2862
    }
2863
2864
    /**
2865
     * Get emails of tutors to course
2866
     * @param int $courseId
2867
     * @return array List of emails of tutors to course
2868
     *
2869
     * @author Carlos Vargas <[email protected]>, Dokeos Latino
2870
     * */
2871
    public static function get_emails_of_tutors_to_course($courseId)
2872
    {
2873
        $list = [];
2874
        $res = Database::query("SELECT user_id FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
2875
                WHERE c_id ='" . intval($courseId)."' AND status=1");
2876
        while ($list_users = Database::fetch_array($res)) {
2877
            $result = Database::query("SELECT * FROM ".Database::get_main_table(TABLE_MAIN_USER)."
2878
                    WHERE user_id=" . $list_users['user_id']);
2879
            while ($row_user = Database::fetch_array($result)) {
2880
                $name_teacher = api_get_person_name($row_user['firstname'], $row_user['lastname']);
2881
                $list[] = array($row_user['email'] => $name_teacher);
2882
            }
2883
        }
2884
        return $list;
2885
    }
2886
2887
    /**
2888
     * Get coaches emails by session
2889
     * @param int $session_id
2890
     * @param int $courseId
2891
     * @return array  array(email => name_tutor)  by coach
2892
     * @author Carlos Vargas <[email protected]>
2893
     */
2894
    public static function get_email_of_tutor_to_session($session_id, $courseId)
2895
    {
2896
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2897
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
2898
        $coachs_emails = array();
2899
2900
        $courseId = intval($courseId);
2901
        $session_id = intval($session_id);
2902
2903
        $sql = "SELECT user_id
2904
                FROM $tbl_session_course_user
2905
                WHERE
2906
                    session_id = '$session_id' AND
2907
                    c_id = '$courseId' AND
2908
                    status = 2
2909
                ";
2910
        $rs = Database::query($sql);
2911
2912
        if (Database::num_rows($rs) > 0) {
2913
2914
            $user_ids = array();
2915
            while ($row = Database::fetch_array($rs)) {
2916
                $user_ids[] = $row['user_id'];
2917
            }
2918
2919
            $sql = "SELECT firstname, lastname, email FROM $tbl_user
2920
                    WHERE user_id IN (".implode(",", $user_ids).")";
2921
            $rs_user = Database::query($sql);
2922
2923
            while ($row_emails = Database::fetch_array($rs_user)) {
2924
                $mail_tutor = array(
2925
                    'email' => $row_emails['email'],
2926
                    'complete_name' => api_get_person_name($row_emails['firstname'], $row_emails['lastname'])
2927
                );
2928
                $coachs_emails[] = $mail_tutor;
2929
            }
2930
        }
2931
        return $coachs_emails;
2932
    }
2933
2934
    /**
2935
     * Creates a new extra field for a given course
2936
     * @param    string    Field's internal variable name
2937
     * @param    int        Field's type
2938
     * @param    string    Field's language var name
2939
     * @param string $default
2940
     * @return boolean     new extra field id
2941
     */
0 ignored issues
show
Documentation Bug introduced by
The doc comment Field's at position 0 could not be parsed: Unknown type name 'Field's' at position 0 in Field's.
Loading history...
2942
    public static function create_course_extra_field($variable, $fieldType, $displayText, $default = '')
2943
    {
2944
        $extraField = new ExtraField('course');
2945
        $params = [
2946
            'variable' => $variable,
2947
            'field_type' => $fieldType,
2948
            'display_text' => $displayText,
2949
            'default_value' => $default
2950
        ];
2951
2952
        return $extraField->save($params);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $extraField->save($params) returns the type integer which is incompatible with the documented return type boolean.
Loading history...
2953
    }
2954
2955
    /**
2956
     * Updates course attribute. Note that you need to check that your
2957
     * attribute is valid before you use this function
2958
     *
2959
     * @param int $id Course id
2960
     * @param string $name Attribute name
2961
     * @param string $value Attribute value
2962
     *
2963
     * @return Doctrine\DBAL\Driver\Statement|null True if attribute was successfully updated,
2964
     * false if course was not found or attribute name is invalid
2965
     */
2966
    public static function update_attribute($id, $name, $value)
2967
    {
2968
        $id = (int) $id;
2969
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
2970
        $sql = "UPDATE $table SET $name = '".Database::escape_string($value)."'
2971
                WHERE id = '$id'";
2972
2973
        return Database::query($sql);
2974
    }
2975
2976
    /**
2977
     * Update course attributes. Will only update attributes with a non-empty value.
2978
     * Note that you NEED to check that your attributes are valid before using this function
2979
     *
2980
     * @param int Course id
2981
     * @param array Associative array with field names as keys and field values as values
2982
     * @return Doctrine\DBAL\Driver\Statement|null True if update was successful, false otherwise
2983
     */
2984
    public static function update_attributes($id, $attributes)
2985
    {
2986
        $id = (int) $id;
2987
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
2988
        $sql = "UPDATE $table SET ";
2989
        $i = 0;
2990
        foreach ($attributes as $name => $value) {
2991
            if ($value != '') {
2992
                if ($i > 0) {
2993
                    $sql .= ", ";
2994
                }
2995
                $sql .= " $name = '".Database::escape_string($value)."'";
2996
                $i++;
2997
            }
2998
        }
2999
        $sql .= " WHERE id = '$id'";
3000
3001
        return Database::query($sql);
3002
    }
3003
3004
    /**
3005
     * Update an extra field value for a given course
3006
     * @param    integer    Course ID
3007
     * @param    string    Field variable name
3008
     * @param    string    Field value
3009
     * @return    boolean|null    true if field updated, false otherwise
3010
     */
3011
    public static function update_course_extra_field_value($course_code, $variable, $value = '')
3012
    {
3013
        $courseInfo = api_get_course_info($course_code);
3014
        $courseId = $courseInfo['real_id'];
3015
3016
        $extraFieldValues = new ExtraFieldValue('course');
3017
        $params = [
3018
            'item_id' => $courseId,
3019
            'variable' => $variable,
3020
            'value' => $value
3021
        ];
3022
3023
        return $extraFieldValues->save($params);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $extraFieldValues->save($params) also could return the type integer which is incompatible with the documented return type null|boolean.
Loading history...
3024
    }
3025
3026
    /**
3027
     * @param int $session_id
3028
     * @return mixed
3029
     */
3030
    public static function get_session_category_id_by_session_id($session_id)
3031
    {
3032
        if (empty($session_id)) {
3033
            return [];
3034
        }
3035
3036
        $sql = 'SELECT sc.id session_category
3037
                FROM ' . Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY).' sc
3038
                INNER JOIN ' . Database::get_main_table(TABLE_MAIN_SESSION).' s
3039
                ON sc.id = s.session_category_id 
3040
                WHERE s.id="' . intval($session_id).'"';
3041
3042
        return Database::result(
3043
            Database::query($sql),
3044
            0,
3045
            'session_category'
3046
        );
3047
    }
3048
3049
    /**
3050
     * Gets the value of a course extra field. Returns null if it was not found
3051
     *
3052
     * @param string $variable Name of the extra field
3053
     * @param string $code Course code
3054
     *
3055
     * @return string Value
3056
     */
3057
    public static function get_course_extra_field_value($variable, $code)
3058
    {
3059
        $courseInfo = api_get_course_info($code);
3060
        $courseId = $courseInfo['real_id'];
3061
3062
        $extraFieldValues = new ExtraFieldValue('course');
3063
        $result = $extraFieldValues->get_values_by_handler_and_field_variable($courseId, $variable);
3064
        if (!empty($result['value'])) {
3065
            return $result['value'];
3066
        }
3067
3068
        return null;
3069
    }
3070
3071
    /**
3072
     * Lists details of the course description
3073
     * @param array        The course description
3074
     * @param string    The encoding
3075
     * @param bool        If true is displayed if false is hidden
3076
     * @return string     The course description in html
3077
     */
3078
    public static function get_details_course_description_html(
3079
        $descriptions,
3080
        $charset,
3081
        $action_show = true
3082
    ) {
3083
        $data = null;
3084
        if (isset($descriptions) && count($descriptions) > 0) {
3085
            foreach ($descriptions as $description) {
3086
                $data .= '<div class="sectiontitle">';
3087
                if (api_is_allowed_to_edit() && $action_show) {
3088
                    //delete
3089
                    $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'),
3090
                                ENT_QUOTES, $charset)).'\')) return false;">';
3091
                    $data .= Display::return_icon('delete.gif', get_lang('Delete'),
3092
                        array('style' => 'vertical-align:middle;float:right;'));
3093
                    $data .= '</a> ';
3094
                    //edit
3095
                    $data .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&description_id='.$description->id.'">';
3096
                    $data .= Display::return_icon('edit.png', get_lang('Edit'),
3097
                        array('style' => 'vertical-align:middle;float:right; padding-right:4px;'), ICON_SIZE_SMALL);
3098
                    $data .= '</a> ';
3099
                }
3100
                $data .= $description->title;
3101
                $data .= '</div>';
3102
                $data .= '<div class="sectioncomment">';
3103
                $data .= Security::remove_XSS($description->content);
3104
                $data .= '</div>';
3105
            }
3106
        } else {
3107
            $data .= '<em>'.get_lang('ThisCourseDescriptionIsEmpty').'</em>';
3108
        }
3109
3110
        return $data;
3111
    }
3112
3113
    /**
3114
     * Returns the details of a course category
3115
     *
3116
     * @param string $code Category code
3117
     * @return array Course category
3118
     */
3119
    public static function get_course_category($code)
3120
    {
3121
        $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
3122
        $code = Database::escape_string($code);
3123
        $sql = "SELECT * FROM $table WHERE code = '$code'";
3124
        return Database::fetch_array(Database::query($sql));
3125
    }
3126
3127
    /**
3128
     * Returns the details of a course category
3129
     *
3130
     * @param string Category code
3131
     * @return array Course category list
3132
     */
3133
    public static function getCategoriesList()
3134
    {
3135
        $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
3136
        $sql = "SELECT * FROM $table";
3137
        $result = Database::query($sql);
3138
        $categoryList = [];
3139
        while ($row = Database::fetch_array($result, 'ASSOC')) {
3140
            $categoryList[$row['code']] = $row['name'];
3141
        }
3142
        return $categoryList;
3143
    }
3144
3145
    /**
3146
     * Subscribes courses to human resource manager (Dashboard feature)
3147
     * @param    int   $hr_manager_id      Human Resource Manager id
3148
     * @param    array $courses_list       Courses code
3149
     * @return int
3150
     **/
3151
    public static function subscribeCoursesToDrhManager($hr_manager_id, $courses_list)
3152
    {
3153
        $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
3154
        $tbl_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
3155
3156
        $hr_manager_id = intval($hr_manager_id);
3157
        $affected_rows = 0;
3158
3159
        //Deleting assigned courses to hrm_id
3160
        if (api_is_multiple_url_enabled()) {
3161
            $sql = "SELECT s.c_id FROM $tbl_course_rel_user s
3162
                    INNER JOIN $tbl_course_rel_access_url a
3163
                    ON (a.c_id = s.c_id)
3164
                    WHERE
3165
                        user_id = $hr_manager_id AND
3166
                        relation_type=".COURSE_RELATION_TYPE_RRHH." AND
3167
                        access_url_id = " . api_get_current_access_url_id()."";
3168
        } else {
3169
            $sql = "SELECT c_id FROM $tbl_course_rel_user
3170
                    WHERE user_id = $hr_manager_id AND relation_type=".COURSE_RELATION_TYPE_RRHH." ";
3171
        }
3172
        $result = Database::query($sql);
3173
        if (Database::num_rows($result) > 0) {
3174
            while ($row = Database::fetch_array($result)) {
3175
                $sql = "DELETE FROM $tbl_course_rel_user
3176
                        WHERE
3177
                            c_id = '{$row['c_id']}' AND
3178
                            user_id = $hr_manager_id AND
3179
                            relation_type=".COURSE_RELATION_TYPE_RRHH." ";
3180
                Database::query($sql);
3181
            }
3182
        }
3183
3184
        // inserting new courses list
3185
        if (is_array($courses_list)) {
3186
            foreach ($courses_list as $course_code) {
3187
                $courseInfo = api_get_course_info($course_code);
3188
                $courseId = $courseInfo['real_id'];
3189
                $sql = "INSERT IGNORE INTO $tbl_course_rel_user(c_id, user_id, status, relation_type)
3190
                        VALUES($courseId, $hr_manager_id, '".DRH."', '".COURSE_RELATION_TYPE_RRHH."')";
3191
                $result = Database::query($sql);
3192
                if (Database::affected_rows($result)) {
3193
                    $affected_rows++;
3194
                }
3195
            }
3196
        }
3197
3198
        return $affected_rows;
3199
    }
3200
3201
    /**
3202
     * get courses followed by human resources manager
3203
     * @param int $user_id
3204
     * @param int $status
3205
     * @param int $from
3206
     * @param int $limit
3207
     * @param string $column
3208
     * @param string $direction
3209
     * @param bool $getCount
3210
     *
3211
     * @return array    courses
3212
     */
3213
    public static function get_courses_followed_by_drh(
3214
        $user_id,
3215
        $status = DRH,
3216
        $from = null,
3217
        $limit = null,
3218
        $column = null,
3219
        $direction = null,
3220
        $getCount = false
3221
    ) {
3222
        return self::getCoursesFollowedByUser(
3223
            $user_id,
3224
            $status,
3225
            $from,
3226
            $limit,
3227
            $column,
3228
            $direction,
3229
            $getCount
3230
        );
3231
    }
3232
3233
    /**
3234
     * get courses followed by user
3235
     * @param   int $user_id
3236
     * @param   int $status
3237
     * @param   int $from
3238
     * @param   int $limit
3239
     * @param   string $column
3240
     * @param   string $direction
3241
     * @param   boolean $getCount
3242
     * @param   string $keyword
3243
     * @param   int $sessionId
3244
     * @param   boolean $showAllAssignedCourses
3245
     * @return  array   courses
3246
     */
3247
    public static function getCoursesFollowedByUser(
3248
        $user_id,
3249
        $status = null,
3250
        $from = null,
3251
        $limit = null,
3252
        $column = null,
3253
        $direction = null,
3254
        $getCount = false,
3255
        $keyword = null,
3256
        $sessionId = 0,
3257
        $showAllAssignedCourses = false
3258
    ) {
3259
        // Database Table Definitions
3260
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
3261
        $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
3262
        $tbl_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
3263
        $sessionId = (int) $sessionId;
3264
        $user_id = (int) $user_id;
3265
        $select = "SELECT DISTINCT *, c.id as real_id ";
3266
3267
        if ($getCount) {
3268
            $select = "SELECT COUNT(DISTINCT c.id) as count";
3269
        }
3270
3271
        $whereConditions = '';
3272
        switch ($status) {
3273
            case COURSEMANAGER:
3274
                $whereConditions .= " AND cru.user_id = '$user_id'";
3275
                if (!$showAllAssignedCourses) {
3276
                    $whereConditions .= " AND cru.status = ".COURSEMANAGER;
3277
                } else {
3278
                    $whereConditions .= " AND relation_type = ".COURSE_RELATION_TYPE_COURSE_MANAGER;
3279
                }
3280
                break;
3281
            case DRH:
3282
                $whereConditions .= " AND
3283
                    cru.user_id = '$user_id' AND
3284
                    cru.status = ".DRH." AND
3285
                    relation_type = '" . COURSE_RELATION_TYPE_RRHH."'
3286
                ";
3287
                break;
3288
        }
3289
3290
        $keywordCondition = null;
3291
        if (!empty($keyword)) {
3292
            $keyword = Database::escape_string($keyword);
3293
            $keywordCondition = " AND (c.code LIKE '%$keyword%' OR c.title LIKE '%$keyword%' ) ";
3294
        }
3295
3296
        $orderBy = null;
3297
        $extraInnerJoin = null;
3298
3299
        if (!empty($sessionId)) {
3300
            if ($status == COURSEMANAGER) {
3301
                // Teacher of course or teacher inside session
3302
                $whereConditions = " AND (cru.status = ".COURSEMANAGER." OR srcru.status = 2) ";
3303
            }
3304
            $courseList = SessionManager::get_course_list_by_session_id(
3305
                $sessionId
3306
            );
3307
            if (!empty($courseList)) {
3308
                $courseListToString = implode("','", array_keys($courseList));
0 ignored issues
show
Bug introduced by
It seems like $courseList can also be of type integer; however, parameter $input of array_keys() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3308
                $courseListToString = implode("','", array_keys(/** @scrutinizer ignore-type */ $courseList));
Loading history...
3309
                $whereConditions .= " AND c.id IN ('".$courseListToString."')";
3310
            }
3311
            $tableSessionRelCourse = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
3312
            $tableSessionRelCourseRelUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
3313
            $orderBy = ' ORDER BY position';
3314
            $extraInnerJoin = " INNER JOIN $tableSessionRelCourse src
3315
                                ON (c.id = src.c_id AND src.session_id = $sessionId)
3316
                                INNER JOIN $tableSessionRelCourseRelUser srcru 
3317
                                ON (src.session_id = srcru.session_id AND srcru.c_id = src.c_id)
3318
                            ";
3319
        }
3320
3321
        $whereConditions .= $keywordCondition;
3322
        $sql = "$select
3323
                FROM $tbl_course c
3324
                INNER JOIN $tbl_course_rel_user cru 
3325
                ON (cru.c_id = c.id)
3326
                INNER JOIN $tbl_course_rel_access_url a 
3327
                ON (a.c_id = c.id)
3328
                $extraInnerJoin
3329
                WHERE
3330
                    access_url_id = ".api_get_current_access_url_id()."
3331
                    $whereConditions
3332
                $orderBy
3333
                ";
3334
        if (isset($from) && isset($limit)) {
3335
            $from = intval($from);
3336
            $limit = intval($limit);
3337
            $sql .= " LIMIT $from, $limit";
3338
        }
3339
3340
        $result = Database::query($sql);
3341
3342
        if ($getCount) {
3343
            $row = Database::fetch_array($result);
3344
            return $row['count'];
3345
        }
3346
3347
        $courses = array();
3348
        if (Database::num_rows($result) > 0) {
3349
            while ($row = Database::fetch_array($result)) {
3350
                $courses[$row['code']] = $row;
3351
            }
3352
        }
3353
3354
        return $courses;
3355
    }
3356
3357
    /**
3358
     * check if a course is special (autoregister)
3359
     * @param int $courseId
3360
     * @return bool
3361
     */
3362
    public static function isSpecialCourse($courseId)
3363
    {
3364
        $extraFieldValue = new ExtraFieldValue('course');
3365
        $result = $extraFieldValue->get_values_by_handler_and_field_variable(
3366
            $courseId,
3367
            'special_course'
3368
        );
3369
3370
        if (!empty($result)) {
3371
            if ($result['value'] == 1) {
3372
                return true;
3373
            }
3374
        }
3375
3376
        return false;
3377
    }
3378
3379
    /**
3380
     * Update course picture
3381
     * @param   array  $courseInfo
3382
     * @param   string  File name
3383
     * @param   string  The full system name of the image
3384
     * from which course picture will be created.
3385
     * @param   string $cropParameters Optional string that contents "x,y,width,height" of a cropped image format
3386
     * @return  bool    Returns the resulting. In case of internal error or negative validation returns FALSE.
3387
     */
3388
    public static function update_course_picture(
3389
        $courseInfo,
3390
        $filename,
3391
        $source_file = null,
3392
        $cropParameters = null
3393
    ) {
3394
        if (empty($courseInfo)) {
3395
            return false;
3396
        }
3397
3398
        // course path
3399
        $store_path = api_get_path(SYS_COURSE_PATH).$courseInfo['path'];
3400
        // image name for courses
3401
        $course_image = $store_path.'/course-pic.png';
3402
        $course_medium_image = $store_path.'/course-pic85x85.png';
3403
3404
        if (file_exists($course_image)) {
3405
            unlink($course_image);
3406
        }
3407
        if (file_exists($course_medium_image)) {
3408
            unlink($course_medium_image);
3409
        }
3410
3411
        //Crop the image to adjust 4:3 ratio
3412
        $image = new Image($source_file);
3413
        $image->crop($cropParameters);
3414
3415
        //Resize the images in two formats
3416
        $medium = new Image($source_file);
3417
        $medium->resize(85);
3418
        $medium->send_image($course_medium_image, -1, 'png');
3419
        $normal = new Image($source_file);
3420
        $normal->resize(400);
3421
        $normal->send_image($course_image, -1, 'png');
3422
3423
        $result = $medium && $normal;
3424
3425
        return $result ? $result : false;
3426
    }
3427
3428
    /**
3429
     * Deletes the course picture
3430
     * @param string $courseCode
3431
     */
3432
    public static function deleteCoursePicture($courseCode)
3433
    {
3434
        $course_info = api_get_course_info($courseCode);
3435
        // course path
3436
        $storePath = api_get_path(SYS_COURSE_PATH).$course_info['path'];
3437
        // image name for courses
3438
        $courseImage = $storePath.'/course-pic.png';
3439
        $courseMediumImage = $storePath.'/course-pic85x85.png';
3440
        $courseSmallImage = $storePath.'/course-pic32.png';
3441
3442
        if (file_exists($courseImage)) {
3443
            unlink($courseImage);
3444
        }
3445
        if (file_exists($courseMediumImage)) {
3446
            unlink($courseMediumImage);
3447
        }
3448
        if (file_exists($courseSmallImage)) {
3449
            unlink($courseSmallImage);
3450
        }
3451
    }
3452
3453
    /**
3454
     * Builds the course block in user_portal.php
3455
     * @todo use Twig
3456
     *
3457
     * @param array $params
3458
     * @return string
3459
     */
3460
    public static function course_item_html_no_icon($params)
3461
    {
3462
        $html = '<div class="course_item">';
3463
        $html .= '<div class="row">';
3464
        $html .= '<div class="col-md-7">';
3465
3466
        $notifications = isset($params['notifications']) ? $params['notifications'] : null;
3467
3468
        $html .= '<h3>'.$params['title'].$notifications.'</h3> ';
3469
3470
        if (isset($params['description'])) {
3471
            $html .= '<p>'.$params['description'].'</p>';
3472
        }
3473
        if (!empty($params['subtitle'])) {
3474
            $html .= '<small>'.$params['subtitle'].'</small>';
3475
        }
3476
        if (!empty($params['teachers'])) {
3477
            $html .= '<h5 class="teacher">'.
3478
                Display::return_icon(
3479
                    'teacher.png',
3480
                    get_lang('Teacher'),
3481
                    array(),
3482
                    ICON_SIZE_TINY
3483
                ).
3484
                $params['teachers'].'</h5>';
3485
        }
3486
        if (!empty($params['coaches'])) {
3487
            $html .= '<h5 class="teacher">'.
3488
                Display::return_icon(
3489
                    'teacher.png',
3490
                    get_lang('Coach'),
3491
                    array(),
3492
                    ICON_SIZE_TINY
3493
                ).
3494
                $params['coaches'].'</h5>';
3495
        }
3496
3497
        $html .= '</div>';
3498
        $params['right_actions'] = isset($params['right_actions']) ? $params['right_actions'] : null;
3499
        $html .= '<div class="pull-right course-box-actions">'.$params['right_actions'].'</div>';
3500
        $html .= '</div>';
3501
        $html .= '</div>';
3502
3503
        return $html;
3504
    }
3505
3506
    /**
3507
     * @param $params
3508
     * @param bool|false $is_sub_content
3509
     * @return string
3510
     */
3511
    public static function session_items_html($params, $is_sub_content = false)
3512
    {
3513
        $html = '';
3514
        $html .= '<div class="row">';
3515
        $html .= '<div class="col-md-2">';
3516
        if (!empty($params['link'])) {
3517
            $html .= '<a class="thumbnail" href="'.$params['link'].'">';
3518
            $html .= $params['icon'];
3519
            $html .= '</a>';
3520
        } else {
3521
            $html .= $params['icon'];
3522
        }
3523
        $html .= '</div>';
3524
        $html .= '<div class="col-md-10">';
3525
        $html .= $params['title'];
3526
        $html .= $params['coaches'];
3527
        $html .= '</div>';
3528
        $html .= '</div>';
3529
3530
        return $html;
3531
    }
3532
3533
    /**
3534
     * Display special courses (and only these) as several HTML divs of class userportal-course-item
3535
     *
3536
     * Special courses are courses that stick on top of the list and are "auto-registerable"
3537
     * in the sense that any user clicking them is registered as a student
3538
     * @param int       $user_id User id
3539
     * @param bool      $load_dirs Whether to show the document quick-loader or not
3540
     * @param bool $useUserLanguageFilterIfAvailable
3541
     * @return array
3542
     */
3543
    public static function returnSpecialCourses(
3544
        $user_id,
3545
        $load_dirs = false,
3546
        $useUserLanguageFilterIfAvailable = true
3547
    ) {
3548
        $user_id = intval($user_id);
3549
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
3550
        $specialCourseList = self::get_special_course_list();
3551
3552
        if (empty($specialCourseList)) {
3553
            return [];
3554
        }
3555
3556
        // Filter by language
3557
        $languageCondition = '';
3558
        $onlyInUserLanguage = api_get_configuration_value('my_courses_show_courses_in_user_language_only');
3559
        if ($useUserLanguageFilterIfAvailable && $onlyInUserLanguage) {
3560
            $userInfo = api_get_user_info(api_get_user_id());
3561
            if (!empty($userInfo['language'])) {
3562
                $languageCondition = " AND course_language = '".$userInfo['language']."' ";
3563
            }
3564
        }
3565
3566
        $sql = "SELECT
3567
                    id,
3568
                    code,
3569
                    subscribe subscr,
3570
                    unsubscribe unsubscr
3571
                FROM $table                      
3572
                WHERE 
3573
                    id IN ('".implode("','", $specialCourseList)."')
3574
                    $languageCondition
3575
                GROUP BY code";
3576
3577
        $rs_special_course = Database::query($sql);
3578
        $number_of_courses = Database::num_rows($rs_special_course);
3579
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
3580
3581
        $courseList = [];
3582
        if ($number_of_courses > 0) {
3583
            while ($course = Database::fetch_array($rs_special_course)) {
3584
                $course_info = api_get_course_info($course['code']);
3585
                $courseId = $course_info['real_id'];
3586
                if ($course_info['visibility'] == COURSE_VISIBILITY_HIDDEN) {
3587
                    continue;
3588
                }
3589
3590
                $params = [];
3591
                //Param (course_code) needed to get the student info in page "My courses"
3592
                $params['course_code'] = $course['code'];
3593
                $params['code'] = $course['code'];
3594
                // Get notifications.
3595
                $course_info['id_session'] = null;
3596
                $courseUserInfo = self::getUserCourseInfo($user_id, $courseId);
3597
3598
                if (empty($courseUserInfo)) {
3599
                    $course_info['status'] = STUDENT;
3600
                } else {
3601
                    $course_info['status'] = $courseUserInfo['status'];
3602
                }
3603
                $show_notification = !api_get_configuration_value('hide_course_notification')
3604
                    ? Display::show_notification($course_info)
3605
                    : '';
3606
                $params['edit_actions'] = '';
3607
                $params['document'] = '';
3608
                if (api_is_platform_admin()) {
3609
                    $params['edit_actions'] .= api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cidReq='.$course['code'];
3610
                    if ($load_dirs) {
3611
                        $params['document'] = '<a id="document_preview_'.$courseId.'_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3612
                           .Display::returnFontAwesomeIcon('folder-open').'</a>';
3613
                        $params['document'] .= Display::div('', ['id' => 'document_result_'.$courseId.'_0', 'class' => 'document_preview_container']);
3614
                    }
3615
                } else {
3616
                    if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED && $load_dirs) {
3617
                        $params['document'] = '<a id="document_preview_'.$courseId.'_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3618
                           .Display::returnFontAwesomeIcon('folder-open').'</a>';
3619
                        $params['document'] .= Display::div('', ['id' => 'document_result_'.$courseId.'_0', 'class' => 'document_preview_container']);
3620
                    }
3621
                }
3622
3623
                $params['visibility'] = $course_info['visibility'];
3624
                $params['status'] = $course_info['status'];
3625
                $params['category'] = $course_info['categoryName'];
3626
                $params['category_code'] = $course_info['categoryCode'];
3627
                $params['icon'] = Display::return_icon(
3628
                    'drawing-pin.png',
3629
                    null,
3630
                    null,
3631
                    ICON_SIZE_LARGE,
3632
                    null
3633
                );
3634
3635
                if (api_get_setting('display_coursecode_in_courselist') == 'true') {
3636
                    $params['code_course'] = '('.$course_info['visual_code'].')';
3637
                }
3638
3639
                $params['title'] = $course_info['title'];
3640
                $params['title_cut'] = $course_info['title'];
3641
                $params['link'] = $course_info['course_public_url'].'?id_session=0&autoreg=1';
3642
                if (api_get_setting('display_teacher_in_courselist') === 'true') {
3643
                    $params['teachers'] = self::getTeachersFromCourse(
3644
                        $courseId,
3645
                        true
3646
                    );
3647
                }
3648
3649
                if ($showCustomIcon === 'true') {
3650
                    $params['thumbnails'] = $course_info['course_image'];
3651
                    $params['image'] = $course_info['course_image_large'];
3652
                }
3653
3654
                if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
3655
                    $params['notifications'] = $show_notification;
3656
                }
3657
3658
                $params['is_special_course'] = true;
3659
                $courseList[] = $params;
3660
            }
3661
        }
3662
3663
        return $courseList;
3664
    }
3665
3666
    /**
3667
     * Display courses (without special courses) as several HTML divs
3668
     * of course categories, as class userportal-catalog-item.
3669
     * @uses displayCoursesInCategory() to display the courses themselves
3670
     * @param int $user_id
3671
     * @param bool  $load_dirs Whether to show the document quick-loader or not
3672
     * @param bool $useUserLanguageFilterIfAvailable
3673
     *
3674
     * @return array
3675
     */
3676
    public static function returnCourses(
3677
        $user_id,
3678
        $load_dirs = false,
3679
        $useUserLanguageFilterIfAvailable = true
3680
    ) {
3681
        $user_id = intval($user_id);
3682
        if (empty($user_id)) {
3683
            $user_id = api_get_user_id();
3684
        }
3685
        // Step 1: We get all the categories of the user
3686
        $table = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
3687
        $sql = "SELECT id, title FROM $table
3688
                WHERE user_id = '".$user_id."'
3689
                ORDER BY sort ASC";
3690
3691
        $result = Database::query($sql);
3692
        $listItems = [
3693
            'in_category' => [],
3694
            'not_category' => []
3695
        ];
3696
        while ($row = Database::fetch_array($result)) {
3697
            // We simply display the title of the category.
3698
            $courseInCategory = self::returnCoursesCategories(
3699
                $row['id'],
3700
                $load_dirs,
3701
                $user_id,
3702
                $useUserLanguageFilterIfAvailable
3703
            );
3704
3705
            $params = [
3706
                'id_category' => $row ['id'],
3707
                'title_category' => $row['title'],
3708
                'courses' => $courseInCategory
3709
            ];
3710
            $listItems['in_category'][] = $params;
3711
        }
3712
3713
        // Step 2: We display the course without a user category.
3714
        $coursesNotCategory = self::returnCoursesCategories(
3715
            0,
3716
            $load_dirs,
3717
            $user_id,
3718
            $useUserLanguageFilterIfAvailable
3719
        );
3720
3721
        if ($coursesNotCategory) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $coursesNotCategory of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
3722
            $listItems['not_category'] = $coursesNotCategory;
3723
        }
3724
3725
        return $listItems;
3726
    }
3727
3728
    /**
3729
     *  Display courses inside a category (without special courses) as HTML dics of
3730
     *  class userportal-course-item.
3731
     * @param int      $user_category_id User category id
3732
     * @param bool $load_dirs Whether to show the document quick-loader or not
3733
     * @param int $user_id
3734
     * @param bool $useUserLanguageFilterIfAvailable
3735
     * @return array
3736
     */
3737
    public static function returnCoursesCategories(
3738
        $user_category_id,
3739
        $load_dirs = false,
3740
        $user_id = 0,
3741
        $useUserLanguageFilterIfAvailable = true
3742
    ) {
3743
        $user_id = $user_id ?: api_get_user_id();
3744
        $user_category_id = (int) $user_category_id;
3745
3746
        // Table definitions
3747
        $TABLECOURS = Database::get_main_table(TABLE_MAIN_COURSE);
3748
        $TABLECOURSUSER = Database::get_main_table(TABLE_MAIN_COURSE_USER);
3749
        $TABLE_ACCESS_URL_REL_COURSE = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
3750
        $current_url_id = api_get_current_access_url_id();
3751
3752
        // Get course list auto-register
3753
        $special_course_list = self::get_special_course_list();
3754
        $without_special_courses = '';
3755
        if (!empty($special_course_list)) {
3756
            $without_special_courses = ' AND course.id NOT IN ("'.implode('","', $special_course_list).'")';
3757
        }
3758
3759
        $userCategoryCondition = " (course_rel_user.user_course_cat = $user_category_id) ";
3760
        if (empty($user_category_id)) {
3761
            $userCategoryCondition = ' (course_rel_user.user_course_cat = 0 OR course_rel_user.user_course_cat IS NULL) ';
3762
        }
3763
3764
        $languageCondition = '';
3765
        $onlyInUserLanguage = api_get_configuration_value('my_courses_show_courses_in_user_language_only');
3766
        if ($useUserLanguageFilterIfAvailable && $onlyInUserLanguage) {
3767
            $userInfo = api_get_user_info(api_get_user_id());
3768
            if (!empty($userInfo['language'])) {
3769
                $languageCondition = " AND course.course_language = '".$userInfo['language']."' ";
3770
            }
3771
        }
3772
3773
        $sql = "SELECT DISTINCT
3774
                    course.id,
3775
                    course_rel_user.status status,
3776
                    course.code as course_code                    
3777
                FROM $TABLECOURS course 
3778
                INNER JOIN $TABLECOURSUSER course_rel_user
3779
                ON (course.id = course_rel_user.c_id)
3780
                INNER JOIN $TABLE_ACCESS_URL_REL_COURSE url
3781
                ON (url.c_id = course.id)
3782
                WHERE
3783
                    course_rel_user.user_id = '".$user_id."' AND
3784
                    $userCategoryCondition
3785
                    $without_special_courses
3786
                    $languageCondition
3787
                ";
3788
        // If multiple URL access mode is enabled, only fetch courses
3789
        // corresponding to the current URL.
3790
        if (api_get_multiple_access_url() && $current_url_id != -1) {
3791
            $sql .= " AND access_url_id='".$current_url_id."'";
3792
        }
3793
        // Use user's classification for courses (if any).
3794
        $sql .= " ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
3795
        $result = Database::query($sql);
3796
3797
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
3798
        // Browse through all courses.
3799
        $courseAdded = [];
3800
        $courseList = [];
3801
        while ($row = Database::fetch_array($result)) {
3802
            $course_info = api_get_course_info_by_id($row['id']);
3803
3804
            if (isset($course_info['visibility']) &&
3805
                $course_info['visibility'] == COURSE_VISIBILITY_HIDDEN
3806
            ) {
3807
                continue;
3808
            }
3809
3810
            // Skip if already in list
3811
            if (in_array($course_info['real_id'], $courseAdded)) {
3812
                continue;
3813
            }
3814
            $course_info['id_session'] = null;
3815
            $course_info['status'] = $row['status'];
3816
            // For each course, get if there is any notification icon to show
3817
            // (something that would have changed since the user's last visit).
3818
            $showNotification = !api_get_configuration_value('hide_course_notification')
3819
                ? Display::show_notification($course_info)
3820
                : '';
3821
            $iconName = basename($course_info['course_image']);
3822
3823
            $params = array();
3824
            //Param (course_code) needed to get the student process
3825
            $params['course_code'] = $row['course_code'];
3826
            $params['code'] = $row['course_code'];
3827
3828
            if ($showCustomIcon === 'true' && $iconName != 'course.png') {
3829
                $params['thumbnails'] = $course_info['course_image'];
3830
                $params['image'] = $course_info['course_image_large'];
3831
            }
3832
3833
            $thumbnails = null;
3834
            $image = null;
3835
            if ($showCustomIcon === 'true' && $iconName != 'course.png') {
3836
                $thumbnails = $course_info['course_image'];
3837
                $image = $course_info['course_image_large'];
3838
            } else {
3839
                $image = Display::return_icon(
3840
                    'session_default.png',
3841
                    null,
3842
                    null,
3843
                    null,
3844
                    null,
3845
                    true
3846
                );
3847
            }
3848
3849
            $params['course_id'] = $course_info['real_id'];
3850
            $params['edit_actions'] = '';
3851
            $params['document'] = '';
3852
            if (api_is_platform_admin()) {
3853
                $params['edit_actions'] .= api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cidReq='.$course_info['code'];
3854
                if ($load_dirs) {
3855
                    $params['document'] = '<a id="document_preview_'.$course_info['real_id'].'_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3856
                               .Display::returnFontAwesomeIcon('folder-open').'</a>';
3857
                    $params['document'] .= Display::div(
3858
                        '',
3859
                        array(
3860
                            'id' => 'document_result_'.$course_info['real_id'].'_0',
3861
                            'class' => 'document_preview_container',
3862
                        )
3863
                    );
3864
                }
3865
            }
3866
            if ($load_dirs) {
3867
                $params['document'] = '<a id="document_preview_'.$course_info['real_id'].'_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
3868
                    . Display::returnFontAwesomeIcon('folder-open').'</a>';
3869
                $params['document'] .= Display::div(
3870
                    '',
3871
                    array(
3872
                        'id' => 'document_result_'.$course_info['real_id'].'_0',
3873
                        'class' => 'document_preview_container',
3874
                    )
3875
                );
3876
            }
3877
3878
            $courseUrl = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/index.php?id_session=0';
3879
            $teachers = [];
3880
            if (api_get_setting('display_teacher_in_courselist') === 'true') {
3881
                $teachers = self::getTeachersFromCourse(
3882
                    $course_info['real_id'],
3883
                    true
3884
                );
3885
            }
3886
3887
            $params['status'] = $row['status'];
3888
            if (api_get_setting('display_coursecode_in_courselist') == 'true') {
3889
                $params['code_course'] = '('.$course_info['visual_code'].') ';
3890
            }
3891
3892
            $params['current_user_is_teacher'] = false;
3893
            /** @var array $teacher */
3894
            foreach ($teachers as $teacher) {
3895
                if ($teacher['id'] != $user_id) {
3896
                    continue;
3897
                }
3898
                $params['current_user_is_teacher'] = true;
3899
            }
3900
3901
            $params['visibility'] = $course_info['visibility'];
3902
            $params['link'] = $courseUrl;
3903
            $params['thumbnails'] = $thumbnails;
3904
            $params['image'] = $image;
3905
            $params['title'] = $course_info['title'];
3906
            $params['title_cut'] = $params['title'];
3907
            $params['category'] = $course_info['categoryName'];
3908
            $params['category_code'] = $course_info['categoryCode'];
3909
            $params['teachers'] = $teachers;
3910
3911
            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
3912
                $params['notifications'] = $showNotification;
3913
            }
3914
            $courseAdded[] = $course_info['real_id'];
3915
            $courseList[] = $params;
3916
        }
3917
3918
        return $courseList;
3919
    }
3920
3921
    /**
3922
     *  Display courses inside a category (without special courses) as HTML dics of
3923
     *  class userportal-course-item.
3924
     * @deprecated use self::returnCoursesCategories(0);
3925
     * @param int      User category id
3926
     * @param bool      Whether to show the document quick-loader or not
3927
     * @return array
3928
     */
3929
    public static function returnCoursesWithoutCategories($user_category_id, $load_dirs = false)
3930
    {
3931
        $user_id = api_get_user_id();
3932
        // Table definitions
3933
        $TABLECOURS = Database::get_main_table(TABLE_MAIN_COURSE);
3934
        $TABLECOURSUSER = Database::get_main_table(TABLE_MAIN_COURSE_USER);
3935
        $TABLE_ACCESS_URL_REL_COURSE = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
3936
        $current_url_id = api_get_current_access_url_id();
3937
        $courseList = [];
3938
3939
        // Get course list auto-register
3940
        $special_course_list = self::get_special_course_list();
3941
3942
        $without_special_courses = '';
3943
        if (!empty($special_course_list)) {
3944
            $without_special_courses = ' AND course.id NOT IN ("'.implode('","', $special_course_list).'")';
3945
        }
3946
3947
        $sql = "SELECT
3948
                    course.id,
3949
                    course.title,
3950
                    course.code,
3951
                    course.subscribe subscr,
3952
                    course.unsubscribe unsubscr,
3953
                    course_rel_user.status status,
3954
                    course_rel_user.sort sort,
3955
                    course_rel_user.user_course_cat user_course_cat
3956
                FROM $TABLECOURS course 
3957
                INNER JOIN $TABLECOURSUSER course_rel_user
3958
                ON (course.id = course_rel_user.c_id)
3959
                INNER JOIN $TABLE_ACCESS_URL_REL_COURSE url
3960
                ON (url.c_id = course.id)
3961
                WHERE
3962
                    course_rel_user.user_id = '".$user_id."' AND
3963
                    course_rel_user.user_course_cat = '" . $user_category_id."'
3964
                    $without_special_courses ";
3965
3966
        // If multiple URL access mode is enabled, only fetch courses
3967
        // corresponding to the current URL.
3968
        if (api_get_multiple_access_url() && $current_url_id != -1) {
3969
            $sql .= " AND url.c_id = course.id AND access_url_id='".$current_url_id."'";
3970
        }
3971
        // Use user's classification for courses (if any).
3972
        $sql .= " ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
3973
        $result = Database::query($sql);
3974
3975
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
3976
        // Browse through all courses.
3977
        while ($row = Database::fetch_array($result)) {
3978
            $course_info = api_get_course_info($row['code']);
3979
            if (isset($course_info['visibility']) &&
3980
                $course_info['visibility'] == COURSE_VISIBILITY_HIDDEN
3981
            ) {
3982
                continue;
3983
            }
3984
            $course_info['id_session'] = null;
3985
            $course_info['status'] = $row['status'];
3986
3987
            // For each course, get if there is any notification icon to show
3988
            // (something that would have changed since the user's last visit).
3989
            $showNotification = !api_get_configuration_value('hide_course_notification')
3990
                ? Display::show_notification($course_info)
3991
                : '';
3992
3993
            $thumbnails = null;
3994
            $image = null;
3995
            $iconName = basename($course_info['course_image']);
3996
            if ($showCustomIcon === 'true' && $iconName != 'course.png') {
3997
                $thumbnails = $course_info['course_image'];
3998
                $image = $course_info['course_image_large'];
3999
            } else {
4000
                $image = Display::return_icon(
4001
                    'session_default.png',
4002
                    null,
4003
                    null,
4004
                    null,
4005
                    null,
4006
                    true
4007
                );
4008
            }
4009
4010
            $params = array();
4011
            //Param (course_code) needed to get the student process
4012
            $params['course_code'] = $row['code'];
4013
            $params['edit_actions'] = '';
4014
            $params['document'] = '';
4015
            if (api_is_platform_admin()) {
4016
                $params['edit_actions'] .= api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cidReq='.$course_info['code'];
4017
                if ($load_dirs) {
4018
                    $params['document'] = '<a id="document_preview_'.$course_info['real_id'].'_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
4019
                               . Display::returnFontAwesomeIcon('folder-open').'</a>';
4020
                    $params['document'] .= Display::div('', array('id' => 'document_result_'.$course_info['real_id'].'_0', 'class' => 'document_preview_container'));
4021
                }
4022
            }
4023
            if ($load_dirs) {
4024
                $params['document'] = '<a id="document_preview_'.$course_info['real_id'].'_0" class="document_preview btn btn-default btn-sm" href="javascript:void(0);">'
4025
                    .Display::returnFontAwesomeIcon('folder-open').'</a>';
4026
                $params['document'] .= Display::div('', array('id' => 'document_result_'.$course_info['real_id'].'_0', 'class' => 'document_preview_container'));
4027
            }
4028
4029
            $course_title_url = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/index.php?id_session=0';
4030
4031
            $teachers = [];
4032
            if (api_get_setting('display_teacher_in_courselist') === 'true') {
4033
                $teachers = self::getTeachersFromCourse(
4034
                    $course_info['real_id'],
4035
                    false
4036
                );
4037
            }
4038
            $params['status'] = $row['status'];
4039
4040
            if (api_get_setting('display_coursecode_in_courselist') == 'true') {
4041
                $params['code_course'] = '('.$course_info['visual_code'].') ';
4042
            }
4043
4044
            $params['visibility'] = $course_info['visibility'];
4045
            $params['link'] = $course_title_url;
4046
            $params['thumbnails'] = $thumbnails;
4047
            $params['image'] = $image;
4048
            $params['title'] = $course_info['title'];
4049
            $params['category'] = $course_info['categoryName'];
4050
            $params['teachers'] = $teachers;
4051
4052
            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
4053
                $params['notifications'] = $showNotification;
4054
            }
4055
4056
            $courseList[] = $params;
4057
        }
4058
4059
        return $courseList;
4060
    }
4061
4062
    /**
4063
     * Retrieves the user defined course categories
4064
     * @param int $userId
4065
     * @return array
4066
     */
4067
    public static function get_user_course_categories($userId = 0)
4068
    {
4069
        $userId = empty($userId) ? api_get_user_id() : (int) $userId;
4070
        $table = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
4071
        $sql = "SELECT * FROM $table 
4072
                WHERE user_id = $userId
4073
                ORDER BY sort ASC
4074
                ";
4075
        $result = Database::query($sql);
4076
        $output = array();
4077
        while ($row = Database::fetch_array($result, 'ASSOC')) {
4078
            $output[$row['id']] = $row;
4079
        }
4080
        return $output;
4081
    }
4082
4083
    /**
4084
     * Return an array the user_category id and title for the course $courseId for user $userId
4085
     * @param $userId
4086
     * @param $courseId
4087
     * @return array
4088
     */
4089
    public static function getUserCourseCategoryForCourse($userId, $courseId)
4090
    {
4091
        $tblCourseRelUser = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4092
        $tblUserCategory = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
4093
        $courseId = intval($courseId);
4094
        $userId = intval($userId);
4095
4096
        $sql = "SELECT user_course_cat, title
4097
                FROM $tblCourseRelUser cru
4098
                LEFT JOIN $tblUserCategory ucc
4099
                ON cru.user_course_cat = ucc.id
4100
                WHERE
4101
                    cru.user_id = $userId AND c_id= $courseId ";
4102
4103
        $res = Database::query($sql);
4104
4105
        $data = array();
4106
        if (Database::num_rows($res) > 0) {
4107
            $data = Database::fetch_assoc($res);
4108
        }
4109
4110
        return $data;
4111
    }
4112
4113
    /**
4114
     * Get the course id based on the original id and field name in the extra fields.
4115
     * Returns 0 if course was not found
4116
     *
4117
     * @param string $value Original course code
4118
     * @param string $variable Original field name
4119
     * @return array
4120
     */
4121
    public static function getCourseInfoFromOriginalId($value, $variable)
4122
    {
4123
        $extraFieldValue = new ExtraFieldValue('course');
4124
        $result = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
4125
            $variable,
4126
            $value
4127
        );
4128
4129
        if (!empty($result)) {
4130
            $courseInfo = api_get_course_info_by_id($result['item_id']);
4131
            return $courseInfo;
4132
        }
4133
4134
        return [];
4135
    }
4136
4137
    /**
4138
     * Display code for one specific course a logged in user is subscribed to.
4139
     * Shows a link to the course, what's new icons...
4140
     *
4141
     * $my_course['d'] - course directory
4142
     * $my_course['i'] - course title
4143
     * $my_course['c'] - visual course code
4144
     * $my_course['k']  - system course code
4145
     *
4146
     * @param   array       Course details
4147
     * @param   integer     Session ID
4148
     * @param   string      CSS class to apply to course entry
4149
     * @param   boolean     Whether the session is supposedly accessible now
4150
     * (not in the case it has passed and is in invisible/unaccessible mode)
4151
     * @param bool      Whether to show the document quick-loader or not
4152
     * @return  string      The HTML to be printed for the course entry
4153
     *
4154
     * @version 1.0.3
4155
     * @todo refactor into different functions for database calls | logic | display
4156
     * @todo replace single-character $my_course['d'] indices
4157
     * @todo move code for what's new icons to a separate function to clear things up
4158
     * @todo add a parameter user_id so that it is possible to show the
4159
     * courselist of other users (=generalisation).
4160
     * This will prevent having to write a new function for this.
4161
     */
4162
    public static function get_logged_user_course_html(
4163
        $course,
4164
        $session_id = 0,
4165
        $class = 'courses',
4166
        $session_accessible = true,
4167
        $load_dirs = false
4168
    ) {
4169
        $now = date('Y-m-d h:i:s');
4170
        $user_id = api_get_user_id();
4171
        $course_info = api_get_course_info_by_id($course['real_id']);
4172
        $course_visibility = $course_info['visibility'];
4173
4174
        if ($course_visibility == COURSE_VISIBILITY_HIDDEN) {
4175
            return '';
4176
        }
4177
4178
        $userInCourseStatus = self::getUserInCourseStatus(
4179
            $user_id,
4180
            $course_info['real_id']
4181
        );
4182
4183
        $course_info['status'] = empty($session_id) ? $userInCourseStatus : STUDENT;
4184
        $course_info['id_session'] = $session_id;
4185
4186
        $is_coach = api_is_coach($session_id, $course_info['real_id']);
0 ignored issues
show
Bug introduced by
It seems like $course_info['real_id'] can also be of type boolean; however, parameter $courseId of api_is_coach() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

4186
        $is_coach = api_is_coach($session_id, /** @scrutinizer ignore-type */ $course_info['real_id']);
Loading history...
4187
4188
        // Display course entry.
4189
        // Show a hyperlink to the course, unless the course is closed and user is not course admin.
4190
        $session_url = '';
4191
        $params = [];
4192
        $params['icon'] = Display::return_icon(
4193
            'blackboard_blue.png',
4194
            null,
4195
            array(),
4196
            ICON_SIZE_LARGE,
4197
            null,
4198
            true
4199
        );
4200
        $params['real_id'] = $course_info['real_id'];
4201
4202
        // Display the "what's new" icons
4203
        $notifications = '';
4204
        if (
4205
            ($course_visibility != COURSE_VISIBILITY_CLOSED && $course_visibility != COURSE_VISIBILITY_HIDDEN) ||
4206
            !api_get_configuration_value('hide_course_notification')
4207
        ) {
4208
            $notifications .= Display::show_notification($course_info);
4209
        }
4210
4211
        if ($session_accessible) {
4212
            if ($course_visibility != COURSE_VISIBILITY_CLOSED ||
4213
                $userInCourseStatus == COURSEMANAGER
4214
            ) {
4215
                if (empty($course_info['id_session'])) {
4216
                    $course_info['id_session'] = 0;
4217
                }
4218
4219
                $sessionCourseAvailable = false;
4220
                $sessionCourseStatus = api_get_session_visibility($session_id, $course_info['real_id']);
0 ignored issues
show
Bug introduced by
It seems like $course_info['real_id'] can also be of type boolean; however, parameter $courseId of api_get_session_visibility() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

4220
                $sessionCourseStatus = api_get_session_visibility($session_id, /** @scrutinizer ignore-type */ $course_info['real_id']);
Loading history...
4221
4222
                if (in_array($sessionCourseStatus,
4223
                    array(SESSION_VISIBLE_READ_ONLY, SESSION_VISIBLE, SESSION_AVAILABLE))) {
4224
                    $sessionCourseAvailable = true;
4225
                }
4226
4227
                if ($userInCourseStatus == COURSEMANAGER || $sessionCourseAvailable) {
4228
                    $session_url = $course_info['course_public_url'].'?id_session='.$course_info['id_session'];
4229
                    $session_title = '<a href="'.$session_url.'">'.$course_info['name'].'</a>'.$notifications;
4230
                } else {
4231
                    $session_title = $course_info['name'];
4232
                }
4233
4234
            } else {
4235
                $session_title =
4236
                    $course_info['name'].' '.
4237
                    Display::tag('span', get_lang('CourseClosed'), array('class' => 'item_closed'));
4238
            }
4239
        } else {
4240
            $session_title = $course_info['name'];
4241
        }
4242
4243
        $thumbnails = null;
4244
        $image = null;
4245
        $showCustomIcon = api_get_setting('course_images_in_courses_list');
4246
        $iconName = basename($course_info['course_image']);
4247
4248
        if ($showCustomIcon === 'true' && $iconName != 'course.png') {
4249
            $thumbnails = $course_info['course_image'];
4250
            $image = $course_info['course_image_large'];
4251
        } else {
4252
            $image = Display::return_icon(
4253
                'session_default.png',
4254
                null,
4255
                null,
4256
                null,
4257
                null,
4258
                true
4259
            );
4260
        }
4261
        $params['thumbnails'] = $thumbnails;
4262
        $params['image'] = $image;
4263
        $params['link'] = $session_url;
4264
        $params['title'] = $session_title;
4265
        $params['edit_actions'] = '';
4266
        $params['document'] = '';
4267
        $params['category'] = $course_info['categoryName'];
4268
4269
        if ($course_visibility != COURSE_VISIBILITY_CLOSED &&
4270
            $course_visibility != COURSE_VISIBILITY_HIDDEN
4271
        ) {
4272
            if (api_is_platform_admin()) {
4273
                $params['edit_actions'] .= api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cidReq='.$course_info['code'];
4274
                if ($load_dirs) {
4275
                    $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);">'.
4276
                        Display::returnFontAwesomeIcon('folder-open').'</a>';
4277
                    $params['document'] .= Display::div('', array(
4278
                        'id' => 'document_result_'.$course_info['real_id'].'_'.$course_info['id_session'],
4279
                        'class' => 'document_preview_container'
4280
                    ));
4281
                }
4282
            }
4283
        }
4284
        if (api_get_setting('display_teacher_in_courselist') === 'true') {
4285
            $teacher_list = self::getTeachersFromCourse(
4286
                $course_info['real_id'],
0 ignored issues
show
Bug introduced by
It seems like $course_info['real_id'] can also be of type boolean; however, parameter $courseId of CourseManager::getTeachersFromCourse() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

4286
                /** @scrutinizer ignore-type */ $course_info['real_id'],
Loading history...
4287
                true
4288
            );
4289
4290
            $course_coachs = self::get_coachs_from_course(
4291
                $course_info['id_session'],
4292
                $course_info['real_id']
0 ignored issues
show
Bug introduced by
It seems like $course_info['real_id'] can also be of type boolean; however, parameter $courseId of CourseManager::get_coachs_from_course() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

4292
                /** @scrutinizer ignore-type */ $course_info['real_id']
Loading history...
4293
            );
4294
            $params['teachers'] = $teacher_list;
4295
4296
            if (($course_info['status'] == STUDENT && !empty($course_info['id_session'])) ||
4297
                ($is_coach && $course_info['status'] != COURSEMANAGER)
4298
            ) {
4299
                $params['coaches'] = $course_coachs;
4300
            }
4301
        }
4302
        $special = isset($course['special_course']) ? true : false;
4303
        $params['title'] = $session_title;
4304
        $params['special'] = $special;
4305
        $params['code'] = $course_info['visual_code'];
4306
        $params['extra'] = '';
4307
        $html = $params;
4308
4309
        $session_category_id = null;
4310
        if (1) {
4311
            $session = '';
4312
            $active = false;
4313
            if (!empty($course_info['id_session'])) {
4314
                $session = api_get_session_info($course_info['id_session']);
4315
                $sessionCoachName = '';
4316
                if (!empty($session['id_coach'])) {
4317
                    $coachInfo = api_get_user_info($session['id_coach']);
4318
                    $sessionCoachName = $coachInfo['complete_name'];
4319
                }
4320
4321
                $session_category_id = self::get_session_category_id_by_session_id($course_info['id_session']);
4322
4323
                if (
4324
                    $session['access_start_date'] == '0000-00-00 00:00:00' || empty($session['access_start_date']) ||
4325
                    $session['access_start_date'] == '0000-00-00'
4326
                ) {
4327
                    $session['dates'] = '';
4328
                    if (api_get_setting('show_session_coach') === 'true') {
4329
                        $session['coach'] = get_lang('GeneralCoach').': '.$sessionCoachName;
4330
                    }
4331
                    $active = true;
4332
                } else {
4333
                    $session ['dates'] = ' - '.get_lang('From').' '.$session['access_start_date'].' '.get_lang('To').' '.$session['access_end_date'];
4334
                    if (api_get_setting('show_session_coach') === 'true') {
4335
                        $session['coach'] = get_lang('GeneralCoach').': '.$sessionCoachName;
4336
                    }
4337
                    $date_start = $session['access_start_date'];
4338
                    $date_end = $session['access_end_date'];
4339
                    $active = !$date_end ? ($date_start <= $now) : ($date_start <= $now && $date_end >= $now);
4340
                }
4341
            }
4342
            $user_course_category = '';
4343
            if (isset($course_info['user_course_cat'])) {
4344
                $user_course_category = $course_info['user_course_cat'];
4345
            }
4346
            $output = array(
4347
                $user_course_category,
4348
                $html,
4349
                $course_info['id_session'],
4350
                $session,
4351
                'active' => $active,
4352
                'session_category_id' => $session_category_id
4353
            );
4354
4355
            if (Skill::isAllowed($user_id, false)) {
4356
                $em = Database::getManager();
4357
                $objUser = api_get_user_entity($user_id);
4358
                $objCourse = $em->find('ChamiloCoreBundle:Course', $course['real_id']);
4359
                $objSession = $em->find('ChamiloCoreBundle:Session', $session_id);
4360
4361
                $skill = $em->getRepository('ChamiloCoreBundle:Skill')->getLastByUser($objUser, $objCourse, $objSession);
4362
4363
                $output['skill'] = null;
4364
                if ($skill) {
4365
                    $output['skill']['name'] = $skill->getName();
4366
                    $output['skill']['icon'] = $skill->getIcon();
4367
                }
4368
            }
4369
        } else {
4370
            $output = array($course_info['user_course_cat'], $html);
4371
        }
4372
4373
        return $output;
4374
    }
4375
4376
    /**
4377
     *
4378
     * @param string $source_course_code
4379
     * @param int $source_session_id
4380
     * @param string $destination_course_code
4381
     * @param int $destination_session_id
4382
     * @param array $params
4383
     *
4384
     * @return  bool
4385
     */
4386
    public static function copy_course(
4387
        $source_course_code,
4388
        $source_session_id,
4389
        $destination_course_code,
4390
        $destination_session_id,
4391
        $params = array()
4392
    ) {
4393
        $course_info = api_get_course_info($source_course_code);
4394
4395
        if (!empty($course_info)) {
4396
            $cb = new CourseBuilder('', $course_info);
4397
            $course = $cb->build($source_session_id, $source_course_code, true);
4398
            $course_restorer = new CourseRestorer($course);
4399
            $course_restorer->skip_content = $params;
4400
            $course_restorer->restore(
4401
                $destination_course_code,
4402
                $destination_session_id,
4403
                true,
4404
                true
4405
            );
4406
            return true;
4407
        }
4408
        return false;
4409
    }
4410
4411
    /**
4412
     * A simpler version of the copy_course, the function creates an empty course with an autogenerated course code
4413
     *
4414
     * @param string $new_title new course title
4415
     * @param string source course code
4416
     * @param int source session id
4417
     * @param int destination session id
4418
     * @param array $params
4419
     *
4420
     * @return     array
4421
     */
4422
    public static function copy_course_simple(
4423
        $new_title,
4424
        $source_course_code,
4425
        $source_session_id = 0,
4426
        $destination_session_id = 0,
4427
        $params = []
4428
    ) {
4429
        $source_course_info = api_get_course_info($source_course_code);
4430
        if (!empty($source_course_info)) {
4431
            $new_course_code = self::generate_nice_next_course_code($source_course_code);
4432
            if ($new_course_code) {
4433
                $new_course_info = self::create_course(
4434
                    $new_title,
4435
                    $new_course_code,
4436
                    false
4437
                );
4438
                if (!empty($new_course_info['code'])) {
4439
                    $result = self::copy_course(
4440
                        $source_course_code,
4441
                        $source_session_id,
4442
                        $new_course_info['code'],
4443
                        $destination_session_id,
4444
                        $params
4445
                    );
4446
                    if ($result) {
4447
                        return $new_course_info;
4448
                    }
4449
                }
4450
            }
4451
        }
4452
4453
        return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type array.
Loading history...
4454
    }
4455
4456
    /**
4457
     * Creates a new course code based in a given code
4458
     *
4459
     * @param string    wanted code
4460
     * <code>    $wanted_code = 'curse' if there are in the DB codes like curse1 curse2 the function will return: course3</code>
4461
     * if the course code doest not exist in the DB the same course code will be returned
4462
     * @return string    wanted unused code
4463
     */
4464
    public static function generate_nice_next_course_code($wanted_code)
4465
    {
4466
        $course_code_ok = !self::course_code_exists($wanted_code);
4467
        if (!$course_code_ok) {
4468
            $wanted_code = self::generate_course_code($wanted_code);
4469
            $table = Database::get_main_table(TABLE_MAIN_COURSE);
4470
            $wanted_code = Database::escape_string($wanted_code);
4471
            $sql = "SELECT count(id) as count
4472
                    FROM $table
4473
                    WHERE code LIKE '$wanted_code%'";
4474
            $result = Database::query($sql);
4475
            if (Database::num_rows($result) > 0) {
4476
                $row = Database::fetch_array($result);
4477
                $count = $row['count'] + 1;
4478
                $wanted_code = $wanted_code.'_'.$count;
4479
                $result = api_get_course_info($wanted_code);
4480
                if (empty($result)) {
4481
                    return $wanted_code;
4482
                }
4483
            }
4484
4485
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type string.
Loading history...
4486
        }
4487
4488
        return $wanted_code;
4489
    }
4490
4491
    /**
4492
     * Gets the status of the users agreement in a course course-session
4493
     *
4494
     * @param int $user_id
4495
     * @param string $course_code
4496
     * @param int $session_id
4497
     * @return boolean
4498
     */
4499
    public static function is_user_accepted_legal($user_id, $course_code, $session_id = 0)
4500
    {
4501
        $user_id = intval($user_id);
4502
        $course_code = Database::escape_string($course_code);
4503
        $session_id = intval($session_id);
4504
4505
        $courseInfo = api_get_course_info($course_code);
4506
        $courseId = $courseInfo['real_id'];
4507
4508
        // Course legal
4509
        $enabled = api_get_plugin_setting('courselegal', 'tool_enable');
4510
4511
        if ($enabled == 'true') {
4512
            require_once api_get_path(SYS_PLUGIN_PATH).'courselegal/config.php';
4513
            $plugin = CourseLegalPlugin::create();
4514
            return $plugin->isUserAcceptedLegal($user_id, $course_code, $session_id);
4515
        }
4516
4517
        if (empty($session_id)) {
4518
            $table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4519
            $sql = "SELECT legal_agreement FROM $table
4520
                    WHERE user_id = $user_id AND c_id = $courseId ";
4521
            $result = Database::query($sql);
4522
            if (Database::num_rows($result) > 0) {
4523
                $result = Database::fetch_array($result);
4524
                if ($result['legal_agreement'] == 1) {
4525
                    return true;
4526
                }
4527
            }
4528
            return false;
4529
        } else {
4530
            $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4531
            $sql = "SELECT legal_agreement FROM $table
4532
                    WHERE user_id = $user_id AND c_id = $courseId AND session_id = $session_id";
4533
            $result = Database::query($sql);
4534
            if (Database::num_rows($result) > 0) {
4535
                $result = Database::fetch_array($result);
4536
                if ($result['legal_agreement'] == 1) {
4537
                    return true;
4538
                }
4539
            }
4540
            return false;
4541
        }
4542
    }
4543
4544
    /**
4545
     * Saves the user-course legal agreement
4546
     * @param   int user id
4547
     * @param   string course code
4548
     * @param   int session id
4549
     * @return mixed
4550
     */
4551
    public static function save_user_legal($user_id, $course_code, $session_id = null)
4552
    {
4553
        // Course plugin legal
4554
        $enabled = api_get_plugin_setting('courselegal', 'tool_enable');
4555
        if ($enabled == 'true') {
4556
            require_once api_get_path(SYS_PLUGIN_PATH).'courselegal/config.php';
4557
            $plugin = CourseLegalPlugin::create();
4558
            return $plugin->saveUserLegal($user_id, $course_code, $session_id);
4559
        }
4560
4561
        $user_id = intval($user_id);
4562
        $course_code = Database::escape_string($course_code);
4563
        $session_id = intval($session_id);
4564
        $courseInfo = api_get_course_info($course_code);
4565
        $courseId = $courseInfo['real_id'];
4566
4567
        if (empty($session_id)) {
4568
            $table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
4569
            $sql = "UPDATE $table SET legal_agreement = '1'
4570
                    WHERE user_id = $user_id AND c_id  = $courseId ";
4571
            Database::query($sql);
4572
        } else {
4573
            $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4574
            $sql = "UPDATE  $table SET legal_agreement = '1'
4575
                    WHERE user_id = $user_id AND c_id = $courseId AND session_id = $session_id";
4576
            Database::query($sql);
4577
        }
4578
    }
4579
4580
    /**
4581
     * @param int $user_id
4582
     * @param int $course_id
4583
     * @param int $session_id
4584
     * @param int $url_id
4585
     * @return bool
4586
     */
4587
    public static function get_user_course_vote($user_id, $course_id, $session_id = 0, $url_id = 0)
4588
    {
4589
        $table_user_course_vote = Database::get_main_table(TABLE_MAIN_USER_REL_COURSE_VOTE);
4590
        $session_id = !isset($session_id) ? api_get_session_id() : intval($session_id);
4591
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4592
        $user_id = intval($user_id);
4593
4594
        if (empty($user_id)) {
4595
            return false;
4596
        }
4597
4598
        $params = array(
4599
            'user_id' => $user_id,
4600
            'c_id' => $course_id,
4601
            'session_id' => $session_id,
4602
            'url_id' => $url_id
4603
        );
4604
4605
        $result = Database::select(
4606
            'vote',
4607
            $table_user_course_vote,
4608
            array(
4609
                'where' => array(
4610
                    'user_id = ? AND c_id = ? AND session_id = ? AND url_id = ?' => $params
4611
                )
4612
            ),
4613
            'first'
4614
        );
4615
        if (!empty($result)) {
4616
            return $result['vote'];
4617
        }
4618
        return false;
4619
    }
4620
4621
    /**
4622
     * @param int $course_id
4623
     * @param int $session_id
4624
     * @param int $url_id
4625
     * @return array
4626
     */
4627
    public static function get_course_ranking(
4628
        $course_id,
4629
        $session_id = 0,
4630
        $url_id = 0
4631
    ) {
4632
        $table_course_ranking = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
4633
4634
        $session_id = empty($session_id) ? api_get_session_id() : intval($session_id);
4635
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4636
        $now = api_get_utc_datetime();
4637
4638
        $params = array(
4639
            'c_id' => $course_id,
4640
            'session_id' => $session_id,
4641
            'url_id' => $url_id,
4642
            'creation_date' => $now,
4643
        );
4644
4645
        $result = Database::select(
4646
            'c_id, accesses, total_score, users',
4647
            $table_course_ranking,
4648
            array('where' => array('c_id = ? AND session_id = ? AND url_id = ?' => $params)),
4649
            'first'
4650
        );
4651
4652
        $point_average_in_percentage = 0;
4653
        $point_average_in_star = 0;
4654
        $users_who_voted = 0;
4655
4656
        if (!empty($result['users'])) {
4657
            $users_who_voted = $result['users'];
4658
            $point_average_in_percentage = round($result['total_score'] / $result['users'] * 100 / 5, 2);
4659
            $point_average_in_star = round($result['total_score'] / $result['users'], 1);
4660
        }
4661
4662
        $result['user_vote'] = false;
4663
        if (!api_is_anonymous()) {
4664
            $result['user_vote'] = self::get_user_course_vote(api_get_user_id(), $course_id, $session_id, $url_id);
4665
        }
4666
4667
        $result['point_average'] = $point_average_in_percentage;
4668
        $result['point_average_star'] = $point_average_in_star;
4669
        $result['users_who_voted'] = $users_who_voted;
4670
4671
        return $result;
4672
    }
4673
4674
    /**
4675
     *
4676
     * Updates the course ranking
4677
     * @param int   course id
4678
     * @param int   $session_id
4679
     * @param int    url id
4680
     * @param $points_to_add
4681
     * @param bool $add_access
4682
     * @param bool $add_user
4683
     * @return array
4684
     **/
4685
    public static function update_course_ranking(
4686
        $course_id = 0 ,
4687
        $session_id = 0,
4688
        $url_id = 0,
4689
        $points_to_add = null,
4690
        $add_access = true,
4691
        $add_user = true
4692
    ) {
4693
        // Course catalog stats modifications see #4191
4694
        $table_course_ranking = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
4695
        $now = api_get_utc_datetime();
4696
        $course_id = empty($course_id) ? api_get_course_int_id() : intval($course_id);
4697
        $session_id = empty($session_id) ? api_get_session_id() : intval($session_id);
4698
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4699
4700
        $params = array(
4701
            'c_id' => $course_id,
4702
            'session_id' => $session_id,
4703
            'url_id' => $url_id,
4704
            'creation_date' => $now,
4705
            'total_score' => 0,
4706
            'users' => 0
4707
        );
4708
4709
        $result = Database::select(
4710
            'id, accesses, total_score, users',
4711
            $table_course_ranking,
4712
            array('where' => array('c_id = ? AND session_id = ? AND url_id = ?' => $params)),
4713
            'first'
4714
        );
4715
4716
        // Problem here every time we load the courses/XXXX/index.php course home page we update the access
4717
        if (empty($result)) {
4718
            if ($add_access) {
4719
                $params['accesses'] = 1;
4720
            }
4721
            //The votes and users are empty
4722
            if (isset($points_to_add) && !empty($points_to_add)) {
4723
                $params['total_score'] = intval($points_to_add);
4724
            }
4725
            if ($add_user) {
4726
                $params['users'] = 1;
4727
            }
4728
            $result = Database::insert($table_course_ranking, $params);
4729
        } else {
4730
            $my_params = array();
4731
4732
            if ($add_access) {
4733
                $my_params['accesses'] = intval($result['accesses']) + 1;
4734
            }
4735
            if (isset($points_to_add) && !empty($points_to_add)) {
4736
                $my_params['total_score'] = $result['total_score'] + $points_to_add;
4737
            }
4738
            if ($add_user) {
4739
                $my_params['users'] = $result['users'] + 1;
4740
            }
4741
4742
            if (!empty($my_params)) {
4743
                $result = Database::update(
4744
                    $table_course_ranking,
4745
                    $my_params,
4746
                    array('c_id = ? AND session_id = ? AND url_id = ?' => $params)
4747
                );
4748
            }
4749
        }
4750
4751
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result also could return the type integer|false which is incompatible with the documented return type array.
Loading history...
4752
    }
4753
4754
    /**
4755
     * Add user vote to a course
4756
     *
4757
     * @param   int user id
4758
     * @param   int vote [1..5]
4759
     * @param   int course id
4760
     * @param   int session id
4761
     * @param   int url id (access_url_id)
4762
     * @return    false|string 'added', 'updated' or 'nothing'
4763
     */
4764
    public static function add_course_vote(
4765
        $user_id,
4766
        $vote,
4767
        $course_id,
4768
        $session_id = 0,
4769
        $url_id = 0
4770
    ) {
4771
        $table_user_course_vote = Database::get_main_table(TABLE_MAIN_USER_REL_COURSE_VOTE);
4772
        $course_id = empty($course_id) ? api_get_course_int_id() : intval($course_id);
4773
4774
        if (empty($course_id) || empty($user_id)) {
4775
            return false;
4776
        }
4777
4778
        if (!in_array($vote, array(1, 2, 3, 4, 5))) {
4779
            return false;
4780
        }
4781
4782
        $session_id = empty($session_id) ? api_get_session_id() : intval($session_id);
4783
        $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4784
        $vote = intval($vote);
4785
4786
        $params = array(
4787
            'user_id' => intval($user_id),
4788
            'c_id' => $course_id,
4789
            'session_id' => $session_id,
4790
            'url_id' => $url_id,
4791
            'vote' => $vote
4792
        );
4793
4794
        $action_done = 'nothing';
4795
        $result = Database::select(
4796
            'id, vote',
4797
            $table_user_course_vote,
4798
            array('where' => array('user_id = ? AND c_id = ? AND session_id = ? AND url_id = ?' => $params)),
4799
            'first'
4800
        );
4801
4802
        if (empty($result)) {
4803
            Database::insert($table_user_course_vote, $params);
4804
            $points_to_add = $vote;
4805
            $add_user = true;
4806
            $action_done = 'added';
4807
        } else {
4808
            $my_params = array('vote' => $vote);
4809
            $points_to_add = $vote - $result['vote'];
4810
            $add_user = false;
4811
4812
            Database::update(
4813
                $table_user_course_vote,
4814
                $my_params,
4815
                array('user_id = ? AND c_id = ? AND session_id = ? AND url_id = ?' => $params)
4816
            );
4817
            $action_done = 'updated';
4818
        }
4819
4820
        // Current points
4821
        if (!empty($points_to_add)) {
4822
            self::update_course_ranking(
4823
                $course_id,
4824
                $session_id,
4825
                $url_id,
4826
                $points_to_add,
4827
                false,
4828
                $add_user
4829
            );
4830
        }
4831
        return $action_done;
4832
    }
4833
4834
    /**
4835
     * Remove course ranking + user votes
4836
     *
4837
     * @param int $course_id
4838
     * @param int $session_id
4839
     * @param int $url_id
4840
     *
4841
     */
4842
    public static function remove_course_ranking($course_id, $session_id, $url_id = null)
4843
    {
4844
        $table_course_ranking = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
4845
        $table_user_course_vote = Database::get_main_table(TABLE_MAIN_USER_REL_COURSE_VOTE);
4846
4847
        if (!empty($course_id) && isset($session_id)) {
4848
            $url_id = empty($url_id) ? api_get_current_access_url_id() : intval($url_id);
4849
            $params = array(
4850
                'c_id' => $course_id,
4851
                'session_id' => $session_id,
4852
                'url_id' => $url_id,
4853
            );
4854
            Database::delete($table_course_ranking, array('c_id = ? AND session_id = ? AND url_id = ?' => $params));
4855
            Database::delete($table_user_course_vote, array('c_id = ? AND session_id = ? AND url_id = ?' => $params));
4856
        }
4857
    }
4858
4859
    /**
4860
     * Returns an array with the hottest courses
4861
     * @param   int $days number of days
4862
     * @param   int $limit number of hottest courses
4863
     * @return array
4864
     */
4865
    public static function return_hot_courses($days = 30, $limit = 6)
4866
    {
4867
        if (api_is_invitee()) {
4868
            return array();
4869
        }
4870
4871
        $limit = intval($limit);
4872
4873
        // Getting my courses
4874
        $my_course_list = self::get_courses_list_by_user_id(api_get_user_id());
4875
4876
        $my_course_code_list = array();
4877
        foreach ($my_course_list as $course) {
4878
            $my_course_code_list[$course['real_id']] = $course['real_id'];
4879
        }
4880
4881
        if (api_is_drh()) {
4882
            $courses = self::get_courses_followed_by_drh(api_get_user_id());
4883
            foreach ($courses as $course) {
4884
                $my_course_code_list[$course['real_id']] = $course['real_id'];
4885
            }
4886
        }
4887
4888
        $table_course_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
4889
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
4890
        $table_course_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
4891
4892
        //$table_course_access table uses the now() and interval ...
4893
        $now = api_get_utc_datetime();
4894
        $sql = "SELECT COUNT(course_access_id) course_count, a.c_id, visibility
4895
                FROM $table_course c
4896
                INNER JOIN $table_course_access a
4897
                ON (c.id = a.c_id)
4898
                INNER JOIN $table_course_url u
4899
                ON u.c_id = c.id
4900
                WHERE
4901
                    u.access_url_id = ".api_get_current_access_url_id()." AND
4902
                    login_course_date <= '$now' AND
4903
                    login_course_date > DATE_SUB('$now', INTERVAL $days DAY) AND
4904
                    visibility <> '".COURSE_VISIBILITY_CLOSED."' AND visibility <> '".COURSE_VISIBILITY_HIDDEN."'
4905
                GROUP BY a.c_id
4906
                ORDER BY course_count DESC
4907
                LIMIT $limit
4908
            ";
4909
4910
        $result = Database::query($sql);
4911
        $courses = array();
4912
4913
        if (Database::num_rows($result)) {
4914
            $courses = Database::store_result($result, 'ASSOC');
4915
            $courses = self::processHotCourseItem($courses, $my_course_code_list);
4916
        }
4917
4918
        return $courses;
4919
    }
4920
4921
    /**
4922
     * @param array $courses
4923
     * @param array $my_course_code_list
4924
     * @return mixed
4925
     */
4926
    public static function processHotCourseItem($courses, $my_course_code_list = array())
4927
    {
4928
        $hotCourses = [];
4929
        $ajax_url = api_get_path(WEB_AJAX_PATH).'course.ajax.php?a=add_course_vote';
4930
        $stok = Security::get_existing_token();
4931
        $user_id = api_get_user_id();
4932
4933
        foreach ($courses as $courseId) {
4934
            $course_info = api_get_course_info_by_id($courseId['c_id']);
4935
            $courseCode = $course_info['code'];
4936
            $categoryCode = !empty($course_info['categoryCode']) ? $course_info['categoryCode'] : "";
4937
            $my_course = $course_info;
4938
            $my_course['go_to_course_button'] = '';
4939
            $my_course['register_button'] = '';
4940
4941
            $access_link = self::get_access_link_by_user(
4942
                api_get_user_id(),
4943
                $course_info,
4944
                $my_course_code_list
4945
            );
4946
4947
            $userRegisteredInCourse = self::is_user_subscribed_in_course($user_id, $course_info['code']);
4948
            $userRegisteredInCourseAsTeacher = self::is_course_teacher($user_id, $course_info['code']);
4949
            $userRegistered = $userRegisteredInCourse && $userRegisteredInCourseAsTeacher;
4950
            $my_course['is_registered'] = $userRegistered;
4951
            $my_course['title_cut'] = cut($course_info['title'], 45);
4952
4953
4954
            //Course visibility
4955
            if ($access_link && in_array('register', $access_link)) {
4956
                $my_course['register_button'] = Display::url(
4957
                    get_lang('Subscribe').' '.
4958
                    Display::returnFontAwesomeIcon('sign-in'),
4959
                    api_get_path(WEB_COURSE_PATH).$course_info['path'].
4960
                     '/index.php?action=subscribe&sec_token='.$stok,
4961
                    array(
4962
                        'class' => 'btn btn-success btn-sm',
4963
                        'title' => get_lang('Subscribe'),
4964
                        'aria-label' => get_lang('Subscribe')
4965
                    )
4966
                );
4967
4968
            }
4969
4970
            if ($access_link && in_array('enter', $access_link) ||
4971
                $course_info['visibility'] == COURSE_VISIBILITY_OPEN_WORLD
4972
            ) {
4973
                $my_course['go_to_course_button'] = Display::url(
4974
                    get_lang('GoToCourse').' '.
4975
                    Display::returnFontAwesomeIcon('share'),
4976
                    api_get_path(WEB_COURSE_PATH).$course_info['path'].'/index.php',
4977
                    array(
4978
                        'class' => 'btn btn-default btn-sm',
4979
                        'title' => get_lang('GoToCourse'),
4980
                        'aria-label' => get_lang('GoToCourse')
4981
                    )
4982
                );
4983
4984
            }
4985
4986
            if ($access_link && in_array('unsubscribe', $access_link)) {
4987
                $my_course['unsubscribe_button'] = Display::url(
4988
                    get_lang('Unreg').' '.
4989
                    Display::returnFontAwesomeIcon('sign-out'),
4990
                    api_get_path(WEB_CODE_PATH).'auth/courses.php?action=unsubscribe&unsubscribe='.$courseCode
4991
                    . '&sec_token='.$stok.'&category_code='.$categoryCode,
4992
                    array(
4993
                        'class' => 'btn btn-danger btn-sm',
4994
                        'title' => get_lang('Unreg'),
4995
                        'aria-label' => get_lang('Unreg')
4996
                    )
4997
                );
4998
            }
4999
5000
            // start buycourse validation
5001
            // display the course price and buy button if the buycourses plugin is enabled and this course is configured
5002
            $plugin = BuyCoursesPlugin::create();
5003
            $isThisCourseInSale = $plugin->buyCoursesForGridCatalogValidator(
5004
                $course_info['real_id'],
5005
                BuyCoursesPlugin::PRODUCT_TYPE_COURSE
5006
            );
5007
            if ($isThisCourseInSale) {
5008
                // set the price label
5009
                $my_course['price'] = $isThisCourseInSale['html'];
5010
                // set the Buy button instead register.
5011
                if ($isThisCourseInSale['verificator'] && !empty($my_course['register_button'])) {
5012
                    $my_course['register_button'] = $plugin->returnBuyCourseButton(
5013
                        $course_info['real_id'],
5014
                        BuyCoursesPlugin::PRODUCT_TYPE_COURSE
5015
                    );
5016
                }
5017
            }
5018
            // end buycourse validation
5019
5020
            // Description
5021
            $my_course['description_button'] = self::returnDescriptionButton($course_info);
5022
            $my_course['teachers'] = self::getTeachersFromCourse($course_info['real_id'], true);
5023
            $point_info = self::get_course_ranking($course_info['real_id'], 0);
5024
            $my_course['rating_html'] = '';
5025
            if (api_get_configuration_value('hide_course_rating') === false) {
5026
                $my_course['rating_html'] = Display::return_rating_system(
5027
                    'star_'.$course_info['real_id'],
5028
                    $ajax_url.'&course_id='.$course_info['real_id'],
5029
                    $point_info
5030
                );
5031
            }
5032
            $hotCourses[] = $my_course;
5033
        }
5034
        return $hotCourses;
5035
    }
5036
5037
    /**
5038
     * @param int $limit
5039
     * @return array
5040
     */
5041
    public static function return_most_accessed_courses($limit = 5)
5042
    {
5043
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_COURSE_RANKING);
5044
        $params['url_id'] = api_get_current_access_url_id();
0 ignored issues
show
Comprehensibility Best Practice introduced by
$params was never initialized. Although not strictly required by PHP, it is generally a good practice to add $params = array(); before regardless.
Loading history...
5045
5046
        $result = Database::select(
5047
            'c_id, accesses, total_score, users',
5048
            $table,
5049
            array('where' => array('url_id = ?' => $params), 'order' => 'accesses DESC', 'limit' => $limit),
5050
            'all',
5051
            true
5052
        );
5053
5054
        return $result;
5055
    }
5056
5057
    /**
5058
     * Get courses count
5059
     * @param int $access_url_id Access URL ID (optional)
5060
     * @param int $visibility
5061
     *
5062
     * @return int Number of courses
5063
     */
5064
    public static function count_courses($access_url_id = null, $visibility = null)
5065
    {
5066
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
5067
        $table_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
5068
        $sql = "SELECT count(c.id) FROM $table_course c";
5069
        if (!empty($access_url_id) && $access_url_id == intval($access_url_id)) {
5070
            $sql .= ", $table_course_rel_access_url u
5071
                    WHERE c.id = u.c_id AND u.access_url_id = $access_url_id";
5072
            if (!empty($visibility)) {
5073
                $visibility = intval($visibility);
5074
                $sql .= " AND visibility = $visibility ";
5075
            }
5076
        } else {
5077
            if (!empty($visibility)) {
5078
                $visibility = intval($visibility);
5079
                $sql .= " WHERE visibility = $visibility ";
5080
            }
5081
        }
5082
5083
        $res = Database::query($sql);
5084
        $row = Database::fetch_row($res);
5085
5086
        return $row[0];
5087
    }
5088
5089
    /**
5090
     * Get active courses count.
5091
     * Active = all courses except the ones with hidden visibility.
5092
     *
5093
     * @param int $urlId Access URL ID (optional)
5094
     * @return int Number of courses
5095
     */
5096
    public static function countActiveCourses($urlId = null)
5097
    {
5098
        $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
5099
        $table_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
5100
        $sql = "SELECT count(id) FROM $table_course c";
5101
        if (!empty($urlId) && $urlId == intval($urlId)) {
5102
            $sql .= ", $table_course_rel_access_url u
5103
                    WHERE
5104
                        c.id = u.c_id AND
5105
                        u.access_url_id = $urlId AND
5106
                        visibility <> ".COURSE_VISIBILITY_HIDDEN;
5107
        } else {
5108
            $sql .= " WHERE visibility <> ".COURSE_VISIBILITY_HIDDEN;
5109
        }
5110
        $res = Database::query($sql);
5111
        $row = Database::fetch_row($res);
5112
        return $row[0];
5113
    }
5114
5115
    /**
5116
     * Returns the SQL conditions to filter course only visible by the user in the catalogue
5117
     *
5118
     * @param string $courseTableAlias Alias of the course table
5119
     * @param bool $hideClosed Whether to hide closed and hidden courses
5120
     * @return string SQL conditions
5121
     */
5122
    public static function getCourseVisibilitySQLCondition(
5123
        $courseTableAlias,
5124
        $hideClosed = false
5125
    ) {
5126
        $visibilityCondition = '';
5127
        $hidePrivate = api_get_setting('course_catalog_hide_private');
5128
        if ($hidePrivate === 'true') {
5129
            $visibilityCondition .= ' AND '.$courseTableAlias.'.visibility <> '.COURSE_VISIBILITY_REGISTERED;
5130
        }
5131
        if ($hideClosed) {
5132
            $visibilityCondition .= ' AND '.$courseTableAlias.'.visibility NOT IN ('.COURSE_VISIBILITY_CLOSED.','.COURSE_VISIBILITY_HIDDEN.')';
5133
        }
5134
5135
        // Check if course have users allowed to see it in the catalogue, then show only if current user is allowed to see it
5136
        $currentUserId = api_get_user_id();
5137
        $restrictedCourses = self::getCatalogueCourseList(true);
5138
        $allowedCoursesToCurrentUser = self::getCatalogueCourseList(true, $currentUserId);
5139
        if (!empty($restrictedCourses)) {
5140
            $visibilityCondition .= ' AND ('.$courseTableAlias.'.code NOT IN ("'.implode('","', $restrictedCourses).'")';
5141
            $visibilityCondition .= ' OR '.$courseTableAlias.'.code IN ("'.implode('","', $allowedCoursesToCurrentUser).'"))';
5142
        }
5143
5144
        // Check if course have users denied to see it in the catalogue, then show only if current user is not denied to see it
5145
        $restrictedCourses = self::getCatalogueCourseList(false);
5146
        $notAllowedCoursesToCurrentUser = self::getCatalogueCourseList(false, $currentUserId);
5147
        if (!empty($restrictedCourses)) {
5148
            $visibilityCondition .= ' AND ('.$courseTableAlias.'.code NOT IN ("'.implode('","', $restrictedCourses).'")';
5149
            $visibilityCondition .= ' OR '.$courseTableAlias.'.code NOT IN ("'.implode('","', $notAllowedCoursesToCurrentUser).'"))';
5150
        }
5151
5152
        return $visibilityCondition;
5153
    }
5154
5155
    /**
5156
     * Get available le courses count
5157
     * @param int $accessUrlId (optional)
5158
     * @return int Number of courses
5159
     */
5160
    public static function countAvailableCourses($accessUrlId = 1)
5161
    {
5162
        $tableCourse = Database::get_main_table(TABLE_MAIN_COURSE);
5163
        $tableCourseRelAccessUrl = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
5164
        $specialCourseList = self::get_special_course_list();
5165
5166
        $withoutSpecialCourses = '';
5167
        if (!empty($specialCourseList)) {
5168
            $withoutSpecialCourses = ' AND c.id NOT IN ("'.implode('","', $specialCourseList).'")';
5169
        }
5170
5171
        $visibilityCondition = self::getCourseVisibilitySQLCondition('c', true);
5172
5173
        $accessUrlId = (int) $accessUrlId;
5174
        if (empty($accessUrlId)) {
5175
            $accessUrlId = 1;
5176
        }
5177
5178
        $sql = "SELECT count(c.id) 
5179
                FROM $tableCourse c 
5180
                INNER JOIN $tableCourseRelAccessUrl u
5181
                ON (c.id = u.c_id)
5182
                WHERE
5183
                    u.access_url_id = $accessUrlId AND
5184
                    c.visibility != 0 AND
5185
                    c.visibility != 4
5186
                    $withoutSpecialCourses
5187
                    $visibilityCondition
5188
                ";
5189
5190
        $res = Database::query($sql);
5191
        $row = Database::fetch_row($res);
5192
5193
        return $row[0];
5194
    }
5195
5196
    /**
5197
     * Return a link to go to the course, validating the visibility of the
5198
     * course and the user status
5199
     * @param int $uid User ID
5200
     * @param array Course details array
5201
     * @param array  List of courses to which the user is subscribed (if not provided, will be generated)
5202
     *
5203
     * @return mixed 'enter' for a link to go to the course or 'register' for a link to subscribe, or false if no access
5204
     */
5205
    static function get_access_link_by_user($uid, $course, $user_courses = [])
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
5206
    {
5207
        if (empty($uid) || empty($course)) {
5208
            return false;
5209
        }
5210
5211
        if (empty($user_courses)) {
5212
            // get the array of courses to which the user is subscribed
5213
            $user_courses = self::get_courses_list_by_user_id($uid);
5214
            foreach ($user_courses as $k => $v) {
5215
                $user_courses[$k] = $v['real_id'];
5216
            }
5217
        }
5218
5219
        if (!isset($course['real_id']) && empty($course['real_id'])) {
5220
            $course = api_get_course_info($course['code']);
5221
        }
5222
5223
        if ($course['visibility'] == COURSE_VISIBILITY_HIDDEN) {
5224
            return array();
5225
        }
5226
5227
        $is_admin = api_is_platform_admin_by_id($uid);
5228
        $options = array();
5229
        // Register button
5230
        if (!api_is_anonymous($uid) &&
5231
            (
5232
            ($course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD || $course['visibility'] == COURSE_VISIBILITY_OPEN_PLATFORM)
5233
                //$course['visibility'] == COURSE_VISIBILITY_REGISTERED && $course['subscribe'] == SUBSCRIBE_ALLOWED
5234
            ) &&
5235
            $course['subscribe'] == SUBSCRIBE_ALLOWED &&
5236
            (!in_array($course['real_id'], $user_courses) || empty($user_courses))
5237
        ) {
5238
            $options[] = 'register';
5239
        }
5240
5241
        // Go To Course button (only if admin, if course public or if student already subscribed)
5242
        if ($is_admin ||
5243
            $course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD && empty($course['registration_code']) ||
5244
            (api_user_is_login($uid) && $course['visibility'] == COURSE_VISIBILITY_OPEN_PLATFORM && empty($course['registration_code'])) ||
5245
            (in_array($course['real_id'], $user_courses) && $course['visibility'] != COURSE_VISIBILITY_CLOSED)
5246
        ) {
5247
            $options[] = 'enter';
5248
        }
5249
5250
        if ($is_admin ||
5251
            $course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD && empty($course['registration_code']) ||
5252
            (api_user_is_login($uid) && $course['visibility'] == COURSE_VISIBILITY_OPEN_PLATFORM && empty($course['registration_code'])) ||
5253
            (in_array($course['real_id'], $user_courses) && $course['visibility'] != COURSE_VISIBILITY_CLOSED)
5254
        ) {
5255
            $options[] = 'enter';
5256
        }
5257
5258
        if ($course['visibility'] != COURSE_VISIBILITY_HIDDEN &&
5259
            empty($course['registration_code']) &&
5260
            $course['unsubscribe'] == UNSUBSCRIBE_ALLOWED &&
5261
            api_user_is_login($uid) &&
5262
            in_array($course['real_id'], $user_courses)
5263
        ) {
5264
            $options[] = 'unsubscribe';
5265
        }
5266
5267
        return $options;
5268
    }
5269
5270
    /**
5271
     * @param array $courseInfo
5272
     * @param array $teachers
5273
     * @param bool $deleteTeachersNotInList
5274
     * @param bool $editTeacherInSessions
5275
     * @param bool $deleteSessionTeacherNotInList
5276
     * @param array $teacherBackup
5277
     * @param Monolog\Logger $logger
5278
     *
5279
     * @return false|null
5280
     */
5281
    public static function updateTeachers(
5282
        $courseInfo,
5283
        $teachers,
5284
        $deleteTeachersNotInList = true,
5285
        $editTeacherInSessions = false,
5286
        $deleteSessionTeacherNotInList = false,
5287
        $teacherBackup = array(),
5288
        $logger = null
5289
    ) {
5290
        if (!is_array($teachers)) {
5291
            $teachers = array($teachers);
5292
        }
5293
5294
        if (empty($courseInfo) || !isset($courseInfo['real_id'])) {
5295
            return false;
5296
        }
5297
5298
        $teachers = array_filter($teachers);
5299
        $courseId = $courseInfo['real_id'];
5300
        $course_code = $courseInfo['code'];
5301
5302
        $course_user_table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5303
        $alreadyAddedTeachers = self::get_teacher_list_from_course_code($course_code);
5304
5305
        if ($deleteTeachersNotInList) {
5306
            // Delete only teacher relations that doesn't match the selected teachers
5307
            $cond = null;
5308
            if (count($teachers) > 0) {
5309
                foreach ($teachers as $key) {
5310
                    $key = Database::escape_string($key);
5311
                    $cond .= " AND user_id <> '".$key."'";
5312
                }
5313
            }
5314
5315
            // Recover user categories
5316
            $sql = 'SELECT * FROM '.$course_user_table.'
5317
                    WHERE c_id ="' . $courseId.'" AND status="1" AND relation_type = 0 '.$cond;
5318
            $result = Database::query($sql);
5319
            if (Database::num_rows($result)) {
5320
                $teachersToDelete = Database::store_result($result, 'ASSOC');
5321
                foreach ($teachersToDelete as $data) {
5322
                    $userId = $data['user_id'];
5323
                    $teacherBackup[$userId][$course_code] = $data;
5324
                }
5325
            }
5326
5327
            $sql = 'DELETE FROM '.$course_user_table.'
5328
                    WHERE c_id ="' . $courseId.'" AND status="1" AND relation_type = 0 '.$cond;
5329
5330
            Database::query($sql);
5331
        }
5332
5333
        if (count($teachers) > 0) {
5334
            foreach ($teachers as $userId) {
5335
                $userId = intval($userId);
5336
                // We check if the teacher is already subscribed in this course
5337
                $sql = 'SELECT 1 FROM '.$course_user_table.'
5338
                        WHERE user_id = "' . $userId.'" AND c_id = "'.$courseId.'" ';
5339
                $result = Database::query($sql);
5340
                if (Database::num_rows($result)) {
5341
                    $sql = 'UPDATE '.$course_user_table.' 
5342
                            SET status = "1"
5343
                            WHERE c_id = "' . $courseId.'" AND user_id = "'.$userId.'"  ';
5344
                } else {
5345
                    $userCourseCategory = '0';
5346
                    if (isset($teacherBackup[$userId]) &&
5347
                        isset($teacherBackup[$userId][$course_code])
5348
                    ) {
5349
                        $courseUserData = $teacherBackup[$userId][$course_code];
5350
                        $userCourseCategory = $courseUserData['user_course_cat'];
5351
                        if ($logger) {
5352
                            $logger->addInfo("Recovering user_course_cat: $userCourseCategory");
5353
                        }
5354
                    }
5355
5356
                    $sql = "INSERT INTO $course_user_table SET
5357
                            c_id = $courseId,
5358
                            user_id = $userId,
5359
                            status = '1',
5360
                            is_tutor = '0',
5361
                            sort = '0',
5362
                            relation_type = '0',
5363
                            user_course_cat = '$userCourseCategory'
5364
                    ";
5365
                }
5366
                Database::query($sql);
5367
            }
5368
        }
5369
5370
        if ($editTeacherInSessions) {
5371
            $sessions = SessionManager::get_session_by_course($courseId);
5372
            if (!empty($sessions)) {
5373
                if ($logger) {
5374
                    $logger->addInfo("Edit teachers in sessions");
5375
                }
5376
                foreach ($sessions as $session) {
5377
                    $sessionId = $session['id'];
5378
                    // Remove old and add new
5379
                    if ($deleteSessionTeacherNotInList) {
5380
                        foreach ($teachers as $userId) {
5381
                            if ($logger) {
5382
                                $logger->addInfo("Set coach #$userId in session #$sessionId of course #$courseId ");
5383
                            }
5384
                            SessionManager::set_coach_to_course_session(
5385
                                $userId,
5386
                                $sessionId,
5387
                                $courseId
5388
                            );
5389
                        }
5390
5391
                        $teachersToDelete = array();
5392
                        if (!empty($alreadyAddedTeachers)) {
5393
                            $teachersToDelete = array_diff(array_keys($alreadyAddedTeachers), $teachers);
5394
                        }
5395
5396
                        if (!empty($teachersToDelete)) {
5397
                            foreach ($teachersToDelete as $userId) {
5398
                                if ($logger) {
5399
                                    $logger->addInfo("Delete coach #$userId in session #$sessionId of course #$courseId ");
5400
                                }
5401
                                SessionManager::set_coach_to_course_session(
5402
                                    $userId,
5403
                                    $sessionId,
5404
                                    $courseId,
5405
                                    true
5406
                                );
5407
                            }
5408
                        }
5409
                    } else {
5410
                        // Add new teachers only
5411
                        foreach ($teachers as $userId) {
5412
                            if ($logger) {
5413
                                $logger->addInfo("Add coach #$userId in session #$sessionId of course #$courseId ");
5414
                            }
5415
                            SessionManager::set_coach_to_course_session(
5416
                                $userId,
5417
                                $sessionId,
5418
                                $courseId
5419
                            );
5420
                        }
5421
                    }
5422
                }
5423
            }
5424
        }
5425
    }
5426
5427
    /**
5428
     * Course available settings variables see c_course_setting table
5429
     * @param AppPlugin $appPlugin
5430
     * @return array
5431
     */
5432
    public static function getCourseSettingVariables(AppPlugin $appPlugin)
5433
    {
5434
        $pluginCourseSettings = $appPlugin->getAllPluginCourseSettings();
5435
        $courseSettings = array(
5436
            // Get allow_learning_path_theme from table
5437
            'allow_learning_path_theme',
5438
            // Get allow_open_chat_window from table
5439
            'allow_open_chat_window',
5440
            'allow_public_certificates',
5441
            // Get allow_user_edit_agenda from table
5442
            'allow_user_edit_agenda',
5443
            // Get allow_user_edit_announcement from table
5444
            'allow_user_edit_announcement',
5445
            // Get allow_user_image_forum from table
5446
            'allow_user_image_forum',
5447
            //Get allow show user list
5448
            'allow_user_view_user_list',
5449
            // Get course_theme from table
5450
            'course_theme',
5451
            //Get allow show user list
5452
            'display_info_advance_inside_homecourse',
5453
            'documents_default_visibility',
5454
            // Get send_mail_setting (work)from table
5455
            'email_alert_manager_on_new_doc',
5456
            // Get send_mail_setting (work)from table
5457
            'email_alert_manager_on_new_quiz',
5458
            // Get send_mail_setting (dropbox) from table
5459
            'email_alert_on_new_doc_dropbox',
5460
            'email_alert_students_on_new_homework',
5461
            // Get send_mail_setting (auth)from table
5462
            'email_alert_to_teacher_on_new_user_in_course',
5463
            'enable_lp_auto_launch',
5464
            'pdf_export_watermark_text',
5465
            'show_system_folders',
5466
            'exercise_invisible_in_session',
5467
            'enable_forum_auto_launch',
5468
            'show_course_in_user_language',
5469
            'email_to_teachers_on_new_work_feedback'
5470
        );
5471
5472
        if (!empty(ExerciseLib::getScoreModels())) {
5473
            $courseSettings[] = 'score_model_id';
5474
        }
5475
5476
        $allowLPReturnLink = api_get_setting('allow_lp_return_link');
5477
        if ($allowLPReturnLink === 'true') {
5478
            $courseSettings[] = 'lp_return_link';
5479
        }
5480
5481
        if (!empty($pluginCourseSettings)) {
5482
            $courseSettings = array_merge(
5483
                $courseSettings,
5484
                $pluginCourseSettings
5485
            );
5486
        }
5487
5488
        return $courseSettings;
5489
    }
5490
5491
    /**
5492
     * @param AppPlugin $appPlugin
5493
     * @param string $variable
5494
     * @param string|array $value
5495
     * @param int $courseId
5496
     * @return bool
5497
     */
5498
    public static function saveCourseConfigurationSetting(AppPlugin $appPlugin, $variable, $value, $courseId)
5499
    {
5500
        $settingList = self::getCourseSettingVariables($appPlugin);
5501
5502
        if (!in_array($variable, $settingList)) {
5503
5504
            return false;
5505
        }
5506
5507
        $courseSettingTable = Database::get_course_table(TABLE_COURSE_SETTING);
5508
5509
        if (is_array($value)) {
5510
            $value = implode(',', $value);
5511
        }
5512
5513
        if (self::hasCourseSetting($variable, $courseId)) {
5514
            // Update
5515
            Database::update(
5516
                $courseSettingTable,
5517
                array('value' => $value),
5518
                array('variable = ? AND c_id = ?' => array($variable, $courseId))
5519
            );
5520
        } else {
5521
            // Create
5522
            Database::insert(
5523
                $courseSettingTable,
5524
                [
5525
                    'title' => $variable,
5526
                    'value' => $value,
5527
                    'c_id' => $courseId,
5528
                    'variable' => $variable,
5529
                ]
5530
            );
5531
        }
5532
        return true;
5533
    }
5534
5535
    /**
5536
     * Check if course setting exists
5537
     * @param string $variable
5538
     * @param int $courseId
5539
     * @return bool
5540
     */
5541
    public static function hasCourseSetting($variable, $courseId)
5542
    {
5543
        $courseSetting = Database::get_course_table(TABLE_COURSE_SETTING);
5544
        $courseId = intval($courseId);
5545
        $variable = Database::escape_string($variable);
5546
        $sql = "SELECT variable FROM $courseSetting
5547
                WHERE c_id = $courseId AND variable = '$variable'";
5548
        $result = Database::query($sql);
5549
5550
        return Database::num_rows($result) > 0;
5551
    }
5552
5553
    /**
5554
     * Get information from the track_e_course_access table
5555
     * @param int $sessionId
5556
     * @param int $userId
5557
     * @param int $limit
5558
     * @return array
5559
     */
5560
    public static function getCourseAccessPerSessionAndUser($sessionId, $userId, $limit = 0)
5561
    {
5562
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
5563
5564
        $sessionId = intval($sessionId);
5565
        $userId = intval($userId);
5566
5567
        $sql = "SELECT * FROM $table
5568
                WHERE session_id = $sessionId AND user_id = $userId";
5569
5570
        if (!empty($limit)) {
5571
            $limit = intval($limit);
5572
            $sql .= " LIMIT $limit";
5573
        }
5574
        $result = Database::query($sql);
5575
5576
        return Database::store_result($result);
5577
    }
5578
5579
    /**
5580
     * Get information from the track_e_course_access table
5581
     * @param int $courseId
5582
     * @param int $sessionId
5583
     * @param string $startDate
5584
     * @param string $endDate
5585
     * @return array
5586
     */
5587
    public static function getCourseAccessPerCourseAndSession(
5588
        $courseId,
5589
        $sessionId,
5590
        $startDate,
5591
        $endDate
5592
    ) {
5593
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
5594
        $courseId = intval($courseId);
5595
        $sessionId = intval($sessionId);
5596
        $startDate = Database::escape_string($startDate);
5597
        $endDate = Database::escape_string($endDate);
5598
5599
        $sql = "SELECT * FROM $table
5600
                WHERE
5601
                    c_id = $courseId AND
5602
                    session_id = $sessionId AND
5603
                    login_course_date BETWEEN '$startDate' AND '$endDate'
5604
                ";
5605
5606
        $result = Database::query($sql);
5607
5608
        return Database::store_result($result);
5609
    }
5610
5611
    /**
5612
     * Get login information from the track_e_course_access table, for any
5613
     * course in the given session
5614
     * @param int $sessionId
5615
     * @param int $userId
5616
     * @return array
5617
     */
5618
    public static function getFirstCourseAccessPerSessionAndUser($sessionId, $userId)
5619
    {
5620
        $sessionId = intval($sessionId);
5621
        $userId = intval($userId);
5622
5623
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
5624
        $sql = "SELECT * FROM $table
5625
                WHERE session_id = $sessionId AND user_id = $userId
5626
                ORDER BY login_course_date ASC
5627
                LIMIT 1";
5628
5629
        $result = Database::query($sql);
5630
        $courseAccess = array();
5631
        if (Database::num_rows($result)) {
5632
            $courseAccess = Database::fetch_array($result, 'ASSOC');
5633
        }
5634
        return $courseAccess;
5635
    }
5636
5637
    /**
5638
     * @param int $courseId
5639
     * @param int $sessionId
5640
     * @param bool $getAllSessions
5641
     * @return mixed
5642
     */
5643
    public static function getCountForum(
5644
        $courseId,
5645
        $sessionId = 0,
5646
        $getAllSessions = false
5647
    ) {
5648
        $forum = Database::get_course_table(TABLE_FORUM);
5649
        if ($getAllSessions) {
5650
            $sql = "SELECT count(*) as count
5651
                    FROM $forum f
5652
                    WHERE f.c_id = %s";
5653
        } else {
5654
            $sql = "SELECT count(*) as count
5655
                    FROM $forum f
5656
                    WHERE f.c_id = %s and f.session_id = %s";
5657
        }
5658
5659
        $sql = sprintf($sql, intval($courseId), intval($sessionId));
5660
        $result = Database::query($sql);
5661
        $row = Database::fetch_array($result);
5662
5663
        return $row['count'];
5664
    }
5665
5666
    /**
5667
     * @param int $userId
5668
     * @param int $courseId
5669
     * @param int $sessionId
5670
     * @return mixed
5671
     */
5672
    public static function getCountPostInForumPerUser(
5673
        $userId,
5674
        $courseId,
5675
        $sessionId = 0
5676
    ) {
5677
        $forum = Database::get_course_table(TABLE_FORUM);
5678
        $forum_post = Database::get_course_table(TABLE_FORUM_POST);
5679
5680
        $sql = "SELECT count(distinct post_id) as count
5681
                FROM $forum_post p
5682
                INNER JOIN $forum f
5683
                ON f.forum_id = p.forum_id AND f.c_id = p.c_id
5684
                WHERE p.poster_id = %s and f.session_id = %s and p.c_id = %s";
5685
5686
        $sql = sprintf(
5687
            $sql,
5688
            intval($userId),
5689
            intval($sessionId),
5690
            intval($courseId)
5691
        );
5692
5693
        $result = Database::query($sql);
5694
        $row = Database::fetch_array($result);
5695
        return $row['count'];
5696
    }
5697
5698
    /**
5699
     * @param int $userId
5700
     * @param int $courseId
5701
     * @param int $sessionId
5702
     * @return mixed
5703
     */
5704
    public static function getCountForumPerUser(
5705
        $userId,
5706
        $courseId,
5707
        $sessionId = 0
5708
    ) {
5709
        $forum = Database::get_course_table(TABLE_FORUM);
5710
        $forum_post = Database::get_course_table(TABLE_FORUM_POST);
5711
5712
        $sql = "SELECT count(distinct f.forum_id) as count
5713
                FROM $forum_post p
5714
                INNER JOIN $forum f
5715
                ON f.forum_id = p.forum_id AND f.c_id = p.c_id
5716
                WHERE p.poster_id = %s and f.session_id = %s and p.c_id = %s";
5717
5718
        $sql = sprintf(
5719
            $sql,
5720
            intval($userId),
5721
            intval($sessionId),
5722
            intval($courseId)
5723
        );
5724
5725
        $result = Database::query($sql);
5726
        $row = Database::fetch_array($result);
5727
        return $row['count'];
5728
    }
5729
5730
    /**
5731
     * Returns the course name from a given code
5732
     * @param string $code
5733
     * @return string
5734
     */
5735
    public static function getCourseNameFromCode($code)
5736
    {
5737
        $tbl_main_categories = Database::get_main_table(TABLE_MAIN_COURSE);
5738
        $sql = 'SELECT title
5739
                FROM ' . $tbl_main_categories.'
5740
                WHERE code = "' . Database::escape_string($code).'"';
5741
        $result = Database::query($sql);
5742
        if ($col = Database::fetch_array($result)) {
5743
            return $col['title'];
5744
        }
5745
    }
5746
5747
    /**
5748
     * Generates a course code from a course title
5749
     * @todo Such a function might be useful in other places too. It might be moved in the CourseManager class.
5750
     * @todo the function might be upgraded for avoiding code duplications (currently,
5751
     * it might suggest a code that is already in use)
5752
     * @param string $title A course title
5753
     * @return string A proposed course code
5754
     * +
5755
     * @assert (null,null) === false
5756
     * @assert ('ABC_DEF', null) === 'ABCDEF'
5757
     * @assert ('ABC09*^[%A', null) === 'ABC09A'
5758
     */
5759
    public static function generate_course_code($title)
5760
    {
5761
        return substr(
5762
            preg_replace('/[^A-Z0-9]/', '', strtoupper(api_replace_dangerous_char($title))),
5763
            0,
5764
            self::MAX_COURSE_LENGTH_CODE
5765
        );
5766
    }
5767
5768
    /**
5769
     * @param $courseId
5770
     * @return array
5771
     */
5772
    public static function getCourseSettings($courseId)
5773
    {
5774
        $settingTable = Database::get_course_table(TABLE_COURSE_SETTING);
5775
        $courseId = intval($courseId);
5776
        $sql = "SELECT * FROM $settingTable WHERE c_id = $courseId";
5777
        $result = Database::query($sql);
5778
        $settings = array();
5779
        if (Database::num_rows($result)) {
5780
            while ($row = Database::fetch_array($result, 'ASSOC')) {
5781
                $settings[$row['variable']] = $row;
5782
            }
5783
        }
5784
        return $settings;
5785
    }
5786
5787
    /**
5788
     * this function gets all the users of the course,
5789
     * including users from linked courses
5790
     * @param $filterByActive
5791
     *
5792
     * @return array
5793
     */
5794
    public static function getCourseUsers($filterByActive = null)
5795
    {
5796
        // This would return only the users from real courses:
5797
        $userList = self::get_user_list_from_course_code(
5798
            api_get_course_id(),
5799
            api_get_session_id(),
5800
            null,
5801
            null,
5802
            null,
5803
            null,
5804
            false,
5805
            false,
5806
            [],
5807
            [],
5808
            [],
5809
            $filterByActive
5810
        );
5811
5812
        return $userList;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $userList also could return the type integer which is incompatible with the documented return type array.
Loading history...
5813
    }
5814
5815
    /**
5816
     * this function gets all the groups of the course,
5817
     * not including linked courses
5818
     */
5819
    public static function getCourseGroups()
5820
    {
5821
        $session_id = api_get_session_id();
5822
        if ($session_id != 0) {
5823
            $new_group_list = self::get_group_list_of_course(
5824
                api_get_course_id(),
5825
                $session_id,
5826
                1
5827
            );
5828
        } else {
5829
            $new_group_list = self::get_group_list_of_course(
5830
                api_get_course_id(),
5831
                0,
5832
                1
5833
            );
5834
        }
5835
5836
        return $new_group_list;
5837
    }
5838
5839
    /**
5840
     * @param FormValidator $form
5841
     * @param array $to_already_selected
5842
     *
5843
     * @return HTML_QuickForm_element
5844
     */
5845
    public static function addUserGroupMultiSelect(&$form, $to_already_selected)
5846
    {
5847
        $userList = self::getCourseUsers(true);
5848
        $group_list = self::getCourseGroups();
5849
        $array = self::buildSelectOptions(
5850
            $group_list,
5851
            $userList,
5852
            $to_already_selected
5853
        );
5854
5855
        $result = array();
5856
        foreach ($array as $content) {
5857
            $result[$content['value']] = $content['content'];
5858
        }
5859
5860
        return $form->addElement(
5861
            'advmultiselect',
5862
            'users',
5863
            get_lang('Users'),
5864
            $result,
5865
            array('select_all_checkbox' => true)
5866
        );
5867
    }
5868
5869
    /**
5870
     * This function separates the users from the groups
5871
     * users have a value USER:XXX (with XXX the groups id have a value
5872
     *  GROUP:YYY (with YYY the group id)
5873
     * @param  array $to Array of strings that define the type and id of each destination
5874
     * @return array Array of groups and users (each an array of IDs)
5875
     */
5876
    public static function separateUsersGroups($to)
5877
    {
5878
        $groupList = array();
5879
        $userList = array();
5880
5881
        foreach ($to as $to_item) {
5882
            if (!empty($to_item)) {
5883
                $parts = explode(':', $to_item);
5884
                $type = isset($parts[0]) ? $parts[0] : '';
5885
                $id = isset($parts[1]) ? $parts[1] : '';
5886
5887
                switch ($type) {
5888
                    case 'GROUP':
5889
                        $groupList[] = intval($id);
5890
                        break;
5891
                    case 'USER':
5892
                        $userList[] = intval($id);
5893
                        break;
5894
                }
5895
            }
5896
        }
5897
5898
        $send_to['groups'] = $groupList;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$send_to was never initialized. Although not strictly required by PHP, it is generally a good practice to add $send_to = array(); before regardless.
Loading history...
5899
        $send_to['users'] = $userList;
5900
5901
        return $send_to;
5902
    }
5903
5904
    /**
5905
     * Shows the form for sending a message to a specific group or user.
5906
     * @param FormValidator $form
5907
     * @param array $groupInfo
5908
     * @param array $to
5909
     *
5910
     * @return HTML_QuickForm_element
5911
     */
5912
    public static function addGroupMultiSelect($form, $groupInfo, $to = [])
5913
    {
5914
        $group_users = GroupManager::get_subscribed_users($groupInfo);
5915
        $array = self::buildSelectOptions(null, $group_users, $to);
5916
5917
        $result = array();
5918
        foreach ($array as $content) {
5919
            $result[$content['value']] = $content['content'];
5920
        }
5921
5922
        return $form->addElement('advmultiselect', 'users', get_lang('Users'), $result);
5923
    }
5924
5925
    /**
5926
     * this function shows the form for sending a message to a specific group or user.
5927
     * @param array $group_list
5928
     * @param array $userList
5929
     * @param array $to_already_selected
5930
     * @return array
5931
     */
5932
    public static function buildSelectOptions(
5933
        $group_list = array(),
5934
        $userList = array(),
5935
        $to_already_selected = array()
5936
    ) {
5937
        if (empty($to_already_selected)) {
5938
            $to_already_selected = array();
5939
        }
5940
5941
        $result = array();
5942
        // adding the groups to the select form
5943
        if ($group_list) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $group_list of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
5944
            foreach ($group_list as $this_group) {
5945
                if (is_array($to_already_selected)) {
5946
                    if (!in_array(
5947
                        "GROUP:".$this_group['id'],
5948
                        $to_already_selected
5949
                    )
5950
                    ) { // $to_already_selected is the array containing the groups (and users) that are already selected
5951
                        $user_label = ($this_group['userNb'] > 0) ? get_lang('Users') : get_lang('LowerCaseUser');
5952
                        $user_disabled = ($this_group['userNb'] > 0) ? "" : "disabled=disabled";
5953
                        $result[] = array(
5954
                            'disabled' => $user_disabled,
5955
                            'value' => "GROUP:".$this_group['id'],
5956
                            // The space before "G" is needed in order to advmultiselect.php js puts groups first
5957
                            'content' => " G: ".$this_group['name']." - ".$this_group['userNb']." ".$user_label
5958
                        );
5959
                    }
5960
                }
5961
            }
5962
        }
5963
5964
        // adding the individual users to the select form
5965
        if ($userList) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $userList of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
5966
            foreach ($userList as $user) {
5967
                if (is_array($to_already_selected)) {
5968
                    if (!in_array(
5969
                        "USER:".$user['user_id'],
5970
                        $to_already_selected
5971
                    )
5972
                    ) { // $to_already_selected is the array containing the users (and groups) that are already selected
5973
5974
                        $result[] = array(
5975
                            'value' => "USER:".$user['user_id'],
5976
                            'content' => api_get_person_name($user['firstname'], $user['lastname'])
5977
                        );
5978
                    }
5979
                }
5980
            }
5981
        }
5982
5983
        return $result;
5984
    }
5985
5986
    /**
5987
     * @return array a list (array) of all courses.
5988
     */
5989
    public static function get_course_list()
5990
    {
5991
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
5992
        return Database::store_result(Database::query("SELECT *, id as real_id FROM $table"));
5993
    }
5994
5995
    /**
5996
     * Returns course code from a given gradebook category's id
5997
     * @param int  Category ID
5998
     * @return string  Course code
5999
     */
6000
    public static function get_course_by_category($category_id)
6001
    {
6002
        $category_id = intval($category_id);
6003
        $info = Database::fetch_array(
6004
            Database::query('SELECT course_code FROM '.Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY).'
6005
            WHERE id=' . $category_id), 'ASSOC'
6006
        );
6007
        return $info ? $info['course_code'] : false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $info ? $info['course_code'] : false could also return false which is incompatible with the documented return type string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
6008
    }
6009
6010
    /**
6011
     * This function gets all the courses that are not in a session
6012
     * @param date Start date
6013
     * @param date End date
6014
     * @param   bool    $includeClosed Whether to include closed and hidden courses
6015
     * @return array Not-in-session courses
6016
     */
6017
    public static function getCoursesWithoutSession(
6018
        $startDate = null,
6019
        $endDate = null,
6020
        $includeClosed = false
6021
    ) {
6022
        $dateConditional = ($startDate && $endDate) ?
6023
            " WHERE session_id IN (SELECT id FROM ".Database::get_main_table(TABLE_MAIN_SESSION).
6024
            " WHERE access_start_date = '$startDate' AND access_end_date = '$endDate')" : null;
6025
        $visibility = ($includeClosed ? '' : 'visibility NOT IN (0, 4) AND ');
6026
6027
        $sql = "SELECT id, code, title
6028
                FROM ".Database::get_main_table(TABLE_MAIN_COURSE)."
6029
                WHERE $visibility code NOT IN (
6030
                    SELECT DISTINCT course_code 
6031
                    FROM ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE).$dateConditional."
6032
                )
6033
                ORDER BY id";
6034
6035
        $result = Database::query($sql);
6036
        $courses = array();
6037
        while ($row = Database::fetch_array($result)) {
6038
            $courses[] = $row;
6039
        }
6040
        return $courses;
6041
    }
6042
6043
    /**
6044
     * Get list of courses based on users of a group for a group admin
6045
     * @param int $userId The user id
6046
     * @return array
6047
     */
6048
    public static function getCoursesFollowedByGroupAdmin($userId)
6049
    {
6050
        $coursesList = [];
6051
        $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
6052
        $courseUserTable = Database::get_main_table(TABLE_MAIN_COURSE_USER);
6053
        $userGroup = new UserGroup();
6054
        $userIdList = $userGroup->getGroupUsersByUser($userId);
6055
6056
        if (empty($userIdList)) {
6057
            return [];
6058
        }
6059
6060
        $sql = "SELECT DISTINCT(c.id), c.title
6061
                FROM $courseTable c
6062
                INNER JOIN $courseUserTable cru ON c.id = cru.c_id
6063
                WHERE (
6064
                    cru.user_id IN (".implode(', ', $userIdList).")
6065
                    AND cru.relation_type = 0
6066
                )";
6067
6068
        if (api_is_multiple_url_enabled()) {
6069
            $courseAccessUrlTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
6070
            $accessUrlId = api_get_current_access_url_id();
6071
6072
            if ($accessUrlId != -1) {
6073
                $sql = "SELECT DISTINCT(c.id), c.title
6074
                        FROM $courseTable c
6075
                        INNER JOIN $courseUserTable cru ON c.id = cru.c_id
6076
                        INNER JOIN $courseAccessUrlTable crau ON c.id = crau.c_id
6077
                        WHERE crau.access_url_id = $accessUrlId
6078
                            AND (
6079
                            cru.id_user IN (".implode(', ', $userIdList).") AND
6080
                            cru.relation_type = 0
6081
                        )";
6082
            }
6083
        }
6084
6085
        $result = Database::query($sql);
6086
        while ($row = Database::fetch_assoc($result)) {
6087
            $coursesList[] = $row;
6088
        }
6089
6090
        return $coursesList;
6091
    }
6092
6093
    /**
6094
     * Direct course link see #5299
6095
     *
6096
     * You can send to your students an URL like this
6097
     * http://chamilodev.beeznest.com/main/auth/inscription.php?c=ABC&e=3
6098
     * Where "c" is the course code and "e" is the exercise Id, after a successful
6099
     * registration the user will be sent to the course or exercise
6100
     *
6101
     */
6102
    public static function redirectToCourse($form_data)
6103
    {
6104
        $course_code_redirect = Session::read('course_redirect');
6105
        $_user = api_get_user_info();
6106
        $user_id = api_get_user_id();
6107
6108
        if (!empty($course_code_redirect)) {
6109
            $course_info = api_get_course_info($course_code_redirect);
6110
            if (!empty($course_info)) {
6111
                if (in_array($course_info['visibility'],
6112
                    array(COURSE_VISIBILITY_OPEN_PLATFORM, COURSE_VISIBILITY_OPEN_WORLD))
6113
                ) {
6114
                    if (self::is_user_subscribed_in_course($user_id, $course_info['code'])) {
6115
6116
                        $form_data['action'] = $course_info['course_public_url'];
6117
                        $form_data['message'] = sprintf(get_lang('YouHaveBeenRegisteredToCourseX'), $course_info['title']);
6118
                        $form_data['button'] = Display::button(
6119
                            'next',
6120
                            get_lang('GoToCourse', null, $_user['language']),
6121
                            array('class' => 'btn btn-primary btn-large')
6122
                        );
6123
6124
                        $exercise_redirect = intval(Session::read('exercise_redirect'));
6125
                        // Specify the course id as the current context does not
6126
                        // hold a global $_course array
6127
                        $objExercise = new Exercise($course_info['real_id']);
6128
                        $result = $objExercise->read($exercise_redirect);
6129
6130
                        if (!empty($exercise_redirect) && !empty($result)) {
6131
                            $form_data['action'] = api_get_path(WEB_CODE_PATH).'exercise/overview.php?exerciseId='.$exercise_redirect.'&cidReq='.$course_info['code'];
6132
                            $form_data['message'] .= '<br />'.get_lang('YouCanAccessTheExercise');
6133
                            $form_data['button'] = Display::button(
6134
                                'next',
6135
                                get_lang('Go', null, $_user['language']),
6136
                                array('class' => 'btn btn-primary btn-large')
6137
                            );
6138
                        }
6139
6140
                        if (!empty($form_data['action'])) {
6141
                            header('Location: '.$form_data['action']);
6142
                            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
6143
                        }
6144
                    }
6145
                }
6146
            }
6147
        }
6148
6149
        return $form_data;
6150
    }
6151
6152
    /**
6153
     * Return tab of params to display a course title in the My Courses tab
6154
     * Check visibility, right, and notification icons, and load_dirs option
6155
     *  // get html course params
6156
     *   //
6157
     * @param $courseId
6158
     * @param bool $loadDirs
6159
     * @return array with keys ['right_actions'] ['teachers'] ['notifications']
6160
     */
6161
    public static function getCourseParamsForDisplay($courseId, $loadDirs = false)
6162
    {
6163
        $user_id = api_get_user_id();
6164
        // Table definitions
6165
        $TABLECOURS = Database::get_main_table(TABLE_MAIN_COURSE);
6166
        $TABLECOURSUSER = Database::get_main_table(TABLE_MAIN_COURSE_USER);
6167
        $TABLE_ACCESS_URL_REL_COURSE = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
6168
        $current_url_id = api_get_current_access_url_id();
6169
6170
        // Get course list auto-register
6171
        $special_course_list = self::get_special_course_list();
6172
6173
        $without_special_courses = '';
6174
        if (!empty($special_course_list)) {
6175
            $without_special_courses = ' AND course.id NOT IN ("'.implode('","', $special_course_list).'")';
6176
        }
6177
6178
        //AND course_rel_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
6179
        $sql = "SELECT 
6180
                    course.id, 
6181
                    course.title, 
6182
                    course.code, 
6183
                    course.subscribe subscr, 
6184
                    course.unsubscribe unsubscr, 
6185
                    course_rel_user.status status,
6186
                    course_rel_user.sort sort, 
6187
                    course_rel_user.user_course_cat user_course_cat
6188
                FROM
6189
                $TABLECOURS course 
6190
                INNER JOIN $TABLECOURSUSER course_rel_user                
6191
                ON (course.id = course_rel_user.c_id)
6192
                INNER JOIN $TABLE_ACCESS_URL_REL_COURSE url
6193
                ON (url.c_id = course.id)
6194
                WHERE
6195
                    course.id=".intval($courseId)." AND
6196
                    course_rel_user.user_id = ".intval($user_id)."
6197
                    $without_special_courses
6198
                ";
6199
6200
        // If multiple URL access mode is enabled, only fetch courses
6201
        // corresponding to the current URL.
6202
        if (api_get_multiple_access_url() && $current_url_id != -1) {
6203
            $sql .= " AND url.c_id = course.id AND access_url_id=".intval($current_url_id);
6204
        }
6205
        // Use user's classification for courses (if any).
6206
        $sql .= " ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
6207
6208
        $result = Database::query($sql);
6209
6210
        // Browse through all courses. We can only have one course because
6211
        // of the  course.id=".intval($courseId) in sql query
6212
        $course = Database::fetch_array($result);
6213
        $course_info = api_get_course_info_by_id($courseId);
6214
        if (empty($course_info)) {
6215
            return '';
0 ignored issues
show
Bug Best Practice introduced by
The expression return '' returns the type string which is incompatible with the documented return type array.
Loading history...
6216
        }
6217
6218
        //$course['id_session'] = null;
6219
        $course_info['id_session'] = null;
6220
        $course_info['status'] = $course['status'];
6221
6222
        // For each course, get if there is any notification icon to show
6223
        // (something that would have changed since the user's last visit).
6224
        $show_notification = !api_get_configuration_value('hide_course_notification')
6225
            ? Display::show_notification($course_info)
6226
            : '';
6227
6228
        // New code displaying the user's status in respect to this course.
6229
        $status_icon = Display::return_icon(
6230
            'blackboard.png',
6231
            $course_info['title'],
6232
            array(),
6233
            ICON_SIZE_LARGE
6234
        );
6235
6236
        $params = array();
6237
        $params['right_actions'] = '';
6238
6239
        if (api_is_platform_admin()) {
6240
            if ($loadDirs) {
6241
                $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>';
6242
                $params['right_actions'] .= '<a href="'.api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cidReq='.$course['code'].'">'.
6243
                    Display::return_icon('edit.png', get_lang('Edit'), array('align' => 'absmiddle'), ICON_SIZE_SMALL).
6244
                    '</a>';
6245
                $params['right_actions'] .= Display::div(
6246
                    '',
6247
                    array(
6248
                        'id' => 'document_result_'.$course_info['real_id'].'_0',
6249
                        'class' => 'document_preview_container',
6250
                    )
6251
                );
6252
            } else {
6253
                $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'].'">'.
6254
                    Display::returnFontAwesomeIcon('pencil').'</a>';
6255
            }
6256
        } else {
6257
            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
6258
                if ($loadDirs) {
6259
                    $params['right_actions'] .= '<a id="document_preview_'.$course_info['real_id'].'_0" class="document_preview" href="javascript:void(0);">'.
6260
                        Display::return_icon('folder.png', get_lang('Documents'), array('align' => 'absmiddle'), ICON_SIZE_SMALL).'</a>';
6261
                    $params['right_actions'] .= Display::div(
6262
                        '',
6263
                        array(
6264
                            'id' => 'document_result_'.$course_info['real_id'].'_0',
6265
                            'class' => 'document_preview_container',
6266
                        )
6267
                    );
6268
                } else {
6269
                    if ($course_info['status'] == COURSEMANAGER) {
6270
                        $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'].'">'.
6271
                            Display::returnFontAwesomeIcon('pencil').'</a>';
6272
                    }
6273
                }
6274
            }
6275
        }
6276
6277
        $course_title_url = '';
6278
        if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED || $course['status'] == COURSEMANAGER) {
6279
            $course_title_url = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/?id_session=0';
6280
            $course_title = Display::url($course_info['title'], $course_title_url);
6281
        } else {
6282
            $course_title = $course_info['title'].' '.Display::tag(
6283
                'span',
6284
                get_lang('CourseClosed'),
6285
                array('class' => 'item_closed')
6286
            );
6287
        }
6288
6289
        // Start displaying the course block itself
6290
        if (api_get_setting('display_coursecode_in_courselist') === 'true') {
6291
            $course_title .= ' ('.$course_info['visual_code'].') ';
6292
        }
6293
        $teachers = '';
6294
        if (api_get_setting('display_teacher_in_courselist') === 'true') {
6295
            $teachers = self::getTeacherListFromCourseCodeToString(
6296
                $course['code'],
6297
                self::USER_SEPARATOR,
6298
                true
6299
            );
6300
        }
6301
        $params['link'] = $course_title_url;
6302
        $params['icon'] = $status_icon;
6303
        $params['title'] = $course_title;
6304
        $params['teachers'] = $teachers;
6305
        if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
6306
            $params['notifications'] = $show_notification;
6307
        }
6308
6309
        return $params;
6310
    }
6311
6312
    /**
6313
     * Get the course id based on the original id and field name in the extra fields.
6314
     * Returns 0 if course was not found
6315
     *
6316
     * @param string $original_course_id_value Original course id
6317
     * @param string $original_course_id_name Original field name
6318
     * @return int Course id
6319
     */
6320
    public static function get_course_id_from_original_id($original_course_id_value, $original_course_id_name)
6321
    {
6322
        $extraFieldValue = new ExtraFieldValue('course');
6323
        $value = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
6324
            $original_course_id_name,
6325
            $original_course_id_value
6326
        );
6327
6328
        if ($value) {
6329
            return $value['item_id'];
6330
        }
6331
        return 0;
6332
    }
6333
6334
    /**
6335
     * Helper function to create a default gradebook (if necessary) upon course creation
6336
     * @param   int     $modelId    The gradebook model ID
6337
     * @param   string  $courseCode Course code
6338
     * @return  void
6339
     */
6340
    public static function createDefaultGradebook($modelId, $courseCode)
6341
    {
6342
        if (api_get_setting('gradebook_enable_grade_model') === 'true') {
6343
            //Create gradebook_category for the new course and add
6344
            // a gradebook model for the course
6345
            if (isset($modelId) &&
6346
                !empty($modelId) &&
6347
                $modelId != '-1'
6348
            ) {
6349
                GradebookUtils::create_default_course_gradebook(
6350
                    $courseCode,
6351
                    $modelId
6352
                );
6353
            }
6354
        }
6355
    }
6356
6357
    /**
6358
     * Helper function to check if there is a course template and, if so, to
6359
     * copy the template as basis for the new course
6360
     * @param   string  $courseCode   Course code
6361
     * @param   int     $courseTemplate 0 if no course template is defined
6362
     */
6363
    public static function useTemplateAsBasisIfRequired($courseCode, $courseTemplate)
6364
    {
6365
        $template = api_get_setting('course_creation_use_template');
6366
        $teacherCanSelectCourseTemplate = api_get_setting('teacher_can_select_course_template') === 'true';
6367
        $courseTemplate = isset($courseTemplate) ? intval($courseTemplate) : 0;
6368
6369
        $useTemplate = false;
6370
6371
        if ($teacherCanSelectCourseTemplate && $courseTemplate) {
6372
            $useTemplate = true;
6373
            $originCourse = api_get_course_info_by_id($courseTemplate);
6374
        } elseif (!empty($template)) {
6375
            $useTemplate = true;
6376
            $originCourse = api_get_course_info_by_id($template);
6377
        }
6378
6379
        if ($useTemplate) {
6380
            // Include the necessary libraries to generate a course copy
6381
            // Call the course copy object
6382
            $originCourse['official_code'] = $originCourse['code'];
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $originCourse does not seem to be defined for all execution paths leading up to this point.
Loading history...
6383
            $cb = new CourseBuilder(null, $originCourse);
6384
            $course = $cb->build(null, $originCourse['code']);
6385
            $cr = new CourseRestorer($course);
6386
            $cr->set_file_option();
6387
            $cr->restore($courseCode);
6388
        }
6389
    }
6390
6391
    /**
6392
     * Helper method to get the number of users defined with a specific course extra field
6393
     * @param   string  $name   Field title
6394
     * @param   string  $tableExtraFields The extra fields table name
6395
     * @param   string  $tableUserFieldValues The user extra field value table name
6396
     * @return  int     The number of users with this extra field with a specific value
6397
     */
6398
    public static function getCountRegisteredUsersWithCourseExtraField(
6399
        $name,
6400
        $tableExtraFields = '',
6401
        $tableUserFieldValues = ''
6402
    ) {
6403
        if (empty($tableExtraFields)) {
6404
            $tableExtraFields = Database::get_main_table(TABLE_EXTRA_FIELD);
6405
        }
6406
        if (empty($tableUserFieldValues)) {
6407
            $tableUserFieldValues = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
6408
        }
6409
6410
        $registered_users_with_extra_field = 0;
6411
        if (!empty($name) && $name != '-') {
6412
            $extraFieldType = EntityExtraField::COURSE_FIELD_TYPE;
6413
            $name = Database::escape_string($name);
6414
            $sql = "SELECT count(v.item_id) as count
6415
                    FROM $tableUserFieldValues v 
6416
                    INNER JOIN $tableExtraFields f
6417
                    ON (f.id = v.field_id)
6418
                    WHERE value = '$name' AND extra_field_type = $extraFieldType";
6419
            $result_count = Database::query($sql);
6420
            if (Database::num_rows($result_count)) {
6421
                $row_count = Database::fetch_array($result_count);
6422
                $registered_users_with_extra_field = $row_count['count'];
6423
            }
6424
        }
6425
6426
        return $registered_users_with_extra_field;
6427
    }
6428
6429
    /**
6430
     * Check if a specific access-url-related setting is a problem or not
6431
     * @param array $_configuration The $_configuration array
6432
     * @param int $accessUrlId The access URL ID
6433
     * @param string $param
6434
     * @param string $msgLabel
6435
     * @return bool|string
6436
     */
6437
    private static function checkCreateCourseAccessUrlParam($_configuration, $accessUrlId, $param, $msgLabel)
6438
    {
6439
        if (isset($_configuration[$accessUrlId][$param]) && $_configuration[$accessUrlId][$param] > 0) {
6440
            $num = self::count_courses($accessUrlId);
6441
            if ($num >= $_configuration[$accessUrlId][$param]) {
6442
                api_warn_hosting_contact($param);
6443
6444
                Display::addFlash(
6445
                    Display::return_message($msgLabel)
6446
                );
6447
            }
6448
        }
6449
        return false;
6450
    }
6451
    /**
6452
     * Fill course with all necessary items
6453
     * @param array $courseInfo Course info array
6454
     * @param array $params Parameters from the course creation form
6455
     * @param int $authorId
6456
     * @return void
6457
     */
6458
    private static function fillCourse($courseInfo, $params, $authorId = 0)
6459
    {
6460
        $authorId = empty($authorId) ? api_get_user_id() : (int) $authorId;
6461
6462
        AddCourse::prepare_course_repository($courseInfo['directory']);
6463
        AddCourse::fill_db_course(
6464
            $courseInfo['real_id'],
6465
            $courseInfo['directory'],
6466
            $courseInfo['course_language'],
6467
            $params['exemplary_content'],
6468
            $authorId
6469
        );
6470
6471
        if (isset($params['gradebook_model_id'])) {
6472
            self::createDefaultGradebook(
6473
                $params['gradebook_model_id'],
6474
                $courseInfo['code']
6475
            );
6476
        }
6477
6478
        // If parameter defined, copy the contents from a specific
6479
        // template course into this new course
6480
        if (isset($params['course_template'])) {
6481
            self::useTemplateAsBasisIfRequired(
6482
                $courseInfo['id'],
6483
                $params['course_template']
6484
            );
6485
        }
6486
        $params['course_code'] = $courseInfo['code'];
6487
        $params['item_id'] = $courseInfo['real_id'];
6488
6489
        $courseFieldValue = new ExtraFieldValue('course');
6490
        $courseFieldValue->saveFieldValues($params);
6491
    }
6492
6493
    /**
6494
     * Get the course categories form a course list
6495
     * @param array $courseList
6496
     * @return array
6497
     */
6498
    public static function getCourseCategoriesFromCourseList(array $courseList)
6499
    {
6500
        $allCategories = array_column($courseList, 'category');
6501
        $categories = array_unique($allCategories);
6502
6503
        sort($categories);
6504
6505
        return $categories;
6506
    }
6507
6508
    /**
6509
     * Display the description button of a course in the course catalog
6510
     * @param array $course
6511
     *
6512
     * @return string HTML string
6513
     */
6514
    public static function returnDescriptionButton($course)
6515
    {
6516
        if (empty($course)) {
6517
            return '';
6518
        }
6519
6520
        if (api_get_setting('show_courses_descriptions_in_catalog') == 'true') {
6521
            $title = $course['title'];
6522
            $url = api_get_path(WEB_CODE_PATH).'inc/ajax/course_home.ajax.php?a=show_course_information&code='.$course['code'];
6523
            $html = Display::url(
6524
                Display::returnFontAwesomeIcon('info-circle', 2),
6525
                $url,
6526
                [
6527
                    'class' => 'ajax btn btn-default btn-sm',
6528
                    'data-title' => $title,
6529
                    'title' => get_lang('Description'),
6530
                    'aria-label' => get_lang('Description'),
6531
                    'data-size' => 'lg'
6532
                ]
6533
            );
6534
            return $html;
6535
        }
6536
        return '';
6537
    }
6538
6539
    /**
6540
     * @param ToolChain $toolList
6541
     */
6542
    public static function setToolList($toolList)
6543
    {
6544
        self::$toolList = $toolList;
6545
    }
6546
6547
    /**
6548
     * @return ToolChain
6549
     */
6550
    public static function getToolList()
6551
    {
6552
        return self::$toolList;
6553
    }
6554
}
6555