Attendance   F
last analyzed

Complexity

Total Complexity 294

Size/Duplication

Total Lines 2939
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 294
eloc 1544
dl 0
loc 2939
rs 0.8
c 0
b 0
f 0

64 Methods

Rating   Name   Duplication   Size   Complexity  
B get_faults_average_inside_courses() 0 42 6
A get_done_attendance_calendar() 0 17 1
A getNumberOfAttendances() 0 28 4
B attendance_edit() 0 67 5
A get_attendances_list() 0 24 5
B get_faults_of_user() 0 49 6
C get_users_rel_course() 0 100 14
A get_attendance_by_id() 0 16 3
B attendance_sheet_add() 0 98 7
A get_faults_average_by_course() 0 42 5
B changeVisibility() 0 50 6
B updateUsersResults() 0 80 7
A saveAttendanceSheetLog() 0 38 3
A attendance_delete() 0 45 5
B attendance_add() 0 67 5
A __construct() 0 2 1
A attendance_restore() 0 43 5
A lock_attendance() 0 21 4
F get_attendance_data() 0 178 26
A get_user_score() 0 42 3
A getGroupListByAttendanceCalendar() 0 10 1
B attendance_repeat_calendar_add() 0 46 9
A updateCalendarBlocked() 0 12 2
B getAttendanceLoginTable() 0 47 8
A set_session_id() 0 3 1
A get_attendance_weight() 0 3 1
A deleteAttendanceCalendarGroup() 0 7 1
A isCalendarBlocked() 0 15 2
A get_date_time() 0 3 1
A is_all_attendance_calendar_done() 0 13 3
A get_course_id() 0 3 1
A set_description() 0 3 1
A set_attendance_qualify_title() 0 3 1
A get_session_id() 0 3 1
A getSignature() 0 27 3
A attendance_calendar_add() 0 46 4
A is_locked_attendance() 0 6 1
A attendance_calendar_edit() 0 35 3
B exportAttendanceLogin() 0 45 6
A get_next_attendance_calendar_id() 0 21 2
C getAttendanceLogin() 0 73 11
A getAttendanceCalendarGroup() 0 10 1
A addAttendanceCalendarToGroup() 0 29 5
A get_attendance_qualify_title() 0 3 1
A get_count_dates_inside_attendance_calendar() 0 17 2
A set_name() 0 3 1
A getAttendanceCalendarExtraFieldValue() 0 13 3
C get_users_attendance_sheet() 0 88 14
A getNextAttendanceCalendarDatetime() 0 20 2
A set_attendance_weight() 0 3 1
A get_description() 0 3 1
A set_date_time() 0 3 1
A get_name() 0 3 1
B get_number_of_attendance_calendar() 0 85 5
A attendance_calendar_delete() 0 52 4
D getCoursesWithAttendance() 0 192 15
A get_attendance_calendar_by_id() 0 17 3
A set_course_id() 0 3 1
F get_attendance_calendar() 0 98 17
A deleteSignature() 0 29 3
A saveComment() 0 64 4
A getComment() 0 51 5
C exportAttendanceSheetToXls() 0 90 16
A saveSignature() 0 43 4

How to fix   Complexity   

Complex Class

Complex classes like Attendance often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Attendance, and based on these observations, apply Extract Interface, too.

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
/**
5
 * This file contains class used like library, provides functions for attendance tool.
6
 * It's also used like model to attendance_controller (MVC pattern).
7
 *
8
 * @author Christian Fasanando <[email protected]>
9
 * @author Julio Montoya <[email protected]> improvements
10
 *
11
 * @package chamilo.attendance
12
 */
