Passed
Push — ofaj ( d9b422...0f9380 )
by
unknown
11:25 queued 11s
created

MySpace::display_tracking_lp_progress_overview()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 105
Code Lines 54

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 54
nc 4
nop 4
dl 0
loc 105
rs 9.0036
c 0
b 0
f 0

How to fix   Long Method   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use ChamiloSession as Session;
5
use CpChart\Cache as pCache;
6
use CpChart\Data as pData;
7
use CpChart\Image as pImage;
8
9
/**
10
 * Class MySpace.
11
 */
12
class MySpace
13
{
14
    /**
15
     * Get admin actions.
16
     *
17
     * @return string
18
     */
19
    public static function getAdminActions()
20
    {
21
        $actions = [
22
            [
23
                'url' => api_get_path(WEB_CODE_PATH).'mySpace/admin_view.php?display=coaches',
24
                'content' => get_lang('DisplayCoaches'),
25
            ],
26
            [
27
                'url' => api_get_path(WEB_CODE_PATH).'mySpace/admin_view.php?display=user',
28
                'content' => get_lang('DisplayUserOverview'),
29
            ],
30
            [
31
                'url' => api_get_path(WEB_CODE_PATH).'mySpace/admin_view.php?display=session',
32
                'content' => get_lang('DisplaySessionOverview'),
33
            ],
34
            [
35
                'url' => api_get_path(WEB_CODE_PATH).'mySpace/admin_view.php?display=course',
36
                'content' => get_lang('DisplayCourseOverview'),
37
            ],
38
            [
39
                'url' => api_get_path(WEB_CODE_PATH).'tracking/question_course_report.php?view=admin',
40
                'content' => get_lang('LPQuestionListResults'),
41
            ],
42
            [
43
                'url' => api_get_path(WEB_CODE_PATH).'tracking/course_session_report.php?view=admin',
44
                'content' => get_lang('LPExerciseResultsBySession'),
45
            ],
46
            [
47
                'url' => api_get_path(WEB_CODE_PATH).'mySpace/admin_view.php?display=accessoverview',
48
                'content' => get_lang('DisplayAccessOverview').' ('.get_lang('Beta').')',
49
            ],
50
            [
51
                'url' => api_get_path(WEB_CODE_PATH).'mySpace/exercise_category_report.php',
52
                'content' => get_lang('ExerciseCategoryAllSessionsReport'),
53
            ],
54
            [
55
                'url' => api_get_path(WEB_CODE_PATH).'mySpace/survey_report.php',
56
                'content' => get_lang('SurveyReport'),
57
            ],
58
            [
59
                'url' => api_get_path(WEB_CODE_PATH).'mySpace/tc_report.php',
60
                'content' => get_lang('TCReport'),
61
            ],
62
            [
63
                'url' => api_get_path(WEB_CODE_PATH).'mySpace/ti_report.php',
64
                'content' => get_lang('TIReport'),
65
            ],
66
        ];
67
68
        return Display::actions($actions, null);
69
    }
70
71
    /**
72
     * @return string
73
     */
74
    public static function getTopMenu()
75
    {
76
        $menuItems = [];
77
        $menuItems[] = Display::url(
78
            Display::return_icon(
79
                'statistics.png',
80
                get_lang('MyStats'),
81
                '',
82
                ICON_SIZE_MEDIUM
83
            ),
84
            api_get_path(WEB_CODE_PATH)."auth/my_progress.php"
85
        );
86
        $menuItems[] = Display::url(
87
            Display::return_icon(
88
                'teacher.png',
89
                get_lang('TeacherInterface'),
90
                [],
91
                32
92
            ),
93
            api_get_path(WEB_CODE_PATH).'mySpace/?view=teacher'
94
        );
95
        $menuItems[] = Display::url(
96
            Display::return_icon(
97
                'star_na.png',
98
                get_lang('AdminInterface'),
99
                [],
100
                32
101
            ),
102
            '#'
103
        );
104
        $menuItems[] = Display::url(
105
            Display::return_icon('quiz.png', get_lang('ExamTracking'), [], 32),
106
            api_get_path(WEB_CODE_PATH).'tracking/exams.php'
107
        );
108
        $menu = '';
109
        foreach ($menuItems as $item) {
110
            $menu .= $item;
111
        }
112
        $menu .= '<br />';
113
114
        return $menu;
115
    }
116
117
    /**
118
     * This function serves exporting data in CSV format.
119
     *
120
     * @param array  $header    the header labels
121
     * @param array  $data      the data array
122
     * @param string $file_name the name of the file which contains exported data
123
     *
124
     * @return string mixed             Returns a message (string) if an error occurred
125
     */
126
    public function export_csv($header, $data, $file_name = 'export.csv')
127
    {
128
        $archive_path = api_get_path(SYS_ARCHIVE_PATH);
129
        $archive_url = api_get_path(WEB_CODE_PATH).'course_info/download.php?archive_path=&archive=';
130
        $message = '';
131
        if (!$open = fopen($archive_path.$file_name, 'w+')) {
132
            $message = get_lang('noOpen');
133
        } else {
134
            $info = '';
135
136
            foreach ($header as $value) {
137
                $info .= $value.';';
138
            }
139
            $info .= "\r\n";
140
141
            foreach ($data as $row) {
142
                foreach ($row as $value) {
143
                    $info .= $value.';';
144
                }
145
                $info .= "\r\n";
146
            }
147
148
            fwrite($open, $info);
149
            fclose($open);
150
            @chmod($file_name, api_get_permissions_for_new_files());
151
152
            header("Location:".$archive_url.$file_name);
153
            exit;
154
        }
155
156
        return $message;
157
    }
158
159
    /**
160
     * Gets the connections to a course as an array of login and logout time.
161
     *
162
     * @param int   $userId     User id
163
     * @param array $courseInfo
164
     * @param int   $sessionId  Session id (optional, default = 0)
165
     *
166
     * @return array Connections
167
     */
168
    public static function get_connections_to_course(
169
        $userId,
170
        $courseInfo,
171
        $sessionId = 0
172
    ) {
173
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
174
175
        // protect data
176
        $userId = (int) $userId;
177
        $courseId = (int) $courseInfo['real_id'];
178
        $sessionId = (int) $sessionId;
179
        $sessionCondition = api_get_session_condition($sessionId);
180
181
        $sql = 'SELECT login_course_date, logout_course_date
182
                FROM '.$table.'
183
                WHERE
184
                    user_id = '.$userId.' AND
185
                    c_id = '.$courseId.'
186
                    '.$sessionCondition.'
187
                ORDER BY login_course_date ASC';
188
        $rs = Database::query($sql);
189
        $connections = [];
190
191
        while ($row = Database::fetch_array($rs)) {
192
            $connections[] = [
193
                'login' => $row['login_course_date'],
194
                'logout' => $row['logout_course_date'],
195
            ];
196
        }
197
198
        return $connections;
199
    }
200
201
    /**
202
     * @param $user_id
203
     * @param $course_list
204
     * @param int $session_id
205
     *
206
     * @return array|bool
207
     */
208
    public static function get_connections_from_course_list(
209
        $user_id,
210
        $course_list,
211
        $session_id = 0
212
    ) {
213
        // Database table definitions
214
        $tbl_track_course = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
215
        if (empty($course_list)) {
216
            return false;
217
        }
218
219
        // protect data
220
        $user_id = (int) $user_id;
221
        $session_id = (int) $session_id;
222
        $new_course_list = [];
223
        foreach ($course_list as $course_item) {
224
            $courseInfo = api_get_course_info($course_item['code']);
225
            if ($courseInfo) {
226
                $courseId = $courseInfo['real_id'];
227
                $new_course_list[] = '"'.$courseId.'"';
228
            }
229
        }
230
        $course_list = implode(', ', $new_course_list);
231
232
        if (empty($course_list)) {
233
            return false;
234
        }
235
        $sql = 'SELECT login_course_date, logout_course_date, c_id
236
                FROM '.$tbl_track_course.'
237
                WHERE
238
                    user_id = '.$user_id.' AND
239
                    c_id IN ('.$course_list.') AND
240
                    session_id = '.$session_id.'
241
                ORDER BY login_course_date ASC';
242
        $rs = Database::query($sql);
243
        $connections = [];
244
245
        while ($row = Database::fetch_array($rs)) {
246
            $timestamp_login_date = api_strtotime($row['login_course_date'], 'UTC');
247
            $timestamp_logout_date = api_strtotime($row['logout_course_date'], 'UTC');
248
            $connections[] = [
249
                'login' => $timestamp_login_date,
250
                'logout' => $timestamp_logout_date,
251
                'c_id' => $row['c_id'],
252
            ];
253
        }
254
255
        return $connections;
256
    }
257
258
    /**
259
     * Creates a small table in the last column of the table with the user overview.
260
     *
261
     * @param int $user_id the id of the user
262
     *
263
     * @return array List course
264
     */
265
    public static function returnCourseTracking($user_id)
266
    {
267
        $user_id = (int) $user_id;
268
269
        if (empty($user_id)) {
270
            return [];
271
        }
272
273
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
274
        // getting all the courses of the user
275
        $sql = "SELECT * FROM $tbl_course_user
276
                WHERE
277
                    user_id = $user_id AND
278
                    relation_type <> ".COURSE_RELATION_TYPE_RRHH;
279
        $result = Database::query($sql);
280
281
        $list = [];
282
283
        while ($row = Database::fetch_array($result)) {
284
            $courseInfo = api_get_course_info_by_id($row['c_id']);
285
            $courseId = $courseInfo['real_id'];
286
            $courseCode = $courseInfo['code'];
287
288
            if (empty($courseInfo)) {
289
                continue;
290
            }
291
292
            $avg_score = Tracking::get_avg_student_score($user_id, $courseCode);
293
            if (is_numeric($avg_score)) {
294
                $avg_score = round($avg_score, 2);
295
            } else {
296
                $avg_score = '-';
297
            }
298
299
            // Student exercises results (obtained score, maximum score, number of exercises answered, score percentage)
300
            $exercisesResults = self::exercises_results($user_id, $courseCode);
301
302
            $resultToString = '';
303
            if (!is_null($exercisesResults['percentage'])) {
304
                $resultToString = $exercisesResults['score_obtained'].'/'.$exercisesResults['score_possible'].' ( '.$exercisesResults['percentage'].'% )';
305
            }
306
307
            $item = [
308
                'code' => $courseInfo['code'],
309
                'real_id' => $courseInfo['real_id'],
310
                'title' => $courseInfo['title'],
311
                'category' => $courseInfo['categoryName'],
312
                'image_small' => $courseInfo['course_image'],
313
                'image_large' => $courseInfo['course_image_large'],
314
                'time_spent' => api_time_to_hms(Tracking::get_time_spent_on_the_course($user_id, $courseId)),
315
                'student_progress' => round(Tracking::get_avg_student_progress($user_id, $courseCode)),
316
                'student_score' => $avg_score,
317
                'student_message' => Tracking::count_student_messages($user_id, $courseCode),
318
                'student_assignments' => Tracking::count_student_assignments($user_id, $courseCode),
319
                'student_exercises' => $resultToString,
320
                'questions_answered' => $exercisesResults['questions_answered'],
321
                'last_connection' => Tracking::get_last_connection_date_on_the_course($user_id, $courseInfo),
322
            ];
323
            $list[] = $item;
324
        }
325
326
        return $list;
327
    }
328
329
    /**
330
     * Creates a small table in the last column of the table with the user overview.
331
     *
332
     * @param int   $user_id    the id of the user
333
     * @param array $url_params additional url parameters
334
     * @param array $row        the row information (the other columns)
335
     *
336
     * @return string html code
337
     */
338
    public static function course_info_tracking_filter($user_id, $url_params, $row)
339
    {
340
        // the table header
341
        $return = '<table class="data_table" style="width: 100%;border:0;padding:0;border-collapse:collapse;table-layout: fixed">';
342
        // database table definition
343
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
344
345
        // getting all the courses of the user
346
        $sql = "SELECT * FROM $tbl_course_user
347
                WHERE
348
                    user_id = '".intval($user_id)."' AND
349
                    relation_type<>".COURSE_RELATION_TYPE_RRHH." ";
350
        $result = Database::query($sql);
351
        while ($row = Database::fetch_array($result)) {
352
            $courseInfo = api_get_course_info_by_id($row['c_id']);
353
            if (empty($courseInfo)) {
354
                continue;
355
            }
356
357
            $courseCode = $courseInfo['code'];
358
            $courseId = $courseInfo['real_id'];
359
360
            $return .= '<tr>';
361
            // course code
362
            $return .= '    <td width="157px" >'.cut($courseCode, 20, true).'</td>';
363
            // time spent in the course
364
            $return .= '<td><div>'.api_time_to_hms(Tracking::get_time_spent_on_the_course($user_id, $courseId)).'</div></td>';
365
            // student progress in course
366
            $return .= '<td><div>'.round(Tracking::get_avg_student_progress($user_id, $courseCode), 2).'</div></td>';
367
            // student score
368
            $avg_score = Tracking::get_avg_student_score($user_id, $courseCode);
369
            if (is_numeric($avg_score)) {
370
                $avg_score = round($avg_score, 2);
371
            } else {
372
                $avg_score = '-';
373
            }
374
375
            $return .= '    <td><div>'.$avg_score.'</div></td>';
376
            // student tes score
377
            //$return .= '  <td><div style="width:40px">'.round(Tracking::get_avg_student_exercise_score ($user_id, $courseCode),2).'%</div></td>';
378
            // student messages
379
            $return .= '    <td><div>'.Tracking::count_student_messages($user_id, $courseCode).'</div></td>';
380
            // student assignments
381
            $return .= '    <td><div>'.Tracking::count_student_assignments($user_id, $courseCode).'</div></td>';
382
            // student exercises results (obtained score, maximum score, number of exercises answered, score percentage)
383
            $exercises_results = self::exercises_results($user_id, $courseCode);
384
            $return .= '    <td width="105px"><div>'.(is_null($exercises_results['percentage']) ? '' : $exercises_results['score_obtained'].'/'.$exercises_results['score_possible'].' ( '.$exercises_results['percentage'].'% )').'</div></td>';
385
            $return .= '    <td><div>'.$exercises_results['questions_answered'].'</div></td>';
386
            $return .= '    <td><div>'.Tracking::get_last_connection_date_on_the_course($user_id, $courseInfo).'</div></td>';
387
            $return .= '<tr>';
388
        }
389
        $return .= '</table>';
390
391
        return $return;
392
    }
393
394
    /**
395
     * Display a sortable table that contains an overview off all the
396
     * reporting progress of all users and all courses the user is subscribed to.
397
     *
398
     * @author Patrick Cool <[email protected]>, Ghent University, Belgium
399
     *          Alex Aragon <[email protected]>, BeezNest, Perú
400
     *
401
     * @version Chamilo 1.11.8
402
     *
403
     * @since April 2019
404
     */
405
    public static function returnTrackingUserOverviewFilter($user_id)
406
    {
407
        $tpl = new Template('', false, false, false, false, false, false);
408
        $userInfo = api_get_user_info($user_id);
409
410
        $avatar = UserManager::getUserPicture($user_id, USER_IMAGE_SIZE_SMALL);
411
        $user = [
412
            'id' => $user_id,
413
            'code_user' => $userInfo['official_code'],
414
            'complete_name' => $userInfo['complete_name'],
415
            'username' => $userInfo['username'],
416
            'course' => self::returnCourseTracking($user_id),
417
            'avatar' => $avatar,
418
        ];
419
420
        $tpl->assign('item', $user);
421
        $templateName = $tpl->get_template('my_space/partials/tracking_user_overview.tpl');
422
        $content = $tpl->fetch($templateName);
423
424
        return $content;
425
    }
426
427
    /**
428
     * Display a sortable table that contains an overview off all the
429
     * reporting progress of all users and all courses the user is subscribed to.
430
     *
431
     * @author Patrick Cool <[email protected]>, Ghent University, Belgium
432
     *
433
     * @version Dokeos 1.8.6
434
     *
435
     * @since October 2008
436
     */
437
    public static function display_tracking_user_overview()
438
    {
439
        self::display_user_overview_export_options();
440
441
        $params = ['view' => 'admin', 'display' => 'user'];
442
        $table = new SortableTable(
443
            'tracking_user_overview',
444
            ['MySpace', 'get_number_of_users_tracking_overview'],
445
            ['MySpace', 'get_user_data_tracking_overview'],
446
            0,
447
            20,
448
            'ASC',
449
            null, [
450
                'class' => 'table table-transparent',
451
            ]
452
        );
453
        $table->additional_parameters = $params;
454
455
        $table->set_column_filter(0, ['MySpace', 'returnTrackingUserOverviewFilter']);
456
        $tableContent = $table->return_table();
457
        $tpl = new Template('', false, false, false, false, false, false);
458
        $tpl->assign('table', $tableContent);
459
        $templateName = $tpl->get_template('my_space/user_summary.tpl');
460
        $tpl->display($templateName);
461
    }
462
463
    /**
464
     * @param $export_csv
465
     */
466
    public static function display_tracking_coach_overview($export_csv)
467
    {
468
        if ($export_csv) {
469
            $is_western_name_order = api_is_western_name_order(PERSON_NAME_DATA_EXPORT);
470
        } else {
471
            $is_western_name_order = api_is_western_name_order();
472
        }
473
        $sort_by_first_name = api_sort_by_first_name();
474
        if (isset($_GET['tracking_list_coaches_column'])) {
475
            $tracking_column = (int) $_GET['tracking_list_coaches_column'];
476
        } else {
477
            $tracking_column = ($is_western_name_order xor $sort_by_first_name) ? 1 : 0;
478
        }
479
480
        $tracking_direction = (isset($_GET['tracking_list_coaches_direction']) && in_array(strtoupper($_GET['tracking_list_coaches_direction']), ['ASC', 'DESC', 'ASCENDING', 'DESCENDING', '0', '1'])) ? $_GET['tracking_list_coaches_direction'] : 'DESC';
481
        // Prepare array for column order - when impossible, use some of user names.
482
        if ($is_western_name_order) {
483
            $order = [
484
                0 => 'firstname',
485
                1 => 'lastname',
486
                2 => $sort_by_first_name ? 'firstname' : 'lastname',
487
                3 => 'login_date',
488
                4 => $sort_by_first_name ? 'firstname' : 'lastname',
489
                5 => $sort_by_first_name ? 'firstname' : 'lastname',
490
            ];
491
        } else {
492
            $order = [
493
                0 => 'lastname',
494
                1 => 'firstname',
495
                2 => $sort_by_first_name ? 'firstname' : 'lastname',
496
                3 => 'login_date',
497
                4 => $sort_by_first_name ? 'firstname' : 'lastname',
498
                5 => $sort_by_first_name ? 'firstname' : 'lastname',
499
            ];
500
        }
501
        $table = new SortableTable(
502
            'tracking_list_coaches_myspace',
503
            ['MySpace', 'count_coaches'],
504
            null,
505
            ($is_western_name_order xor $sort_by_first_name) ? 1 : 0
506
        );
507
        $parameters['view'] = 'admin';
508
        $table->set_additional_parameters($parameters);
509
        if ($is_western_name_order) {
510
            $table->set_header(0, get_lang('FirstName'), true);
511
            $table->set_header(1, get_lang('LastName'), true);
512
        } else {
513
            $table->set_header(0, get_lang('LastName'), true);
514
            $table->set_header(1, get_lang('FirstName'), true);
515
        }
516
        $table->set_header(2, get_lang('TimeSpentOnThePlatform'), false);
517
        $table->set_header(3, get_lang('LastConnexion'), false);
518
        $table->set_header(4, get_lang('NbStudents'), false);
519
        $table->set_header(5, get_lang('CountCours'), false);
520
        $table->set_header(6, get_lang('NumberOfSessions'), false);
521
        $table->set_header(7, get_lang('Sessions'), false);
522
523
        if ($is_western_name_order) {
524
            $csv_header[] = [
525
                get_lang('FirstName'),
526
                get_lang('LastName'),
527
                get_lang('TimeSpentOnThePlatform'),
528
                get_lang('LastConnexion'),
529
                get_lang('NbStudents'),
530
                get_lang('CountCours'),
531
                get_lang('NumberOfSessions'),
532
            ];
533
        } else {
534
            $csv_header[] = [
535
                get_lang('LastName'),
536
                get_lang('FirstName'),
537
                get_lang('TimeSpentOnThePlatform'),
538
                get_lang('LastConnexion'),
539
                get_lang('NbStudents'),
540
                get_lang('CountCours'),
541
                get_lang('NumberOfSessions'),
542
            ];
543
        }
544
545
        $tbl_track_login = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
546
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
547
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
548
        $tbl_sessions = Database::get_main_table(TABLE_MAIN_SESSION);
549
550
        $sqlCoachs = "SELECT DISTINCT
551
                        scu.user_id as id_coach,
552
                        u.id as user_id,
553
                        lastname,
554
                        firstname,
555
                        MAX(login_date) as login_date
556
                        FROM $tbl_user u, $tbl_session_course_user scu, $tbl_track_login
557
                        WHERE
558
                            scu.user_id = u.id AND scu.status=2 AND login_user_id=u.id
559
                        GROUP BY user_id ";
560
561
        if (api_is_multiple_url_enabled()) {
562
            $tbl_session_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
563
            $access_url_id = api_get_current_access_url_id();
564
            if ($access_url_id != -1) {
565
                $sqlCoachs = "SELECT DISTINCT
566
                                    scu.user_id as id_coach,
567
                                    u.id as user_id,
568
                                    lastname,
569
                                    firstname,
570
                                    MAX(login_date) as login_date
571
                                FROM $tbl_user u,
572
                                $tbl_session_course_user scu,
573
                                $tbl_track_login ,
574
                                $tbl_session_rel_access_url session_rel_url
575
                                WHERE
576
                                    scu.user_id = u.id AND
577
                                    scu.status = 2 AND
578
                                    login_user_id = u.id AND
579
                                    access_url_id = $access_url_id AND
580
                                    session_rel_url.session_id = scu.session_id
581
                                GROUP BY u.id";
582
            }
583
        }
584
        if (!empty($order[$tracking_column])) {
585
            $sqlCoachs .= " ORDER BY `".$order[$tracking_column]."` ".$tracking_direction;
586
        }
587
588
        $result_coaches = Database::query($sqlCoachs);
589
        $global_coaches = [];
590
        while ($coach = Database::fetch_array($result_coaches)) {
591
            $global_coaches[$coach['user_id']] = $coach;
592
        }
593
594
        $sql_session_coach = "SELECT session.id_coach, u.id as user_id, lastname, firstname, MAX(login_date) as login_date
595
                                FROM $tbl_user u , $tbl_sessions as session, $tbl_track_login
596
                                WHERE id_coach = u.id AND login_user_id = u.id
597
                                GROUP BY u.id
598
                                ORDER BY login_date $tracking_direction";
599
600
        if (api_is_multiple_url_enabled()) {
601
            $tbl_session_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
602
            $access_url_id = api_get_current_access_url_id();
603
            if ($access_url_id != -1) {
604
                $sql_session_coach = "SELECT session.id_coach, u.id as user_id, lastname, firstname, MAX(login_date) as login_date
605
					FROM $tbl_user u , $tbl_sessions as session, $tbl_track_login , $tbl_session_rel_access_url as session_rel_url
606
					WHERE
607
					    id_coach = u.id AND
608
					    login_user_id = u.id  AND
609
					    access_url_id = $access_url_id AND
610
					    session_rel_url.session_id = session.id
611
					GROUP BY  u.id
612
					ORDER BY login_date $tracking_direction";
613
            }
614
        }
615
616
        $result_sessions_coach = Database::query($sql_session_coach);
617
        //$total_no_coaches += Database::num_rows($result_sessions_coach);
618
        while ($coach = Database::fetch_array($result_sessions_coach)) {
619
            $global_coaches[$coach['user_id']] = $coach;
620
        }
621
622
        $all_datas = [];
623
        foreach ($global_coaches as $id_coach => $coaches) {
624
            $time_on_platform = api_time_to_hms(
625
                Tracking::get_time_spent_on_the_platform($coaches['user_id'])
626
            );
627
            $last_connection = Tracking::get_last_connection_date(
628
                $coaches['user_id']
629
            );
630
            $nb_students = count(
631
                Tracking::get_student_followed_by_coach($coaches['user_id'])
632
            );
633
            $nb_courses = count(
634
                Tracking::get_courses_followed_by_coach($coaches['user_id'])
635
            );
636
            $nb_sessions = count(
637
                Tracking::get_sessions_coached_by_user($coaches['user_id'])
638
            );
639
640
            $table_row = [];
641
            if ($is_western_name_order) {
642
                $table_row[] = $coaches['firstname'];
643
                $table_row[] = $coaches['lastname'];
644
            } else {
645
                $table_row[] = $coaches['lastname'];
646
                $table_row[] = $coaches['firstname'];
647
            }
648
            $table_row[] = $time_on_platform;
649
            $table_row[] = $last_connection;
650
            $table_row[] = $nb_students;
651
            $table_row[] = $nb_courses;
652
            $table_row[] = $nb_sessions;
653
            $table_row[] = '<a href="session.php?id_coach='.$coaches['user_id'].'">
654
                '.Display::return_icon('2rightarrow.png', get_lang('Details')).'
655
            </a>';
656
            $all_datas[] = $table_row;
657
658
            if ($is_western_name_order) {
659
                $csv_content[] = [
660
                    api_html_entity_decode($coaches['firstname'], ENT_QUOTES),
661
                    api_html_entity_decode($coaches['lastname'], ENT_QUOTES),
662
                    $time_on_platform,
663
                    $last_connection,
664
                    $nb_students,
665
                    $nb_courses,
666
                    $nb_sessions,
667
                ];
668
            } else {
669
                $csv_content[] = [
670
                    api_html_entity_decode($coaches['lastname'], ENT_QUOTES),
671
                    api_html_entity_decode($coaches['firstname'], ENT_QUOTES),
672
                    $time_on_platform,
673
                    $last_connection,
674
                    $nb_students,
675
                    $nb_courses,
676
                    $nb_sessions,
677
                ];
678
            }
679
        }
680
681
        if ($tracking_column != 3) {
682
            if ($tracking_direction == 'DESC') {
683
                usort($all_datas, ['MySpace', 'rsort_users']);
684
            } else {
685
                usort($all_datas, ['MySpace', 'sort_users']);
686
            }
687
        }
688
689
        if ($export_csv && $tracking_column != 3) {
690
            usort($csv_content, 'sort_users');
691
        }
692
        if ($export_csv) {
693
            $csv_content = array_merge($csv_header, $csv_content);
694
        }
695
696
        foreach ($all_datas as $row) {
697
            $table->addRow($row, 'align="right"');
698
        }
699
        $table->display();
700
    }
701
702
    /**
703
     * @return mixed
704
     */
705
    public static function count_coaches()
706
    {
707
        global $total_no_coaches;
708
709
        return $total_no_coaches;
710
    }
711
712
    public static function sort_users($a, $b)
713
    {
714
        $tracking = Session::read('tracking_column');
715
716
        return api_strcmp(
717
            trim(api_strtolower($a[$tracking])),
718
            trim(api_strtolower($b[$tracking]))
719
        );
720
    }
721
722
    public static function rsort_users($a, $b)
723
    {
724
        $tracking = Session::read('tracking_column');
725
726
        return api_strcmp(
727
            trim(api_strtolower($b[$tracking])),
728
            trim(api_strtolower($a[$tracking]))
729
        );
730
    }
731
732
    /**
733
     * Display a sortable table that contains an overview off all the progress of the user in a session.
734
     *
735
     * @deprecated ?
736
     *
737
     * @author César Perales <[email protected]>, Beeznest Team
738
     */
739
    public static function display_tracking_lp_progress_overview(
740
        $sessionId = '',
741
        $courseId = '',
742
        $date_from,
743
        $date_to
744
    ) {
745
        $course = api_get_course_info_by_id($courseId);
746
        /**
747
         * Column name
748
         * The order is important you need to check the $column variable in the model.ajax.php file.
749
         */
750
        $columns = [
751
            get_lang('Username'),
752
            get_lang('FirstName'),
753
            get_lang('LastName'),
754
        ];
755
        //add lessons of course
756
        $lessons = LearnpathList::get_course_lessons($course['code'], $sessionId);
757
758
        //create columns array
759
        foreach ($lessons as $lesson_id => $lesson) {
760
            $columns[] = $lesson['name'];
761
        }
762
763
        $columns[] = get_lang('Total');
764
765
        /**
766
         * Column config.
767
         */
768
        $column_model = [
769
            [
770
                'name' => 'username',
771
                'index' => 'username',
772
                'align' => 'left',
773
                'search' => 'true',
774
                'wrap_cell' => "true",
775
            ],
776
            [
777
                'name' => 'firstname',
778
                'index' => 'firstname',
779
                'align' => 'left',
780
                'search' => 'true',
781
            ],
782
            [
783
                'name' => 'lastname',
784
                'index' => 'lastname',
785
                'align' => 'left',
786
                'search' => 'true',
787
            ],
788
        ];
789
790
        // Get dinamic column names
791
        foreach ($lessons as $lesson_id => $lesson) {
792
            $column_model[] = [
793
                'name' => $lesson['id'],
794
                'index' => $lesson['id'],
795
                'align' => 'left',
796
                'search' => 'true',
797
            ];
798
        }
799
800
        $column_model[] = [
801
            'name' => 'total',
802
            'index' => 'total',
803
            'align' => 'left',
804
            'search' => 'true',
805
        ];
806
807
        $action_links = '';
808
        // jqgrid will use this URL to do the selects
809
        $url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_session_lp_progress&session_id='.$sessionId.'&course_id='.$courseId.'&date_to='.$date_to.'&date_from='.$date_from;
810
811
        // Table Id
812
        $tableId = 'lpProgress';
813
814
        // Autowidth
815
        $extra_params['autowidth'] = 'true';
816
817
        // height auto
818
        $extra_params['height'] = 'auto';
819
820
        $table = Display::grid_js(
821
            $tableId,
822
            $url,
823
            $columns,
824
            $column_model,
825
            $extra_params,
826
            [],
827
            $action_links,
828
            true
829
        );
830
831
        $return = '<script>$(function() {'.$table.
832
            'jQuery("#'.$tableId.'").jqGrid("navGrid","#'.$tableId.'_pager",{view:false, edit:false, add:false, del:false, search:false, excel:true});
833
                jQuery("#'.$tableId.'").jqGrid("navButtonAdd","#'.$tableId.'_pager",{
834
                       caption:"",
835
                       title:"'.get_lang('ExportExcel').'",
836
                       onClickButton : function () {
837
                           jQuery("#'.$tableId.'").jqGrid("excelExport",{"url":"'.$url.'&export_format=xls"});
838
                       }
839
                });
840
            });</script>';
