Test Setup Failed
Push — master ( c7183e...00c715 )
by Julito
30:43
created

MySpace::element_start()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 10

Duplication

Lines 12
Ratio 92.31 %

Importance

Changes 0
Metric Value
cc 2
eloc 10
nc 2
nop 2
dl 12
loc 13
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use CpChart\Chart\Cache as pCache;
5
use CpChart\Chart\Data as pData;
6
use CpChart\Chart\Image as pImage;
7
8
/**
9
 * Class MySpace
10
 * @package chamilo.reporting
11
 */
12
class MySpace
13
{
14
    /**
15
     * Get admin actions
16
     * @return string
17
     */
18
    public static function getAdminActions()
19
    {
20
        $actions = array(
21
            //array('url' => api_get_path(WEB_CODE_PATH).'mySpace/index.php', 'content' => get_lang('Home')),
22
            array(
23
                'url' => api_get_path(WEB_CODE_PATH).'mySpace/admin_view.php?display=coaches',
24
                'content' => get_lang('DisplayCoaches'),
25
            ),
26
            array(
27
                'url' => api_get_path(WEB_CODE_PATH).'mySpace/admin_view.php?display=user',
28
                'content' => get_lang('DisplayUserOverview'),
29
            ),
30
            array(
31
                'url' => api_get_path(WEB_CODE_PATH).'mySpace/admin_view.php?display=session',
32
                'content' => get_lang('DisplaySessionOverview'),
33
            ),
34
            array(
35
                'url' => api_get_path(WEB_CODE_PATH).'mySpace/admin_view.php?display=course',
36
                'content' => get_lang('DisplayCourseOverview'),
37
            ),
38
            array(
39
                'url' => api_get_path(WEB_CODE_PATH).'tracking/question_course_report.php?view=admin',
40
                'content' => get_lang('LPQuestionListResults'),
41
            ),
42
            array(
43
                'url' => api_get_path(WEB_CODE_PATH).'tracking/course_session_report.php?view=admin',
44
                'content' => get_lang('LPExerciseResultsBySession'),
45
            ),
46
            [
47
                'url' => api_get_path(WEB_CODE_PATH).'mySpace/admin_view.php?display=accessoverview',
48
                'content' => get_lang('DisplayAccessOverview').' ('.get_lang('Beta').')',
49
            ],
50
        );
51
52
        return Display::actions($actions, null);
53
    }
54
55
    /**
56
     * @return string
57
     */
58
    public static function getTopMenu()
59
    {
60
        $menu_items = array();
61
        $menu_items[] = Display::url(
62
            Display::return_icon('stats.png', get_lang('MyStats'), '', ICON_SIZE_MEDIUM),
63
            api_get_path(WEB_CODE_PATH)."auth/my_progress.php"
64
        );
65
        $menu_items[] = Display::url(
66
            Display::return_icon('teacher.png', get_lang('TeacherInterface'), array(), 32),
67
            api_get_path(WEB_CODE_PATH).'mySpace/?view=teacher'
68
        );
69
        $menu_items[] = Display::url(Display::return_icon('star_na.png', get_lang('AdminInterface'), array(), 32), '#');
70
        $menu_items[] = Display::url(
71
            Display::return_icon('quiz.png', get_lang('ExamTracking'), array(), 32),
72
            api_get_path(WEB_CODE_PATH).'tracking/exams.php'
73
        );
74
        $menu = '';
75
        foreach ($menu_items as $item) {
76
            $menu .= $item;
77
        }
78
        $menu .= '<br />';
79
80
        return $menu;
81
    }
82
83
    /**
84
     * This function serves exporting data in CSV format.
85
     * @param array $header         The header labels.
86
     * @param array $data           The data array.
87
     * @param string $file_name     The name of the file which contains exported data.
88
     * @return string mixed             Returns a message (string) if an error occurred.
89
     */
90
    public function export_csv($header, $data, $file_name = 'export.csv')
91
    {
92
        $archive_path = api_get_path(SYS_ARCHIVE_PATH);
93
        $archive_url = api_get_path(WEB_CODE_PATH).'course_info/download.php?archive_path=&archive=';
94
        $message = '';
95
        if (!$open = fopen($archive_path.$file_name, 'w+')) {
96
            $message = get_lang('noOpen');
97
        } else {
98
            $info = '';
99
100
            foreach ($header as $value) {
101
                $info .= $value.';';
102
            }
103
            $info .= "\r\n";
104
105
            foreach ($data as $row) {
106
                foreach ($row as $value) {
107
                    $info .= $value.';';
108
                }
109
                $info .= "\r\n";
110
            }
111
112
            fwrite($open, $info);
113
            fclose($open);
114
            @chmod($file_name, api_get_permissions_for_new_files());
115
116
            header("Location:".$archive_url.$file_name);
117
        }
118
        return $message;
119
    }
120
121
    /**
122
     * Gets the connections to a course as an array of login and logout time
123
     *
124
     * @param int $userId User id
125
     * @param array $courseInfo
126
     * @param int $sessionId Session id (optional, default = 0)
127
     * @return array Connections
128
     */
129
    public static function get_connections_to_course(
130
        $userId,
131
        $courseInfo,
132
        $sessionId = 0
133
    ) {
134
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
135
136
        // protect data
137
        $userId = (int) $userId;
138
        $courseId = (int) $courseInfo['real_id'];
139
        $sessionId = (int) $sessionId;
140
        $sessionCondition = api_get_session_condition($sessionId);
141
142
        $sql = 'SELECT login_course_date, logout_course_date
143
                FROM ' . $table.'
144
                WHERE
145
                    user_id = '.$userId.' AND
146
                    c_id = '.$courseId.' 
147
                    '.$sessionCondition.'
148
                ORDER BY login_course_date ASC';
149
        $rs = Database::query($sql);
150
        $connections = array();
151
152 View Code Duplication
        while ($row = Database::fetch_array($rs)) {
153
            $connections[] = array(
154
                'login' => $row['login_course_date'],
155
                'logout' => $row['logout_course_date']
156
            );
157
        }
158
159
        return $connections;
160
    }
161
162
    /**
163
     * @param $user_id
164
     * @param $course_list
165
     * @param int $session_id
166
     * @return array|bool
167
     */
168
    public static function get_connections_from_course_list(
169
        $user_id,
170
        $course_list,
171
        $session_id = 0
172
    ) {
173
        // Database table definitions
174
        $tbl_track_course = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
175
        if (empty($course_list)) {
176
            return false;
177
        }
178
179
        // protect data
180
        $user_id = intval($user_id);
181
        $session_id = intval($session_id);
182
        $new_course_list = array();
183
        foreach ($course_list as $course_item) {
184
            $courseInfo = api_get_course_info($course_item['code']);
185
            $courseId = $courseInfo['real_id'];
186
            $new_course_list[] = '"'.$courseId.'"';
187
        }
188
        $course_list = implode(', ', $new_course_list);
189
190
        if (empty($course_list)) {
191
            return false;
192
        }
193
        $sql = 'SELECT login_course_date, logout_course_date, c_id
194
                FROM ' . $tbl_track_course.'
195
                WHERE
196
                    user_id = '.$user_id.' AND
197
                    c_id IN ('.$course_list.') AND
198
                    session_id = '.$session_id.'
199
                ORDER BY login_course_date ASC';
200
        $rs = Database::query($sql);
201
        $connections = array();
202
203
        while ($row = Database::fetch_array($rs)) {
204
            $timestamp_login_date = api_strtotime($row['login_course_date'], 'UTC');
205
            $timestamp_logout_date = api_strtotime($row['logout_course_date'], 'UTC');
206
            $connections[] = array(
207
                'login' => $timestamp_login_date,
208
                'logout' => $timestamp_logout_date,
209
                'c_id' => $row['c_id']
210
            );
211
        }
212
213
        return $connections;
214
    }
215
216
    /**
217
     * Creates a small table in the last column of the table with the user overview
218
     *
219
     * @param integer $user_id the id of the user
220
     * @param array $url_params additional url parameters
221
     * @param array $row the row information (the other columns)
222
     * @return string html code
223
     */
224
    public static function course_info_tracking_filter($user_id, $url_params, $row)
225
    {
226
        // the table header
227
        $return = '<table class="data_table" style="width: 100%;border:0;padding:0;border-collapse:collapse;table-layout: fixed">';
228
        // database table definition
229
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
230
231
        // getting all the courses of the user
232
        $sql = "SELECT * FROM $tbl_course_user
233
                WHERE
234
                    user_id = '".intval($user_id)."' AND
235
                    relation_type<>".COURSE_RELATION_TYPE_RRHH." ";
236
        $result = Database::query($sql);
237
        while ($row = Database::fetch_array($result)) {
238
            $courseInfo = api_get_course_info_by_id($row['c_id']);
239
            if (empty($courseInfo)) {
240
                continue;
241
            }
242
243
            $courseCode = $courseInfo['code'];
244
            $courseId = $courseInfo['real_id'];
245
246
            $return .= '<tr>';
247
            // course code
248
            $return .= '    <td width="157px" >'.cut($courseCode, 20, true).'</td>';
249
            // time spent in the course
250
            $return .= '    <td><div>'.api_time_to_hms(Tracking::get_time_spent_on_the_course($user_id, $courseId)).'</div></td>';
251
            // student progress in course
252
            $return .= '    <td><div>'.round(Tracking::get_avg_student_progress($user_id, $courseCode), 2).'</div></td>';
253
            // student score
254
            $avg_score = Tracking::get_avg_student_score($user_id, $courseCode);
255
            if (is_numeric($avg_score)) {
256
                $avg_score = round($avg_score, 2);
257
            } else {
258
                $$avg_score = '-';
259
            }
260
261
            $return .= '    <td><div>'.$avg_score.'</div></td>';
262
            // student tes score
263
            //$return .= '  <td><div style="width:40px">'.round(Tracking::get_avg_student_exercise_score ($user_id, $courseCode),2).'%</div></td>';
264
            // student messages
265
            $return .= '    <td><div>'.Tracking::count_student_messages($user_id, $courseCode).'</div></td>';
266
            // student assignments
267
            $return .= '    <td><div>'.Tracking::count_student_assignments($user_id, $courseCode).'</div></td>';
268
            // student exercises results (obtained score, maximum score, number of exercises answered, score percentage)
269
            $exercises_results = self::exercises_results($user_id, $courseCode);
270
            $return .= '    <td width="105px"><div>'.(is_null($exercises_results['percentage']) ? '' : $exercises_results['score_obtained'].'/'.$exercises_results['score_possible'].' ( '.$exercises_results['percentage'].'% )').'</div></td>';
271
            $return .= '    <td><div>'.$exercises_results['questions_answered'].'</div></td>';
272
            $return .= '    <td><div>'.Tracking::get_last_connection_date_on_the_course($user_id, $courseInfo).'</div></td>';
273
            $return .= '<tr>';
274
        }
275
        $return .= '</table>';
276
        return $return;
277
    }
278
279
    /**
280
     * Display a sortable table that contains an overview off all the
281
     * reporting progress of all users and all courses the user is subscribed to
282
     * @author Patrick Cool <[email protected]>, Ghent University, Belgium
283
     * @version Dokeos 1.8.6
284
     * @since October 2008
285
     */
286
    public static function display_tracking_user_overview()
287
    {
288
        self::display_user_overview_export_options();
289
        $t_head = '<table style="width: 100%;border:0;padding:0;border-collapse:collapse;table-layout: fixed">';
290
        $t_head .= '<tr>';
291
        $t_head .= '<th width="155px" style="border-left:0;border-bottom:0"><span>'.get_lang('Course').'</span></th>';
292
        $t_head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('AvgTimeSpentInTheCourse'), 6, true).'</span></th>';
293
        $t_head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('AvgStudentsProgress'), 6, true).'</span></th>';
294
        $t_head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('AvgCourseScore'), 6, true).'</span></th>';
295
        $t_head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('TotalNumberOfMessages'), 6, true).'</span></th>';
296
        $t_head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('TotalNumberOfAssignments'), 6, true).'</span></th>';
297
        $t_head .= '<th width="105px" style="border-bottom:0"><span>'.get_lang('TotalExercisesScoreObtained').'</span></th>';
298
        $t_head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('TotalExercisesAnswered'), 6, true).'</span></th>';
299
        $t_head .= '<th style="padding:0;border-bottom:0;border-right:0;"><span>'.get_lang('LatestLogin').'</span></th>';
300
        $t_head .= '</tr></table>';
301
        $addparams = array('view' => 'admin', 'display' => 'user');
302
        $table = new SortableTable(
303
            'tracking_user_overview',
304
            array('MySpace', 'get_number_of_users_tracking_overview'),
305
            array('MySpace', 'get_user_data_tracking_overview'),
306
            0
307
        );
308
        $table->additional_parameters = $addparams;
309
        $table->set_header(0, get_lang('OfficialCode'), true, array('style' => 'font-size:8pt'), array('style' => 'font-size:8pt'));
310
        if (api_is_western_name_order()) {
311
            $table->set_header(1, get_lang('FirstName'), true, array('style' => 'font-size:8pt'), array('style' => 'font-size:8pt'));
312
            $table->set_header(2, get_lang('LastName'), true, array('style' => 'font-size:8pt'), array('style' => 'font-size:8pt'));
313
        } else {
314
            $table->set_header(1, get_lang('LastName'), true, array('style' => 'font-size:8pt'), array('style' => 'font-size:8pt'));
315
            $table->set_header(2, get_lang('FirstName'), true, array('style' => 'font-size:8pt'), array('style' => 'font-size:8pt'));
316
        }
317
        $table->set_header(3, get_lang('LoginName'), true, array('style' => 'font-size:8pt'), array('style' => 'font-size:8pt'));
318
        $table->set_header(4, $t_head, false, array('style' => 'width:90%;border:0;padding:0;font-size:7.5pt;'), array('style' => 'width:90%;padding:0;font-size:7.5pt;'));
319
        $table->set_column_filter(4, array('MySpace', 'course_info_tracking_filter'));
320
        $table->display();
321
    }
322
323
    /**
324
     * @param $export_csv
325
     */
326
    public static function display_tracking_coach_overview($export_csv)
