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

Event::accessCourse()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 38
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 24
nc 4
nop 0
dl 0
loc 38
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/* See license terms in /license.txt */
3
4
//use Chamilo\UserBundle\Entity\User;
5
use ChamiloSession as Session;
6
use Chamilo\CoreBundle\Component\Utils\ChamiloApi;
7
8
/**
9
 * Class Event
10
 * Functions of this library are used to record informations when some kind
11
 * of event occur. Each event has his own types of informations then each event
12
 * use its own function.
13
 */
14
class Event
15
{
16
    /**
17
     * @author Sebastien Piraux <[email protected]>
18
     * @desc Record information for open event (when homepage is opened)
19
     */
20
    public static function open()
21
    {
22
        global $_configuration;
23
        global $TABLETRACK_OPEN;
24
25
        // @getHostByAddr($_SERVER['REMOTE_ADDR']) : will provide host and country information
26
        // $_SERVER['HTTP_USER_AGENT'] :  will provide browser and os information
27
        // $_SERVER['HTTP_REFERER'] : provide information about refering url
28
        if (isset($_SERVER['HTT_REFERER'])) {
29
            $referer = Database::escape_string($_SERVER['HTTP_REFERER']);
30
        } else {
31
            $referer = '';
32
        }
33
        // record informations only if user comes from another site
34
        //if(!eregi($_configuration['root_web'],$referer))
35
        $pos = strpos($referer, $_configuration['root_web']);
36
        if ($pos === false && $referer != '') {
37
            $ip = api_get_real_ip();
38
            $remhost = @ getHostByAddr($ip);
39
            if ($remhost == $ip) {
40
                $remhost = "Unknown";
41
            } // don't change this
42
            $reallyNow = api_get_utc_datetime();
43
            $params = [
44
                'open_remote_host' => $remhost,
45
                'open_agent' => $_SERVER['HTTP_USER_AGENT'],
46
                'open_referer' => $referer,
47
                'open_date' => $reallyNow,
48
            ];
49
            Database::insert($TABLETRACK_OPEN, $params);
50
        }
51
52
        return 1;
53
    }
54
55
    /**
56
     * @author Sebastien Piraux <[email protected]> old code
57
     * @author Julio Montoya
58
     * @param int $userId
59
     * @return bool
60
     * @desc Record information for login event when an user identifies himself with username & password
61
     */
62
    public static function eventLogin($userId)
63
    {
64
        $userInfo = api_get_user_info($userId);
65
        $userId = intval($userId);
66
67
        if (empty($userInfo)) {
68
            return false;
69
        }
70
71
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
72
        $reallyNow = api_get_utc_datetime();
73
74
        $sql = "INSERT INTO ".$table." (login_user_id, user_ip, login_date, logout_date) VALUES
75
                    ('".$userId."',
76
                    '".Database::escape_string(api_get_real_ip())."',
77
                    '".$reallyNow."',
78
                    '".$reallyNow."'
79
                    )";
80
        Database::query($sql);
81
82
        // Auto subscribe
83
        $user_status = $userInfo['status'] == SESSIONADMIN ? 'sessionadmin' : $userInfo['status'] == COURSEMANAGER ? 'teacher' : $userInfo['status'] == DRH ? 'DRH' : 'student';
84
        $autoSubscribe = api_get_setting($user_status.'_autosubscribe');
85
        if ($autoSubscribe) {
86
            $autoSubscribe = explode('|', $autoSubscribe);
87
            foreach ($autoSubscribe as $code) {
88
                if (CourseManager::course_exists($code)) {
89
                    CourseManager::subscribe_user($userId, $code);
90
                }
91
            }
92
        }
93
        return true;
94
    }
95
96
    /**
97
     * @author Sebastien Piraux <[email protected]>
98
     * @desc Record information for access event for courses
99
     */
100
    public static function accessCourse()
101
    {
102
        $TABLETRACK_ACCESS = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS);
103
        //for "what's new" notification
104
        $TABLETRACK_LASTACCESS = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
105
106
        $id_session = api_get_session_id();
107
        $now = api_get_utc_datetime();
108
        $courseId = api_get_course_int_id();
109
        $user_id = api_get_user_id();
110
        $ip = api_get_real_ip();
111
112
        if ($user_id) {
113
            $user_id = "'".$user_id."'";
114
        } else {
115
            $user_id = "0"; // no one
116
        }
117
        $sql = "INSERT INTO ".$TABLETRACK_ACCESS."  (user_ip, access_user_id, c_id, access_date, access_session_id) 
118
                VALUES ('".$ip."', ".$user_id.", '".$courseId."', '".$now."','".$id_session."')";
119
120
        Database::query($sql);
121
122
        // added for "what's new" notification
123
        $sql = "UPDATE $TABLETRACK_LASTACCESS  SET access_date = '$now'
124
                WHERE 
125
                  access_user_id = $user_id AND
126
                  c_id = '$courseId' AND 
127
                  access_tool IS NULL AND 
128
                  access_session_id=".$id_session;
129
        $result = Database::query($sql);
130
131
        if (Database::affected_rows($result) == 0) {
132
            $sql = "INSERT INTO $TABLETRACK_LASTACCESS (access_user_id, c_id, access_date, access_session_id)
133
                    VALUES (".$user_id.", '".$courseId."', '$now', '".$id_session."')";
134
            Database::query($sql);
135
        }
136
137
        return 1;
138
    }
139
140
    /**
141
     * @param string $tool name of the tool (name in mainDb.accueil table)
142
     * @author Sebastien Piraux <[email protected]>
143
     * @desc Record information for access event for tools
144
     *
145
     *  $tool can take this values :
146
     *  Links, Calendar, Document, Announcements,
147
     *  Group, Video, Works, Users, Exercises, Course Desc
148
     *  ...
149
     *  Values can be added if new modules are created (15char max)
150
     *  I encourage to use $nameTool as $tool when calling this function
151
     *
152
     * Functionality for "what's new" notification is added by Toon Van Hoecke
153
     * @return bool
154
     */
155
    public static function event_access_tool($tool)
156
    {
157
        $tool = Database::escape_string($tool);
158
159
        if (empty($tool)) {
160
            return false;
161
        }
162
163
        $_course = api_get_course_info();
164
        $courseId = api_get_course_int_id();
165
        $sessionId = api_get_session_id();
166
        $reallyNow = api_get_utc_datetime();
167
        $user_id = api_get_user_id();
168
169
        if (empty($_course)) {
170
            return false;
171
        }
172
173
        $tableAccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS);
174
        //for "what's new" notification
175
        $tableLastAccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
176
177
        // record information
178
        // only if user comes from the course $_cid
179
        //if( eregi($_configuration['root_web'].$_cid,$_SERVER['HTTP_REFERER'] ) )
180
        //$pos = strpos($_SERVER['HTTP_REFERER'],$_configuration['root_web'].$_cid);
181
        $coursePath = isset($_course['path']) ? $_course['path'] : null;
182
183
        $pos = isset($_SERVER['HTTP_REFERER']) ? strpos(strtolower($_SERVER['HTTP_REFERER']), strtolower(api_get_path(WEB_COURSE_PATH).$coursePath)) : false;
184
        // added for "what's new" notification
185
        $pos2 = isset($_SERVER['HTTP_REFERER']) ? strpos(strtolower($_SERVER['HTTP_REFERER']), strtolower(api_get_path(WEB_PATH)."index")) : false;
186
187
        // end "what's new" notification
188
        if ($pos !== false || $pos2 !== false) {
189
            $params = [
190
                'access_user_id' => $user_id,
191
                'c_id' => $courseId,
192
                'access_tool' => $tool,
193
                'access_date' => $reallyNow,
194
                'access_session_id' => $sessionId,
195
                'user_ip' => api_get_real_ip()
196
            ];
197
            Database::insert($tableAccess, $params);
198
        }
199
200
        // "what's new" notification
201
        $sql = "UPDATE $tableLastAccess
202
                SET access_date = '$reallyNow'
203
                WHERE 
204
                    access_user_id = ".$user_id." AND 
205
                    c_id = '".$courseId."' AND 
206
                    access_tool = '".$tool."' AND 
207
                    access_session_id=".$sessionId;
208
        $result = Database::query($sql);
209
210
        if (Database::affected_rows($result) == 0) {
211
            $params = [
212
                'access_user_id' => $user_id,
213
                'c_id' => $courseId,
214
                'access_tool' => $tool,
215
                'access_date' => $reallyNow,
216
                'access_session_id' => $sessionId
217
            ];
218
            Database::insert($tableLastAccess, $params);
219
        }
220
        return true;
221
    }
222
223
    /**
224
     * @param string $doc_url
225
     * @author Sebastien Piraux <[email protected]>
226
     * @desc Record information for download event
227
     * (when an user click to d/l a document)
228
     * it will be used in a redirection page
229
     * bug fixed: Roan Embrechts
230
     * Roan:
231
     * The user id is put in single quotes,
232
     * (why? perhaps to prevent sql insertion hacks?)
233
     * and later again.
234
     * Doing this twice causes an error, I remove one of them.
235
     * @return int
236
     */
237
    public static function event_download($doc_url)
238
    {
239
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_DOWNLOADS);
240
        $doc_url = Database::escape_string($doc_url);
241
242
        $reallyNow = api_get_utc_datetime();
243
        $user_id = "'".api_get_user_id()."'";
244
        $_cid = api_get_course_int_id();
245
246
        $sql = "INSERT INTO $table (
247
                 down_user_id,
248
                 c_id,
249
                 down_doc_path,
250
                 down_date,
251
                 down_session_id
252
                )
253
                VALUES (
254
                 ".$user_id.",
255
                 '".$_cid."',
256
                 '".$doc_url."',
257
                 '".$reallyNow."',
258
                 '".api_get_session_id()."'
259
                )";
260
        Database::query($sql);
261
262
        return 1;
263
    }
264
265
    /**
266
     * @param int $doc_id of document (id in mainDb.document table)
267
     * @author Sebastien Piraux <[email protected]>
268
     * @desc Record information for upload event
269
     * used in the works tool to record informations when
270
     * an user upload 1 work
271
     * @return int
272
     */
273
    public static function event_upload($doc_id)
274
    {
275
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_UPLOADS);
276
        $courseId = api_get_course_int_id();
277
        $reallyNow = api_get_utc_datetime();
278
        $user_id = api_get_user_id();
279
        $doc_id = intval($doc_id);
280
281
        $sql = "INSERT INTO $table
282
                ( upload_user_id,
283
                  c_id,
284
                  upload_cours_id,
285
                  upload_work_id,
286
                  upload_date,
287
                  upload_session_id
288
                )
289
                VALUES (
290
                 ".$user_id.",
291
                 '".$courseId."',
292
                 '',
293
                 '".$doc_id."',
294
                 '".$reallyNow."',
295
                 '".api_get_session_id()."'
296
                )";
