Passed
Push — master ( df67a3...c6e3ba )
by Julito
08:42
created

MySpace::returnCourseTracking()   B

Complexity

Conditions 6
Paths 7

Size

Total Lines 62
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 41
nc 7
nop 1
dl 0
loc 62
rs 8.6417
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
 * @package chamilo.reporting
13
 */
14
class MySpace
15
{
16
    /**
17
     * Get admin actions.
18
     *
19
     * @return string
20
     */
21
    public static function getAdminActions()
22
    {
23
        $actions = [
24
            [
25
                'url' => api_get_path(WEB_CODE_PATH).'mySpace/admin_view.php?display=coaches',
26
                'content' => get_lang('DisplayCoaches'),
27
            ],
28
            [
29
                'url' => api_get_path(WEB_CODE_PATH).'mySpace/admin_view.php?display=user',
30
                'content' => get_lang('DisplayUserOverview'),
31
            ],
32
            [
33
                'url' => api_get_path(WEB_CODE_PATH).'mySpace/admin_view.php?display=session',
34
                'content' => get_lang('DisplaySessionOverview'),
35
            ],
36
            [
37
                'url' => api_get_path(WEB_CODE_PATH).'mySpace/admin_view.php?display=course',
38
                'content' => get_lang('DisplayCourseOverview'),
39
            ],
40
            [
41
                'url' => api_get_path(WEB_CODE_PATH).'tracking/question_course_report.php?view=admin',
42
                'content' => get_lang('LPQuestionListResults'),
43
            ],
44
            [
45
                'url' => api_get_path(WEB_CODE_PATH).'tracking/course_session_report.php?view=admin',
46
                'content' => get_lang('LPExerciseResultsBySession'),
47
            ],
48
            [
49
                'url' => api_get_path(WEB_CODE_PATH).'mySpace/admin_view.php?display=accessoverview',
50
                'content' => get_lang('DisplayAccessOverview').' ('.get_lang('Beta').')',
51
            ],
52
            [
53
                'url' => api_get_path(WEB_CODE_PATH).'mySpace/exercise_category_report.php',
54
                'content' => get_lang('ExerciseCategoryAllSessionsReport'),
55
            ],
56
            [
57
                'url' => api_get_path(WEB_CODE_PATH).'mySpace/survey_report.php',
58
                'content' => get_lang('SurveyReport'),
59
            ],
60
        ];
61
62
        return Display::actions($actions, null);
63
    }
64
65
    /**
66
     * @return string
67
     */
68
    public static function getTopMenu()
69
    {
70
        $menuItems = [];
71
        $menuItems[] = Display::url(
72
            Display::return_icon(
73
                'statistics.png',
74
                get_lang('MyStats'),
75
                '',
76
                ICON_SIZE_MEDIUM
77
            ),
78
            api_get_path(WEB_CODE_PATH)."auth/my_progress.php"
79
        );
80
        $menuItems[] = Display::url(
81
            Display::return_icon(
82
                'teacher.png',
83
                get_lang('TeacherInterface'),
84
                [],
85
                32
86
            ),
87
            api_get_path(WEB_CODE_PATH).'mySpace/?view=teacher'
88
        );
89
        $menuItems[] = Display::url(
90
            Display::return_icon(
91
                'star_na.png',
92
                get_lang('AdminInterface'),
93
                [],
94
                32
95
            ),
96
            '#'
97
        );
98
        $menuItems[] = Display::url(
99
            Display::return_icon('quiz.png', get_lang('ExamTracking'), [], 32),
100
            api_get_path(WEB_CODE_PATH).'tracking/exams.php'
101
        );
102
        $menu = '';
103
        foreach ($menuItems as $item) {
104
            $menu .= $item;
105
        }
106
        $menu .= '<br />';
107
108
        return $menu;
109
    }
110
111
    /**
112
     * This function serves exporting data in CSV format.
113
     *
114
     * @param array  $header    the header labels
115
     * @param array  $data      the data array
116
     * @param string $file_name the name of the file which contains exported data
117
     *
118
     * @return string mixed             Returns a message (string) if an error occurred
119
     */
120
    public function export_csv($header, $data, $file_name = 'export.csv')
121
    {
122
        $archive_path = api_get_path(SYS_ARCHIVE_PATH);
123
        $archive_url = api_get_path(WEB_CODE_PATH).'course_info/download.php?archive_path=&archive=';
124
        $message = '';
125
        if (!$open = fopen($archive_path.$file_name, 'w+')) {
126
            $message = get_lang('noOpen');
127
        } else {
128
            $info = '';
129
130
            foreach ($header as $value) {
131
                $info .= $value.';';
132
            }
133
            $info .= "\r\n";
134
135
            foreach ($data as $row) {
136
                foreach ($row as $value) {
137
                    $info .= $value.';';
138
                }
139
                $info .= "\r\n";
140
            }
141
142
            fwrite($open, $info);
143
            fclose($open);
144
            @chmod($file_name, api_get_permissions_for_new_files());
145
146
            header("Location:".$archive_url.$file_name);
147
            exit;
148
        }
149
150
        return $message;
151
    }
152
153
    /**
154
     * Gets the connections to a course as an array of login and logout time.
155
     *
156
     * @param int   $userId     User id
157
     * @param array $courseInfo
158
     * @param int   $sessionId  Session id (optional, default = 0)
159
     *
160
     * @return array Connections
161
     */
162
    public static function get_connections_to_course(
163
        $userId,
164
        $courseInfo,
165
        $sessionId = 0
166
    ) {
167
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
168
169
        // protect data
170
        $userId = (int) $userId;
171
        $courseId = (int) $courseInfo['real_id'];
172
        $sessionId = (int) $sessionId;
173
        $sessionCondition = api_get_session_condition($sessionId);
174
175
        $sql = 'SELECT login_course_date, logout_course_date
176
                FROM '.$table.'
177
                WHERE
178
                    user_id = '.$userId.' AND
179
                    c_id = '.$courseId.' 
180
                    '.$sessionCondition.'
181
                ORDER BY login_course_date ASC';
182
        $rs = Database::query($sql);
183
        $connections = [];
184
185
        while ($row = Database::fetch_array($rs)) {
186
            $connections[] = [
187
                'login' => $row['login_course_date'],
188
                'logout' => $row['logout_course_date'],
189
            ];
190
        }
191
192
        return $connections;
193
    }
194
195
    /**
196
     * @param $user_id
197
     * @param $course_list
198
     * @param int $session_id
199
     *
200
     * @return array|bool
201
     */
202
    public static function get_connections_from_course_list(
203
        $user_id,
204
        $course_list,
205
        $session_id = 0
206
    ) {
207
        // Database table definitions
208
        $tbl_track_course = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
209
        if (empty($course_list)) {
210
            return false;
211
        }
212
213
        // protect data
214
        $user_id = (int) $user_id;
215
        $session_id = (int) $session_id;
216
        $new_course_list = [];
217
        foreach ($course_list as $course_item) {
218
            $courseInfo = api_get_course_info($course_item['code']);
219
            if ($courseInfo) {
220
                $courseId = $courseInfo['real_id'];
221
                $new_course_list[] = '"'.$courseId.'"';
222
            }
223
        }
224
        $course_list = implode(', ', $new_course_list);
225
226
        if (empty($course_list)) {
227
            return false;
228
        }
229
        $sql = 'SELECT login_course_date, logout_course_date, c_id
230
                FROM '.$tbl_track_course.'
231
                WHERE
232
                    user_id = '.$user_id.' AND
233
                    c_id IN ('.$course_list.') AND
234
                    session_id = '.$session_id.'
235
                ORDER BY login_course_date ASC';
236
        $rs = Database::query($sql);
237
        $connections = [];
238
239
        while ($row = Database::fetch_array($rs)) {
240
            $timestamp_login_date = api_strtotime($row['login_course_date'], 'UTC');
241
            $timestamp_logout_date = api_strtotime($row['logout_course_date'], 'UTC');
242
            $connections[] = [
243
                'login' => $timestamp_login_date,
244
                'logout' => $timestamp_logout_date,
245
                'c_id' => $row['c_id'],
246
            ];
247
        }
248
249
        return $connections;
250
    }
251
252
    /**
253
     * Creates a small table in the last column of the table with the user overview.
254
     *
255
     * @param int $user_id the id of the user
256
     *
257
     * @return array List course
258
     */
259
    public static function returnCourseTracking($user_id)
260
    {
261
        $user_id = (int) $user_id;
262
263
        if (empty($user_id)) {
264
            return [];
265
        }
266
267
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
268
        // getting all the courses of the user
269
        $sql = "SELECT * FROM $tbl_course_user
270
                WHERE
271
                    user_id = $user_id AND
272
                    relation_type <> ".COURSE_RELATION_TYPE_RRHH;
273
        $result = Database::query($sql);
274
275
        $list = [];
276
277
        while ($row = Database::fetch_array($result)) {
278
            $courseInfo = api_get_course_info_by_id($row['c_id']);
279
            $courseId = $courseInfo['real_id'];
280
            $courseCode = $courseInfo['code'];
281
282
            if (empty($courseInfo)) {
283
                continue;
284
            }
285
286
            $avg_score = Tracking::get_avg_student_score($user_id, $courseCode);
287
            if (is_numeric($avg_score)) {
288
                $avg_score = round($avg_score, 2);
289
            } else {
290
                $avg_score = '-';
291
            }
292
293
            // Student exercises results (obtained score, maximum score, number of exercises answered, score percentage)
294
            $exercisesResults = self::exercises_results($user_id, $courseCode);
295
296
            $resultToString = '';
297
            if (!is_null($exercisesResults['percentage'])) {
298
                $resultToString = $exercisesResults['score_obtained'].'/'.$exercisesResults['score_possible'].' ( '.$exercisesResults['percentage'].'% )';
299
            }
300
301
            $item = [
302
                'code' => $courseInfo['code'],
303
                'real_id' => $courseInfo['real_id'],
304
                'title' => $courseInfo['title'],
305
                'category' => $courseInfo['categoryName'],
306
                'image_small' => $courseInfo['course_image'],
307
                'image_large' => $courseInfo['course_image_large'],
308
                'time_spent' => api_time_to_hms(Tracking::get_time_spent_on_the_course($user_id, $courseId)),
309
                'student_progress' => round(Tracking::get_avg_student_progress($user_id, $courseCode)),
310
                'student_score' => $avg_score,
311
                'student_message' => Tracking::count_student_messages($user_id, $courseCode),
312
                'student_assignments' => Tracking::count_student_assignments($user_id, $courseCode),
313
                'student_exercises' => $resultToString,
314
                'questions_answered' => $exercisesResults['questions_answered'],
315
                'last_connection' => Tracking::get_last_connection_date_on_the_course($user_id, $courseInfo),
316
            ];
317
            $list[] = $item;
318
        }
319
320
        return $list;
321
    }
322
323
    /**
324
     * Display a sortable table that contains an overview off all the
325
     * reporting progress of all users and all courses the user is subscribed to.
326
     *
327
     * @author Patrick Cool <[email protected]>, Ghent University, Belgium
328
     *          Alex Aragon <[email protected]>, BeezNest, Perú
329
     *
330
     * @version Chamilo 1.11.8
331
     *
332
     * @since April 2019
333
     */
334
    public static function returnTrackingUserOverviewFilter($user_id)
335
    {
336
        $tpl = new Template('', false, false, false, false, false, false);
337
        $userInfo = api_get_user_info($user_id);
338
339
        $avatar = UserManager::getUserPicture($user_id, USER_IMAGE_SIZE_SMALL);
340
        $user = [
341
            'id' => $user_id,
342
            'code_user' => $userInfo['official_code'],
343
            'complete_name' => $userInfo['complete_name'],
344
            'username' => $userInfo['username'],
345
            'course' => self::returnCourseTracking($user_id),
346
            'avatar' => $avatar,
347
        ];
348
349
        $tpl->assign('item', $user);
350
        $templateName = $tpl->get_template('my_space/partials/tracking_user_overview.tpl');
351
        $content = $tpl->fetch($templateName);
352
353
        return $content;
354
    }
355
356
    /**
357
     * Display a sortable table that contains an overview off all the
358
     * reporting progress of all users and all courses the user is subscribed to.
359
     *
360
     * @author Patrick Cool <[email protected]>, Ghent University, Belgium
361
     *         Alex Aragon <[email protected]>, BeezNest, Perú
362
     *
363
     * @version Chamilo 1.11.8
364
     *
365
     * @since October 2008, Update April 2019
366
     */
367
    public static function display_tracking_user_overview()
368
    {
369
        self::display_user_overview_export_options();
370
371
        $params = ['view' => 'admin', 'display' => 'user'];
372
        $table = new SortableTable(
373
            'tracking_user_overview',
374
            ['MySpace', 'get_number_of_users_tracking_overview'],
375
            ['MySpace', 'get_user_data_tracking_overview'],
376
            0,
377
            20,
378
            'ASC',
379
            null, [
380
                'class' => 'table table-transparent',
381
            ]
382
        );
383
        $table->additional_parameters = $params;
384
385
        $table->set_column_filter(0, ['MySpace', 'returnTrackingUserOverviewFilter']);
386
        $tableContent = $table->return_table();
387
        $tpl = new Template('', false, false, false, false, false, false);
388
        $tpl->assign('table', $tableContent);
389
        $templateName = $tpl->get_template('my_space/user_summary.tpl');
390
        $tpl->display($templateName);
391
    }
392
393
    /**
394
     * @param $export_csv
395
     */
396
    public static function display_tracking_coach_overview($export_csv)
397
    {
398
        if ($export_csv) {
399
            $is_western_name_order = api_is_western_name_order(PERSON_NAME_DATA_EXPORT);
400
        } else {
401
            $is_western_name_order = api_is_western_name_order();
402
        }
403
        $sort_by_first_name = api_sort_by_first_name();
404
        $tracking_column = isset($_GET['tracking_list_coaches_column']) ? $_GET['tracking_list_coaches_column'] : ($is_western_name_order xor $sort_by_first_name) ? 1 : 0;
405
        $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';
406
        // Prepare array for column order - when impossible, use some of user names.
407
        if ($is_western_name_order) {
408
            $order = [
409
                0 => 'firstname',
410
                1 => 'lastname',
411
                2 => $sort_by_first_name ? 'firstname' : 'lastname',
412
                3 => 'login_date',
413
                4 => $sort_by_first_name ? 'firstname' : 'lastname',
414
                5 => $sort_by_first_name ? 'firstname' : 'lastname',
415
            ];
416
        } else {
417
            $order = [
418
                0 => 'lastname',
419
                1 => 'firstname',
420
                2 => $sort_by_first_name ? 'firstname' : 'lastname',
421
                3 => 'login_date',
422
                4 => $sort_by_first_name ? 'firstname' : 'lastname',
423
                5 => $sort_by_first_name ? 'firstname' : 'lastname',
424
            ];
425
        }
426
        $table = new SortableTable(
427
            'tracking_list_coaches_myspace',
428
            ['MySpace', 'count_coaches'],
429
            null,
430
            ($is_western_name_order xor $sort_by_first_name) ? 1 : 0
431
        );
432
        $parameters['view'] = 'admin';
433
        $table->set_additional_parameters($parameters);
434
        if ($is_western_name_order) {
435
            $table->set_header(0, get_lang('FirstName'), true);
436
            $table->set_header(1, get_lang('LastName'), true);
437
        } else {
438
            $table->set_header(0, get_lang('LastName'), true);
439
            $table->set_header(1, get_lang('FirstName'), true);
440
        }
441
        $table->set_header(2, get_lang('TimeSpentOnThePlatform'), false);
442
        $table->set_header(3, get_lang('LastConnexion'), false);
443
        $table->set_header(4, get_lang('NbStudents'), false);
444
        $table->set_header(5, get_lang('CountCours'), false);
445
        $table->set_header(6, get_lang('NumberOfSessions'), false);
446
        $table->set_header(7, get_lang('Sessions'), false);
447
448
        if ($is_western_name_order) {
449
            $csv_header[] = [
450
                get_lang('FirstName'),
451
                get_lang('LastName'),
452
                get_lang('TimeSpentOnThePlatform'),
453
                get_lang('LastConnexion'),
454
                get_lang('NbStudents'),
455
                get_lang('CountCours'),
456
                get_lang('NumberOfSessions'),
457
            ];
458
        } else {
459
            $csv_header[] = [
460
                get_lang('LastName'),
461
                get_lang('FirstName'),
462
                get_lang('TimeSpentOnThePlatform'),
463
                get_lang('LastConnexion'),
464
                get_lang('NbStudents'),
465
                get_lang('CountCours'),
466
                get_lang('NumberOfSessions'),
467
            ];
468
        }
469
470
        $tbl_track_login = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
471
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
472
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
473
        $tbl_sessions = Database::get_main_table(TABLE_MAIN_SESSION);
474
475
        $sqlCoachs = "SELECT DISTINCT
476
                        scu.user_id as id_coach,
477
                        u.id as user_id,
478
                        lastname,
479
                        firstname,
480
                        MAX(login_date) as login_date
481
                        FROM $tbl_user u, $tbl_session_course_user scu, $tbl_track_login
482
                        WHERE
483
                            scu.user_id = u.id AND scu.status=2 AND login_user_id=u.id
484
                        GROUP BY user_id ";
485
486
        if (api_is_multiple_url_enabled()) {
487
            $tbl_session_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
488
            $access_url_id = api_get_current_access_url_id();
489
            if ($access_url_id != -1) {
490
                $sqlCoachs = "SELECT DISTINCT
491
                                    scu.user_id as id_coach,
492
                                    u.id as user_id,
493
                                    lastname,
494
                                    firstname,
495
                                    MAX(login_date) as login_date
496
                                FROM $tbl_user u,
497
                                $tbl_session_course_user scu,
498
                                $tbl_track_login ,
499
                                $tbl_session_rel_access_url session_rel_url
500
                                WHERE
501
                                    scu.user_id = u.id AND
502
                                    scu.status = 2 AND
503
                                    login_user_id = u.id AND
504
                                    access_url_id = $access_url_id AND
505
                                    session_rel_url.session_id = scu.session_id
506
                                GROUP BY u.id";
507
            }
508
        }
509
        if (!empty($order[$tracking_column])) {
510
            $sqlCoachs .= ' ORDER BY '.$order[$tracking_column].' '.$tracking_direction;
511
        }
512
513
        $result_coaches = Database::query($sqlCoachs);
514
        $global_coaches = [];
515
        while ($coach = Database::fetch_array($result_coaches)) {
516
            $global_coaches[$coach['user_id']] = $coach;
517
        }
518
519
        $sql_session_coach = "SELECT session.id_coach, u.id as user_id, lastname, firstname, MAX(login_date) as login_date
520
                                FROM $tbl_user u , $tbl_sessions as session, $tbl_track_login
521
                                WHERE id_coach = u.id AND login_user_id = u.id
522
                                GROUP BY u.id
523
                                ORDER BY login_date $tracking_direction";
524
525
        if (api_is_multiple_url_enabled()) {
526
            $tbl_session_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
527
            $access_url_id = api_get_current_access_url_id();
528
            if ($access_url_id != -1) {
529
                $sql_session_coach = "SELECT session.id_coach, u.id as user_id, lastname, firstname, MAX(login_date) as login_date
530
					FROM $tbl_user u , $tbl_sessions as session, $tbl_track_login , $tbl_session_rel_access_url as session_rel_url
531
					WHERE
532
					    id_coach = u.id AND
533
					    login_user_id = u.id  AND
534
					    access_url_id = $access_url_id AND
535
					    session_rel_url.session_id = session.id
536
					GROUP BY  u.id
537
					ORDER BY login_date $tracking_direction";
538
            }
539
        }
540
541
        $result_sessions_coach = Database::query($sql_session_coach);
542
        //$total_no_coaches += Database::num_rows($result_sessions_coach);
543
        while ($coach = Database::fetch_array($result_sessions_coach)) {
544
            $global_coaches[$coach['user_id']] = $coach;
545
        }
546
547
        $all_datas = [];
548
        foreach ($global_coaches as $id_coach => $coaches) {
549
            $time_on_platform = api_time_to_hms(
550
                Tracking::get_time_spent_on_the_platform($coaches['user_id'])
551
            );
552
            $last_connection = Tracking::get_last_connection_date(
553
                $coaches['user_id']
554
            );
555
            $nb_students = count(
556
                Tracking::get_student_followed_by_coach($coaches['user_id'])
557
            );
558
            $nb_courses = count(
559
                Tracking::get_courses_followed_by_coach($coaches['user_id'])
560
            );
561
            $nb_sessions = count(
562
                Tracking::get_sessions_coached_by_user($coaches['user_id'])
563
            );
564
565
            $table_row = [];
566
            if ($is_western_name_order) {
567
                $table_row[] = $coaches['firstname'];
568
                $table_row[] = $coaches['lastname'];
569
            } else {
570
                $table_row[] = $coaches['lastname'];
571
                $table_row[] = $coaches['firstname'];
572
            }
573
            $table_row[] = $time_on_platform;
574
            $table_row[] = $last_connection;
575
            $table_row[] = $nb_students;
576
            $table_row[] = $nb_courses;
577
            $table_row[] = $nb_sessions;
578
            $table_row[] = '<a href="session.php?id_coach='.$coaches['user_id'].'">
579
                '.Display::return_icon('2rightarrow.png', get_lang('Details')).'
580
            </a>';
581
            $all_datas[] = $table_row;
582
583
            if ($is_western_name_order) {
584
                $csv_content[] = [
585
                    api_html_entity_decode($coaches['firstname'], ENT_QUOTES),
586
                    api_html_entity_decode($coaches['lastname'], ENT_QUOTES),
587
                    $time_on_platform,
588
                    $last_connection,
589
                    $nb_students,
590
                    $nb_courses,
591
                    $nb_sessions,
592
                ];
593
            } else {
594
                $csv_content[] = [
595
                    api_html_entity_decode($coaches['lastname'], ENT_QUOTES),
596
                    api_html_entity_decode($coaches['firstname'], ENT_QUOTES),
597
                    $time_on_platform,
598
                    $last_connection,
599
                    $nb_students,
600
                    $nb_courses,
601
                    $nb_sessions,
602
                ];
603
            }
604
        }
605
606
        if ($tracking_column != 3) {
607
            if ($tracking_direction == 'DESC') {
608
                usort($all_datas, ['MySpace', 'rsort_users']);
609
            } else {
610
                usort($all_datas, ['MySpace', 'sort_users']);
611
            }
612
        }
613
614
        if ($export_csv && $tracking_column != 3) {
615
            usort($csv_content, 'sort_users');
616
        }
617
        if ($export_csv) {
618
            $csv_content = array_merge($csv_header, $csv_content);
619
        }
620
621
        foreach ($all_datas as $row) {
622
            $table->addRow($row, 'align="right"');
623
        }
624
        $table->display();
625
    }
626
627
    /**
628
     * @return mixed
629
     */
630
    public static function count_coaches()
631
    {
632
        global $total_no_coaches;
633
634
        return $total_no_coaches;
635
    }
636
637
    public static function sort_users($a, $b)
638
    {
639
        $tracking = Session::read('tracking_column');
640
641
        return api_strcmp(
642
            trim(api_strtolower($a[$tracking])),
643
            trim(api_strtolower($b[$tracking]))
644
        );
645
    }
646
647
    public static function rsort_users($a, $b)
648
    {
649
        $tracking = Session::read('tracking_column');
650
651
        return api_strcmp(
652
            trim(api_strtolower($b[$tracking])),
653
            trim(api_strtolower($a[$tracking]))
654
        );
655
    }
656
657
    /**
658
     * Displays a form with all the additionally defined user fields of the profile
659
     * and give you the opportunity to include these in the CSV export.
660
     *
661
     * @author Patrick Cool <[email protected]>, Ghent University, Belgium
662
     *
663
     * @version 1.8.6
664
     *
665
     * @since November 2008
666
     */
667
    public static function display_user_overview_export_options()
668
    {
669
        $message = '';
670
        $defaults = [];
671
        // include the user manager and formvalidator library
672
        if (isset($_GET['export']) && $_GET['export'] == 'options') {
673
            // get all the defined extra fields
674
            $extrafields = UserManager::get_extra_fields(
675
                0,
676
                50,
677
                5,
678
                'ASC',
679
                false,
680
                1
681
            );
682
683
            // creating the form with all the defined extra fields
684
            $form = new FormValidator(
685
                'exportextrafields',
686
                'post',
687
                api_get_self()."?view=".Security::remove_XSS($_GET['view']).'&display='.Security::remove_XSS($_GET['display']).'&export='.Security::remove_XSS($_GET['export'])
688
            );
689
690
            if (is_array($extrafields) && count($extrafields) > 0) {
691
                foreach ($extrafields as $key => $extra) {
692
                    $form->addElement('checkbox', 'extra_export_field'.$extra[0], '', $extra[3]);
693
                }
694
                $form->addButtonSave(get_lang('Ok'), 'submit');
695
696
                // setting the default values for the form that contains all the extra fields
697
                $exportFields = Session::read('additional_export_fields');
698
                if (is_array($exportFields)) {
699
                    foreach ($exportFields as $key => $value) {
700
                        $defaults['extra_export_field'.$value] = 1;
701
                    }
702
                }
703
                $form->setDefaults($defaults);
704
            } else {
705
                $form->addElement('html', Display::return_message(get_lang('ThereAreNotExtrafieldsAvailable'), 'warning'));
706
            }
707
708
            if ($form->validate()) {
709
                // exporting the form values
710
                $values = $form->exportValues();
711
712
                // re-initialising the session that contains the additional fields that need to be exported
713
                Session::write('additional_export_fields', []);
714
715
                // adding the fields that are checked to the session
716
                $message = '';
717
                $additionalExportFields = [];
718
                foreach ($values as $field_ids => $value) {
719
                    if ($value == 1 && strstr($field_ids, 'extra_export_field')) {
720
                        $additionalExportFields[] = str_replace('extra_export_field', '', $field_ids);
721
                    }
722
                }
723
                Session::write('additional_export_fields', $additionalExportFields);
724
725
                // adding the fields that will be also exported to a message string
726
                $additionalExportFields = Session::read('additional_export_fields');
727
                if (is_array($additionalExportFields)) {
728
                    foreach ($additionalExportFields as $key => $extra_field_export) {
729
                        $message .= '<li>'.$extrafields[$extra_field_export][3].'</li>';
730
                    }
731
                }
732
733
                // Displaying a feedback message
734
                if (!empty($additionalExportFields)) {
735
                    echo Display::return_message(
736
                        get_lang('FollowingFieldsWillAlsoBeExported').': <br /><ul>'.$message.'</ul>',
737
                        'confirm',
738
                        false
739
                    );
740
                } else {
741
                    echo Display::return_message(
742
                        get_lang('NoAdditionalFieldsWillBeExported'),
743
                        'confirm',
744
                        false
745
                    );
746
                }
747
            } else {
748
                $form->display();
749
            }
750
        } else {
751
            $additionalExportFields = Session::read('additional_export_fields');
752
            if (!empty($additionalExportFields)) {
753
                // get all the defined extra fields
754
                $extrafields = UserManager::get_extra_fields(0, 50, 5, 'ASC');
755
756
                foreach ($additionalExportFields as $key => $extra_field_export) {
757
                    $message .= '<li>'.$extrafields[$extra_field_export][3].'</li>';
758
                }
759
760
                echo Display::return_message(
761
                    get_lang('FollowingFieldsWillAlsoBeExported').': <br /><ul>'.$message.'</ul>',
762
                    'normal',
763
                    false
764
                );
765
            }
766
        }
767
    }
768
769
    /**
770
     * Display a sortable table that contains an overview of all the reporting progress of all courses.
771
     */
772
    public static function display_tracking_course_overview()
773
    {
774
        $params = ['view' => 'admin', 'display' => 'courseoverview'];
775
        $table = new SortableTable(
776
            'tracking_session_overview',
777
            ['MySpace', 'get_total_number_courses'],
778
            ['MySpace', 'get_course_data_tracking_overview'],
779
            1,
780
            20,
781
            'ASC',
782
            null, [
783
                'class' => 'table table-transparent',
784
            ]
785
        );
786
        $table->additional_parameters = $params;
787
        $table->set_column_filter(0, ['MySpace', 'course_tracking_filter']);
788
        $tableContent = $table->return_table();
789
790
        $tpl = new Template('', false, false, false, false, false, false);
791
        $tpl->assign('table', $tableContent);
792
        $templateName = $tpl->get_template('my_space/course_summary.tpl');
793
        $tpl->display($templateName);
794
    }
795
796
    /**
797
     * Get the total number of courses.
798
     *
799
     * @return int Total number of courses
800
     */
801
    public static function get_total_number_courses()
802
    {
803
        return CourseManager::count_courses(api_get_current_access_url_id());
804
    }
805
806
    /**
807
     * Get data for the courses.
808
     *
809
     * @param int    $from        Inferior limit
810
     * @param int    $numberItems Number of items to select
811
     * @param string $column      Column to order on
812
     * @param string $direction   Order direction
813
     *
814
     * @return array Results
815
     */
816
    public static function get_course_data_tracking_overview(
817
        $from,
818
        $numberItems,
819
        $column,
820
        $direction
821
    ) {
822
        $courses = CourseManager::get_courses_list(
823
            $from,
824
            $numberItems,
825
            $column,
826
            $direction,
827
             -1,
828
            '',
829
            api_get_current_access_url_id()
830
        );
831
832
        $list = [];
833
        foreach ($courses as $course) {
834
            $list[] = [
835
                '0' => $course['code'],
836
                'col0' => $course['code'],
837
            ];
838
        }
839
840
        return $list;
841
    }
842
843
    /**
844
     * Fills in course reporting data.
845
     *
846
     * @param int course code
847
     * @param array $url_params additional url parameters
848
     * @param array $row        the row information (the other columns)
849
     *
850
     * @return string html code
851
     */
852
    public static function course_tracking_filter($course_code, $url_params, $row)
853
    {
854
        $course_code = $row[0];
855
        $courseInfo = api_get_course_info($course_code);
856
        $courseId = $courseInfo['real_id'];
857
858
        $tpl = new Template('', false, false, false, false, false, false);
859
        $data = null;
860
861
        // database table definition
862
        $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
863
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
864
865
        // getting all the courses of the user
866
        $sql = "SELECT *
867
                FROM $tbl_user AS u
868
                INNER JOIN $tbl_course_rel_user AS cu
869
                ON cu.user_id = u.user_id
870
                WHERE cu.c_id = '".$courseId."'";
871
        $result = Database::query($sql);
872
        $time_spent = 0;
873
        $progress = 0;
874
        $nb_progress_lp = 0;
875
        $score = 0;
876
        $nb_score_lp = 0;
877
        $nb_messages = 0;
878
        $nb_assignments = 0;
879
        $last_login_date = false;
880
        $total_score_obtained = 0;
881
        $total_score_possible = 0;
882
        $total_questions_answered = 0;
883
        while ($row = Database::fetch_object($result)) {
884
            // get time spent in the course and session
885
            $time_spent += Tracking::get_time_spent_on_the_course(
886
                $row->user_id,
887
                $courseInfo['real_id']
888
            );
889
            $progress_tmp = Tracking::get_avg_student_progress(
890
                $row->user_id,
891
                $course_code,
892
                [],
893
                null,
894
                true
895
            );
896
            $progress += $progress_tmp[0];
897
            $nb_progress_lp += $progress_tmp[1];
898
            $score_tmp = Tracking::get_avg_student_score(
899
                $row->user_id,
900
                $course_code,
901
                [],
902
                null,
903
                true
904
            );
905
            if (is_array($score_tmp)) {
906
                $score += $score_tmp[0];
907
                $nb_score_lp += $score_tmp[1];
908
            }
909
            $nb_messages += Tracking::count_student_messages(
910
                $row->user_id,
911
                $course_code
912
            );
913
            $nb_assignments += Tracking::count_student_assignments(
914
                $row->user_id,
915
                $course_code
916
            );
917
            $last_login_date_tmp = Tracking::get_last_connection_date_on_the_course(
918
                $row->user_id,
919
                $courseInfo,
920
                null,
921
                false
922
            );
923
            if ($last_login_date_tmp != false &&
924
                $last_login_date == false
925
            ) { // TODO: To be cleaned
926
                $last_login_date = $last_login_date_tmp;
927
            } elseif ($last_login_date_tmp != false && $last_login_date != false) {
928
                // TODO: Repeated previous condition. To be cleaned.
929
                // Find the max and assign it to first_login_date
930
                if (strtotime($last_login_date_tmp) > strtotime($last_login_date)) {
931
                    $last_login_date = $last_login_date_tmp;
932
                }
933
            }
934
935
            $exercise_results_tmp = self::exercises_results($row->user_id, $course_code);
936
            $total_score_obtained += $exercise_results_tmp['score_obtained'];
937
            $total_score_possible += $exercise_results_tmp['score_possible'];
938
            $total_questions_answered += $exercise_results_tmp['questions_answered'];
939
        }
940
        if ($nb_progress_lp > 0) {
941
            $avg_progress = round($progress / $nb_progress_lp, 2);
942
        } else {
943
            $avg_progress = 0;
944
        }
945
        if ($nb_score_lp > 0) {
946
            $avg_score = round($score / $nb_score_lp, 2);
947
        } else {
948
            $avg_score = '-';
949
        }
950
        if ($last_login_date) {
951
            $last_login_date = api_convert_and_format_date(
952
                $last_login_date,
953
                DATE_FORMAT_SHORT,
954
                date_default_timezone_get()
955
            );
956
        } else {
957
            $last_login_date = '-';
958
        }
959
        if ($total_score_possible > 0) {
960
            $total_score_percentage = round($total_score_obtained / $total_score_possible * 100, 2);
961
        } else {
962
            $total_score_percentage = 0;
963
        }
964
        if ($total_score_percentage > 0) {
965
            $total_score = $total_score_obtained.'/'.$total_score_possible.' ('.$total_score_percentage.' %)';
966
        } else {
967
            $total_score = '-';
968
        }
969
970
        $data = [
971
            'course_code' => $course_code,
972
            'id' => $courseId,
973
            'image' => $courseInfo['course_image_large'],
974
            'image_small' => $courseInfo['course_image'],
975
            'title' => $courseInfo['title'],
976
            'url' => $courseInfo['course_public_url'],
977
            'category' => $courseInfo['categoryName'],
978
            'time_spent' => api_time_to_hms($time_spent),
979
            'avg_progress' => $avg_progress,
980
            'avg_score' => $avg_score,
981
            'number_message' => $nb_messages,
982
            'number_assignments' => $nb_assignments,
983
            'total_score' => $total_score,
984
            'questions_answered' => $total_questions_answered,
985
            'last_login' => $last_login_date,
986
        ];
987
988
        $tpl->assign('data', $data);
989
        $layout = $tpl->get_template('my_space/partials/tracking_course_overview.tpl');
990
        $content = $tpl->fetch($layout);
991
992
        return $content;
993
    }
994
995
    /**
996
     * This function exports the table that we see in display_tracking_course_overview().
997
     */
998
    public static function export_tracking_course_overview()
999
    {
1000
        // database table definition
1001
        $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1002
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
1003
1004
        // the values of the sortable table
1005
        if ($_GET['tracking_course_overview_page_nr']) {
1006
            $from = $_GET['tracking_course_overview_page_nr'];
1007
        } else {
1008
            $from = 0;
1009
        }
1010
        if ($_GET['tracking_course_overview_column']) {
1011
            $orderby = $_GET['tracking_course_overview_column'];
1012
        } else {
1013
            $orderby = 0;
1014
        }
1015
1016
        if ($_GET['tracking_course_overview_direction']) {
1017
            $direction = $_GET['tracking_course_overview_direction'];
1018
        } else {
1019
            $direction = 'ASC';
1020
        }
1021
1022
        $course_data = self::get_course_data_tracking_overview(
1023
            $from,
1024
            1000,
1025
            $orderby,
1026
            $direction
1027
        );
1028
1029
        $csv_content = [];
1030
1031
        // the first line of the csv file with the column headers
1032
        $csv_row = [];
1033
        $csv_row[] = get_lang('Course');
1034
        $csv_row[] = get_lang('AvgTimeSpentInTheCourse');
1035
        $csv_row[] = get_lang('AvgStudentsProgress');
1036
        $csv_row[] = get_lang('AvgCourseScore');
1037
        $csv_row[] = get_lang('TotalNumberOfMessages');
1038
        $csv_row[] = get_lang('TotalNumberOfAssignments');
1039
        $csv_row[] = get_lang('TotalExercisesScoreObtained');
1040
        $csv_row[] = get_lang('TotalExercisesScorePossible');
1041
        $csv_row[] = get_lang('TotalExercisesAnswered');
1042
        $csv_row[] = get_lang('TotalExercisesScorePercentage');
1043
        $csv_row[] = get_lang('LatestLogin');
1044
        $csv_content[] = $csv_row;
1045
1046
        // the other lines (the data)
1047
        foreach ($course_data as $key => $course) {
1048
            $course_code = $course[0];
1049
            $courseInfo = api_get_course_info($course_code);
1050
            $course_title = $courseInfo['title'];
1051
            $courseId = $courseInfo['real_id'];
1052
1053
            $csv_row = [];
1054
            $csv_row[] = $course_title;
1055
1056
            // getting all the courses of the session
1057
            $sql = "SELECT *
1058
                    FROM $tbl_user AS u
1059
                    INNER JOIN $tbl_course_rel_user AS cu
1060
                    ON cu.user_id = u.user_id
1061
                    WHERE cu.c_id = '".$courseId."'";
1062
            $result = Database::query($sql);
1063
            $time_spent = 0;
1064
            $progress = 0;
1065
            $nb_progress_lp = 0;
1066
            $score = 0;
1067
            $nb_score_lp = 0;
1068
            $nb_messages = 0;
1069
            $nb_assignments = 0;
1070
            $last_login_date = false;
1071
            $total_score_obtained = 0;
1072
            $total_score_possible = 0;
1073
            $total_questions_answered = 0;
1074
            while ($row = Database::fetch_object($result)) {
1075
                // get time spent in the course and session
1076
                $time_spent += Tracking::get_time_spent_on_the_course(
1077
                    $row->user_id,
1078
                    $courseId
1079
                );
1080
                $progress_tmp = Tracking::get_avg_student_progress(
1081
                    $row->user_id,
1082
                    $course_code,
1083
                    [],
1084
                    null,
1085
                    true
1086
                );
1087
                $progress += $progress_tmp[0];
1088
                $nb_progress_lp += $progress_tmp[1];
1089
                $score_tmp = Tracking::get_avg_student_score(
1090
                    $row->user_id,
1091
                    $course_code,
1092
                    [],
1093
                    null,
1094
                    true
1095
                );
1096
                if (is_array($score_tmp)) {
1097
                    $score += $score_tmp[0];
1098
                    $nb_score_lp += $score_tmp[1];
1099
                }
1100
                $nb_messages += Tracking::count_student_messages(
1101
                    $row->user_id,
1102
                    $course_code
1103
                );
1104
                $nb_assignments += Tracking::count_student_assignments(
1105
                    $row->user_id,
1106
                    $course_code
1107
                );
1108
1109
                $last_login_date_tmp = Tracking::get_last_connection_date_on_the_course(
1110
                    $row->user_id,
1111
                    $courseInfo,
1112
                    null,
1113
                    false
1114
                );
1115
                if ($last_login_date_tmp != false && $last_login_date == false) {
1116
                    // TODO: To be cleaned.
1117
                    $last_login_date = $last_login_date_tmp;
1118
                } elseif ($last_login_date_tmp != false && $last_login_date == false) {
1119
                    // TODO: Repeated previous condition. To be cleaned.
1120
                    // Find the max and assign it to first_login_date
1121
                    if (strtotime($last_login_date_tmp) > strtotime($last_login_date)) {
1122
                        $last_login_date = $last_login_date_tmp;
1123
                    }
1124
                }
1125
1126
                $exercise_results_tmp = self::exercises_results($row->user_id, $course_code);
1127
                $total_score_obtained += $exercise_results_tmp['score_obtained'];
1128
                $total_score_possible += $exercise_results_tmp['score_possible'];
1129
                $total_questions_answered += $exercise_results_tmp['questions_answered'];
1130
            }
1131
            if ($nb_progress_lp > 0) {
1132
                $avg_progress = round($progress / $nb_progress_lp, 2);
1133
            } else {
1134
                $avg_progress = 0;
1135
            }
1136
            if ($nb_score_lp > 0) {
1137
                $avg_score = round($score / $nb_score_lp, 2);
1138
            } else {
1139
                $avg_score = '-';
1140
            }
1141
            if ($last_login_date) {
1142
                $last_login_date = api_convert_and_format_date(
1143
                    $last_login_date,
1144
                    DATE_FORMAT_SHORT,
1145
                    date_default_timezone_get()
1146
                );
1147
            } else {
1148
                $last_login_date = '-';
1149
            }
1150
            if ($total_score_possible > 0) {
1151
                $total_score_percentage = round($total_score_obtained / $total_score_possible * 100, 2);
1152
            } else {
1153
                $total_score_percentage = 0;
1154
            }
1155
            // time spent in the course
1156
            $csv_row[] = api_time_to_hms($time_spent);
1157
            // student progress in course
1158
            $csv_row[] = $avg_progress;
1159
            // student score
1160
            $csv_row[] = $avg_score;
1161
            // student messages
1162
            $csv_row[] = $nb_messages;
1163
            // student assignments
1164
            $csv_row[] = $nb_assignments;
1165
            // student exercises results (obtained score, maximum score, number of exercises answered, score percentage)
1166
            $csv_row[] = $total_score_obtained;
1167
            $csv_row[] = $total_score_possible;
1168
            $csv_row[] = $total_questions_answered;
1169
            $csv_row[] = $total_score_percentage;
1170
            // last connection
1171
            $csv_row[] = $last_login_date;
1172
            $csv_content[] = $csv_row;
1173
        }
1174
        Export::arrayToCsv($csv_content, 'reporting_course_overview');
1175
        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...
1176
    }
1177
1178
    /**
1179
     * Display a sortable table that contains an overview of all the reporting
1180
     * progress of all sessions and all courses the user is subscribed to.
1181
     *
1182
     * @author Guillaume Viguier <[email protected]>
1183
     */
1184
    public static function display_tracking_session_overview()
1185
    {
1186
        $head = '<table style="width: 100%;border:0;padding:0;border-collapse:collapse;table-layout: fixed">';
1187
        $head .= '<tr>';
1188
        $head .= '<th width="155px" style="border-left:0;border-bottom:0"><span>'.get_lang('Course').'</span></th>';
1189
        $head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('AvgTimeSpentInTheCourse'), 6, true).'</span></th>';
1190
        $head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('AvgStudentsProgress'), 6, true).'</span></th>';