327
    {
328
        if ($export_csv) {
329
            $is_western_name_order = api_is_western_name_order(PERSON_NAME_DATA_EXPORT);
330
        } else {
331
            $is_western_name_order = api_is_western_name_order();
332
        }
333
        $sort_by_first_name = api_sort_by_first_name();
334
        $tracking_column = isset($_GET['tracking_list_coaches_column']) ? $_GET['tracking_list_coaches_column'] : ($is_western_name_order xor $sort_by_first_name) ? 1 : 0;
335
        $tracking_direction = (isset($_GET['tracking_list_coaches_direction']) && in_array(strtoupper($_GET['tracking_list_coaches_direction']), array('ASC', 'DESC', 'ASCENDING', 'DESCENDING', '0', '1'))) ? $_GET['tracking_list_coaches_direction'] : 'DESC';
336
        // Prepare array for column order - when impossible, use some of user names.
337
        if ($is_western_name_order) {
338
            $order = array(
339
                0 => 'firstname',
340
                1 => 'lastname',
341
                2 => ($sort_by_first_name ? 'firstname' : 'lastname'),
342
                3 => 'login_date',
343
                4 => ($sort_by_first_name ? 'firstname' : 'lastname'),
344
                5 => ($sort_by_first_name ? 'firstname' : 'lastname'),
345
            );
346
        } else {
347
            $order = array(
348
                0 => 'lastname',
349
                1 => 'firstname',
350
                2 => ($sort_by_first_name ? 'firstname' : 'lastname'),
351
                3 => 'login_date',
352
                4 => ($sort_by_first_name ? 'firstname' : 'lastname'),
353
                5 => ($sort_by_first_name ? 'firstname' : 'lastname'),
354
            );
355
        }
356
        $table = new SortableTable(
357
            'tracking_list_coaches_myspace',
358
            array('MySpace', 'count_coaches'),
359
            null,
360
            ($is_western_name_order xor $sort_by_first_name) ? 1 : 0
361
        );
362
        $parameters['view'] = 'admin';
363
        $table->set_additional_parameters($parameters);
364 View Code Duplication
        if ($is_western_name_order) {
365
            $table->set_header(0, get_lang('FirstName'), true);
366
            $table->set_header(1, get_lang('LastName'), true);
367
        } else {
368
            $table->set_header(0, get_lang('LastName'), true);
369
            $table->set_header(1, get_lang('FirstName'), true);
370
        }
371
        $table->set_header(2, get_lang('TimeSpentOnThePlatform'), false);
372
        $table->set_header(3, get_lang('LastConnexion'), false);
373
        $table->set_header(4, get_lang('NbStudents'), false);
374
        $table->set_header(5, get_lang('CountCours'), false);
375
        $table->set_header(6, get_lang('NumberOfSessions'), false);
376
        $table->set_header(7, get_lang('Sessions'), false);
377
378
        if ($is_western_name_order) {
379
            $csv_header[] = array(
380
                get_lang('FirstName'),
381
                get_lang('LastName'),
382
                get_lang('TimeSpentOnThePlatform'),
383
                get_lang('LastConnexion'),
384
                get_lang('NbStudents'),
385
                get_lang('CountCours'),
386
                get_lang('NumberOfSessions')
387
            );
388
        } else {
389
            $csv_header[] = array(
390
                get_lang('LastName'),
391
                get_lang('FirstName'),
392
                get_lang('TimeSpentOnThePlatform'),
393
                get_lang('LastConnexion'),
394
                get_lang('NbStudents'),
395
                get_lang('CountCours'),
396
                get_lang('NumberOfSessions')
397
            );
398
        }
399
400
        $tbl_track_login = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
401
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
402
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
403
        $tbl_sessions = Database::get_main_table(TABLE_MAIN_SESSION);
404
405
        $sqlCoachs = "SELECT DISTINCT
406
                        scu.user_id as id_coach,
407
                        u.id as user_id,
408
                        lastname,
409
                        firstname,
410
                        MAX(login_date) as login_date
411
                        FROM $tbl_user u, $tbl_session_course_user scu, $tbl_track_login
412
                        WHERE
413
                            scu.user_id = u.id AND scu.status=2 AND login_user_id=u.id
414
                        GROUP BY user_id ";
415
416
        if (api_is_multiple_url_enabled()) {
417
            $tbl_session_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
418
            $access_url_id = api_get_current_access_url_id();
419
            if ($access_url_id != -1) {
420
                $sqlCoachs = "SELECT DISTINCT
421
                                    scu.user_id as id_coach,
422
                                    u.id as user_id,
423
                                    lastname,
424
                                    firstname,
425
                                    MAX(login_date) as login_date
426
                                FROM $tbl_user u,
427
                                $tbl_session_course_user scu,
428
                                $tbl_track_login ,
429
                                $tbl_session_rel_access_url session_rel_url
430
                                WHERE
431
                                    scu.user_id = u.id AND
432
                                    scu.status = 2 AND
433
                                    login_user_id = u.id AND
434
                                    access_url_id = $access_url_id AND
435
                                    session_rel_url.session_id = scu.session_id
436
                                GROUP BY u.id";
437
            }
438
        }
439
        if (!empty($order[$tracking_column])) {
440
            $sqlCoachs .= " ORDER BY ".$order[$tracking_column]." ".$tracking_direction;
441
        }
442
443
        $result_coaches = Database::query($sqlCoachs);
444
        $global_coaches = array();
445
        while ($coach = Database::fetch_array($result_coaches)) {
446
            $global_coaches[$coach['user_id']] = $coach;
447
        }
448
449
        $sql_session_coach = "SELECT session.id_coach, u.id as user_id, lastname, firstname, MAX(login_date) as login_date
450
                                FROM $tbl_user u , $tbl_sessions as session, $tbl_track_login
451
                                WHERE id_coach = u.id AND login_user_id = u.id
452
                                GROUP BY u.id
453
                                ORDER BY login_date $tracking_direction";
454
455 View Code Duplication
        if (api_is_multiple_url_enabled()) {
456
            $tbl_session_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
457
            $access_url_id = api_get_current_access_url_id();
458
            if ($access_url_id != -1) {
459
                $sql_session_coach = "SELECT session.id_coach, u.id as user_id, lastname, firstname, MAX(login_date) as login_date
460
					FROM $tbl_user u , $tbl_sessions as session, $tbl_track_login , $tbl_session_rel_access_url as session_rel_url
461
					WHERE
462
					    id_coach = u.id AND
463
					    login_user_id = u.id  AND
464
					    access_url_id = $access_url_id AND
465
					    session_rel_url.session_id = session.id
466
					GROUP BY  u.id
467
					ORDER BY login_date $tracking_direction";
468
            }
469
        }
470
471
        $result_sessions_coach = Database::query($sql_session_coach);
472
        //$total_no_coaches += Database::num_rows($result_sessions_coach);
473
        while ($coach = Database::fetch_array($result_sessions_coach)) {
474
            $global_coaches[$coach['user_id']] = $coach;
475
        }
476
477
        $all_datas = array();
478
        foreach ($global_coaches as $id_coach => $coaches) {
479
            $time_on_platform = api_time_to_hms(
480
                Tracking::get_time_spent_on_the_platform($coaches['user_id'])
481
            );
482
            $last_connection = Tracking::get_last_connection_date(
483
                $coaches['user_id']
484
            );
485
            $nb_students = count(
486
                Tracking::get_student_followed_by_coach($coaches['user_id'])
487
            );
488
            $nb_courses = count(
489
                Tracking::get_courses_followed_by_coach($coaches['user_id'])
490
            );
491
            $nb_sessions = count(
492
                Tracking::get_sessions_coached_by_user($coaches['user_id'])
493
            );
494
495
            $table_row = array();
496
            if ($is_western_name_order) {
497
                $table_row[] = $coaches['firstname'];
498
                $table_row[] = $coaches['lastname'];
499
            } else {
500
                $table_row[] = $coaches['lastname'];
501
                $table_row[] = $coaches['firstname'];
502
            }
503
            $table_row[] = $time_on_platform;
504
            $table_row[] = $last_connection;
505
            $table_row[] = $nb_students;
506
            $table_row[] = $nb_courses;
507
            $table_row[] = $nb_sessions;
508
            $table_row[] = '<a href="session.php?id_coach='.$coaches['user_id'].'">
509
                '.Display::return_icon('2rightarrow.png').'
510
            </a>';
511
            $all_datas[] = $table_row;
512
513
            if ($is_western_name_order) {
514
                $csv_content[] = array(
515
                    api_html_entity_decode($coaches['firstname'], ENT_QUOTES),
516
                    api_html_entity_decode($coaches['lastname'], ENT_QUOTES),
517
                    $time_on_platform,
518
                    $last_connection,
519
                    $nb_students,
520
                    $nb_courses,
521
                    $nb_sessions
522
                );
523
            } else {
524
                $csv_content[] = array(
525
                    api_html_entity_decode($coaches['lastname'], ENT_QUOTES),
526
                    api_html_entity_decode($coaches['firstname'], ENT_QUOTES),
527
                    $time_on_platform,
528
                    $last_connection,
529
                    $nb_students,
530
                    $nb_courses,
531
                    $nb_sessions
532
                );
533
            }
534
        }
535
536
        if ($tracking_column != 3) {
537
            if ($tracking_direction == 'DESC') {
538
                usort($all_datas, array('MySpace', 'rsort_users'));
539
            } else {
540
                usort($all_datas, array('MySpace', 'sort_users'));
541
            }
542
        }
543
544
        if ($export_csv && $tracking_column != 3) {
545
            usort($csv_content, 'sort_users');
546
        }
547
        if ($export_csv) {
548
            $csv_content = array_merge($csv_header, $csv_content);
549
        }
550
551
        foreach ($all_datas as $row) {
552
            $table -> addRow($row, 'align="right"');
553
        }
554
        $table -> display();
555
    }
556
557
    /**
558
     * @return mixed
559
     */
560
    public static function count_coaches()
561
    {
562
        global $total_no_coaches;
563
        return $total_no_coaches;
564
    }
565
566
    public static function sort_users($a, $b)
567
    {
568
        return api_strcmp(trim(api_strtolower($a[$_SESSION['tracking_column']])), trim(api_strtolower($b[$_SESSION['tracking_column']])));
569
    }
570
571
    public static function rsort_users($a, $b)
572
    {
573
        return api_strcmp(trim(api_strtolower($b[$_SESSION['tracking_column']])), trim(api_strtolower($a[$_SESSION['tracking_column']])));
574
    }
575
576
    /**
577
     * Display a sortable table that contains an overview off all the progress of the user in a session
578
     * @author César Perales <[email protected]>, Beeznest Team
579
     */
580
    public static function display_tracking_lp_progress_overview(
581
        $sessionId = '',
582
        $courseId = '',
583
        $date_from,
584
        $date_to
585
    ) {
586
        $course = api_get_course_info_by_id($courseId);
587
        /**
588
         * Column name
589
         * The order is important you need to check the $column variable in the model.ajax.php file
590
         */
591
        $columns = array(
592
            get_lang('Username'),
593
            get_lang('FirstName'),
594
            get_lang('LastName'),
595
        );
596
        //add lessons of course
597
        $lessons = LearnpathList::get_course_lessons($course['code'], $sessionId);
598
599
        //create columns array
600
        foreach ($lessons as $lesson_id => $lesson) {
601
            $columns[] = $lesson['name'];
602
        }
603
604
        $columns[] = get_lang('Total');
605
606
        /**
607
         * Column config
608
         */
609
        $column_model = array(
610
            array(
611
                'name' => 'username',
612
                'index' => 'username',
613
                'align' => 'left',
614
                'search' => 'true',
615
                'wrap_cell' => "true",
616
            ),
617
            array(
618
                'name' => 'firstname',
619
                'index' => 'firstname',
620
                'align' => 'left',
621
                'search' => 'true',
622
            ),
623
            array(
624
                'name' => 'lastname',
625
                'index' => 'lastname',
626
                'align' => 'left',
627
                'search' => 'true',
628
            ),
629
        );
630
631
        // Get dinamic column names
632
        foreach ($lessons as $lesson_id => $lesson) {
633
            $column_model[] = array(
634
                'name' => $lesson['id'],
635
                'index' => $lesson['id'],
636
                'align' => 'left',
637
                'search' => 'true',
638
            );
639
        }
640
641
        $column_model[] = array(
642
            'name' => 'total',
643
            'index' => 'total',
644
            'align' => 'left',
645
            'search' => 'true',
646
        );
647
648
        $action_links = '';
649
        // jqgrid will use this URL to do the selects
650
        $url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_session_lp_progress&session_id='.$sessionId.'&course_id='.$courseId.'&date_to='.$date_to.'&date_from='.$date_from;
651
652
        //Table Id
653
        $tableId = 'lpProgress';
654
655
        //Autowidth
656
        $extra_params['autowidth'] = 'true';
657
658
        //height auto
659
        $extra_params['height'] = 'auto';
660
661
        $table = Display::grid_js(
662
            $tableId,
663
            $url,
664
            $columns,
665
            $column_model,
666
            $extra_params,
667
            array(),
668
            $action_links,
669
            true
670
        );
671
672
        $return = '<script>$(function() {'.$table.
673
            'jQuery("#'.$tableId.'").jqGrid("navGrid","#'.$tableId.'_pager",{view:false, edit:false, add:false, del:false, search:false, excel:true});
674
                jQuery("#'.$tableId.'").jqGrid("navButtonAdd","#'.$tableId.'_pager",{
675
                       caption:"",
676
                       title:"' . get_lang('ExportExcel').'",
677
                       onClickButton : function () {
678
                           jQuery("#'.$tableId.'").jqGrid("excelExport",{"url":"'.$url.'&export_format=xls"});
679
                       }
680
                });
681
            });</script>';
682
        $return .= Display::grid_html($tableId);
683
        return $return;
684
    }
685
686
    /**
687
     * Display a sortable table that contains an overview off all the progress of the user in a session
688
     * @param   int $sessionId  The session ID
689
     * @param   int $courseId   The course ID
690
     * @param   int $exerciseId The quiz ID
691
     * @param   $date_from
692
     * @param   $date_to
693
     * @return  string  HTML array of results formatted for gridJS
694
     * @author César Perales <[email protected]>, Beeznest Team
695
     */
696
    public static function display_tracking_exercise_progress_overview(
697
        $sessionId = 0,
698
        $courseId = 0,
699
        $exerciseId = 0,
700
        $date_from = null,
701
        $date_to = null
702
    ) {
703
        $date_from = Security::remove_XSS($date_from);
704
        $date_to = Security::remove_XSS($date_to);
705
        /**
706
         * Column names
707
         * The column order is important. Check $column variable in the main/inc/ajax/model.ajax.php file
708
         */
709
        $columns = array(
710
            get_lang('Session'),
711
            get_lang('ExerciseId'),
712
            get_lang('ExerciseName'),
713
            get_lang('Username'),
714
            get_lang('LastName'),
715
            get_lang('FirstName'),
716
            get_lang('Time'),
717
            get_lang('QuestionId'),
718
            get_lang('QuestionTitle'),
719
            get_lang('WorkDescription'),
720
            get_lang('Answer'),
721
            get_lang('Correct')
722
        );
723
724
        /**
725
         * Column config
726
         */
727
        $column_model = array(
728
            array('name'=>'session', 'index'=>'session', 'align'=>'left', 'search' => 'true', 'wrap_cell' => "true"),
729
            array('name'=>'exercise_id', 'index'=>'exercise_id', 'align'=>'left', 'search' => 'true'),
730
            array('name'=>'quiz_title', 'index'=>'quiz_title', 'align'=>'left', 'search' => 'true'),
731
            array('name'=>'username', 'index'=>'username', 'align'=>'left', 'search' => 'true'),
732
            array('name'=>'lastname', 'index'=>'lastname', 'align'=>'left', 'search' => 'true'),
733
            array('name'=>'firstname', 'index'=>'firstname', 'align'=>'left', 'search' => 'true'),
734
            array('name'=>'time', 'index'=>'time', 'align'=>'left', 'search' => 'true', 'wrap_cell' => "true"),
735
            array('name'=>'question_id', 'index'=>'question_id', 'align'=>'left', 'search' => 'true'),
736
            array('name'=>'question', 'index'=>'question', 'align'=>'left', 'search' => 'true', 'wrap_cell' => "true"),
737
            array('name'=>'description', 'index'=>'description', 'align'=>'left', 'width' => '550', 'search' => 'true', 'wrap_cell' => "true"),
738
            array('name'=>'answer', 'index'=>'answer', 'align'=>'left', 'search' => 'true', 'wrap_cell' => "true"),
739
            array('name'=>'correct', 'index'=>'correct', 'align'=>'left', 'search' => 'true', 'wrap_cell' => "true"),
740
        );
741
        //get dynamic column names
742
743
        // jqgrid will use this URL to do the selects
744
        $url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_exercise_progress&session_id='.$sessionId.'&course_id='.$courseId.'&exercise_id='.$exerciseId.'&date_to='.$date_to.'&date_from='.$date_from;
745
746
        // Autowidth
747
        $extra_params['autowidth'] = 'true';
748
749
        // height auto
750
        $extra_params['height'] = 'auto';
751
752
        $tableId = 'exerciseProgressOverview';
753
        $table = Display::grid_js(
754
            $tableId,
755
            $url,
756
            $columns,
757
            $column_model,
758
            $extra_params,
759
            array(),
760
            '',
761
            true
762
        );
763
764
        $return = '<script>$(function() {'.$table.
765
            'jQuery("#'.$tableId.'").jqGrid("navGrid","#'.$tableId.'_pager",{view:false, edit:false, add:false, del:false, search:false, excel:true});
766
                jQuery("#'.$tableId.'").jqGrid("navButtonAdd","#'.$tableId.'_pager",{
767
                       caption:"",
768
                       title:"' . get_lang('ExportExcel').'",
769
                       onClickButton : function () {
770
                           jQuery("#'.$tableId.'").jqGrid("excelExport",{"url":"'.$url.'&export_format=xls"});
771
                       }
772
                });
773
            });</script>';