297
        Database::query($sql);
298
299
        return 1;
300
    }
301
302
    /**
303
     * @param int $link_id (id in coursDb liens table)
304
     * @author Sebastien Piraux <[email protected]>
305
     * @desc Record information for link event (when an user click on an added link)
306
     * it will be used in a redirection page
307
     * @return int
308
     */
309
    public static function event_link($link_id)
310
    {
311
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LINKS);
312
        $reallyNow = api_get_utc_datetime();
313
        $user_id = api_get_user_id();
314
        $sql = "INSERT INTO ".$table."
315
                    ( links_user_id,
316
                     c_id,
317
                     links_link_id,
318
                     links_date,
319
                     links_session_id
320
                    ) VALUES (
321
                     ".$user_id.",
322
                     '".api_get_course_int_id()."',
323
                     '".Database::escape_string($link_id)."',
324
                     '".$reallyNow."',
325
                     '".api_get_session_id()."'
326
                    )";
327
        Database::query($sql);
328
        return 1;
329
    }
330
331
    /**
332
     * Update the TRACK_E_EXERCICES exercises
333
     *
334
     * @param   int     exeid id of the attempt
335
     * @param   int     exo_id    exercise id
336
     * @param   mixed   result    score
337
     * @param   int     weighting ( higher score )
338
     * @param   int     duration ( duration of the attempt in seconds )
339
     * @param   int     session_id
340
     * @param   int     learnpath_id (id of the learnpath)
341
     * @param   int     learnpath_item_id (id of the learnpath_item)
342
     * @return bool
343
     *
344
     * @author Sebastien Piraux <[email protected]>
345
     * @author Julio Montoya Armas <[email protected]> Reworked 2010
346
     * @desc Record result of user when an exercise was done
347
     */
348
    public static function updateEventExercise(
349
        $exeid,
350
        $exo_id,
351
        $score,
352
        $weighting,
353
        $session_id,
354
        $learnpath_id = 0,
355
        $learnpath_item_id = 0,
356
        $learnpath_item_view_id = 0,
357
        $duration = 0,
358
        $question_list = array(),
359
        $status = '',
360
        $remind_list = array(),
361
        $end_date = null
362
    ) {
363
        if ($exeid != '') {
364
            /*
365
             * Code commented due BT#8423 do not change the score to 0.
366
             *
367
             * Validation in case of fraud with actived control time
368
            if (!ExerciseLib::exercise_time_control_is_valid($exo_id, $learnpath_id, $learnpath_item_id)) {
369
                $score = 0;
370
            }
371
            */
372
            if (!isset($status) || empty($status)) {
373
                $status = '';
374
            } else {
375
                $status = Database::escape_string($status);
376
            }
377
378
            $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
379
380
            if (!empty($question_list)) {
381
                $question_list = array_map('intval', $question_list);
382
            }
383
384
            if (!empty($remind_list)) {
385
                $remind_list = array_map('intval', $remind_list);
386
                $remind_list = array_filter($remind_list);
387
                $remind_list = implode(",", $remind_list);
388
            } else {
389
                $remind_list = '';
390
            }
391
392
            if (empty($end_date)) {
393
                $end_date = api_get_utc_datetime();
394
            }
395
396
            $sql = "UPDATE $table SET
397
        		   exe_exo_id = '".Database::escape_string($exo_id)."',
398
        		   exe_result = '".Database::escape_string($score)."',
399
        		   exe_weighting = '".Database::escape_string($weighting)."',
400
        		   session_id = '".Database::escape_string($session_id)."',
401
        		   orig_lp_id = '".Database::escape_string($learnpath_id)."',
402
        		   orig_lp_item_id = '".Database::escape_string($learnpath_item_id)."',
403
                   orig_lp_item_view_id = '".Database::escape_string($learnpath_item_view_id)."',
404
        		   exe_duration = '".Database::escape_string($duration)."',
405
        		   exe_date = '".$end_date."',
406
        		   status = '".$status."',
407
        		   questions_to_check = '".$remind_list."',
408
        		   data_tracking = '".implode(',', $question_list)."',
409
                   user_ip = '" . Database::escape_string(api_get_real_ip())."'
410
        		 WHERE exe_id = '".Database::escape_string($exeid)."'";
411
            Database::query($sql);
412
413
            //Deleting control time session track
414
            //ExerciseLib::exercise_time_control_delete($exo_id);
415
            return true;
416
        } else {
417
            return false;
418
        }
419
    }
420
421
    /**
422
     * Record an event for this attempt at answering an exercise
423
     * @param    float    Score achieved
424
     * @param    string    Answer given
425
     * @param    integer    Question ID
426
     * @param    integer Exercise attempt ID a.k.a exe_id (from track_e_exercise)
427
     * @param    integer    Position
428
     * @param    integer Exercise ID (from c_quiz)
429
     * @param    bool update results?
430
     * @param    $fileName string  Filename (for audio answers - using nanogong)
431
     * @param    int User ID The user who's going to get this score. Default value of null means "get from context".
432
     * @param    int Course ID (from the "id" column of course table). Default value of null means "get from context".
433
     * @param    int Session ID (from the session table). Default value of null means "get from context".
434
     * @param    int Learnpath ID (from c_lp table). Default value of null means "get from context".
435
     * @param    int Learnpath item ID (from the c_lp_item table). Default value of null means "get from context".
436
     * @return    boolean    Result of the insert query
437
     */
438
    public static function saveQuestionAttempt(
439
        $score,
440
        $answer,
441
        $question_id,
442
        $exe_id,
443
        $position,
444
        $exercise_id = 0,
445
        $updateResults = false,
446
        $fileName = null,
447
        $user_id = null,
448
        $course_id = null,
449
        $session_id = null,
450
        $learnpath_id = null,
451
        $learnpath_item_id = null
452
    ) {
453
        global $debug;
454
        $question_id = Database::escape_string($question_id);
455
        $exe_id = Database::escape_string($exe_id);
456
        $position = Database::escape_string($position);
457
        $now = api_get_utc_datetime();
458
459
        // check user_id or get from context
460
        if (empty($user_id)) {
461
            $user_id = api_get_user_id();
462
            // anonymous
463
            if (empty($user_id)) {
464
                $user_id = api_get_anonymous_id();
465
            }
466
        }
467
        // check course_id or get from context
468
        if (empty($course_id) or intval($course_id) != $course_id) {
469
            $course_id = api_get_course_int_id();
470
        }
471
        // check session_id or get from context
472
        if (empty($session_id)) {
473
            $session_id = api_get_session_id();
474
        }
475
        // check learnpath_id or get from context
476
        if (empty($learnpath_id)) {
477
            global $learnpath_id;
478
        }
479
        // check learnpath_item_id or get from context
480
        if (empty($learnpath_item_id)) {
481
            global $learnpath_item_id;
482
        }
483
484
        $TBL_TRACK_ATTEMPT = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
485
486
        if ($debug) {
487
            error_log("----- entering saveQuestionAttempt() function ------");
488
            error_log("answer: $answer");
489
            error_log("score: $score");
490
            error_log("question_id : $question_id");
491
            error_log("position: $position");
492
        }
493
494
        //Validation in case of fraud with active control time
495
        if (!ExerciseLib::exercise_time_control_is_valid($exercise_id, $learnpath_id, $learnpath_item_id)) {
496
            if ($debug) {
497
                error_log("exercise_time_control_is_valid is false");
498
            }
499
            $score = 0;
500
            $answer = 0;
501
        }
502
503
        $session_id = api_get_session_id();
504
505
        if (!empty($question_id) && !empty($exe_id) && !empty($user_id)) {
506
            if (is_null($answer)) {
507
                $answer = '';
508
            }
509
            $attempt = array(
510
                'user_id' => $user_id,
511
                'question_id' => $question_id,
512
                'answer' => $answer,
513
                'marks' => $score,
514
                'c_id' => $course_id,
515
                'session_id' => $session_id,
516
                'position' => $position,
517
                'tms' => $now,
518
                'filename' => !empty($fileName) ? basename($fileName) : $fileName,
519
                'teacher_comment' => ''
520
            );
521
522
            // Check if attempt exists.
523
            $sql = "SELECT exe_id FROM $TBL_TRACK_ATTEMPT
524
                    WHERE
525
                        c_id = $course_id AND
526
                        session_id = $session_id AND
527
                        exe_id = $exe_id AND
528
                        user_id = $user_id AND
529
                        question_id = $question_id AND
530
                        position = $position";
531
            $result = Database::query($sql);
532
            if (Database::num_rows($result)) {
533
                if ($debug) {
534
                    error_log("Attempt already exist: exe_id: $exe_id - user_id:$user_id - question_id:$question_id");
535
                }
536
                if ($updateResults == false) {
537
                    //The attempt already exist do not update use  update_event_exercise() instead
538
                    return false;
539
                }
540
            } else {
541
                $attempt['exe_id'] = $exe_id;
542
            }
543
544
            if ($debug) {
545
                error_log("updateResults : $updateResults");
546
                error_log("Saving question attempt: ");
547
                error_log($sql);
548
            }
549
550
            $recording_table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING);
551
552
            if ($updateResults == false) {
553
                $attempt_id = Database::insert($TBL_TRACK_ATTEMPT, $attempt);
554
555
                if ($debug) {
556
                    error_log("Insert attempt with id #$attempt_id");
557
                }
558
559
                if (defined('ENABLED_LIVE_EXERCISE_TRACKING')) {
560
                    if ($debug) {
561
                        error_log("Saving e attempt recording ");
562
                    }
563
                    $attempt_recording = array(
564
                        'exe_id' => $attempt_id,
565
                        'question_id' => $question_id,
566
                        'marks' => $score,
567
                        'insert_date' => $now,
568
                        'author' => '',
569
                        'session_id' => $session_id,
570
                    );
571
                    Database::insert($recording_table, $attempt_recording);
572
                }
573
            } else {
574
                Database::update(
575
                    $TBL_TRACK_ATTEMPT,
576
                    $attempt,
577
                    array(
578
                        'exe_id = ? AND question_id = ? AND user_id = ? ' => array(
579
                            $exe_id,
580
                            $question_id,
581
                            $user_id
582
                        )
583
                    )
584
                );
585
586
                if (defined('ENABLED_LIVE_EXERCISE_TRACKING')) {
587
                    $attempt_recording = array(
588
                        'exe_id' => $exe_id,
589
                        'question_id' => $question_id,
590
                        'marks' => $score,
591
                        'insert_date' => $now,
592
                        'author' => '',
593
                        'session_id' => $session_id,
594
                    );
595
596
                    Database::update(
597
                        $recording_table,
598
                        $attempt_recording,
599
                        array(
600
                            'exe_id = ? AND question_id = ? AND session_id = ? ' => array(
601
                                $exe_id,
602
                                $question_id,
603
                                $session_id
604
                            )
605
                        )
606
                    );
607
                }
608
                $attempt_id = $exe_id;
609
            }
610
611
            return $attempt_id;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $attempt_id also could return the type integer|string which is incompatible with the documented return type boolean.
Loading history...
612
        } else {
613
            return false;
614
        }