13
14
use Chamilo\CourseBundle\Entity\CAttendanceCalendar;
15
use Chamilo\CourseBundle\Entity\CAttendanceResultComment;
16
use Chamilo\CourseBundle\Entity\CAttendanceSheet;
17
18
class Attendance
19
{
20
    // constants
21
    public const DONE_ATTENDANCE_LOG_TYPE = 'done_attendance_sheet';
22
    public const UPDATED_ATTENDANCE_LOG_TYPE = 'updated_attendance_sheet';
23
    public const LOCKED_ATTENDANCE_LOG_TYPE = 'locked_attendance_sheet';
24
    public $category_id;
25
    private $session_id;
26
    private $course_id;
27
    private $date_time;
28
    private $name;
29
    private $description;
30
    private $attendance_qualify_title;
31
    private $attendance_weight;
32
    private $course_int_id;
33
34
    /**
35
     * Constructor.
36
     */
37
    public function __construct()
38
    {
39
        //$this->course_int_id = api_get_course_int_id();
40
    }
41
42
    /**
43
     * Get the total number of attendance inside current course and current session.
44
     *
45
     * @return int
46
     *
47
     * @see SortableTable#get_total_number_of_items()
48
     */
49
    public static function getNumberOfAttendances()
50
    {
51
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
52
        $session_id = api_get_session_id();
53
        $condition_session = api_get_session_condition($session_id);
54
        $course_id = api_get_course_int_id();
55
56
        $active_plus = '';
57
58
        if ((isset($_GET['isStudentView']) && $_GET['isStudentView'] == 'true') ||
59
            !api_is_allowed_to_edit(null, true)
60
        ) {
61
            $active_plus = ' AND att.active = 1';
62
        }
63
64
        $sql = "SELECT COUNT(att.id) AS total_number_of_items
65
                FROM $tbl_attendance att
66
                WHERE
67
                      c_id = $course_id AND
68
                      active <> 2 $active_plus $condition_session  ";
69
        /*$active = (int) $active;
70
        if ($active === 1 || $active === 0) {
71
            $sql .= "AND att.active = $active";
72
        }*/
73
        $res = Database::query($sql);
74
        $obj = Database::fetch_object($res);
75
76
        return $obj->total_number_of_items;
77
    }
78
79
    /**
80
     * Get attendance list only the id, name and attendance_qualify_max fields.
81
     *
82
     * @param int $course_id  course db name (optional)
83
     * @param int $session_id session id (optional)
84
     *
85
     * @return array attendances list
86
     */
87
    public function get_attendances_list($course_id = 0, $session_id = 0)
88
    {
89
        $table = Database::get_course_table(TABLE_ATTENDANCE);
90
        $course_id = (int) $course_id;
91
        if (empty($course_id)) {
92
            $course_id = api_get_course_int_id();
93
        }
94
95
        $session_id = !empty($session_id) ? (int) $session_id : api_get_session_id();
96
        $condition_session = api_get_session_condition($session_id);
97
98
        // Get attendance data
99
        $sql = "SELECT id, name, attendance_qualify_max
100
                FROM $table
101
                WHERE c_id = $course_id AND active = 1 $condition_session ";
102
        $result = Database::query($sql);
103
        $data = [];
104
        if (Database::num_rows($result) > 0) {
105
            while ($row = Database::fetch_array($result, 'ASSOC')) {
106
                $data[$row['id']] = $row;
107
            }
108
        }
109
110
        return $data;
111
    }
112
113
    /**
114
     * Get the attendances to display on the current page (fill the sortable-table).
115
     *
116
     * @param   int     offset of first user to recover
117
     * @param   int     Number of users to get
118
     * @param   int     Column to sort on
119
     * @param   string  Order (ASC,DESC)
120
     *
121
     * @see SortableTable#get_table_data($from)
122
     *
123
     * @return array
124
     */
125
    public static function get_attendance_data(
126
        $from,
127
        $number_of_items,
128
        $column,
129
        $direction
130
    ) {
131
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
132
        $course_id = api_get_course_int_id();
133
        $session_id = api_get_session_id();
134
        $condition_session = api_get_session_condition($session_id);
135
        $column = (int) $column;
136
        $from = (int) $from;
137
        $number_of_items = (int) $number_of_items;
138
139
        if (!in_array($direction, ['ASC', 'DESC'])) {
140
            $direction = 'ASC';
141
        }
142
143
        $active_plus = '';
144
        if ((isset($_GET['isStudentView']) && $_GET['isStudentView'] == 'true') ||
145
            !api_is_allowed_to_edit(null, true)
146
        ) {
147
            $active_plus = ' AND att.active = 1';
148
        }
149
150
        $sql = "SELECT
151
                    att.id AS col0,
152
                    att.name AS col1,
153
                    att.description AS col2,
154
                    att.attendance_qualify_max AS col3,
155
                    att.locked AS col4,
156
                    att.active AS col5,
157
                    att.session_id
158
                FROM $tbl_attendance att
159
                WHERE
160
                    att.active <> 2 AND
161
                    c_id = $course_id $active_plus $condition_session
162
                ORDER BY col$column $direction
163
                LIMIT $from,$number_of_items ";
164
165
        $res = Database::query($sql);
166
        $attendances = [];
167
        $user_info = api_get_user_info();
168
        $allowDelete = api_get_setting('allow_delete_attendance');
169
170
        $student_param = '';
171
        $studentRequestId = isset($_GET['student_id']) ? (int) $_GET['student_id'] : 0;
172
        if (api_is_drh() && !empty($studentRequestId)) {
173
            $student_param = '&student_id='.$studentRequestId;
174
        }
175
176
        while ($attendance = Database::fetch_row($res)) {
177
            $session_star = '';
178
            if ($session_id == $attendance[6]) {
179
                $session_star = api_get_session_image($session_id, $user_info['status']);
180
            }
181
182
            if ($attendance[5] == 1) {
183
                $isDrhOfCourse = CourseManager::isUserSubscribedInCourseAsDrh(
184
                    api_get_user_id(),
185
                    api_get_course_info()
186
                ) || api_is_drh();
187
                if (api_is_allowed_to_edit(null, true) || $isDrhOfCourse) {
188
                    // Link to edit
189
                    $attendance[1] = '<a
190
                        href="index.php?'.api_get_cidreq().'&action=attendance_sheet_list&attendance_id='.$attendance[0].$student_param.'">'.
191
                        Security::remove_XSS($attendance[1]).
192
                        '</a>'.
193
                        $session_star;
194
                } else {
195
                    // Link to view
196
                    $attendance[1] = '<a
197
                        href="index.php?'.api_get_cidreq().'&action=attendance_sheet_list_no_edit&attendance_id='.$attendance[0].$student_param.'">'.
198
                        Security::remove_XSS($attendance[1]).
199
                        '</a>'.
200
                        $session_star;
201
                }
202
            } else {
203
                $attendance[1] = '<a
204
                    class="muted"
205
                    href="index.php?'.api_get_cidreq().'&action=attendance_sheet_list&attendance_id='.$attendance[0].$student_param.'">'.
206
                    Security::remove_XSS($attendance[1]).
207
                    '</a>'.
208
                    $session_star;
209
            }
210
211
            if ($attendance[5] == 1) {
212
                $attendance[3] = '<center>'.$attendance[3].'</center>';
213
            } else {
214
                $attendance[3] = '<center><span class="muted">'.$attendance[3].'</span></center>';
215
            }
216
217
            $attendance[3] = '<center>'.$attendance[3].'</center>';
218
            if (api_is_allowed_to_edit(null, true)) {
219
                $actions = '<center>';
220
                if (api_is_platform_admin()) {
221
                    $actions .= '<a href="index.php?'.api_get_cidreq().'&action=attendance_edit&attendance_id='.$attendance[0].'">'.
222
                        Display::return_icon('edit.png', get_lang('Edit'), [], ICON_SIZE_SMALL).'</a>&nbsp;';
223
                    // Visible
224
                    if ($attendance[5] == 1) {
225
                        $actions .= '<a href="index.php?'.api_get_cidreq().'&action=attendance_set_invisible&attendance_id='.$attendance[0].'">'.
226
                            Display::return_icon('visible.png', get_lang('Hide'), [], ICON_SIZE_SMALL).'</a>';
227
                    } else {
228
                        $actions .= '<a href="index.php?'.api_get_cidreq().'&action=attendance_set_visible&attendance_id='.$attendance[0].'">'.
229
                            Display::return_icon('invisible.png', get_lang('Show'), [], ICON_SIZE_SMALL).'</a>';
230
                        $attendance[2] = '<span class="muted">'.$attendance[2].'</span>';
231
                    }
232
                    if ($allowDelete === 'true') {
233
                        $actions .= '<a href="index.php?'.api_get_cidreq().'&action=attendance_delete&attendance_id='.$attendance[0].'">'.
234
                            Display::return_icon('delete.png', get_lang('Delete'), [], ICON_SIZE_SMALL).'</a>';
235
                    }
236
                } else {
237
                    $is_locked_attendance = self::is_locked_attendance($attendance[0]);
238
                    if ($is_locked_attendance) {
239
                        $actions .= Display::return_icon('edit_na.png', get_lang('Edit')).'&nbsp;';
240
                        $actions .= Display::return_icon('visible.png', get_lang('Hide'));
241
                    } else {
242
                        $actions .= '<a href="index.php?'.api_get_cidreq().'&action=attendance_edit&attendance_id='.$attendance[0].'">'.
243
                            Display::return_icon('edit.png', get_lang('Edit'), [], ICON_SIZE_SMALL).'</a>&nbsp;';
244
245
                        if ($attendance[5] == 1) {
246
                            $actions .= ' <a href="index.php?'.api_get_cidreq().'&action=attendance_set_invisible&attendance_id='.$attendance[0].'">'.
247
                                Display::return_icon('visible.png', get_lang('Hide'), [], ICON_SIZE_SMALL).'</a>';
248
                        } else {
249
                            $actions .= ' <a href="index.php?'.api_get_cidreq().'&action=attendance_set_visible&attendance_id='.$attendance[0].'">'.
250
                                Display::return_icon('invisible.png', get_lang('Show'), [], ICON_SIZE_SMALL).'</a>';
251
                            $attendance[2] = '<span class="muted">'.$attendance[2].'</span>';
252
                        }
253
                        if ($allowDelete === 'true') {
254
                            $actions .= ' <a href="index.php?'.api_get_cidreq().'&action=attendance_delete&attendance_id='.$attendance[0].'">'.
255
                                Display::return_icon('delete.png', get_lang('Delete'), [], ICON_SIZE_SMALL).'</a>';
256
                        }
257
                    }
258
                }
259
260
                // display lock/unlock icon
261
                $is_done_all_calendar = self::is_all_attendance_calendar_done($attendance[0]);
262
263
                if ($is_done_all_calendar) {
264
                    $locked = $attendance[4];
265
                    if ($locked == 0) {
266
                        if (api_is_platform_admin()) {
267
                            $message_alert = get_lang('AreYouSureToLockTheAttendance');
268
                        } else {
269
                            $message_alert = get_lang('UnlockMessageInformation');
270
                        }
271
                        $actions .= '&nbsp;<a onclick="javascript:if(!confirm(\''.$message_alert.'\')) return false;" href="index.php?'.api_get_cidreq().'&action=lock_attendance&attendance_id='.$attendance[0].'">'.
272
                            Display::return_icon('lock-open.png', get_lang('LockAttendance')).'</a>';
273
                    } else {
274
                        if (api_is_platform_admin()) {
275
                            $actions .= '&nbsp;<a onclick="javascript:if(!confirm(\''.get_lang('AreYouSureToUnlockTheAttendance').'\')) return false;" href="index.php?'.api_get_cidreq().'&action=unlock_attendance&attendance_id='.$attendance[0].'">'.
276
                                    Display::return_icon('lock-closed.png', get_lang('UnlockAttendance')).'</a>';
277
                        } else {
278
                            $actions .= '&nbsp;'.Display::return_icon('locked_na.png', get_lang('LockedAttendance'));
279
                        }
280
                    }
281
                }
282
                $actions .= '</center>';
283
284
                $attendances[] = [
285
                    $attendance[0],
286
                    $attendance[1],
287
                    Security::remove_XSS($attendance[2]),
288
                    $attendance[3],
289
                    $actions,
290
                ];
291
            } else {
292
                $attendance[0] = '&nbsp;';
293
                $attendances[] = [
294
                    $attendance[0],
295
                    $attendance[1],
296
                    Security::remove_XSS($attendance[2]),
297
                    $attendance[3],
298
                ];
299
            }
300
        }
301
302
        return $attendances;
303
    }
304
305
    /**
306
     * Get the attendances by id to display on the current page.
307
     *
308
     * @param int $attendanceId
309
     *
310
     * @return array attendance data
311
     */
312
    public function get_attendance_by_id($attendanceId)
313
    {
314
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
315
        $attendanceId = (int) $attendanceId;
316
        $course_id = api_get_course_int_id();
317
        $attendance_data = [];
318
        $sql = "SELECT * FROM $tbl_attendance
319
                WHERE c_id = $course_id AND id = '$attendanceId'";
320
        $res = Database::query($sql);
321
        if (Database::num_rows($res) > 0) {
322
            while ($row = Database::fetch_array($res)) {
323
                $attendance_data = $row;
324
            }
325
        }
326
327
        return $attendance_data;
328
    }
329
330
    /**
331
     * Add attendances sheet inside table. This is the *list of* dates, not
332
     * a specific date in itself.
333
     *
334
     * @param  bool   true for adding link in gradebook or false otherwise (optional)
335
     *
336
     * @return int last attendance id
337
     */
338
    public function attendance_add($link_to_gradebook = false)
339
    {
340
        $_course = api_get_course_info();
341
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
342
        $table_link = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
343
        $session_id = api_get_session_id();
344
        $user_id = api_get_user_id();
345
        $course_code = $_course['code'];
346
        $course_id = $_course['real_id'];
347
        $title_gradebook = $this->attendance_qualify_title;
348
        $value_calification = 0;
349
        $weight_calification = api_float_val($this->attendance_weight);
350
351
        $params = [
352
            'c_id' => $course_id,
353
            'name' => $this->name,
354
            'description' => $this->description,
355
            'attendance_qualify_title' => $title_gradebook,
356
            'attendance_weight' => $weight_calification,
357
            'session_id' => $session_id,
358
            'active' => 1,
359
            'attendance_qualify_max' => 0,
360
            'locked' => 0,
361
        ];
362
        $last_id = Database::insert($tbl_attendance, $params);
363
364
        if (!empty($last_id)) {
365
            $sql = "UPDATE $tbl_attendance SET id = iid WHERE iid = $last_id";
366
            Database::query($sql);
367
368
            api_item_property_update(
369
                $_course,
370
                TOOL_ATTENDANCE,
371
                $last_id,
372
                "AttendanceAdded",
373
                $user_id
374
            );
375
        }
376
        // add link to gradebook
377
        if ($link_to_gradebook && !empty($this->category_id)) {
378
            $description = '';
379
            $link_info = GradebookUtils::isResourceInCourseGradebook(
380
                $course_code,
381
                7,
382
                $last_id,
383
                $session_id
384
            );
385
            $link_id = $link_info['id'];
386
            if (!$link_info) {
387
                GradebookUtils::add_resource_to_course_gradebook(
388
                    $this->category_id,
389
                    $course_code,
390
                    7,
391
                    $last_id,
392
                    $title_gradebook,
393
                    $weight_calification,
394
                    $value_calification,
395
                    $description,
396
                    1,
397
                    $session_id
398
                );
399
            } else {
400
                Database::query('UPDATE '.$table_link.' SET weight='.$weight_calification.' WHERE id='.$link_id.'');
401
            }
402
        }
403
404
        return $last_id;
405
    }
406
407
    /**
408
     * edit attendances inside table.
409
     *
410
     * @param int attendance id
411
     * @param bool true for adding link in gradebook or false otherwise (optional)
412
     *
413
     * @return int last id
414
     */
415
    public function attendance_edit($attendanceId, $link_to_gradebook = false)
416
    {
417
        $_course = api_get_course_info();
418
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
419
        $table_link = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
420
421
        $session_id = api_get_session_id();
422
        $user_id = api_get_user_id();
423
        $attendanceId = (int) $attendanceId;
424
        $course_code = $_course['code'];
425
        $course_id = $_course['real_id'];
426
        $title_gradebook = $this->attendance_qualify_title;
427
        $value_calification = 0;
428
        $weight_calification = api_float_val($this->attendance_weight);
429
430
        if (!empty($attendanceId)) {
431
            $params = [
432
                'name' => $this->name,
433
                'description' => $this->description,
434
                'attendance_qualify_title' => $title_gradebook,
435
                'attendance_weight' => $weight_calification,
436
            ];
437
            Database::update(
438
                $tbl_attendance,
439
                $params,
440
                ['c_id = ? AND id = ?' => [$course_id, $attendanceId]]
441
            );
442
443
            api_item_property_update(
444
                $_course,
445
                TOOL_ATTENDANCE,
446
                $attendanceId,
447
                "AttendanceUpdated",
448
                $user_id
449
            );
450
451
            // add link to gradebook
452
            if ($link_to_gradebook && !empty($this->category_id)) {
453
                $description = '';
454
                $link_info = GradebookUtils::isResourceInCourseGradebook(
455
                    $course_code,
456
                    7,
457
                    $attendanceId,
458
                    $session_id
459
                );
460
                if (!$link_info) {
461
                    GradebookUtils::add_resource_to_course_gradebook(
462
                        $this->category_id,
463
                        $course_code,
464
                        7,
465
                        $attendanceId,
466
                        $title_gradebook,
467
                        $weight_calification,
468
                        $value_calification,
469
                        $description,
470
                        1,
471
                        $session_id
472
                    );
473
                } else {
474
                    Database::query('UPDATE '.$table_link.' SET weight='.$weight_calification.' WHERE id='.$link_info['id'].'');
475
                }
476
            }
477
478
            return $attendanceId;
479
        }
480
481
        return null;
482
    }
483
484
    /**
485
     * Restore attendance.
486
     *
487
     * @param int|array one or many attendances id
488
     *
489
     * @return int affected rows
490
     */
491
    public function attendance_restore($attendanceId)
492
    {
493
        $_course = api_get_course_info();
494
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
495
        $user_id = api_get_user_id();
496
        $course_id = $_course['real_id'];
497
        if (is_array($attendanceId)) {
498
            foreach ($attendanceId as $id) {
499
                $id = (int) $id;
500
                $sql = "UPDATE $tbl_attendance SET active = 1
501
                        WHERE c_id = $course_id AND id = '$id'";
502
                $result = Database::query($sql);
503
                $affected_rows = Database::affected_rows($result);
504
                if (!empty($affected_rows)) {
505
                    // update row item property table
506
                    api_item_property_update(
507
                        $_course,
508
                        TOOL_ATTENDANCE,
509
                        $id,
510
                        'restore',
511
                        $user_id
512
                    );
513
                }
514
            }
515
        } else {
516
            $attendanceId = (int) $attendanceId;
517
            $sql = "UPDATE $tbl_attendance SET active = 1
518
                    WHERE c_id = $course_id AND id = '$attendanceId'";
519
            $result = Database::query($sql);
520
            $affected_rows = Database::affected_rows($result);
521
            if (!empty($affected_rows)) {
522
                // update row item property table
523
                api_item_property_update(
524
                    $_course,
525
                    TOOL_ATTENDANCE,
526
                    $attendanceId,
527
                    'restore',
528
                    $user_id
529
                );
530
            }
531
        }
532
533
        return $affected_rows;
534
    }
535
536
    /**
537
     * Delete attendances.
538
     *
539
     * @param int|array $attendanceId one or many attendances id
540
     *
541
     * @return int affected rows
542
     */
543
    public function attendance_delete($attendanceId)
544
    {
545
        $_course = api_get_course_info();
546
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
547
        $user_id = api_get_user_id();
548
        $course_id = $_course['real_id'];
549
550
        if (is_array($attendanceId)) {
551
            foreach ($attendanceId as $id) {
552
                $id = intval($id);
553
                $sql = "UPDATE $tbl_attendance SET active = 2
554
                        WHERE c_id = $course_id AND id = '$id'";
555
                $result = Database::query($sql);
556
                $affected_rows = Database::affected_rows($result);
557
                if (!empty($affected_rows)) {
558
                    // update row item property table
559
                    api_item_property_update(
560
                        $_course,
561
                        TOOL_ATTENDANCE,
562
                        $id,
563
                        "delete",
564
                        $user_id
565
                    );
566
                }
567
            }
568
        } else {
569
            $attendanceId = intval($attendanceId);
570
            $sql = "UPDATE $tbl_attendance SET active = 2
571
                    WHERE c_id = $course_id AND id = '$attendanceId'";
572
573
            $result = Database::query($sql);
574
            $affected_rows = Database::affected_rows($result);
575
            if (!empty($affected_rows)) {
576
                // update row item property table
577
                api_item_property_update(
578
                    $_course,
579
                    TOOL_ATTENDANCE,
580
                    $attendanceId,
581
                    "delete",
582
                    $user_id
583
                );
584
            }
585
        }
586
587
        return $affected_rows;
588
    }
589
590
    /**
591
     * Changes visibility.
592
     *
593
     * @param int|array $attendanceId one or many attendances id
594
     * @param int       $status
595
     *
596
     * @return int affected rows
597
     */
598
    public function changeVisibility($attendanceId, $status = 1)
599
    {
600
        $_course = api_get_course_info();
601
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
602
        $user_id = api_get_user_id();
603
        $course_id = $_course['real_id'];
604
        $status = (int) $status;
605
606
        $action = 'visible';
607
        if ($status == 0) {
608
            $action = 'invisible';
609
        }
610
611
        if (is_array($attendanceId)) {
612
            foreach ($attendanceId as $id) {
613
                $id = (int) $id;
614
                $sql = "UPDATE $tbl_attendance SET active = $status
615
                        WHERE c_id = $course_id AND id = '$id'";
616
                $result = Database::query($sql);
617
                $affected_rows = Database::affected_rows($result);
618
                if (!empty($affected_rows)) {
619
                    // update row item property table
620
                    api_item_property_update(
621
                        $_course,
622
                        TOOL_ATTENDANCE,
623
                        $id,
624
                        $action,
625
                        $user_id
626
                    );
627
                }
628
            }
629
        } else {
630
            $attendanceId = (int) $attendanceId;
631
            $sql = "UPDATE $tbl_attendance SET active = $status
632
                    WHERE c_id = $course_id AND id = '$attendanceId'";
633
            $result = Database::query($sql);
634
            $affected_rows = Database::affected_rows($result);
635
            if (!empty($affected_rows)) {
636
                // update row item property table
637
                api_item_property_update(
638
                    $_course,
639
                    TOOL_ATTENDANCE,
640
                    $attendanceId,
641
                    $action,
642
                    $user_id
643
                );
644
            }
645
        }
646
647
        return $affected_rows;
648
    }
649
650
    /**
651
     * Lock or unlock an attendance.
652
     *
653
     * @param   int     attendance id
654
     * @param   bool    True to lock or false otherwise
655
     *
656
     * @return int
657
     */
658
    public function lock_attendance($attendanceId, $lock = true)
659
    {
660
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
661
        $course_id = api_get_course_int_id();
662
        $attendanceId = (int) $attendanceId;
663
        $locked = $lock ? 1 : 0;
664
        $upd = "UPDATE $tbl_attendance SET locked = $locked
665
                WHERE c_id = $course_id AND id = $attendanceId";
666
        $result = Database::query($upd);
667
        $affected_rows = Database::affected_rows($result);
668
        if ($affected_rows && $lock) {
669
            // Save attendance sheet log
670
            $this->saveAttendanceSheetLog(
671
                $attendanceId,
672
                api_get_utc_datetime(),
673
                self::LOCKED_ATTENDANCE_LOG_TYPE,
674
                api_get_user_id()
675
            );
676
        }
677
678
        return $affected_rows;
679
    }
680
681
    /**
682
     * Get registered users inside current course.
683
     *
684
     * @param int $attendanceId attendance id for showing attendance result field (optional)
685
     * @param int $groupId
686
     *
687
     * @return array users data
688
     */
689
    public function get_users_rel_course($attendanceId = 0, $groupId = 0)
690
    {
691
        $current_session_id = api_get_session_id();
692
        $current_course_id = api_get_course_id();
693
        $currentCourseIntId = api_get_course_int_id();
694
        $studentInGroup = [];
695
696
        if (!empty($current_session_id)) {
697
            $a_course_users = CourseManager::get_user_list_from_course_code(
698
                $current_course_id,
699
                $current_session_id,
700
                '',
701
                'lastname'
702
            );
703
        } else {
704
            $a_course_users = CourseManager::get_user_list_from_course_code(
705
                $current_course_id,
706
                0,
707
                '',
708
                'lastname'
709
            );
710
        }
711
712
        if (!empty($groupId)) {
713
            $groupInfo = GroupManager::get_group_properties($groupId);
714
            $students = GroupManager::getStudents($groupInfo['iid']);
715
            if (!empty($students)) {
716
                foreach ($students as $student) {
717
                    $studentInGroup[$student['user_id']] = true;
718
                }
719
            }
720
        }
721
722
        // get registered users inside current course
723
        $a_users = [];
724
        foreach ($a_course_users as $key => $user_data) {
725
            $value = [];
726
            $uid = $user_data['user_id'];
727
            $userInfo = api_get_user_info($uid);
728
            $status = $user_data['status'];
729
730
            if (!empty($groupId)) {
731
                if (!isset($studentInGroup[$uid])) {
732
                    continue;
733
                }
734
            }
735
736
            $user_status_in_session = null;
737
            $user_status_in_course = null;
738
739
            if (api_get_session_id()) {
740
                $user_status_in_session = SessionManager::get_user_status_in_course_session(
741
                    $uid,
742
                    $currentCourseIntId,
743
                    $current_session_id
744
                );
745
            } else {
746
                $user_status_in_course = CourseManager::getUserInCourseStatus(
747
                    $uid,
748
                    $currentCourseIntId
749
                );
750
            }
751
752
            // Not taking into account DRH or COURSEMANAGER
753
            if ($uid <= 1 ||
754
                $status == DRH ||
755
                $user_status_in_course == COURSEMANAGER ||
756
                $user_status_in_session == 2
757
            ) {
758
                continue;
759
            }
760
761
            if (!empty($attendanceId)) {
762
                $user_faults = $this->get_faults_of_user(
763
                    $uid,
764
                    $attendanceId,
765
                    $groupId
766
                );
767
                $value['attendance_result'] = $user_faults['faults'].'/'.$user_faults['total'].' ('.$user_faults['faults_porcent'].'%)';
768
                $value['result_color_bar'] = $user_faults['color_bar'];
769
            }
770
771
            $photo = Display::img(
772
                $userInfo['avatar_small'],
773
                $userInfo['complete_name'],
774
                [],
775
                false
776
            );
777
778
            $value['photo'] = $photo;
779
            $value['firstname'] = $user_data['firstname'];
780
            $value['lastname'] = $user_data['lastname'];
781
            $value['username'] = $user_data['username'];
782
            $value['user_id'] = $uid;
783
784
            // Sending only 5 items in the array instead of 60
785
            $a_users[$key] = $value;
786
        }
787
788
        return $a_users;
789
    }
790
791
    /**
792
     * add attendances sheet inside table.
793
     *
794
     * @param int   $calendar_id   attendance calendar id
795
     * @param array $users_present present users during current class
796
     * @param int   $attendanceId
797
     *
798
     * @return int affected rows
799
     */
800
    public function attendance_sheet_add($calendar_id, $users_present, $attendanceId)
801
    {
802
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
803
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
804
805
        $calendar_id = (int) $calendar_id;
806
        $attendanceId = (int) $attendanceId;
807
        $users = $this->get_users_rel_course();
808
        $course_id = api_get_course_int_id();
809
810
        $user_ids = array_keys($users);
811
        $users_absent = array_diff($user_ids, $users_present);
812
        $affected_rows = 0;
813
814
        // get last edit type
815
        $calendar_data = $this->get_attendance_calendar_by_id($calendar_id);
816
        $lastedit_type = self::DONE_ATTENDANCE_LOG_TYPE;
817
        if ($calendar_data['done_attendance']) {
818
            $lastedit_type = self::UPDATED_ATTENDANCE_LOG_TYPE;
819
        }
820
821
        // save users present in class
822
        foreach ($users_present as $user_present) {
823
            $uid = (int) $user_present;
824
            // check if user already was registered with the $calendar_id
825
            $sql = "SELECT user_id FROM $tbl_attendance_sheet
826
                    WHERE c_id = $course_id AND user_id='$uid' AND attendance_calendar_id = '$calendar_id'";
827
            $rs = Database::query($sql);
828
            if (Database::num_rows($rs) == 0) {
829
                $sql = "INSERT INTO $tbl_attendance_sheet SET
830
                        c_id = $course_id,
831
                        user_id = '$uid',
832
                        attendance_calendar_id = '$calendar_id',
833
                        presence = 1";
834
                $result = Database::query($sql);
835
836
                $affected_rows += Database::affected_rows($result);
837
            } else {
838
                $sql = "UPDATE $tbl_attendance_sheet SET presence = 1
839
                        WHERE
840
                            c_id = $course_id AND
841
                            user_id ='$uid' AND
842
                            attendance_calendar_id = '$calendar_id'
843
                        ";
844
                $result = Database::query($sql);
845
                $affected_rows += Database::affected_rows($result);
846
            }
847
        }
848
849
        // save users absent in class
850
        foreach ($users_absent as $user_absent) {
851
            $uid = intval($user_absent);
852
            // check if user already was registered with the $calendar_id
853
            $sql = "SELECT user_id FROM $tbl_attendance_sheet
854
                    WHERE c_id = $course_id AND user_id='$uid' AND attendance_calendar_id = '$calendar_id'";
855
            $rs = Database::query($sql);
856
            if (Database::num_rows($rs) == 0) {
857
                $sql = "INSERT INTO $tbl_attendance_sheet SET
858
                        c_id = $course_id,
859
                        user_id ='$uid',
860
                        attendance_calendar_id = '$calendar_id',
861
                        presence = 0";
862
                $result = Database::query($sql);
863
864
                Database::insert_id();
865
866
                $affected_rows += Database::affected_rows($result);
867
            } else {
868
                $sql = "UPDATE $tbl_attendance_sheet SET presence = 0
869
                        WHERE
870
                            c_id = $course_id AND
871
                            user_id ='$uid' AND
872
                            attendance_calendar_id = '$calendar_id'";
873
                $result = Database::query($sql);
874
                $affected_rows += Database::affected_rows($result);
875
            }
876
        }
877
878
        // update done_attendance inside attendance calendar table
879
        $sql = "UPDATE $tbl_attendance_calendar SET done_attendance = 1
880
                WHERE  c_id = $course_id AND id = '$calendar_id'";
881
        Database::query($sql);
882
883
        // save users' results
884
        $this->updateUsersResults($user_ids, $attendanceId);
885
886
        if ($affected_rows) {
887
            //save attendance sheet log
888
            $this->saveAttendanceSheetLog(
889
                $attendanceId,
890
                api_get_utc_datetime(),
891
                $lastedit_type,
892
                api_get_user_id(),
893
                $calendar_data['date_time']
894
            );
895
        }
896
897
        return $affected_rows;
898
    }
899
900
    /**
901
     * update users' attendance results.
902
     *
903
     * @param array $user_ids     registered users inside current course
904
     * @param int   $attendanceId
905
     */
906
    public function updateUsersResults($user_ids, $attendanceId)
907
    {
908
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
909
        $tbl_attendance_result = Database::get_course_table(TABLE_ATTENDANCE_RESULT);
910
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
911
        $course_id = api_get_course_int_id();
912
        $attendanceId = intval($attendanceId);
913
        // fill results about presence of students
914
        $attendance_calendar = $this->get_attendance_calendar(
915
            $attendanceId,
916
            'all',
917
            null,
918
            null,
919
            true
920
        );
921
        $calendar_ids = [];
922
        // get all dates from calendar by current attendance
923
        foreach ($attendance_calendar as $cal) {
924
            $calendar_ids[] = $cal['id'];
925
        }
926
927
        // get count of presences by users inside current attendance and save like results
928
        if (count($user_ids) > 0) {
929
            foreach ($user_ids as $uid) {
930
                $uid = (int) $uid;
931
                $count_presences = 0;
932
                if (count($calendar_ids) > 0) {
933
                    $sql = "SELECT count(presence) as count_presences
934
                            FROM $tbl_attendance_sheet
935
                            WHERE
936
                                c_id = $course_id AND
937
                                user_id = '$uid' AND
938
                                attendance_calendar_id IN (".implode(',', $calendar_ids).") AND
939
                                presence = 1";
940
                    $rs_count = Database::query($sql);
941
                    $row_count = Database::fetch_array($rs_count);
942
                    $count_presences = $row_count['count_presences'];
943
                }
944
945
                // save results
946
                $sql = "SELECT id FROM $tbl_attendance_result
947
                        WHERE
948
                            c_id = $course_id AND
949
                            user_id = '$uid' AND
950
                            attendance_id = '$attendanceId' ";
951
                $rs_check_result = Database::query($sql);
952
953
                if (Database::num_rows($rs_check_result) > 0) {
954
                    // update result
955
                    $sql = "UPDATE $tbl_attendance_result SET
956
                            score = '$count_presences'
957
                            WHERE
958
                                c_id = $course_id AND
959
                                user_id='$uid' AND
960
                                attendance_id='$attendanceId'";
961
                    Database::query($sql);
962
                } else {
963
                    // insert new result
964
                    $sql = "INSERT INTO $tbl_attendance_result SET
965
                            c_id = $course_id ,
966
                            user_id			= '$uid',
967
                            attendance_id 	= '$attendanceId',
968
                            score			= '$count_presences'";
969
                    Database::query($sql);
970
971
                    $insertId = Database::insert_id();
972
                    if ($insertId) {
973
                        $sql = "UPDATE $tbl_attendance_result SET id = iid WHERE iid = $insertId";
974
                        Database::query($sql);
975
                    }
976
                }
977
            }
978
        }
979
980
        // update attendance qualify max
981
        $count_done_calendar = self::get_done_attendance_calendar($attendanceId);
982
        $sql = "UPDATE $tbl_attendance SET
983
                    attendance_qualify_max = '$count_done_calendar'
984
                WHERE c_id = $course_id AND id = '$attendanceId'";
985
        Database::query($sql);
986
    }
987
988
    /**
989
     * update attendance_sheet_log table, is used as history of an attendance sheet.
990
     *
991
     * @param   int     Attendance id
992
     * @param   string  Last edit datetime
993
     * @param   string  Event type ('locked_attendance', 'done_attendance_sheet' ...)
994
     * @param   int     Last edit user id
995
     * @param   string  Calendar datetime value (optional, when event type is 'done_attendance_sheet')
996
     *
997
     * @return int Affected rows
998
     */
999
    public function saveAttendanceSheetLog(
1000
        $attendanceId,
1001
        $lastedit_date,
1002
        $lastedit_type,
1003
        $lastedit_user_id,
1004
        $calendar_date_value = null
1005
    ) {
1006
        $course_id = api_get_course_int_id();
1007
1008
        // define table
1009
        $tbl_attendance_sheet_log = Database::get_course_table(TABLE_ATTENDANCE_SHEET_LOG);
1010
1011
        // protect data
1012
        $attendanceId = intval($attendanceId);
1013
        $lastedit_user_id = intval($lastedit_user_id);
1014
1015
        if (isset($calendar_date_value)) {
1016
            $calendar_date_value = $calendar_date_value;
1017
        } else {
1018
            $calendar_date_value = '';
1019
        }
1020
1021
        // save data
1022
        $params = [
1023
            'c_id' => $course_id,
1024
            'attendance_id' => $attendanceId,
1025
            'lastedit_date' => $lastedit_date,
1026
            'lastedit_type' => $lastedit_type,
1027
            'lastedit_user_id' => $lastedit_user_id,
1028
            'calendar_date_value' => $calendar_date_value,
1029
        ];
1030
        $insertId = Database::insert($tbl_attendance_sheet_log, $params);
1031
        if ($insertId) {
1032
            $sql = "UPDATE $tbl_attendance_sheet_log SET id = iid WHERE iid = $insertId";
1033
            Database::query($sql);
1034
        }
1035
1036
        return $insertId;
1037
    }
1038
1039
    /**
1040
     * Get number of done attendances inside current sheet.
1041
     *
1042
     * @param int attendance id
1043
     *
1044
     * @return int number of done attendances
1045
     */
1046
    public static function get_done_attendance_calendar($attendanceId)
1047
    {
1048
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1049
        $attendanceId = intval($attendanceId);
1050
        $course_id = api_get_course_int_id();
1051
        $sql = "SELECT count(done_attendance) as count
1052
                FROM $table
1053
                WHERE
1054
                    c_id = $course_id AND
1055
                    attendance_id = '$attendanceId' AND
1056
                    done_attendance = 1
1057
                ";
1058
        $rs = Database::query($sql);
1059
        $row = Database::fetch_array($rs);
1060
        $count = $row['count'];
1061
1062
        return $count;
1063
    }
1064
1065
    /**
1066
     * Get results of faults (absents) by user.
1067
     *
1068
     * @param int $user_id
1069
     * @param int $attendanceId
1070
     * @param int $groupId
1071
     *
1072
     * @return array results containing number of faults, total done attendance,
1073
     *               percent of faults and color depend on result (red, orange)
1074
     */
1075
    public function get_faults_of_user($user_id, $attendanceId, $groupId = null)
1076
    {
1077
        $user_id = intval($user_id);
1078
        $attendanceId = intval($attendanceId);
1079
        $results = [];
1080
        $calendar_count = self::get_number_of_attendance_calendar(
1081
            $attendanceId,
1082
            $groupId,
1083
            null,
1084
            $user_id
1085
        );
1086
        // $total_done_attendance 	= $attendance_data['attendance_qualify_max'];
1087
        $total_done_attendance = self::get_number_of_attendance_calendar(
1088
            $attendanceId,
1089
            $groupId,
1090
            true,
1091
            $user_id
1092
        );
1093
        $attendance_user_score = $this->get_user_score(
1094
            $user_id,
1095
            $attendanceId,
1096
            $groupId
1097
        );
1098
1099
        //This is the main change of the BT#1381
1100
        //$total_done_attendance = $calendar_count;
1101
1102
        // calculate results
1103
        $faults = $total_done_attendance - $attendance_user_score;
1104
1105
        if (empty($calendar_count)) {
1106
            $faults = 0;
1107
        }
1108
1109
        $faults = $faults > 0 ? $faults : 0;
1110
        $faults_porcent = $calendar_count > 0 ? round(($faults * 100) / $calendar_count, 0) : 0;
1111
        $results['faults'] = $faults;
1112
        $results['total'] = $calendar_count;
1113
        $results['faults_porcent'] = $faults_porcent;
1114
        $color_bar = '';
1115
1116
        if ($faults_porcent > 25) {
1117
            $color_bar = '#f28989';
1118
        } elseif ($faults_porcent > 10) {
1119
            $color_bar = '#F90';
1120
        }
1121
        $results['color_bar'] = $color_bar;
1122
1123
        return $results;
1124
    }
1125
1126
    /**
1127
     * Get results of faults average for all courses by user.
1128
     *
1129
     * @param int $user_id
1130
     *
1131
     * @return array results containing number of faults, total done attendance,
1132
     *               percentage of faults and color depend on result (red, orange)
1133
     */
1134
    public function get_faults_average_inside_courses($user_id)
1135
    {
1136
        // get all courses of current user
1137
        $courses = CourseManager::get_courses_list_by_user_id($user_id, true);
1138
        $user_id = intval($user_id);
1139
        $results = [];
1140
        $total_faults = $total_weight = $porcent = 0;
1141
        foreach ($courses as $course) {
1142
            //$course_code = $course['code'];
1143
            //$course_info = api_get_course_info($course_code);
1144
            $course_id = $course['real_id'];
1145
            $tbl_attendance_result = Database::get_course_table(TABLE_ATTENDANCE_RESULT);
1146
            $attendances_by_course = $this->get_attendances_list($course_id);
1147
1148
            foreach ($attendances_by_course as $attendance) {
1149
                // get total faults and total weight
1150
                $total_done_attendance = $attendance['attendance_qualify_max'];
1151
                $sql = "SELECT score
1152
                        FROM $tbl_attendance_result
1153
                        WHERE
1154
                            c_id = $course_id AND
1155
                            user_id = $user_id AND
1156
                            attendance_id = ".$attendance['id'];
1157
                $rs = Database::query($sql);
1158
                $score = 0;
1159
                if (Database::num_rows($rs) > 0) {
1160
                    $row = Database::fetch_array($rs);
1161
                    $score = $row['score'];
1162
                }
1163
                $faults = $total_done_attendance - $score;
1164
                $faults = $faults > 0 ? $faults : 0;
1165
                $total_faults += $faults;
1166
                $total_weight += $total_done_attendance;
1167
            }
1168
        }
1169
1170
        $porcent = $total_weight > 0 ? round(($total_faults * 100) / $total_weight, 0) : 0;
1171
        $results['faults'] = $total_faults;
1172
        $results['total'] = $total_weight;
1173
        $results['porcent'] = $porcent;
1174
1175
        return $results;
1176
    }
1177
1178
    /**
1179
     * Get results of faults average by course.
1180
     *
1181
     * @param int    $user_id
1182
     * @param string $course_code
1183
     * @param int Session id (optional)
1184
     *
1185
     * @return array results containing number of faults,
1186
     *               total done attendance, porcent of faults and color depend on result (red, orange)
1187
     */
1188
    public function get_faults_average_by_course(
1189
        $user_id,
1190
        $course_code,
1191
        $session_id = null
1192
    ) {
1193
        // Database tables and variables
1194
        $course_info = api_get_course_info($course_code);
1195
        $tbl_attendance_result = Database::get_course_table(TABLE_ATTENDANCE_RESULT);
1196
        $user_id = intval($user_id);
1197
        $results = [];
1198
        $total_faults = $total_weight = $porcent = 0;
1199
        $attendances_by_course = $this->get_attendances_list(
1200
            $course_info['real_id'],
1201
            $session_id
1202
        );
1203
1204
        foreach ($attendances_by_course as $attendance) {
1205
            // Get total faults and total weight
1206
            $total_done_attendance = $attendance['attendance_qualify_max'];
1207
            $sql = "SELECT score FROM $tbl_attendance_result
1208
                    WHERE
1209
                        c_id = {$course_info['real_id']} AND
1210
                        user_id = $user_id AND
1211
                        attendance_id=".$attendance['id'];
1212
            $rs = Database::query($sql);
1213
            $score = 0;
1214
            if (Database::num_rows($rs) > 0) {
1215
                $row = Database::fetch_array($rs);
1216
                $score = $row['score'];
1217
            }
1218
            $faults = $total_done_attendance - $score;
1219
            $faults = $faults > 0 ? $faults : 0;
1220
            $total_faults += $faults;
1221
            $total_weight += $total_done_attendance;
1222
        }
1223
1224
        $porcent = $total_weight > 0 ? round(($total_faults * 100) / $total_weight, 0) : 0;
1225
        $results['faults'] = $total_faults;
1226
        $results['total'] = $total_weight;
1227
        $results['porcent'] = $porcent;
1228
1229
        return $results;
1230
    }
1231
1232
    /**
1233
     * Get registered users' attendance sheet inside current course or course by id.
1234
     *
1235
     * @param int      $attendanceId
1236
     * @param int      $user_id      for showing data for only one user (optional)
1237
     * @param int      $groupId
1238
     * @param int      $course_id    if id = 0 get the current course
1239
     * @param DateTime $startDate    Filter atttendance sheet with a start date
1240
     * @param DateTime $endDate      Filter atttendance sheet with a end date
1241
     *
1242
     * @return array users attendance sheet data
1243
     */
1244
    public function get_users_attendance_sheet(
1245
        $attendanceId,
1246
        $user_id = 0,
1247
        $groupId = 0,
1248
        $course_id = 0,
1249
        DateTime $startDate = null,
1250
        DateTime $endDate = null
1251
    ) {
1252
        //Get actual course or by course_id
1253
        $course_id = (0 == $course_id) ? api_get_course_int_id() : (int) $course_id;
1254
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
1255
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1256
        $attendance_calendar = $this->get_attendance_calendar(
1257
            $attendanceId,
1258
            'all',
1259
            null,
1260
            $groupId,
1261
            true,
1262
            $course_id,
1263
            $startDate,
1264
            $endDate
1265
        );
1266
        $calendar_ids = [];
1267
        // get all dates from calendar by current attendance
1268
        foreach ($attendance_calendar as $cal) {
1269
            $calendar_ids[] = $cal['id'];
1270
        }
1271
1272
        $whereDate = '';
1273
        if (!empty($startDate)) {
1274
            $whereDate .= " AND cal.date_time >= '".$startDate->format('Y-m-d H:i:s')."'";
1275
        }
1276
        if (!empty($endDate)) {
1277
            $whereDate .= " AND cal.date_time <= '".$endDate->format('Y-m-d H:i:s')."'";
1278
        }
1279
1280
        // moved at start of this function
1281
        // $course_id = api_get_course_int_id();
1282
1283
        $data = [];
1284
        if (empty($user_id)) {
1285
            // get all registered users inside current course
1286
            $users = $this->get_users_rel_course();
1287
            $user_ids = array_keys($users);
1288
            if (count($calendar_ids) > 0 && count($user_ids) > 0) {
1289
                foreach ($user_ids as $uid) {
1290
                    $uid = (int) $uid;
1291
                    $sql = "SELECT * FROM $tbl_attendance_sheet
1292
                            WHERE
1293
                                c_id = $course_id AND
1294
                                user_id = '$uid' AND
1295
                                attendance_calendar_id IN(".implode(',', $calendar_ids).")
1296
                            ";
1297
                    $res = Database::query($sql);
1298
                    if (Database::num_rows($res) > 0) {
1299
                        while ($row = Database::fetch_array($res)) {
1300
                            $data[$uid][$row['attendance_calendar_id']]['presence'] = $row['presence'];
1301
                        }
1302
                    }
1303
                }
1304
            }
1305
        } else {
1306
            // Get attendance for current user
1307
            $user_id = (int) $user_id;
1308
            if (count($calendar_ids) > 0) {
1309
                $sql = "SELECT cal.date_time, att.presence, cal.iid as calendar_id
1310
                        FROM $tbl_attendance_sheet att
1311
                        INNER JOIN  $tbl_attendance_calendar cal
1312
                        ON cal.id = att.attendance_calendar_id
1313
                        WHERE
1314
                            att.c_id = $course_id AND
1315
                            cal.c_id =  $course_id AND
1316
                            att.user_id = '$user_id' AND
1317
                            att.attendance_calendar_id IN (".implode(',', $calendar_ids).")
1318
                            $whereDate
1319
                        ORDER BY date_time";
1320
                $res = Database::query($sql);
1321
                if (Database::num_rows($res) > 0) {
1322
                    while ($row = Database::fetch_array($res)) {
1323
                        $row['duration'] = Attendance::getAttendanceCalendarExtraFieldValue('duration', $row['calendar_id']);
1324
                        $row['date_time'] = api_convert_and_format_date($row['date_time'], null, date_default_timezone_get());
1325
                        $data[$user_id][] = $row;
1326
                    }
1327
                }
1328
            }
1329
        }
1330
1331
        return $data;
1332
    }
1333
1334
    /**
1335
     * Get next attendance calendar without presences (done attendances).
1336
     *
1337
     * @param int    attendance id
1338
     *
1339
     * @return int attendance calendar id
1340
     */
1341
    public function get_next_attendance_calendar_id($attendanceId)
1342
    {
1343
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1344
        $attendanceId = (int) $attendanceId;
1345
        $course_id = api_get_course_int_id();
1346
1347
        $sql = "SELECT id FROM $table
1348
                WHERE
1349
                    c_id = $course_id AND
1350
                    attendance_id = '$attendanceId' AND
1351
                    done_attendance = 0
1352
                ORDER BY date_time
1353
                LIMIT 1";
1354
        $rs = Database::query($sql);
1355
        $next_calendar_id = 0;
1356
        if (Database::num_rows($rs) > 0) {
1357
            $row = Database::fetch_array($rs);
1358
            $next_calendar_id = $row['id'];
1359
        }
1360
1361
        return $next_calendar_id;
1362
    }
1363
1364
    /**
1365
     * Get next attendance calendar datetime without presences (done attendances).
1366
     *
1367
     * @param int    attendance id
1368
     *
1369
     * @return int UNIX time format datetime
1370
     */
1371
    public function getNextAttendanceCalendarDatetime($attendanceId)
1372
    {
1373
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1374
        $course_id = api_get_course_int_id();
1375
        $attendanceId = (int) $attendanceId;
1376
        $sql = "SELECT id, date_time FROM $table
1377
                WHERE
1378
                    c_id = $course_id AND
1379
                    attendance_id = '$attendanceId' AND
1380
                    done_attendance = 0
1381
                ORDER BY date_time
1382
                LIMIT 1";
1383
        $rs = Database::query($sql);
1384
        $next_calendar_datetime = 0;
1385
        if (Database::num_rows($rs) > 0) {
1386
            $row = Database::fetch_array($rs);
1387
            $next_calendar_datetime = api_get_local_time($row['date_time']);
1388
        }
1389
1390
        return $next_calendar_datetime;
1391
    }
1392
1393
    /**
1394
     * Get user's score from current attendance.
1395
     *
1396
     * @param int $user_id
1397
     * @param int $attendanceId
1398
     * @param int $groupId
1399
     *
1400
     * @return int score
1401
     */
1402
    public function get_user_score($user_id, $attendanceId, $groupId = 0)
1403
    {
1404
        $tbl_attendance_result = Database::get_course_table(TABLE_ATTENDANCE_RESULT);
1405
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
1406
        $tbl_attendance_cal_rel_group = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1407
        $tbl_attendance_cal = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1408
        $user_id = intval($user_id);
1409
        $attendanceId = intval($attendanceId);
1410
        $groupId = (int) $groupId;
1411
        $course_id = api_get_course_int_id();
1412
1413
        if (empty($groupId)) {
1414
            $sql = "SELECT score FROM $tbl_attendance_result
1415
                    WHERE
1416
                        c_id = $course_id AND
1417
                        user_id='$user_id' AND
1418
                        attendance_id='$attendanceId'";
1419
        } else {
1420
            $sql = "SELECT count(presence) as score FROM $tbl_attendance_sheet
1421
                    WHERE
1422
                        c_id = $course_id AND
1423
                        user_id='$user_id' AND
1424
                        presence = 1 AND
1425
                        attendance_calendar_id IN (
1426
                            SELECT calendar_id FROM $tbl_attendance_cal_rel_group crg
1427
                            INNER JOIN $tbl_attendance_cal c
1428
                            ON (crg.calendar_id = c.id)
1429
                            WHERE
1430
                                crg.c_id = $course_id AND
1431
                                crg.group_id = $groupId AND
1432
                                c.attendance_id = $attendanceId
1433
                        )
1434
                    ";
1435
        }
1436
        $rs = Database::query($sql);
1437
        $score = 0;
1438
        if (Database::num_rows($rs) > 0) {
1439
            $row = Database::fetch_array($rs);
1440
            $score = $row['score'];
1441
        }
1442
1443
        return $score;
1444
    }
1445
1446
    /**
1447
     * Get attendance calendar data by id.
1448
     *
1449
     * @param int    attendance calendar id
1450
     *
1451
     * @return array attendance calendar data
1452
     */
1453
    public function get_attendance_calendar_by_id($calendar_id)
1454
    {
1455
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1456
        $calendar_id = intval($calendar_id);
1457
        $course_id = api_get_course_int_id();
1458
        $sql = "SELECT * FROM $table
1459
                WHERE c_id = $course_id AND id = '$calendar_id' ";
1460
        $rs = Database::query($sql);
1461
        $data = [];
1462
        if (Database::num_rows($rs) > 0) {
1463
            while ($row = Database::fetch_array($rs)) {
1464
                $row['date_time'] = api_get_local_time($row['date_time']);
1465
                $data = $row;
1466
            }
1467
        }
1468
1469
        return $data;
1470
    }
1471
1472
    /**
1473
     * Get all attendance calendar data inside current attendance or by course id.
1474
     *
1475
     * @param int      $attendanceId
1476
     * @param string   $type
1477
     * @param int      $calendar_id
1478
     * @param int      $groupId
1479
     * @param bool     $showAll      = false show group calendar items or not
1480
     * @param int      $course_id
1481
     * @param DateTime $startDate    Filter calendar with a start date
1482
     * @param DateTime $endDate      Filter calendar with a end date
1483
     *
1484
     * @return array attendance calendar data
1485
     */
1486
    public function get_attendance_calendar(
1487
        $attendanceId,
1488
        $type = 'all',
1489
        $calendar_id = null,
1490
        $groupId = 0,
1491
        $showAll = false,
1492
        $course_id = 0,
1493
        DateTime $startDate = null,
1494
        DateTime $endDate = null
1495
    ) {
1496
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1497
        $tbl_acrg = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1498
        $attendanceId = intval($attendanceId);
1499
        $course_id = (0 == $course_id) ? api_get_course_int_id() : (int) $course_id;
1500
        $whereDate = '';
1501
        if (!empty($startDate)) {
1502
            $whereDate .= " AND c.date_time >= '".$startDate->format('Y-m-d H:i:s')."'";
1503
        }
1504
        if (!empty($endDate)) {
1505
            $whereDate .= " AND c.date_time <= '".$endDate->format('Y-m-d H:i:s')."'";
1506
        }
1507
        if ($showAll) {
1508
            $sql = "SELECT * FROM $tbl_attendance_calendar c
1509
                    WHERE c_id = $course_id
1510
                      AND attendance_id = '$attendanceId'
1511
                        $whereDate";
1512
        } else {
1513
            $sql = "SELECT * FROM $tbl_attendance_calendar c
1514
                    WHERE
1515
                        c_id = $course_id AND
1516
                        attendance_id = '$attendanceId' AND
1517
                        id NOT IN (
1518
                            SELECT calendar_id FROM $tbl_acrg
1519
                            WHERE c_id = $course_id AND group_id != 0 AND group_id IS NOT NULL
1520
                        )
1521
                        $whereDate
1522
                    ";
1523
        }
1524
1525
        if (!empty($groupId)) {
1526
            $groupId = intval($groupId);
1527
            $sql = "SELECT c.* FROM $tbl_attendance_calendar c
1528
                    INNER JOIN $tbl_acrg g
1529
                    ON c.c_id = g.c_id AND c.id = g.calendar_id
1530
                    WHERE
1531
                        c.c_id = $course_id AND
1532
                        g.group_id = '$groupId' AND
1533
                        c.attendance_id = '$attendanceId'
1534
                   ";
1535
        }
1536
1537
        if (!in_array($type, ['today', 'all', 'all_done', 'all_not_done', 'calendar_id'])) {
1538
            $type = 'all';
1539
        }
1540
1541
        switch ($type) {
1542
            case 'calendar_id':
1543
                $calendar_id = intval($calendar_id);
1544
                if (!empty($calendar_id)) {
1545
                    $sql .= " AND c.id = $calendar_id";
1546
                }
1547
                break;
1548
            case 'today':
1549
                //$sql .= ' AND DATE_FORMAT(date_time,"%d-%m-%Y") = DATE_FORMAT("'.api_get_utc_datetime().'", "%d-%m-%Y" )';
1550
                break;
1551
            case 'all_done':
1552
                $sql .= " AND done_attendance = 1 ";
1553
                break;
1554
            case 'all_not_done':
1555
                $sql .= " AND done_attendance = 0 ";
1556
                break;
1557
            case 'all':
1558
            default:
1559
                break;
1560
        }
1561
        $sql .= " ORDER BY date_time ";
1562
1563
        $rs = Database::query($sql);
1564
        $data = [];
1565
        if (Database::num_rows($rs) > 0) {
1566
            while ($row = Database::fetch_array($rs, 'ASSOC')) {
1567
                $row['db_date_time'] = $row['date_time'];
1568
                $row['date_time'] = api_get_local_time($row['date_time']);
1569
                $row['date'] = api_format_date($row['date_time'], DATE_FORMAT_SHORT);
1570
                $row['time'] = api_format_date($row['date_time'], TIME_NO_SEC_FORMAT);
1571
                $row['groups'] = $this->getGroupListByAttendanceCalendar($row['id'], $course_id);
1572
                $row['duration'] = Attendance::getAttendanceCalendarExtraFieldValue('duration', $row['id']);
1573
                if ($type == 'today') {
1574
                    if (date('d-m-Y', api_strtotime($row['date_time'], 'UTC')) == date('d-m-Y', time())) {
1575
                        $data[] = $row;
1576
                    }
1577
                } else {
1578
                    $data[] = $row;
1579
                }
1580
            }
1581
        }
1582
1583
        return $data;
1584
    }
1585
1586
    /**
1587
     * Get number of attendance calendar inside current attendance.
1588
     *
1589
     * @param int $attendanceId
1590
     * @param int $groupId
1591
     * @param $done_attendance
1592
     * @param int $userId
1593
     *
1594
     * @return int number of dates in attendance calendar
1595
     */
1596
    public static function get_number_of_attendance_calendar(
1597
        $attendanceId,
1598
        $groupId = 0,
1599
        $done_attendance = null,
1600
        $userId = 0
1601
    ) {
1602
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1603
        $calendarRelGroup = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1604
        $tbl_groupRelUser = Database::get_course_table(TABLE_GROUP_USER);
1605
        $attendanceId = intval($attendanceId);
1606
        $groupId = intval($groupId);
1607
        $course_id = api_get_course_int_id();
1608
1609
        $where_attendance = '';
1610
        if ($done_attendance) {
1611
            $where_attendance = ' done_attendance = 1 AND ';
1612
        }
1613
        if (empty($userId)) {
1614
            if (empty($groupId)) {
1615
                $sql = "SELECT count(a.id)
1616
                        FROM $tbl_attendance_calendar a
1617
                        WHERE
1618
                            c_id = $course_id AND
1619
                            $where_attendance
1620
                            attendance_id = '$attendanceId' AND
1621
                            id NOT IN (
1622
                                SELECT calendar_id FROM $calendarRelGroup
1623
                                WHERE
1624
                                    c_id = $course_id AND
1625
                                    group_id != 0 AND
1626
                                    group_id IS NOT NULL
1627
                            )
1628
                        ";
1629
            } else {
1630
                $sql = "SELECT count(a.id)
1631
                        FROM $tbl_attendance_calendar a
1632
                        INNER JOIN $calendarRelGroup g
1633
                        ON (a.id = g.calendar_id AND a.c_id = g.c_id)
1634
                        WHERE
1635
                            a.c_id = $course_id AND
1636
                            $where_attendance
1637
                            attendance_id = '$attendanceId' AND
1638
                            group_id = $groupId
1639
                        ";
1640
            }
1641
        } else {
1642
            if (empty($groupId)) {
1643
                $sql = "SELECT count(a.id)
1644
                        FROM $tbl_attendance_calendar a
1645
                        WHERE
1646
                            c_id = $course_id AND
1647
                            $where_attendance
1648
                            attendance_id = '$attendanceId' AND
1649
                            id NOT IN (
1650
                                SELECT calendar_id FROM $calendarRelGroup
1651
                                WHERE
1652
                                    c_id = $course_id AND
1653
                                    group_id != 0 AND
1654
                                    group_id IS NOT NULL AND
1655
                                    group_id NOT IN (
1656
                                        SELECT group_id
1657
                                        FROM $tbl_groupRelUser
1658
                                        WHERE user_id = $userId
1659
                                    )
1660
                            )
1661
                        ";
1662
            } else {
1663
                $sql = "SELECT count(a.id)
1664
                        FROM $tbl_attendance_calendar a
1665
                        INNER JOIN $calendarRelGroup g
1666
                        ON (a.id = g.calendar_id AND a.c_id = g.c_id)
1667
                        WHERE
1668
                            a.c_id = $course_id AND
1669
                            $where_attendance
1670
                            attendance_id = '$attendanceId' AND
1671
                            group_id = $groupId
1672
                        ";
1673
            }
1674
        }
1675
1676
        $rs = Database::query($sql);
1677
        $row = Database::fetch_row($rs);
1678
        $count = $row[0];
1679
1680
        return $count;
1681
    }
1682
1683
    /**
1684
     * Get count dates inside attendance calendar by attendance id.
1685
     *
1686
     * @param int $attendanceId
1687
     *
1688
     * @return int count of dates
1689
     */
1690
    public static function get_count_dates_inside_attendance_calendar($attendanceId)
1691
    {
1692
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1693
        $attendanceId = intval($attendanceId);
1694
        $course_id = api_get_course_int_id();
1695
        $sql = "SELECT count(id) FROM $tbl_attendance_calendar
1696
                WHERE
1697
                    c_id = $course_id AND
1698
                    attendance_id = '$attendanceId'";
1699
        $rs = Database::query($sql);
1700
        $count = 0;
1701
        if (Database::num_rows($rs) > 0) {
1702
            $row = Database::fetch_row($rs);
1703
            $count = $row[0];
1704
        }
1705
1706
        return $count;
1707
    }
1708
1709
    /**
1710
     * check if all calendar of an attendance is done.
1711
     *
1712
     * @param int $attendanceId
1713
     *
1714
     * @return bool True if all calendar is done, otherwise false
1715
     */
1716
    public static function is_all_attendance_calendar_done($attendanceId)
1717
    {
1718
        $attendanceId = (int) $attendanceId;
1719
        $done_calendar = self::get_done_attendance_calendar($attendanceId);
1720
        $count_dates_in_calendar = self::get_count_dates_inside_attendance_calendar($attendanceId);
1721
        $number_of_dates = self::get_number_of_attendance_calendar($attendanceId);
1722
1723
        $result = false;
1724
        if ($number_of_dates && intval($count_dates_in_calendar) == intval($done_calendar)) {
1725
            $result = true;
1726
        }
1727
1728
        return $result;
1729
    }
1730
1731
    /**
1732
     * check if an attendance is locked.
1733
     *
1734
     * @param int $attendanceId
1735
     * @param bool
1736
     *
1737
     * @return bool
1738
     */
1739
    public static function is_locked_attendance($attendanceId)
1740
    {
1741
        //  Use gradebook lock
1742
        $result = api_resource_is_locked_by_gradebook($attendanceId, LINK_ATTENDANCE);
1743
1744
        return $result;
1745
    }
1746
1747
    /**
1748
     * Add new datetime inside attendance calendar table.
1749
     *
1750
     * @param int   $attendanceId
1751
     * @param array $groupList
1752
     * @param array $extraValues
1753
     *
1754
     * @return int affected rows
1755
     */
1756
    public function attendance_calendar_add($attendanceId, $groupList = [], $extraValues = [])
1757
    {
1758
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1759
        $affected_rows = 0;
1760
        $attendanceId = intval($attendanceId);
1761
        $course_id = api_get_course_int_id();
1762
        // check if datetime already exists inside the table
1763
        /*$sql = "SELECT id FROM $tbl_attendance_calendar
1764
                WHERE
1765
                    c_id = $course_id AND
1766
                    date_time='".Database::escape_string($this->date_time)."' AND
1767
                    attendance_id = '$attendanceId'";
1768
        $rs = Database::query($sql);
1769
        if (Database::num_rows($rs) == 0) {*/
1770
        $params = [
1771
            'c_id' => $course_id,
1772
            'date_time' => $this->date_time,
1773
            'attendance_id' => $attendanceId,
1774
            'done_attendance' => 0,
1775
        ];
1776
        $id = Database::insert($tbl_attendance_calendar, $params);
1777
1778
        if ($id) {
1779
            $sql = "UPDATE $tbl_attendance_calendar SET id = iid WHERE iid = $id";
1780
            Database::query($sql);
1781
            $affected_rows++;
1782
1783
            if (!empty($extraValues)) {
1784
                // It saves extra fields values
1785
                $extraFieldValue = new ExtraFieldValue('attendance_calendar');
1786
                $extraValues['item_id'] = $id;
1787
                $extraFieldValue->saveFieldValues($extraValues);
1788
            }
1789
        }
1790
        $this->addAttendanceCalendarToGroup($id, $course_id, $groupList);
1791
        //}
1792
1793
        // update locked attendance
1794
        $is_all_calendar_done = self::is_all_attendance_calendar_done($attendanceId);
1795
        if (!$is_all_calendar_done) {
1796
            self::lock_attendance($attendanceId, false);
1797
        } else {
1798
            self::lock_attendance($attendanceId);
1799
        }
1800
1801
        return $affected_rows;
1802
    }
1803
1804
    /**
1805
     * @param int   $calendarId
1806
     * @param int   $courseId
1807
     * @param array $groupList
1808
     *
1809
     * @return bool
1810
     */
1811
    public function addAttendanceCalendarToGroup($calendarId, $courseId, $groupList)
1812
    {
1813
        if (empty($groupList)) {
1814
            return false;
1815
        }
1816
1817
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1818
        foreach ($groupList as $groupId) {
1819
            if (empty($groupId)) {
1820
                continue;
1821
            }
1822
1823
            $result = $this->getAttendanceCalendarGroup(
1824
                $calendarId,
1825
                $courseId,
1826
                $groupId
1827
            );
1828
1829
            if (empty($result)) {
1830
                $params = [
1831
                    'calendar_id' => $calendarId,
1832
                    'c_id' => $courseId,
1833
                    'group_id' => $groupId,
1834
                ];
1835
                Database::insert($table, $params);
1836
            }
1837
        }
1838
1839
        return true;
1840
    }
1841
1842
    /**
1843
     * @param int $calendarId
1844
     * @param int $courseId
1845
     *
1846
     * @return array
1847
     */
1848
    public function getGroupListByAttendanceCalendar($calendarId, $courseId)
1849
    {
1850
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1851
1852
        return Database::select(
1853
            '*',
1854
            $table,
1855
            [
1856
                'where' => [
1857
                    'calendar_id = ? AND c_id = ?' => [$calendarId, $courseId],
1858
                ],
1859
            ]
1860
        );
1861
    }
1862
1863
    /**
1864
     * @param int $calendarId
1865
     * @param int $courseId
1866
     * @param int $groupId
1867
     *
1868
     * @return array
1869
     */
1870
    public function getAttendanceCalendarGroup($calendarId, $courseId, $groupId)
1871
    {
1872
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1873
1874
        return Database::select(
1875
            '*',
1876
            $table,
1877
            [
1878
                'where' => [
1879
                    'calendar_id = ? AND c_id = ? AND group_id = ?' => [$calendarId, $courseId, $groupId],
1880
                ],
1881
            ]
1882
        );
1883
    }
1884
1885
    /**
1886
     * @param int $calendarId
1887
     * @param int $courseId
1888
     */
1889
    public function deleteAttendanceCalendarGroup($calendarId, $courseId)
1890
    {
1891
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1892
        Database::delete(
1893
            $table,
1894
            [
1895
                'calendar_id = ? AND c_id = ?' => [$calendarId, $courseId],
1896
            ]
1897
        );
1898
    }
1899
1900
    /**
1901
     * save repeated date inside attendance calendar table.
1902
     *
1903
     * @param int    $attendanceId
1904
     * @param int    $start_date   start date in tms
1905
     * @param int    $end_date     end date in tms
1906
     * @param string $repeat_type  daily, weekly, biweekly, xdays, monthlyByDate
1907
     * @param array  $groupList
1908
     */
1909
    public function attendance_repeat_calendar_add(
1910
        $attendanceId,
1911
        $start_date,
1912
        $end_date,
1913
        $repeat_type,
1914
        $groupList = [],
1915
        $extraValues = []
1916
    ) {
1917
        $attendanceId = intval($attendanceId);
1918
        // save start date
1919
        $datetimezone = api_get_utc_datetime($start_date);
1920
        $this->set_date_time($datetimezone);
1921
        $this->attendance_calendar_add($attendanceId, $groupList, $extraValues);
1922
1923
        // 86400 = 24 hours in seconds
1924
        // 604800 = 1 week in seconds
1925
        // 1296000 = 2 weeks in seconds
1926
        // 2419200 = 1 month in seconds
1927
        // 86400 x xdays = interval by x days (in seconds)
1928
        // Saves repeated dates
1929
        $seconds = 0;
1930
        switch ($repeat_type) {
1931
            case 'daily':
1932
                $seconds = 86400;
1933
                break;
1934
            case 'weekly':
1935
                $seconds = 604800;
1936
                break;
1937
            case 'biweekly':
1938
                $seconds = 1296000;
1939
                break;
1940
            case 'monthlyByDate':
1941
                $seconds = 2419200;
1942
                break;
1943
            case 'xdays':
1944
                $seconds = isset($extraValues['xdays_number']) ? (int) $extraValues['xdays_number'] * 86400 : 0;
1945
                break;
1946
        }
1947
1948
        if ($seconds > 0) {
1949
            $j = 1;
1950
            for ($i = $start_date + $seconds; ($i <= $end_date); $i += $seconds) {
1951
                $datetimezone = api_get_utc_datetime($i);
1952
                $this->set_date_time($datetimezone);
1953
                $this->attendance_calendar_add($attendanceId, $groupList, $extraValues);
1954
                $j++;
1955
            }
1956
        }
1957
    }
1958
1959
    /**
1960
     * Gets the value of a attendance calendar extra field. Returns null if it was not found.
1961
     *
1962
     * @param string $variable   Name of the extra field
1963
     * @param string $calendarId Calendar id
1964
     *
1965
     * @return string Value
1966
     */
1967
    public static function getAttendanceCalendarExtraFieldValue($variable, $calendarId)
1968
    {
1969
        if (true !== api_get_configuration_value('attendance_calendar_set_duration')) {
1970
            return false;
1971
        }
1972
1973
        $extraFieldValues = new ExtraFieldValue('attendance_calendar');
1974
        $result = $extraFieldValues->get_values_by_handler_and_field_variable($calendarId, $variable);
1975
        if (!empty($result['value'])) {
1976
            return $result['value'];
1977
        }
1978
1979
        return null;
1980
    }
1981
1982
    /**
1983
     * edit a datetime inside attendance calendar table.
1984
     *
1985
     * @param int	attendance calendar id
1986
     * @param int	attendance id
1987
     * @param array extra values
1988
     *
1989
     * @return int affected rows
1990
     */
1991
    public function attendance_calendar_edit($calendar_id, $attendanceId, $extraValues = [])
1992
    {
1993
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1994
        $affected_rows = 0;
1995
        $attendanceId = intval($attendanceId);
1996
        $course_id = api_get_course_int_id();
1997
        // check if datetime already exists inside the table
1998
        $sql = "SELECT id FROM $tbl_attendance_calendar
1999
                WHERE
2000
                    c_id = $course_id AND
2001
                    date_time = '".Database::escape_string($this->date_time)."' AND
2002
                    attendance_id = '$attendanceId'";
2003
        $rs = Database::query($sql);
2004
2005
        if (Database::num_rows($rs) == 0) {
2006
            $sql = "UPDATE $tbl_attendance_calendar
2007
                    SET date_time='".Database::escape_string($this->date_time)."'
2008
                    WHERE c_id = $course_id AND id = '".intval($calendar_id)."'";
2009
            Database::query($sql);
2010
        }
2011
2012
        // It saves extra fields values
2013
        $extraFieldValue = new ExtraFieldValue('attendance_calendar');
2014
        $extraValues['item_id'] = $calendar_id;
2015
        $extraFieldValue->saveFieldValues($extraValues);
2016
2017
        // update locked attendance
2018
        $is_all_calendar_done = self::is_all_attendance_calendar_done($attendanceId);
2019
        if (!$is_all_calendar_done) {
2020
            self::lock_attendance($attendanceId, false);
2021
        } else {
2022
            self::lock_attendance($attendanceId);
2023
        }
2024
2025
        return $affected_rows;
2026
    }
2027
2028
    /**
2029
     * delete a datetime from attendance calendar table.
2030
     *
2031
     * @param	int		attendance calendar id
2032
     * @param	int		attendance id
2033
     * @param	bool true for removing all calendar inside current attendance, false for removing by calendar id
2034
     *
2035
     * @return int affected rows
2036
     */
2037
    public function attendance_calendar_delete(
2038
        $calendar_id,
2039
        $attendanceId,
2040
        $all_delete = false
2041
    ) {
2042
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
2043
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
2044
2045
        $attendanceId = intval($attendanceId);
2046
        $calendar_id = (int) $calendar_id;
2047
2048
        // get all registered users inside current course
2049
        $users = $this->get_users_rel_course();
2050
        $user_ids = array_keys($users);
2051
        $course_id = api_get_course_int_id();
2052
        $affected_rows = 0;
2053
        if ($all_delete) {
2054
            $attendance_calendar = $this->get_attendance_calendar($attendanceId);
2055
            // get all dates from calendar by current attendance
2056
            if (!empty($attendance_calendar)) {
2057
                foreach ($attendance_calendar as $cal) {
2058
                    // delete all data from attendance sheet
2059
                    $sql = "DELETE FROM $tbl_attendance_sheet
2060
                            WHERE c_id = $course_id AND attendance_calendar_id = '".intval($cal['id'])."'";
2061
                    Database::query($sql);
2062
                    // delete data from attendance calendar
2063
                    $sql = "DELETE FROM $tbl_attendance_calendar
2064
                            WHERE c_id = $course_id AND id = '".intval($cal['id'])."'";
2065
                    Database::query($sql);
2066
2067
                    $this->deleteAttendanceCalendarGroup($cal['id'], $course_id);
2068
                    $affected_rows++;
2069
                }
2070
            }
2071
        } else {
2072
            // delete just one row from attendance sheet by the calendar id
2073
            $sql = "DELETE FROM $tbl_attendance_sheet
2074
                    WHERE c_id = $course_id AND attendance_calendar_id = '".$calendar_id."'";
2075
            Database::query($sql);
2076
            // delete data from attendance calendar
2077
            $sql = "DELETE FROM $tbl_attendance_calendar
2078
                    WHERE c_id = $course_id AND id = '".$calendar_id."'";
2079
            Database::query($sql);
2080
2081
            $this->deleteAttendanceCalendarGroup($calendar_id, $course_id);
2082
            $affected_rows++;
2083
        }
2084
2085
        // update users' results
2086
        $this->updateUsersResults($user_ids, $attendanceId);
2087
2088
        return $affected_rows;
2089
    }
2090
2091
    public function set_session_id($sessionId)
2092
    {
2093
        $this->session_id = $sessionId;
2094
    }
2095
2096
    public function set_course_id($course_id)
2097
    {
2098
        $this->course_id = $course_id;
2099
    }
2100
2101
    public function set_date_time($datetime)
2102
    {
2103
        $this->date_time = $datetime;
2104
    }
2105
2106
    public function set_name($name)
2107
    {
2108
        $this->name = $name;
2109
    }
2110
2111
    public function set_description($description)
2112
    {
2113
        $this->description = $description;
2114
    }
2115
2116
    public function set_attendance_qualify_title($attendance_qualify_title)
2117
    {
2118
        $this->attendance_qualify_title = $attendance_qualify_title;
2119
    }
2120
2121
    public function set_attendance_weight($attendance_weight)
2122
    {
2123
        $this->attendance_weight = $attendance_weight;
2124
    }
2125
2126
    /** Getters for fields of attendances tables */
2127
    public function get_session_id()
2128
    {
2129
        return $this->session_id;
2130
    }
2131
2132
    public function get_course_id()
2133
    {
2134
        return $this->course_id;
2135
    }
2136
2137
    public function get_date_time()
2138
    {
2139
        return $this->date_time;
2140
    }
2141
2142
    public function get_name()
2143
    {
2144
        return $this->name;
2145
    }
2146
2147
    public function get_description()
2148
    {
2149
        return $this->description;
2150
    }
2151
2152
    public function get_attendance_qualify_title()
2153
    {
2154
        return $this->attendance_qualify_title;
2155
    }
2156
2157
    public function get_attendance_weight()
2158
    {
2159
        return $this->attendance_weight;
2160
    }
2161
2162
    /**
2163
     * @param string $startDate in UTC time
2164
     * @param string $endDate   in UTC time
2165
     *
2166
     * @return array
2167
     */
2168
    public function getAttendanceLogin($startDate, $endDate)
2169
    {
2170
        if (empty($startDate) ||
2171
            $startDate == '0000-00-00' ||
2172
            $startDate == '0000-00-00 00:00:00' ||
2173
            empty($endDate) ||
2174
            $endDate == '0000-00-00' ||
2175
            $endDate == '0000-00-00 00:00:00'
2176
        ) {
2177
            return false;
2178
        }
2179
2180
        $sessionId = api_get_session_id();
2181
        $courseCode = api_get_course_id();
2182
        $courseId = api_get_course_int_id();
2183
2184
        if (!empty($sessionId)) {
2185
            $users = CourseManager::get_user_list_from_course_code(
2186
                $courseCode,
2187
                $sessionId,
2188
                '',
2189
                'lastname',
2190
                0
2191
            );
2192
        } else {
2193
            $users = CourseManager::get_user_list_from_course_code(
2194
                $courseCode,
2195
                0,
2196
                '',
2197
                'lastname',
2198
                STUDENT
2199
            );
2200
        }
2201
2202
        $dateTimeStartOriginal = new DateTime($startDate);
2203
        $dateTimeStart = new DateTime($startDate);
2204
        $dateTimeEnd = new DateTime($endDate);
2205
        $interval = $dateTimeStart->diff($dateTimeEnd);
2206
        $days = intval($interval->format('%a'));
2207
2208
        $dateList = [$dateTimeStart->format('Y-m-d')];
2209
        $headers = [
2210
            get_lang('User'),
2211
            $dateTimeStart->format('Y-m-d'),
2212
        ];
2213
2214
        for ($i = 0; $i < $days; $i++) {
2215
            $dateTimeStart = $dateTimeStart->add(new DateInterval('P1D'));
2216
            $date = $dateTimeStart->format('Y-m-d');
2217
            $dateList[] = $date;
2218
            $headers[] = $date;
2219
        }
2220
2221
        $accessData = CourseManager::getCourseAccessPerCourseAndSession(
2222
            $courseId,
2223
            $sessionId,
2224
            $dateTimeStartOriginal->format('Y-m-d H:i:s'),
2225
            $dateTimeEnd->format('Y-m-d H:i:s')
2226
        );
2227
2228
        $results = [];
2229
        if (!empty($accessData)) {
2230
            foreach ($accessData as $data) {
2231
                $onlyDate = substr($data['login_course_date'], 0, 10);
2232
                $results[$data['user_id']][$onlyDate] = true;
2233
            }
2234
        }
2235
2236
        return [
2237
            'users' => $users,
2238
            'dateList' => $dateList,
2239
            'headers' => $headers,
2240
            'results' => $results,
2241
        ];
2242
    }
2243
2244
    /**
2245
     * @param string $startDate in UTC time
2246
     * @param string $endDate   in UTC time
2247
     *
2248
     * @return string
2249
     */
2250
    public function getAttendanceLoginTable($startDate, $endDate)
2251
    {
2252
        $data = $this->getAttendanceLogin($startDate, $endDate);
2253
        if (!$data) {
2254
            return null;
2255
        }
2256
2257
        $headers = $data['headers'];
2258
        $dateList = $data['dateList'];
2259
        $users = $data['users'];
2260
        $results = $data['results'];
2261
2262
        $table = new HTML_Table(['class' => 'table table-hover table-striped data_table']);
2263
        $row = 0;
2264
        $column = 0;
2265
        foreach ($headers as $header) {
2266
            $table->setHeaderContents($row, $column, $header);
2267
            $column++;
2268
        }
2269
        $row = 1;
2270
        foreach ($users as $user) {
2271
            $table->setCellContents(
2272
                $row,
2273
                0,
2274
                $user['lastname'].' '.$user['firstname'].' ('.$user['username'].')'
2275
            );
2276
            $row++;
2277
        }
2278
2279
        $column = 1;
2280
        $row = 1;
2281
        foreach ($users as $user) {
2282
            foreach ($dateList as $date) {
2283
                $status = null;
2284
                if (isset($results[$user['user_id']]) &&
2285
                    isset($results[$user['user_id']][$date])
2286
                ) {
2287
                    $status = 'X';
2288
                }
2289
                $table->setCellContents($row, $column, $status);
2290
                $column++;
2291
            }
2292
            $row++;
2293
            $column = 1;
2294
        }
2295
2296
        return $table->toHtml();
2297
    }
2298
2299
    /**
2300
     * @param string $startDate in UTC time
2301
     * @param string $endDate   in UTC time
2302
     *
2303
     * @return string
2304
     */
2305
    public function exportAttendanceLogin($startDate, $endDate)
2306
    {
2307
        $data = $this->getAttendanceLogin($startDate, $endDate);
2308
2309
        if (!$data) {
2310
            return null;
2311
        }
2312
        $users = $data['users'];
2313
        $results = $data['results'];
2314
2315
        $table = new HTML_Table(['class' => 'table table-hover table-striped data_table']);
2316
        $table->setHeaderContents(0, 0, get_lang('User'));
2317
        $table->setHeaderContents(0, 1, get_lang('Date'));
2318
2319
        $row = 1;
2320
        foreach ($users as $user) {
2321
            $table->setCellContents(
2322
                $row,
2323
                0,
2324
                $user['lastname'].' '.$user['firstname'].' ('.$user['username'].')'
2325
            );
2326
            $row++;
2327
        }
2328
        $table->setColAttributes(0, ['style' => 'width:28%']);
2329
2330
        $row = 1;
2331
        foreach ($users as $user) {
2332
            if (isset($results[$user['user_id']]) &&
2333
                !empty($results[$user['user_id']])
2334
            ) {
2335
                $dates = implode(', ', array_keys($results[$user['user_id']]));
2336
                $table->setCellContents($row, 1, $dates);
2337
            }
2338
            $row++;
2339
        }
2340
2341
        $tableToString = $table->toHtml();
2342
        $params = [
2343
            'filename' => get_lang('Attendance').'_'.api_get_utc_datetime(),
2344
            'pdf_title' => get_lang('Attendance'),
2345
            'course_code' => api_get_course_id(),
2346
            'show_real_course_teachers' => true,
2347
        ];
2348
        $pdf = new PDF('A4', null, $params);
2349
        $pdf->html_to_pdf_with_template($tableToString);
2350
    }
2351
2352
    /**
2353
     * Return all course for a student between dates and order by key date (Y-m-d).
2354
     *
2355
     * @param int       $studentId
2356
     * @param \DateTime $startDate
2357
     * @param \DateTime $endDate
2358
     * @param bool      $orderDesc
2359
     *
2360
     * @return array
2361
     */
2362
    public function getCoursesWithAttendance(
2363
        $studentId = 0,
2364
        DateTime $startDate = null,
2365
        DateTime $endDate = null,
2366
        $orderDesc = false
2367
    ) {
2368
        // Lang variables
2369
        $presentString = get_lang('Present');
2370
        //$absentString = get_lang('Absent');
2371
        $absentString = '-';
2372
        // Lang variables
2373
        $attendanceLib = new Attendance();
2374
        $data = [];
2375
        /*
2376
         $specialCourses = CourseManager::returnSpecialCourses(
2377
            $studentId, false, false
2378
        );
2379
         */
2380
        $courses = CourseManager::returnCourses(
2381
            $studentId,
2382
            false,
2383
            false
2384
        );
2385
        /* Get course with (in_category) and without (not_category) category */
2386
        foreach ($courses as $courseData) {
2387
            /*
2388
             * $coursesKey can be in_category or not_category for courses
2389
             * */
2390
            $totalCoursesNoCategory = count($courseData);
2391
            for ($i = 0; $i < $totalCoursesNoCategory; $i++) {
2392
                $courseItem = $courseData[$i];
2393
                $courseId = $courseItem['course_id'];
2394
2395
                /* Get all attendance by courses*/
2396
                $attenances = $attendanceLib->get_attendances_list($courseId);
2397
                $temp = [];
2398
                $sheetsProccessed = [];
2399
                $tempDate = [];
2400
                foreach ($attenances as $attendanceData) {
2401
                    $attendanceId = $attendanceData['id'];
2402
                    $sheets = $attendanceLib->get_users_attendance_sheet(
2403
                        $attendanceId,
2404
                        $studentId,
2405
                        0,
2406
                        $courseId,
2407
                        $startDate,
2408
                        $endDate
2409
                    );
2410
2411
                    $sheetsProccessed[] = [];
2412
                    foreach ($sheets as $sheetData) {
2413
                        $totalb = count($sheetData);
2414
                        $tempDate = [];
2415
                        for ($ii = 0; $ii < $totalb; $ii++) {
2416
                            $attendancesProccess = $sheetData[$ii];
2417
                            if (!empty($attendancesProccess)) {
2418
                                $dateTemp = $attendancesProccess['0'];
2419
                                $attendancesProccess[0] = $attendancesProccess[1];
2420
                                $attendancesProccess[1] = $dateTemp;
2421
2422
                                $attendancesProccess[2] = $courseItem['title'];
2423
                                $attendancesProccess['courseTitle'] = $courseItem['title'];
2424
2425
                                $attendancesProccess[3] = $courseItem['real_id'];
2426
                                $attendancesProccess['courseId'] = $courseItem['real_id'];
2427
2428
                                $attendancesProccess[4] = $attendanceData['name'];
2429
                                $attendancesProccess['attendanceName'] = $attendanceData['name'];
2430
                                $attendancesProccess['courseCode'] = $courseItem['course_code'];
2431
2432
                                $attendancesProccess[5] = $attendanceData['id'];
2433
                                $attendancesProccess['attendanceId'] = $attendanceData['id'];
2434
                                if ($attendancesProccess['presence'] == 1) {
2435
                                    $attendancesProccess['presence'] = $presentString;
2436
                                    $attendancesProccess[0] = 1;
2437
                                } else {
2438
                                    $attendancesProccess['presence'] = $absentString;
2439
                                    $attendancesProccess[0] = 0;
2440
                                }
2441
                                $attendancesProccess['session'] = 0;
2442
                                $attendancesProccess['sessionName'] = '';
2443
                                $tempDate[] = $attendancesProccess;
2444
                                $dateKey = new DateTime($dateTemp);
2445
                                /*
2446
                                $attendancesProccess['teacher'] = '';
2447
                                if(isset($courseItem['teachers']) and isset($courseItem['teachers'][0])){
2448
                                    $attendancesProccess['teacher'] = $courseItem['teachers'][0]['fullname'];
2449
                                }
2450
                                */
2451
                                $data[$dateKey->format('Y-m-d')][] = $attendancesProccess;
2452
                            }
2453
                        }
2454
                    }
2455
                    $sheetsProccessed[] = $tempDate;
2456
                    $temp[] = $sheetsProccessed;
2457
                }
2458
                $courses['not_category'][$i]['attendanceSheet'] = $temp;
2459
            }
2460
        }
2461
2462
        /* Sessions */
2463
        $studentId = (int) $studentId;
2464
        $sql = "
2465
            SELECT
2466
                session_id,
2467
                c_id
2468
            FROM
2469
                session_rel_course_rel_user
2470
            WHERE
2471
                user_id = $studentId";
2472
2473
        $rs = Database::query($sql);
2474
        // get info from sessions
2475
        while ($row = Database::fetch_array($rs, 'ASSOC')) {
2476
            $courseId = $row['c_id'];
2477
            $sessionId = $row['session_id'];
2478
            $courseItem = api_get_course_info_by_id($courseId);
2479
2480
            $attenances = $attendanceLib->get_attendances_list(
2481
                $courseId,
2482
                $sessionId
2483
            );
2484
            $temp = [];
2485
            $sheetsProccessed = [];
2486
            $tempDate = [];
2487
            foreach ($attenances as $attendanceData) {
2488
                $attendanceId = $attendanceData['id'];
2489
                $sheets = $attendanceLib->get_users_attendance_sheet(
2490
                    $attendanceId,
2491
                    $studentId,
2492
                    0,
2493
                    $courseId,
2494
                    $startDate,
2495
                    $endDate
2496
                );
2497
2498
                $sheetsProccessed[] = [];
2499
                foreach ($sheets as $sheetData) {
2500
                    $totalb = count($sheetData);
2501
                    $tempDate = [];
2502
                    for ($ii = 0; $ii < $totalb; $ii++) {
2503
                        $work = $sheetData[$ii];
2504
                        $attendancesProccess = $work;
2505
                        if (!empty($attendancesProccess)) {
2506
                            $dateTemp = $attendancesProccess['0'];
2507
                            $attendancesProccess[0] = $attendancesProccess[1];
2508
                            $attendancesProccess[1] = $dateTemp;
2509
                            $attendancesProccess[2] = $courseItem['title'];
2510
                            $attendancesProccess['courseTitle'] = $courseItem['title'];
2511
                            $attendancesProccess[3] = $courseItem['real_id'];
2512
                            $attendancesProccess['courseId'] = $courseItem['real_id'];
2513
                            $attendancesProccess[4] = $attendanceData['name'];
2514
                            $attendancesProccess['attendanceName'] = $attendanceData['name'];
2515
                            $attendancesProccess[5] = $attendanceData['id'];
2516
                            $attendancesProccess['attendanceId'] = $attendanceData['id'];
2517
                            $attendancesProccess['courseCode'] = $courseItem['official_code'];
2518
                            if ($attendancesProccess['presence'] == 1) {
2519
                                $attendancesProccess['presence'] = $presentString;
2520
                                $attendancesProccess[0] = 1;
2521
                            } else {
2522
                                $attendancesProccess['presence'] = $absentString;
2523
                                $attendancesProccess[0] = 0;
2524
                            }
2525
                            $attendancesProccess['session'] = $sessionId;
2526
                            $attendancesProccess['sessionName'] = api_get_session_name($sessionId);
2527
2528
                            $tempDate[] = $attendancesProccess;
2529
                            $dateKey = new DateTime($dateTemp);
2530
                            /*
2531
                            $attendancesProccess['teacher'] = '';
2532
                            if(isset($courseItem['tutor_name']) ){
2533
                                $attendancesProccess['teacher'] = $courseItem['tutor_name'];
2534
                            }
2535
                            */
2536
                            $data[$dateKey->format('Y-m-d')][] = $attendancesProccess;
2537
                        }
2538
                    }
2539
                }
2540
                $sheetsProccessed[] = $tempDate;
2541
                $temp[] = $sheetsProccessed;
2542
            }
2543
            $courses['session'][$i]['attendanceSheet'] = $temp;
2544
        }
2545
2546
        /* Order desc by date,  by default */
2547
        if ($orderDesc == true) {
2548
            ksort($data);
2549
        } else {
2550
            krsort($data);
2551
        }
2552
2553
        return $data;
2554
    }
2555
2556
    /**
2557
     * Clean a sing of a user in attendance sheet.
2558
     *
2559
     * @param $userId
2560
     * @param $attendanceCalendarId
2561
     *
2562
     * @return false or void when it is deleted.
2563
     */
2564
    public function deleteSignature(
2565
        $userId,
2566
        $attendanceCalendarId,
2567
        $attendanceId
2568
    ) {
2569
        $allowSignature = api_get_configuration_value('enable_sign_attendance_sheet');
2570
        if (!$allowSignature) {
2571
            return false;
2572
        }
2573
2574
        $courseId = api_get_course_int_id();
2575
        $em = Database::getManager();
2576
        $criteria = [
2577
            'userId' => $userId,
2578
            'attendanceCalendarId' => $attendanceCalendarId,
2579
            'cId' => $courseId,
2580
        ];
2581
2582
        $repo = $em->getRepository('ChamiloCourseBundle:CAttendanceSheet');
2583
        $attendanceSheet = $repo->findOneBy($criteria);
2584
2585
        if ($attendanceSheet) {
2586
            /** @var CAttendanceSheet $attendanceSheet */
2587
            $attendanceSheet->setPresence(0);
2588
            $attendanceSheet->setSignature('');
2589
2590
            $em->persist($attendanceSheet);
2591
            $em->flush();
2592
            $this->updateUsersResults([$userId], $attendanceId);
2593
        }
2594
    }
2595
2596
    /**
2597
     * It checks if the calendar in a attendance sheet is blocked.
2598
     *
2599
     * @param $calendarId
2600
     *
2601
     * @return bool
2602
     */
2603
    public function isCalendarBlocked($calendarId)
2604
    {
2605
        $em = Database::getManager();
2606
        $repo = $em->getRepository('ChamiloCourseBundle:CAttendanceCalendar');
2607
2608
        $blocked = 0;
2609
        $attendanceCalendar = $repo->find($calendarId);
2610
        /** @var CAttendanceCalendar $attendanceCalendar */
2611
        if ($attendanceCalendar) {
2612
            $blocked = (int) $attendanceCalendar->getBlocked();
2613
        }
2614
2615
        $isBlocked = (1 === $blocked);
2616
2617
        return $isBlocked;
2618
    }
2619
2620
    /**
2621
     * It blocks/unblocks the calendar in attendance sheet.
2622
     *
2623
     * @param $calendarId
2624
     *
2625
     * @throws \Doctrine\ORM\ORMException
2626
     * @throws \Doctrine\ORM\OptimisticLockException
2627
     */
2628
    public function updateCalendarBlocked($calendarId)
2629
    {
2630
        $em = Database::getManager();
2631
        $repo = $em->getRepository('ChamiloCourseBundle:CAttendanceCalendar');
2632
        $attendanceCalendar = $repo->find($calendarId);
2633
2634
        /** @var CAttendanceCalendar $attendanceCalendar */
2635
        if ($attendanceCalendar) {
2636
            $blocked = !$this->isCalendarBlocked($calendarId);
2637
            $attendanceCalendar->setBlocked($blocked);
2638
            $em->persist($attendanceCalendar);
2639
            $em->flush();
2640
        }
2641
    }
2642
2643
    /**
2644
     * Get the user sign in attendance sheet.
2645
     *
2646
     * @param $userId
2647
     * @param $attendanceCalendarId
2648
     *
2649
     * @return false|string
2650
     */
2651
    public function getSignature(
2652
        $userId,
2653
        $attendanceCalendarId
2654
    ) {
2655
        $allowSignature = api_get_configuration_value('enable_sign_attendance_sheet');
2656
        if (!$allowSignature) {
2657
            return false;
2658
        }
2659
2660
        $courseId = api_get_course_int_id();
2661
        $em = Database::getManager();
2662
        $repo = $em->getRepository('ChamiloCourseBundle:CAttendanceSheet');
2663
2664
        $criteria = [
2665
            'userId' => $userId,
2666
            'attendanceCalendarId' => $attendanceCalendarId,
2667
            'cId' => $courseId,
2668
        ];
2669
        $attendanceSheet = $repo->findOneBy($criteria);
2670
2671
        $signature = "";
2672
        if ($attendanceSheet) {
2673
            /** @var CAttendanceSheet $attendanceSheet */
2674
            $signature = $attendanceSheet->getSignature();
2675
        }
2676
2677
        return $signature;
2678
    }
2679
2680
    /**
2681
     * Exports the attendance sheet to Xls format.
2682
     */
2683
    public function exportAttendanceSheetToXls(
2684
        int $attendanceId,
2685
        int $studentId,
2686
        string $courseCode,
2687
        int $groupId,
2688
        string $filterType,
2689
        ?int $myCalendarId
2690
    ) {
2691
        $users = $this->get_users_rel_course($attendanceId, $groupId);
2692
        $calendar = $this->get_attendance_calendar(
2693
            $attendanceId,
2694
            $filterType,
2695
            $myCalendarId,
2696
            $groupId
2697
        );
2698
2699
        if (!empty($studentId)) {
2700
            $userId = $studentId;
2701
        } else {
2702
            $userId = api_get_user_id();
2703
        }
2704
        $courseInfo = api_get_course_info($courseCode);
2705
2706
        $userPresence = [];
2707
        if (api_is_allowed_to_edit(null, true) || api_is_drh()) {
2708
            $userPresence = $this->get_users_attendance_sheet($attendanceId, 0, $groupId);
2709
        } else {
2710
            $userPresence = $this->get_users_attendance_sheet($attendanceId, $userId, $groupId);
2711
        }
2712
2713
        // Set headers pdf.
2714
        $teacherInfo = CourseManager::get_teacher_list_from_course_code($courseInfo['code']);
2715
        $teacherName = null;
2716
        foreach ($teacherInfo as $teacherData) {
2717
            if ($teacherName != null) {
2718
                $teacherName = $teacherName." / ";
2719
            }
2720
            $teacherName .= api_get_person_name($teacherData['firstname'], $teacherData['lastname']);
2721
        }
2722
2723
        // Get data table
2724
        $dataTable = [];
2725
        $headTable = ['#', get_lang('Name')];
2726
        foreach ($calendar as $classDay) {
2727
            $labelDuration = !empty($classDay['duration']) ? get_lang('Duration').' : '.$classDay['duration'] : '';
2728
            $headTable[] =
2729
                api_format_date($classDay['date_time'], DATE_FORMAT_NUMBER_NO_YEAR).' '.
2730
                api_format_date($classDay['date_time'], TIME_NO_SEC_FORMAT).' '.
2731
                $labelDuration;
2732
        }
2733
        $dataTable[] = $headTable;
2734
        $dataUsersPresence = $userPresence;
2735
        $count = 1;
2736
2737
        if (!empty($users)) {
2738
            foreach ($users as $user) {
2739
                $cols = 1;
2740
                $result = [];
2741
                $result['count'] = $count;
2742
                $result['full_name'] = api_get_person_name($user['firstname'], $user['lastname']);
2743
                foreach ($calendar as $classDay) {
2744
                    $commentInfo = $this->getComment($user['user_id'], $classDay['id']);
2745
                    $comment = '';
2746
                    if (!empty($commentInfo['comment'])) {
2747
                        $comment .= $commentInfo['comment'];
2748
                    }
2749
                    if (!empty($commentInfo['author'])) {
2750
                        $comment .= ' - '.get_lang('Author').': '.$commentInfo['author'];
2751
                    }
2752
                    $txtComment = !empty($comment) ? '[comment]'.$comment : '';
2753
                    if (1 == (int) $classDay['done_attendance']) {
2754
                        if (1 == (int) $dataUsersPresence[$user['user_id']][$classDay['id']]['presence']) {
2755
                            $result[$classDay['id']] = get_lang('UserAttendedSymbol').$txtComment;
2756
                        } else {
2757
                            $result[$classDay['id']] = get_lang('UserNotAttendedSymbol').$txtComment;
2758
                        }
2759
                    } else {
2760
                        $result[$classDay['id']] = ' ';
2761
                    }
2762
                    $cols++;
2763
                }
2764
                $count++;
2765
                $dataTable[] = $result;
2766
            }
2767
        }
2768
2769
        $filename = get_lang('Attendance').'-'.api_get_local_time();
2770
        Export::arrayToXlsAndComments($dataTable, $filename);
2771
2772
        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
2773
    }
2774
2775
    /**
2776
     * Get the user comment in attendance sheet.
2777
     *
2778
     * @return false|array The comment text and the author.
2779
     */
2780
    public function getComment(
2781
        int $userId,
2782
        int $attendanceCalendarId
2783
    ) {
2784
        $allowComment = api_get_configuration_value('attendance_allow_comments');
2785
        if (!$allowComment) {
2786
            return false;
2787
        }
2788
2789
        $courseId = api_get_course_int_id();
2790
        $em = Database::getManager();
2791
        $repo = $em->getRepository('ChamiloCourseBundle:CAttendanceSheet');
2792
2793
        $criteria = [
2794
            'userId' => $userId,
2795
            'attendanceCalendarId' => $attendanceCalendarId,
2796
            'cId' => $courseId,
2797
        ];
2798
        $attendanceSheet = $repo->findOneBy($criteria);
2799
2800
        $comment = "";
2801
        if ($attendanceSheet) {
2802
            /** @var CAttendanceSheet $attendanceSheet */
2803
            $attendanceSheetId = $attendanceSheet->getIid();
2804
2805
            $criteria = [
2806
                'userId' => $userId,
2807
                'attendanceSheetId' => $attendanceSheetId,
2808
            ];
2809
2810
            $repo = $em->getRepository('ChamiloCourseBundle:CAttendanceResultComment');
2811
            $attendanceResultComment = $repo->findOneBy($criteria);
2812
2813
            $author = '';
2814
            /** @var CAttendanceResultComment $attendanceResultComment */
2815
            if ($attendanceResultComment) {
2816
                $comment = $attendanceResultComment->getComment();
2817
                $authorId = $attendanceResultComment->getAuthorUserId();
2818
                if (!empty($authorId)) {
2819
                    $authorInfo = api_get_user_info($authorId);
2820
                    $author = api_get_person_name($authorInfo['firstname'], $authorInfo['lastname']);
2821
                }
2822
            }
2823
        }
2824
2825
        $commentInfo = [
2826
            'comment' => $comment,
2827
            'author' => $author,
2828
        ];
2829
2830
        return $commentInfo;
2831
    }
2832
2833
    /**
2834
     * Saves the user comment from attendance sheet.
2835
     *
2836
     * @return false
2837
     */
2838
    public function saveComment(
2839
        int $userId,
2840
        int $attendanceCalendarId,
2841
        string $comment,
2842
        int $attendanceId
2843
    ) {
2844
        $allowComment = api_get_configuration_value('attendance_allow_comments');
2845
        if (!$allowComment) {
2846
            return false;
2847
        }
2848
2849
        $courseId = api_get_course_int_id();
2850
        $em = Database::getManager();
2851
        $criteria = [
2852
            'userId' => $userId,
2853
            'attendanceCalendarId' => $attendanceCalendarId,
2854
            'cId' => $courseId,
2855
        ];
2856
2857
        $repo = $em->getRepository('ChamiloCourseBundle:CAttendanceSheet');
2858
        $attendanceSheet = $repo->findOneBy($criteria);
2859
2860
        /** @var CAttendanceSheet $attendanceSheet */
2861
        if (!$attendanceSheet) {
2862
            $attendanceSheet = new CAttendanceSheet();
2863
            $attendanceSheet
2864
                ->setCId($courseId)
2865
                ->setPresence(0)
2866
                ->setUserId($userId)
2867
                ->setAttendanceCalendarId($attendanceCalendarId);
2868
2869
            $em->persist($attendanceSheet);
2870
            $em->flush();
2871
        }
2872
        $this->updateUsersResults([$userId], $attendanceId);
2873
2874
        $attendanceSheetId = $attendanceSheet->getIid();
2875
2876
        // It saves the comment in the current attendance sheet
2877
        $criteria = [
2878
            'userId' => $userId,
2879
            'attendanceSheetId' => $attendanceSheetId,
2880
        ];
2881
2882
        $repo = $em->getRepository('ChamiloCourseBundle:CAttendanceResultComment');
2883
        $attendanceResultComment = $repo->findOneBy($criteria);
2884
2885
        /** @var CAttendanceResultComment $attendanceResultComment */
2886
        if ($attendanceResultComment) {
2887
            $attendanceResultComment->setComment($comment);
2888
            $attendanceResultComment->setUpdatedAt(api_get_utc_datetime(null, false, true));
2889
            $attendanceResultComment->setAuthorUserId(api_get_user_id());
2890
            $em->persist($attendanceResultComment);
2891
            $em->flush();
2892
        } else {
2893
            $attendanceResultComment = new CAttendanceResultComment();
2894
            $attendanceResultComment
2895
                ->setAttendanceSheetId($attendanceSheetId)
2896
                ->setUserId($userId)
2897
                ->setComment($comment)
2898
                ->setAuthorUserId(api_get_user_id());
2899
2900
            $em->persist($attendanceResultComment);
2901
            $em->flush();
2902
        }
2903
    }
2904
2905
    /**
2906
     * It saves the user sign from attendance sheet.
2907
     *
2908
     * @param $userId
2909
     * @param $attendanceCalendarId
2910
     * @param $file string in base64
2911
     *
2912
     * @return false or void when it is saved.
2913
     */
2914
    public function saveSignature(
2915
        $userId,
2916
        $attendanceCalendarId,
2917
        $file,
2918
        $attendanceId,
2919
        $courseId = NULL
2920
    ) {
2921
        $allowSignature = api_get_configuration_value('enable_sign_attendance_sheet');
2922
        if (!$allowSignature) {
2923
            return false;
2924
        }
2925
        if (!isset($courseId)) {
2926
            $courseId = api_get_course_int_id();
2927
        }
2928
        $em = Database::getManager();
2929
        $criteria = [
2930
            'userId' => $userId,
2931
            'attendanceCalendarId' => $attendanceCalendarId,
2932
            'cId' => $courseId,
2933
        ];
2934
2935
        $repo = $em->getRepository('ChamiloCourseBundle:CAttendanceSheet');
2936
        $attendanceSheet = $repo->findOneBy($criteria);
2937
2938
        /** @var CAttendanceSheet $attendanceSheet */
2939
        if ($attendanceSheet) {
2940
            $attendanceSheet->setPresence(1);
2941
            $attendanceSheet->setSignature($file);
2942
            $em->persist($attendanceSheet);
2943
            $em->flush();
2944
        } else {
2945
            $attendanceSheet = new CAttendanceSheet();
2946
            $attendanceSheet
2947
                ->setCId($courseId)
2948
                ->setPresence(1)
2949
                ->setUserId($userId)
2950
                ->setAttendanceCalendarId($attendanceCalendarId)
2951
                ->setSignature($file);
2952
2953
            $em->persist($attendanceSheet);
2954
            $em->flush();
2955
        }
2956
        $this->updateUsersResults([$userId], $attendanceId);
2957
    }
2958
}
2959