841
        $return .= Display::grid_html($tableId);
842
843
        return $return;
844
    }
845
846
    /**
847
     * Display a sortable table that contains an overview off all the progress of the user in a session.
848
     *
849
     * @param int $sessionId  The session ID
850
     * @param int $courseId   The course ID
851
     * @param int $exerciseId The quiz ID
852
     * @param     $date_from
853
     * @param     $date_to
854
     *
855
     * @return string HTML array of results formatted for gridJS
856
     *
857
     * @deprecated ?
858
     *
859
     * @author César Perales <[email protected]>, Beeznest Team
860
     */
861
    public static function display_tracking_exercise_progress_overview(
862
        $sessionId = 0,
863
        $courseId = 0,
864
        $exerciseId = 0,
865
        $date_from = null,
866
        $date_to = null
867
    ) {
868
        $date_from = Security::remove_XSS($date_from);
869
        $date_to = Security::remove_XSS($date_to);
870
        /**
871
         * Column names
872
         * The column order is important. Check $column variable in the main/inc/ajax/model.ajax.php file.
873
         */
874
        $columns = [
875
            get_lang('Session'),
876
            get_lang('ExerciseId'),
877
            get_lang('ExerciseName'),
878
            get_lang('Username'),
879
            get_lang('LastName'),
880
            get_lang('FirstName'),
881
            get_lang('Time'),
882
            get_lang('QuestionId'),
883
            get_lang('QuestionTitle'),
884
            get_lang('WorkDescription'),
885
            get_lang('Answer'),
886
            get_lang('Correct'),
887
        ];
888
889
        /**
890
         * Column config.
891
         */
892
        $column_model = [
893
            ['name' => 'session', 'index' => 'session', 'align' => 'left', 'search' => 'true', 'wrap_cell' => "true"],
894
            ['name' => 'exercise_id', 'index' => 'exercise_id', 'align' => 'left', 'search' => 'true'],
895
            ['name' => 'quiz_title', 'index' => 'quiz_title', 'align' => 'left', 'search' => 'true'],
896
            ['name' => 'username', 'index' => 'username', 'align' => 'left', 'search' => 'true'],
897
            ['name' => 'lastname', 'index' => 'lastname', 'align' => 'left', 'search' => 'true'],
898
            ['name' => 'firstname', 'index' => 'firstname', 'align' => 'left', 'search' => 'true'],
899
            ['name' => 'time', 'index' => 'time', 'align' => 'left', 'search' => 'true', 'wrap_cell' => "true"],
900
            ['name' => 'question_id', 'index' => 'question_id', 'align' => 'left', 'search' => 'true'],
901
            ['name' => 'question', 'index' => 'question', 'align' => 'left', 'search' => 'true', 'wrap_cell' => "true"],
902
            ['name' => 'description', 'index' => 'description', 'align' => 'left', 'width' => '550', 'search' => 'true', 'wrap_cell' => "true"],
903
            ['name' => 'answer', 'index' => 'answer', 'align' => 'left', 'search' => 'true', 'wrap_cell' => "true"],
904
            ['name' => 'correct', 'index' => 'correct', 'align' => 'left', 'search' => 'true', 'wrap_cell' => "true"],
905
        ];
906
        //get dynamic column names
907
908
        // jqgrid will use this URL to do the selects
909
        $url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_exercise_progress&session_id='.$sessionId.'&course_id='.$courseId.'&exercise_id='.$exerciseId.'&date_to='.$date_to.'&date_from='.$date_from;
910
911
        // Autowidth
912
        $extra_params['autowidth'] = 'true';
913
914
        // height auto
915
        $extra_params['height'] = 'auto';
916
917
        $tableId = 'exerciseProgressOverview';
918
        $table = Display::grid_js(
919
            $tableId,
920
            $url,
921
            $columns,
922
            $column_model,
923
            $extra_params,
924
            [],
925
            '',
926
            true
927
        );
928
929
        $return = '<script>$(function() {'.$table.
930
            'jQuery("#'.$tableId.'").jqGrid("navGrid","#'.$tableId.'_pager",{view:false, edit:false, add:false, del:false, search:false, excel:true});
931
                jQuery("#'.$tableId.'").jqGrid("navButtonAdd","#'.$tableId.'_pager",{
932
                       caption:"",
933
                       title:"'.get_lang('ExportExcel').'",
934
                       onClickButton : function () {
935
                           jQuery("#'.$tableId.'").jqGrid("excelExport",{"url":"'.$url.'&export_format=xls"});
936
                       }
937
                });
938
            });</script>';
