Completed
Push — master ( ae5621...ef667c )
by Julito
13:23
created

Event::addEvent()   C

Complexity

Conditions 10
Paths 193

Size

Total Lines 74
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 45
nc 193
nop 7
dl 0
loc 74
rs 5.4676
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

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

2227
    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...
2228
    {
2229
        return true;
2230
    }
2231
2232
    /**
2233
     * user_registration - send_mail filter.
2234
     *
2235
     * @deprecated
2236
     *
2237
     * @param array $values (passing by reference)
2238
     *
2239
     * @return bool True if everything is OK, false otherwise
2240
     */
2241
    public function user_registration_event_send_mail_filter_func(&$values)
2242
    {
2243
        $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

2243
        /** @scrutinizer ignore-call */ 
2244
        $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

2243
        $res = /** @scrutinizer ignore-deprecated */ self::event_send_mail_filter_func($values);
Loading history...
2244
        // proper logic for this filter
2245
        return $res;
2246
    }
2247
2248
    /**
2249
     * portal_homepage_edited - send_mail filter.
2250
     *
2251
     * @deprecated
2252
     *
2253
     * @param array $values (passing by reference)
2254
     *
2255
     * @return bool True if everything is OK, false otherwise
2256
     */
2257
    public function portal_homepage_edited_event_send_mail_filter_func(&$values)
2258
    {
2259
        $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

2259
        /** @scrutinizer ignore-call */ 
2260
        $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

2259
        $res = /** @scrutinizer ignore-deprecated */ self::event_send_mail_filter_func($values);
Loading history...
2260
        // proper logic for this filter
2261
        return $res;
2262
    }
2263
}
2264