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

Event::updateEventExercise()   C

Complexity

Conditions 7
Paths 17

Size

Total Lines 81
Code Lines 46

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 46
nc 17
nop 13
dl 0
loc 81
rs 6.5544
c 0
b 0
f 0

How to fix   Long Method    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

1
<?php
2
/* See license terms in /license.txt */
3
4
//use Chamilo\UserBundle\Entity\User;
5
use 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