939
        $return .= Display::grid_html($tableId);
940
941
        return $return;
942
    }
943
944
    /**
945
     * Displays a form with all the additionally defined user fields of the profile
946
     * and give you the opportunity to include these in the CSV export.
947
     *
948
     * @author Patrick Cool <[email protected]>, Ghent University, Belgium
949
     *
950
     * @version 1.8.6
951
     *
952
     * @since November 2008
953
     */
954
    public static function display_user_overview_export_options()
955
    {
956
        $message = '';
957
        $defaults = [];
958
        // include the user manager and formvalidator library
959
        if (isset($_GET['export']) && $_GET['export'] == 'options') {
960
            // get all the defined extra fields
961
            $extrafields = UserManager::get_extra_fields(
962
                0,
963
                50,
964
                5,
965
                'ASC',
966
                false,
967
                1
968
            );
969
970
            // creating the form with all the defined extra fields
971
            $form = new FormValidator(
972
                'exportextrafields',
973
                'post',
974
                api_get_self()."?view=".Security::remove_XSS($_GET['view']).'&display='.Security::remove_XSS($_GET['display']).'&export='.Security::remove_XSS($_GET['export'])
975
            );
976
977
            if (is_array($extrafields) && count($extrafields) > 0) {
978
                foreach ($extrafields as $key => $extra) {
979
                    $form->addElement('checkbox', 'extra_export_field'.$extra[0], '', $extra[3]);
980
                }
981
                $form->addButtonSave(get_lang('Ok'), 'submit');
982
983
                // setting the default values for the form that contains all the extra fields
984
                $exportFields = Session::read('additional_export_fields');
985
                if (is_array($exportFields)) {
986
                    foreach ($exportFields as $key => $value) {
987
                        $defaults['extra_export_field'.$value] = 1;
988
                    }
989
                }
990
                $form->setDefaults($defaults);
991
            } else {
992
                $form->addElement('html', Display::return_message(get_lang('ThereAreNotExtrafieldsAvailable'), 'warning'));
993
            }
994
995
            if ($form->validate()) {
996
                // exporting the form values
997
                $values = $form->exportValues();
998
999
                // re-initialising the session that contains the additional fields that need to be exported
1000
                Session::write('additional_export_fields', []);
1001
1002
                // adding the fields that are checked to the session
1003
                $message = '';
1004
                $additionalExportFields = [];
1005
                foreach ($values as $field_ids => $value) {
1006
                    if ($value == 1 && strstr($field_ids, 'extra_export_field')) {
1007
                        $additionalExportFields[] = str_replace('extra_export_field', '', $field_ids);
1008
                    }
1009
                }
1010
                Session::write('additional_export_fields', $additionalExportFields);
1011
1012
                // adding the fields that will be also exported to a message string
1013
                $additionalExportFields = Session::read('additional_export_fields');
1014
                if (is_array($additionalExportFields)) {
1015
                    foreach ($additionalExportFields as $key => $extra_field_export) {
1016
                        $message .= '<li>'.$extrafields[$extra_field_export][3].'</li>';
1017
                    }
1018
                }
1019
1020
                // Displaying a feedback message
1021
                if (!empty($additionalExportFields)) {
1022
                    echo Display::return_message(
1023
                        get_lang('FollowingFieldsWillAlsoBeExported').': <br /><ul>'.$message.'</ul>',
1024
                        'confirm',
1025
                        false
1026
                    );
1027
                } else {
1028
                    echo Display::return_message(
1029
                        get_lang('NoAdditionalFieldsWillBeExported'),
1030
                        'confirm',
1031
                        false
1032
                    );
1033
                }
1034
            } else {
1035
                $form->display();
1036
            }
1037
        } else {
1038
            $additionalExportFields = Session::read('additional_export_fields');
1039
            if (!empty($additionalExportFields)) {
1040
                // get all the defined extra fields
1041
                $extrafields = UserManager::get_extra_fields(0, 50, 5, 'ASC');
1042
1043
                foreach ($additionalExportFields as $key => $extra_field_export) {
1044
                    $message .= '<li>'.$extrafields[$extra_field_export][3].'</li>';
1045
                }
1046
1047
                echo Display::return_message(
1048
                    get_lang('FollowingFieldsWillAlsoBeExported').': <br /><ul>'.$message.'</ul>',
1049
                    'normal',
1050
                    false
1051
                );
1052
            }
1053
        }
1054
    }
1055
1056
    /**
1057
     * Display a sortable table that contains an overview of all the reporting progress of all courses.
1058
     */
1059
    public static function display_tracking_course_overview()
1060
    {
1061
        $params = ['view' => 'admin', 'display' => 'courseoverview'];
1062
        $table = new SortableTable(
1063
            'tracking_session_overview',
1064
            ['MySpace', 'get_total_number_courses'],
1065
            ['MySpace', 'get_course_data_tracking_overview'],
1066
            1,
1067
            20,
1068
            'ASC',
1069
            null, [
1070
                'class' => 'table table-transparent',
1071
            ]
1072
        );
1073
        $table->additional_parameters = $params;
1074
        $table->set_column_filter(0, ['MySpace', 'course_tracking_filter']);
1075
        $tableContent = $table->return_table();
1076
1077
        $tpl = new Template('', false, false, false, false, false, false);
1078
        $tpl->assign('table', $tableContent);
1079
        $templateName = $tpl->get_template('my_space/course_summary.tpl');
1080
        $tpl->display($templateName);
1081
    }
1082
1083
    /**
1084
     * Get the total number of courses.
1085
     *
1086
     * @return int Total number of courses
1087
     */
1088
    public static function get_total_number_courses()
1089
    {
1090
        return CourseManager::count_courses(api_get_current_access_url_id());
1091
    }
1092
1093
    /**
1094
     * Get data for the courses.
1095
     *
1096
     * @param int    $from        Inferior limit
1097
     * @param int    $numberItems Number of items to select
1098
     * @param string $column      Column to order on
1099
     * @param string $direction   Order direction
1100
     *
1101
     * @return array Results
1102
     */
1103
    public static function get_course_data_tracking_overview(
1104
        $from,
1105
        $numberItems,
1106
        $column,
1107
        $direction
1108
    ) {
1109
        switch ($column) {
1110
            default:
1111
            case 1:
1112
                $column = 'title';
1113
                break;
1114
        }
1115
1116
        $courses = CourseManager::get_courses_list(
1117
            $from,
1118
            $numberItems,
1119
            $column,
1120
            $direction,
1121
             -1,
1122
            '',
1123
            api_get_current_access_url_id()
1124
        );
1125
1126
        $list = [];
1127
        foreach ($courses as $course) {
1128
            $list[] = [
1129
                '0' => $course['code'],
1130
                'col0' => $course['code'],
1131
            ];
1132
        }
1133
1134
        return $list;
1135
    }
1136
1137
    /**
1138
     * Fills in course reporting data.
1139
     *
1140
     * @param int course code
1141
     * @param array $url_params additional url parameters
1142
     * @param array $row        the row information (the other columns)
1143
     *
1144
     * @return string html code
1145
     */
1146
    public static function course_tracking_filter($course_code, $url_params, $row)
1147
    {
1148
        $course_code = $row[0];
1149
        $courseInfo = api_get_course_info($course_code);
1150
        $courseId = $courseInfo['real_id'];
1151
1152
        $tpl = new Template('', false, false, false, false, false, false);
1153
        $data = null;
1154
1155
        // database table definition
1156
        $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1157
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
1158
1159
        // getting all the courses of the user
1160
        $sql = "SELECT *
1161
                FROM $tbl_user AS u
1162
                INNER JOIN $tbl_course_rel_user AS cu
1163
                ON cu.user_id = u.user_id
1164
                WHERE cu.c_id = '".$courseId."'";
1165
        $result = Database::query($sql);
1166
        $time_spent = 0;
1167
        $progress = 0;
1168
        $nb_progress_lp = 0;
1169
        $score = 0;
1170
        $nb_score_lp = 0;
1171
        $nb_messages = 0;
1172
        $nb_assignments = 0;
1173
        $last_login_date = false;
1174
        $total_score_obtained = 0;
1175
        $total_score_possible = 0;
1176
        $total_questions_answered = 0;
1177
        while ($row = Database::fetch_object($result)) {
1178
            // get time spent in the course and session
1179
            $time_spent += Tracking::get_time_spent_on_the_course(
1180
                $row->user_id,
1181
                $courseInfo['real_id']
1182
            );
1183
            $progress_tmp = Tracking::get_avg_student_progress(
1184
                $row->user_id,
1185
                $course_code,
1186
                [],
1187
                null,
1188
                true
1189
            );
1190
            if ($progress_tmp) {
1191
                $progress += $progress_tmp[0];
1192
                $nb_progress_lp += $progress_tmp[1];
1193
            }
1194
            $score_tmp = Tracking::get_avg_student_score(
1195
                $row->user_id,
1196
                $course_code,
1197
                [],
1198
                null,
1199
                true
1200
            );
1201
            if (is_array($score_tmp)) {
1202
                $score += $score_tmp[0];
1203
                $nb_score_lp += $score_tmp[1];
1204
            }
1205
            $nb_messages += Tracking::count_student_messages(
1206
                $row->user_id,
1207
                $course_code
1208
            );
1209
            $nb_assignments += Tracking::count_student_assignments(
1210
                $row->user_id,
1211
                $course_code
1212
            );
1213
            $last_login_date_tmp = Tracking::get_last_connection_date_on_the_course(
1214
                $row->user_id,
1215
                $courseInfo,
1216
                null,
1217
                false
1218
            );
1219
            if ($last_login_date_tmp != false &&
1220
                $last_login_date == false
1221
            ) { // TODO: To be cleaned
1222
                $last_login_date = $last_login_date_tmp;
1223
            } elseif ($last_login_date_tmp != false && $last_login_date != false) {
1224
                // TODO: Repeated previous condition. To be cleaned.
1225
                // Find the max and assign it to first_login_date
1226
                if (strtotime($last_login_date_tmp) > strtotime($last_login_date)) {
1227
                    $last_login_date = $last_login_date_tmp;
1228
                }
1229
            }
1230
1231
            $exercise_results_tmp = self::exercises_results($row->user_id, $course_code);
1232
            $total_score_obtained += $exercise_results_tmp['score_obtained'];
1233
            $total_score_possible += $exercise_results_tmp['score_possible'];
1234
            $total_questions_answered += $exercise_results_tmp['questions_answered'];
1235
        }
1236
        if ($nb_progress_lp > 0) {
1237
            $avg_progress = round($progress / $nb_progress_lp, 2);
1238
        } else {
1239
            $avg_progress = 0;
1240
        }
1241
        if ($nb_score_lp > 0) {
1242
            $avg_score = round($score / $nb_score_lp, 2);
1243
        } else {
1244
            $avg_score = '-';
1245
        }
1246
        if ($last_login_date) {
1247
            $last_login_date = api_convert_and_format_date(
1248
                $last_login_date,
1249
                DATE_FORMAT_SHORT,
1250
                date_default_timezone_get()
1251
            );
1252
        } else {
1253
            $last_login_date = '-';
1254
        }
1255
        if ($total_score_possible > 0) {
1256
            $total_score_percentage = round($total_score_obtained / $total_score_possible * 100, 2);
1257
        } else {
1258
            $total_score_percentage = 0;
1259
        }
1260
        if ($total_score_percentage > 0) {
1261
            $total_score = $total_score_obtained.'/'.$total_score_possible.' ('.$total_score_percentage.' %)';
1262
        } else {
1263
            $total_score = '-';
1264
        }
1265
1266
        $data = [
1267
            'course_code' => $course_code,
1268
            'id' => $courseId,
1269
            'image' => $courseInfo['course_image_large'],
1270
            'image_small' => $courseInfo['course_image'],
1271
            'title' => $courseInfo['title'],
1272
            'url' => $courseInfo['course_public_url'],
1273
            'category' => $courseInfo['categoryName'],
1274
            'time_spent' => api_time_to_hms($time_spent),
1275
            'avg_progress' => $avg_progress,
1276
            'avg_score' => $avg_score,
1277
            'number_message' => $nb_messages,
1278
            'number_assignments' => $nb_assignments,
1279
            'total_score' => $total_score,
1280
            'questions_answered' => $total_questions_answered,
1281
            'last_login' => $last_login_date,
1282
        ];
1283
1284
        $tpl->assign('data', $data);
1285
        $layout = $tpl->get_template('my_space/partials/tracking_course_overview.tpl');
1286
        $content = $tpl->fetch($layout);
1287
1288
        return $content;
1289
    }
1290
1291
    /**
1292
     * This function exports the table that we see in display_tracking_course_overview().
1293
     */
1294
    public static function export_tracking_course_overview()