615
    }
616
617
    /**
618
     * Record an hotspot spot for this attempt at answering an hotspot question
619
     * @param int $exeId
620
     * @param int $questionId Question ID
621
     * @param int $answerId Answer ID
622
     * @param int $correct
623
     * @param string $coords Coordinates of this point (e.g. 123;324)
624
     * @param bool $updateResults
625
     * @param int $exerciseId
626
     *
627
     * @return bool Result of the insert query
628
     * @uses Course code and user_id from global scope $_cid and $_user
629
     */
630
    public static function saveExerciseAttemptHotspot(
631
        $exeId,
632
        $questionId,
633
        $answerId,
634
        $correct,
635
        $coords,
636
        $updateResults = false,
637
        $exerciseId = 0
638
    ) {
639
        global $safe_lp_id, $safe_lp_item_id;
640
641
        if ($updateResults == 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...
642
            // Validation in case of fraud with activated control time
643
            if (!ExerciseLib::exercise_time_control_is_valid($exerciseId, $safe_lp_id, $safe_lp_item_id)) {
644
                $correct = 0;
645
            }
646
        }
647
648
        if (empty($exeId)) {
649
            return false;
650
        }
651
652
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTSPOT);
653
        if ($updateResults) {
654
            $params = array(
655
                'hotspot_correct' => $correct,
656
                'hotspot_coordinate' => $coords
657
            );
658
            Database::update(
659
                $table,
660
                $params,
661
                array(
662
                    'hotspot_user_id = ? AND hotspot_exe_id = ? AND hotspot_question_id = ? AND hotspot_answer_id = ? ' => array(
663
                        api_get_user_id(),
664
                        $exeId,
665
                        $questionId,
666
                        $answerId
667
                    )
668
                )
669
            );
670
671
        } else {
672
            return Database::insert(
0 ignored issues
show
Bug Best Practice introduced by
The expression return Database::insert(...oordinate' => $coords)) also could return the type integer which is incompatible with the documented return type boolean.
Loading history...
673
                $table,
674
                [
675
                    'hotspot_course_code' => api_get_course_id(),
676
                    'hotspot_user_id' => api_get_user_id(),
677
                    'c_id' => api_get_course_int_id(),
678
                    'hotspot_exe_id' => $exeId,
679
                    'hotspot_question_id' => $questionId,
680
                    'hotspot_answer_id' => $answerId,
681
                    'hotspot_correct' => $correct,
682
                    'hotspot_coordinate' => $coords
683
                ]
684
            );
685
        }
686
    }
687
688
    /**
689
     * Records information for common (or admin) events (in the track_e_default table)
690
     * @author Yannick Warnier <[email protected]>
691
     * @param   string  $event_type Type of event
692
     * @param   string  $event_value_type Type of value
693
     * @param   string  $event_value Value
694
     * @param   string  $datetime Datetime (UTC) (defaults to null)
695
     * @param   int     $user_id User ID (defaults to null)
696
     * @param   int $course_id Course ID (defaults to null)
697
     * @param   int $sessionId Session ID
698
     * @return  bool
699
     * @assert ('','','') === false
700
     */
701
    public static function addEvent(
702
        $event_type,
703
        $event_value_type,
704
        $event_value,
705
        $datetime = null,
706
        $user_id = null,
707
        $course_id = null,
708
        $sessionId = 0
709
    ) {
710
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_DEFAULT);
711
712
        if (empty($event_type)) {
713
            return false;
714
        }
715
        $event_type = Database::escape_string($event_type);
716
        $event_value_type = Database::escape_string($event_value_type);
717
        if (!empty($course_id)) {
718
            $course_id = intval($course_id);
719
        } else {
720
            $course_id = api_get_course_int_id();
721
        }
722
        if (!empty($sessionId)) {
723
            $sessionId = intval($sessionId);
724
        } else {
725
            $sessionId = api_get_session_id();
726
        }
727
728
        //Clean the user_info
729
        if ($event_value_type == LOG_USER_OBJECT) {
730
            if (is_array($event_value)) {
731
                unset($event_value['complete_name']);
732
                unset($event_value['complete_name_with_username']);
733
                unset($event_value['firstName']);
734
                unset($event_value['lastName']);
735
                unset($event_value['avatar_small']);
736
                unset($event_value['avatar']);
737
                unset($event_value['mail']);
738
                unset($event_value['password']);
739
                unset($event_value['last_login']);
740
                unset($event_value['picture_uri']);
741
                $event_value = serialize($event_value);
742
            }
743
        }
744
        // If event is an array then the $event_value_type should finish with
745
        // the suffix _array for example LOG_WORK_DATA = work_data_array
746
        if (is_array($event_value)) {
747
            $event_value = serialize($event_value);
748
        }
749
750
        $event_value = Database::escape_string($event_value);
751
        $sessionId = empty($sessionId) ? api_get_session_id() : intval($sessionId);
752
753
        if (!isset($datetime)) {
754
            $datetime = api_get_utc_datetime();
755
        }
756
757
        $datetime = Database::escape_string($datetime);
758
759
        if (!isset($user_id)) {
760
            $user_id = api_get_user_id();
761
        }
762
763
        $params = array(
764
            'default_user_id' => $user_id,
765
            'c_id' => $course_id,
766
            'default_date' => $datetime,
767
            'default_event_type' => $event_type,
768
            'default_value_type' => $event_value_type,
769
            'default_value' => $event_value,
770
            'session_id' => $sessionId
771
        );
772
        Database::insert($table, $params);
773
774
        return true;
775
    }
776
777
    /**
778
     * Get every email stored in the database
779
     * @deprecated
780
     * @return array
781
     * @assert () !== false
782
     */
783
    public static function get_all_event_types()
784
    {
785
        global $event_config;
786
787
        $sql = 'SELECT etm.id, event_type_name, activated, language_id, message, subject, dokeos_folder
788
                FROM '.Database::get_main_table(TABLE_EVENT_EMAIL_TEMPLATE).' etm
789
                INNER JOIN '.Database::get_main_table(TABLE_MAIN_LANGUAGE).' l
790
                ON etm.language_id = l.id';
791
792
        $events_types = Database::store_result(Database::query($sql), 'ASSOC');
793
794
        $to_return = array();
795
        foreach ($events_types as $et) {
796
            $et['nameLangVar'] = $event_config[$et["event_type_name"]]["name_lang_var"];
797
            $et['descLangVar'] = $event_config[$et["event_type_name"]]["desc_lang_var"];
798
            $to_return[] = $et;
799
        }
800
801
        return $to_return;
802
    }
803
804
    /**
805
     * Get the users related to one event
806
     *
807
     * @param string $event_name
808
     *
809
     * @return string
810
     */
811
    public static function get_event_users($event_name)
812
    {
813
        $event_name = Database::escape_string($event_name);
814
        $sql = 'SELECT user.user_id,  user.firstname, user.lastname
815
                FROM '.Database::get_main_table(TABLE_MAIN_USER).' user
816
                JOIN '.Database::get_main_table(TABLE_EVENT_TYPE_REL_USER).' relUser
817
                ON relUser.user_id = user.user_id
818
                WHERE user.status <> '.ANONYMOUS.' AND relUser.event_type_name = "'.$event_name.'"';
819
        $user_list = Database::store_result(Database::query($sql), 'ASSOC');
820
821
        return json_encode($user_list);
822
    }
823
824
    /**
825
     * @param int $user_id
826
     * @param string $event_type
827
     * @return array|bool
828
     */
829
    public static function get_events_by_user_and_type($user_id, $event_type)
830
    {
831
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_DEFAULT);
832
        $user_id = intval($user_id);
833
        $event_type = Database::escape_string($event_type);
834
835
        $sql = "SELECT * FROM $table
836
                WHERE default_value_type = 'user_id' AND
837
                      default_value = $user_id AND
838
                      default_event_type = '$event_type'
839
                ORDER BY default_date ";
840
        $result = Database::query($sql);
841
        if ($result) {
842
            return Database::store_result($result, 'ASSOC');
843
        }
844
        return false;
845
    }
846
847
    /**
848
     * Save the new message for one event and for one language
849
     *
850
     * @param string $event_name
851
     * @param array $users
852
     * @param string $message
853
     * @param string $subject
854
     * @param string $event_message_language
855
     * @param int $activated
856
     */
857
    public static function save_event_type_message(
858
        $event_name,
859
        $users,
860
        $message,
861
        $subject,
862
        $event_message_language,
863
        $activated
864
    ) {
865
        $event_name = Database::escape_string($event_name);
866
        $activated = intval($activated);
867
        $event_message_language = Database::escape_string($event_message_language);
868
869
        // Deletes then re-adds the users linked to the event
870
        $sql = 'DELETE FROM '.Database::get_main_table(TABLE_EVENT_TYPE_REL_USER).' 
871
                WHERE event_type_name = "'.$event_name.'"	';
872
        Database::query($sql);
873
874
        foreach ($users as $user) {
875
            $sql = 'INSERT INTO '.Database::get_main_table(TABLE_EVENT_TYPE_REL_USER).' (user_id,event_type_name)
876
                    VALUES('.intval($user).',"'.$event_name.'")';
877
            Database::query($sql);
878
        }
879
        $language_id = api_get_language_id($event_message_language);
880
        // check if this template in this language already exists or not
881
        $sql = 'SELECT COUNT(id) as total
882
                FROM '.Database::get_main_table(TABLE_EVENT_EMAIL_TEMPLATE).'
883
                WHERE event_type_name = "'.$event_name.'" AND language_id = '.$language_id;
884
885
        $sql = Database::store_result(Database::query($sql), 'ASSOC');
886
887
        // if already exists, we update
888
        if ($sql[0]["total"] > 0) {
889
            $sql = 'UPDATE '.Database::get_main_table(TABLE_EVENT_EMAIL_TEMPLATE).'
890
                SET message = "'.Database::escape_string($message).'",
891
                subject = "'.Database::escape_string($subject).'",
892
                activated = '.$activated.'
893
                WHERE event_type_name = "'.$event_name.'" AND language_id = (
894
                    SELECT id FROM '.Database::get_main_table(TABLE_MAIN_LANGUAGE).'
895
                    WHERE dokeos_folder = "'.$event_message_language.'"
896
                )';
897
            Database::query($sql);
898
        } else { // else we create a new record
899
            // gets the language_-_id
900
            $lang_id = '(SELECT id FROM '.Database::get_main_table(TABLE_MAIN_LANGUAGE).'
901
                        WHERE dokeos_folder = "'.$event_message_language.'")';
902
            $lang_id = Database::store_result(Database::query($lang_id), 'ASSOC');
903
904
            if (!empty($lang_id[0]["id"])) {
905
                $sql = 'INSERT INTO '.Database::get_main_table(TABLE_EVENT_EMAIL_TEMPLATE).' (event_type_name, language_id, message, subject, activated)
906
                    VALUES("'.$event_name.'", '.$lang_id[0]["id"].', "'.Database::escape_string($message).'", "'.Database::escape_string($subject).'", '.$activated.')';
907
                Database::query($sql);
908
            }
909
        }