1191
        $head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('AvgCourseScore'), 6, true).'</span></th>';
1192
        $head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('TotalNumberOfMessages'), 6, true).'</span></th>';
1193
        $head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('TotalNumberOfAssignments'), 6, true).'</span></th>';
1194
        $head .= '<th width="105px" style="border-bottom:0"><span>'.get_lang('TotalExercisesScoreObtained').'</span></th>';
1195
        $head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('TotalExercisesAnswered'), 6, true).'</span></th>';
1196
        $head .= '<th style="padding:0;border-bottom:0;border-right:0;"><span>'.get_lang('LatestLogin').'</span></th>';
1197
        $head .= '</tr></table>';
1198
1199
        $params = ['view' => 'admin', 'display' => 'sessionoverview'];
1200
        $table = new SortableTable(
1201
            'tracking_session_overview',
1202
            ['MySpace', 'get_total_number_sessions'],
1203
            ['MySpace', 'get_session_data_tracking_overview'],
1204
            1
1205
        );
1206
        $table->additional_parameters = $params;
1207
1208
        $table->set_header(0, '', false, null, ['style' => 'display: none']);
1209
        $table->set_header(
1210
            1,
1211
            get_lang('Session'),
1212
            true,
1213
            ['style' => 'font-size:8pt'],
1214
            ['style' => 'font-size:8pt']
1215
        );