1295
    {
1296
        // database table definition
1297
        $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1298
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
1299
1300
        // the values of the sortable table
1301
        if ($_GET['tracking_course_overview_page_nr']) {
1302
            $from = $_GET['tracking_course_overview_page_nr'];
1303
        } else {
1304
            $from = 0;
1305
        }
1306
        if ($_GET['tracking_course_overview_column']) {
1307
            $orderby = $_GET['tracking_course_overview_column'];
1308
        } else {
1309
            $orderby = 0;
1310
        }
1311
1312
        if ($_GET['tracking_course_overview_direction']) {
1313
            $direction = $_GET['tracking_course_overview_direction'];
1314
        } else {
1315
            $direction = 'ASC';
1316
        }
1317
1318
        $course_data = self::get_course_data_tracking_overview(
1319
            $from,
1320
            1000,
1321
            $orderby,
1322
            $direction
1323
        );
1324
1325
        $csv_content = [];
1326
1327
        // the first line of the csv file with the column headers
1328
        $csv_row = [];
1329
        $csv_row[] = get_lang('Course');
1330
        $csv_row[] = get_lang('AvgTimeSpentInTheCourse');
1331
        $csv_row[] = get_lang('AvgStudentsProgress');
1332
        $csv_row[] = get_lang('AvgCourseScore');
1333
        $csv_row[] = get_lang('TotalNumberOfMessages');
1334
        $csv_row[] = get_lang('TotalNumberOfAssignments');
1335
        $csv_row[] = get_lang('TotalExercisesScoreObtained');
1336
        $csv_row[] = get_lang('TotalExercisesScorePossible');
1337
        $csv_row[] = get_lang('TotalExercisesAnswered');
1338
        $csv_row[] = get_lang('TotalExercisesScorePercentage');
1339
        $csv_row[] = get_lang('LatestLogin');
1340
        $csv_content[] = $csv_row;
1341
1342
        // the other lines (the data)
1343
        foreach ($course_data as $key => $course) {
1344
            $course_code = $course[0];
1345
            $courseInfo = api_get_course_info($course_code);
1346
            $course_title = $courseInfo['title'];
1347
            $courseId = $courseInfo['real_id'];
1348
1349
            $csv_row = [];
1350
            $csv_row[] = $course_title;
1351
1352
            // getting all the courses of the session
1353
            $sql = "SELECT *
1354
                    FROM $tbl_user AS u
1355
                    INNER JOIN $tbl_course_rel_user AS cu
1356
                    ON cu.user_id = u.user_id
1357
                    WHERE cu.c_id = '".$courseId."'";
1358
            $result = Database::query($sql);
1359
            $time_spent = 0;
1360
            $progress = 0;
1361
            $nb_progress_lp = 0;
1362
            $score = 0;
1363
            $nb_score_lp = 0;
1364
            $nb_messages = 0;
1365
            $nb_assignments = 0;
1366
            $last_login_date = false;
1367
            $total_score_obtained = 0;
1368
            $total_score_possible = 0;
1369
            $total_questions_answered = 0;
1370
            while ($row = Database::fetch_object($result)) {
1371
                // get time spent in the course and session
1372
                $time_spent += Tracking::get_time_spent_on_the_course(
1373
                    $row->user_id,
1374
                    $courseId
1375
                );
1376
                $progress_tmp = Tracking::get_avg_student_progress(
1377
                    $row->user_id,
1378
                    $course_code,
1379
                    [],
1380
                    null,
1381
                    true
1382
                );
1383
                $progress += $progress_tmp[0];
1384
                $nb_progress_lp += $progress_tmp[1];
1385
                $score_tmp = Tracking::get_avg_student_score(
1386
                    $row->user_id,
1387
                    $course_code,
1388
                    [],
1389
                    null,
1390
                    true
1391
                );
1392
                if (is_array($score_tmp)) {
1393
                    $score += $score_tmp[0];
1394
                    $nb_score_lp += $score_tmp[1];
1395
                }
1396
                $nb_messages += Tracking::count_student_messages(
1397
                    $row->user_id,
1398
                    $course_code
1399
                );
1400
                $nb_assignments += Tracking::count_student_assignments(
1401
                    $row->user_id,
1402
                    $course_code
1403
                );
1404
1405
                $last_login_date_tmp = Tracking::get_last_connection_date_on_the_course(
1406
                    $row->user_id,
1407
                    $courseInfo,
1408
                    null,
1409
                    false
1410
                );
1411
                if ($last_login_date_tmp != false && $last_login_date == false) {
1412
                    // TODO: To be cleaned.
1413
                    $last_login_date = $last_login_date_tmp;
1414
                } elseif ($last_login_date_tmp != false && $last_login_date == false) {
1415
                    // TODO: Repeated previous condition. To be cleaned.
1416
                    // Find the max and assign it to first_login_date
1417
                    if (strtotime($last_login_date_tmp) > strtotime($last_login_date)) {
1418
                        $last_login_date = $last_login_date_tmp;
1419
                    }
1420
                }
1421
1422
                $exercise_results_tmp = self::exercises_results($row->user_id, $course_code);
1423
                $total_score_obtained += $exercise_results_tmp['score_obtained'];
1424
                $total_score_possible += $exercise_results_tmp['score_possible'];
1425
                $total_questions_answered += $exercise_results_tmp['questions_answered'];
1426
            }
1427
            if ($nb_progress_lp > 0) {
1428
                $avg_progress = round($progress / $nb_progress_lp, 2);
1429
            } else {
1430
                $avg_progress = 0;
1431
            }
1432
            if ($nb_score_lp > 0) {
1433
                $avg_score = round($score / $nb_score_lp, 2);
1434
            } else {
1435
                $avg_score = '-';
1436
            }
1437
            if ($last_login_date) {
1438
                $last_login_date = api_convert_and_format_date(
1439
                    $last_login_date,
1440
                    DATE_FORMAT_SHORT,
1441
                    date_default_timezone_get()
1442
                );
1443
            } else {
1444
                $last_login_date = '-';
1445
            }
1446
            if ($total_score_possible > 0) {
1447
                $total_score_percentage = round($total_score_obtained / $total_score_possible * 100, 2);
1448
            } else {
1449
                $total_score_percentage = 0;
1450
            }
1451
            // time spent in the course
1452
            $csv_row[] = api_time_to_hms($time_spent);
1453
            // student progress in course
1454
            $csv_row[] = $avg_progress;
1455
            // student score
1456
            $csv_row[] = $avg_score;
1457
            // student messages
1458
            $csv_row[] = $nb_messages;
1459
            // student assignments
1460
            $csv_row[] = $nb_assignments;
1461
            // student exercises results (obtained score, maximum score, number of exercises answered, score percentage)
1462
            $csv_row[] = $total_score_obtained;
1463
            $csv_row[] = $total_score_possible;
1464
            $csv_row[] = $total_questions_answered;
1465
            $csv_row[] = $total_score_percentage;
1466
            // last connection
1467
            $csv_row[] = $last_login_date;
1468
            $csv_content[] = $csv_row;
1469
        }
1470
        Export::arrayToCsv($csv_content, 'reporting_course_overview');
1471
        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

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

Loading history...
1472
    }
1473
1474
    /**
1475
     * Display a sortable table that contains an overview of all the reporting
1476
     * progress of all sessions and all courses the user is subscribed to.
1477
     *
1478
     * @author Guillaume Viguier <[email protected]>
1479
     */
1480
    public static function display_tracking_session_overview()
1481
    {
1482
        $head = '<table style="width: 100%;border:0;padding:0;border-collapse:collapse;table-layout: fixed">';
1483
        $head .= '<tr>';
1484
        $head .= '<th width="155px" style="border-left:0;border-bottom:0"><span>'.get_lang('Course').'</span></th>';
1485
        $head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('AvgTimeSpentInTheCourse'), 6, true).'</span></th>';
1486
        $head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('AvgStudentsProgress'), 6, true).'</span></th>';
1487
        $head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('AvgCourseScore'), 6, true).'</span></th>';
1488
        $head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('TotalNumberOfMessages'), 6, true).'</span></th>';
1489
        $head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('TotalNumberOfAssignments'), 6, true).'</span></th>';
1490
        $head .= '<th width="105px" style="border-bottom:0"><span>'.get_lang('TotalExercisesScoreObtained').'</span></th>';
1491
        $head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('TotalExercisesAnswered'), 6, true).'</span></th>';
1492
        $head .= '<th style="padding:0;border-bottom:0;border-right:0;"><span>'.get_lang('LatestLogin').'</span></th>';
1493
        $head .= '</tr></table>';
1494
1495
        $params = ['view' => 'admin', 'display' => 'sessionoverview'];
1496
        $table = new SortableTable(
1497
            'tracking_session_overview',
1498
            ['MySpace', 'get_total_number_sessions'],
1499
            ['MySpace', 'get_session_data_tracking_overview'],
1500
            1
1501
        );
1502
        $table->additional_parameters = $params;
1503
1504
        $table->set_header(0, '', false, null, ['style' => 'display: none']);
1505
        $table->set_header(
1506
            1,
1507
            get_lang('Session'),
1508
            true,
1509
            ['style' => 'font-size:8pt'],
1510
            ['style' => 'font-size:8pt']
1511
        );
1512
        $table->set_header(
1513
            2,
1514
            $head,
1515
            false,
1516
            ['style' => 'width:90%;border:0;padding:0;font-size:7.5pt;'],
1517
            ['style' => 'width:90%;padding:0;font-size:7.5pt;']
1518
        );
1519
        $table->set_column_filter(2, ['MySpace', 'session_tracking_filter']);
1520
        $table->display();
1521
    }
1522
1523
    /**
1524
     * Get the total number of sessions.
1525
     *
1526
     * @return int Total number of sessions
1527
     */
1528
    public static function get_total_number_sessions()
1529
    {
1530
        return SessionManager::count_sessions(api_get_current_access_url_id());
1531
    }
1532
1533
    /**
1534
     * Get data for the sessions.
1535
     *
1536
     * @param int    $from        Inferior limit
1537
     * @param int    $numberItems Number of items to select
1538
     * @param string $column      Column to order on
1539
     * @param string $direction   Order direction
1540
     *
1541
     * @return array Results
1542
     */
1543
    public static function get_session_data_tracking_overview(
1544
        $from,
1545
        $numberItems,
1546
        $column,
1547
        $direction
1548
    ) {
1549
        $from = (int) $from;
1550
        $numberItems = (int) $numberItems;
1551
        $direction = Database::escape_string($direction);
1552
        $columnName = 'name';
1553
        if ($column === 1) {
1554
            $columnName = 'id';
1555
        }
1556
1557
        $options = [
1558
            'order' => " $columnName $direction",
1559
            'limit' => " $from,$numberItems",
1560
        ];
1561
        $sessions = SessionManager::get_sessions_admin($options);
1562
        $list = [];
1563
        foreach ($sessions as $session) {
1564
            $list[] = [
1565
                '0' => $session['id'],
1566
                'col0' => $session['id'],
1567
                '1' => strip_tags($session['name']),
1568
                'col1' => strip_tags($session['name']),
1569
            ];
1570
        }
1571
1572
        return $list;
1573
    }
1574
1575
    /**
1576
     * Fills in session reporting data.
1577
     *
1578
     * @param int   $session_id the id of the user
1579
     * @param array $url_params additonal url parameters
1580
     * @param array $row        the row information (the other columns)
1581
     *
1582
     * @return string html code
1583
     */
1584
    public static function session_tracking_filter($session_id, $url_params, $row)
1585
    {
1586
        $session_id = $row[0];
1587
        // the table header
1588
        $return = '<table class="data_table" style="width: 100%;border:0;padding:0;border-collapse:collapse;table-layout: fixed">';
1589
1590
        // database table definition
1591
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
1592
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
1593
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
1594
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
1595
1596
        // getting all the courses of the user
1597
        $sql = "SELECT * FROM $tbl_course AS c
1598
                INNER JOIN $tbl_session_rel_course AS sc
1599
                ON sc.c_id = c.id
1600
                WHERE sc.session_id = '".$session_id."'";
1601
        $result = Database::query($sql);
1602
        while ($row = Database::fetch_object($result)) {
1603
            $courseId = $row->c_id;
1604
            $courseInfo = api_get_course_info_by_id($courseId);
1605
            $return .= '<tr>';
1606
            // course code
1607
            $return .= '    <td width="157px" >'.$row->title.'</td>';
1608
            // get the users in the course
1609
            $sql = "SELECT u.user_id
1610
                    FROM $tbl_user AS u
1611
                    INNER JOIN $tbl_session_rel_course_rel_user AS scu
1612
                    ON u.user_id = scu.user_id
1613
                    WHERE scu.session_id = '".$session_id."' AND scu.c_id = '".$courseId."'";
1614
            $result_users = Database::query($sql);
1615
            $time_spent = 0;
1616
            $progress = 0;
1617
            $nb_progress_lp = 0;
1618
            $score = 0;
1619
            $nb_score_lp = 0;
1620
            $nb_messages = 0;
1621
            $nb_assignments = 0;
1622
            $last_login_date = false;
1623
            $total_score_obtained = 0;
1624
            $total_score_possible = 0;
1625
            $total_questions_answered = 0;
1626
            while ($row_user = Database::fetch_object($result_users)) {
1627
                // get time spent in the course and session
1628
                $time_spent += Tracking::get_time_spent_on_the_course($row_user->user_id, $courseId, $session_id);
1629
                $progress_tmp = Tracking::get_avg_student_progress($row_user->user_id, $row->code, [], $session_id, true);
1630
                $progress += $progress_tmp[0];
1631
                $nb_progress_lp += $progress_tmp[1];
1632
                $score_tmp = Tracking::get_avg_student_score($row_user->user_id, $row->code, [], $session_id, true);
1633
                if (is_array($score_tmp)) {
1634
                    $score += $score_tmp[0];
1635
                    $nb_score_lp += $score_tmp[1];
1636
                }
1637
                $nb_messages += Tracking::count_student_messages($row_user->user_id, $row->code, $session_id);
1638
                $nb_assignments += Tracking::count_student_assignments($row_user->user_id, $row->code, $session_id);
1639
                $last_login_date_tmp = Tracking::get_last_connection_date_on_the_course(
1640
                    $row_user->user_id,
1641
                    $courseInfo,
1642
                    $session_id,
1643
                    false
1644
                );
1645
                if ($last_login_date_tmp != false && $last_login_date == false) {
1646
                    // TODO: To be cleaned.
1647
                    $last_login_date = $last_login_date_tmp;
1648
                } elseif ($last_login_date_tmp != false && $last_login_date != false) {
1649
                    // TODO: Repeated previous condition! To be cleaned.
1650
                    // Find the max and assign it to first_login_date
1651
                    if (strtotime($last_login_date_tmp) > strtotime($last_login_date)) {
1652
                        $last_login_date = $last_login_date_tmp;
1653
                    }
1654
                }
1655
1656
                $exercise_results_tmp = self::exercises_results($row_user->user_id, $row->code, $session_id);
1657
                $total_score_obtained += $exercise_results_tmp['score_obtained'];
1658
                $total_score_possible += $exercise_results_tmp['score_possible'];
1659
                $total_questions_answered += $exercise_results_tmp['questions_answered'];
1660
            }
1661
            if ($nb_progress_lp > 0) {
1662
                $avg_progress = round($progress / $nb_progress_lp, 2);
1663
            } else {
1664
                $avg_progress = 0;
1665
            }
1666
            if ($nb_score_lp > 0) {
1667
                $avg_score = round($score / $nb_score_lp, 2);
1668
            } else {
1669
                $avg_score = '-';
1670
            }
1671
            if ($last_login_date) {
1672
                $last_login_date = api_convert_and_format_date(
1673
                    $last_login_date,
1674
                    DATE_FORMAT_SHORT,
1675
                    date_default_timezone_get()
1676
                );
1677
            } else {
1678
                $last_login_date = '-';
1679
            }
1680
            if ($total_score_possible > 0) {
1681
                $total_score_percentage = round($total_score_obtained / $total_score_possible * 100, 2);
1682
            } else {
1683
                $total_score_percentage = 0;
1684
            }
1685
            if ($total_score_percentage > 0) {
1686
                $total_score = $total_score_obtained.'/'.$total_score_possible.' ('.$total_score_percentage.' %)';
1687
            } else {
1688
                $total_score = '-';
1689
            }
1690
            // time spent in the course
1691
            $return .= '    <td><div>'.api_time_to_hms($time_spent).'</div></td>';
1692
            // student progress in course
1693
            $return .= '    <td><div>'.$avg_progress.'</div></td>';
1694
            // student score
1695
            $return .= '    <td><div>'.$avg_score.'</div></td>';
1696
            // student messages
1697
            $return .= '    <td><div>'.$nb_messages.'</div></td>';
1698
            // student assignments
1699
            $return .= '    <td><div>'.$nb_assignments.'</div></td>';
1700
            // student exercises results (obtained score, maximum score, number of exercises answered, score percentage)
1701
            $return .= '<td width="105px;">'.$total_score.'</td>';
1702
            $return .= '<td>'.$total_questions_answered.'</td>';
1703
            // last connection
1704
            $return .= '    <td><div>'.$last_login_date.'</div></td>';
1705
            $return .= '<tr>';
1706
        }
1707
        $return .= '</table>';
1708
1709
        return $return;
1710
    }
1711
1712
    /**
1713
     * This function exports the table that we see in display_tracking_session_overview().
1714
     */
1715
    public static function export_tracking_session_overview()