910
911
        // set activated at every save
912
        $sql = 'UPDATE '.Database::get_main_table(TABLE_EVENT_EMAIL_TEMPLATE).'
913
                SET activated = '.$activated.'
914
                WHERE event_type_name = "'.$event_name.'"';
915
        Database::query($sql);
916
    }
917
918
    /**
919
     * Gets the last attempt of an exercise based in the exe_id
920
     * @param int $exe_id
921
     * @return mixed
922
     */
923
    public static function getLastAttemptDateOfExercise($exe_id)
924
    {
925
        $exe_id = intval($exe_id);
926
        $track_attempts = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
927
        $sql = 'SELECT max(tms) as last_attempt_date
928
                FROM '.$track_attempts.'
929
                WHERE exe_id='.$exe_id;
930
        $rs_last_attempt = Database::query($sql);
931
        $row_last_attempt = Database::fetch_array($rs_last_attempt);
932
        $date = $row_last_attempt['last_attempt_date']; //Get the date of last attempt
933
934
        return $date;
935
    }
936
937
    /**
938
     * Gets the last attempt of an exercise based in the exe_id
939
     * @param int $exe_id
940
     * @return mixed
941
     */
942
    public static function getLatestQuestionIdFromAttempt($exe_id)
943
    {
944
        $exe_id = intval($exe_id);
945
        $track_attempts = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
946
        $sql = 'SELECT question_id FROM '.$track_attempts.'
947
                WHERE exe_id='.$exe_id.'
948
                ORDER BY tms DESC
949
                LIMIT 1';
950
        $result = Database::query($sql);
951
        if (Database::num_rows($result)) {
952
            $row = Database::fetch_array($result);
953
            return $row['question_id'];
954
        } else {
955
            return false;
956
        }
957
    }
958
959
    /**
960
     * Gets how many attempts exists by user, exercise, learning path
961
     * @param   int user id
962
     * @param   int exercise id
963
     * @param   int lp id
964
     * @param   int lp item id
965
     * @param   int lp item view id
966
     * @return int
967
     */
968
    public static function get_attempt_count(
969
        $user_id,
970
        $exerciseId,
971
        $lp_id,
972
        $lp_item_id,
973
        $lp_item_view_id
974
    ) {
975
        $stat_table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
976
        $user_id = intval($user_id);
977
        $exerciseId = intval($exerciseId);
978
        $lp_id = intval($lp_id);
979
        $lp_item_id = intval($lp_item_id);
980
        $lp_item_view_id = intval($lp_item_view_id);
981
982
        $sql = "SELECT count(*) as count
983
                FROM $stat_table
984
                WHERE
985
                    exe_exo_id = $exerciseId AND
986
                    exe_user_id = $user_id AND
987
                    status != 'incomplete' AND
988
                    orig_lp_id = $lp_id AND
989
                    orig_lp_item_id = $lp_item_id AND
990
                    orig_lp_item_view_id = $lp_item_view_id AND
991
                    c_id = '".api_get_course_int_id()."' AND
992
                    session_id = '".api_get_session_id()."'";
993
994
        $query = Database::query($sql);
995
        if (Database::num_rows($query) > 0) {
996
            $attempt = Database::fetch_array($query, 'ASSOC');
997
            return $attempt['count'];
998
        } else {
999
            return 0;
1000
        }
1001
    }
1002
1003
    /**
1004
     * @param $user_id
1005
     * @param $exerciseId
1006
     * @param $lp_id
1007
     * @param $lp_item_id
1008
     * @return int
1009
     */
1010
    public static function get_attempt_count_not_finished(
1011
        $user_id,
1012
        $exerciseId,
1013
        $lp_id,
1014
        $lp_item_id
1015
    ) {
1016
        $stat_table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
1017
        $user_id = intval($user_id);
1018
        $exerciseId = intval($exerciseId);
1019
        $lp_id = intval($lp_id);
1020
        $lp_item_id = intval($lp_item_id);
1021
        //$lp_item_view_id = intval($lp_item_view_id);
1022
1023
        $sql = "SELECT count(*) as count
1024
                FROM $stat_table
1025
                WHERE
1026
                    exe_exo_id 			= $exerciseId AND
1027
                    exe_user_id 		= $user_id AND
1028
                    status 				!= 'incomplete' AND
1029
                    orig_lp_id 			= $lp_id AND
1030
                    orig_lp_item_id 	= $lp_item_id AND
1031
                    c_id = '".api_get_course_int_id()."' AND
1032
                    session_id = '".api_get_session_id()."'";
1033
1034
        $query = Database::query($sql);
1035
        if (Database::num_rows($query) > 0) {
1036
            $attempt = Database::fetch_array($query, 'ASSOC');
1037
            return $attempt['count'];
1038
        } else {
1039
            return 0;
1040
        }
1041
    }
1042
1043
    /**
1044
     * @param int $user_id
1045
     * @param int $lp_id
1046
     * @param array $course
1047
     * @param int $session_id
1048
     */
1049
    public static function delete_student_lp_events(
1050
        $user_id,
1051
        $lp_id,
1052
        $course,
1053
        $session_id
1054
    ) {
1055
        $lp_view_table = Database::get_course_table(TABLE_LP_VIEW);
1056
        $lp_item_view_table = Database::get_course_table(TABLE_LP_ITEM_VIEW);
1057
        $lpInteraction = Database::get_course_table(TABLE_LP_IV_INTERACTION);
1058
        $lpObjective = Database::get_course_table(TABLE_LP_IV_OBJECTIVE);
1059
1060
        $course_id = $course['real_id'];
1061
1062
        if (empty($course_id)) {
1063
            $course_id = api_get_course_int_id();
1064
        }
1065
1066
        $track_e_exercises = Database::get_main_table(
1067
            TABLE_STATISTIC_TRACK_E_EXERCISES
1068
        );
1069
        $track_attempts = Database::get_main_table(
1070
            TABLE_STATISTIC_TRACK_E_ATTEMPT
1071
        );
1072
        $recording_table = Database::get_main_table(
1073
            TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING
1074
        );
1075
1076
        $user_id = intval($user_id);
1077
        $lp_id = intval($lp_id);
1078
        $session_id = intval($session_id);
1079
1080
        //Make sure we have the exact lp_view_id
1081
        $sql = "SELECT id FROM $lp_view_table
1082
                WHERE
1083
                    c_id = $course_id AND
1084
                    user_id = $user_id AND
1085
                    lp_id = $lp_id AND
1086
                    session_id = $session_id ";
1087
        $result = Database::query($sql);
1088
1089
        if (Database::num_rows($result)) {
1090
            $view = Database::fetch_array($result, 'ASSOC');
1091
            $lp_view_id = $view['id'];
1092
1093
            $sql = "DELETE FROM $lp_item_view_table
1094
                    WHERE c_id = $course_id AND lp_view_id = $lp_view_id ";
1095
            Database::query($sql);
1096
1097
            $sql = "DELETE FROM $lpInteraction
1098
                    WHERE c_id = $course_id AND lp_iv_id = $lp_view_id ";
1099
            Database::query($sql);
1100
1101
            $sql = "DELETE FROM $lpObjective
1102
                    WHERE c_id = $course_id AND lp_iv_id = $lp_view_id ";
1103
            Database::query($sql);
1104
        }
1105
1106
        $sql = "DELETE FROM $lp_view_table
1107
                WHERE
1108
                    c_id = $course_id AND
1109
                    user_id = $user_id AND
1110
                    lp_id= $lp_id AND
1111
                    session_id = $session_id
1112
            ";
1113
        Database::query($sql);
1114
1115
        $sql = "SELECT exe_id FROM $track_e_exercises
1116
                WHERE   
1117
                    exe_user_id = $user_id AND
1118
                    session_id = $session_id AND
1119
                    c_id = $course_id AND
1120
                    orig_lp_id = $lp_id";
1121
        $result = Database::query($sql);
1122
        $exe_list = array();
1123
        while ($row = Database::fetch_array($result, 'ASSOC')) {
1124
            $exe_list[] = $row['exe_id'];
1125
        }
1126
1127
        if (!empty($exe_list) && is_array($exe_list) && count($exe_list) > 0) {
1128
            $sql = "DELETE FROM $track_e_exercises
1129
                WHERE exe_id IN (".implode(',', $exe_list).")";
1130
            Database::query($sql);
1131
1132
            $sql = "DELETE FROM $track_attempts
1133
                WHERE exe_id IN (".implode(',', $exe_list).")";
1134
            Database::query($sql);
1135
1136
            $sql = "DELETE FROM $recording_table
1137
                WHERE exe_id IN (".implode(',', $exe_list).")";
1138
            Database::query($sql);
1139
        }
1140
1141
        self::addEvent(
1142
            LOG_LP_ATTEMPT_DELETE,
1143
            LOG_LP_ID,
1144
            $lp_id,
1145
            null,
1146
            null,
1147
            $course_id,
1148
            $session_id
1149
        );
1150
    }
1151
1152
    /**
1153
     * Delete all exercise attempts (included in LP or not)
1154
     *
1155
     * @param int user id
1156
     * @param int exercise id
1157
     * @param int $course_id
1158
     * @param int session id
1159
     */
1160
    public static function delete_all_incomplete_attempts(
1161
        $user_id,
1162
        $exercise_id,
1163
        $course_id,
1164
        $session_id = 0
1165
    ) {
1166
        $track_e_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
1167
        $user_id = intval($user_id);
1168
        $exercise_id = intval($exercise_id);
1169
        $course_id = intval($course_id);
1170
        $session_id = intval($session_id);
1171
        if (!empty($user_id) && !empty($exercise_id) && !empty($course_code)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $course_code does not exist. Did you maybe mean $course_id?
Loading history...
1172
            $sql = "DELETE FROM $track_e_exercises
1173
                    WHERE
1174
                        exe_user_id = $user_id AND
1175
                        exe_exo_id = $exercise_id AND
1176
                        c_id = '$course_id' AND
1177
                        session_id = $session_id AND
1178
                        status = 'incomplete' ";
1179
            Database::query($sql);
1180
            self::addEvent(
1181
                LOG_EXERCISE_RESULT_DELETE,
1182
                LOG_EXERCISE_AND_USER_ID,
1183
                $exercise_id.'-'.$user_id,
1184
                null,
1185
                null,
1186
                $course_id,
1187
                $session_id
1188
            );
1189
        }
1190
    }
