Passed
Push — master ( d0b226...f5358a )
by Julito
10:41
created

MySpace::get_total_number_courses()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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