1716
    {
1717
        // database table definition
1718
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
1719
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
1720
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
1721
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
1722
1723
        // the values of the sortable table
1724
        $from = 0;
1725
        if ($_GET['tracking_session_overview_page_nr']) {
1726
            $from = $_GET['tracking_session_overview_page_nr'];
1727
        }
1728
1729
        $orderby = 0;
1730
        if ($_GET['tracking_session_overview_column']) {
1731
            $orderby = $_GET['tracking_session_overview_column'];
1732
        }
1733
1734
        $direction = 'ASC';
1735
        if ($_GET['tracking_session_overview_direction']) {
1736
            $direction = $_GET['tracking_session_overview_direction'];
1737
        }
1738
1739
        $session_data = self::get_session_data_tracking_overview($from, 1000, $orderby, $direction);
1740
1741
        $csv_content = [];
1742
1743
        // the first line of the csv file with the column headers
1744
        $csv_row = [];
1745
        $csv_row[] = get_lang('Session');
1746
        $csv_row[] = get_lang('Course');
1747
        $csv_row[] = get_lang('AvgTimeSpentInTheCourse');
1748
        $csv_row[] = get_lang('AvgStudentsProgress');
1749
        $csv_row[] = get_lang('AvgCourseScore');
1750
        $csv_row[] = get_lang('TotalNumberOfMessages');
1751
        $csv_row[] = get_lang('TotalNumberOfAssignments');
1752
        $csv_row[] = get_lang('TotalExercisesScoreObtained');
1753
        $csv_row[] = get_lang('TotalExercisesScorePossible');
1754
        $csv_row[] = get_lang('TotalExercisesAnswered');
1755
        $csv_row[] = get_lang('TotalExercisesScorePercentage');
1756
        $csv_row[] = get_lang('LatestLogin');
1757
        $csv_content[] = $csv_row;
1758
1759
        // the other lines (the data)
1760
        foreach ($session_data as $key => $session) {
1761
            $session_id = $session[0];
1762
            $session_title = $session[1];
1763
1764
            // getting all the courses of the session
1765
            $sql = "SELECT * FROM $tbl_course AS c
1766
                    INNER JOIN $tbl_session_rel_course AS sc
1767
                    ON sc.c_id = c.id
1768
                    WHERE sc.session_id = '".$session_id."';";
1769
            $result = Database::query($sql);
1770
            while ($row = Database::fetch_object($result)) {
1771
                $courseId = $row->c_id;
1772
                $courseInfo = api_get_course_info_by_id($courseId);
1773
                $csv_row = [];
1774
                $csv_row[] = $session_title;
1775
                $csv_row[] = $row->title;
1776
                // get the users in the course
1777
                $sql = "SELECT scu.user_id
1778
                        FROM $tbl_user AS u
1779
                        INNER JOIN $tbl_session_rel_course_rel_user AS scu
1780
                        ON u.user_id = scu.user_id
1781
                        WHERE scu.session_id = '".$session_id."' AND scu.c_id = '".$courseId."'";
1782
                $result_users = Database::query($sql);
1783
                $time_spent = 0;
1784
                $progress = 0;
1785
                $nb_progress_lp = 0;
1786
                $score = 0;
1787
                $nb_score_lp = 0;
1788
                $nb_messages = 0;
1789
                $nb_assignments = 0;
1790
                $last_login_date = false;
1791
                $total_score_obtained = 0;
1792
                $total_score_possible = 0;
1793
                $total_questions_answered = 0;
1794
                while ($row_user = Database::fetch_object($result_users)) {
1795
                    // get time spent in the course and session
1796
                    $time_spent += Tracking::get_time_spent_on_the_course($row_user->user_id, $courseId, $session_id);
1797
                    $progress_tmp = Tracking::get_avg_student_progress(
1798
                        $row_user->user_id,
1799
                        $row->code,
1800
                        [],
1801
                        $session_id,
1802
                        true
1803
                    );
1804
                    $progress += $progress_tmp[0];
1805
                    $nb_progress_lp += $progress_tmp[1];
1806
                    $score_tmp = Tracking::get_avg_student_score(
1807
                        $row_user->user_id,
1808
                        $row->code,
1809
                        [],
1810
                        $session_id,
1811
                        true
1812
                    );
1813
                    if (is_array($score_tmp)) {
1814
                        $score += $score_tmp[0];
1815
                        $nb_score_lp += $score_tmp[1];
1816
                    }
1817
                    $nb_messages += Tracking::count_student_messages(
1818
                        $row_user->user_id,
1819
                        $row->code,
1820
                        $session_id
1821
                    );
1822
1823
                    $nb_assignments += Tracking::count_student_assignments(
1824
                        $row_user->user_id,
1825
                        $row->code,
1826
                        $session_id
1827
                    );
1828
1829
                    $last_login_date_tmp = Tracking:: get_last_connection_date_on_the_course(
1830
                        $row_user->user_id,
1831
                        $courseInfo,
1832
                        $session_id,
1833
                        false
1834
                    );
1835
                    if ($last_login_date_tmp != false && $last_login_date == false) {
1836
                        // TODO: To be cleaned.
1837
                        $last_login_date = $last_login_date_tmp;
1838
                    } elseif ($last_login_date_tmp != false && $last_login_date == false) {
1839
                        // TODO: Repeated previous condition. To be cleaned.
1840
                        // Find the max and assign it to first_login_date
1841
                        if (strtotime($last_login_date_tmp) > strtotime($last_login_date)) {
1842
                            $last_login_date = $last_login_date_tmp;
1843
                        }
1844
                    }
1845
1846
                    $exercise_results_tmp = self::exercises_results($row_user->user_id, $row->code, $session_id);
1847
                    $total_score_obtained += $exercise_results_tmp['score_obtained'];
1848
                    $total_score_possible += $exercise_results_tmp['score_possible'];
1849
                    $total_questions_answered += $exercise_results_tmp['questions_answered'];
1850
                }
1851
                if ($nb_progress_lp > 0) {
1852
                    $avg_progress = round($progress / $nb_progress_lp, 2);
1853
                } else {
1854
                    $avg_progress = 0;
1855
                }
1856
                if ($nb_score_lp > 0) {
1857
                    $avg_score = round($score / $nb_score_lp, 2);
1858
                } else {
1859
                    $avg_score = '-';
1860
                }
1861
                if ($last_login_date) {
1862
                    $last_login_date = api_convert_and_format_date(
1863
                        $last_login_date,
1864
                        DATE_FORMAT_SHORT,
1865
                        date_default_timezone_get()
1866
                    );
1867
                } else {
1868
                    $last_login_date = '-';
1869
                }
1870
                if ($total_score_possible > 0) {
1871
                    $total_score_percentage = round($total_score_obtained / $total_score_possible * 100, 2);
1872
                } else {
1873
                    $total_score_percentage = 0;
1874
                }
1875
                if ($total_score_percentage > 0) {
1876
                    $total_score = $total_score_obtained.'/'.$total_score_possible.' ('.$total_score_percentage.' %)';
1877
                } else {
1878
                    $total_score = '-';
1879
                }
1880
                // time spent in the course
1881
                $csv_row[] = api_time_to_hms($time_spent);
1882
                // student progress in course
1883
                $csv_row[] = $avg_progress;
1884
                // student score
1885
                $csv_row[] = $avg_score;
1886
                // student messages
1887
                $csv_row[] = $nb_messages;
1888
                // student assignments
1889
                $csv_row[] = $nb_assignments;
1890
                // student exercises results (obtained score, maximum score, number of exercises answered, score percentage)
1891
                $csv_row[] = $total_score_obtained;
1892
                $csv_row[] = $total_score_possible;
1893
                $csv_row[] = $total_questions_answered;
1894
                $csv_row[] = $total_score_percentage;
1895
                // last connection
1896
                $csv_row[] = $last_login_date;
1897
                $csv_content[] = $csv_row;
1898
            }
1899
        }
1900
        Export::arrayToCsv($csv_content, 'reporting_session_overview');
1901
        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

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

Loading history...
1902
    }
1903
1904
    /**
1905
     * Get general information about the exercise performance of the user
1906
     * the total obtained score (all the score on all the questions)
1907
     * the maximum score that could be obtained
1908
     * the number of questions answered
1909
     * the success percentage.
1910
     *
1911
     * @param int    $user_id     the id of the user
1912
     * @param string $course_code the course code
1913
     * @param int    $session_id
1914
     *
1915
     * @return array
1916
     *
1917
     * @author Patrick Cool <[email protected]>, Ghent University, Belgium
1918
     *
1919
     * @version Dokeos 1.8.6
1920
     *
1921
     * @since November 2008
1922
     */
1923
    public static function exercises_results($user_id, $course_code, $session_id = 0)
1924
    {
1925
        $user_id = (int) $user_id;
1926
        $courseId = api_get_course_int_id($course_code);
1927
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
1928
1929
        $sql = "SELECT exe_result, exe_weighting
1930
                FROM $table
1931
                WHERE
1932
                    c_id = $courseId AND
1933
                    exe_user_id = $user_id";
1934
1935
        $session_id = (int) $session_id;
1936
        if (!empty($session_id)) {
1937
            $sql .= " AND session_id = '".$session_id."' ";
1938
        }
1939
        $result = Database::query($sql);
1940
        $score_obtained = 0;
1941
        $score_possible = 0;
1942
        $questions_answered = 0;
1943
        while ($row = Database::fetch_array($result)) {
1944
            $score_obtained += $row['exe_result'];
1945
            $score_possible += $row['exe_weighting'];
1946
            $questions_answered++;
1947
        }
1948
1949
        $percentage = null;
1950
        if ($score_possible != 0) {
1951
            $percentage = round(($score_obtained / $score_possible * 100), 2);
1952
        }
1953
1954
        return [
1955
            'score_obtained' => $score_obtained,
1956
            'score_possible' => $score_possible,
1957
            'questions_answered' => $questions_answered,
1958
            'percentage' => $percentage,
1959
        ];
1960
    }
1961
1962
    /**
1963
     * This function exports the table that we see in display_tracking_user_overview().
1964
     *
1965
     * @author Patrick Cool <[email protected]>, Ghent University, Belgium
1966
     *
1967
     * @version Dokeos 1.8.6
1968
     *
1969
     * @since October 2008
1970
     */
1971
    public static function export_tracking_user_overview()
1972
    {
1973
        // database table definitions
1974
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1975
        $is_western_name_order = api_is_western_name_order(PERSON_NAME_DATA_EXPORT);
1976
1977
        // the values of the sortable table
1978
        if ($_GET['tracking_user_overview_page_nr']) {
1979
            $from = $_GET['tracking_user_overview_page_nr'];
1980
        } else {
1981
            $from = 0;
1982
        }
1983
        if ($_GET['tracking_user_overview_column']) {
1984
            $orderby = $_GET['tracking_user_overview_column'];
1985
        } else {
1986
            $orderby = 0;
1987
        }
1988
        if ($is_western_name_order != api_is_western_name_order() && ($orderby == 1 || $orderby == 2)) {
1989
            // Swapping the sorting column if name order for export is different than the common name order.
1990
            $orderby = 3 - $orderby;
1991
        }
1992
        if ($_GET['tracking_user_overview_direction']) {
1993
            $direction = $_GET['tracking_user_overview_direction'];
1994
        } else {
1995
            $direction = 'ASC';
1996
        }
1997
1998
        $user_data = self::get_user_data_tracking_overview(
1999
            $from,
2000
            1000,
2001
            $orderby,
2002
            $direction
2003
        );
2004
2005
        // the first line of the csv file with the column headers
2006
        $csv_row = [];
2007
        $csv_row[] = get_lang('OfficialCode');
2008
        if ($is_western_name_order) {
2009
            $csv_row[] = get_lang('FirstName');
2010
            $csv_row[] = get_lang('LastName');
2011
        } else {
2012
            $csv_row[] = get_lang('LastName');
2013
            $csv_row[] = get_lang('FirstName');
2014
        }
2015
        $csv_row[] = get_lang('LoginName');
2016
        $csv_row[] = get_lang('CourseCode');
2017
2018
        // the additional user defined fields (only those that were selected to be exported)
2019
        $fields = UserManager::get_extra_fields(0, 50, 5, 'ASC');
2020
2021
        $additionalExportFields = Session::read('additional_export_fields');
2022
2023
        if (is_array($additionalExportFields)) {
2024
            foreach ($additionalExportFields as $key => $extra_field_export) {
2025
                $csv_row[] = $fields[$extra_field_export][3];
2026
                $field_names_to_be_exported[] = 'extra_'.$fields[$extra_field_export][1];
2027
            }
2028
        }
2029
        $csv_row[] = get_lang('AvgTimeSpentInTheCourse', '');
2030
        $csv_row[] = get_lang('AvgStudentsProgress', '');
2031
        $csv_row[] = get_lang('AvgCourseScore', '');
2032
        $csv_row[] = get_lang('AvgExercisesScore', '');
2033
        $csv_row[] = get_lang('AvgMessages', '');
2034
        $csv_row[] = get_lang('AvgAssignments', '');
2035
        $csv_row[] = get_lang('TotalExercisesScoreObtained', '');
2036
        $csv_row[] = get_lang('TotalExercisesScorePossible', '');
2037
        $csv_row[] = get_lang('TotalExercisesAnswered', '');
2038
        $csv_row[] = get_lang('TotalExercisesScorePercentage', '');
2039
        $csv_row[] = get_lang('FirstLogin', '');
2040
        $csv_row[] = get_lang('LatestLogin', '');
2041
        $csv_content[] = $csv_row;
2042
2043
        // the other lines (the data)
2044
        foreach ($user_data as $key => $user) {
2045
            // getting all the courses of the user
2046
            $sql = "SELECT * FROM $tbl_course_user
2047
                    WHERE user_id = '".intval($user[4])."' AND relation_type<>".COURSE_RELATION_TYPE_RRHH." ";
2048
            $result = Database::query($sql);
2049
            while ($row = Database::fetch_row($result)) {
2050
                $courseInfo = api_get_course_info($row['course_code']);
2051
                $courseId = $courseInfo['real_id'];
2052
2053
                $csv_row = [];
2054
                // user official code
2055
                $csv_row[] = $user[0];
2056
                // user first|last name
2057
                $csv_row[] = $user[1];
2058
                // user last|first name
2059
                $csv_row[] = $user[2];
2060
                // user login name
2061
                $csv_row[] = $user[3];
2062
                // course code
2063
                $csv_row[] = $row[0];
2064
                // the additional defined user fields
2065
                $extra_fields = self::get_user_overview_export_extra_fields($user[4]);
2066
2067
                if (is_array($field_names_to_be_exported)) {
2068
                    foreach ($field_names_to_be_exported as $key => $extra_field_export) {
2069
                        $csv_row[] = $extra_fields[$extra_field_export];
2070
                    }
2071
                }
2072
                // time spent in the course
2073
                $csv_row[] = api_time_to_hms(Tracking::get_time_spent_on_the_course($user[4], $courseId));
2074
                // student progress in course
2075
                $csv_row[] = round(Tracking::get_avg_student_progress($user[4], $row[0]), 2);
2076
                // student score
2077
                $csv_row[] = round(Tracking::get_avg_student_score($user[4], $row[0]), 2);
2078
                // student tes score
2079
                $csv_row[] = round(Tracking::get_avg_student_exercise_score($user[4], $row[0]), 2);
2080
                // student messages
2081
                $csv_row[] = Tracking::count_student_messages($user[4], $row[0]);
2082
                // student assignments
2083
                $csv_row[] = Tracking::count_student_assignments($user[4], $row[0]);
2084
                // student exercises results
2085
                $exercises_results = self::exercises_results($user[4], $row[0]);
2086
                $csv_row[] = $exercises_results['score_obtained'];
2087
                $csv_row[] = $exercises_results['score_possible'];
2088
                $csv_row[] = $exercises_results['questions_answered'];
2089
                $csv_row[] = $exercises_results['percentage'];
2090
                // first connection
2091
                $csv_row[] = Tracking::get_first_connection_date_on_the_course($user[4], $courseId);
2092
                // last connection
2093
                $csv_row[] = strip_tags(Tracking::get_last_connection_date_on_the_course($user[4], $courseInfo));
2094
2095
                $csv_content[] = $csv_row;
2096
            }
2097
        }
2098
        Export::arrayToCsv($csv_content, 'reporting_user_overview');
2099
        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

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

Loading history...
2100
    }
2101
2102
    /**
2103
     * Get data for courses list in sortable with pagination.
2104
     *
2105
     * @return array
2106
     */
2107
    public static function get_course_data($from, $number_of_items, $column, $direction)