1191
1192
    /**
1193
     * Gets all exercise results (NO Exercises in LPs ) from a given exercise id, course, session
1194
     * @param   int     exercise id
1195
     * @param   int $courseId
1196
     * @param   int     session id
1197
     * @return  array   with the results
1198
     *
1199
     */
1200
    public static function get_all_exercise_results(
1201
        $exercise_id,
1202
        $courseId,
1203
        $session_id = 0,
1204
        $load_question_list = true,
1205
        $user_id = null
1206
    ) {
1207
        $TABLETRACK_EXERCICES = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
1208
        $TBL_TRACK_ATTEMPT = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
1209
        $courseId = intval($courseId);
1210
        $exercise_id = intval($exercise_id);
1211
        $session_id = intval($session_id);
1212
1213
        $user_condition = null;
1214
        if (!empty($user_id)) {
1215
            $user_id = intval($user_id);
1216
            $user_condition = "AND exe_user_id = $user_id ";
1217
        }
1218
        $sql = "SELECT * FROM $TABLETRACK_EXERCICES
1219
                WHERE
1220
                    status = ''  AND
1221
                    c_id = '$courseId' AND
1222
                    exe_exo_id = '$exercise_id' AND
1223
                    session_id = $session_id  AND
1224
                    orig_lp_id =0 AND
1225
                    orig_lp_item_id = 0
1226
                    $user_condition
1227
                ORDER BY exe_id";
1228
        $res = Database::query($sql);
1229
        $list = array();
1230
        while ($row = Database::fetch_array($res, 'ASSOC')) {
1231
            $list[$row['exe_id']] = $row;
1232
            if ($load_question_list) {
1233
                $sql = "SELECT * FROM $TBL_TRACK_ATTEMPT
1234
                        WHERE exe_id = {$row['exe_id']}";
1235
                $res_question = Database::query($sql);
1236
                while ($row_q = Database::fetch_array($res_question, 'ASSOC')) {
1237
                    $list[$row['exe_id']]['question_list'][$row_q['question_id']] = $row_q;
1238
                }
1239
            }
1240
        }
1241
        return $list;
1242
    }
1243
1244
    /**
1245
     * Gets all exercise results (NO Exercises in LPs ) from a given exercise id, course, session
1246
     * @param   int  $courseId
1247
     * @param   int     session id
1248
     * @param bool $get_count
1249
     * @return  array   with the results
1250
     *
1251
     */
1252
    public static function get_all_exercise_results_by_course(
1253
        $courseId,
1254
        $session_id = 0,
1255
        $get_count = true
1256
    ) {
1257
        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
1258
        $courseId = intval($courseId);
1259
        $session_id = intval($session_id);
1260
1261
        $select = '*';
1262
        if ($get_count) {
1263
            $select = 'count(*) as count';
1264
        }
1265
        $sql = "SELECT $select FROM $table_track_exercises
1266
                WHERE   status = ''  AND
1267
                        c_id = '$courseId' AND
1268
                        session_id = $session_id  AND
1269
                        orig_lp_id = 0 AND
1270
                        orig_lp_item_id = 0
1271
                ORDER BY exe_id";
1272
        $res = Database::query($sql);
1273
        if ($get_count) {
1274
            $row = Database::fetch_array($res, 'ASSOC');
1275
            return $row['count'];
1276
        } else {
1277
            $list = array();
1278
            while ($row = Database::fetch_array($res, 'ASSOC')) {
1279
                $list[$row['exe_id']] = $row;
1280
            }
1281
            return $list;
1282
        }
1283
    }
1284
1285
    /**
1286
     * Gets all exercise results (NO Exercises in LPs) from a given exercise id, course, session
1287
     * @param   int     exercise id
1288
     * @param   int  $courseId
1289
     * @param   int     session id
1290
     * @return  array   with the results
1291
     *
1292
     */
1293
    public static function get_all_exercise_results_by_user(
1294
        $user_id,
1295
        $courseId,
1296
        $session_id = 0
1297
    ) {
1298
        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
1299
        $table_track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
1300
        $courseId = intval($courseId);
1301
        $session_id = intval($session_id);
1302
        $user_id = intval($user_id);
1303
1304
        $sql = "SELECT * FROM $table_track_exercises
1305
                WHERE
1306
                    status = '' AND
1307
                    exe_user_id = $user_id AND
1308
                    c_id = '$courseId' AND
1309
                    session_id = $session_id AND
1310
                    orig_lp_id = 0 AND
1311
                    orig_lp_item_id = 0
1312
                ORDER by exe_id";
1313
1314
        $res = Database::query($sql);
1315
        $list = array();
1316
        while ($row = Database::fetch_array($res, 'ASSOC')) {
1317
            $list[$row['exe_id']] = $row;
1318
            $sql = "SELECT * FROM $table_track_attempt 
1319
                    WHERE exe_id = {$row['exe_id']}";
1320
            $res_question = Database::query($sql);
1321
            while ($row_q = Database::fetch_array($res_question, 'ASSOC')) {
1322
                $list[$row['exe_id']]['question_list'][$row_q['question_id']] = $row_q;
1323
            }
1324
        }
1325
1326
        return $list;
1327
    }
1328
1329
    /**
1330
     * Gets exercise results (NO Exercises in LPs) from a given exercise id, course, session
1331
     * @param   int     $exe_id exercise id
1332
     * @param string $status
1333
     * @return  array   with the results
1334
     *
1335
     */
1336
    public static function get_exercise_results_by_attempt($exe_id, $status = null)
1337
    {
1338
        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
1339
        $table_track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
1340
        $table_track_attempt_recording = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING);
1341
        $exe_id = intval($exe_id);
1342
1343
        $status = Database::escape_string($status);
1344
1345
        $sql = "SELECT * FROM $table_track_exercises
1346
                WHERE status = '".$status."' AND exe_id = $exe_id";
1347
1348
        $res = Database::query($sql);
1349
        $list = array();
1350
        if (Database::num_rows($res)) {
1351
            $row = Database::fetch_array($res, 'ASSOC');
1352
1353
            //Checking if this attempt was revised by a teacher
1354
            $sql_revised = 'SELECT exe_id FROM '.$table_track_attempt_recording.'
1355
                            WHERE author != "" AND exe_id = '.$exe_id.' 
1356
                            LIMIT 1';
1357
            $res_revised = Database::query($sql_revised);
1358
            $row['attempt_revised'] = 0;
1359
            if (Database::num_rows($res_revised) > 0) {
1360
                $row['attempt_revised'] = 1;
1361
            }
1362
            $list[$exe_id] = $row;
1363
            $sql = "SELECT * FROM $table_track_attempt
1364
                    WHERE exe_id = $exe_id 
1365
                    ORDER BY tms ASC";
1366
            $res_question = Database::query($sql);
1367
            while ($row_q = Database::fetch_array($res_question, 'ASSOC')) {
1368
                $list[$exe_id]['question_list'][$row_q['question_id']] = $row_q;
1369
            }
1370
        }
1371
1372
        return $list;
1373
    }
1374
1375
    /**
1376
     * Gets exercise results (NO Exercises in LPs) from a given user, exercise id, course, session, lp_id, lp_item_id
1377
     * @param   int     user id
1378
     * @param   int     exercise id
1379
     * @param   string  course code
1380
     * @param   int     session id
1381
     * @param   int     lp id
1382
     * @param   int     lp item id
1383
     * @param   string order asc or desc
1384
     * @return  array   with the results
1385
     *
1386
     */
1387
    public static function getExerciseResultsByUser(
1388
        $user_id,
1389
        $exercise_id,
1390
        $courseId,
1391
        $session_id = 0,
1392
        $lp_id = 0,
1393
        $lp_item_id = 0,
1394
        $order = null
1395
    ) {
1396
        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
1397
        $table_track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
1398
        $table_track_attempt_recording = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING);
1399
        $courseId = intval($courseId);
1400
        $exercise_id = intval($exercise_id);
1401
        $session_id = intval($session_id);
1402
        $user_id = intval($user_id);
1403
        $lp_id = intval($lp_id);
1404
        $lp_item_id = intval($lp_item_id);
1405
1406
        if (!in_array(strtolower($order), array('asc', 'desc'))) {
1407
            $order = 'asc';
1408
        }
1409
1410
        $sql = "SELECT * FROM $table_track_exercises
1411
                WHERE
1412
                    status 			= '' AND
1413
                    exe_user_id 	= $user_id AND
1414
                    c_id 	        = $courseId AND
1415
                    exe_exo_id 		= $exercise_id AND
1416
                    session_id 		= $session_id AND
1417
                    orig_lp_id 		= $lp_id AND
1418
                    orig_lp_item_id = $lp_item_id
1419
                ORDER by exe_id $order ";
1420
1421
        $res = Database::query($sql);
1422
        $list = array();
1423
        while ($row = Database::fetch_array($res, 'ASSOC')) {
1424
            // Checking if this attempt was revised by a teacher
1425
            $sql = 'SELECT exe_id FROM '.$table_track_attempt_recording.'
1426
                    WHERE author != "" AND exe_id = '.$row['exe_id'].'
1427
                    LIMIT 1';
1428
            $res_revised = Database::query($sql);
1429
            $row['attempt_revised'] = 0;
1430
            if (Database::num_rows($res_revised) > 0) {
1431
                $row['attempt_revised'] = 1;
1432
            }
1433
            $list[$row['exe_id']] = $row;
1434
            $sql = "SELECT * FROM $table_track_attempt
1435
                    WHERE exe_id = {$row['exe_id']}";
1436
            $res_question = Database::query($sql);
1437
            while ($row_q = Database::fetch_array($res_question, 'ASSOC')) {
1438
                $list[$row['exe_id']]['question_list'][$row_q['question_id']][] = $row_q;
1439
            }
1440
        }
1441
        return $list;
1442
    }
1443
1444
    /**
1445
     * Count exercise attempts (NO Exercises in LPs ) from a given exercise id, course, session
1446
     * @param int $user_id
1447
     * @param   int     exercise id
1448
     * @param   int     $courseId
1449
     * @param   int     session id
1450
     * @return  array   with the results
1451
     *
1452
     */
1453
    public static function count_exercise_attempts_by_user(
1454
        $user_id,
1455
        $exercise_id,
1456
        $courseId,
1457
        $session_id = 0
1458
    ) {
1459
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
1460
        $courseId = intval($courseId);
1461
        $exercise_id = intval($exercise_id);
1462
        $session_id = intval($session_id);
1463
        $user_id = intval($user_id);
1464
1465
        $sql = "SELECT count(*) as count 
1466
                FROM $table
1467
                WHERE status = ''  AND
1468
                    exe_user_id = '$user_id' AND
1469
                    c_id = '$courseId' AND
1470
                    exe_exo_id = '$exercise_id' AND
1471
                    session_id = $session_id AND
1472
                    orig_lp_id =0 AND
1473
                    orig_lp_item_id = 0
1474
                ORDER BY exe_id";
1475
        $res = Database::query($sql);
1476
        $result = 0;
1477
        if (Database::num_rows($res) > 0) {
1478
            $row = Database::fetch_array($res, 'ASSOC');
1479
            $result = $row['count'];
1480
        }
1481
1482
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result also could return the type integer which is incompatible with the documented return type array.
Loading history...
1483
    }