774
        $return .= Display::grid_html($tableId);
775
776
        return $return;
777
    }
778
779
    /**
780
     * Displays a form with all the additionally defined user fields of the profile
781
     * and give you the opportunity to include these in the CSV export
782
     *
783
     * @author Patrick Cool <[email protected]>, Ghent University, Belgium
784
     * @version 1.8.6
785
     * @since November 2008
786
     */
787
    public static function display_user_overview_export_options()
788
    {
789
        $message = '';
790
        $defaults = [];
791
        // include the user manager and formvalidator library
792
        if (isset($_GET['export']) && $_GET['export'] == 'options') {
793
            // get all the defined extra fields
794
            $extrafields = UserManager::get_extra_fields(
795
                0,
796
                50,
797
                5,
798
                'ASC',
799
                false,
800
                1
801
            );
802
803
            // creating the form with all the defined extra fields
804
            $form = new FormValidator(
805
                'exportextrafields',
806
                'post',
807
                api_get_self()."?view=".Security::remove_XSS($_GET['view']).'&display='.Security::remove_XSS($_GET['display']).'&export='.Security::remove_XSS($_GET['export'])
808
            );
809
810
            if (is_array($extrafields) && count($extrafields) > 0) {
811
                foreach ($extrafields as $key => $extra) {
812
                    $form->addElement('checkbox', 'extra_export_field'.$extra[0], '', $extra[3]);
813
                }
814
                $form->addButtonSave(get_lang('Ok'), 'submit');
815
816
                // setting the default values for the form that contains all the extra fields
817
                if (is_array($_SESSION['additional_export_fields'])) {
818
                    foreach ($_SESSION['additional_export_fields'] as $key => $value) {
819
                        $defaults['extra_export_field'.$value] = 1;
820
                    }
821
                }
822
                $form->setDefaults($defaults);
823
            } else {
824
                $form->addElement('html', Display::return_message(get_lang('ThereAreNotExtrafieldsAvailable'), 'warning'));
825
            }
826
827
            if ($form->validate()) {
828
                // exporting the form values
829
                $values = $form->exportValues();
830
831
                // re-initialising the session that contains the additional fields that need to be exported
832
                $_SESSION['additional_export_fields'] = array();
833
834
                // adding the fields that are checked to the session
835
                $message = '';
836
                foreach ($values as $field_ids => $value) {
837
                    if ($value == 1 && strstr($field_ids, 'extra_export_field')) {
838
                        $_SESSION['additional_export_fields'][] = str_replace('extra_export_field', '', $field_ids);
839
                    }
840
                }
841
842
                // adding the fields that will be also exported to a message string
843
                if (is_array($_SESSION['additional_export_fields'])) {
844 View Code Duplication
                    foreach ($_SESSION['additional_export_fields'] as $key => $extra_field_export) {
845
                        $message .= '<li>'.$extrafields[$extra_field_export][3].'</li>';
846
                    }
847
                }
848
849
                // Displaying a feedback message
850
                if (!empty($_SESSION['additional_export_fields'])) {
851
                    echo Display::return_message(get_lang('FollowingFieldsWillAlsoBeExported').': <br /><ul>'.$message.'</ul>', 'confirm', false);
852
                } else {
853
                    echo Display::return_message(
854
                        get_lang('NoAdditionalFieldsWillBeExported'),
855
                        'confirm',
856
                        false
857
                    );
858
                }
859
            } else {
860
                $form->display();
861
            }
862
863
        } else {
864
            if (!empty($_SESSION['additional_export_fields'])) {
865
                // get all the defined extra fields
866
                $extrafields = UserManager::get_extra_fields(0, 50, 5, 'ASC');
867
868 View Code Duplication
                foreach ($_SESSION['additional_export_fields'] as $key => $extra_field_export) {
869
                    $message .= '<li>'.$extrafields[$extra_field_export][3].'</li>';
870
                }
871
872
                echo Display::return_message(get_lang('FollowingFieldsWillAlsoBeExported').': <br /><ul>'.$message.'</ul>', 'normal', false);
873
            }
874
        }
875
    }
876
877
    /**
878
     * Display a sortable table that contains an overview of all the reporting progress of all courses
879
     */
880
    public static function display_tracking_course_overview()
881
    {
882
        $t_head = '<table style="width: 100%;border:0;padding:0;border-collapse:collapse;table-layout: fixed">';
883
        $t_head .= '<tr>';
884
        $t_head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('AvgTimeSpentInTheCourse'), 6, true).'</span></th>';
885
        $t_head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('AvgStudentsProgress'), 6, true).'</span></th>';
886
        $t_head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('AvgCourseScore'), 6, true).'</span></th>';
887
        $t_head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('TotalNumberOfMessages'), 6, true).'</span></th>';
888
        $t_head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('TotalNumberOfAssignments'), 6, true).'</span></th>';
889
        $t_head .= '<th width="105px" style="border-bottom:0"><span>'.get_lang('TotalExercisesScoreObtained').'</span></th>';
890
        $t_head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('TotalExercisesAnswered'), 6, true).'</span></th>';
891
        $t_head .= '<th style="padding:0;border-bottom:0;border-right:0;"><span>'.get_lang('LatestLogin').'</span></th>';
892
        $t_head .= '</tr></table>';
893
        $addparams = array('view' => 'admin', 'display' => 'courseoverview');
894
        $table = new SortableTable(
895
            'tracking_session_overview',
896
            array('MySpace', 'get_total_number_courses'),
897
            array('MySpace', 'get_course_data_tracking_overview'),
898
            1
899
        );
900
        $table->additional_parameters = $addparams;
901
902
        $table->set_header(0, '', false, null, array('style' => 'display: none'));
903
        $table->set_header(1, get_lang('Course'), true, array('style' => 'font-size:8pt'), array('style' => 'font-size:8pt'));
904
        $table->set_header(2, $t_head, false, array('style' => 'width:90%;border:0;padding:0;font-size:7.5pt;'), array('style' => 'width:90%;padding:0;font-size:7.5pt;'));
905
        $table->set_column_filter(2, array('MySpace', 'course_tracking_filter'));
906
        $table->display();
907
    }
908
909
    /**
910
     * Get the total number of courses
911
     *
912
     * @return integer Total number of courses
913
     */
914
    public static function get_total_number_courses()
915
    {
916
        return CourseManager::count_courses(api_get_current_access_url_id());
917
    }
918
919
    /**
920
     * Get data for the courses
921
     *
922
     * @param int $from Inferior limit
923
     * @param int $numberItems Number of items to select
924
     * @param string $column Column to order on
925
     * @param string $direction Order direction
926
     * @return array Results
927
     */
928
    public static function get_course_data_tracking_overview(
929
        $from,
930
        $numberItems,
931
        $column,
932
        $direction
933
    ) {
934
        $courses = CourseManager::get_courses_list(
935
            $from,
936
            $numberItems,
937
            $column,
938
            $direction,
939
             -1,
940
            '',
941
            api_get_current_access_url_id()
942
        );
943
944
        $list = [];
945
        foreach ($courses as $course) {
946
            $list[] = [
947
                '0' => $course['code'],
948
                'col0' => $course['code'],
949
                '1' => $course['title'],
950
                'col1' => $course['title']
951
            ];
952
        }
953
954
        return $list;
955
    }
956
957
    /**
958
     * Fills in course reporting data
959
     *
960
     * @param integer course code
961
     * @param array $url_params additional url parameters
962
     * @param array $row the row information (the other columns)
963
     * @return string html code
964
     */
965
    public static function course_tracking_filter($course_code, $url_params, $row)
966
    {
967
        $course_code = $row[0];
968
        $courseInfo = api_get_course_info($course_code);
969
        $courseId = $courseInfo['real_id'];
970
971
        // the table header
972
        $return = '<table class="data_table" style="width: 100%;border:0;padding:0;border-collapse:collapse;table-layout: fixed">';
973
974
        // database table definition
975
        $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
976
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
977
978
        // getting all the courses of the user
979
        $sql = "SELECT *
980
                FROM $tbl_user AS u
981
                INNER JOIN $tbl_course_rel_user AS cu
982
                ON cu.user_id = u.user_id
983
                WHERE cu.c_id = '".$courseId."'";
984
        $result = Database::query($sql);
985
        $time_spent = 0;
986
        $progress = 0;
987
        $nb_progress_lp = 0;
988
        $score = 0;
989
        $nb_score_lp = 0;
990
        $nb_messages = 0;
991
        $nb_assignments = 0;
992
        $last_login_date = false;
993
        $total_score_obtained = 0;
994
        $total_score_possible = 0;
995
        $total_questions_answered = 0;
996 View Code Duplication
        while ($row = Database::fetch_object($result)) {
997
            // get time spent in the course and session
998
            $time_spent += Tracking::get_time_spent_on_the_course(
999
                $row->user_id,
1000
                $courseInfo['real_id']
1001
            );
1002
            $progress_tmp = Tracking::get_avg_student_progress(
1003
                $row->user_id,
1004
                $course_code,
1005
                array(),
1006
                null,
1007
                true
1008
            );
1009
            $progress += $progress_tmp[0];
1010
            $nb_progress_lp += $progress_tmp[1];
1011
            $score_tmp = Tracking::get_avg_student_score(
1012
                $row->user_id,
1013
                $course_code,
1014
                array(),
1015
                null,
1016
                true
1017
            );
1018
            if (is_array($score_tmp)) {
1019
                $score += $score_tmp[0];
1020
                $nb_score_lp += $score_tmp[1];
1021
            }
1022
            $nb_messages += Tracking::count_student_messages(
1023
                $row->user_id,
1024
                $course_code
1025
            );
1026
            $nb_assignments += Tracking::count_student_assignments(
1027
                $row->user_id,
1028
                $course_code
1029
            );
1030
            $last_login_date_tmp = Tracking::get_last_connection_date_on_the_course(
1031
                $row->user_id,
1032
                $courseInfo,
1033
                null,
1034
                false
1035
            );
1036
            if ($last_login_date_tmp != false && $last_login_date == false) { // TODO: To be cleaned
1037
                $last_login_date = $last_login_date_tmp;
1038
            } else if ($last_login_date_tmp != false && $last_login_date != false) { // TODO: Repeated previous condition. To be cleaned.
1039
                // Find the max and assign it to first_login_date
1040
                if (strtotime($last_login_date_tmp) > strtotime($last_login_date)) {
1041
                    $last_login_date = $last_login_date_tmp;
1042
                }
1043
            }
1044
1045
            $exercise_results_tmp = self::exercises_results($row->user_id, $course_code);
1046
            $total_score_obtained += $exercise_results_tmp['score_obtained'];
1047
            $total_score_possible += $exercise_results_tmp['score_possible'];
1048
            $total_questions_answered += $exercise_results_tmp['questions_answered'];
1049
        }
1050 View Code Duplication
        if ($nb_progress_lp > 0) {
1051
            $avg_progress = round($progress / $nb_progress_lp, 2);
1052
        } else {
1053
            $avg_progress = 0;
1054
        }
1055 View Code Duplication
        if ($nb_score_lp > 0) {
1056
            $avg_score = round($score / $nb_score_lp, 2);
1057
        } else {
1058
            $avg_score = '-';
1059
        }
1060
        if ($last_login_date) {
1061
            $last_login_date = api_convert_and_format_date(
1062
                $last_login_date,
1063
                DATE_FORMAT_SHORT,
1064
                date_default_timezone_get()
1065
            );
1066
        } else {
1067
            $last_login_date = '-';
1068
        }
1069 View Code Duplication
        if ($total_score_possible > 0) {
1070
            $total_score_percentage = round($total_score_obtained / $total_score_possible * 100, 2);
1071
        } else {
1072
            $total_score_percentage = 0;
1073
        }
1074 View Code Duplication
        if ($total_score_percentage > 0) {
1075
            $total_score = $total_score_obtained.'/'.$total_score_possible.' ('.$total_score_percentage.' %)';
1076
        } else {
1077
            $total_score = '-';
1078
        }
1079
        $return .= '<tr>';
1080
        // time spent in the course
1081
        $return .= '    <td style="width:164px;">'.api_time_to_hms($time_spent).'</td>';
1082
        // student progress in course
1083
        $return .= '    <td>'.$avg_progress.'</td>';
1084
        // student score
1085
        $return .= '    <td>'.$avg_score.'</td>';
1086
        // student messages
1087
        $return .= '    <td>'.$nb_messages.'</td>';
1088
        // student assignments
1089
        $return .= '    <td>'.$nb_assignments.'</td>';
1090
        // student exercises results (obtained score, maximum score, number of exercises answered, score percentage)
1091
        $return .= '<td width="105px;">'.$total_score.'</td>';
1092
        $return .= '<td>'.$total_questions_answered.'</td>';
1093
        // last connection
1094
        $return .= '    <td>'.$last_login_date.'</td>';
1095
        $return .= '</tr>';
1096
        $return .= '</table>';
1097
        return $return;
1098
    }
1099
1100
    /**
1101
     * This function exports the table that we see in display_tracking_course_overview()
1102
     *
1103
     */
1104
    public static function export_tracking_course_overview()
