Passed
Push — master ( 2a697d...2fc9bb )
by Julito
11:49 queued 02:46
created

MySpace::make_username()   A

Complexity

Conditions 6
Paths 6

Size

Total Lines 28
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

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