1216
        $table->set_header(
1217
            2,
1218
            $head,
1219
            false,
1220
            ['style' => 'width:90%;border:0;padding:0;font-size:7.5pt;'],
1221
            ['style' => 'width:90%;padding:0;font-size:7.5pt;']
1222
        );
1223
        $table->set_column_filter(2, ['MySpace', 'session_tracking_filter']);
1224
        $table->display();
1225
    }
1226
1227
    /**
1228
     * Get the total number of sessions.
1229
     *
1230
     * @return int Total number of sessions
1231
     */
1232
    public static function get_total_number_sessions()
1233
    {
1234
        return SessionManager::count_sessions(api_get_current_access_url_id());
1235
    }
1236
1237
    /**
1238
     * Get data for the sessions.
1239
     *
1240
     * @param int    $from        Inferior limit
1241
     * @param int    $numberItems Number of items to select
1242
     * @param string $column      Column to order on
1243
     * @param string $direction   Order direction
1244
     *
1245
     * @return array Results
1246
     */
1247
    public static function get_session_data_tracking_overview(
1248
        $from,
1249
        $numberItems,
1250
        $column,
1251
        $direction
1252
    ) {
1253
        $from = (int) $from;
1254
        $numberItems = (int) $numberItems;
1255
        $direction = Database::escape_string($direction);
1256
        $columnName = 'name';
1257
        if ($column === 1) {
1258
            $columnName = 'id';
1259
        }
1260
1261
        $options = [
1262
            'order' => " $columnName $direction",
1263
            'limit' => " $from,$numberItems",
1264
        ];
1265
        $sessions = SessionManager::formatSessionsAdminForGrid($options);
1266
        $list = [];
1267
        foreach ($sessions as $session) {
1268
            $list[] = [
1269
                '0' => $session['id'],
1270
                'col0' => $session['id'],
1271
                '1' => strip_tags($session['name']),
1272
                'col1' => strip_tags($session['name']),
1273
            ];
1274
        }
1275
1276
        return $list;
1277
    }