1105
    {
1106
        // database table definition
1107
        $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1108
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
1109
1110
        // the values of the sortable table
1111
        if ($_GET['tracking_course_overview_page_nr']) {
1112
            $from = $_GET['tracking_course_overview_page_nr'];
1113
        } else {
1114
            $from = 0;
1115
        }
1116
        if ($_GET['tracking_course_overview_column']) {
1117
            $orderby = $_GET['tracking_course_overview_column'];
1118
        } else {
1119
            $orderby = 0;
1120
        }
1121
1122
        if ($_GET['tracking_course_overview_direction']) {
1123
            $direction = $_GET['tracking_course_overview_direction'];
1124
        } else {
1125
            $direction = 'ASC';
1126
        }
1127
1128
        $course_data = self::get_course_data_tracking_overview(
1129
            $from,
1130
            1000,
1131
            $orderby,
1132
            $direction
1133
        );
1134
1135
        $csv_content = array();
1136
1137
        // the first line of the csv file with the column headers
1138
        $csv_row = array();
1139
        $csv_row[] = get_lang('Course');
1140
        $csv_row[] = get_lang('AvgTimeSpentInTheCourse');
1141
        $csv_row[] = get_lang('AvgStudentsProgress');
1142
        $csv_row[] = get_lang('AvgCourseScore');
1143
        $csv_row[] = get_lang('TotalNumberOfMessages');
1144
        $csv_row[] = get_lang('TotalNumberOfAssignments');
1145
        $csv_row[] = get_lang('TotalExercisesScoreObtained');
1146
        $csv_row[] = get_lang('TotalExercisesScorePossible');
1147
        $csv_row[] = get_lang('TotalExercisesAnswered');
1148
        $csv_row[] = get_lang('TotalExercisesScorePercentage');
1149
        $csv_row[] = get_lang('LatestLogin');
1150
        $csv_content[] = $csv_row;
1151
1152
        // the other lines (the data)
1153
        foreach ($course_data as $key => $course) {
1154
            $course_code = $course[0];
1155
            $courseInfo = api_get_course_info($course_code);
1156
            $course_title = $courseInfo['title'];
1157
            $courseId = $courseInfo['real_id'];
1158
1159
            $csv_row = array();
1160
            $csv_row[] = $course_title;
1161
1162
            // getting all the courses of the session
1163
            $sql = "SELECT *
1164
                    FROM $tbl_user AS u
1165
                    INNER JOIN $tbl_course_rel_user AS cu
1166
                    ON cu.user_id = u.user_id
1167
                    WHERE cu.c_id = '".$courseId."'";
1168
            $result = Database::query($sql);
1169
            $time_spent = 0;
1170
            $progress = 0;
1171
            $nb_progress_lp = 0;
1172
            $score = 0;
1173
            $nb_score_lp = 0;
1174
            $nb_messages = 0;
1175
            $nb_assignments = 0;
1176
            $last_login_date = false;
1177
            $total_score_obtained = 0;
1178
            $total_score_possible = 0;
1179
            $total_questions_answered = 0;
1180 View Code Duplication
            while ($row = Database::fetch_object($result)) {
1181
                // get time spent in the course and session
1182
                $time_spent += Tracking::get_time_spent_on_the_course(
1183
                    $row->user_id,
1184
                    $courseId
1185
                );
1186
                $progress_tmp = Tracking::get_avg_student_progress(
1187
                    $row->user_id,
1188
                    $course_code,
1189
                    array(),
1190
                    null,
1191
                    true
1192
                );
1193
                $progress += $progress_tmp[0];
1194
                $nb_progress_lp += $progress_tmp[1];
1195
                $score_tmp = Tracking::get_avg_student_score(
1196
                    $row->user_id,
1197
                    $course_code,
1198
                    array(),
1199
                    null,
1200
                    true
1201
                );
1202
                if (is_array($score_tmp)) {
1203
                    $score += $score_tmp[0];
1204
                    $nb_score_lp += $score_tmp[1];
1205
                }
1206
                $nb_messages += Tracking::count_student_messages(
1207
                    $row->user_id,
1208
                    $course_code
1209
                );
1210
                $nb_assignments += Tracking::count_student_assignments(
1211
                    $row->user_id,
1212
                    $course_code
1213
                );
1214
1215
                $last_login_date_tmp = Tracking::get_last_connection_date_on_the_course(
1216
                    $row->user_id,
1217
                    $courseInfo,
1218
                    null,
1219
                    false
1220
                );
1221
                if ($last_login_date_tmp != false && $last_login_date == false) { // TODO: To be cleaned.
1222
                    $last_login_date = $last_login_date_tmp;
1223
                } else if ($last_login_date_tmp != false && $last_login_date == false) { // TODO: Repeated previous condition. To be cleaned.
1224
                    // Find the max and assign it to first_login_date
1225
                    if (strtotime($last_login_date_tmp) > strtotime($last_login_date)) {
1226
                        $last_login_date = $last_login_date_tmp;
1227
                    }
1228
                }
1229
1230
                $exercise_results_tmp = self::exercises_results($row->user_id, $course_code);
1231
                $total_score_obtained += $exercise_results_tmp['score_obtained'];
1232
                $total_score_possible += $exercise_results_tmp['score_possible'];
1233
                $total_questions_answered += $exercise_results_tmp['questions_answered'];
1234
            }
1235 View Code Duplication
            if ($nb_progress_lp > 0) {
1236
                $avg_progress = round($progress / $nb_progress_lp, 2);
1237
            } else {
1238
                $avg_progress = 0;
1239
            }
1240 View Code Duplication
            if ($nb_score_lp > 0) {
1241
                $avg_score = round($score / $nb_score_lp, 2);
1242
            } else {
1243
                $avg_score = '-';
1244
            }
1245
            if ($last_login_date) {
1246
                $last_login_date = api_convert_and_format_date(
1247
                    $last_login_date,
1248
                    DATE_FORMAT_SHORT,
1249
                    date_default_timezone_get()
1250
                );
1251
            } else {
1252
                $last_login_date = '-';
1253
            }
1254 View Code Duplication
            if ($total_score_possible > 0) {
1255
                $total_score_percentage = round($total_score_obtained / $total_score_possible * 100, 2);
1256
            } else {
1257
                $total_score_percentage = 0;
1258
            }
1259
            // time spent in the course
1260
            $csv_row[] = api_time_to_hms($time_spent);
1261
            // student progress in course
1262
            $csv_row[] = $avg_progress;
1263
            // student score
1264
            $csv_row[] = $avg_score;
1265
            // student messages
1266
            $csv_row[] = $nb_messages;
1267
            // student assignments
1268
            $csv_row[] = $nb_assignments;
1269
            // student exercises results (obtained score, maximum score, number of exercises answered, score percentage)
1270
            $csv_row[] = $total_score_obtained;
1271
            $csv_row[] = $total_score_possible;
1272
            $csv_row[] = $total_questions_answered;
1273
            $csv_row[] = $total_score_percentage;
1274
            // last connection
1275
            $csv_row[] = $last_login_date;
1276
            $csv_content[] = $csv_row;
1277
        }
1278
        Export::arrayToCsv($csv_content, 'reporting_course_overview');
1279
        exit;
1280
    }
1281
1282
    /**
1283
     * Display a sortable table that contains an overview of all the reporting
1284
     * progress of all sessions and all courses the user is subscribed to
1285
     * @author Guillaume Viguier <[email protected]>
1286
     */
1287
    public static function display_tracking_session_overview()
1288
    {
1289
        $t_head = '<table style="width: 100%;border:0;padding:0;border-collapse:collapse;table-layout: fixed">';
1290
        $t_head .= '<tr>';
1291
        $t_head .= '<th width="155px" style="border-left:0;border-bottom:0"><span>'.get_lang('Course').'</span></th>';
1292
        $t_head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('AvgTimeSpentInTheCourse'), 6, true).'</span></th>';
1293
        $t_head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('AvgStudentsProgress'), 6, true).'</span></th>';
1294
        $t_head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('AvgCourseScore'), 6, true).'</span></th>';
1295
        $t_head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('TotalNumberOfMessages'), 6, true).'</span></th>';
1296
        $t_head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('TotalNumberOfAssignments'), 6, true).'</span></th>';
1297
        $t_head .= '<th width="105px" style="border-bottom:0"><span>'.get_lang('TotalExercisesScoreObtained').'</span></th>';
1298
        $t_head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('TotalExercisesAnswered'), 6, true).'</span></th>';
1299
        $t_head .= '<th style="padding:0;border-bottom:0;border-right:0;"><span>'.get_lang('LatestLogin').'</span></th>';
1300
        $t_head .= '</tr></table>';
1301
1302
        $addparams = array('view' => 'admin', 'display' => 'sessionoverview');
1303
        $table = new SortableTable(
1304
            'tracking_session_overview',
1305
            array('MySpace', 'get_total_number_sessions'),
1306
            array('MySpace', 'get_session_data_tracking_overview'),
1307
            1
1308
        );
1309
        $table->additional_parameters = $addparams;
1310
1311
        $table->set_header(0, '', false, null, array('style' => 'display: none'));
1312
        $table->set_header(1, get_lang('Session'), true, array('style' => 'font-size:8pt'), array('style' => 'font-size:8pt'));
1313
        $table->set_header(2, $t_head, false, array('style' => 'width:90%;border:0;padding:0;font-size:7.5pt;'), array('style' => 'width:90%;padding:0;font-size:7.5pt;'));
1314
        $table->set_column_filter(2, array('MySpace', 'session_tracking_filter'));
1315
        $table->display();
1316
    }
1317
1318
    /**
1319
     * Get the total number of sessions
1320
     *
1321
     * @return integer Total number of sessions
1322
     */
1323
    public static function get_total_number_sessions()
1324
    {
1325
        return SessionManager::count_sessions(api_get_current_access_url_id());
1326
    }
1327
1328
    /**
1329
     * Get data for the sessions
1330
     *
1331
     * @param int $from Inferior limit
1332
     * @param int $numberItems Number of items to select
1333
     * @param string $column Column to order on
1334
     * @param string $direction Order direction
1335
     * @return array Results
1336
     */
1337
    public static function get_session_data_tracking_overview(
1338
        $from,
1339
        $numberItems,
1340
        $column,
1341
        $direction
1342
    ) {
1343
        $from = (int) $from;
1344
        $numberItems = (int) $numberItems;
1345
        $direction = Database::escape_string($direction);
1346
        $columnName = 'name';
1347
        if ($column === 1) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of $column (string) and 1 (integer) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
1348
            $columnName = 'id';
1349
        }
1350
1351
        $options = [
1352
            'order' => " $columnName $direction",
1353
            'limit' => " $from,$numberItems"
1354
        ];
1355
        $sessions = SessionManager::get_sessions_admin($options);
1356
        $list = [];
1357
        foreach ($sessions as $session) {
1358
            $list[] = [
1359
                '0' => $session['id'],
1360
                'col0' => $session['id'],
1361
                '1' => strip_tags($session['name']),
1362
                'col1' => strip_tags($session['name'])
1363
            ];
1364
        }
1365
1366
        return $list;
1367
    }
1368
1369
    /**
1370
     * Fills in session reporting data
1371
     *
1372
     * @param int $session_id the id of the user
1373
     * @param array $url_params additonal url parameters
1374
     * @param array $row the row information (the other columns)
1375
     * @return string html code
1376
     */
1377
    public static function session_tracking_filter($session_id, $url_params, $row)
1378
    {
1379
        $session_id = $row[0];
1380
        // the table header
1381
        $return = '<table class="data_table" style="width: 100%;border:0;padding:0;border-collapse:collapse;table-layout: fixed">';
1382
1383
        // database table definition
1384
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
1385
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
1386
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
1387
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
1388
1389
        // getting all the courses of the user
1390
        $sql = "SELECT * FROM $tbl_course AS c
1391
                INNER JOIN $tbl_session_rel_course AS sc
1392
                ON sc.c_id = c.id
1393
                WHERE sc.session_id = '".$session_id."'";
1394
        $result = Database::query($sql);
1395
        while ($row = Database::fetch_object($result)) {
1396
            $courseId = $row->c_id;
1397
            $courseInfo = api_get_course_info_by_id($courseId);
1398
            $return .= '<tr>';
1399
            // course code
1400
            $return .= '    <td width="157px" >'.$row->title.'</td>';
1401
            // get the users in the course
1402
            $sql = "SELECT u.user_id
1403
                    FROM $tbl_user AS u
1404
                    INNER JOIN $tbl_session_rel_course_rel_user AS scu
1405
                    ON u.user_id = scu.user_id
1406
                    WHERE scu.session_id = '".$session_id."' AND scu.c_id = '".$courseId."'";
1407
            $result_users = Database::query($sql);
1408
            $time_spent = 0;
1409
            $progress = 0;
1410
            $nb_progress_lp = 0;
1411
            $score = 0;
1412
            $nb_score_lp = 0;
1413
            $nb_messages = 0;
1414
            $nb_assignments = 0;
1415
            $last_login_date = false;
1416
            $total_score_obtained = 0;
1417
            $total_score_possible = 0;
1418
            $total_questions_answered = 0;
1419 View Code Duplication
            while ($row_user = Database::fetch_object($result_users)) {
1420
                // get time spent in the course and session
1421
                $time_spent += Tracking::get_time_spent_on_the_course($row_user->user_id, $courseId, $session_id);
1422
                $progress_tmp = Tracking::get_avg_student_progress($row_user->user_id, $row->code, array(), $session_id, true);
1423
                $progress += $progress_tmp[0];
1424
                $nb_progress_lp += $progress_tmp[1];
1425
                $score_tmp = Tracking::get_avg_student_score($row_user->user_id, $row->code, array(), $session_id, true);
1426
                if (is_array($score_tmp)) {
1427
                    $score += $score_tmp[0];
1428
                    $nb_score_lp += $score_tmp[1];
1429
                }
1430
                $nb_messages += Tracking::count_student_messages($row_user->user_id, $row->code, $session_id);
1431
                $nb_assignments += Tracking::count_student_assignments($row_user->user_id, $row->code, $session_id);
1432
                $last_login_date_tmp = Tracking::get_last_connection_date_on_the_course($row_user->user_id, $courseInfo, $session_id, false);
1433
                if ($last_login_date_tmp != false && $last_login_date == false) {
1434
                    // TODO: To be cleaned.
1435
                    $last_login_date = $last_login_date_tmp;
1436
                } else if ($last_login_date_tmp != false && $last_login_date != false) {
1437
                    // TODO: Repeated previous condition! To be cleaned.
1438
                    // Find the max and assign it to first_login_date
1439
                    if (strtotime($last_login_date_tmp) > strtotime($last_login_date)) {
1440
                        $last_login_date = $last_login_date_tmp;
1441
                    }
1442
                }
1443
1444
                $exercise_results_tmp = self::exercises_results($row_user->user_id, $row->code, $session_id);
1445
                $total_score_obtained += $exercise_results_tmp['score_obtained'];
1446
                $total_score_possible += $exercise_results_tmp['score_possible'];
1447
                $total_questions_answered += $exercise_results_tmp['questions_answered'];
1448
            }
1449 View Code Duplication
            if ($nb_progress_lp > 0) {
1450
                $avg_progress = round($progress / $nb_progress_lp, 2);
1451
            } else {
1452
                $avg_progress = 0;
1453
            }
1454 View Code Duplication
            if ($nb_score_lp > 0) {
1455
                $avg_score = round($score / $nb_score_lp, 2);
1456
            } else {
1457
                $avg_score = '-';
1458
            }
1459
            if ($last_login_date) {
1460
                $last_login_date = api_convert_and_format_date($last_login_date, DATE_FORMAT_SHORT, date_default_timezone_get());
1461
            } else {
1462
                $last_login_date = '-';
1463
            }
1464 View Code Duplication
            if ($total_score_possible > 0) {
1465
                $total_score_percentage = round($total_score_obtained / $total_score_possible * 100, 2);
1466
            } else {
1467
                $total_score_percentage = 0;
1468
            }
1469 View Code Duplication
            if ($total_score_percentage > 0) {
1470
                $total_score = $total_score_obtained.'/'.$total_score_possible.' ('.$total_score_percentage.' %)';
1471
            } else {
1472
                $total_score = '-';
1473
            }
1474
            // time spent in the course
1475
            $return .= '    <td><div>'.api_time_to_hms($time_spent).'</div></td>';
1476
            // student progress in course
1477
            $return .= '    <td><div>'.$avg_progress.'</div></td>';
1478
            // student score
1479
            $return .= '    <td><div>'.$avg_score.'</div></td>';
1480
            // student messages
1481
            $return .= '    <td><div>'.$nb_messages.'</div></td>';
1482
            // student assignments
1483
            $return .= '    <td><div>'.$nb_assignments.'</div></td>';
1484
            // student exercises results (obtained score, maximum score, number of exercises answered, score percentage)
1485
            $return .= '<td width="105px;">'.$total_score.'</td>';
1486
            $return .= '<td>'.$total_questions_answered.'</td>';
1487
            // last connection
1488
            $return .= '    <td><div>'.$last_login_date.'</div></td>';
1489
            $return .= '<tr>';
1490
        }
1491
        $return .= '</table>';
1492
        return $return;
1493
    }
1494
1495
    /**
1496
     * This function exports the table that we see in display_tracking_session_overview()
1497
     *
1498
     */
1499
    public static function export_tracking_session_overview()