2108
    {
2109
        global $courses, $csv_content, $charset, $session_id;
2110
2111
        // definition database tables
2112
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
2113
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2114
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2115
2116
        $course_data = [];
2117
        $courses_code = array_keys($courses);
2118
2119
        foreach ($courses_code as &$code) {
2120
            $code = "'$code'";
2121
        }
2122
2123
        // get all courses with limit
2124
        $sql = "SELECT course.code as col1, course.title as col2
2125
                FROM $tbl_course course
2126
                WHERE course.code IN (".implode(',', $courses_code).")";
2127
2128
        if (!in_array($direction, ['ASC', 'DESC'])) {
2129
            $direction = 'ASC';
2130
        }
2131
2132
        $column = (int) $column;
2133
        $from = (int) $from;
2134
        $number_of_items = (int) $number_of_items;
2135
        $sql .= " ORDER BY col$column $direction ";
2136
        $sql .= " LIMIT $from,$number_of_items";
2137
2138
        $res = Database::query($sql);
2139
        while ($row_course = Database::fetch_row($res)) {
2140
            $course_code = $row_course[0];
2141
            $courseInfo = api_get_course_info($course_code);
2142
            $courseId = $courseInfo['real_id'];
2143
            $avg_assignments_in_course = $avg_messages_in_course = $nb_students_in_course = $avg_progress_in_course = $avg_score_in_course = $avg_time_spent_in_course = $avg_score_in_exercise = 0;
2144
2145
            // students directly subscribed to the course
2146
            if (empty($session_id)) {
2147
                $sql = "SELECT user_id
2148
                        FROM $tbl_course_user as course_rel_user
2149
                        WHERE
2150
                            course_rel_user.status='5' AND
2151
                            course_rel_user.c_id = '$courseId'";
2152
            } else {
2153
                $sql = "SELECT user_id FROM $tbl_session_course_user srcu
2154
                        WHERE
2155
                            c_id = '$courseId' AND
2156
                            session_id = '$session_id' AND
2157
                            status<>2";
2158
            }
2159
            $rs = Database::query($sql);
2160
            $users = [];
2161
            while ($row = Database::fetch_array($rs)) {
2162
                $users[] = $row['user_id'];
2163
            }
2164
2165
            if (count($users) > 0) {
2166
                $nb_students_in_course = count($users);
2167
                $avg_assignments_in_course = Tracking::count_student_assignments($users, $course_code, $session_id);
2168
                $avg_messages_in_course = Tracking::count_student_messages($users, $course_code, $session_id);
2169
                $avg_progress_in_course = Tracking::get_avg_student_progress($users, $course_code, [], $session_id);
2170
                $avg_score_in_course = Tracking::get_avg_student_score($users, $course_code, [], $session_id);
2171
                $avg_score_in_exercise = Tracking::get_avg_student_exercise_score($users, $course_code, 0, $session_id);
2172
                $avg_time_spent_in_course = Tracking::get_time_spent_on_the_course(
2173
                    $users,
2174
                    $courseInfo['real_id'],
2175
                    $session_id
2176
                );
2177
2178
                $avg_progress_in_course = round($avg_progress_in_course / $nb_students_in_course, 2);
2179
                if (is_numeric($avg_score_in_course)) {
2180
                    $avg_score_in_course = round($avg_score_in_course / $nb_students_in_course, 2);
2181
                }
2182
                $avg_time_spent_in_course = api_time_to_hms($avg_time_spent_in_course / $nb_students_in_course);
2183
            } else {
2184
                $avg_time_spent_in_course = null;
2185
                $avg_progress_in_course = null;
2186
                $avg_score_in_course = null;
2187
                $avg_score_in_exercise = null;
2188
                $avg_messages_in_course = null;
2189
                $avg_assignments_in_course = null;
2190
            }
2191
            $table_row = [];
2192
            $table_row[] = $row_course[1];
2193
            $table_row[] = $nb_students_in_course;
2194
            $table_row[] = $avg_time_spent_in_course;
2195
            $table_row[] = is_null($avg_progress_in_course) ? '' : $avg_progress_in_course.'%';
2196
            $table_row[] = is_null($avg_score_in_course) ? '' : $avg_score_in_course.'%';
2197
            $table_row[] = is_null($avg_score_in_exercise) ? '' : $avg_score_in_exercise.'%';
2198
            $table_row[] = $avg_messages_in_course;
2199
            $table_row[] = $avg_assignments_in_course;
2200
2201
            //set the "from" value to know if I access the Reporting by the chamilo tab or the course link
2202
            $table_row[] = '<center><a href="../../tracking/courseLog.php?cidReq='.$course_code.'&from=myspace&id_session='.$session_id.'">
2203
                             '.Display::return_icon('2rightarrow.png', get_lang('Details')).'
2204
                             </a>
2205
                            </center>';
2206
            $csv_content[] = [
2207
                api_html_entity_decode($row_course[1], ENT_QUOTES, $charset),
2208
                $nb_students_in_course,
2209
                $avg_time_spent_in_course,
2210
                is_null($avg_progress_in_course) ? null : $avg_progress_in_course.'%',
2211
                is_null($avg_score_in_course) ? null : is_numeric($avg_score_in_course) ? $avg_score_in_course.'%' : $avg_score_in_course,
2212
                is_null($avg_score_in_exercise) ? null : $avg_score_in_exercise.'%',
2213
                $avg_messages_in_course,
2214
                $avg_assignments_in_course,
2215
            ];
2216
            $course_data[] = $table_row;
2217
        }
2218
2219
        return $course_data;
2220
    }
2221
2222
    /**
2223
     * Get the number of users of the platform.
2224
     *
2225
     * @return int
2226
     */
2227
    public static function get_number_of_users_tracking_overview()
2228
    {
2229
        return UserManager::get_number_of_users(0, api_get_current_access_url_id());
2230
    }
2231
2232
    /**
2233
     * Get all the data for the sortable table of the reporting progress of
2234
     * all users and all the courses the user is subscribed to.
2235
     *
2236
     * @param int    $from
2237
     * @param int    $numberItems
2238
     * @param int    $column
2239
     * @param string $direction
2240
     *
2241
     * @return array
2242
     */
2243
    public static function get_user_data_tracking_overview($from, $numberItems, $column, $direction)
2244
    {
2245
        $isWestern = api_is_western_name_order();
2246
2247
        switch ($column) {
2248
            case '0':
2249
                $column = 'official_code';
2250
                break;
2251
            case '1':
2252
                $column = $isWestern ? 'firstname' : 'lastname';
2253
                break;
2254
            case '2':
2255
                $column = $isWestern ? 'lastname' : 'firstname';
2256
                break;
2257
            case '3':
2258
                $column = 'username';
2259
                break;
2260
            case '4':
2261
                $column = 'username';
2262
                break;
2263
        }
2264
2265
        $order = [
2266
            " `$column` $direction",
2267
        ];
2268
        $userList = UserManager::get_user_list([], $order, $from, $numberItems);
2269
        $return = [];
2270
        foreach ($userList as $user) {
2271
            $firstPosition = $user['lastname'];
2272
            $secondPosition = $user['firstname'];
2273
            if ($isWestern) {
2274
                $firstPosition = $user['firstname'];
2275
                $secondPosition = $user['lastname'];
2276
            }
2277
            $return[] = [
2278
                '0' => $user['official_code'],
2279
                'col0' => $user['official_code'],
2280
                '1' => $firstPosition,
2281
                'col1' => $firstPosition,
2282
                '2' => $secondPosition,
2283
                'col2' => $secondPosition,
2284
                '3' => $user['username'],
2285
                'col3' => $user['username'],
2286
                '4' => $user['user_id'],
2287
                'col4' => $user['user_id'],
2288
            ];
2289
        }
2290
2291
        return $return;
2292
    }
2293
2294
    /**
2295
     * Get all information that the user with user_id = $user_data has
2296
     * entered in the additionally defined profile fields.
2297
     *
2298
     * @param int $user_id the id of the user
2299
     *
2300
     * @return array
2301
     *
2302
     * @author Patrick Cool <[email protected]>, Ghent University, Belgium
2303
     *
2304
     * @version Dokeos 1.8.6
2305
     *
2306
     * @since November 2008
2307
     */
2308
    public static function get_user_overview_export_extra_fields($user_id)
2309
    {
2310
        // include the user manager
2311
        $data = UserManager::get_extra_user_data($user_id, true);
2312
2313
        return $data;
2314
    }
2315
2316
    /**
2317
     * Checks if a username exist in the DB otherwise it create a "double"
2318
     * i.e. if we look into for jmontoya but the user's name already exist we create the user jmontoya2
2319
     * the return array will be array(username=>'jmontoya', sufix='2').
2320
     *
2321
     * @param string firstname
2322
     * @param string lastname
2323
     * @param string username
2324
     *
2325
     * @return array with the username, the sufix
2326
     *
2327
     * @author Julio Montoya
2328
     */
2329
    public static function make_username($firstname, $lastname, $username, $language = null, $encoding = null)
2330
    {
2331
        // if username exist
2332
        if (!UserManager::is_username_available($username) || empty($username)) {
2333
            $i = 0;
2334
            while (1) {
2335
                if ($i == 0) {
2336
                    $sufix = '';
2337
                } else {
2338
                    $sufix = $i;
2339
                }
2340
                $desired_username = UserManager::create_username(
2341
                    $firstname,
2342
                    $lastname
2343
                );
2344
                if (UserManager::is_username_available($desired_username.$sufix)) {
2345
                    break;
2346
                } else {
2347
                    $i++;
2348
                }
2349
            }
2350
            $username_array = ['username' => $desired_username, 'sufix' => $sufix];
2351
2352
            return $username_array;
2353
        } else {
2354
            $username_array = ['username' => $username, 'sufix' => ''];
2355
2356
            return $username_array;
2357
        }
2358
    }
2359
2360
    /**
2361
     * Checks if there are repeted users in a given array.
2362
     *
2363
     * @param array $usernames  list of the usernames in the uploaded file
2364
     * @param array $user_array $user_array['username'] and $user_array['sufix']
2365
     *                          where suffix is the number part in a login i.e -> jmontoya2
2366
     *
2367
     * @return array with the $usernames array and the $user_array array
2368
     *
2369
     * @author Julio Montoya
2370
     */
2371
    public static function check_user_in_array($usernames, $user_array)
2372
    {
2373
        $user_list = array_keys($usernames);
2374
        $username = $user_array['username'].$user_array['sufix'];
2375
2376
        if (in_array($username, $user_list)) {
2377
            $user_array['sufix'] += $usernames[$username];
2378
            $usernames[$username]++;
2379
        } else {
2380
            $usernames[$username] = 1;
2381
        }
2382
        $result_array = [$usernames, $user_array];
2383
2384
        return $result_array;
2385
    }
2386
2387
    /**
2388
     * Checks whether a username has been already subscribed in a session.
2389
     *
2390
     * @param string $username    a given username
2391
     * @param array  $course_list the array with the course list id
2392
     * @param int    $id_session  the session id
2393
     *
2394
     * @return int 0 if the user is not subscribed otherwise it returns the user_id of the given username
2395
     *
2396
     * @author Julio Montoya
2397
     */
2398
    public static function user_available_in_session($username, $course_list, $id_session)
2399
    {
2400
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
2401
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2402
        $id_session = (int) $id_session;
2403
        $username = Database::escape_string($username);
2404
        foreach ($course_list as $courseId) {
2405
            $courseId = (int) $courseId;
2406
            $sql = " SELECT u.user_id FROM $tbl_session_rel_course_rel_user rel
2407
                     INNER JOIN $table_user u
2408
                     ON (rel.user_id = u.user_id)
2409
                     WHERE
2410
                        rel.session_id='$id_session' AND
2411
                        u.status='5' AND
2412
                        u.username ='$username' AND
2413
                        rel.c_id='$courseId'";
2414
            $rs = Database::query($sql);
2415
            if (Database::num_rows($rs) > 0) {
2416
                return Database::result($rs, 0, 0);
2417
            }
2418
        }
2419
2420
        return 0;
2421
    }
2422
2423
    /**
2424
     * This function checks whether some users in the uploaded file
2425
     * repeated and creates unique usernames if necesary.
2426
     * A case: Within the file there is an user repeted twice (Julio Montoya / Julio Montoya)
2427
     * and the username fields are empty.
2428
     * Then, this function would create unique usernames based on the first and the last name.
2429
     * Two users wiould be created - jmontoya and jmontoya2.
2430
     * Of course, if in the database there is a user with the name jmontoya,
2431
     * the newly created two users registered would be jmontoya2 and jmontoya3.
2432
     *
2433
     * @param $users list of users
2434
     *
2435
     * @return array
2436
     *
2437
     * @author Julio Montoya Armas
2438
     */
2439
    public static function check_all_usernames($users, $course_list, $id_session)
2440
    {
2441
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
2442
        $usernames = [];
2443
        $new_users = [];
2444
        foreach ($users as $index => $user) {
2445
            $desired_username = [];
2446
            if (empty($user['UserName'])) {
2447
                $desired_username = self::make_username($user['FirstName'], $user['LastName'], '');
2448
                $pre_username = $desired_username['username'].$desired_username['sufix'];
2449
                $user['UserName'] = $pre_username;
2450
                $user['create'] = '1';
2451
            } else {
2452
                if (UserManager::is_username_available($user['UserName'])) {
2453
                    $desired_username = self::make_username($user['FirstName'], $user['LastName'], $user['UserName']);
2454
                    $user['UserName'] = $desired_username['username'].$desired_username['sufix'];
2455
                    $user['create'] = '1';
2456
                } else {
2457
                    $is_session_avail = self::user_available_in_session($user['UserName'], $course_list, $id_session);
2458
                    if ($is_session_avail == 0) {
2459
                        $user_name = $user['UserName'];
2460
                        $sql_select = "SELECT user_id FROM $table_user WHERE username ='$user_name' ";
2461
                        $rs = Database::query($sql_select);
2462
                        $user['create'] = Database::result($rs, 0, 0);
2463
                    } else {
2464
                        $user['create'] = $is_session_avail;
2465
                    }
2466
                }
2467
            }
2468
            // Usernames is the current list of users in the file.
2469
            $result_array = self::check_user_in_array($usernames, $desired_username);
2470
            $usernames = $result_array[0];
2471
            $desired_username = $result_array[1];
2472
            $user['UserName'] = $desired_username['username'].$desired_username['sufix'];
2473
            $new_users[] = $user;
2474
        }
2475
2476
        return $new_users;
2477
    }
2478
2479
    /**
2480
     * This functions checks whether there are users that are already
2481
     * registered in the DB by different creator than the current coach.
2482
     *
2483
     * @param array $users
2484
     *
2485
     * @return array
2486
     *
2487
     * @author Julio Montoya Armas
2488
     */
2489
    public static function get_user_creator($users)
2490
    {
2491
        $errors = [];
2492
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
2493
        foreach ($users as $index => $user) {
2494
            $username = Database::escape_string($user['UserName']);
2495
            $sql = "SELECT creator_id FROM $table_user WHERE username='$username' ";
2496
2497
            $rs = Database::query($sql);
2498
            $creator_id = Database::result($rs, 0, 0);
2499
            // check if we are the creators or not
2500
            if ($creator_id != '') {
2501
                if ($creator_id != api_get_user_id()) {
2502
                    $user['error'] = get_lang('UserAlreadyRegisteredByOtherCreator');
2503
                    $errors[] = $user;
2504
                }
2505
            }
2506
        }
2507
2508
        return $errors;
2509
    }
2510
2511
    /**
2512
     * Validates imported data.
2513
     *
2514
     * @param array $users list of users
2515
     */
2516
    public static function validate_data($users, $id_session = null)
2517
    {
2518
        $errors = [];
2519
        $new_users = [];
2520
        foreach ($users as $index => $user) {
2521
            // 1. Check whether mandatory fields are set.
2522
            $mandatory_fields = ['LastName', 'FirstName'];
2523
            if (api_get_setting('registration', 'email') == 'true') {
2524
                $mandatory_fields[] = 'Email';
2525
            }
2526
2527
            foreach ($mandatory_fields as $key => $field) {
2528
                if (!isset($user[$field]) || strlen($user[$field]) == 0) {
2529
                    $user['error'] = get_lang($field.'Mandatory');
2530
                    $errors[] = $user;
2531
                }
2532
            }
2533
            // 2. Check whether the username is too long.
2534
            if (UserManager::is_username_too_long($user['UserName'])) {
2535
                $user['error'] = get_lang('UserNameTooLong');
2536
                $errors[] = $user;
2537
            }
2538
2539
            $user['UserName'] = trim($user['UserName']);
2540
2541
            if (empty($user['UserName'])) {
2542
                $user['UserName'] = UserManager::create_username($user['FirstName'], $user['LastName']);
2543
            }
2544
            $new_users[] = $user;
2545
        }
2546
        $results = ['errors' => $errors, 'users' => $new_users];
2547
2548
        return $results;
2549
    }
