Completed
Push — master ( f41061...196bfc )
by Julito
09:03
created

MySpace::display_tracking_user_overview()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 77
Code Lines 58

Duplication

Lines 0
Ratio 0 %

Importance

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