1500
    {
1501
        // database table definition
1502
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
1503
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
1504
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
1505
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
1506
1507
        // the values of the sortable table
1508
        if ($_GET['tracking_session_overview_page_nr']) {
1509
            $from = $_GET['tracking_session_overview_page_nr'];
1510
        } else {
1511
            $from = 0;
1512
        }
1513
        if ($_GET['tracking_session_overview_column']) {
1514
            $orderby = $_GET['tracking_session_overview_column'];
1515
        } else {
1516
            $orderby = 0;
1517
        }
1518
1519
        if ($_GET['tracking_session_overview_direction']) {
1520
            $direction = $_GET['tracking_session_overview_direction'];
1521
        } else {
1522
            $direction = 'ASC';
1523
        }
1524
1525
        $session_data = self::get_session_data_tracking_overview($from, 1000, $orderby, $direction);
1526
1527
        $csv_content = array();
1528
1529
        // the first line of the csv file with the column headers
1530
        $csv_row = array();
1531
        $csv_row[] = get_lang('Session');
1532
        $csv_row[] = get_lang('Course');
1533
        $csv_row[] = get_lang('AvgTimeSpentInTheCourse');
1534
        $csv_row[] = get_lang('AvgStudentsProgress');
1535
        $csv_row[] = get_lang('AvgCourseScore');
1536
        $csv_row[] = get_lang('TotalNumberOfMessages');
1537
        $csv_row[] = get_lang('TotalNumberOfAssignments');
1538
        $csv_row[] = get_lang('TotalExercisesScoreObtained');
1539
        $csv_row[] = get_lang('TotalExercisesScorePossible');
1540
        $csv_row[] = get_lang('TotalExercisesAnswered');
1541
        $csv_row[] = get_lang('TotalExercisesScorePercentage');
1542
        $csv_row[] = get_lang('LatestLogin');
1543
        $csv_content[] = $csv_row;
1544
1545
        // the other lines (the data)
1546
        foreach ($session_data as $key => $session) {
1547
            $session_id = $session[0];
1548
            $session_title = $session[1];
1549
1550
            // getting all the courses of the session
1551
            $sql = "SELECT * FROM $tbl_course AS c
1552
                    INNER JOIN $tbl_session_rel_course AS sc
1553
                    ON sc.c_id = c.id
1554
                    WHERE sc.session_id = '".$session_id."';";
1555
            $result = Database::query($sql);
1556
            while ($row = Database::fetch_object($result)) {
1557
                $courseId = $row->c_id;
1558
                $courseInfo = api_get_course_info_by_id($courseId);
1559
                $csv_row = array();
1560
                $csv_row[] = $session_title;
1561
                $csv_row[] = $row->title;
1562
                // get the users in the course
1563
                $sql = "SELECT scu.user_id
1564
                        FROM $tbl_user AS u
1565
                        INNER JOIN $tbl_session_rel_course_rel_user AS scu
1566
                        ON u.user_id = scu.user_id
1567
                        WHERE scu.session_id = '".$session_id."' AND scu.c_id = '".$courseId."'";
1568
                $result_users = Database::query($sql);
1569
                $time_spent = 0;
1570
                $progress = 0;
1571
                $nb_progress_lp = 0;
1572
                $score = 0;
1573
                $nb_score_lp = 0;
1574
                $nb_messages = 0;
1575
                $nb_assignments = 0;
1576
                $last_login_date = false;
1577
                $total_score_obtained = 0;
1578
                $total_score_possible = 0;
1579
                $total_questions_answered = 0;
1580 View Code Duplication
                while ($row_user = Database::fetch_object($result_users)) {
1581
                    // get time spent in the course and session
1582
                    $time_spent += Tracking::get_time_spent_on_the_course($row_user->user_id, $courseId, $session_id);
1583
                    $progress_tmp = Tracking::get_avg_student_progress($row_user->user_id, $row->code, array(), $session_id, true);
1584
                    $progress += $progress_tmp[0];
1585
                    $nb_progress_lp += $progress_tmp[1];
1586
                    $score_tmp = Tracking::get_avg_student_score($row_user->user_id, $row->code, array(), $session_id, true);
1587
                    if (is_array($score_tmp)) {
1588
                        $score += $score_tmp[0];
1589
                        $nb_score_lp += $score_tmp[1];
1590
                    }
1591
                    $nb_messages += Tracking::count_student_messages(
1592
                        $row_user->user_id,
1593
                        $row->code,
1594
                        $session_id
1595
                    );
1596
1597
                    $nb_assignments += Tracking::count_student_assignments(
1598
                        $row_user->user_id,
1599
                        $row->code,
1600
                        $session_id
1601
                    );
1602
1603
                    $last_login_date_tmp = Tracking:: get_last_connection_date_on_the_course(
1604
                        $row_user->user_id,
1605
                        $courseInfo,
1606
                        $session_id,
1607
                        false
1608
                    );
1609
                    if ($last_login_date_tmp != false && $last_login_date == false) { // TODO: To be cleaned.
1610
                        $last_login_date = $last_login_date_tmp;
1611
                    } else if ($last_login_date_tmp != false && $last_login_date == false) { // TODO: Repeated previous condition. To be cleaned.
1612
                        // Find the max and assign it to first_login_date
1613
                        if (strtotime($last_login_date_tmp) > strtotime($last_login_date)) {
1614
                            $last_login_date = $last_login_date_tmp;
1615
                        }
1616
                    }
1617
1618
                    $exercise_results_tmp = self::exercises_results($row_user->user_id, $row->code, $session_id);
1619
                    $total_score_obtained += $exercise_results_tmp['score_obtained'];
1620
                    $total_score_possible += $exercise_results_tmp['score_possible'];
1621
                    $total_questions_answered += $exercise_results_tmp['questions_answered'];
1622
                }
1623 View Code Duplication
                if ($nb_progress_lp > 0) {
1624
                    $avg_progress = round($progress / $nb_progress_lp, 2);
1625
                } else {
1626
                    $avg_progress = 0;
1627
                }
1628 View Code Duplication
                if ($nb_score_lp > 0) {
1629
                    $avg_score = round($score / $nb_score_lp, 2);
1630
                } else {
1631
                    $avg_score = '-';
1632
                }
1633
                if ($last_login_date) {
1634
                    $last_login_date = api_convert_and_format_date($last_login_date, DATE_FORMAT_SHORT, date_default_timezone_get());
1635
                } else {
1636
                    $last_login_date = '-';
1637
                }
1638 View Code Duplication
                if ($total_score_possible > 0) {
1639
                    $total_score_percentage = round($total_score_obtained / $total_score_possible * 100, 2);
1640
                } else {
1641
                    $total_score_percentage = 0;
1642
                }
1643 View Code Duplication
                if ($total_score_percentage > 0) {
1644
                    $total_score = $total_score_obtained.'/'.$total_score_possible.' ('.$total_score_percentage.' %)';
1645
                } else {
1646
                    $total_score = '-';
1647
                }
1648
                // time spent in the course
1649
                $csv_row[] = api_time_to_hms($time_spent);
1650
                // student progress in course
1651
                $csv_row[] = $avg_progress;
1652
                // student score
1653
                $csv_row[] = $avg_score;
1654
                // student messages
1655
                $csv_row[] = $nb_messages;
1656
                // student assignments
1657
                $csv_row[] = $nb_assignments;
1658
                // student exercises results (obtained score, maximum score, number of exercises answered, score percentage)
1659
                $csv_row[] = $total_score_obtained;
1660
                $csv_row[] = $total_score_possible;
1661
                $csv_row[] = $total_questions_answered;
1662
                $csv_row[] = $total_score_percentage;
1663
                // last connection
1664
                $csv_row[] = $last_login_date;
1665
                $csv_content[] = $csv_row;
1666
            }
1667
        }
1668
        Export::arrayToCsv($csv_content, 'reporting_session_overview');
1669
        exit;
1670
    }
1671
1672
    /**
1673
     * Get general information about the exercise performance of the user
1674
     * the total obtained score (all the score on all the questions)
1675
     * the maximum score that could be obtained
1676
     * the number of questions answered
1677
     * the success percentage
1678
     * @param integer $user_id the id of the user
1679
     * @param string $course_code the course code
1680
     * @return array
1681
     * @author Patrick Cool <[email protected]>, Ghent University, Belgium
1682
     * @version Dokeos 1.8.6
1683
     * @since November 2008
1684
     */
1685
    public static function exercises_results($user_id, $course_code, $session_id = false)
1686
    {
1687
        $courseId = api_get_course_int_id($course_code);
1688
        $sql = 'SELECT exe_result, exe_weighting
1689
                FROM '.Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES)."
1690
                WHERE 
1691
                    c_id = ' . $courseId . ' AND 
1692
                    exe_user_id = '".intval($user_id)."'";
1693
        if ($session_id !== false) {
1694
            $sql .= " AND session_id = '".$session_id."' ";
1695
        }
1696
        $result = Database::query($sql);
1697
        $score_obtained = 0;
1698
        $score_possible = 0;
1699
        $questions_answered = 0;
1700
        while ($row = Database::fetch_array($result)) {
1701
            $score_obtained += $row['exe_result'];
1702
            $score_possible += $row['exe_weighting'];
1703
            $questions_answered++;
1704
        }
1705
1706
        if ($score_possible != 0) {
1707
            $percentage = round(($score_obtained / $score_possible * 100), 2);
1708
        } else {
1709
            $percentage = null;
1710
        }
1711
1712
        return array(
1713
            'score_obtained' => $score_obtained,
1714
            'score_possible' => $score_possible,
1715
            'questions_answered' => $questions_answered,
1716
            'percentage' => $percentage
1717
        );
1718
    }
1719
1720
    /**
1721
     * This function exports the table that we see in display_tracking_user_overview()
1722
     *
1723
     * @author Patrick Cool <[email protected]>, Ghent University, Belgium
1724
     * @version Dokeos 1.8.6
1725
     * @since October 2008
1726
     */
1727
    public static function export_tracking_user_overview()
1728
    {
1729
        // database table definitions
1730
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1731
        $is_western_name_order = api_is_western_name_order(PERSON_NAME_DATA_EXPORT);
1732
1733
        // the values of the sortable table
1734
        if ($_GET['tracking_user_overview_page_nr']) {
1735
            $from = $_GET['tracking_user_overview_page_nr'];
1736
        } else {
1737
            $from = 0;
1738
        }
1739
        if ($_GET['tracking_user_overview_column']) {
1740
            $orderby = $_GET['tracking_user_overview_column'];
1741
        } else {
1742
            $orderby = 0;
1743
        }
1744
        if ($is_western_name_order != api_is_western_name_order() && ($orderby == 1 || $orderby == 2)) {
1745
            // Swapping the sorting column if name order for export is different than the common name order.
1746
            $orderby = 3 - $orderby;
1747
        }
1748
        if ($_GET['tracking_user_overview_direction']) {
1749
            $direction = $_GET['tracking_user_overview_direction'];
1750
        } else {
1751
            $direction = 'ASC';
1752
        }
1753
1754
        $user_data = self::get_user_data_tracking_overview(
1755
            $from,
1756
            1000,
1757
            $orderby,
1758
            $direction
1759
        );
1760
1761
        // the first line of the csv file with the column headers
1762
        $csv_row = array();
1763
        $csv_row[] = get_lang('OfficialCode');
1764 View Code Duplication
        if ($is_western_name_order) {
1765
            $csv_row[] = get_lang('FirstName', '');
1766
            $csv_row[] = get_lang('LastName', '');
1767
        } else {
1768
            $csv_row[] = get_lang('LastName', '');
1769
            $csv_row[] = get_lang('FirstName', '');
1770
        }
1771
        $csv_row[] = get_lang('LoginName');
1772
        $csv_row[] = get_lang('CourseCode');
1773
        // the additional user defined fields (only those that were selected to be exported)
1774
1775
        $fields = UserManager::get_extra_fields(0, 50, 5, 'ASC');
1776
1777
        if (is_array($_SESSION['additional_export_fields'])) {
1778
            foreach ($_SESSION['additional_export_fields'] as $key => $extra_field_export) {
1779
                $csv_row[] = $fields[$extra_field_export][3];
1780
                $field_names_to_be_exported[] = 'extra_'.$fields[$extra_field_export][1];
1781
            }
1782
        }
1783
        $csv_row[] = get_lang('AvgTimeSpentInTheCourse', '');
1784
        $csv_row[] = get_lang('AvgStudentsProgress', '');
1785
        $csv_row[] = get_lang('AvgCourseScore', '');
1786
        $csv_row[] = get_lang('AvgExercisesScore', '');
1787
        $csv_row[] = get_lang('AvgMessages', '');
1788
        $csv_row[] = get_lang('AvgAssignments', '');
1789
        $csv_row[] = get_lang('TotalExercisesScoreObtained', '');
1790
        $csv_row[] = get_lang('TotalExercisesScorePossible', '');
1791
        $csv_row[] = get_lang('TotalExercisesAnswered', '');
1792
        $csv_row[] = get_lang('TotalExercisesScorePercentage', '');
1793
        $csv_row[] = get_lang('FirstLogin', '');
1794
        $csv_row[] = get_lang('LatestLogin', '');
1795
        $csv_content[] = $csv_row;
1796
1797
        // the other lines (the data)
1798
        foreach ($user_data as $key => $user) {
1799
            // getting all the courses of the user
1800
            $sql = "SELECT * FROM $tbl_course_user
1801
                    WHERE user_id = '".intval($user[4])."' AND relation_type<>".COURSE_RELATION_TYPE_RRHH." ";
1802
            $result = Database::query($sql);
1803
            while ($row = Database::fetch_row($result)) {
1804
                $courseInfo = api_get_course_info($row['course_code']);
1805
                $courseId = $courseInfo['real_id'];
1806
1807
                $csv_row = array();
1808
                // user official code
1809
                $csv_row[] = $user[0];
1810
                // user first|last name
1811
                $csv_row[] = $user[1];
1812
                // user last|first name
1813
                $csv_row[] = $user[2];
1814
                // user login name
1815
                $csv_row[] = $user[3];
1816
                // course code
1817
                $csv_row[] = $row[0];
1818
                // the additional defined user fields
1819
                $extra_fields = self::get_user_overview_export_extra_fields($user[4]);
1820
1821
                if (is_array($field_names_to_be_exported)) {
1822
                    foreach ($field_names_to_be_exported as $key => $extra_field_export) {
1823
                        $csv_row[] = $extra_fields[$extra_field_export];
1824
                    }
1825
                }
1826
                // time spent in the course
1827
                $csv_row[] = api_time_to_hms(Tracking::get_time_spent_on_the_course($user[4], $courseId));
1828
                // student progress in course
1829
                $csv_row[] = round(Tracking::get_avg_student_progress($user[4], $row[0]), 2);
1830
                // student score
1831
                $csv_row[] = round(Tracking::get_avg_student_score($user[4], $row[0]), 2);
1832
                // student tes score
1833
                $csv_row[] = round(Tracking::get_avg_student_exercise_score($user[4], $row[0]), 2);
1834
                // student messages
1835
                $csv_row[] = Tracking::count_student_messages($user[4], $row[0]);
1836
                // student assignments
1837
                $csv_row[] = Tracking::count_student_assignments($user[4], $row[0]);
1838
                // student exercises results
1839
                $exercises_results = self::exercises_results($user[4], $row[0]);
1840
                $csv_row[] = $exercises_results['score_obtained'];
1841
                $csv_row[] = $exercises_results['score_possible'];
1842
                $csv_row[] = $exercises_results['questions_answered'];
1843
                $csv_row[] = $exercises_results['percentage'];
1844
                // first connection
1845
                $csv_row[] = Tracking::get_first_connection_date_on_the_course($user[4], $courseId);
1846
                // last connection
1847
                $csv_row[] = strip_tags(Tracking::get_last_connection_date_on_the_course($user[4], $courseInfo));
1848
1849
                $csv_content[] = $csv_row;
1850
            }
1851
        }
1852
        Export::arrayToCsv($csv_content, 'reporting_user_overview');
1853
        exit;
1854
    }
1855
1856
    /**
1857
     * Get data for courses list in sortable with pagination
1858
     * @return array
1859
     */
1860
    public static function get_course_data($from, $number_of_items, $column, $direction)