1278
1279
    /**
1280
     * Fills in session reporting data.
1281
     *
1282
     * @param int   $session_id the id of the user
1283
     * @param array $url_params additonal url parameters
1284
     * @param array $row        the row information (the other columns)
1285
     *
1286
     * @return string html code
1287
     */
1288
    public static function session_tracking_filter($session_id, $url_params, $row)
1289
    {
1290
        $session_id = $row[0];
1291
        // the table header
1292
        $return = '<table class="data_table" style="width: 100%;border:0;padding:0;border-collapse:collapse;table-layout: fixed">';
1293
1294
        // database table definition
1295
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
1296
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
1297
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
1298
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
1299
1300
        // getting all the courses of the user
1301
        $sql = "SELECT * FROM $tbl_course AS c
1302
                INNER JOIN $tbl_session_rel_course AS sc
1303
                ON sc.c_id = c.id
1304
                WHERE sc.session_id = '".$session_id."'";
1305
        $result = Database::query($sql);
1306
        while ($row = Database::fetch_object($result)) {
1307
            $courseId = $row->c_id;
1308
            $courseInfo = api_get_course_info_by_id($courseId);
1309
            $return .= '<tr>';
1310
            // course code
1311
            $return .= '    <td width="157px" >'.$row->title.'</td>';
1312
            // get the users in the course
1313
            $sql = "SELECT u.user_id
1314
                    FROM $tbl_user AS u
1315
                    INNER JOIN $tbl_session_rel_course_rel_user AS scu
1316
                    ON u.user_id = scu.user_id
1317
                    WHERE scu.session_id = '".$session_id."' AND scu.c_id = '".$courseId."'";
1318
            $result_users = Database::query($sql);
1319
            $time_spent = 0;
1320
            $progress = 0;
1321
            $nb_progress_lp = 0;
1322
            $score = 0;
1323
            $nb_score_lp = 0;
1324
            $nb_messages = 0;
1325
            $nb_assignments = 0;
1326
            $last_login_date = false;
1327
            $total_score_obtained = 0;
1328
            $total_score_possible = 0;
1329
            $total_questions_answered = 0;
1330
            while ($row_user = Database::fetch_object($result_users)) {
1331
                // get time spent in the course and session
1332
                $time_spent += Tracking::get_time_spent_on_the_course($row_user->user_id, $courseId, $session_id);
1333
                $progress_tmp = Tracking::get_avg_student_progress($row_user->user_id, $row->code, [], $session_id, true);
1334
                $progress += $progress_tmp[0];
1335
                $nb_progress_lp += $progress_tmp[1];
1336
                $score_tmp = Tracking::get_avg_student_score($row_user->user_id, $row->code, [], $session_id, true);
1337
                if (is_array($score_tmp)) {
1338
                    $score += $score_tmp[0];
1339
                    $nb_score_lp += $score_tmp[1];
1340
                }
1341
                $nb_messages += Tracking::count_student_messages($row_user->user_id, $row->code, $session_id);
1342
                $nb_assignments += Tracking::count_student_assignments($row_user->user_id, $row->code, $session_id);
1343
                $last_login_date_tmp = Tracking::get_last_connection_date_on_the_course(
1344
                    $row_user->user_id,
1345
                    $courseInfo,
1346
                    $session_id,
1347
                    false
1348
                );
1349
                if ($last_login_date_tmp != false && $last_login_date == false) {
1350
                    // TODO: To be cleaned.
1351
                    $last_login_date = $last_login_date_tmp;
1352
                } elseif ($last_login_date_tmp != false && $last_login_date != false) {
1353
                    // TODO: Repeated previous condition! To be cleaned.
1354
                    // Find the max and assign it to first_login_date
1355
                    if (strtotime($last_login_date_tmp) > strtotime($last_login_date)) {
1356
                        $last_login_date = $last_login_date_tmp;
1357
                    }
1358
                }
1359
1360
                $exercise_results_tmp = self::exercises_results($row_user->user_id, $row->code, $session_id);
1361
                $total_score_obtained += $exercise_results_tmp['score_obtained'];
1362
                $total_score_possible += $exercise_results_tmp['score_possible'];
1363
                $total_questions_answered += $exercise_results_tmp['questions_answered'];
1364
            }
1365
            if ($nb_progress_lp > 0) {
1366
                $avg_progress = round($progress / $nb_progress_lp, 2);
1367
            } else {
1368
                $avg_progress = 0;
1369
            }
1370
            if ($nb_score_lp > 0) {
1371
                $avg_score = round($score / $nb_score_lp, 2);
1372
            } else {
1373
                $avg_score = '-';
1374
            }
1375
            if ($last_login_date) {
1376
                $last_login_date = api_convert_and_format_date(
1377
                    $last_login_date,
1378
                    DATE_FORMAT_SHORT,
1379
                    date_default_timezone_get()
1380
                );
1381
            } else {
1382
                $last_login_date = '-';
1383
            }
1384
            if ($total_score_possible > 0) {
1385
                $total_score_percentage = round($total_score_obtained / $total_score_possible * 100, 2);
1386
            } else {
1387
                $total_score_percentage = 0;
1388
            }
1389
            if ($total_score_percentage > 0) {
1390
                $total_score = $total_score_obtained.'/'.$total_score_possible.' ('.$total_score_percentage.' %)';
1391
            } else {
1392
                $total_score = '-';
1393
            }
1394
            // time spent in the course
1395
            $return .= '    <td><div>'.api_time_to_hms($time_spent).'</div></td>';
1396
            // student progress in course
1397
            $return .= '    <td><div>'.$avg_progress.'</div></td>';
1398
            // student score
1399
            $return .= '    <td><div>'.$avg_score.'</div></td>';
1400
            // student messages
1401
            $return .= '    <td><div>'.$nb_messages.'</div></td>';
1402
            // student assignments
1403
            $return .= '    <td><div>'.$nb_assignments.'</div></td>';
1404
            // student exercises results (obtained score, maximum score, number of exercises answered, score percentage)
1405
            $return .= '<td width="105px;">'.$total_score.'</td>';
1406
            $return .= '<td>'.$total_questions_answered.'</td>';
1407
            // last connection
1408
            $return .= '    <td><div>'.$last_login_date.'</div></td>';
1409
            $return .= '<tr>';
1410
        }
1411
        $return .= '</table>';
1412
1413
        return $return;
1414
    }
1415
1416
    /**
1417
     * This function exports the table that we see in display_tracking_session_overview().
1418
     */
1419
    public static function export_tracking_session_overview()
1420
    {
1421
        // database table definition
1422
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
1423
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
1424
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
1425
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
1426
1427
        // the values of the sortable table
1428
        $from = 0;
1429
        if ($_GET['tracking_session_overview_page_nr']) {
1430
            $from = $_GET['tracking_session_overview_page_nr'];
1431
        }
1432
1433
        $orderby = 0;
1434
        if ($_GET['tracking_session_overview_column']) {
1435
            $orderby = $_GET['tracking_session_overview_column'];
1436
        }
1437
1438
        $direction = 'ASC';
1439
        if ($_GET['tracking_session_overview_direction']) {
1440
            $direction = $_GET['tracking_session_overview_direction'];
1441
        }
1442
1443
        $session_data = self::get_session_data_tracking_overview($from, 1000, $orderby, $direction);
1444
1445
        $csv_content = [];
1446
1447
        // the first line of the csv file with the column headers
1448
        $csv_row = [];
1449
        $csv_row[] = get_lang('Session');
1450
        $csv_row[] = get_lang('Course');
1451
        $csv_row[] = get_lang('AvgTimeSpentInTheCourse');
1452
        $csv_row[] = get_lang('AvgStudentsProgress');
1453
        $csv_row[] = get_lang('AvgCourseScore');
1454
        $csv_row[] = get_lang('TotalNumberOfMessages');
1455
        $csv_row[] = get_lang('TotalNumberOfAssignments');
1456
        $csv_row[] = get_lang('TotalExercisesScoreObtained');
1457
        $csv_row[] = get_lang('TotalExercisesScorePossible');
1458
        $csv_row[] = get_lang('TotalExercisesAnswered');
1459
        $csv_row[] = get_lang('TotalExercisesScorePercentage');
1460
        $csv_row[] = get_lang('LatestLogin');
1461
        $csv_content[] = $csv_row;
1462
1463
        // the other lines (the data)
1464
        foreach ($session_data as $key => $session) {
1465
            $session_id = $session[0];
1466
            $session_title = $session[1];
1467
1468
            // getting all the courses of the session
1469
            $sql = "SELECT * FROM $tbl_course AS c
1470
                    INNER JOIN $tbl_session_rel_course AS sc
1471
                    ON sc.c_id = c.id
1472
                    WHERE sc.session_id = '".$session_id."';";
1473
            $result = Database::query($sql);
1474
            while ($row = Database::fetch_object($result)) {
1475
                $courseId = $row->c_id;
1476
                $courseInfo = api_get_course_info_by_id($courseId);
1477
                $csv_row = [];
1478
                $csv_row[] = $session_title;
1479
                $csv_row[] = $row->title;
1480
                // get the users in the course
1481
                $sql = "SELECT scu.user_id
1482
                        FROM $tbl_user AS u
1483
                        INNER JOIN $tbl_session_rel_course_rel_user AS scu
1484
                        ON u.user_id = scu.user_id
1485
                        WHERE scu.session_id = '".$session_id."' AND scu.c_id = '".$courseId."'";
1486
                $result_users = Database::query($sql);
1487
                $time_spent = 0;
1488
                $progress = 0;
1489
                $nb_progress_lp = 0;
1490
                $score = 0;
1491
                $nb_score_lp = 0;
1492
                $nb_messages = 0;
1493
                $nb_assignments = 0;
1494
                $last_login_date = false;
1495
                $total_score_obtained = 0;
1496
                $total_score_possible = 0;
1497
                $total_questions_answered = 0;
1498
                while ($row_user = Database::fetch_object($result_users)) {
1499
                    // get time spent in the course and session
1500
                    $time_spent += Tracking::get_time_spent_on_the_course($row_user->user_id, $courseId, $session_id);
1501
                    $progress_tmp = Tracking::get_avg_student_progress(
1502
                        $row_user->user_id,
1503
                        $row->code,
1504
                        [],
1505
                        $session_id,
1506
                        true
1507
                    );
1508
                    $progress += $progress_tmp[0];
1509
                    $nb_progress_lp += $progress_tmp[1];
1510
                    $score_tmp = Tracking::get_avg_student_score(
1511
                        $row_user->user_id,
1512
                        $row->code,
1513
                        [],
1514
                        $session_id,
1515
                        true
1516
                    );
1517
                    if (is_array($score_tmp)) {
1518
                        $score += $score_tmp[0];
1519
                        $nb_score_lp += $score_tmp[1];
1520
                    }
1521
                    $nb_messages += Tracking::count_student_messages(
1522
                        $row_user->user_id,
1523
                        $row->code,
1524
                        $session_id
1525
                    );
1526
1527
                    $nb_assignments += Tracking::count_student_assignments(
1528
                        $row_user->user_id,
1529
                        $row->code,
1530
                        $session_id
1531
                    );
1532
1533
                    $last_login_date_tmp = Tracking:: get_last_connection_date_on_the_course(
1534
                        $row_user->user_id,
1535
                        $courseInfo,
1536
                        $session_id,
1537
                        false
1538
                    );
1539
                    if ($last_login_date_tmp != false && $last_login_date == false) {
1540
                        // TODO: To be cleaned.
1541
                        $last_login_date = $last_login_date_tmp;
1542
                    } elseif ($last_login_date_tmp != false && $last_login_date == false) {
1543
                        // TODO: Repeated previous condition. To be cleaned.
1544
                        // Find the max and assign it to first_login_date
1545
                        if (strtotime($last_login_date_tmp) > strtotime($last_login_date)) {
1546
                            $last_login_date = $last_login_date_tmp;
1547
                        }
1548
                    }
1549
1550
                    $exercise_results_tmp = self::exercises_results($row_user->user_id, $row->code, $session_id);
1551
                    $total_score_obtained += $exercise_results_tmp['score_obtained'];
1552
                    $total_score_possible += $exercise_results_tmp['score_possible'];
1553
                    $total_questions_answered += $exercise_results_tmp['questions_answered'];
1554
                }
1555
                if ($nb_progress_lp > 0) {
1556
                    $avg_progress = round($progress / $nb_progress_lp, 2);
1557
                } else {
1558
                    $avg_progress = 0;
1559
                }
1560
                if ($nb_score_lp > 0) {
1561
                    $avg_score = round($score / $nb_score_lp, 2);
1562
                } else {
1563
                    $avg_score = '-';
1564
                }
1565
                if ($last_login_date) {
1566
                    $last_login_date = api_convert_and_format_date(
1567
                        $last_login_date,
1568
                        DATE_FORMAT_SHORT,
1569
                        date_default_timezone_get()
1570
                    );
1571
                } else {
1572
                    $last_login_date = '-';
1573
                }
1574
                if ($total_score_possible > 0) {
1575
                    $total_score_percentage = round($total_score_obtained / $total_score_possible * 100, 2);
1576
                } else {
1577
                    $total_score_percentage = 0;
1578
                }
1579
                if ($total_score_percentage > 0) {
1580
                    $total_score = $total_score_obtained.'/'.$total_score_possible.' ('.$total_score_percentage.' %)';
1581
                } else {
1582
                    $total_score = '-';
1583
                }
1584
                // time spent in the course
1585
                $csv_row[] = api_time_to_hms($time_spent);
1586
                // student progress in course
1587
                $csv_row[] = $avg_progress;
1588
                // student score
1589
                $csv_row[] = $avg_score;
1590
                // student messages
1591
                $csv_row[] = $nb_messages;
1592
                // student assignments
1593
                $csv_row[] = $nb_assignments;
1594
                // student exercises results (obtained score, maximum score, number of exercises answered, score percentage)
1595
                $csv_row[] = $total_score_obtained;
1596
                $csv_row[] = $total_score_possible;
1597
                $csv_row[] = $total_questions_answered;
1598
                $csv_row[] = $total_score_percentage;
1599
                // last connection
1600
                $csv_row[] = $last_login_date;
1601
                $csv_content[] = $csv_row;
1602
            }
1603
        }
1604
        Export::arrayToCsv($csv_content, 'reporting_session_overview');
1605
        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...
1606
    }