1484
1485
    /**
1486
     * Gets all exercise BEST results attempts (NO Exercises in LPs)
1487
     * from a given exercise id, course, session per user
1488
     * @param   int     $exercise_id
1489
     * @param   int     $courseId
1490
     * @param   int     $session_id
1491
     * @param int $userId
1492
     * @return  array   with the results
1493
     * @todo rename this function
1494
     */
1495
    public static function get_best_exercise_results_by_user(
1496
        $exercise_id,
1497
        $courseId,
1498
        $session_id = 0,
1499
        $userId = 0
1500
    ) {
1501
        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
1502
        $table_track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
1503
        $courseId = intval($courseId);
1504
        $exercise_id = intval($exercise_id);
1505
        $session_id = intval($session_id);
1506
1507
        $sql = "SELECT * FROM $table_track_exercises
1508
                WHERE
1509
                    status = '' AND
1510
                    c_id = $courseId AND
1511
                    exe_exo_id = '$exercise_id' AND
1512
                    session_id = $session_id AND
1513
                    orig_lp_id = 0 AND
1514
                    orig_lp_item_id = 0";
1515
1516
        if (!empty($userId)) {
1517
            $userId = (int) $userId;
1518
            $sql .= " AND exe_user_id = $userId ";
1519
        }
1520
        $sql .= " ORDER BY exe_id";
1521
1522
        $res = Database::query($sql);
1523
        $list = array();
1524
        while ($row = Database::fetch_array($res, 'ASSOC')) {
1525
            $list[$row['exe_id']] = $row;
1526
            $sql = "SELECT * FROM $table_track_attempt 
1527
                    WHERE exe_id = {$row['exe_id']}";
1528
            $res_question = Database::query($sql);
1529
            while ($row_q = Database::fetch_array($res_question, 'ASSOC')) {
1530
                $list[$row['exe_id']]['question_list'][$row_q['question_id']] = $row_q;
1531
            }
1532
        }
1533
1534
        // Getting the best results of every student
1535
        $best_score_return = array();
1536
        foreach ($list as $student_result) {
1537
            $user_id = $student_result['exe_user_id'];
1538
            $current_best_score[$user_id] = $student_result['exe_result'];
1539
1540
            //echo $current_best_score[$user_id].' - '.$best_score_return[$user_id]['exe_result'].'<br />';
1541
            if (!isset($best_score_return[$user_id]['exe_result'])) {
1542
                $best_score_return[$user_id] = $student_result;
1543
            }
1544
1545
            if ($current_best_score[$user_id] > $best_score_return[$user_id]['exe_result']) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $current_best_score seems to be defined later in this foreach loop on line 1538. Are you sure it is defined here?
Loading history...
1546
                $best_score_return[$user_id] = $student_result;
1547
            }
1548
        }
1549
1550
        return $best_score_return;
1551
    }
1552
1553
    /**
1554
     * @param int $user_id
1555
     * @param int $exercise_id
1556
     * @param int $courseId
1557
     * @param int $session_id
1558
     * @return array
1559
     */
1560
    public static function get_best_attempt_exercise_results_per_user(
1561
        $user_id,
1562
        $exercise_id,
1563
        $courseId,
1564
        $session_id = 0
1565
    ) {
1566
        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
1567
        $courseId = intval($courseId);
1568
        $exercise_id = intval($exercise_id);
1569
        $session_id = intval($session_id);
1570
        $user_id = intval($user_id);
1571
1572
        $sql = "SELECT * FROM $table_track_exercises
1573
                WHERE
1574
                    status = ''  AND
1575
                    c_id = '$courseId' AND
1576
                    exe_exo_id = '$exercise_id' AND
1577
                    session_id = $session_id  AND
1578
                    exe_user_id = $user_id AND
1579
                    orig_lp_id =0 AND
1580
                    orig_lp_item_id = 0
1581
                ORDER BY exe_id";
1582
1583
        $res = Database::query($sql);
1584
        $list = array();
1585
        while ($row = Database::fetch_array($res, 'ASSOC')) {
1586
            $list[$row['exe_id']] = $row;
1587
        }
1588
        //Getting the best results of every student
1589
        $best_score_return = array();
1590
        $best_score_return['exe_result'] = 0;
1591
1592
        foreach ($list as $result) {
1593
            $current_best_score = $result;
1594
            if ($current_best_score['exe_result'] > $best_score_return['exe_result']) {
1595
                $best_score_return = $result;
1596
            }
1597
        }
1598
        if (!isset($best_score_return['exe_weighting'])) {
1599
            $best_score_return = array();
1600
        }
1601
        return $best_score_return;
1602
    }
1603
1604
    /**
1605
     * @param int $exercise_id
1606
     * @param int $courseId
1607
     * @param int $session_id
1608
     * @return mixed
1609
     */
1610
    public static function count_exercise_result_not_validated(
1611
        $exercise_id,
1612
        $courseId,
1613
        $session_id = 0
1614
    ) {
1615
        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
1616
        $table_track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING);
1617
        $courseId = intval($courseId);
1618
        $session_id = intval($session_id);
1619
        $exercise_id = intval($exercise_id);
1620
1621
        $sql = "SELECT count(e.exe_id) as count
1622
                FROM $table_track_exercises e
1623
                LEFT JOIN $table_track_attempt a
1624
                ON e.exe_id = a.exe_id
1625
                WHERE
1626
                    exe_exo_id = $exercise_id AND
1627
                    c_id = '$courseId' AND
1628
                    e.session_id = $session_id  AND
1629
                    orig_lp_id = 0 AND
1630
                    marks IS NULL AND
1631
                    status = '' AND
1632
                    orig_lp_item_id = 0
1633
                ORDER BY e.exe_id";
1634
        $res = Database::query($sql);
1635
        $row = Database::fetch_array($res, 'ASSOC');
1636
1637
        return $row['count'];
1638
    }
1639
1640
    /**
1641
     * Gets all exercise BEST results attempts (NO Exercises in LPs)
1642
     * from a given exercise id, course, session per user
1643
     * @param   int     exercise id
1644
     * @param   int   course id
1645
     * @param   int     session id
1646
     * @return  array   with the results
1647
     *
1648
     */
1649
    public static function get_count_exercises_attempted_by_course(
1650
        $courseId,
1651
        $session_id = 0
1652
    ) {
1653
        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
1654
        $courseId = intval($courseId);
1655
        $session_id = intval($session_id);
1656
1657
        $sql = "SELECT DISTINCT exe_exo_id, exe_user_id
1658
                FROM $table_track_exercises
1659
                WHERE
1660
                    status = '' AND
1661
                    c_id = '$courseId' AND
1662
                    session_id = $session_id AND
1663
                    orig_lp_id =0 AND
1664
                    orig_lp_item_id = 0
1665
                ORDER BY exe_id";
1666
        $res = Database::query($sql);
1667
        $count = 0;
1668
        if (Database::num_rows($res) > 0) {
1669
            $count = Database::num_rows($res);
1670
        }
1671
        return $count;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $count returns the type integer which is incompatible with the documented return type array.
Loading history...
1672
    }
1673
1674
    /**
1675
     * Gets all exercise events from a Learning Path within a Course    nd Session
1676
     * @param int $exercise_id
1677
     * @param int $courseId
1678
     * @param int $session_id
1679
     * @return array
1680
     */
1681
    public static function get_all_exercise_event_from_lp(
1682
        $exercise_id,
1683
        $courseId,
1684
        $session_id = 0
1685
    ) {
1686
        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
1687
        $table_track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
1688
        $courseId = intval($courseId);
1689
        $exercise_id = intval($exercise_id);
1690
        $session_id = intval($session_id);
1691
1692
        $sql = "SELECT * FROM $table_track_exercises
1693
                WHERE
1694
                    status = '' AND
1695
                    c_id = $courseId AND
1696
                    exe_exo_id = '$exercise_id' AND
1697
                    session_id = $session_id AND
1698
                    orig_lp_id !=0 AND
1699
                    orig_lp_item_id != 0";
1700
1701
        $res = Database::query($sql);
1702
        $list = array();
1703
        while ($row = Database::fetch_array($res, 'ASSOC')) {
1704
            $list[$row['exe_id']] = $row;
1705
            $sql = "SELECT * FROM $table_track_attempt 
1706
                    WHERE exe_id = {$row['exe_id']}";
1707
            $res_question = Database::query($sql);
1708
            while ($row_q = Database::fetch_array($res_question, 'ASSOC')) {
1709
                $list[$row['exe_id']]['question_list'][$row_q['question_id']] = $row_q;
1710
            }
1711
        }
1712
        return $list;
1713
    }
1714
1715
    /**
1716
     * @param int $lp_id
1717
     * @param int $course_id
1718
     *
1719
     * @return array
1720
     */
1721
    public static function get_all_exercises_from_lp($lp_id, $course_id)
1722
    {
1723
        $lp_item_table = Database::get_course_table(TABLE_LP_ITEM);
1724
        $course_id = intval($course_id);
1725
        $lp_id = intval($lp_id);
1726
        $sql = "SELECT * FROM $lp_item_table
1727
                WHERE
1728
                    c_id = $course_id AND
1729
                    lp_id = '".$lp_id."' AND
1730
                    item_type = 'quiz'
1731
                ORDER BY parent_item_id, display_order";
1732
        $res = Database::query($sql);
1733
1734
        $my_exercise_list = array();
1735
        while ($row = Database::fetch_array($res, 'ASSOC')) {
1736
            $my_exercise_list[] = $row;
1737
        }
1738
1739
        return $my_exercise_list;
1740
    }
1741
1742
    /**
1743
     * This function gets the comments of an exercise
1744
     *
1745
     * @param int $exe_id
1746
     * @param int $question_id
1747
     *
1748
     * @return string the comment
1749
     */
1750
    public static function get_comments($exe_id, $question_id)
1751
    {
1752
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
1753
        $sql = "SELECT teacher_comment 
1754
                FROM $table
1755
                WHERE
1756
                    exe_id='".Database::escape_string($exe_id)."' AND
1757
                    question_id = '".Database::escape_string($question_id)."'
1758
                ORDER by question_id";
1759
        $sqlres = Database::query($sql);
1760
        $comm = Database::result($sqlres, 0, 'teacher_comment');
1761
        $comm = trim($comm);
1762
1763
        return $comm;
1764
    }
1765
1766
    /**
1767
     * @param int $exeId
1768
     *
1769
     * @return array
1770
     */