1861
    {
1862
        global $courses, $csv_content, $charset, $session_id;
1863
1864
        // definition database tables
1865
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
1866
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
1867
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
1868
1869
        $course_data = array();
1870
        $courses_code = array_keys($courses);
1871
1872
        foreach ($courses_code as &$code) {
1873
            $code = "'$code'";
1874
        }
1875
1876
        // get all courses with limit
1877
        $sql = "SELECT course.code as col1, course.title as col2
1878
                FROM $tbl_course course
1879
                WHERE course.code IN (".implode(',', $courses_code).")";
1880
1881
        if (!in_array($direction, array('ASC', 'DESC'))) $direction = 'ASC';
1882
1883
        $column = intval($column);
1884
        $from = intval($from);
1885
        $number_of_items = intval($number_of_items);
1886
        $sql .= " ORDER BY col$column $direction ";
1887
        $sql .= " LIMIT $from,$number_of_items";
1888
1889
        $res = Database::query($sql);
1890
        while ($row_course = Database::fetch_row($res)) {
1891
            $course_code = $row_course[0];
1892
            $courseInfo = api_get_course_info($course_code);
1893
            $courseId = $courseInfo['real_id'];
1894
            $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;
1895
1896
            // students directly subscribed to the course
1897
            if (empty($session_id)) {
1898
                $sql = "SELECT user_id
1899
                        FROM $tbl_course_user as course_rel_user
1900
                        WHERE
1901
                            course_rel_user.status='5' AND
1902
                            course_rel_user.c_id = '$courseId'";
1903
            } else {
1904
                $sql = "SELECT user_id FROM $tbl_session_course_user srcu
1905
                        WHERE
1906
                            c_id = '$courseId' AND
1907
                            session_id = '$session_id' AND
1908
                            status<>2";
1909
            }
1910
            $rs = Database::query($sql);
1911
            $users = array();
1912
            while ($row = Database::fetch_array($rs)) {
1913
                $users[] = $row['user_id'];
1914
            }
1915
1916
            if (count($users) > 0) {
1917
                $nb_students_in_course = count($users);
1918
                $avg_assignments_in_course = Tracking::count_student_assignments($users, $course_code, $session_id);
1919
                $avg_messages_in_course = Tracking::count_student_messages($users, $course_code, $session_id);
1920
                $avg_progress_in_course = Tracking::get_avg_student_progress($users, $course_code, array(), $session_id);
1921
                $avg_score_in_course = Tracking::get_avg_student_score($users, $course_code, array(), $session_id);
1922
                $avg_score_in_exercise = Tracking::get_avg_student_exercise_score($users, $course_code, 0, $session_id);
1923
                $avg_time_spent_in_course = Tracking::get_time_spent_on_the_course($users, $courseInfo['real_id'], $session_id);
1924
1925
                $avg_progress_in_course = round($avg_progress_in_course / $nb_students_in_course, 2);
1926
                if (is_numeric($avg_score_in_course)) {
1927
                    $avg_score_in_course = round($avg_score_in_course / $nb_students_in_course, 2);
1928
                }
1929
                $avg_time_spent_in_course = api_time_to_hms($avg_time_spent_in_course / $nb_students_in_course);
1930
            } else {
1931
                $avg_time_spent_in_course = null;
1932
                $avg_progress_in_course = null;
1933
                $avg_score_in_course = null;
1934
                $avg_score_in_exercise = null;
1935
                $avg_messages_in_course = null;
1936
                $avg_assignments_in_course = null;
1937
            }
1938
            $table_row = array();
1939
            $table_row[] = $row_course[1];
1940
            $table_row[] = $nb_students_in_course;
1941
            $table_row[] = $avg_time_spent_in_course;
1942
            $table_row[] = is_null($avg_progress_in_course) ? '' : $avg_progress_in_course.'%';
1943
            $table_row[] = is_null($avg_score_in_course) ? '' : $avg_score_in_course.'%';
1944
            $table_row[] = is_null($avg_score_in_exercise) ? '' : $avg_score_in_exercise.'%';
1945
            $table_row[] = $avg_messages_in_course;
1946
            $table_row[] = $avg_assignments_in_course;
1947
1948
            //set the "from" value to know if I access the Reporting by the chamilo tab or the course link
1949
            $table_row[] = '<center><a href="../../tracking/courseLog.php?cidReq='.$course_code.'&from=myspace&id_session='.$session_id.'">
1950
                             '.Display::return_icon('2rightarrow.png').'
1951
                             </a>
1952
                            </center>';
1953
            $csv_content[] = array(
1954
                api_html_entity_decode($row_course[1], ENT_QUOTES, $charset),
1955
                $nb_students_in_course,
1956
                $avg_time_spent_in_course,
1957
                is_null($avg_progress_in_course) ? null : $avg_progress_in_course.'%',
1958
                is_null($avg_score_in_course) ? null : is_numeric($avg_score_in_course) ? $avg_score_in_course.'%' : $avg_score_in_course,
1959
                is_null($avg_score_in_exercise) ? null : $avg_score_in_exercise.'%',
1960
                $avg_messages_in_course,
1961
                $avg_assignments_in_course,
1962
            );
1963
            $course_data[] = $table_row;
1964
        }
1965
        return $course_data;
1966
    }
1967
1968
    /**
1969
     * Get the number of users of the platform
1970
     *
1971
     * @return integer
1972
     *
1973
     */
1974
    public static function get_number_of_users_tracking_overview()
1975
    {
1976
        return UserManager::get_number_of_users(0, api_get_current_access_url_id());
1977
    }
1978
1979
    /**
1980
     * Get all the data for the sortable table of the reporting progress of
1981
     * all users and all the courses the user is subscribed to.
1982
     *
1983
     * @param int $from
1984
     * @param int $numberItems
1985
     * @param int $column
1986
     * @param string $direction
1987
     * @return array
1988
     */
1989
    public static function get_user_data_tracking_overview($from, $numberItems, $column, $direction)
1990
    {
1991
        $isWestern = api_is_western_name_order();
1992
        switch ($column) {
1993
            case '0':
1994
                $column = 'official_code';
1995
                break;
1996
            case '1':
1997
                $column = $isWestern ? 'firstname' : 'lastname';
1998
                break;
1999
            case '2':
2000
                $column = $isWestern ? 'lastname' : 'firstname';
2001
                break;
2002
            case '3':
2003
                $column = 'username';
2004
                break;
2005
            case '4':
2006
                $column = 'username';
2007
                break;
2008
        }
2009
2010
        $order = [
2011
            "$column $direction"
2012
        ];
2013
        $userList = UserManager::get_user_list([], $order, $from, $numberItems);
2014
        $return = [];
2015
        foreach ($userList as $user) {
2016
            $firstPosition = $user['lastname'];
2017
            $secondPosition = $user['firstname'];
2018
            if ($isWestern) {
2019
                $firstPosition = $user['firstname'];
2020
                $secondPosition = $user['lastname'];
2021
            }
2022
            $return[] = [
2023
                '0' => $user['official_code'],
2024
                'col0' => $user['official_code'],
2025
                '1' => $firstPosition,
2026
                'col1' => $firstPosition,
2027
                '2' => $secondPosition,
2028
                'col2' => $secondPosition,
2029
                '3' => $user['username'],
2030
                'col3' => $user['username'],
2031
                '4' => $user['user_id'],
2032
                'col4' => $user['user_id']
2033
            ];
2034
        }
2035
2036
        return $return;
2037
    }
2038
2039
    /**
2040
     * Get all information that the user with user_id = $user_data has
2041
     * entered in the additionally defined profile fields
2042
     * @param integer $user_id the id of the user
2043
     * @return array
2044
     * @author Patrick Cool <[email protected]>, Ghent University, Belgium
2045
     * @version Dokeos 1.8.6
2046
     * @since November 2008
2047
     */
2048
    public static function get_user_overview_export_extra_fields($user_id)
2049
    {
2050
        // include the user manager
2051
        $extra_data = UserManager::get_extra_user_data($user_id, true);
2052
        return $extra_data;
2053
    }
2054
2055
    /**
2056
     * Checks if a username exist in the DB otherwise it create a "double"
2057
     * i.e. if we look into for jmontoya but the user's name already exist we create the user jmontoya2
2058
     * the return array will be array(username=>'jmontoya', sufix='2')
2059
     * @param string firstname
2060
     * @param string lastname
2061
     * @param string username
2062
     * @return array with the username, the sufix
2063
     * @author Julio Montoya Armas
2064
     */
2065
    public static function make_username($firstname, $lastname, $username, $language = null, $encoding = null)
2066
    {
2067
        // if username exist
2068
        if (!UserManager::is_username_available($username) || empty($username)) {
2069
            $i = 0;
2070
            while (1) {
2071
                if ($i == 0) {
2072
                    $sufix = '';
2073
                } else {
2074
                    $sufix = $i;
2075
                }
2076
                $desired_username = UserManager::create_username(
2077
                    $firstname,
2078
                    $lastname,
2079
                    $language,
2080
                    $encoding
2081
                );
2082
                if (UserManager::is_username_available($desired_username.$sufix)) {
2083
                    break;
2084
                } else {
2085
                    $i++;
2086
                }
2087
            }
2088
            $username_array = array('username' => $desired_username, 'sufix' => $sufix);
2089
            return $username_array;
2090
        } else {
2091
            $username_array = array('username' => $username, 'sufix' => '');
2092
            return $username_array;
2093
        }
2094
    }
2095
2096
    /**
2097
     * Checks if there are repeted users in a given array
2098
     * @param  array $usernames list of the usernames in the uploaded file
2099
     * @param  array $user_array $user_array['username'] and $user_array['sufix'] where sufix is the number part in a login i.e -> jmontoya2
2100
     * @return array with the $usernames array and the $user_array array
2101
     * @author Julio Montoya
2102
     */
2103
    public static function check_user_in_array($usernames, $user_array)
2104
    {
2105
        $user_list = array_keys($usernames);
2106
        $username = $user_array['username'].$user_array['sufix'];
2107
2108
        if (in_array($username, $user_list)) {
2109
            $user_array['sufix'] += $usernames[$username];
2110
            $usernames[$username]++;
2111
        } else {
2112
            $usernames[$username] = 1;
2113
        }
2114
        $result_array = array($usernames, $user_array);
2115
        return $result_array;
2116
    }
2117
2118
    /**
2119
     * Checks whether a username has been already subscribed in a session.
2120
     * @param string $username a given username
2121
     * @param array $course_list the array with the course list id
2122
     * @param int $id_session the session id
2123
     * @return int 0 if the user is not subscribed otherwise it returns the user_id of the given username
2124
     * @author Julio Montoya
2125
     */
2126
    public static function user_available_in_session($username, $course_list, $id_session)
2127
    {
2128
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
2129
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2130
        $id_session = intval($id_session);
2131
        $username = Database::escape_string($username);
2132
        foreach ($course_list as $courseId) {
2133
            $courseId = intval($courseId);
2134
            $sql = " SELECT u.user_id FROM $tbl_session_rel_course_rel_user rel
2135
                     INNER JOIN $table_user u
2136
                     ON (rel.user_id = u.user_id)
2137
                     WHERE
2138
                        rel.session_id='$id_session' AND
2139
                        u.status='5' AND
2140
                        u.username ='$username' AND
2141
                        rel.c_id='$courseId'";
2142
            $rs = Database::query($sql);
2143
            if (Database::num_rows($rs) > 0) {
2144
                return Database::result($rs, 0, 0);
2145
            } else {
2146
                return 0;
2147
            }
2148
        }
2149
        return 0;
2150
    }
2151
2152
    /**
2153
     * This function checks whether some users in the uploaded file
2154
     * repeated and creates unique usernames if necesary.
2155
     * A case: Within the file there is an user repeted twice (Julio Montoya / Julio Montoya)
2156
     * and the username fields are empty.
2157
     * Then, this function would create unique usernames based on the first and the last name.
2158
     * Two users wiould be created - jmontoya and jmontoya2.
2159
     * Of course, if in the database there is a user with the name jmontoya,
2160
     * the newly created two users registered would be jmontoya2 and jmontoya3.
2161
     * @param $users list of users
2162
     * @return array
2163
     * @author Julio Montoya Armas
2164
     */
2165
    function check_all_usernames($users, $course_list, $id_session)
2166
    {
2167
        $table_user = Database::get_main_table(TABLE_MAIN_USER);
2168
        $usernames = array();
2169
        $new_users = array();
2170
        foreach ($users as $index => $user) {
2171
            $desired_username = array();
2172
            if (empty($user['UserName'])) {
2173
                $desired_username = self::make_username($user['FirstName'], $user['LastName'], '');
2174
                $pre_username = $desired_username['username'].$desired_username['sufix'];
2175
                $user['UserName'] = $pre_username;
2176
                $user['create'] = '1';
2177
            } else {
2178
                if (UserManager::is_username_available($user['UserName'])) {
2179
                    $desired_username = self::make_username($user['FirstName'], $user['LastName'], $user['UserName']);
2180
                    $user['UserName'] = $desired_username['username'].$desired_username['sufix'];
2181
                    $user['create'] = '1';
2182 View Code Duplication
                } else {
2183
                    $is_session_avail = self::user_available_in_session($user['UserName'], $course_list, $id_session);
2184
                    if ($is_session_avail == 0) {
2185
                        $user_name = $user['UserName'];
2186
                        $sql_select = "SELECT user_id FROM $table_user WHERE username ='$user_name' ";
2187
                        $rs = Database::query($sql_select);
2188
                        $user['create'] = Database::result($rs, 0, 0); // This should be the ID because the user exists.
2189
                    } else {
2190
                        $user['create'] = $is_session_avail;
2191
                    }
2192
                }
2193
            }
2194
            // Usernames is the current list of users in the file.
2195
            $result_array = self::check_user_in_array($usernames, $desired_username);
2196
            $usernames = $result_array[0];
2197
            $desired_username = $result_array[1];
2198
            $user['UserName'] = $desired_username['username'].$desired_username['sufix'];
2199
            $new_users[] = $user;
2200
        }
2201
        return $new_users;
2202
    }
2203
2204
    /**
2205
     * This functions checks whether there are users that are already
2206
     * registered in the DB by different creator than the current coach.
2207
     * @param string a given username
2208
     * @param array $users the array with the course list ids
2209
     * @return array
2210
     * @author Julio Montoya Armas
2211
     */
2212
    public function get_user_creator($users)
2213
    {
2214
        $errors = array();
2215
        foreach ($users as $index => $user) {
2216
            // database table definition
2217
            $table_user = Database::get_main_table(TABLE_MAIN_USER);
2218
            $username = Database::escape_string($user['UserName']);
2219
            $sql = "SELECT creator_id FROM $table_user WHERE username='$username' ";
2220
2221
            $rs = Database::query($sql);
2222
            $creator_id = Database::result($rs, 0, 0);
2223
            // check if we are the creators or not
2224
            if ($creator_id != '') {
2225
                if ($creator_id != api_get_user_id()) {
2226
                    $user['error'] = get_lang('UserAlreadyRegisteredByOtherCreator');
2227
                    $errors[] = $user;
2228
                }
2229
            }
2230
        }
2231
2232
        return $errors;
2233
    }
2234
2235
    /**
2236
     * Validates imported data.
2237
     * @param $users list of users
2238
     */
2239
    function validate_data($users, $id_session = null)
2240
    {
2241
        $errors = array();
2242
        $new_users = array();
2243
        foreach ($users as $index => $user) {
2244
            // 1. Check whether mandatory fields are set.
2245
            $mandatory_fields = array('LastName', 'FirstName');
2246
            if (api_get_setting('registration', 'email') == 'true') {
2247
                $mandatory_fields[] = 'Email';
2248
            }
2249
2250
            foreach ($mandatory_fields as $key => $field) {
2251
                if (!isset ($user[$field]) || strlen($user[$field]) == 0) {
2252
                    $user['error'] = get_lang($field.'Mandatory');
2253
                    $errors[] = $user;
2254
                }
2255
            }
2256
            // 2. Check whether the username is too long.
2257 View Code Duplication
            if (UserManager::is_username_too_long($user['UserName'])) {
2258
                $user['error'] = get_lang('UserNameTooLong');
2259
                $errors[] = $user;
2260
            }
2261
2262
            $user['UserName'] = trim($user['UserName']);
2263
2264
            if (empty($user['UserName'])) {
2265
                $user['UserName'] = UserManager::create_username($user['FirstName'], $user['LastName']);
2266
            }
2267
            $new_users[] = $user;
2268
        }
2269
        $results = array('errors' => $errors, 'users' => $new_users);
2270
        return $results;
2271
    }
2272
2273
    /**
2274
     * Adds missing user-information (which isn't required, like password, etc).
2275
     */
2276
    function complete_missing_data($user)
2277
    {
2278
        // 1. Generate a password if it is necessary.
2279 View Code Duplication
        if (!isset ($user['Password']) || strlen($user['Password']) == 0) {
2280
            $user['Password'] = api_generate_password();
2281
        }
2282
2283
        return $user;
2284
    }
2285
2286
    /**
2287
     * Saves imported data.
2288
     */
2289
    public function save_data($users, $course_list, $id_session)