1607
1608
    /**
1609
     * Get general information about the exercise performance of the user
1610
     * the total obtained score (all the score on all the questions)
1611
     * the maximum score that could be obtained
1612
     * the number of questions answered
1613
     * the success percentage.
1614
     *
1615
     * @param int    $user_id     the id of the user
1616
     * @param string $course_code the course code
1617
     * @param int    $session_id
1618
     *
1619
     * @return array
1620
     *
1621
     * @author Patrick Cool <[email protected]>, Ghent University, Belgium
1622
     *
1623
     * @version Dokeos 1.8.6
1624
     *
1625
     * @since November 2008
1626
     */
1627
    public static function exercises_results($user_id, $course_code, $session_id = 0)
1628
    {
1629
        $user_id = (int) $user_id;
1630
        $courseId = api_get_course_int_id($course_code);
1631
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
1632
1633
        $sql = "SELECT score, max_score
1634
                FROM $table
1635
                WHERE 
1636
                    c_id = $courseId AND 
1637
                    exe_user_id = $user_id";
1638
1639
        $session_id = (int) $session_id;
1640
        if (!empty($session_id)) {
1641
            $sql .= " AND session_id = '".$session_id."' ";
1642
        }
1643
        $result = Database::query($sql);
1644
        $score_obtained = 0;
1645
        $score_possible = 0;
1646
        $questions_answered = 0;
1647
        while ($row = Database::fetch_array($result)) {
1648
            $score_obtained += $row['score'];
1649
            $score_possible += $row['max_score'];
1650
            $questions_answered++;
1651
        }
1652
1653
        $percentage = null;
1654
        if ($score_possible != 0) {
1655
            $percentage = round(($score_obtained / $score_possible * 100), 2);
1656
        }
1657
1658
        return [
1659
            'score_obtained' => $score_obtained,
1660
            'score_possible' => $score_possible,
1661
            'questions_answered' => $questions_answered,
1662
            'percentage' => $percentage,
1663
        ];
1664
    }
1665
1666
    /**
1667
     * This function exports the table that we see in display_tracking_user_overview().
1668
     *
1669
     * @author Patrick Cool <[email protected]>, Ghent University, Belgium
1670
     *
1671
     * @version Dokeos 1.8.6
1672
     *
1673
     * @since October 2008
1674
     */
1675
    public static function export_tracking_user_overview()
1676
    {
1677
        // database table definitions
1678
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1679
        $is_western_name_order = api_is_western_name_order(PERSON_NAME_DATA_EXPORT);
1680
1681
        // the values of the sortable table
1682
        if ($_GET['tracking_user_overview_page_nr']) {
1683
            $from = $_GET['tracking_user_overview_page_nr'];
1684
        } else {
1685
            $from = 0;
1686
        }
1687
        if ($_GET['tracking_user_overview_column']) {
1688
            $orderby = $_GET['tracking_user_overview_column'];
1689
        } else {
1690
            $orderby = 0;
1691
        }
1692
        if ($is_western_name_order != api_is_western_name_order() && ($orderby == 1 || $orderby == 2)) {
1693
            // Swapping the sorting column if name order for export is different than the common name order.
1694
            $orderby = 3 - $orderby;
1695
        }
1696
        if ($_GET['tracking_user_overview_direction']) {
1697
            $direction = $_GET['tracking_user_overview_direction'];
1698
        } else {
1699
            $direction = 'ASC';
1700
        }
1701
1702
        $user_data = self::get_user_data_tracking_overview(
1703
            $from,
1704
            1000,
1705
            $orderby,
1706
            $direction
1707
        );
1708
1709
        // the first line of the csv file with the column headers
1710
        $csv_row = [];
1711
        $csv_row[] = get_lang('OfficialCode');
1712
        if ($is_western_name_order) {
1713
            $csv_row[] = get_lang('FirstName');
1714
            $csv_row[] = get_lang('LastName');
1715
        } else {
1716
            $csv_row[] = get_lang('LastName');
1717
            $csv_row[] = get_lang('FirstName');
1718
        }
1719
        $csv_row[] = get_lang('LoginName');
1720
        $csv_row[] = get_lang('CourseCode');
1721
1722
        // the additional user defined fields (only those that were selected to be exported)
1723
        $fields = UserManager::get_extra_fields(0, 50, 5, 'ASC');
1724
1725
        $additionalExportFields = Session::read('additional_export_fields');
1726
1727
        if (is_array($additionalExportFields)) {
1728
            foreach ($additionalExportFields as $key => $extra_field_export) {
1729
                $csv_row[] = $fields[$extra_field_export][3];
1730
                $field_names_to_be_exported[] = 'extra_'.$fields[$extra_field_export][1];
1731
            }
1732
        }
1733
        $csv_row[] = get_lang('AvgTimeSpentInTheCourse', '');
1734
        $csv_row[] = get_lang('AvgStudentsProgress', '');
1735
        $csv_row[] = get_lang('AvgCourseScore', '');
1736
        $csv_row[] = get_lang('AvgExercisesScore', '');
1737
        $csv_row[] = get_lang('AvgMessages', '');
1738
        $csv_row[] = get_lang('AvgAssignments', '');
1739
        $csv_row[] = get_lang('TotalExercisesScoreObtained', '');
1740
        $csv_row[] = get_lang('TotalExercisesScorePossible', '');
1741
        $csv_row[] = get_lang('TotalExercisesAnswered', '');
1742
        $csv_row[] = get_lang('TotalExercisesScorePercentage', '');
1743
        $csv_row[] = get_lang('FirstLogin', '');
1744
        $csv_row[] = get_lang('LatestLogin', '');
1745
        $csv_content[] = $csv_row;
1746
1747
        // the other lines (the data)
1748
        foreach ($user_data as $key => $user) {
1749
            // getting all the courses of the user
1750
            $sql = "SELECT * FROM $tbl_course_user
1751
                    WHERE user_id = '".intval($user[4])."' AND relation_type<>".COURSE_RELATION_TYPE_RRHH." ";
1752
            $result = Database::query($sql);
1753
            while ($row = Database::fetch_row($result)) {
1754
                $courseInfo = api_get_course_info($row['course_code']);
1755
                $courseId = $courseInfo['real_id'];
1756
1757
                $csv_row = [];
1758
                // user official code
1759
                $csv_row[] = $user[0];
1760
                // user first|last name
1761
                $csv_row[] = $user[1];
1762
                // user last|first name
1763
                $csv_row[] = $user[2];
1764
                // user login name
1765
                $csv_row[] = $user[3];
1766
                // course code
1767
                $csv_row[] = $row[0];
1768
                // the additional defined user fields
1769
                $extra_fields = self::get_user_overview_export_extra_fields($user[4]);
1770
1771
                if (is_array($field_names_to_be_exported)) {
1772
                    foreach ($field_names_to_be_exported as $key => $extra_field_export) {
1773
                        $csv_row[] = $extra_fields[$extra_field_export];
1774
                    }
1775
                }
1776
                // time spent in the course
1777
                $csv_row[] = api_time_to_hms(Tracking::get_time_spent_on_the_course($user[4], $courseId));
1778
                // student progress in course
1779
                $csv_row[] = round(Tracking::get_avg_student_progress($user[4], $row[0]), 2);
1780
                // student score
1781
                $csv_row[] = round(Tracking::get_avg_student_score($user[4], $row[0]), 2);
1782
                // student tes score
1783
                $csv_row[] = round(Tracking::get_avg_student_exercise_score($user[4], $row[0]), 2);
1784
                // student messages
1785
                $csv_row[] = Tracking::count_student_messages($user[4], $row[0]);
1786
                // student assignments
1787
                $csv_row[] = Tracking::count_student_assignments($user[4], $row[0]);
1788
                // student exercises results
1789
                $exercises_results = self::exercises_results($user[4], $row[0]);
1790
                $csv_row[] = $exercises_results['score_obtained'];
1791
                $csv_row[] = $exercises_results['score_possible'];
1792
                $csv_row[] = $exercises_results['questions_answered'];
1793
                $csv_row[] = $exercises_results['percentage'];
1794
                // first connection
1795
                $csv_row[] = Tracking::get_first_connection_date_on_the_course($user[4], $courseId);
1796
                // last connection
1797
                $csv_row[] = strip_tags(Tracking::get_last_connection_date_on_the_course($user[4], $courseInfo));
1798
1799
                $csv_content[] = $csv_row;
1800
            }
1801
        }
1802
        Export::arrayToCsv($csv_content, 'reporting_user_overview');
1803
        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...
1804
    }
1805
1806
    /**
1807
     * Get data for courses list in sortable with pagination.
1808
     *
1809
     * @return array
1810
     */
1811
    public static function get_course_data($from, $number_of_items, $column, $direction)
1812
    {
1813
        global $courses, $csv_content, $charset, $session_id;
1814
1815
        // definition database tables
1816
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
1817
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1818
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
1819
1820
        $course_data = [];
1821
        $courses_code = array_keys($courses);
1822
1823
        foreach ($courses_code as &$code) {
1824
            $code = "'$code'";
1825
        }
1826
1827
        // get all courses with limit
1828
        $sql = "SELECT course.code as col1, course.title as col2
1829
                FROM $tbl_course course
1830
                WHERE course.code IN (".implode(',', $courses_code).")";
1831
1832
        if (!in_array($direction, ['ASC', 'DESC'])) {
1833
            $direction = 'ASC';
1834
        }
1835
1836
        $column = intval($column);
1837
        $from = intval($from);
1838
        $number_of_items = intval($number_of_items);
1839
        $sql .= " ORDER BY col$column $direction ";
1840
        $sql .= " LIMIT $from,$number_of_items";
1841
1842
        $res = Database::query($sql);
1843
        while ($row_course = Database::fetch_row($res)) {
1844
            $course_code = $row_course[0];
1845
            $courseInfo = api_get_course_info($course_code);
1846
            $courseId = $courseInfo['real_id'];
1847
            $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;
1848
1849
            // students directly subscribed to the course
1850
            if (empty($session_id)) {
1851
                $sql = "SELECT user_id
1852
                        FROM $tbl_course_user as course_rel_user
1853
                        WHERE
1854
                            course_rel_user.status='5' AND
1855
                            course_rel_user.c_id = '$courseId'";
1856
            } else {
1857
                $sql = "SELECT user_id FROM $tbl_session_course_user srcu
1858
                        WHERE
1859
                            c_id = '$courseId' AND
1860
                            session_id = '$session_id' AND
1861
                            status<>2";
1862
            }
1863
            $rs = Database::query($sql);
1864
            $users = [];
1865
            while ($row = Database::fetch_array($rs)) {
1866
                $users[] = $row['user_id'];
1867
            }
1868
1869
            if (count($users) > 0) {
1870
                $nb_students_in_course = count($users);
1871
                $avg_assignments_in_course = Tracking::count_student_assignments($users, $course_code, $session_id);
1872
                $avg_messages_in_course = Tracking::count_student_messages($users, $course_code, $session_id);
1873
                $avg_progress_in_course = Tracking::get_avg_student_progress($users, $course_code, [], $session_id);
1874
                $avg_score_in_course = Tracking::get_avg_student_score($users, $course_code, [], $session_id);
1875
                $avg_score_in_exercise = Tracking::get_avg_student_exercise_score($users, $course_code, 0, $session_id);
1876
                $avg_time_spent_in_course = Tracking::get_time_spent_on_the_course(
1877
                    $users,
1878
                    $courseInfo['real_id'],
1879
                    $session_id
1880
                );
1881
1882
                $avg_progress_in_course = round($avg_progress_in_course / $nb_students_in_course, 2);
1883
                if (is_numeric($avg_score_in_course)) {
1884
                    $avg_score_in_course = round($avg_score_in_course / $nb_students_in_course, 2);
1885
                }
1886
                $avg_time_spent_in_course = api_time_to_hms($avg_time_spent_in_course / $nb_students_in_course);
1887
            } else {
1888
                $avg_time_spent_in_course = null;
1889
                $avg_progress_in_course = null;
1890
                $avg_score_in_course = null;
1891
                $avg_score_in_exercise = null;
1892
                $avg_messages_in_course = null;
1893
                $avg_assignments_in_course = null;
1894
            }
1895
            $table_row = [];
1896
            $table_row[] = $row_course[1];
1897
            $table_row[] = $nb_students_in_course;
1898
            $table_row[] = $avg_time_spent_in_course;
1899
            $table_row[] = is_null($avg_progress_in_course) ? '' : $avg_progress_in_course.'%';
1900
            $table_row[] = is_null($avg_score_in_course) ? '' : $avg_score_in_course.'%';
1901
            $table_row[] = is_null($avg_score_in_exercise) ? '' : $avg_score_in_exercise.'%';
1902
            $table_row[] = $avg_messages_in_course;
1903
            $table_row[] = $avg_assignments_in_course;
1904
1905
            //set the "from" value to know if I access the Reporting by the chamilo tab or the course link
1906
            $table_row[] = '<center><a href="../../tracking/courseLog.php?cidReq='.$course_code.'&from=myspace&id_session='.$session_id.'">
1907
                             '.Display::return_icon('2rightarrow.png', get_lang('Details')).'
1908
                             </a>
1909
                            </center>';
1910
            $csv_content[] = [
1911
                api_html_entity_decode($row_course[1], ENT_QUOTES, $charset),
1912
                $nb_students_in_course,
1913
                $avg_time_spent_in_course,
1914
                is_null($avg_progress_in_course) ? null : $avg_progress_in_course.'%',
1915
                is_null($avg_score_in_course) ? null : is_numeric($avg_score_in_course) ? $avg_score_in_course.'%' : $avg_score_in_course,
1916
                is_null($avg_score_in_exercise) ? null : $avg_score_in_exercise.'%',
1917
                $avg_messages_in_course,
1918
                $avg_assignments_in_course,
1919
            ];
1920
            $course_data[] = $table_row;
1921
        }
1922
1923
        return $course_data;
1924
    }