2550
2551
    /**
2552
     * Adds missing user-information (which isn't required, like password, etc).
2553
     */
2554
    public static function complete_missing_data($user)
2555
    {
2556
        // 1. Generate a password if it is necessary.
2557
        if (!isset($user['Password']) || strlen($user['Password']) == 0) {
2558
            $user['Password'] = api_generate_password();
2559
        }
2560
2561
        return $user;
2562
    }
2563
2564
    /**
2565
     * Saves imported data.
2566
     */
2567
    public static function save_data($users, $course_list, $id_session)
2568
    {
2569
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2570
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2571
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2572
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
2573
2574
        $id_session = (int) $id_session;
2575
        $sendMail = $_POST['sendMail'] ? 1 : 0;
2576
2577
        // Adding users to the platform.
2578
        $new_users = [];
2579
        foreach ($users as $index => $user) {
2580
            $user = self::complete_missing_data($user);
2581
            // coach only will registered users
2582
            $default_status = STUDENT;
2583
            if ($user['create'] == COURSEMANAGER) {
2584
                $user['id'] = UserManager:: create_user(
2585
                    $user['FirstName'],
2586
                    $user['LastName'],
2587
                    $default_status,
2588
                    $user['Email'],
2589
                    $user['UserName'],
2590
                    $user['Password'],
2591
                    $user['OfficialCode'],
2592
                    api_get_setting('PlatformLanguage'),
2593
                    $user['PhoneNumber'],
2594
                    ''
2595
                );
2596
                $user['added_at_platform'] = 1;
2597
            } else {
2598
                $user['id'] = $user['create'];
2599
                $user['added_at_platform'] = 0;
2600
            }
2601
            $new_users[] = $user;
2602
        }
2603
        // Update user list.
2604
        $users = $new_users;
2605
2606
        // Inserting users.
2607
        foreach ($course_list as $enreg_course) {
2608
            $nbr_users = 0;
2609
            $new_users = [];
2610
            $enreg_course = Database::escape_string($enreg_course);
2611
            foreach ($users as $index => $user) {
2612
                $userid = (int) $user['id'];
2613
                $sql = "INSERT IGNORE INTO $tbl_session_rel_course_rel_user(session_id, c_id, user_id)
2614
                        VALUES('$id_session','$enreg_course','$userid')";
2615
                $result = Database::query($sql);
2616
                if (Database::affected_rows($result)) {
2617
                    $nbr_users++;
2618
                }
2619
                $new_users[] = $user;
2620
            }
2621
2622
            //update the nbr_users field
2623
            $sql_select = "SELECT COUNT(user_id) as nbUsers FROM $tbl_session_rel_course_rel_user
2624
                           WHERE session_id='$id_session' AND c_id='$enreg_course'";
2625
            $rs = Database::query($sql_select);
2626
            list($nbr_users) = Database::fetch_array($rs);
2627
            $sql_update = "UPDATE $tbl_session_rel_course SET nbr_users=$nbr_users
2628
                           WHERE session_id='$id_session' AND c_id='$enreg_course'";
2629
            Database::query($sql_update);
2630
2631
            $sql_update = "UPDATE $tbl_session SET nbr_users= '$nbr_users' WHERE id='$id_session'";
2632
            Database::query($sql_update);
2633
        }
2634
2635
        $new_users = [];
2636
        foreach ($users as $index => $user) {
2637
            $userid = $user['id'];
2638
            $sql_insert = "INSERT IGNORE INTO $tbl_session_rel_user(session_id, user_id, registered_at)
2639
                           VALUES ('$id_session','$userid', '".api_get_utc_datetime()."')";
2640
            Database::query($sql_insert);
2641
            $user['added_at_session'] = 1;
2642
            $new_users[] = $user;
2643
        }
2644
2645
        $users = $new_users;
2646
        $registered_users = get_lang('FileImported').'<br /> Import file results : <br />';
2647
        // Sending emails.
2648
        $addedto = '';
2649
        if ($sendMail) {
2650
            foreach ($users as $index => $user) {
2651
                $emailsubject = '['.api_get_setting('siteName').'] '.get_lang('YourReg').' '.api_get_setting('siteName');
2652
                $emailbody = get_lang('Dear').' '.
2653
                    api_get_person_name($user['FirstName'], $user['LastName']).",\n\n".
2654
                    get_lang('YouAreReg')." ".api_get_setting('siteName')." ".get_lang('WithTheFollowingSettings')."\n\n".
2655
                    get_lang('Username')." : $user[UserName]\n".
2656
                    get_lang('Pass')." : $user[Password]\n\n".
2657
                    get_lang('Address')." ".api_get_setting('siteName')." ".get_lang('Is')." : ".api_get_path(WEB_PATH)." \n\n".
2658
                    get_lang('Problem')."\n\n".
2659
                    get_lang('SignatureFormula').",\n\n".
2660
                    api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'))."\n".
2661
                    get_lang('Manager')." ".api_get_setting('siteName')."\nT. ".
2662
                    api_get_setting('administratorTelephone')."\n".get_lang('Email')." : ".api_get_setting('emailAdministrator');
2663
2664
                api_mail_html(
2665
                    api_get_person_name($user['FirstName'], $user['LastName'], null, PERSON_NAME_EMAIL_ADDRESS),
2666
                    $user['Email'],
2667
                    $emailsubject,
2668
                    $emailbody
2669
                );
2670
                $userInfo = api_get_user_info($user['id']);
2671
2672
                if (($user['added_at_platform'] == 1 && $user['added_at_session'] == 1) || $user['added_at_session'] == 1) {
2673
                    if ($user['added_at_platform'] == 1) {
2674
                        $addedto = get_lang('UserCreatedPlatform');
2675
                    } else {
2676
                        $addedto = '          ';
2677
                    }
2678
2679
                    if ($user['added_at_session'] == 1) {
2680
                        $addedto .= get_lang('UserInSession');
2681
                    }
2682
                } else {
2683
                    $addedto = get_lang('UserNotAdded');
2684
                }
2685
2686
                $registered_users .= UserManager::getUserProfileLink($userInfo).' - '.$addedto.'<br />';
2687
            }
2688
        } else {
2689
            foreach ($users as $index => $user) {
2690
                $userInfo = api_get_user_info($user['id']);
2691
                if (($user['added_at_platform'] == 1 && $user['added_at_session'] == 1) || $user['added_at_session'] == 1) {
2692
                    if ($user['added_at_platform'] == 1) {
2693
                        $addedto = get_lang('UserCreatedPlatform');
2694
                    } else {
2695
                        $addedto = '          ';
2696
                    }
2697
2698
                    if ($user['added_at_session'] == 1) {
2699
                        $addedto .= ' '.get_lang('UserInSession');
2700
                    }
2701
                } else {
2702
                    $addedto = get_lang('UserNotAdded');
2703
                }
2704
                $registered_users .= "<a href=\"../user/userInfo.php?uInfo=".$user['id']."\">".
2705
                    Security::remove_XSS($userInfo['complete_user_name'])."</a> - ".$addedto.'<br />';
2706
            }
2707
        }
2708
        Display::addFlash(Display::return_message($registered_users, 'normal', false));
2709
        header('Location: course.php?id_session='.$id_session);
2710
        exit;
2711
    }
2712
2713
    /**
2714
     * Reads CSV-file.
2715
     *
2716
     * @param string $file Path to the CSV-file
2717
     *
2718
     * @return array All userinformation read from the file
2719
     */
2720
    public function parse_csv_data($file)
2721
    {
2722
        $users = Import::csvToArray($file);
2723
        foreach ($users as $index => $user) {
2724
            if (isset($user['Courses'])) {
2725
                $user['Courses'] = explode('|', trim($user['Courses']));
2726
            }
2727
            $users[$index] = $user;
2728
        }
2729
2730
        return $users;
2731
    }
2732
2733
    /**
2734
     * Reads XML-file.
2735
     *
2736
     * @param string $file Path to the XML-file
2737
     *
2738
     * @return array All userinformation read from the file
2739
     */
2740
    public static function parse_xml_data($file)
2741
    {
2742
        $crawler = new \Symfony\Component\DomCrawler\Crawler();
2743
        $crawler->addXmlContent(file_get_contents($file));
2744
        $crawler = $crawler->filter('Contacts > Contact ');
2745
        $array = [];
2746
        foreach ($crawler as $domElement) {
2747
            $row = [];
2748
            foreach ($domElement->childNodes as $node) {
2749
                if ($node->nodeName != '#text') {
2750
                    $row[$node->nodeName] = $node->nodeValue;
2751
                }
2752
            }
2753
            if (!empty($row)) {
2754
                $array[] = $row;
2755
            }
2756
        }
2757
2758
        return $array;
2759
    }
2760
2761
    /**
2762
     * @param int $courseId
2763
     * @param int $sessionId
2764
     * @param int $studentId
2765
     */
2766
    public static function displayTrackingAccessOverView($courseId, $sessionId, $studentId)
2767
    {
2768
        $courseId = (int) $courseId;
2769
        $sessionId = (int) $sessionId;
2770
        $studentId = (int) $studentId;
2771
2772
        $courseList = [];
2773
        $sessionList = [];
2774
        $studentList = [];
2775
2776
        if (!empty($courseId)) {
2777
            $course = api_get_course_entity($courseId);
2778
            if ($course) {
2779
                $courseList[$course->getId()] = $course->getTitle();
2780
            }
2781
        }
2782
2783
        if (!empty($sessionId)) {
2784
            $session = api_get_session_entity($sessionId);
2785
            if ($session) {
2786
                $sessionList[$session->getId()] = $session->getName();
2787
            }
2788
        }
2789
2790
        if (!empty($studentId)) {
2791
            $student = api_get_user_entity($studentId);
2792
            if ($student) {
2793
                $studentList[$student->getId()] = UserManager::formatUserFullName($student);
2794
            }
2795
        }
2796
2797
        $form = new FormValidator('access_overview', 'GET');
2798
        $form->addElement(
2799
            'select_ajax',
2800
            'course_id',
2801
            get_lang('SearchCourse'),
2802
            $courseList,
2803
            [
2804
                'url' => api_get_path(WEB_AJAX_PATH).'course.ajax.php?'.http_build_query([
2805
                    'a' => 'search_course_by_session_all',
2806
                    'session_id' => $sessionId,
2807
                    'course_id' => $courseId,
2808
                ]),
2809
            ]
2810
        );
2811
2812
        $form->addElement(
2813
            'select_ajax',
2814
            'session_id',
2815
            get_lang('SearchSession'),
2816
            $sessionList,
2817
            [
2818
                'url_function' => "
2819
                    function () {
2820
                        var params = $.param({
2821
                            a: 'search_session_by_course',
2822
                            course_id: $('#access_overview_course_id').val() || 0
2823
                        });
2824
2825
                        return '".api_get_path(WEB_AJAX_PATH)."session.ajax.php?' + params;
2826
                    }
2827
                ",
2828
            ]
2829
        );
2830
2831
        $form->addSelect(
2832
            'profile',
2833
            get_lang('Profile'),
2834
            [
2835
                '' => get_lang('Select'),
2836
                STUDENT => get_lang('Student'),
2837
                COURSEMANAGER => get_lang('CourseManager'),
2838
                DRH => get_lang('Drh'),
2839
            ],
2840
            ['id' => 'profile']
2841
        );
2842
2843
        $form->addElement(
2844
            'select_ajax',
2845
            'student_id',
2846
            get_lang('SearchUsers'),
2847
            $studentList,
2848
            [
2849
                'placeholder' => get_lang('All'),
2850
                'url_function' => "
2851
                    function () {
2852
                        var params = $.param({
2853
                            a: 'search_user_by_course',
2854
                            session_id: $('#access_overview_session_id').val(),
2855
                            course_id: $('#access_overview_course_id').val()
2856
                        });
2857
2858
                        return '".api_get_path(WEB_AJAX_PATH)."course.ajax.php?' + params;
2859
                    }
2860
                ",
2861
            ]
2862
        );
2863
        $form->addDateRangePicker(
2864
            'date',
2865
            get_lang('DateRange'),
2866
            true,
2867
            [
2868
                'id' => 'date_range',
2869
                'format' => 'YYYY-MM-DD',
2870
                'timePicker' => 'false',
2871
                'validate_format' => 'Y-m-d',
2872
            ]
2873
        );
2874
        $form->addHidden('display', 'accessoverview');
2875
        $form->addRule('course_id', get_lang('Required'), 'required');
2876
        $form->addRule('profile', get_lang('Required'), 'required');
2877
        $form->addButton('submit', get_lang('Generate'), 'gear', 'primary');
2878
2879
        $table = null;
2880
2881
        if ($form->validate()) {
2882
            $table = new SortableTable(
2883
                'tracking_access_overview',
2884
                ['MySpace', 'getNumberOfTrackAccessOverview'],
2885
                ['MySpace', 'getUserDataAccessTrackingOverview'],
2886
                0
2887
            );
2888
            $table->set_header(0, get_lang('LoginDate'), true);
2889
            $table->set_header(1, get_lang('Username'), true);
2890
            if (api_is_western_name_order()) {
2891
                $table->set_header(2, get_lang('FirstName'), true);
2892
                $table->set_header(3, get_lang('LastName'), true);
2893
            } else {
2894
                $table->set_header(2, get_lang('LastName'), true);
2895
                $table->set_header(3, get_lang('FirstName'), true);
2896
            }
2897
            $table->set_header(4, get_lang('Clicks'), false);
2898
            $table->set_header(5, get_lang('IP'), false);
2899
            $table->set_header(6, get_lang('TimeLoggedIn'), false);
2900
        }
2901
2902
        $template = new Template(
2903
            null,
2904
            false,
2905
            false,
2906
            false,
2907
            false,
2908
            false,
2909
            false
2910
        );
2911
        $template->assign('form', $form->returnForm());
2912
        $template->assign('table', $table ? $table->return_table() : null);
2913
2914
        echo $template->fetch(
2915
            $template->get_template('my_space/accessoverview.tpl')
2916
        );
2917
    }
2918
2919
    /**
2920
     * @return int
2921
     */
2922
    public static function getNumberOfTrackAccessOverview()
2923
    {
2924
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
2925
        $sql = "SELECT COUNT(course_access_id) count FROM $table";
2926
        $result = Database::query($sql);
2927
        $row = Database::fetch_assoc($result);
2928
2929
        return $row['count'];
2930
    }
2931
2932
    /**
2933
     * @param $from
2934
     * @param $numberItems
2935
     * @param $column
2936
     * @param $orderDirection
2937
     *
2938
     * @return array
2939
     */
2940
    public static function getUserDataAccessTrackingOverview(
2941
        $from,
2942
        $numberItems,
2943
        $column,
2944
        $orderDirection
2945
    ) {
2946
        $from = (int) $from;
2947
        $numberItems = (int) $numberItems;
2948
        $column = (int) $column;
2949
        $orderDirection = Database::escape_string($orderDirection);
2950
        $orderDirection = !in_array(strtolower(trim($orderDirection)), ['asc', 'desc']) ? 'asc' : $orderDirection;
2951
2952
        $user = Database::get_main_table(TABLE_MAIN_USER);
2953
        $course = Database::get_main_table(TABLE_MAIN_COURSE);
2954
        $track_e_login = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
2955
        $track_e_course_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
2956
2957
        global $export_csv;
2958
        $is_western_name_order = api_is_western_name_order();
2959
        if ($export_csv) {
2960
            $is_western_name_order = api_is_western_name_order(PERSON_NAME_DATA_EXPORT);
2961
        }
2962
2963
        //TODO add course name
2964
        $sql = "SELECT
2965
                a.login_course_date as col0,
2966
                u.username as col1,
2967
                ".(
2968
                    $is_western_name_order ? "
2969
                        u.firstname AS col2,
2970
                        u.lastname AS col3,
2971
                    " : "
2972
                        u.lastname AS col2,
2973
                        u.firstname AS col3,
2974
                "
2975
        )."
2976
                a.logout_course_date,
2977
                c.title,
2978
                c.code,
2979
                u.user_id
2980
            FROM $track_e_course_access a
2981
            INNER JOIN $user u ON a.user_id = u.user_id
2982
            INNER JOIN $course c ON a.c_id = c.id
2983
            WHERE 1=1 ";
