Completed
Push — master ( 024a20...a0a31d )
by Julito
09:32
created

MySpace::grapher()   F

Complexity

Conditions 18
Paths 9248

Size

Total Lines 206
Code Lines 127

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 18
eloc 127
nc 9248
nop 4
dl 0
loc 206
rs 0.56
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

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