1925
1926
    /**
1927
     * Get the number of users of the platform.
1928
     *
1929
     * @return int
1930
     */
1931
    public static function get_number_of_users_tracking_overview()
1932
    {
1933
        return UserManager::get_number_of_users(0, api_get_current_access_url_id());
1934
    }
1935
1936
    /**
1937
     * Get all the data for the sortable table of the reporting progress of
1938
     * all users and all the courses the user is subscribed to.
1939
     *
1940
     * @param int    $from
1941
     * @param int    $numberItems
1942
     * @param int    $column
1943
     * @param string $direction
1944
     *
1945
     * @return array
1946
     */
1947
    public static function get_user_data_tracking_overview($from, $numberItems, $column, $direction)
1948
    {
1949
        $isWestern = api_is_western_name_order();
1950
1951
        switch ($column) {
1952
            case '0':
1953
                $column = $isWestern ? 'firstname' : 'lastname';
1954
                break;
1955
        }
1956
1957
        $order = [
1958
            "$column $direction",
1959
        ];
1960
        $userList = UserManager::get_user_list([], $order, $from, $numberItems);
1961
        $return = [];
1962
        foreach ($userList as $user) {
1963
            $return[] = [
1964
                '0' => $user['user_id'],
1965
                'col0' => $user['user_id'],
1966
            ];
1967
        }
1968
1969
        return $return;
1970
    }
1971
1972
    /**
1973
     * Get all information that the user with user_id = $user_data has
1974
     * entered in the additionally defined profile fields.
1975
     *
1976
     * @param int $user_id the id of the user
1977
     *
1978
     * @return array
1979
     *
1980
     * @author Patrick Cool <[email protected]>, Ghent University, Belgium
1981
     *
1982
     * @version Dokeos 1.8.6
1983
     *
1984
     * @since November 2008
1985
     */
1986
    public static function get_user_overview_export_extra_fields($user_id)
1987
    {
1988
        // include the user manager
1989
        $data = UserManager::get_extra_user_data($user_id, true);
1990
1991
        return $data;
1992
    }
1993
1994
    /**
1995
     * Checks if a username exist in the DB otherwise it create a "double"
1996
     * i.e. if we look into for jmontoya but the user's name already exist we create the user jmontoya2
1997
     * the return array will be array(username=>'jmontoya', sufix='2').
1998
     *
1999
     * @param string firstname
2000
     * @param string lastname
2001
     * @param string username
2002
     *
2003
     * @return array with the username, the sufix
2004
     *
2005
     * @author Julio Montoya
2006
     */
2007
    public static function make_username($firstname, $lastname, $username, $language = null, $encoding = null)
2008
    {
2009
        // if username exist
2010
        if (!UserManager::is_username_available($username) || empty($username)) {
2011
            $i = 0;
2012
            while (1) {
2013
                if ($i == 0) {
2014
                    $sufix = '';
2015
                } else {
2016
                    $sufix = $i;
2017
                }
2018
                $desired_username = UserManager::create_username(
2019
                    $firstname,
2020
                    $lastname
2021
                );
2022
                if (UserManager::is_username_available($desired_username.$sufix)) {
2023
                    break;
2024
                } else {
2025
                    $i++;
2026
                }
2027
            }
2028
            $username_array = ['username' => $desired_username, 'sufix' => $sufix];
2029
2030
            return $username_array;
2031
        } else {
2032
            $username_array = ['username' => $username, 'sufix' => ''];
2033
2034
            return $username_array;
2035
        }
2036
    }
2037
2038
    /**
2039
     * Checks if there are repeted users in a given array.
2040
     *
2041
     * @param array $usernames  list of the usernames in the uploaded file
2042
     * @param array $user_array $user_array['username'] and $user_array['sufix']
2043
     *                          where suffix is the number part in a login i.e -> jmontoya2
2044
     *
2045
     * @return array with the $usernames array and the $user_array array
2046
     *
2047
     * @author Julio Montoya
2048
     */
2049
    public static function check_user_in_array($usernames, $user_array)
2050
    {
2051
        $user_list = array_keys($usernames);
2052
        $username = $user_array['username'].$user_array['sufix'];
2053
2054
        if (in_array($username, $user_list)) {
2055
            $user_array['sufix'] += $usernames[$username];
2056
            $usernames[$username]++;
2057
        } else {
2058
            $usernames[$username] = 1;
2059
        }
2060
        $result_array = [$usernames, $user_array];
2061
2062
        return $result_array;
2063
    }
2064
2065
    /**
2066
     * Checks whether a username has been already subscribed in a session.
2067
     *
2068
     * @param string $username    a given username
2069
     * @param array  $course_list the array with the course list id
2070
     * @param int    $id_session  the session id
2071
     *
2072
     * @return int 0 if the user is not subscribed otherwise it returns the user_id of the given username
2073
     *
2074
     * @author Julio Montoya
2075
     */
2076
    public static function user_available_in_session($username, $course_list, $id_session)
2077
    {
2078
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
2079
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2080
        $id_session = (int) $id_session;
2081
        $username = Database::escape_string($username);
2082
        foreach ($course_list as $courseId) {
2083
            $courseId = (int) $courseId;
2084
            $sql = " SELECT u.user_id FROM $tbl_session_rel_course_rel_user rel
2085
                     INNER JOIN $table_user u
2086
                     ON (rel.user_id = u.user_id)
2087
                     WHERE
2088
                        rel.session_id='$id_session' AND
2089
                        u.status='5' AND
2090
                        u.username ='$username' AND
2091
                        rel.c_id='$courseId'";
2092
            $rs = Database::query($sql);
2093
            if (Database::num_rows($rs) > 0) {
2094
                return Database::result($rs, 0, 0);
2095
            }
2096
        }
2097
2098
        return 0;
2099
    }
2100
2101
    /**
2102
     * This function checks whether some users in the uploaded file
2103
     * repeated and creates unique usernames if necesary.
2104
     * A case: Within the file there is an user repeted twice (Julio Montoya / Julio Montoya)
2105
     * and the username fields are empty.
2106
     * Then, this function would create unique usernames based on the first and the last name.
2107
     * Two users wiould be created - jmontoya and jmontoya2.
2108
     * Of course, if in the database there is a user with the name jmontoya,
2109
     * the newly created two users registered would be jmontoya2 and jmontoya3.
2110
     *
2111
     * @param $users list of users
2112
     *
2113
     * @return array
2114
     *
2115
     * @author Julio Montoya Armas
2116
     */
2117
    public static function check_all_usernames($users, $course_list, $id_session)
2118
    {
2119
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
2120
        $usernames = [];
2121
        $new_users = [];
2122
        foreach ($users as $index => $user) {
2123
            $desired_username = [];
2124
            if (empty($user['UserName'])) {
2125
                $desired_username = self::make_username($user['FirstName'], $user['LastName'], '');
2126
                $pre_username = $desired_username['username'].$desired_username['sufix'];
2127
                $user['UserName'] = $pre_username;
2128
                $user['create'] = '1';
2129
            } else {
2130
                if (UserManager::is_username_available($user['UserName'])) {
2131
                    $desired_username = self::make_username($user['FirstName'], $user['LastName'], $user['UserName']);
2132
                    $user['UserName'] = $desired_username['username'].$desired_username['sufix'];
2133
                    $user['create'] = '1';
2134
                } else {
2135
                    $is_session_avail = self::user_available_in_session($user['UserName'], $course_list, $id_session);
2136
                    if ($is_session_avail == 0) {
2137
                        $user_name = $user['UserName'];
2138
                        $sql_select = "SELECT user_id FROM $table_user WHERE username ='$user_name' ";
2139
                        $rs = Database::query($sql_select);
2140
                        $user['create'] = Database::result($rs, 0, 0);
2141
                    } else {
2142
                        $user['create'] = $is_session_avail;
2143
                    }
2144
                }
2145
            }
2146
            // Usernames is the current list of users in the file.
2147
            $result_array = self::check_user_in_array($usernames, $desired_username);
2148
            $usernames = $result_array[0];
2149
            $desired_username = $result_array[1];
2150
            $user['UserName'] = $desired_username['username'].$desired_username['sufix'];
2151
            $new_users[] = $user;
2152
        }
2153
2154
        return $new_users;
2155
    }
2156
2157
    /**
2158
     * This functions checks whether there are users that are already
2159
     * registered in the DB by different creator than the current coach.
2160
     *
2161
     * @param array $users
2162
     *
2163
     * @return array
2164
     *
2165
     * @author Julio Montoya Armas
2166
     */
2167
    public static function get_user_creator($users)
2168
    {
2169
        $errors = [];
2170
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
2171
        foreach ($users as $index => $user) {
2172
            $username = Database::escape_string($user['UserName']);
2173
            $sql = "SELECT creator_id FROM $table_user WHERE username='$username' ";
2174
2175
            $rs = Database::query($sql);
2176
            $creator_id = Database::result($rs, 0, 0);
2177
            // check if we are the creators or not
2178
            if ($creator_id != '') {
2179
                if ($creator_id != api_get_user_id()) {
2180
                    $user['error'] = get_lang('UserAlreadyRegisteredByOtherCreator');
2181
                    $errors[] = $user;
2182
                }
2183
            }
2184
        }
2185
2186
        return $errors;
2187
    }
2188
2189
    /**
2190
     * Validates imported data.
2191
     *
2192
     * @param array $users list of users
2193
     */
2194
    public static function validate_data($users, $id_session = null)
2195
    {
2196
        $errors = [];
2197
        $new_users = [];
2198
        foreach ($users as $index => $user) {
2199
            // 1. Check whether mandatory fields are set.
2200
            $mandatory_fields = ['LastName', 'FirstName'];
2201
            if (api_get_setting('registration', 'email') == 'true') {
2202
                $mandatory_fields[] = 'Email';
2203
            }
2204
2205
            foreach ($mandatory_fields as $key => $field) {
2206
                if (!isset($user[$field]) || strlen($user[$field]) == 0) {
2207
                    $user['error'] = get_lang($field.'Mandatory');
2208
                    $errors[] = $user;
2209
                }
2210
            }
2211
            // 2. Check whether the username is too long.
2212
            if (UserManager::is_username_too_long($user['UserName'])) {
2213
                $user['error'] = get_lang('UserNameTooLong');
2214
                $errors[] = $user;
2215
            }
2216
2217
            $user['UserName'] = trim($user['UserName']);
2218
2219
            if (empty($user['UserName'])) {
2220
                $user['UserName'] = UserManager::create_username($user['FirstName'], $user['LastName']);
2221
            }
2222
            $new_users[] = $user;
2223
        }
2224
        $results = ['errors' => $errors, 'users' => $new_users];
2225
2226
        return $results;
2227
    }
2228
2229
    /**
2230
     * Adds missing user-information (which isn't required, like password, etc).
2231
     */
2232
    public static function complete_missing_data($user)
2233
    {
2234
        // 1. Generate a password if it is necessary.
2235
        if (!isset($user['Password']) || strlen($user['Password']) == 0) {
2236
            $user['Password'] = api_generate_password();
2237
        }
2238
2239
        return $user;
2240
    }
2241
2242
    /**
2243
     * Saves imported data.
2244
     */
2245
    public static function save_data($users, $course_list, $id_session)