2290
    {
2291
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2292
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2293
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2294
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
2295
2296
        $id_session = intval($id_session);
2297
        $sendMail = $_POST['sendMail'] ? 1 : 0;
2298
2299
        // Adding users to the platform.
2300
        $new_users = array();
2301
        foreach ($users as $index => $user) {
2302
            $user = self::complete_missing_data($user);
2303
            // coach only will registered users
2304
            $default_status = STUDENT;
2305
            if ($user['create'] == COURSEMANAGER) {
2306
                $user['id'] = UserManager:: create_user(
2307
                    $user['FirstName'],
2308
                    $user['LastName'],
2309
                    $default_status,
2310
                    $user['Email'],
2311
                    $user['UserName'],
2312
                    $user['Password'],
2313
                    $user['OfficialCode'],
2314
                    api_get_setting('PlatformLanguage'),
2315
                    $user['PhoneNumber'],
2316
                    ''
2317
                );
2318
                $user['added_at_platform'] = 1;
2319
            } else {
2320
                $user['id'] = $user['create'];
2321
                $user['added_at_platform'] = 0;
2322
            }
2323
            $new_users[] = $user;
2324
        }
2325
        // Update user list.
2326
        $users = $new_users;
2327
2328
        // Inserting users.
2329
        $super_list = array();
2330
        foreach ($course_list as $enreg_course) {
2331
            $nbr_users = 0;
2332
            $new_users = array();
2333
            $enreg_course = Database::escape_string($enreg_course);
2334
            foreach ($users as $index => $user) {
2335
                $userid = intval($user['id']);
2336
                $sql = "INSERT IGNORE INTO $tbl_session_rel_course_rel_user(session_id, c_id, user_id)
2337
                        VALUES('$id_session','$enreg_course','$userid')";
2338
                $course_session = array('course' => $enreg_course, 'added' => 1);
2339
2340
                $result = Database::query($sql);
2341
                if (Database::affected_rows($result)) {
2342
                    $nbr_users++;
2343
                }
2344
                $new_users[] = $user;
2345
            }
2346
            $super_list[] = $new_users;
2347
2348
            //update the nbr_users field
2349
            $sql_select = "SELECT COUNT(user_id) as nbUsers FROM $tbl_session_rel_course_rel_user
2350
                           WHERE session_id='$id_session' AND c_id='$enreg_course'";
2351
            $rs = Database::query($sql_select);
2352
            list($nbr_users) = Database::fetch_array($rs);
2353
            $sql_update = "UPDATE $tbl_session_rel_course SET nbr_users=$nbr_users
2354
                           WHERE session_id='$id_session' AND c_id='$enreg_course'";
2355
            Database::query($sql_update);
2356
2357
            $sql_update = "UPDATE $tbl_session SET nbr_users= '$nbr_users' WHERE id='$id_session'";
2358
            Database::query($sql_update);
2359
        }
2360
2361
        $new_users = array();
2362
        foreach ($users as $index => $user) {
2363
            $userid = $user['id'];
2364
            $sql_insert = "INSERT IGNORE INTO $tbl_session_rel_user(session_id, user_id, registered_at)
2365
                           VALUES ('$id_session','$userid', '".api_get_utc_datetime()."')";
2366
            Database::query($sql_insert);
2367
            $user['added_at_session'] = 1;
2368
            $new_users[] = $user;
2369
        }
2370
2371
        $users = $new_users;
2372
        $registered_users = get_lang('FileImported').'<br /> Import file results : <br />';
2373
        // Sending emails.
2374
        $addedto = '';
2375
        if ($sendMail) {
2376
            $i = 0;
2377
            foreach ($users as $index => $user) {
2378
                $emailsubject = '['.api_get_setting('siteName').'] '.get_lang('YourReg').' '.api_get_setting('siteName');
2379
                $emailbody = get_lang('Dear').' '.
2380
                    api_get_person_name($user['FirstName'], $user['LastName']).",\n\n".
2381
                    get_lang('YouAreReg')." ".api_get_setting('siteName')." ".get_lang('WithTheFollowingSettings')."\n\n".
2382
                    get_lang('Username')." : $user[UserName]\n".
2383
                    get_lang('Pass')." : $user[Password]\n\n".
2384
                    get_lang('Address')." ".api_get_setting('siteName')." ".get_lang('Is')." : ".api_get_path(WEB_PATH)." \n\n".
2385
                    get_lang('Problem')."\n\n".
2386
                    get_lang('SignatureFormula').",\n\n".
2387
                    api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'))."\n".
2388
                    get_lang('Manager')." ".api_get_setting('siteName')."\nT. ".
2389
                    api_get_setting('administratorTelephone')."\n".get_lang('Email')." : ".api_get_setting('emailAdministrator');
2390
2391
                api_mail_html(
2392
                    api_get_person_name($user['FirstName'], $user['LastName'], null, PERSON_NAME_EMAIL_ADDRESS),
2393
                    $user['Email'],
2394
                    $emailsubject,
2395
                    $emailbody
2396
                );
2397
                $userInfo = api_get_user_info($user['id']);
2398
2399 View Code Duplication
                if (($user['added_at_platform'] == 1 && $user['added_at_session'] == 1) || $user['added_at_session'] == 1) {
2400
                    if ($user['added_at_platform'] == 1) {
2401
                        $addedto = get_lang('UserCreatedPlatform');
2402
                    } else {
2403
                        $addedto = '          ';
2404
                    }
2405
2406
                    if ($user['added_at_session'] == 1) {
2407
                        $addedto .= get_lang('UserInSession');
2408
                    }
2409
                } else {
2410
                    $addedto = get_lang('UserNotAdded');
2411
                }
2412
2413
                $registered_users .= UserManager::getUserProfileLink($userInfo)." - ".$addedto.'<br />';
0 ignored issues
show
Security Bug introduced by
It seems like $userInfo defined by api_get_user_info($user['id']) on line 2397 can also be of type false; however, UserManager::getUserProfileLink() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
2414
            }
2415
        } else {
2416
            $i = 0;
2417
            foreach ($users as $index => $user) {
2418
                $userInfo = api_get_user_info($user['id']);
2419 View Code Duplication
                if (($user['added_at_platform'] == 1 && $user['added_at_session'] == 1) || $user['added_at_session'] == 1) {
2420
                    if ($user['added_at_platform'] == 1) {
2421
                        $addedto = get_lang('UserCreatedPlatform');
2422
                    } else {
2423
                        $addedto = '          ';
2424
                    }
2425
2426
                    if ($user['added_at_session'] == 1) {
2427
                        $addedto .= ' '.get_lang('UserInSession');
2428
                    }
2429
                } else {
2430
                    $addedto = get_lang('UserNotAdded');
2431
                }
2432
                $registered_users .= "<a href=\"../user/userInfo.php?uInfo=".$user['id']."\">".api_get_person_name($user['FirstName'], $user['LastName'])."</a> - ".$addedto.'<br />';
2433
            }
2434
        }
2435
        Display::addFlash(Display::return_message($registered_users));
2436
        header('Location: course.php?id_session='.$id_session);
2437
        exit;
2438
    }
2439
2440
    /**
2441
     * Reads CSV-file.
2442
     * @param string $file Path to the CSV-file
2443
     * @return array All userinformation read from the file
2444
     */
2445 View Code Duplication
    function parse_csv_data($file)
2446
    {
2447
        $users = Import::csvToArray($file);
0 ignored issues
show
Deprecated Code introduced by
The method Import::csvToArray() has been deprecated with message: use cvs_reader instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
2448
        foreach ($users as $index => $user) {
2449
            if (isset ($user['Courses'])) {
2450
                $user['Courses'] = explode('|', trim($user['Courses']));
2451
            }
2452
            $users[$index] = $user;
2453
        }
2454
        return $users;
2455
    }
2456
2457
    /**
2458
     * XML-parser: the handler at the beginning of element.
2459
     */
2460 View Code Duplication
    function element_start($parser, $data)
2461
    {
2462
        $data = api_utf8_decode($data);
2463
        global $user;
2464
        global $current_tag;
2465
        switch ($data) {
2466
            case 'Contact' :
2467
                $user = array();
2468
                break;
2469
            default:
2470
                $current_tag = $data;
2471
        }
2472
    }
2473
2474
    /**
2475
     * XML-parser: the handler at the end of element.
2476
     */
2477
    function element_end($parser, $data)
2478
    {
2479
        $data = api_utf8_decode($data);
2480
        global $user;
2481
        global $users;
2482
        global $current_value;
2483
        global $purification_option_for_usernames;
2484
        $user[$data] = $current_value;
2485
        switch ($data) {
2486
            case 'Contact' :
2487
                $user['UserName'] = UserManager::purify_username($user['UserName'], $purification_option_for_usernames);
2488
                $users[] = $user;
2489
                break;
2490
            default:
2491
                $user[$data] = $current_value;
2492
                break;
2493
        }
2494
    }
2495
2496
    /**
2497
     * XML-parser: the handler for character data.
2498
     */
2499
    function character_data($parser, $data)
2500
    {
2501
        $data = trim(api_utf8_decode($data));
2502
        global $current_value;
2503
        $current_value = $data;
2504
    }
2505
2506
    /**
2507
     * Reads XML-file.
2508
     * @param string $file Path to the XML-file
2509
     * @return array All userinformation read from the file
2510
     */
2511
    function parse_xml_data($file)
2512
    {
2513
        global $current_tag;
2514
        global $current_value;
2515
        global $user;
2516
        global $users;
2517
        $users = array();
2518
        $parser = xml_parser_create('UTF-8');
2519
        xml_set_element_handler($parser, array('MySpace', 'element_start'), array('MySpace', 'element_end'));
2520
        xml_set_character_data_handler($parser, "character_data");
2521
        xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false);
2522
        xml_parse($parser, api_utf8_encode_xml(file_get_contents($file)));
2523
        xml_parser_free($parser);
2524
        return $users;
2525
    }
2526
2527
    public static function displayTrackingAccessOverView($courseId, $sessionId, $studentId)
2528
    {
2529
        $courseId = intval($courseId);
2530
        $sessionId = intval($sessionId);
2531
        $studentId = intval($studentId);
2532
2533
        $em = Database::getManager();
2534
        $sessionRepo = $em->getRepository('ChamiloCoreBundle:Session');
2535
2536
        $courseList = [];
2537
        $sessionList = [];
2538
        $studentList = [];
2539
2540
        if (!empty($courseId)) {
2541
            $course = $em->find('ChamiloCoreBundle:Course', $courseId);
2542
2543
            $courseList[$course->getId()] = $course->getTitle();
2544
        }
2545
2546
        if (!empty($sessionId)) {
2547
            $session = $em->find('ChamiloCoreBundle:Session', $sessionId);
2548
2549
            $sessionList[$session->getId()] = $session->getName();
2550
        }
2551
2552
        if (!empty($studentId)) {
2553
            $student = $em->find('ChamiloUserBundle:User', $studentId);
2554
2555
            $studentList[$student->getId()] = $student->getCompleteName();
2556
        }
2557
2558
        $form = new FormValidator('access_overview', 'GET');
2559
        $form->addElement(
2560
            'select_ajax',
2561
            'course_id',
2562
            get_lang('SearchCourse'),
2563
            $courseList,
2564
            [
2565
                'url' => api_get_path(WEB_AJAX_PATH).'course.ajax.php?'.http_build_query([
2566
                    'a' => 'search_course_by_session_all',
2567
                    'session_id' => $sessionId
2568
                ])
2569
            ]
2570
        );
2571
        $form->addElement(
2572
            'select_ajax',
2573
            'session_id',
2574
            get_lang('SearchSession'),
2575
            $sessionList,
2576
            [
2577
                'url_function' => "
2578
                    function () {
2579
                        var params = $.param({
2580
                            a: 'search_session_by_course',
2581
                            course_id: $('#course_id').val() || 0
2582
                        });
2583
2584
                        return '" . api_get_path(WEB_AJAX_PATH)."session.ajax.php?' + params;
2585
                    }
2586
                "
2587
            ]
2588
        );
2589
        $form->addSelect(
2590
            'profile',
2591
            get_lang('Profile'),
2592
            [
2593
                '' => get_lang('Select'),
2594
                STUDENT => get_lang('Student'),
2595
                COURSEMANAGER => get_lang('CourseManager'),
2596
                DRH => get_lang('Drh')
2597
            ],
2598
            ['id' => 'profile']
2599
        );
2600
        $form->addElement(
2601
            'select_ajax',
2602
            'student_id',
2603
            get_lang('SearchUsers'),
2604
            $studentList,
2605
            [
2606
                'placeholder' => get_lang('All'),
2607
                'url_function' => "
2608
                    function () {
2609
                        var params = $.param({
2610
                            a: 'search_user_by_course',
2611
                            session_id: $('#session_id').val(),
2612
                            course_id: $('#course_id').val()
2613
                        });
2614
2615
                        return '" . api_get_path(WEB_AJAX_PATH)."course.ajax.php?' + params;
2616
                    }
2617
                "
2618
            ]
2619
        );
2620
        $form->addDateRangePicker(
2621
            'date',
2622
            get_lang('DateRange'),
2623
            true,
2624
            [
2625
                'id' => 'date_range',
2626
                'format' => 'YYYY-MM-DD',
2627
                'timePicker' => 'false',
2628
                'validate_format' => 'Y-m-d'
2629
            ]
2630
        );
2631
        $form->addHidden('display', 'accessoverview');
2632
        $form->addRule('course_id', get_lang('Required'), 'required');
2633
        $form->addRule('profile', get_lang('Required'), 'required');
2634
        $form->addButton('submit', get_lang('Generate'), 'gear', 'primary');
2635
2636
        $table = null;
2637
2638
        if ($form->validate()) {
2639
            $table = new SortableTable(
2640
                'tracking_access_overview',
2641
                ['MySpace', 'getNumberOfTrackAccessOverview'],
2642
                ['MySpace', 'getUserDataAccessTrackingOverview'],
2643
                0
2644
            );
2645
            $table->additional_parameters = $form->exportValues();
2646
2647
            $table->set_header(0, get_lang('LoginDate'), true);
2648
            $table->set_header(1, get_lang('Username'), true);
2649 View Code Duplication
            if (api_is_western_name_order()) {
2650
                $table->set_header(2, get_lang('FirstName'), true);
2651
                $table->set_header(3, get_lang('LastName'), true);
2652
            } else {
2653
                $table->set_header(2, get_lang('LastName'), true);
2654
                $table->set_header(3, get_lang('FirstName'), true);
2655
            }
2656
            $table->set_header(4, get_lang('Clicks'), false);
2657
            $table->set_header(5, get_lang('IP'), false);
2658
            $table->set_header(6, get_lang('TimeLoggedIn'), false);
2659
        }
2660
2661
        $template = new Template(
2662
            null, false, false, false, false, false, false
2663
        );
2664
        $template->assign('form', $form->returnForm());
2665
        $template->assign('table', $table ? $table->return_table() : null);
2666
2667
        echo $template->fetch(
2668
            $template->get_template('my_space/accessoverview.tpl')
2669
        );
2670
    }
2671
2672
    /**
2673
     * @return int
2674
     */
2675 View Code Duplication
    public static function getNumberOfTrackAccessOverview()
2676
    {
2677
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
2678
        $sql = "SELECT COUNT(course_access_id) count FROM $table";
2679
        $result = Database::query($sql);
2680
        $row = Database::fetch_assoc($result);
2681
2682
        return $row['count'];
2683
    }
2684
2685
    /**
2686
     * @param $from
2687
     * @param $numberItems
2688
     * @param $column
2689
     * @param $orderDirection
2690
     * @return array
2691
     */
2692
    public static function getUserDataAccessTrackingOverview($from, $numberItems, $column, $orderDirection)
