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

Event::saveQuestionAttempt()   F

Complexity

Conditions 25
Paths > 20000

Size

Total Lines 176
Code Lines 108

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 25
eloc 108
nc 57888
nop 13
dl 0
loc 176
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

1
<?php
2
/* 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