1771
    public static function getAllExerciseEventByExeId($exeId)
1772
    {
1773
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
1774
        $exeId = intval($exeId);
1775
1776
        $sql = "SELECT * FROM $table
1777
                WHERE exe_id = $exeId
1778
                ORDER BY position";
1779
        $res_question = Database::query($sql);
1780
        $list = array();
1781
        if (Database::num_rows($res_question)) {
1782
            while ($row = Database::fetch_array($res_question, 'ASSOC')) {
1783
                $list[$row['question_id']][] = $row;
1784
            }
1785
        }
1786
        return $list;
1787
    }
1788
1789
    /**
1790
     *
1791
     * @param int $exeId
1792
     * @param int $user_id
1793
     * @param int $courseId
1794
     * @param int $session_id
1795
     * @param int $question_id
1796
     */
1797
    public static function delete_attempt(
1798
        $exeId,
1799
        $user_id,
1800
        $courseId,
1801
        $session_id,
1802
        $question_id
1803
    ) {
1804
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
1805
1806
        $exeId = intval($exeId);
1807
        $user_id = intval($user_id);
1808
        $courseId = intval($courseId);
1809
        $session_id = intval($session_id);
1810
        $question_id = intval($question_id);
1811
1812
        $sql = "DELETE FROM $table
1813
                WHERE
1814
                    exe_id = $exeId AND
1815
                    user_id = $user_id AND
1816
                    c_id = $courseId AND
1817
                    session_id = $session_id AND
1818
                    question_id = $question_id ";
1819
        Database::query($sql);
1820
1821
        self::addEvent(
1822
            LOG_QUESTION_RESULT_DELETE,
1823
            LOG_EXERCISE_ATTEMPT_QUESTION_ID,
1824
            $exeId.'-'.$question_id,
1825
            null,
1826
            null,
1827
            $courseId,
1828
            $session_id
1829
        );
1830
    }
1831
1832
    /**
1833
     * @param $exeId
1834
     * @param $user_id
1835
     * @param int $courseId
1836
     * @param $question_id
1837
     * @param int $sessionId
1838
     */
1839
    public static function delete_attempt_hotspot(
1840
        $exeId,
1841
        $user_id,
1842
        $courseId,
1843
        $question_id,
1844
        $sessionId = null
1845
    ) {
1846
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTSPOT);
1847
1848
        $exeId = intval($exeId);
1849
        $user_id = intval($user_id);
1850
        $courseId = intval($courseId);
1851
        $question_id = intval($question_id);
1852
        if (!isset($sessionId)) {
1853
            $sessionId = api_get_session_id();
1854
        }
1855
1856
        $sql = "DELETE FROM $table
1857
                WHERE   
1858
                    hotspot_exe_id = $exeId AND
1859
                    hotspot_user_id = $user_id AND
1860
                    c_id = $courseId AND
1861
                    hotspot_question_id = $question_id ";
1862
        Database::query($sql);
1863
        self::addEvent(
1864
            LOG_QUESTION_RESULT_DELETE,
1865
            LOG_EXERCISE_ATTEMPT_QUESTION_ID,
1866
            $exeId.'-'.$question_id,
1867
            null,
1868
            null,
1869
            $courseId,
1870
            $sessionId
1871
        );
1872
    }
1873
1874
    /**
1875
     * Registers in track_e_course_access when user logs in for the first time to a course
1876
     * @param int $courseId ID of the course
1877
     * @param int $user_id ID of the user
1878
     * @param int $sessionId ID of the session (if any)
1879
     *
1880
     * @return bool
1881
     */
1882
    public static function eventCourseLogin($courseId, $user_id, $sessionId)
1883
    {
1884
        if (Session::read('login_as')) {
1885
            return false;
1886
        }
1887
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
1888
        $loginDate = $logoutDate = api_get_utc_datetime();
1889
1890
        // $counter represents the number of time this record has been refreshed
1891
        $counter = 1;
1892
        $courseId = intval($courseId);
1893
        $user_id = intval($user_id);
1894
        $sessionId = intval($sessionId);
1895
        $ip = api_get_real_ip();
1896
1897
        $sql = "INSERT INTO $table(c_id, user_ip, user_id, login_course_date, logout_course_date, counter, session_id)
1898
                VALUES('".$courseId."', '".$ip."', '".$user_id."', '$loginDate', '$logoutDate', $counter, '".$sessionId."')";
1899
        $courseAccessId = Database::query($sql);
1900
1901
        if ($courseAccessId) {
1902
            // Course catalog stats modifications see #4191
1903
            CourseManager::update_course_ranking(
1904
                null,
1905
                null,
1906
                null,
1907
                null,
1908
                true,
1909
                false
1910
            );
1911
            return true;
1912
        }
1913
    }
1914
1915
    /**
1916
     * Updates the user - course - session every X minutes
1917
     * In order to avoid
1918
     * @param int $courseId
1919
     * @param int $userId
1920
     * @param int $sessionId
1921
     * @param int $minutes
1922
     *
1923
     * @return bool
1924
     */
1925
    public static function eventCourseLoginUpdate(
1926
        $courseId,
1927
        $userId,
1928
        $sessionId,
1929
        $minutes = 5
1930
    ) {
1931
        if (Session::read('login_as')) {
1932
            return false;
1933
        }
1934
1935
        if (empty($courseId) || empty($userId)) {
1936
            return false;
1937
        }
1938
1939
        $courseId = intval($courseId);
1940
        $userId = intval($userId);
1941
        $sessionId = intval($sessionId);
1942
1943
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
1944
        $sql = "SELECT course_access_id, logout_course_date 
1945
                FROM $table 
1946
                WHERE 
1947
                    c_id = $courseId AND
1948
                    session_id = $sessionId AND   
1949
                    user_id = $userId                     
1950
                ORDER BY login_course_date DESC
1951
                LIMIT 1";
1952
1953
        $result = Database::query($sql);
1954
1955
        // Save every 5 minutes by default
1956
        $seconds = $minutes * 60;
1957
        $maxSeconds = 3600; // Only update if max diff is one hour
1958
        if (Database::num_rows($result)) {
1959
            $row = Database::fetch_array($result);
1960
            $id = $row['course_access_id'];
1961
            $logout = $row['logout_course_date'];
1962
            $now = time();
1963
            $logout = api_strtotime($logout, 'UTC');
1964
            if ($now - $logout > $seconds &&
1965
                $now - $logout < $maxSeconds
1966
            ) {
1967
                $now = api_get_utc_datetime();
1968
                $sql = "UPDATE $table SET 
1969
                            logout_course_date = '$now', 
1970
                            counter = counter + 1
1971
                        WHERE course_access_id = $id";
1972
                Database::query($sql);
1973
            }
1974
1975
            return true;
1976
        }
1977
1978
        return false;
1979
    }
1980
1981
    /**
1982
     * Register the logout of the course (usually when logging out of the platform)
1983
     * from the track_e_course_access table
1984
     * @param array $logoutInfo Information stored by local.inc.php
1985
     * before new context ['uid'=> x, 'cid'=>y, 'sid'=>z]
1986
     * @return bool
1987
     */
1988
    public static function courseLogout($logoutInfo)
1989
    {
1990
        if (Session::read('login_as')) {
1991
            return false;
1992
        }
1993
1994
        if (empty($logoutInfo['uid']) || empty($logoutInfo['cid'])) {
1995
            return false;
1996
        }
1997
1998
        $sessionLifetime = api_get_configuration_value('session_lifetime');
1999
        /*
2000
         * When $_configuration['session_lifetime'] is larger than ~100 hours
2001
         * (in order to let users take exercises with no problems)
2002
         * the function Tracking::get_time_spent_on_the_course() returns larger values (200h) due the condition:
2003
         * login_course_date > now() - INTERVAL $session_lifetime SECOND
2004
         */
2005
        if (empty($sessionLifetime) || $sessionLifetime > 86400) {
2006
            $sessionLifetime = 3600; // 1 hour
2007
        }
2008
        if (!empty($logoutInfo) && !empty($logoutInfo['cid'])) {
2009
            $tableCourseAccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
2010
            $userId = intval($logoutInfo['uid']);
2011
            $courseId = intval($logoutInfo['cid']);
2012
            $sessionId = 0;
2013
            if (!empty($logoutInfo['sid'])) {
2014
                $sessionId = intval($logoutInfo['sid']);
2015
            }
2016
            $currentDate = api_get_utc_datetime();
2017
            // UTC time
2018
            $diff = time() - $sessionLifetime;
2019
            $time = api_get_utc_datetime($diff);
2020
            $sql = "SELECT course_access_id, logout_course_date
2021
                    FROM $tableCourseAccess
2022
                    WHERE 
2023
                        user_id = $userId AND
2024
                        c_id = $courseId  AND
2025
                        session_id = $sessionId AND
2026
                        login_course_date > '$time'
2027
                    ORDER BY login_course_date DESC 
2028
                    LIMIT 1";
2029
            $result = Database::query($sql);
2030
            $insert = false;
2031
            if (Database::num_rows($result) > 0) {
2032
                $row = Database::fetch_array($result, 'ASSOC');
2033
                $courseAccessId = $row['course_access_id'];
2034
                /*$logout = $row['logout_course_date'];
2035
                $now = time();
2036
                $logout = api_strtotime($logout, 'UTC');
2037
                */
2038
                //if ($now - $logout < $sessionLifetime) {
2039
                    $sql = "UPDATE $tableCourseAccess SET 
2040
                                logout_course_date = '$currentDate', 
2041
                                counter = counter + 1
2042
                            WHERE course_access_id = $courseAccessId";
2043
                    Database::query($sql);
2044
                //}
2045
            } else {
2046
                $insert = true;
2047
            }
2048
2049
            if ($insert) {
2050
                $ip = api_get_real_ip();
2051
                $sql = "INSERT INTO $tableCourseAccess (c_id, user_ip, user_id, login_course_date, logout_course_date, counter, session_id)
2052
                        VALUES ($courseId, '$ip', $userId, '$currentDate', '$currentDate', 1, $sessionId)";
2053
                Database::query($sql);
2054
            }
2055
2056
            return true;
2057
        }
2058
    }
2059
2060
    /**
2061
     * Register a "fake" time spent on the platform, for example to match the
2062
     * estimated time he took to author an assignment/work, see configuration
2063
     * setting considered_working_time.
2064
     * This assumes there is already some connection of the student to the
2065
     * course, otherwise he wouldn't be able to upload an assignment.
2066
     * This works by creating a new record, copy of the current one, then
2067
     * updating the current one to be just the considered_working_time and
2068
     * end at the same second as the user connected to the course.
2069
     * @param int $courseId The course in which to add the time
2070
     * @param int $userId The user for whom to add the time
2071
     * @param int $sessionId The session in which to add the time (if any)
2072
     * @param string $virtualTime The amount of time to be added,
2073
     * in a hh:mm:ss format. If int, we consider it is expressed in hours.
2074
     * @param string $ip IP address to go on record for this time record
2075
     *
2076
     * @return True on successful insertion, false otherwise
2077
     */