2693
    {
2694
        $user = Database::get_main_table(TABLE_MAIN_USER);
2695
        $course = Database::get_main_table(TABLE_MAIN_COURSE);
2696
        $track_e_login = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
2697
        $track_e_course_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
2698
2699
        global $export_csv;
2700
2701
        if ($export_csv) {
2702
            $is_western_name_order = api_is_western_name_order(PERSON_NAME_DATA_EXPORT);
2703
        } else {
2704
            $is_western_name_order = api_is_western_name_order();
2705
        }
2706
2707
        //TODO add course name
2708
        $sql = "SELECT
2709
                a.login_course_date as col0,
2710
                u.username as col1,
2711
                " . (
2712
                    $is_western_name_order ? "
2713
                        u.firstname AS col2,
2714
                        u.lastname AS col3,
2715
                    " : "
2716
                        u.lastname AS col2,
2717
                        u.firstname AS col3,
2718
                " )."
2719
                a.logout_course_date,
2720
                c.title,
2721
                c.code,
2722
                u.user_id
2723
            FROM $track_e_course_access a
2724
            INNER JOIN $user u ON a.user_id = u.user_id
2725
            INNER JOIN $course c ON a.c_id = c.id";
2726
2727
        if (isset($_GET['session_id']) && !empty($_GET['session_id'])) {
2728
            $sessionId = intval($_GET['session_id']);
2729
            $sql .= " WHERE a.session_id = ".$sessionId;
2730
        }
2731
2732
        $sql .= " ORDER BY col$column $orderDirection ";
2733
        $sql .= " LIMIT $from,$numberItems";
2734
        $result = Database::query($sql);
2735
2736
        //$clicks = Tracking::get_total_clicks_by_session();
2737
        $data = array();
2738
        while ($user = Database::fetch_assoc($result)) {
2739
            $data[] = $user;
2740
        }
2741
2742
        $return = [];
2743
        //TODO: Dont use numeric index
2744
        foreach ($data as $key => $info) {
2745
            $start_date = $info['col0'];
2746
            $end_date = $info['logout_course_date'];
2747
2748
            $return[$info['user_id']] = array(
2749
                $start_date,
2750
                $info['col1'],
2751
                $info['col2'],
2752
                $info['col3'],
2753
                $info['user_id'],
2754
                'ip',
2755
                //TODO is not correct/precise, it counts the time not logged between two loggins
2756
                gmdate("H:i:s", strtotime($end_date) - strtotime($start_date))
2757
            );
2758
        }
2759
2760
        foreach ($return as $key => $info) {
2761
            $ipResult = Database::select(
2762
                'user_ip',
2763
                $track_e_login,
2764
                ['where' => [
2765
                    '? BETWEEN login_date AND logout_date' => $info[0]
2766
                ]],
2767
                'first'
2768
            );
2769
2770
            $return[$key][5] = $ipResult['user_ip'];
2771
        }
2772
2773
        return $return;
2774
    }
2775
2776
    /**
2777
     * Gets the connections to a course as an array of login and logout time
2778
     *
2779
     * @param   int $user_id
2780
     * @param   array $course_info
2781
     * @param int $sessionId
2782
     * @param string $start_date
2783
     * @param string $end_date
2784
     * @author  Jorge Frisancho Jibaja
2785
     * @author  Julio Montoya <[email protected]> fixing the function
2786
     * @version OCT-22- 2010
2787
     * @return  array
2788
     */
2789
    public static function get_connections_to_course_by_date(
2790
        $user_id,
2791
        $course_info,
2792
        $sessionId,
2793
        $start_date,
2794
        $end_date
2795
    ) {
2796
        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
2797
        $user_id = intval($user_id);
2798
        $connections = array();
2799
        if (!empty($course_info)) {
2800
            $courseId = intval($course_info['real_id']);
2801
            $end_date = add_day_to($end_date);
2802
            $sessionCondition = api_get_session_condition($sessionId);
2803
            $sql = "SELECT login_course_date, logout_course_date
2804
                    FROM $table
2805
                    WHERE
2806
                        user_id = $user_id AND
2807
                        c_id = $courseId AND
2808
                        login_course_date BETWEEN '$start_date' AND '$end_date' AND
2809
                        logout_course_date BETWEEN '$start_date' AND '$end_date'
2810
                        $sessionCondition
2811
                    ORDER BY login_course_date ASC";
2812
            $rs = Database::query($sql);
2813
2814 View Code Duplication
            while ($row = Database::fetch_array($rs)) {
2815
                $connections[] = array(
2816
                    'login' => $row['login_course_date'],
2817
                    'logout' =>$row['logout_course_date']
2818
                );
2819
            }
2820
        }
2821
        return $connections;
2822
    }
2823
}
2824
2825
/**
2826
 * @param $user_id
2827
 * @param array $course_info
2828
 * @param int $sessionId
2829
 * @param null $start_date
2830
 * @param null $end_date
2831
 * @return array
2832
 */
2833
function get_stats($user_id, $course_info, $sessionId, $start_date = null, $end_date = null)
2834
{
2835
    $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
2836
    $result = array();
2837
    if (!empty($course_info)) {
2838
        $stringStartDate = '';
2839
        $stringEndDate = '';
2840
        if ($start_date != null && $end_date != null) {
2841
            $end_date = add_day_to($end_date);
2842
            $stringStartDate = "AND login_course_date BETWEEN '$start_date' AND '$end_date'";
2843
            $stringEndDate = "AND logout_course_date BETWEEN '$start_date' AND '$end_date'";
2844
        }
2845
        $user_id = intval($user_id);
2846
        $courseId = intval($course_info['real_id']);
2847
        $sessionCondition = api_get_session_condition($sessionId);
2848
        $sql = "SELECT
2849
                SEC_TO_TIME(AVG(time_to_sec(timediff(logout_course_date,login_course_date)))) as avrg,
2850
                SEC_TO_TIME(SUM(time_to_sec(timediff(logout_course_date,login_course_date)))) as total,
2851
                count(user_id) as times
2852
                FROM $table
2853
                WHERE
2854
                    user_id = $user_id AND
2855
                    c_id = $courseId $stringStartDate $stringEndDate 
2856
                    $sessionCondition                    
2857
                ORDER BY login_course_date ASC";
2858
2859
        $rs = Database::query($sql);
2860
        if ($row = Database::fetch_array($rs)) {
2861
            $foo_avg = $row['avrg'];
2862
            $foo_total = $row['total'];
2863
            $foo_times = $row['times'];
2864
            $result = array(
2865
                'avg' => $foo_avg,
2866
                'total' => $foo_total,
2867
                'times' => $foo_times
2868
            );
2869
        }
2870
    }
2871
2872
    return $result;
2873
}
2874
2875
function add_day_to($end_date)
2876
{
2877
    $foo_date = strtotime($end_date);
2878
    $foo_date = strtotime(" +1 day", $foo_date);
2879
    $foo_date = date("Y-m-d", $foo_date);
2880
    return $foo_date;
2881
}
2882
2883
/**
2884
 *
2885
 * @param array
2886
 * @author Jorge Frisancho Jibaja
2887
 * @version OCT-22- 2010
2888
 * @return array
2889
 */
2890
function convert_to_array($sql_result)
2891
{
2892
    $result_to_print = '<table>';
2893
    foreach ($sql_result as $key => $data) {
2894
        $result_to_print .= '<tr><td>'.date('d-m-Y (H:i:s)', $data['login']).'</td><td>'.api_time_to_hms($data['logout'] - $data['login']).'</tr></td>'."\n";
2895
    }
2896
    $result_to_print .= '</table>';
2897
    $result_to_print = array("result"=>$result_to_print);
2898
    return $result_to_print;
2899
}
2900
2901
2902
/**
2903
 * Converte an array to a table in html
2904
 *
2905
 * @param array $result
2906
 * @author Jorge Frisancho Jibaja
2907
 * @version OCT-22- 2010
2908
 * @return string
2909
 */
2910
function convert_to_string($result)
2911
{
2912
    $html = '<table class="table">';
2913
    if (!empty($result)) {
2914
        foreach ($result as $key => $data) {
2915
            $html .= '<tr><td>';
2916
            $html .= api_get_local_time($data['login']);
2917
            $html .= '</td>';
2918
            $html .= '<td>';
2919
2920
            $html .= api_time_to_hms(api_strtotime($data['logout']) - api_strtotime($data['login']));
2921
            $html .= '</tr></td>';
2922
        }
2923
    }
2924
    $html .= '</table>';
2925
    return $html;
2926
}
2927
2928
2929
/**
2930
 * This function draw the graphic to be displayed on the user view as an image
2931
 *
2932
 * @param array $sql_result
2933
 * @param string $start_date
2934
 * @param string $end_date
2935
 * @param string $type
2936
 * @author Jorge Frisancho Jibaja
2937
 * @version OCT-22- 2010
2938
 * @return string
2939
 */
2940
function grapher($sql_result, $start_date, $end_date, $type = '')
2941
{
2942
    if (empty($start_date)) {
2943
        $start_date = '';
2944
    }
2945
    if (empty($end_date)) {
2946
        $end_date = '';
2947
    }
2948
    if ($type == '') {
2949
        $type = 'day';
2950
    }
2951
    $main_year = $main_month_year = $main_day = [];
2952
2953
    $period = new DatePeriod(
2954
        new DateTime($start_date),
2955
        new DateInterval('P1D'),
2956
        new DateTime($end_date)
2957
    );
2958
2959
    foreach ($period as $date) {
2960
        $main_day[$date->format('d-m-Y')] = 0;
2961
    }
2962
2963
    $period = new DatePeriod(
2964
        new DateTime($start_date),
2965
        new DateInterval('P1M'),
2966
        new DateTime($end_date)
2967
    );
2968
2969
    foreach ($period as $date) {
2970
        $main_month_year[$date->format('m-Y')] = 0;
2971
    }
2972
2973
    $i = 0;
2974
    if (is_array($sql_result) && count($sql_result) > 0) {
2975
        foreach ($sql_result as $key => $data) {
2976
            $login = api_strtotime($data['login']);
2977
            $logout = api_strtotime($data['logout']);
2978
            //creating the main array
2979 View Code Duplication
            if (isset($main_month_year[date('m-Y', $login)])) {
2980
                $main_month_year[date('m-Y', $login)] += float_format(($logout - $login) / 60, 0);
2981
            }
2982 View Code Duplication
            if (isset($main_day[date('d-m-Y', $login)])) {
2983
                $main_day[date('d-m-Y', $login)] += float_format(($logout - $login) / 60, 0);
2984
            }
2985
            if ($i > 500) {
2986
                break;
2987
            }
2988
            $i++;
2989
        }
2990
        switch ($type) {
2991
            case 'day':
2992
                $main_date = $main_day;
2993
                break;
2994
            case 'month':
2995
                $main_date = $main_month_year;
2996
                break;
2997
            case 'year':
2998
                $main_date = $main_year;
2999
                break;
3000
        }
3001
3002
        $labels = array_keys($main_date);
3003
        if (count($main_date) == 1) {
3004
            $labels = $labels[0];
3005
            $main_date = $main_date[$labels];
3006
        }
3007
3008
        /* Create and populate the pData object */
3009
        $myData = new pData();
3010
        $myData->addPoints($main_date, 'Serie1');
3011
        if (count($main_date) != 1) {
3012
            $myData->addPoints($labels, 'Labels');
3013
            $myData->setSerieDescription('Labels', 'Months');
3014
            $myData->setAbscissa('Labels');
3015
        }
3016
        $myData->setSerieWeight('Serie1', 1);
3017
        $myData->setSerieDescription('Serie1', get_lang('MyResults'));
3018
        $myData->setAxisName(0, get_lang('Minutes'));
3019
        $myData->loadPalette(api_get_path(SYS_CODE_PATH).'palettes/pchart/default.color', true);
3020
3021
        // Cache definition
3022
        $cachePath = api_get_path(SYS_ARCHIVE_PATH);
3023
        $myCache = new pCache(array('CacheFolder' => substr($cachePath, 0, strlen($cachePath) - 1)));
3024
        $chartHash = $myCache->getHash($myData);
3025
3026
        if ($myCache->isInCache($chartHash)) {
3027
            //if we already created the img
3028
            $imgPath = api_get_path(SYS_ARCHIVE_PATH).$chartHash;
3029
            $myCache->saveFromCache($chartHash, $imgPath);
3030
            $imgPath = api_get_path(WEB_ARCHIVE_PATH).$chartHash;
3031
        } else {
3032
            /* Define width, height and angle */
3033
            $mainWidth = 760;
3034
            $mainHeight = 230;
3035
            $angle = 50;
3036
3037
            /* Create the pChart object */
3038
            $myPicture = new pImage($mainWidth, $mainHeight, $myData);
3039
3040
            /* Turn of Antialiasing */
3041
            $myPicture->Antialias = false;
3042
            /* Draw the background */
3043
            $settings = array("R" => 255, "G" => 255, "B" => 255);
3044
            $myPicture->drawFilledRectangle(0, 0, $mainWidth, $mainHeight, $settings);
3045
3046
            /* Add a border to the picture */
3047
            $myPicture->drawRectangle(
3048
                0,
3049
                0,
3050
                $mainWidth - 1,
3051
                $mainHeight - 1,
3052
                array("R" => 0, "G" => 0, "B" => 0)
3053
            );
3054
3055
            /* Set the default font */
3056
            $myPicture->setFontProperties(
3057
                array(
3058
                    "FontName" => api_get_path(SYS_FONTS_PATH).'opensans/OpenSans-Regular.ttf',
3059
                    "FontSize" => 10)
3060
            );
3061
            /* Write the chart title */
3062
            $myPicture->drawText(
3063
                $mainWidth / 2,
3064
                30,
3065
                get_lang('TimeSpentInTheCourse'),
3066
                array(
3067
                    "FontSize" => 12,
3068
                    "Align" => TEXT_ALIGN_BOTTOMMIDDLE
3069
                )
3070
            );
3071
3072
            /* Set the default font */
3073
            $myPicture->setFontProperties(
3074
                array(
3075
                    "FontName" => api_get_path(SYS_FONTS_PATH).'opensans/OpenSans-Regular.ttf',
3076
                    "FontSize" => 8
3077
                )
3078
            );
3079
3080
            /* Define the chart area */
3081
            $myPicture->setGraphArea(50, 40, $mainWidth - 40, $mainHeight - 80);
3082
3083
            /* Draw the scale */
3084
            $scaleSettings = array(
3085
                'XMargin' => 10,
3086
                'YMargin' => 10,
3087
                'Floating' => true,
3088
                'GridR' => 200,
3089
                'GridG' => 200,
3090
                'GridB' => 200,
3091
                'DrawSubTicks' => true,
3092
                'CycleBackground' => true,
3093
                'LabelRotation' => $angle,
3094
                'Mode' => SCALE_MODE_ADDALL_START0,
3095
            );
3096
            $myPicture->drawScale($scaleSettings);
3097
3098
            /* Turn on Antialiasing */
3099
            $myPicture->Antialias = true;
3100
3101
            /* Enable shadow computing */
3102
            $myPicture->setShadow(
3103
                true,
3104
                array(
3105
                    "X" => 1,
3106
                    "Y" => 1,
3107
                    "R" => 0,
3108
                    "G" => 0,
3109
                    "B" => 0,
3110
                    "Alpha" => 10
3111
                )
3112
            );
3113
3114
            /* Draw the line chart */
3115
            $myPicture->setFontProperties(
3116
                array(
3117
                    "FontName" => api_get_path(SYS_FONTS_PATH).'opensans/OpenSans-Regular.ttf',
3118
                    "FontSize" => 10
3119
                )
3120
            );
3121
            $myPicture->drawSplineChart();
3122
            $myPicture->drawPlotChart(
3123
                array(
3124
                    "DisplayValues" => true,
3125
                    "PlotBorder" => true,
3126
                    "BorderSize" => 1,
3127
                    "Surrounding" => -60,
3128
                    "BorderAlpha" => 80
3129
                )
3130
            );
3131
3132
            /* Do NOT Write the chart legend */
3133
3134
            /* Write and save into cache */
3135
            $myCache->writeToCache($chartHash, $myPicture);
3136
            $imgPath = api_get_path(SYS_ARCHIVE_PATH).$chartHash;
3137
            $myCache->saveFromCache($chartHash, $imgPath);
3138
            $imgPath = api_get_path(WEB_ARCHIVE_PATH).$chartHash;
3139
        }
3140
        $html = '<img src="'.$imgPath.'">';
3141
3142
        return $html;
3143
    } else {
3144
        $foo_img = api_convert_encoding(
3145
            '<div id="messages" class="warning-message">'.get_lang('GraphicNotAvailable').'</div>',
3146
            'UTF-8'
3147
        );
3148
3149
        return $foo_img;
3150
    }
3151
}
3152