2984
2985
        if (isset($_GET['course_id']) && !empty($_GET['course_id'])) {
2986
            $courseId = (int) $_GET['course_id'];
2987
            $sql .= " AND c.id = ".$courseId;
2988
        }
2989
2990
        if (isset($_GET['session_id']) && !empty($_GET['session_id'])) {
2991
            $sessionId = (int) $_GET['session_id'];
2992
            $sql .= " AND a.session_id = ".$sessionId;
2993
        }
2994
2995
        if (isset($_GET['student_id']) && !empty($_GET['student_id'])) {
2996
            $userId = (int) $_GET['student_id'];
2997
            $sql .= " AND u.user_id = ".$userId;
2998
        }
2999
3000
        if (isset($_GET['date']) && !empty($_GET['date'])) {
3001
            $dates = DateRangePicker::parseDateRange($_GET['date']);
3002
            if (isset($dates['start']) && !empty($dates['start'])) {
3003
                $dates['start'] = Database::escape_string($dates['start']);
3004
                $sql .= " AND login_course_date >= '".$dates['start']."'";
3005
            }
3006
            if (isset($dates['end']) && !empty($dates['end'])) {
3007
                $dates['end'] = Database::escape_string($dates['end']);
3008
                $sql .= " AND logout_course_date <= '".$dates['end']."'";
3009
            }
3010
        }
3011
3012
        $sql .= " ORDER BY col$column $orderDirection ";
3013
        $sql .= " LIMIT $from,$numberItems";
3014
3015
        $result = Database::query($sql);
3016
3017
        $data = [];
3018
        while ($user = Database::fetch_assoc($result)) {
3019
            $data[] = $user;
3020
        }
3021
3022
        $return = [];
3023
        //TODO: Dont use numeric index
3024
        foreach ($data as $key => $info) {
3025
            $start_date = $info['col0'];
3026
            $end_date = $info['logout_course_date'];
3027
3028
            $return[$info['user_id']] = [
3029
                $start_date,
3030
                $info['col1'],
3031
                $info['col2'],
3032
                $info['col3'],
3033
                $info['user_id'],
3034
                'ip',
3035
                //TODO is not correct/precise, it counts the time not logged between two loggins
3036
                gmdate("H:i:s", strtotime($end_date) - strtotime($start_date)),
3037
            ];
3038
        }
3039
3040
        foreach ($return as $key => $info) {
3041
            $ipResult = Database::select(
3042
                'user_ip',
3043
                $track_e_login,
3044
                ['where' => [
3045
                    '? BETWEEN login_date AND logout_date' => $info[0],
3046
                ]],
3047
                'first'
3048
            );
3049
3050
            $return[$key][5] = $ipResult['user_ip'];
3051
        }
3052
3053
        return $return;
3054
    }
3055
3056
    /**
3057
     * Gets the connections to a course as an array of login and logout time.
3058
     *
3059
     * @param int    $user_id
3060
     * @param array  $course_info
3061
     * @param int    $sessionId
3062
     * @param string $start_date
3063
     * @param string $end_date
3064
     *
3065
     * @author  Jorge Frisancho Jibaja
3066
     * @author  Julio Montoya <[email protected]> fixing the function
3067
     *
3068
     * @version OCT-22- 2010
3069
     *
3070
     * @return array
3071
     */
3072
    public static function get_connections_to_course_by_date(
3073
        $user_id,
3074
        $course_info,
3075
        $sessionId,
3076
        $start_date,
3077
        $end_date
3078
    ) {
3079
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
3080
        $user_id = (int) $user_id;
3081
        $connections = [];
3082
        if (!empty($course_info)) {
3083
            $courseId = (int) $course_info['real_id'];
3084
            $end_date = add_day_to($end_date);
3085
3086
            $start_date = Database::escape_string($start_date);
3087
            $end_date = Database::escape_string($end_date);
3088
            $sessionCondition = api_get_session_condition($sessionId);
3089
            $sql = "SELECT
3090
                        login_course_date,
3091
                        logout_course_date,
3092
                        TIMESTAMPDIFF(SECOND, login_course_date, logout_course_date) duration
3093
                    FROM $table
3094
                    WHERE
3095
                        user_id = $user_id AND
3096
                        c_id = $courseId AND
3097
                        login_course_date BETWEEN '$start_date' AND '$end_date' AND
3098
                        logout_course_date BETWEEN '$start_date' AND '$end_date'
3099
                        $sessionCondition
3100
                    ORDER BY login_course_date ASC";
3101
            $rs = Database::query($sql);
3102
3103
            while ($row = Database::fetch_array($rs)) {
3104
                $connections[] = [
3105
                    'login' => $row['login_course_date'],
3106
                    'logout' => $row['logout_course_date'],
3107
                    'duration' => $row['duration'],
3108
                ];
3109
            }
3110
        }
3111
3112
        return $connections;
3113
    }
3114
}
3115
3116
/**
3117
 * @param $user_id
3118
 * @param array $course_info
3119
 * @param int   $sessionId
3120
 * @param null  $start_date
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $start_date is correct as it would always require null to be passed?
Loading history...
3121
 * @param null  $end_date
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $end_date is correct as it would always require null to be passed?
Loading history...
3122
 *
3123
 * @return array
3124
 */
3125
function get_stats($user_id, $course_info, $sessionId, $start_date = null, $end_date = null)
3126
{
3127
    $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
3128
    $result = [];
3129
    if (!empty($course_info)) {
3130
        $stringStartDate = '';
3131
        $stringEndDate = '';
3132
        if ($start_date != null && $end_date != null) {
3133
            $end_date = add_day_to($end_date);
3134
3135
            $start_date = Database::escape_string($start_date);
3136
            $end_date = Database::escape_string($end_date);
3137
3138
            $stringStartDate = "AND login_course_date BETWEEN '$start_date' AND '$end_date'";
3139
            $stringEndDate = "AND logout_course_date BETWEEN '$start_date' AND '$end_date'";
3140
        }
3141
        $user_id = (int) $user_id;
3142
        $courseId = (int) $course_info['real_id'];
3143
        $sessionCondition = api_get_session_condition($sessionId);
3144
        $sql = "SELECT
3145
                SEC_TO_TIME(AVG(time_to_sec(timediff(logout_course_date,login_course_date)))) as avrg,
3146
                SEC_TO_TIME(SUM(time_to_sec(timediff(logout_course_date,login_course_date)))) as total,
3147
                count(user_id) as times
3148
                FROM $table
3149
                WHERE
3150
                    user_id = $user_id AND
3151
                    c_id = $courseId $stringStartDate $stringEndDate
3152
                    $sessionCondition
3153
                ORDER BY login_course_date ASC";
3154
3155
        $rs = Database::query($sql);
3156
        if ($row = Database::fetch_array($rs)) {
3157
            $foo_avg = $row['avrg'];
3158
            $foo_total = $row['total'];
3159
            $foo_times = $row['times'];
3160
            $result = [
3161
                'avg' => $foo_avg,
3162
                'total' => $foo_total,
3163
                'times' => $foo_times,
3164
            ];
3165
        }
3166
    }
3167
3168
    return $result;
3169
}
3170
3171
function add_day_to($end_date)
3172
{
3173
    $foo_date = strtotime($end_date);
3174
    $foo_date = strtotime(' +1 day', $foo_date);
3175
    $foo_date = date('Y-m-d', $foo_date);
3176
3177
    return $foo_date;
3178
}
3179
3180
/**
3181
 * Converte an array to a table in html.
3182
 *
3183
 * @param array $result
3184
 *
3185
 * @author Jorge Frisancho Jibaja
3186
 *
3187
 * @version OCT-22- 2010
3188
 *
3189
 * @return string
3190
 */
3191
function convert_to_string($result)
3192
{
3193
    $html = '<table class="table">';
3194
    if (!empty($result)) {
3195
        foreach ($result as $key => $data) {
3196
            $html .= '<tr><td>';
3197
            $html .= api_get_local_time($data['login']);
3198
            $html .= '</td>';
3199
            $html .= '<td>';
3200
3201
            $html .= api_time_to_hms(api_strtotime($data['logout']) - api_strtotime($data['login']));
3202
            $html .= '</tr></td>';
3203
        }
3204
    }
3205
    $html .= '</table>';
3206
3207
    return $html;
3208
}
3209
3210
/**
3211
 * This function draw the graphic to be displayed on the user view as an image.
3212
 *
3213
 * @param array  $sql_result
3214
 * @param string $start_date
3215
 * @param string $end_date
3216
 * @param string $type
3217
 *
3218
 * @author Jorge Frisancho Jibaja
3219
 *
3220
 * @version OCT-22- 2010
3221
 *
3222
 * @return string
3223
 */
3224
function grapher($sql_result, $start_date, $end_date, $type = '')
3225
{
3226
    if (empty($start_date)) {
3227
        $start_date = '';
3228
    }
3229
    if (empty($end_date)) {
3230
        $end_date = '';
3231
    }
3232
    if ($type == '') {
3233
        $type = 'day';
3234
    }
3235
    $main_year = $main_month_year = $main_day = [];
3236
3237
    $period = new DatePeriod(
3238
        new DateTime($start_date),
3239
        new DateInterval('P1D'),
3240
        new DateTime($end_date)
3241
    );
3242
3243
    foreach ($period as $date) {
3244
        $main_day[$date->format('d-m-Y')] = 0;
3245
    }
3246
3247
    $period = new DatePeriod(
3248
        new DateTime($start_date),
3249
        new DateInterval('P1M'),
3250
        new DateTime($end_date)
3251
    );
3252
3253
    foreach ($period as $date) {
3254
        $main_month_year[$date->format('m-Y')] = 0;
3255
    }
3256
3257
    $i = 0;
3258
    if (is_array($sql_result) && count($sql_result) > 0) {
3259
        foreach ($sql_result as $key => $data) {
3260
            $login = api_strtotime($data['login']);
3261
            $logout = api_strtotime($data['logout']);
3262
            //creating the main array
3263
            if (isset($main_month_year[date('m-Y', $login)])) {
3264
                $main_month_year[date('m-Y', $login)] += float_format(($logout - $login) / 60, 0);
3265
            }
3266
            if (isset($main_day[date('d-m-Y', $login)])) {
3267
                $main_day[date('d-m-Y', $login)] += float_format(($logout - $login) / 60, 0);
3268
            }
3269
            if ($i > 500) {
3270
                break;
3271
            }
3272
            $i++;
3273
        }
3274
        switch ($type) {
3275
            case 'day':
3276
                $main_date = $main_day;
3277
                break;
3278
            case 'month':
3279
                $main_date = $main_month_year;
3280
                break;
3281
            case 'year':
3282
                $main_date = $main_year;
3283
                break;
3284
        }
3285
3286
        $labels = array_keys($main_date);
3287
        if (count($main_date) == 1) {
3288
            $labels = $labels[0];
3289
            $main_date = $main_date[$labels];
3290
        }
3291
3292
        /* Create and populate the pData object */
3293
        $myData = new pData();
3294
        $myData->addPoints($main_date, 'Serie1');
3295
        if (count($main_date) != 1) {
3296
            $myData->addPoints($labels, 'Labels');
3297
            $myData->setSerieDescription('Labels', 'Months');
3298
            $myData->setAbscissa('Labels');
3299
        }
3300
        $myData->setSerieWeight('Serie1', 1);
3301
        $myData->setSerieDescription('Serie1', get_lang('MyResults'));
3302
        $myData->setAxisName(0, get_lang('Minutes'));
3303
        $myData->loadPalette(api_get_path(SYS_CODE_PATH).'palettes/pchart/default.color', true);
3304
3305
        // Cache definition
3306
        $cachePath = api_get_path(SYS_ARCHIVE_PATH);
3307
        $myCache = new pCache(['CacheFolder' => substr($cachePath, 0, strlen($cachePath) - 1)]);
3308
        $chartHash = $myCache->getHash($myData);
3309
3310
        if ($myCache->isInCache($chartHash)) {
3311
            //if we already created the img
3312
            $imgPath = api_get_path(SYS_ARCHIVE_PATH).$chartHash;
3313
            $myCache->saveFromCache($chartHash, $imgPath);
3314
            $imgPath = api_get_path(WEB_ARCHIVE_PATH).$chartHash;
3315
        } else {
3316
            /* Define width, height and angle */
3317
            $mainWidth = 760;
3318
            $mainHeight = 230;
3319
            $angle = 50;
3320
3321
            /* Create the pChart object */
3322
            $myPicture = new pImage($mainWidth, $mainHeight, $myData);
3323
3324
            /* Turn of Antialiasing */
3325
            $myPicture->Antialias = false;
3326
            /* Draw the background */
3327
            $settings = ["R" => 255, "G" => 255, "B" => 255];
3328
            $myPicture->drawFilledRectangle(0, 0, $mainWidth, $mainHeight, $settings);
3329
3330
            /* Add a border to the picture */
3331
            $myPicture->drawRectangle(
3332
                0,
3333
                0,
3334
                $mainWidth - 1,
3335
                $mainHeight - 1,
3336
                ["R" => 0, "G" => 0, "B" => 0]
3337
            );
3338
3339
            /* Set the default font */
3340
            $myPicture->setFontProperties(
3341
                [
3342
                    "FontName" => api_get_path(SYS_FONTS_PATH).'opensans/OpenSans-Regular.ttf',
3343
                    "FontSize" => 10, ]
3344
            );
3345
            /* Write the chart title */
3346
            $myPicture->drawText(
3347
                $mainWidth / 2,
3348
                30,
3349
                get_lang('TimeSpentInTheCourse'),
3350
                [
3351
                    "FontSize" => 12,
3352
                    "Align" => TEXT_ALIGN_BOTTOMMIDDLE,
3353
                ]
3354
            );
3355
3356
            /* Set the default font */
3357
            $myPicture->setFontProperties(
3358
                [
3359
                    "FontName" => api_get_path(SYS_FONTS_PATH).'opensans/OpenSans-Regular.ttf',
3360
                    "FontSize" => 8,
3361
                ]
3362
            );
3363
3364
            /* Define the chart area */
3365
            $myPicture->setGraphArea(50, 40, $mainWidth - 40, $mainHeight - 80);
3366
3367
            /* Draw the scale */
3368
            $scaleSettings = [
3369
                'XMargin' => 10,
3370
                'YMargin' => 10,
3371
                'Floating' => true,
3372
                'GridR' => 200,
3373
                'GridG' => 200,
3374
                'GridB' => 200,
3375
                'DrawSubTicks' => true,
3376
                'CycleBackground' => true,
3377
                'LabelRotation' => $angle,
3378
                'Mode' => SCALE_MODE_ADDALL_START0,
3379
            ];
3380
            $myPicture->drawScale($scaleSettings);
3381
3382
            /* Turn on Antialiasing */
3383
            $myPicture->Antialias = true;
3384
3385
            /* Enable shadow computing */
3386
            $myPicture->setShadow(
3387
                true,
3388
                [
3389
                    "X" => 1,
3390
                    "Y" => 1,
3391
                    "R" => 0,
3392
                    "G" => 0,
3393
                    "B" => 0,
3394
                    "Alpha" => 10,
3395
                ]
3396
            );
3397
3398
            /* Draw the line chart */
3399
            $myPicture->setFontProperties(
3400
                [
3401
                    "FontName" => api_get_path(SYS_FONTS_PATH).'opensans/OpenSans-Regular.ttf',
3402
                    "FontSize" => 10,
3403
                ]
3404
            );
3405
            $myPicture->drawSplineChart();
3406
            $myPicture->drawPlotChart(
3407
                [
3408
                    "DisplayValues" => true,
3409
                    "PlotBorder" => true,
3410
                    "BorderSize" => 1,
3411
                    "Surrounding" => -60,
3412
                    "BorderAlpha" => 80,
3413
                ]
3414
            );
3415
3416
            /* Do NOT Write the chart legend */
3417
3418
            /* Write and save into cache */
3419
            $myCache->writeToCache($chartHash, $myPicture);
3420
            $imgPath = api_get_path(SYS_ARCHIVE_PATH).$chartHash;
3421
            $myCache->saveFromCache($chartHash, $imgPath);
3422
            $imgPath = api_get_path(WEB_ARCHIVE_PATH).$chartHash;
3423
        }
3424
        $html = '<img src="'.$imgPath.'">';
3425
3426
        return $html;
3427
    } else {
3428
        $foo_img = api_convert_encoding(
3429
            '<div id="messages" class="warning-message">'.get_lang('GraphicNotAvailable').'</div>',
3430
            'UTF-8'
3431
        );
3432
3433
        return $foo_img;
3434
    }
3435
}
3436