2246
    {
2247
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2248
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2249
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2250
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
2251
2252
        $id_session = (int) $id_session;
2253
        $sendMail = $_POST['sendMail'] ? 1 : 0;
2254
2255
        // Adding users to the platform.
2256
        $new_users = [];
2257
        foreach ($users as $index => $user) {
2258
            $user = self::complete_missing_data($user);
2259
            // coach only will registered users
2260
            $default_status = STUDENT;
2261
            if ($user['create'] == COURSEMANAGER) {
2262
                $user['id'] = UserManager:: create_user(
2263
                    $user['FirstName'],
2264
                    $user['LastName'],
2265
                    $default_status,
2266
                    $user['Email'],
2267
                    $user['UserName'],
2268
                    $user['Password'],
2269
                    $user['OfficialCode'],
2270
                    api_get_setting('PlatformLanguage'),
2271
                    $user['PhoneNumber'],
2272
                    ''
2273
                );
2274
                $user['added_at_platform'] = 1;
2275
            } else {
2276
                $user['id'] = $user['create'];
2277
                $user['added_at_platform'] = 0;
2278
            }
2279
            $new_users[] = $user;
2280
        }
2281
        // Update user list.
2282
        $users = $new_users;
2283
2284
        // Inserting users.
2285
        foreach ($course_list as $enreg_course) {
2286
            $nbr_users = 0;
2287
            $new_users = [];
2288
            $enreg_course = Database::escape_string($enreg_course);
2289
            foreach ($users as $index => $user) {
2290
                $userid = (int) $user['id'];
2291
                $sql = "INSERT IGNORE INTO $tbl_session_rel_course_rel_user(session_id, c_id, user_id)
2292
                        VALUES('$id_session','$enreg_course','$userid')";
2293
                $result = Database::query($sql);
2294
                if (Database::affected_rows($result)) {
2295
                    $nbr_users++;
2296
                }
2297
                $new_users[] = $user;
2298
            }
2299
2300
            //update the nbr_users field
2301
            $sql_select = "SELECT COUNT(user_id) as nbUsers FROM $tbl_session_rel_course_rel_user
2302
                           WHERE session_id='$id_session' AND c_id='$enreg_course'";
2303
            $rs = Database::query($sql_select);
2304
            list($nbr_users) = Database::fetch_array($rs);
2305
            $sql_update = "UPDATE $tbl_session_rel_course SET nbr_users=$nbr_users
2306
                           WHERE session_id='$id_session' AND c_id='$enreg_course'";
2307
            Database::query($sql_update);
2308
2309
            $sql_update = "UPDATE $tbl_session SET nbr_users= '$nbr_users' WHERE id='$id_session'";
2310
            Database::query($sql_update);
2311
        }
2312
2313
        $new_users = [];
2314
        foreach ($users as $index => $user) {
2315
            $userid = $user['id'];
2316
            $sql_insert = "INSERT IGNORE INTO $tbl_session_rel_user(session_id, user_id, registered_at)
2317
                           VALUES ('$id_session','$userid', '".api_get_utc_datetime()."')";
2318
            Database::query($sql_insert);
2319
            $user['added_at_session'] = 1;
2320
            $new_users[] = $user;
2321
        }
2322
2323
        $users = $new_users;
2324
        $registered_users = get_lang('FileImported').'<br /> Import file results : <br />';
2325
        // Sending emails.
2326
        $addedto = '';
2327
        if ($sendMail) {
2328
            foreach ($users as $index => $user) {
2329
                $emailsubject = '['.api_get_setting('siteName').'] '.get_lang('YourReg').' '.api_get_setting('siteName');
2330
                $emailbody = get_lang('Dear').' '.
2331
                    api_get_person_name($user['FirstName'], $user['LastName']).",\n\n".
2332
                    get_lang('YouAreReg')." ".api_get_setting('siteName')." ".get_lang('WithTheFollowingSettings')."\n\n".
2333
                    get_lang('Username')." : $user[UserName]\n".
2334
                    get_lang('Pass')." : $user[Password]\n\n".
2335
                    get_lang('Address')." ".api_get_setting('siteName')." ".get_lang('Is')." : ".api_get_path(WEB_PATH)." \n\n".
2336
                    get_lang('Problem')."\n\n".
2337
                    get_lang('SignatureFormula').",\n\n".
2338
                    api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'))."\n".
2339
                    get_lang('Manager')." ".api_get_setting('siteName')."\nT. ".
2340
                    api_get_setting('administratorTelephone')."\n".get_lang('Email')." : ".api_get_setting('emailAdministrator');
2341
2342
                api_mail_html(
2343
                    api_get_person_name($user['FirstName'], $user['LastName'], null, PERSON_NAME_EMAIL_ADDRESS),
2344
                    $user['Email'],
2345
                    $emailsubject,
2346
                    $emailbody
2347
                );
2348
                $userInfo = api_get_user_info($user['id']);
2349
2350
                if (($user['added_at_platform'] == 1 && $user['added_at_session'] == 1) || $user['added_at_session'] == 1) {
2351
                    if ($user['added_at_platform'] == 1) {
2352
                        $addedto = get_lang('UserCreatedPlatform');
2353
                    } else {
2354
                        $addedto = '          ';
2355
                    }
2356
2357
                    if ($user['added_at_session'] == 1) {
2358
                        $addedto .= get_lang('UserInSession');
2359
                    }
2360
                } else {
2361
                    $addedto = get_lang('UserNotAdded');
2362
                }
2363
2364
                $registered_users .= UserManager::getUserProfileLink($userInfo).' - '.$addedto.'<br />';
2365
            }
2366
        } else {
2367
            foreach ($users as $index => $user) {
2368
                $userInfo = api_get_user_info($user['id']);
2369
                if (($user['added_at_platform'] == 1 && $user['added_at_session'] == 1) || $user['added_at_session'] == 1) {
2370
                    if ($user['added_at_platform'] == 1) {
2371
                        $addedto = get_lang('UserCreatedPlatform');
2372
                    } else {
2373
                        $addedto = '          ';
2374
                    }
2375
2376
                    if ($user['added_at_session'] == 1) {
2377
                        $addedto .= ' '.get_lang('UserInSession');
2378
                    }
2379
                } else {
2380
                    $addedto = get_lang('UserNotAdded');
2381
                }
2382
                $registered_users .= "<a href=\"../user/userInfo.php?uInfo=".$user['id']."\">".
2383
                    Security::remove_XSS($userInfo['complete_user_name'])."</a> - ".$addedto.'<br />';
2384
            }
2385
        }
2386
        Display::addFlash(Display::return_message($registered_users, 'normal', false));
2387
        header('Location: course.php?id_session='.$id_session);
2388
        exit;
2389
    }
2390
2391
    /**
2392
     * Reads CSV-file.
2393
     *
2394
     * @param string $file Path to the CSV-file
2395
     *
2396
     * @return array All userinformation read from the file
2397
     */
2398
    public function parse_csv_data($file)
2399
    {
2400
        $users = Import::csvToArray($file);
2401
        foreach ($users as $index => $user) {
2402
            if (isset($user['Courses'])) {
2403
                $user['Courses'] = explode('|', trim($user['Courses']));
2404
            }
2405
            $users[$index] = $user;
2406
        }
2407
2408
        return $users;
2409
    }
2410
2411
    /**
2412
     * Reads XML-file.
2413
     *
2414
     * @param string $file Path to the XML-file
2415
     *
2416
     * @return array All userinformation read from the file
2417
     */
2418
    public static function parse_xml_data($file)
2419
    {
2420
        $crawler = new \Symfony\Component\DomCrawler\Crawler();
2421
        $crawler->addXmlContent(file_get_contents($file));
2422
        $crawler = $crawler->filter('Contacts > Contact ');
2423
        $array = [];
2424
        foreach ($crawler as $domElement) {
2425
            $row = [];
2426
            foreach ($domElement->childNodes as $node) {
2427
                if ($node->nodeName != '#text') {
2428
                    $row[$node->nodeName] = $node->nodeValue;
2429
                }
2430
            }
2431
            if (!empty($row)) {
2432
                $array[] = $row;
2433
            }
2434
        }
2435
2436
        return $array;
2437
    }
2438
2439
    /**
2440
     * @param int $courseId
2441
     * @param int $sessionId
2442
     * @param int $studentId
2443
     */
2444
    public static function displayTrackingAccessOverView($courseId, $sessionId, $studentId)
2445
    {
2446
        $courseId = (int) $courseId;
2447
        $sessionId = (int) $sessionId;
2448
        $studentId = (int) $studentId;
2449
2450
        $courseList = [];
2451
        $sessionList = [];
2452
        $studentList = [];
2453
2454
        if (!empty($courseId)) {
2455
            $course = api_get_course_entity($courseId);
2456
            if ($course) {
2457
                $courseList[$course->getId()] = $course->getTitle();
2458
            }
2459
        }
2460
2461
        if (!empty($sessionId)) {
2462
            $session = api_get_session_entity($sessionId);
2463
            if ($session) {
2464
                $sessionList[$session->getId()] = $session->getName();
2465
            }
2466
        }
2467
2468
        if (!empty($studentId)) {
2469
            $student = api_get_user_entity($studentId);
2470
            if ($student) {
2471
                $studentList[$student->getId()] = UserManager::formatUserFullName($student);
2472
            }
2473
        }
2474
2475
        $form = new FormValidator('access_overview', 'GET');
2476
        $form->addElement(
2477
            'select_ajax',
2478
            'course_id',
2479
            get_lang('SearchCourse'),
2480
            $courseList,
2481
            [
2482
                'url' => api_get_path(WEB_AJAX_PATH).'course.ajax.php?'.http_build_query([
2483
                    'a' => 'search_course_by_session_all',
2484
                    'session_id' => $sessionId,
2485
                    'course_id' => $courseId,
2486
                ]),
2487
            ]
2488
        );
2489
2490
        $form->addElement(
2491
            'select_ajax',
2492
            'session_id',
2493
            get_lang('SearchSession'),
2494
            $sessionList,
2495
            [
2496
                'url_function' => "
2497
                    function () {
2498
                        var params = $.param({
2499
                            a: 'search_session_by_course',
2500
                            course_id: $('#access_overview_course_id').val() || 0
2501
                        });
2502
2503
                        return '".api_get_path(WEB_AJAX_PATH)."session.ajax.php?' + params;
2504
                    }
2505
                ",
2506
            ]
2507
        );
2508
2509
        $form->addSelect(
2510
            'profile',
2511
            get_lang('Profile'),
2512
            [
2513
                '' => get_lang('Select'),
2514
                STUDENT => get_lang('Student'),
2515
                COURSEMANAGER => get_lang('CourseManager'),
2516
                DRH => get_lang('Drh'),
2517
            ],
2518
            ['id' => 'profile']
2519
        );
2520
2521
        $form->addElement(
2522
            'select_ajax',
2523
            'student_id',
2524
            get_lang('SearchUsers'),
2525
            $studentList,
2526
            [
2527
                'placeholder' => get_lang('All'),
2528
                'url_function' => "
2529
                    function () {                    
2530
                        var params = $.param({
2531
                            a: 'search_user_by_course',
2532
                            session_id: $('#access_overview_session_id').val(),
2533
                            course_id: $('#access_overview_course_id').val()
2534
                        });
2535
2536
                        return '".api_get_path(WEB_AJAX_PATH)."course.ajax.php?' + params;
2537
                    }
2538
                ",
2539
            ]
2540
        );
2541
        $form->addDateRangePicker(
2542
            'date',
2543
            get_lang('DateRange'),
2544
            true,
2545
            [
2546
                'id' => 'date_range',
2547
                'format' => 'YYYY-MM-DD',
2548
                'timePicker' => 'false',
2549
                'validate_format' => 'Y-m-d',
2550
            ]
2551
        );
2552
        $form->addHidden('display', 'accessoverview');
2553
        $form->addRule('course_id', get_lang('Required'), 'required');
2554
        $form->addRule('profile', get_lang('Required'), 'required');
2555
        $form->addButton('submit', get_lang('Generate'), 'gear', 'primary');
2556
2557
        $table = null;
2558
2559
        if ($form->validate()) {
2560
            $table = new SortableTable(
2561
                'tracking_access_overview',
2562
                ['MySpace', 'getNumberOfTrackAccessOverview'],
2563
                ['MySpace', 'getUserDataAccessTrackingOverview'],
2564
                0
2565
            );
2566
            $table->set_header(0, get_lang('LoginDate'), true);
2567
            $table->set_header(1, get_lang('Username'), true);
2568
            if (api_is_western_name_order()) {
2569
                $table->set_header(2, get_lang('FirstName'), true);
2570
                $table->set_header(3, get_lang('LastName'), true);
2571
            } else {
2572
                $table->set_header(2, get_lang('LastName'), true);
2573
                $table->set_header(3, get_lang('FirstName'), true);
2574
            }
2575
            $table->set_header(4, get_lang('Clicks'), false);
2576
            $table->set_header(5, get_lang('IP'), false);
2577
            $table->set_header(6, get_lang('TimeLoggedIn'), false);
2578
        }
2579
2580
        $template = new Template(
2581
            null,
2582
            false,
2583
            false,
2584
            false,
2585
            false,
2586
            false,
2587
            false
2588
        );
2589
        $template->assign('form', $form->returnForm());
2590
        $template->assign('table', $table ? $table->return_table() : null);
2591
2592
        echo $template->fetch(
2593
            $template->get_template('my_space/accessoverview.tpl')
2594
        );
2595
    }
2596
2597
    /**
2598
     * @return int
2599
     */
2600
    public static function getNumberOfTrackAccessOverview()
2601
    {
2602
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
2603
        $sql = "SELECT COUNT(course_access_id) count FROM $table";
2604
        $result = Database::query($sql);
2605
        $row = Database::fetch_assoc($result);
2606
2607
        return $row['count'];
2608
    }
2609
2610
    /**
2611
     * @param $from
2612
     * @param $numberItems
2613
     * @param $column
2614
     * @param $orderDirection
2615
     *
2616
     * @return array
2617
     */
2618
    public static function getUserDataAccessTrackingOverview(
2619
        $from,
2620
        $numberItems,
2621
        $column,
2622
        $orderDirection
2623
    ) {
2624
        $from = (int) $from;
2625
        $numberItems = (int) $numberItems;
2626
        $column = (int) $column;
2627
        $orderDirection = Database::escape_string($orderDirection);
2628
2629
        $user = Database::get_main_table(TABLE_MAIN_USER);
2630
        $course = Database::get_main_table(TABLE_MAIN_COURSE);
2631
        $track_e_login = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
2632
        $track_e_course_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
2633
2634
        global $export_csv;
2635
        $is_western_name_order = api_is_western_name_order();
2636
        if ($export_csv) {
2637
            $is_western_name_order = api_is_western_name_order(PERSON_NAME_DATA_EXPORT);
2638
        }
2639
2640
        //TODO add course name
2641
        $sql = "SELECT
2642
                a.login_course_date as col0,
2643
                u.username as col1,
2644
                ".(
2645
                    $is_western_name_order ? "
2646
                        u.firstname AS col2,
2647
                        u.lastname AS col3,
2648
                    " : "
2649
                        u.lastname AS col2,
2650
                        u.firstname AS col3,
2651
                "
2652
        )."
2653
                a.logout_course_date,
2654
                c.title,
2655
                c.code,
2656
                u.user_id
2657
            FROM $track_e_course_access a
2658
            INNER JOIN $user u ON a.user_id = u.user_id
2659
            INNER JOIN $course c ON a.c_id = c.id
2660
            WHERE 1=1 ";
2661
2662
        if (isset($_GET['course_id']) && !empty($_GET['course_id'])) {
2663
            $courseId = (int) $_GET['course_id'];
2664
            $sql .= " AND c.id = ".$courseId;
2665
        }
2666
2667
        if (isset($_GET['session_id']) && !empty($_GET['session_id'])) {
2668
            $sessionId = (int) $_GET['session_id'];
2669
            $sql .= " AND a.session_id = ".$sessionId;
2670
        }
2671
2672
        if (isset($_GET['student_id']) && !empty($_GET['student_id'])) {
2673
            $userId = (int) $_GET['student_id'];
2674
            $sql .= " AND u.user_id = ".$userId;
2675
        }
2676
2677
        if (isset($_GET['date']) && !empty($_GET['date'])) {
2678
            $dates = DateRangePicker::parseDateRange($_GET['date']);
2679
            if (isset($dates['start']) && !empty($dates['start'])) {
2680
                $dates['start'] = Database::escape_string($dates['start']);
2681
                $sql .= " AND login_course_date >= '".$dates['start']."'";
2682
            }
2683
            if (isset($dates['end']) && !empty($dates['end'])) {
2684
                $dates['end'] = Database::escape_string($dates['end']);
2685
                $sql .= " AND logout_course_date <= '".$dates['end']."'";
2686
            }
2687
        }
2688
2689
        $sql .= " ORDER BY col$column $orderDirection ";
2690
        $sql .= " LIMIT $from,$numberItems";
2691
2692
        $result = Database::query($sql);
2693
2694
        $data = [];
2695
        while ($user = Database::fetch_assoc($result)) {
2696
            $data[] = $user;
2697
        }
2698
2699
        $return = [];
2700
        //TODO: Dont use numeric index