2078
    public static function eventAddVirtualCourseTime(
2079
        $courseId,
2080
        $userId,
2081
        $sessionId,
2082
        $virtualTime = '',
2083
        $ip = ''
2084
    ) {
2085
        $courseTrackingTable = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
2086
        $time = $loginDate = $logoutDate = api_get_utc_datetime();
2087
2088
        $courseId = intval($courseId);
2089
        $userId = intval($userId);
2090
        $sessionId = intval($sessionId);
2091
        $ip = Database::escape_string($ip);
2092
2093
        // Get the current latest course connection register. We need that
2094
        // record to re-use the data and create a new record.
2095
        $sql = "SELECT *
2096
                FROM $courseTrackingTable
2097
                WHERE
2098
                    user_id = ".$userId." AND
2099
                    c_id = ".$courseId."  AND
2100
                    session_id  = ".$sessionId." AND
2101
                    login_course_date > '$time' - INTERVAL 3600 SECOND
2102
                ORDER BY login_course_date DESC 
2103
                LIMIT 0,1";
2104
        $result = Database::query($sql);
2105
2106
        // Ignore if we didn't find any course connection record in the last
2107
        // hour. In this case it wouldn't be right to add a "fake" time record.
2108
        if (Database::num_rows($result) > 0) {
2109
            // Found the latest connection
2110
            $row = Database::fetch_array($result);
2111
            $courseAccessId = $row['course_access_id'];
2112
            $courseAccessLoginDate = $row['login_course_date'];
2113
            $counter = $row['counter'];
2114
            $counter = $counter ? $counter : 0;
2115
            // Insert a new record, copy of the current one (except the logout
2116
            // date that we update to the current time)
2117
            $sql = "INSERT INTO $courseTrackingTable(
2118
                    c_id,
2119
                    user_ip, 
2120
                    user_id, 
2121
                    login_course_date, 
2122
                    logout_course_date, 
2123
                    counter, 
2124
                    session_id
2125
                ) VALUES(
2126
                    $courseId, 
2127
                    '$ip', 
2128
                    $userId, 
2129
                    '$courseAccessLoginDate', 
2130
                    '$logoutDate', 
2131
                    $counter, 
2132
                    $sessionId
2133
                )";
2134
            Database::query($sql);
2135
2136
            $loginDate = ChamiloApi::addOrSubTimeToDateTime(
2137
                $virtualTime,
2138
                $courseAccessLoginDate,
2139
                false
2140
            );
2141
            // We update the course tracking table
2142
            $sql = "UPDATE $courseTrackingTable  
2143
                    SET 
2144
                        login_course_date = '$loginDate',
2145
                        logout_course_date = '$courseAccessLoginDate',
2146
                        counter = 0
2147
                    WHERE 
2148
                        course_access_id = ".intval($courseAccessId)." AND 
2149
                        session_id = ".$sessionId;
2150
            Database::query($sql);
2151
2152
            return true;
2153
        }
2154
2155
        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 true.
Loading history...
2156
    }
2157
    /**
2158
     * Removes a "fake" time spent on the platform, for example to match the
2159
     * estimated time he took to author an assignment/work, see configuration
2160
     * setting considered_working_time.
2161
     * This method should be called when something that generated a fake
2162
     * time record is removed. Given the database link is weak (no real
2163
     * relationship kept between the deleted item and this record), this
2164
     * method just looks for the latest record that has the same time as the
2165
     * item's fake time, is in the past and in this course+session. If such a
2166
     * record cannot be found, it doesn't do anything.
2167
     * The IP address is not considered a useful filter here.
2168
     * @param int $courseId The course in which to add the time
2169
     * @param int $userId The user for whom to add the time
2170
     * @param int $sessionId The session in which to add the time (if any)
2171
     * @param string $virtualTime The amount of time to be added, in a hh:mm:ss format. If int, we consider it is expressed in hours.
2172
     * @return True on successful removal, false otherwise
2173
     */
2174
    public static function eventRemoveVirtualCourseTime(
2175
        $courseId,
2176
        $userId,
2177
        $sessionId = 0,
2178
        $virtualTime = ''
2179
    ) {
2180
        if (empty($virtualTime)) {
2181
            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 true.
Loading history...
2182
        }
2183
        $courseTrackingTable = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
2184
        $time = $loginDate = $logoutDate = api_get_utc_datetime();
2185
2186
        $courseId = intval($courseId);
2187
        $userId = intval($userId);
2188
        $sessionId = intval($sessionId);
2189
        // Change $virtualTime format from hh:mm:ss to hhmmss which is the
2190
        // format returned by SQL for a subtraction of two datetime values
2191
        // @todo make sure this is portable between DBMSes
2192
        if (preg_match('/:/', $virtualTime)) {
2193
            list($h, $m, $s) = preg_split('/:/', $virtualTime);
2194
            $virtualTime = $h * 3600 + $m * 60 + $s;
2195
        } else {
2196
            $virtualTime *= 3600;
2197
        }
2198
2199
        // Get the current latest course connection register. We need that
2200
        // record to re-use the data and create a new record.
2201
        $sql = "SELECT course_access_id
2202
                FROM $courseTrackingTable
2203
                WHERE
2204
                    user_id = $userId AND
2205
                    c_id = $courseId  AND
2206
                    session_id  = $sessionId AND
2207
                    counter = 0 AND
2208
                    (UNIX_TIMESTAMP(logout_course_date) - UNIX_TIMESTAMP(login_course_date)) = '$virtualTime'
2209
                ORDER BY login_course_date DESC LIMIT 0,1";
2210
        $result = Database::query($sql);
2211
2212
        // Ignore if we didn't find any course connection record in the last
2213
        // hour. In this case it wouldn't be right to add a "fake" time record.
2214
        if (Database::num_rows($result) > 0) {
2215
            // Found the latest connection
2216
            $row = Database::fetch_row($result);
2217
            $courseAccessId = $row[0];
2218
            $sql = "DELETE FROM $courseTrackingTable 
2219
                    WHERE course_access_id = $courseAccessId";
2220
            $result = Database::query($sql);
2221
2222
            return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result returns the type Doctrine\DBAL\Driver\Statement which is incompatible with the documented return type true.
Loading history...
2223
        }
2224
2225
        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 true.
Loading history...
2226
    }
2227
2228
    /**
2229
     * For the sake of genericity, this function is a switch.
2230
     * It's called by EventsDispatcher and fires the good function
2231
     * with the good require_once.
2232
     *
2233
     * @deprecated
2234
     * @param string $event_name
2235
     * @param array $params
2236
     */
2237
    public static function event_send_mail($event_name, $params)
2238
    {
2239
        EventsMail::send_mail($event_name, $params);
2240
    }
2241
2242
    /**
2243
     * Internal function checking if the mail was already sent from that user to that user
2244
     * @param string $event_name
2245
     * @param int $user_from
2246
     * @param int $user_to
2247
     * @return boolean
2248
     */
2249
    public static function check_if_mail_already_sent(
2250
        $event_name,
2251
        $user_from,
2252
        $user_to = null
2253
    ) {
2254
        if ($user_to == null) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $user_to of type null|integer against null; this is ambiguous if the integer can be zero. Consider using a strict comparison === instead.
Loading history...
2255
            $sql = 'SELECT COUNT(*) as total 
2256
                    FROM '.Database::get_main_table(TABLE_EVENT_SENT).'
2257
                    WHERE 
2258
                        user_from = '.$user_from.' AND 
2259
                        event_type_name = "'.$event_name.'"';
2260
        } else {
2261
            $sql = 'SELECT COUNT(*) as total 
2262
                    FROM '.Database::get_main_table(TABLE_EVENT_SENT).'
2263
                    WHERE 
2264
                        user_from = '.$user_from.' AND 
2265
                        user_to = '.$user_to.' AND 
2266
                        event_type_name = "'.$event_name.'"';
2267
        }
2268
        $result = Database::store_result(Database::query($sql), 'ASSOC');
2269
2270
        return $result[0]["total"];
2271
    }
2272
2273
    /**
2274
     * Filter EventEmailTemplate Filters see the main/inc/conf/events.conf.dist.php
2275
     */
2276
2277
    /**
2278
     * Basic template event message filter (to be used by other filters as default)
2279
     * @deprecated
2280
     * @param array $values (passing by reference)     *
2281
     * @return boolean True if everything is OK, false otherwise
2282
     */
2283
    public function event_send_mail_filter_func(&$values)
0 ignored issues
show
Unused Code introduced by
The parameter $values is not used and could be removed. ( Ignorable by Annotation )

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

2283
    public function event_send_mail_filter_func(/** @scrutinizer ignore-unused */ &$values)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
2284
    {
2285
        return true;
2286
    }
2287
2288
    /**
2289
     * user_registration - send_mail filter
2290
     * @deprecated
2291
     * @param array $values (passing by reference)
2292
     * @return boolean True if everything is OK, false otherwise
2293
     */
2294
    public function user_registration_event_send_mail_filter_func(&$values)
2295
    {
2296
        $res = self::event_send_mail_filter_func($values);
0 ignored issues
show
Bug Best Practice introduced by
The method Event::event_send_mail_filter_func() is not static, but was called statically. ( Ignorable by Annotation )

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

2296
        /** @scrutinizer ignore-call */ 
2297
        $res = self::event_send_mail_filter_func($values);
Loading history...
Deprecated Code introduced by
The function Event::event_send_mail_filter_func() has been deprecated. ( Ignorable by Annotation )

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

2296
        $res = /** @scrutinizer ignore-deprecated */ self::event_send_mail_filter_func($values);
Loading history...
2297
        // proper logic for this filter
2298
        return $res;
2299
    }
2300
2301
    /**
2302
     * portal_homepage_edited - send_mail filter
2303
     * @deprecated
2304
     * @param array $values (passing by reference)
2305
     * @return boolean True if everything is OK, false otherwise
2306
     */
2307
    public function portal_homepage_edited_event_send_mail_filter_func(&$values)
2308
    {
2309
        $res = self::event_send_mail_filter_func($values);
0 ignored issues
show
Bug Best Practice introduced by
The method Event::event_send_mail_filter_func() is not static, but was called statically. ( Ignorable by Annotation )

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

2309
        /** @scrutinizer ignore-call */ 
2310
        $res = self::event_send_mail_filter_func($values);
Loading history...
Deprecated Code introduced by
The function Event::event_send_mail_filter_func() has been deprecated. ( Ignorable by Annotation )

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

2309
        $res = /** @scrutinizer ignore-deprecated */ self::event_send_mail_filter_func($values);
Loading history...
2310
        // proper logic for this filter
2311
        return $res;
2312
    }
2313
}
2314