2701
        foreach ($data as $key => $info) {
2702
            $start_date = $info['col0'];
2703
            $end_date = $info['logout_course_date'];
2704
2705
            $return[$info['user_id']] = [
2706
                $start_date,
2707
                $info['col1'],
2708
                $info['col2'],
2709
                $info['col3'],
2710
                $info['user_id'],
2711
                'ip',
2712
                //TODO is not correct/precise, it counts the time not logged between two loggins
2713
                gmdate("H:i:s", strtotime($end_date) - strtotime($start_date)),
2714
            ];
2715
        }
2716
2717
        foreach ($return as $key => $info) {
2718
            $ipResult = Database::select(
2719
                'user_ip',
2720
                $track_e_login,
2721
                ['where' => [
2722
                    '? BETWEEN login_date AND logout_date' => $info[0],
2723
                ]],
2724
                'first'
2725
            );
2726
2727
            $return[$key][5] = $ipResult['user_ip'];
2728
        }
2729
2730
        return $return;
2731
    }
2732
2733
    /**
2734
     * Gets the connections to a course as an array of login and logout time.
2735
     *
2736
     * @param int    $user_id
2737
     * @param array  $course_info
2738
     * @param int    $sessionId
2739
     * @param string $start_date
2740
     * @param string $end_date
2741
     *
2742
     * @author  Jorge Frisancho Jibaja
2743
     * @author  Julio Montoya <[email protected]> fixing the function
2744
     *
2745
     * @version OCT-22- 2010
2746
     *
2747
     * @return array
2748
     */
2749
    public static function get_connections_to_course_by_date(
2750
        $user_id,
2751
        $course_info,
2752
        $sessionId,
2753
        $start_date,
2754
        $end_date
2755
    ) {
2756
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
2757
        $user_id = (int) $user_id;
2758
        $connections = [];
2759
        if (!empty($course_info)) {
2760
            $courseId = (int) $course_info['real_id'];
2761
            $end_date = add_day_to($end_date);
2762
2763
            $start_date = Database::escape_string($start_date);
2764
            $end_date = Database::escape_string($end_date);
2765
            $sessionCondition = api_get_session_condition($sessionId);
2766
            $sql = "SELECT 
2767
                        login_course_date, 
2768
                        logout_course_date, 
2769
                        TIMESTAMPDIFF(SECOND, login_course_date, logout_course_date) duration
2770
                    FROM $table
2771
                    WHERE
2772
                        user_id = $user_id AND
2773
                        c_id = $courseId AND
2774
                        login_course_date BETWEEN '$start_date' AND '$end_date' AND
2775
                        logout_course_date BETWEEN '$start_date' AND '$end_date'
2776
                        $sessionCondition
2777
                    ORDER BY login_course_date ASC";
2778
            $rs = Database::query($sql);
2779
2780
            while ($row = Database::fetch_array($rs)) {
2781
                $connections[] = [
2782
                    'login' => $row['login_course_date'],
2783
                    'logout' => $row['logout_course_date'],
2784
                    'duration' => $row['duration'],
2785
                ];
2786
            }
2787
        }
2788
2789
        return $connections;
2790
    }
2791
}
2792
2793
/**
2794
 * @param $user_id
2795
 * @param array $course_info
2796
 * @param int   $sessionId
2797
 * @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...
2798
 * @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...
2799
 *
2800
 * @return array
2801
 */
2802
function get_stats($user_id, $course_info, $sessionId, $start_date = null, $end_date = null)
2803
{
2804
    $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
2805
    $result = [];
2806
    if (!empty($course_info)) {
2807
        $stringStartDate = '';
2808
        $stringEndDate = '';
2809
        if ($start_date != null && $end_date != null) {
2810
            $end_date = add_day_to($end_date);
2811
2812
            $start_date = Database::escape_string($start_date);
2813
            $end_date = Database::escape_string($end_date);
2814
2815
            $stringStartDate = "AND login_course_date BETWEEN '$start_date' AND '$end_date'";
2816
            $stringEndDate = "AND logout_course_date BETWEEN '$start_date' AND '$end_date'";
2817
        }
2818
        $user_id = (int) $user_id;
2819
        $courseId = (int) $course_info['real_id'];
2820
        $sessionCondition = api_get_session_condition($sessionId);
2821
        $sql = "SELECT
2822
                SEC_TO_TIME(AVG(time_to_sec(timediff(logout_course_date,login_course_date)))) as avrg,
2823
                SEC_TO_TIME(SUM(time_to_sec(timediff(logout_course_date,login_course_date)))) as total,
2824
                count(user_id) as times
2825
                FROM $table
2826
                WHERE
2827
                    user_id = $user_id AND
2828
                    c_id = $courseId $stringStartDate $stringEndDate 
2829
                    $sessionCondition                    
2830
                ORDER BY login_course_date ASC";
2831
2832
        $rs = Database::query($sql);
2833
        if ($row = Database::fetch_array($rs)) {
2834
            $foo_avg = $row['avrg'];
2835
            $foo_total = $row['total'];
2836
            $foo_times = $row['times'];
2837
            $result = [
2838
                'avg' => $foo_avg,
2839
                'total' => $foo_total,
2840
                'times' => $foo_times,
2841
            ];
2842
        }
2843
    }
2844
2845
    return $result;
2846
}
2847
2848
function add_day_to($end_date)
2849
{
2850
    $foo_date = strtotime($end_date);
2851
    $foo_date = strtotime(' +1 day', $foo_date);
2852
    $foo_date = date('Y-m-d', $foo_date);
2853
2854
    return $foo_date;
2855
}
2856
2857
/**
2858
 * Converte an array to a table in html.
2859
 *
2860
 * @param array $result
2861
 *
2862
 * @author Jorge Frisancho Jibaja
2863
 *
2864
 * @version OCT-22- 2010
2865
 *
2866
 * @return string
2867
 */
2868
function convert_to_string($result)
2869
{
2870
    $html = '<table class="table">';
2871
    if (!empty($result)) {
2872
        foreach ($result as $key => $data) {
2873
            $html .= '<tr><td>';
2874
            $html .= api_get_local_time($data['login']);
2875
            $html .= '</td>';
2876
            $html .= '<td>';
2877
2878
            $html .= api_time_to_hms(api_strtotime($data['logout']) - api_strtotime($data['login']));
2879
            $html .= '</tr></td>';
2880
        }
2881
    }
2882
    $html .= '</table>';
2883
2884
    return $html;
2885
}
2886
2887
/**
2888
 * This function draw the graphic to be displayed on the user view as an image.
2889
 *
2890
 * @param array  $sql_result
2891
 * @param string $start_date
2892
 * @param string $end_date
2893
 * @param string $type
2894
 *
2895
 * @author Jorge Frisancho Jibaja
2896
 *
2897
 * @version OCT-22- 2010
2898
 *
2899
 * @return string
2900
 */
2901
function grapher($sql_result, $start_date, $end_date, $type = '')
2902
{
2903
    if (empty($start_date)) {
2904
        $start_date = '';
2905
    }
2906
    if (empty($end_date)) {
2907
        $end_date = '';
2908
    }
2909
    if ($type == '') {
2910
        $type = 'day';
2911
    }
2912
    $main_year = $main_month_year = $main_day = [];
2913
2914
    $period = new DatePeriod(
2915
        new DateTime($start_date),
2916
        new DateInterval('P1D'),
2917
        new DateTime($end_date)
2918
    );
2919
2920
    foreach ($period as $date) {
2921
        $main_day[$date->format('d-m-Y')] = 0;
2922
    }
2923
2924
    $period = new DatePeriod(
2925
        new DateTime($start_date),
2926
        new DateInterval('P1M'),
2927
        new DateTime($end_date)
2928
    );
2929
2930
    foreach ($period as $date) {
2931
        $main_month_year[$date->format('m-Y')] = 0;
2932
    }
2933
2934
    $i = 0;
2935
    if (is_array($sql_result) && count($sql_result) > 0) {
2936
        foreach ($sql_result as $key => $data) {
2937
            $login = api_strtotime($data['login']);
2938
            $logout = api_strtotime($data['logout']);
2939
            //creating the main array
2940
            if (isset($main_month_year[date('m-Y', $login)])) {
2941
                $main_month_year[date('m-Y', $login)] += float_format(($logout - $login) / 60, 0);
2942
            }
2943
            if (isset($main_day[date('d-m-Y', $login)])) {
2944
                $main_day[date('d-m-Y', $login)] += float_format(($logout - $login) / 60, 0);
2945
            }
2946
            if ($i > 500) {
2947
                break;
2948
            }
2949
            $i++;
2950
        }
2951
        switch ($type) {
2952
            case 'day':
2953
                $main_date = $main_day;
2954
                break;
2955
            case 'month':
2956
                $main_date = $main_month_year;
2957
                break;
2958
            case 'year':
2959
                $main_date = $main_year;
2960
                break;
2961
        }
2962
2963
        $labels = array_keys($main_date);
2964
        if (count($main_date) == 1) {
2965
            $labels = $labels[0];
2966
            $main_date = $main_date[$labels];
2967
        }
2968
2969
        /* Create and populate the pData object */
2970
        $myData = new pData();
2971
        $myData->addPoints($main_date, 'Serie1');
2972
        if (count($main_date) != 1) {
2973
            $myData->addPoints($labels, 'Labels');
2974
            $myData->setSerieDescription('Labels', 'Months');
2975
            $myData->setAbscissa('Labels');
2976
        }
2977
        $myData->setSerieWeight('Serie1', 1);
2978
        $myData->setSerieDescription('Serie1', get_lang('MyResults'));
2979
        $myData->setAxisName(0, get_lang('Minutes'));
2980
        $myData->loadPalette(api_get_path(SYS_CODE_PATH).'palettes/pchart/default.color', true);
2981
2982
        // Cache definition
2983
        $cachePath = api_get_path(SYS_ARCHIVE_PATH);
2984
        $myCache = new pCache(['CacheFolder' => substr($cachePath, 0, strlen($cachePath) - 1)]);
2985
        $chartHash = $myCache->getHash($myData);
2986
2987
        if ($myCache->isInCache($chartHash)) {
2988
            //if we already created the img
2989
            $imgPath = api_get_path(SYS_ARCHIVE_PATH).$chartHash;
2990
            $myCache->saveFromCache($chartHash, $imgPath);
2991
            $imgPath = api_get_path(WEB_ARCHIVE_PATH).$chartHash;
2992
        } else {
2993
            /* Define width, height and angle */
2994
            $mainWidth = 760;
2995
            $mainHeight = 230;
2996
            $angle = 50;
2997
2998
            /* Create the pChart object */
2999
            $myPicture = new pImage($mainWidth, $mainHeight, $myData);
3000
3001
            /* Turn of Antialiasing */
3002
            $myPicture->Antialias = false;
3003
            /* Draw the background */
3004
            $settings = ["R" => 255, "G" => 255, "B" => 255];
3005
            $myPicture->drawFilledRectangle(0, 0, $mainWidth, $mainHeight, $settings);
3006
3007
            /* Add a border to the picture */
3008
            $myPicture->drawRectangle(
3009
                0,
3010
                0,
3011
                $mainWidth - 1,
3012
                $mainHeight - 1,
3013
                ["R" => 0, "G" => 0, "B" => 0]
3014
            );
3015
3016
            /* Set the default font */
3017
            $myPicture->setFontProperties(
3018
                [
3019
                    "FontName" => api_get_path(SYS_FONTS_PATH).'opensans/OpenSans-Regular.ttf',
3020
                    "FontSize" => 10, ]
3021
            );
3022
            /* Write the chart title */
3023
            $myPicture->drawText(
3024
                $mainWidth / 2,
3025
                30,
3026
                get_lang('TimeSpentInTheCourse'),
3027
                [
3028
                    "FontSize" => 12,
3029
                    "Align" => TEXT_ALIGN_BOTTOMMIDDLE,
3030
                ]
3031
            );
3032
3033
            /* Set the default font */
3034
            $myPicture->setFontProperties(
3035
                [
3036
                    "FontName" => api_get_path(SYS_FONTS_PATH).'opensans/OpenSans-Regular.ttf',
3037
                    "FontSize" => 8,
3038
                ]
3039
            );
3040
3041
            /* Define the chart area */
3042
            $myPicture->setGraphArea(50, 40, $mainWidth - 40, $mainHeight - 80);
3043
3044
            /* Draw the scale */
3045
            $scaleSettings = [
3046
                'XMargin' => 10,
3047
                'YMargin' => 10,
3048
                'Floating' => true,
3049
                'GridR' => 200,
3050
                'GridG' => 200,
3051
                'GridB' => 200,
3052
                'DrawSubTicks' => true,
3053
                'CycleBackground' => true,
3054
                'LabelRotation' => $angle,
3055
                'Mode' => SCALE_MODE_ADDALL_START0,
3056
            ];
3057
            $myPicture->drawScale($scaleSettings);
3058
3059
            /* Turn on Antialiasing */
3060
            $myPicture->Antialias = true;
3061
3062
            /* Enable shadow computing */
3063
            $myPicture->setShadow(
3064
                true,
3065
                [
3066
                    "X" => 1,
3067
                    "Y" => 1,
3068
                    "R" => 0,
3069
                    "G" => 0,
3070
                    "B" => 0,
3071
                    "Alpha" => 10,
3072
                ]
3073
            );
3074
3075
            /* Draw the line chart */
3076
            $myPicture->setFontProperties(
3077
                [
3078
                    "FontName" => api_get_path(SYS_FONTS_PATH).'opensans/OpenSans-Regular.ttf',
3079
                    "FontSize" => 10,
3080
                ]
3081
            );
3082
            $myPicture->drawSplineChart();
3083
            $myPicture->drawPlotChart(
3084
                [
3085
                    "DisplayValues" => true,
3086
                    "PlotBorder" => true,
3087
                    "BorderSize" => 1,
3088
                    "Surrounding" => -60,
3089
                    "BorderAlpha" => 80,
3090
                ]
3091
            );
3092
3093
            /* Do NOT Write the chart legend */
3094
3095
            /* Write and save into cache */
3096
            $myCache->writeToCache($chartHash, $myPicture);
3097
            $imgPath = api_get_path(SYS_ARCHIVE_PATH).$chartHash;
3098
            $myCache->saveFromCache($chartHash, $imgPath);
3099
            $imgPath = api_get_path(WEB_ARCHIVE_PATH).$chartHash;
3100
        }
3101
        $html = '<img src="'.$imgPath.'">';
3102
3103
        return $html;
3104
    } else {
3105
        $foo_img = api_convert_encoding(
3106
            '<div id="messages" class="warning-message">'.get_lang('GraphicNotAvailable').'</div>',
3107
            'UTF-8'
3108
        );
3109
3110
        return $foo_img;
3111
    }
3112
}
3113