Completed
Push — master ( 7bef58...5c053f )
by Julito
25:30
created

Attendance::getAttendanceLoginTable()   C

Complexity

Conditions 8
Paths 17

Size

Total Lines 47
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 32
nc 17
nop 2
dl 0
loc 47
rs 5.7377
c 0
b 0
f 0
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
class Attendance
14
{
15
    // constants
16
    const DONE_ATTENDANCE_LOG_TYPE = 'done_attendance_sheet';
17
    const UPDATED_ATTENDANCE_LOG_TYPE = 'updated_attendance_sheet';
18
    const LOCKED_ATTENDANCE_LOG_TYPE = 'locked_attendance_sheet';
19
    public $category_id;
20
    private $session_id;
21
    private $course_id;
22
    private $date_time;
23
    private $name;
24
    private $description;
25
    private $attendance_qualify_title;
26
    private $attendance_weight;
27
    private $course_int_id;
0 ignored issues
show
introduced by
The private property $course_int_id is not used, and could be removed.
Loading history...
28
29
    /**
30
     * Constructor.
31
     */
32
    public function __construct()
33
    {
34
        //$this->course_int_id = api_get_course_int_id();
35
    }
36
37
    /**
38
     * Get the total number of attendance inside current course and current session.
39
     *
40
     * @param int $active
41
     *
42
     * @return int
43
     *
44
     * @see SortableTable#get_total_number_of_items()
45
     */
46
    public static function getNumberOfAttendances($active = -1)
47
    {
48
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
49
        $session_id = api_get_session_id();
50
        $condition_session = api_get_session_condition($session_id);
51
        $course_id = api_get_course_int_id();
52
        $sql = "SELECT COUNT(att.id) AS total_number_of_items
53
                FROM $tbl_attendance att
54
                WHERE c_id = $course_id $condition_session ";
55
        if ($active == 1 || $active == 0) {
56
            $sql .= "AND att.active = $active";
57
        }
58
        $res = Database::query($sql);
59
        $obj = Database::fetch_object($res);
60
61
        return $obj->total_number_of_items;
62
    }
63
64
    /**
65
     * Get attendance list only the id, name and attendance_qualify_max fields.
66
     *
67
     * @param int $course_id  course db name (optional)
68
     * @param int $session_id session id (optional)
69
     *
70
     * @return array attendances list
71
     */
72
    public function get_attendances_list($course_id = 0, $session_id = 0)
73
    {
74
        $table = Database::get_course_table(TABLE_ATTENDANCE);
75
        $course_id = intval($course_id);
76
        if (empty($course_id)) {
77
            $course_id = api_get_course_int_id();
78
        }
79
80
        $session_id = !empty($session_id) ? intval($session_id) : api_get_session_id();
81
        $condition_session = api_get_session_condition($session_id);
82
83
        // Get attendance data
84
        $sql = "SELECT id, name, attendance_qualify_max
85
                FROM $table
86
                WHERE c_id = $course_id AND active = 1 $condition_session ";
87
        $result = Database::query($sql);
88
        $data = [];
89
        if (Database::num_rows($result) > 0) {
90
            while ($row = Database::fetch_array($result, 'ASSOC')) {
91
                $data[$row['id']] = $row;
92
            }
93
        }
94
95
        return $data;
96
    }
97
98
    /**
99
     * Get the attendances to display on the current page (fill the sortable-table).
100
     *
101
     * @param   int     offset of first user to recover
102
     * @param   int     Number of users to get
103
     * @param   int     Column to sort on
104
     * @param   string  Order (ASC,DESC)
105
     *
106
     * @see SortableTable#get_table_data($from)
107
     *
108
     * @return array
109
     */
110
    public static function get_attendance_data(
111
        $from,
112
        $number_of_items,
113
        $column,
114
        $direction
115
    ) {
116
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
117
        $course_id = api_get_course_int_id();
118
        $session_id = api_get_session_id();
119
        $condition_session = api_get_session_condition($session_id);
120
        $column = intval($column);
121
        $from = intval($from);
122
        $number_of_items = intval($number_of_items);
123
124
        if (!in_array($direction, ['ASC', 'DESC'])) {
125
            $direction = 'ASC';
126
        }
127
128
        $active_plus = '';
129
        if ((isset($_GET['isStudentView']) && $_GET['isStudentView'] == 'true') ||
130
            !api_is_allowed_to_edit(null, true)
131
        ) {
132
            $active_plus = ' AND att.active = 1';
133
        }
134
135
        $sql = "SELECT
136
                    att.id AS col0,
137
                    att.name AS col1,
138
                    att.description AS col2,
139
                    att.attendance_qualify_max AS col3,
140
                    att.locked AS col4,
141
                    att.active AS col5,
142
                    att.session_id
143
                FROM $tbl_attendance att
144
                WHERE
145
                    att.active <> 2 AND
146
                    c_id = $course_id $active_plus $condition_session
147
                ORDER BY col$column $direction
148
                LIMIT $from,$number_of_items ";
149
150
        $res = Database::query($sql);
151
        $attendances = [];
152
        $user_info = api_get_user_info();
153
        $allowDelete = api_get_setting('allow_delete_attendance');
154
155
        while ($attendance = Database::fetch_row($res)) {
156
            $student_param = '';
157
            if (api_is_drh() && $_GET['student_id']) {
158
                $student_param = '&student_id='.intval($_GET['student_id']);
159
            }
160
161
            $session_star = '';
162
            if (api_get_session_id() == $attendance[6]) {
163
                $session_star = api_get_session_image(api_get_session_id(), $user_info['status']);
164
            }
165
            if ($attendance[5] == 1) {
166
                $isDrhOfCourse = CourseManager::isUserSubscribedInCourseAsDrh(
167
                    api_get_user_id(),
168
                    api_get_course_info()
169
                );
170
171
                if (api_is_allowed_to_edit(null, true) || $isDrhOfCourse) {
172
                    // Link to edit
173
                    $attendance[1] = '<a href="index.php?'.api_get_cidreq().'&action=attendance_sheet_list&attendance_id='.$attendance[0].$student_param.'">'.$attendance[1].'</a>'.$session_star;
174
                } else {
175
                    // Link to view
176
                    $attendance[1] = '<a href="index.php?'.api_get_cidreq().'&action=attendance_sheet_list_no_edit&attendance_id='.$attendance[0].$student_param.'">'.$attendance[1].'</a>'.$session_star;
177
                }
178
            } else {
179
                $attendance[1] = '<a class="muted" href="index.php?'.api_get_cidreq().'&action=attendance_sheet_list&attendance_id='.$attendance[0].$student_param.'">'.$attendance[1].'</a>'.$session_star;
180
            }
181
182
            if ($attendance[5] == 1) {
183
                $attendance[3] = '<center>'.$attendance[3].'</center>';
184
            } else {
185
                $attendance[3] = '<center><span class="muted">'.$attendance[3].'</span></center>';
186
            }
187
188
            $attendance[3] = '<center>'.$attendance[3].'</center>';
189
            if (api_is_allowed_to_edit(null, true)) {
190
                $actions = '';
191
                $actions .= '<center>';
192
193
                if (api_is_platform_admin()) {
194
                    $actions .= '<a href="index.php?'.api_get_cidreq().'&action=attendance_edit&attendance_id='.$attendance[0].'">'.
195
                        Display::return_icon('edit.png', get_lang('Edit'), [], ICON_SIZE_SMALL).'</a>&nbsp;';
196
                    // Visible
197
                    if ($attendance[5] == 1) {
198
                        $actions .= '<a href="index.php?'.api_get_cidreq().'&action=attendance_set_invisible&attendance_id='.$attendance[0].'">'.
199
                            Display::return_icon('visible.png', get_lang('Hide'), [], ICON_SIZE_SMALL).'</a>';
200
                    } else {
201
                        $actions .= '<a href="index.php?'.api_get_cidreq().'&action=attendance_set_visible&attendance_id='.$attendance[0].'">'.
202
                            Display::return_icon('invisible.png', get_lang('Show'), [], ICON_SIZE_SMALL).'</a>';
203
                        $attendance[2] = '<span class="muted">'.$attendance[2].'</span>';
204
                    }
205
                    if ($allowDelete === 'true') {
206
                        $actions .= '<a href="index.php?'.api_get_cidreq().'&action=attendance_delete&attendance_id='.$attendance[0].'">'.
207
                            Display::return_icon('delete.png', get_lang('Delete'), [], ICON_SIZE_SMALL).'</a>';
208
                    }
209
                } else {
210
                    $is_locked_attendance = self::is_locked_attendance($attendance[0]);
211
                    if ($is_locked_attendance) {
212
                        $actions .= Display::return_icon('edit_na.png', get_lang('Edit')).'&nbsp;';
213
                        $actions .= Display::return_icon('visible.png', get_lang('Hide'));
214
                    } else {
215
                        $actions .= '<a href="index.php?'.api_get_cidreq().'&action=attendance_edit&attendance_id='.$attendance[0].'">'.
216
                            Display::return_icon('edit.png', get_lang('Edit'), [], ICON_SIZE_SMALL).'</a>&nbsp;';
217
218
                        if ($attendance[5] == 1) {
219
                            $actions .= ' <a href="index.php?'.api_get_cidreq().'&action=attendance_set_invisible&attendance_id='.$attendance[0].'">'.
220
                                Display::return_icon('visible.png', get_lang('Hide'), [], ICON_SIZE_SMALL).'</a>';
221
                        } else {
222
                            $actions .= ' <a href="index.php?'.api_get_cidreq().'&action=attendance_set_visible&attendance_id='.$attendance[0].'">'.
223
                                Display::return_icon('invisible.png', get_lang('Show'), [], ICON_SIZE_SMALL).'</a>';
224
                            $attendance[2] = '<span class="muted">'.$attendance[2].'</span>';
225
                        }
226
                        if ($allowDelete === 'true') {
227
                            $actions .= ' <a href="index.php?'.api_get_cidreq().'&action=attendance_delete&attendance_id='.$attendance[0].'">'.
228
                                Display::return_icon('delete.png', get_lang('Delete'), [], ICON_SIZE_SMALL).'</a>';
229
                        }
230
                    }
231
                }
232
233
                // display lock/unlock icon
234
                $is_done_all_calendar = self::is_all_attendance_calendar_done($attendance[0]);
235
236
                if ($is_done_all_calendar) {
237
                    $locked = $attendance[4];
238
                    if ($locked == 0) {
239
                        if (api_is_platform_admin()) {
240
                            $message_alert = get_lang('AreYouSureToLockTheAttendance');
241
                        } else {
242
                            $message_alert = get_lang('UnlockMessageInformation');
243
                        }
244
                        $actions .= '&nbsp;<a onclick="javascript:if(!confirm(\''.$message_alert.'\')) return false;" href="index.php?'.api_get_cidreq().'&action=lock_attendance&attendance_id='.$attendance[0].'">'.
245
                            Display::return_icon('unlock.png', get_lang('LockAttendance')).'</a>';
246
                    } else {
247
                        if (api_is_platform_admin()) {
248
                            $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].'">'.
249
                                    Display::return_icon('locked.png', get_lang('UnlockAttendance')).'</a>';
250
                        } else {
251
                            $actions .= '&nbsp;'.Display::return_icon('locked_na.png', get_lang('LockedAttendance'));
252
                        }
253
                    }
254
                }
255
                $actions .= '</center>';
256
257
                $attendances[] = [
258
                    $attendance[0],
259
                    $attendance[1],
260
                    $attendance[2],
261
                    $attendance[3],
262
                    $actions,
263
                ];
264
            } else {
265
                $attendance[0] = '&nbsp;';
266
                $attendances[] = [
267
                    $attendance[0],
268
                    $attendance[1],
269
                    $attendance[2],
270
                    $attendance[3],
271
                ];
272
            }
273
        }
274
275
        return $attendances;
276
    }
277
278
    /**
279
     * Get the attendances by id to display on the current page.
280
     *
281
     * @param int $attendanceId
282
     *
283
     * @return array attendance data
284
     */
285
    public function get_attendance_by_id($attendanceId)
286
    {
287
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
288
        $attendanceId = intval($attendanceId);
289
        $course_id = api_get_course_int_id();
290
        $attendance_data = [];
291
        $sql = "SELECT * FROM $tbl_attendance
292
                WHERE c_id = $course_id AND id = '$attendanceId'";
293
        $res = Database::query($sql);
294
        if (Database::num_rows($res) > 0) {
295
            while ($row = Database::fetch_array($res)) {
296
                $attendance_data = $row;
297
            }
298
        }
299
300
        return $attendance_data;
301
    }
302
303
    /**
304
     * Add attendances sheet inside table. This is the *list of* dates, not
305
     * a specific date in itself.
306
     *
307
     * @param  bool   true for adding link in gradebook or false otherwise (optional)
308
     *
309
     * @return int last attendance id
310
     */
311
    public function attendance_add($link_to_gradebook = false)
312
    {
313
        $_course = api_get_course_info();
314
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
315
        $table_link = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
316
        $session_id = api_get_session_id();
317
        $user_id = api_get_user_id();
318
        $course_code = $_course['code'];
319
        $course_id = $_course['real_id'];
320
        $title_gradebook = $this->attendance_qualify_title;
321
        $value_calification = 0;
322
        $weight_calification = api_float_val($this->attendance_weight);
323
324
        $params = [
325
            'c_id' => $course_id,
326
            'name' => $this->name,
327
            'description' => $this->description,
328
            'attendance_qualify_title' => $title_gradebook,
329
            'attendance_weight' => $weight_calification,
330
            'session_id' => $session_id,
331
            'active' => 1,
332
            'attendance_qualify_max' => 0,
333
            'locked' => 0,
334
        ];
335
        $last_id = Database::insert($tbl_attendance, $params);
336
337
        if (!empty($last_id)) {
338
            $sql = "UPDATE $tbl_attendance SET id = iid WHERE iid = $last_id";
339
            Database::query($sql);
340
341
            api_item_property_update(
342
                $_course,
343
                TOOL_ATTENDANCE,
344
                $last_id,
345
                "AttendanceAdded",
346
                $user_id
347
            );
348
        }
349
        // add link to gradebook
350
        if ($link_to_gradebook && !empty($this->category_id)) {
351
            $description = '';
352
            $link_info = GradebookUtils::isResourceInCourseGradebook(
353
                $course_code,
354
                7,
355
                $last_id,
0 ignored issues
show
Bug introduced by
It seems like $last_id can also be of type false; however, parameter $resource_id of GradebookUtils::isResourceInCourseGradebook() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

355
                /** @scrutinizer ignore-type */ $last_id,
Loading history...
356
                $session_id
357
            );
358
            $link_id = $link_info['id'];
359
            if (!$link_info) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $link_info of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
360
                GradebookUtils::add_resource_to_course_gradebook(
361
                    $this->category_id,
362
                    $course_code,
363
                    7,
364
                    $last_id,
365
                    $title_gradebook,
366
                    $weight_calification,
367
                    $value_calification,
368
                    $description,
369
                    1,
370
                    $session_id
371
                );
372
            } else {
373
                Database::query('UPDATE '.$table_link.' SET weight='.$weight_calification.' WHERE id='.$link_id.'');
374
            }
375
        }
376
377
        return $last_id;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $last_id could also return false which is incompatible with the documented return type integer. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
378
    }
379
380
    /**
381
     * edit attendances inside table.
382
     *
383
     * @param int attendance id
384
     * @param bool true for adding link in gradebook or false otherwise (optional)
385
     *
386
     * @return int last id
387
     */
388
    public function attendance_edit($attendanceId, $link_to_gradebook = false)
389
    {
390
        $_course = api_get_course_info();
391
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
392
        $table_link = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
393
394
        $session_id = api_get_session_id();
395
        $user_id = api_get_user_id();
396
        $attendanceId = intval($attendanceId);
397
        $course_code = $_course['code'];
398
        $course_id = $_course['real_id'];
399
        $title_gradebook = $this->attendance_qualify_title;
400
        $value_calification = 0;
401
        $weight_calification = api_float_val($this->attendance_weight);
402
403
        if (!empty($attendanceId)) {
404
            $params = [
405
                'name' => $this->name,
406
                'description' => $this->description,
407
                'attendance_qualify_title' => $title_gradebook,
408
                'attendance_weight' => $weight_calification,
409
            ];
410
            Database::update(
411
                $tbl_attendance,
412
                $params,
413
                ['c_id = ? AND id = ?' => [$course_id, $attendanceId]]
414
            );
415
416
            api_item_property_update(
417
                $_course,
418
                TOOL_ATTENDANCE,
419
                $attendanceId,
420
                "AttendanceUpdated",
421
                $user_id
422
            );
423
424
            // add link to gradebook
425
            if ($link_to_gradebook && !empty($this->category_id)) {
426
                $description = '';
427
                $link_info = GradebookUtils::isResourceInCourseGradebook(
428
                    $course_code,
429
                    7,
430
                    $attendanceId,
431
                    $session_id
432
                );
433
                if (!$link_info) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $link_info of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
434
                    GradebookUtils::add_resource_to_course_gradebook(
435
                        $this->category_id,
436
                        $course_code,
437
                        7,
438
                        $attendanceId,
439
                        $title_gradebook,
440
                        $weight_calification,
441
                        $value_calification,
442
                        $description,
443
                        1,
444
                        $session_id
445
                    );
446
                } else {
447
                    Database::query('UPDATE '.$table_link.' SET weight='.$weight_calification.' WHERE id='.$link_info['id'].'');
448
                }
449
            }
450
451
            return $attendanceId;
452
        }
453
454
        return null;
455
    }
456
457
    /**
458
     * Restore attendance.
459
     *
460
     * @param int|array one or many attendances id
461
     *
462
     * @return int affected rows
463
     */
464
    public function attendance_restore($attendanceId)
465
    {
466
        $_course = api_get_course_info();
467
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
468
        $user_id = api_get_user_id();
469
        $course_id = $_course['real_id'];
470
        if (is_array($attendanceId)) {
471
            foreach ($attendanceId as $id) {
472
                $id = intval($id);
473
                $sql = "UPDATE $tbl_attendance SET active = 1
474
                        WHERE c_id = $course_id AND id = '$id'";
475
                $result = Database::query($sql);
476
                $affected_rows = Database::affected_rows($result);
477
                if (!empty($affected_rows)) {
478
                    // update row item property table
479
                    api_item_property_update(
480
                        $_course,
481
                        TOOL_ATTENDANCE,
482
                        $id,
483
                        'restore',
484
                        $user_id
485
                    );
486
                }
487
            }
488
        } else {
489
            $attendanceId = intval($attendanceId);
490
            $sql = "UPDATE $tbl_attendance SET active = 1
491
                    WHERE c_id = $course_id AND id = '$attendanceId'";
492
            $result = Database::query($sql);
493
            $affected_rows = Database::affected_rows($result);
494
            if (!empty($affected_rows)) {
495
                // update row item property table
496
                api_item_property_update(
497
                    $_course,
498
                    TOOL_ATTENDANCE,
499
                    $attendanceId,
500
                    'restore',
501
                    $user_id
502
                );
503
            }
504
        }
505
506
        return $affected_rows;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $affected_rows does not seem to be defined for all execution paths leading up to this point.
Loading history...
507
    }
508
509
    /**
510
     * Delete attendances.
511
     *
512
     * @param int|array $attendanceId one or many attendances id
513
     *
514
     * @return int affected rows
515
     */
516
    public function attendance_delete($attendanceId)
517
    {
518
        $_course = api_get_course_info();
519
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
520
        $user_id = api_get_user_id();
521
        $course_id = $_course['real_id'];
522
523
        if (is_array($attendanceId)) {
524
            foreach ($attendanceId as $id) {
525
                $id = intval($id);
526
                $sql = "UPDATE $tbl_attendance SET active = 2
527
                        WHERE c_id = $course_id AND id = '$id'";
528
                $result = Database::query($sql);
529
                $affected_rows = Database::affected_rows($result);
530
                if (!empty($affected_rows)) {
531
                    // update row item property table
532
                    api_item_property_update(
533
                        $_course,
534
                        TOOL_ATTENDANCE,
535
                        $id,
536
                        "delete",
537
                        $user_id
538
                    );
539
                }
540
            }
541
        } else {
542
            $attendanceId = intval($attendanceId);
543
            $sql = "UPDATE $tbl_attendance SET active = 2
544
                    WHERE c_id = $course_id AND id = '$attendanceId'";
545
546
            $result = Database::query($sql);
547
            $affected_rows = Database::affected_rows($result);
548
            if (!empty($affected_rows)) {
549
                // update row item property table
550
                api_item_property_update(
551
                    $_course,
552
                    TOOL_ATTENDANCE,
553
                    $attendanceId,
554
                    "delete",
555
                    $user_id
556
                );
557
            }
558
        }
559
560
        return $affected_rows;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $affected_rows does not seem to be defined for all execution paths leading up to this point.
Loading history...
561
    }
562
563
    /**
564
     * Changes visibility.
565
     *
566
     * @param int|array $attendanceId one or many attendances id
567
     * @param int       $status
568
     *
569
     * @return int affected rows
570
     */
571
    public function changeVisibility($attendanceId, $status = 1)
572
    {
573
        $_course = api_get_course_info();
574
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
575
        $user_id = api_get_user_id();
576
        $course_id = $_course['real_id'];
577
        $status = intval($status);
578
579
        $action = 'visible';
580
        if ($status == 0) {
581
            $action = 'invisible';
582
        }
583
584
        if (is_array($attendanceId)) {
585
            foreach ($attendanceId as $id) {
586
                $id = intval($id);
587
                $sql = "UPDATE $tbl_attendance SET active = $status
588
                        WHERE c_id = $course_id AND id = '$id'";
589
                $result = Database::query($sql);
590
                $affected_rows = Database::affected_rows($result);
591
                if (!empty($affected_rows)) {
592
                    // update row item property table
593
                    api_item_property_update(
594
                        $_course,
595
                        TOOL_ATTENDANCE,
596
                        $id,
597
                        $action,
598
                        $user_id
599
                    );
600
                }
601
            }
602
        } else {
603
            $attendanceId = intval($attendanceId);
604
            $sql = "UPDATE $tbl_attendance SET active = $status
605
                    WHERE c_id = $course_id AND id = '$attendanceId'";
606
            $result = Database::query($sql);
607
            $affected_rows = Database::affected_rows($result);
608
            if (!empty($affected_rows)) {
609
                // update row item property table
610
                api_item_property_update(
611
                    $_course,
612
                    TOOL_ATTENDANCE,
613
                    $attendanceId,
614
                    $action,
615
                    $user_id
616
                );
617
            }
618
        }
619
620
        return $affected_rows;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $affected_rows does not seem to be defined for all execution paths leading up to this point.
Loading history...
621
    }
622
623
    /**
624
     * Lock or unlock an attendance.
625
     *
626
     * @param   int     attendance id
627
     * @param   bool    True to lock or false otherwise
628
     *
629
     * @return int
630
     */
631
    public function lock_attendance($attendanceId, $lock = true)
632
    {
633
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
634
        $course_id = api_get_course_int_id();
635
        $attendanceId = intval($attendanceId);
636
        $locked = ($lock) ? 1 : 0;
637
        $upd = "UPDATE $tbl_attendance SET locked = $locked
638
                WHERE c_id = $course_id AND id = $attendanceId";
639
        $result = Database::query($upd);
640
        $affected_rows = Database::affected_rows($result);
641
        if ($affected_rows && $lock) {
642
            // Save attendance sheet log
643
            $this->saveAttendanceSheetLog(
644
                $attendanceId,
645
                api_get_utc_datetime(),
646
                self::LOCKED_ATTENDANCE_LOG_TYPE,
647
                api_get_user_id()
648
            );
649
        }
650
651
        return $affected_rows;
652
    }
653
654
    /**
655
     * Get registered users inside current course.
656
     *
657
     * @param int $attendanceId attendance id for showing attendance result field (optional)
658
     * @param int $groupId
659
     *
660
     * @return array users data
661
     */
662
    public function get_users_rel_course($attendanceId = 0, $groupId = 0)
663
    {
664
        $current_session_id = api_get_session_id();
665
        $current_course_id = api_get_course_id();
666
        $currentCourseIntId = api_get_course_int_id();
667
        $studentInGroup = [];
668
669
        if (!empty($current_session_id)) {
670
            $a_course_users = CourseManager:: get_user_list_from_course_code(
671
                $current_course_id,
672
                $current_session_id,
673
                '',
674
                'lastname'
675
            );
676
        } else {
677
            $a_course_users = CourseManager:: get_user_list_from_course_code(
678
                $current_course_id,
679
                0,
680
                '',
681
                'lastname'
682
            );
683
        }
684
685
        if (!empty($groupId)) {
686
            $groupInfo = GroupManager::get_group_properties($groupId);
687
            $students = GroupManager::getStudents($groupInfo['iid']);
688
            if (!empty($students)) {
689
                foreach ($students as $student) {
690
                    $studentInGroup[$student['user_id']] = true;
691
                }
692
            }
693
        }
694
695
        // get registered users inside current course
696
        $a_users = [];
697
        foreach ($a_course_users as $key => $user_data) {
698
            $value = [];
699
            $uid = $user_data['user_id'];
700
            $userInfo = api_get_user_info($uid);
701
            $status = $user_data['status'];
702
703
            if (!empty($groupId)) {
704
                if (!isset($studentInGroup[$uid])) {
705
                    continue;
706
                }
707
            }
708
709
            $user_status_in_session = null;
710
            $user_status_in_course = null;
711
712
            if (api_get_session_id()) {
713
                $user_status_in_session = SessionManager::get_user_status_in_course_session(
714
                    $uid,
715
                    $currentCourseIntId,
716
                    $current_session_id
717
                );
718
            } else {
719
                $user_status_in_course = CourseManager::getUserInCourseStatus(
720
                    $uid,
721
                    $currentCourseIntId
722
                );
723
            }
724
725
            // Not taking into account DRH or COURSEMANAGER
726
            if ($uid <= 1 ||
727
                $status == DRH ||
728
                $user_status_in_course == COURSEMANAGER ||
729
                $user_status_in_session == 2
730
            ) {
731
                continue;
732
            }
733
734
            if (!empty($attendanceId)) {
735
                $user_faults = $this->get_faults_of_user(
736
                    $uid,
737
                    $attendanceId,
738
                    $groupId
739
                );
740
                $value['attendance_result'] = $user_faults['faults'].'/'.$user_faults['total'].' ('.$user_faults['faults_porcent'].'%)';
741
                $value['result_color_bar'] = $user_faults['color_bar'];
742
            }
743
744
            $photo = Display::img(
745
                $userInfo['avatar_small'],
746
                $userInfo['complete_name'],
747
                [],
748
                false
749
            );
750
751
            $value['photo'] = $photo;
752
            $value['firstname'] = $user_data['firstname'];
753
            $value['lastname'] = $user_data['lastname'];
754
            $value['username'] = $user_data['username'];
755
            $value['user_id'] = $uid;
756
757
            // Sending only 5 items in the array instead of 60
758
            $a_users[$key] = $value;
759
        }
760
761
        return $a_users;
762
    }
763
764
    /**
765
     * add attendances sheet inside table.
766
     *
767
     * @param int   $calendar_id   attendance calendar id
768
     * @param array $users_present present users during current class
769
     * @param int   $attendanceId
770
     *
771
     * @return int affected rows
772
     */
773
    public function attendance_sheet_add($calendar_id, $users_present, $attendanceId)
774
    {
775
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
776
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
777
778
        $calendar_id = intval($calendar_id);
779
        $attendanceId = intval($attendanceId);
780
        $users = $this->get_users_rel_course();
781
        $course_id = api_get_course_int_id();
782
783
        $user_ids = array_keys($users);
784
        $users_absent = array_diff($user_ids, $users_present);
785
        $affected_rows = 0;
786
787
        // get last edit type
788
        $calendar_data = $this->get_attendance_calendar_by_id($calendar_id);
789
        $lastedit_type = self::DONE_ATTENDANCE_LOG_TYPE;
790
        if ($calendar_data['done_attendance']) {
791
            $lastedit_type = self::UPDATED_ATTENDANCE_LOG_TYPE;
792
        }
793
794
        // save users present in class
795
        foreach ($users_present as $user_present) {
796
            $uid = intval($user_present);
797
            // check if user already was registered with the $calendar_id
798
            $sql = "SELECT user_id FROM $tbl_attendance_sheet
799
                    WHERE c_id = $course_id AND user_id='$uid' AND attendance_calendar_id = '$calendar_id'";
800
            $rs = Database::query($sql);
801
            if (Database::num_rows($rs) == 0) {
802
                $sql = "INSERT INTO $tbl_attendance_sheet SET
803
                        c_id = $course_id,
804
                        user_id = '$uid',
805
                        attendance_calendar_id = '$calendar_id',
806
                        presence = 1";
807
                $result = Database::query($sql);
808
809
                $affected_rows += Database::affected_rows($result);
810
            } else {
811
                $sql = "UPDATE $tbl_attendance_sheet SET presence = 1
812
                        WHERE
813
                            c_id = $course_id AND
814
                            user_id ='$uid' AND
815
                            attendance_calendar_id = '$calendar_id'
816
                        ";
817
                $result = Database::query($sql);
818
                $affected_rows += Database::affected_rows($result);
819
            }
820
        }
821
822
        // save users absent in class
823
        foreach ($users_absent as $user_absent) {
824
            $uid = intval($user_absent);
825
            // check if user already was registered with the $calendar_id
826
            $sql = "SELECT user_id FROM $tbl_attendance_sheet
827
                    WHERE c_id = $course_id AND user_id='$uid' AND attendance_calendar_id = '$calendar_id'";
828
            $rs = Database::query($sql);
829
            if (Database::num_rows($rs) == 0) {
830
                $sql = "INSERT INTO $tbl_attendance_sheet SET
831
                        c_id = $course_id,
832
                        user_id ='$uid',
833
                        attendance_calendar_id = '$calendar_id',
834
                        presence = 0";
835
                $result = Database::query($sql);
836
837
                Database::insert_id();
838
839
                $affected_rows += Database::affected_rows($result);
840
            } else {
841
                $sql = "UPDATE $tbl_attendance_sheet SET presence = 0
842
                        WHERE
843
                            c_id = $course_id AND
844
                            user_id ='$uid' AND
845
                            attendance_calendar_id = '$calendar_id'";
846
                $result = Database::query($sql);
847
                $affected_rows += Database::affected_rows($result);
848
            }
849
        }
850
851
        // update done_attendance inside attendance calendar table
852
        $sql = "UPDATE $tbl_attendance_calendar SET done_attendance = 1
853
                WHERE  c_id = $course_id AND id = '$calendar_id'";
854
        Database::query($sql);
855
856
        // save users' results
857
        $this->updateUsersResults($user_ids, $attendanceId);
858
859
        if ($affected_rows) {
860
            //save attendance sheet log
861
            $this->saveAttendanceSheetLog(
862
                $attendanceId,
863
                api_get_utc_datetime(),
864
                $lastedit_type,
865
                api_get_user_id(),
866
                $calendar_data['date_time']
867
            );
868
        }
869
870
        return $affected_rows;
871
    }
872
873
    /**
874
     * update users' attendance results.
875
     *
876
     * @param array $user_ids     registered users inside current course
877
     * @param int   $attendanceId
878
     */
879
    public function updateUsersResults($user_ids, $attendanceId)
880
    {
881
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
882
        $tbl_attendance_result = Database::get_course_table(TABLE_ATTENDANCE_RESULT);
883
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
884
        $course_id = api_get_course_int_id();
885
        $attendanceId = intval($attendanceId);
886
        // fill results about presence of students
887
        $attendance_calendar = $this->get_attendance_calendar(
888
            $attendanceId,
889
            'all',
890
            null,
891
            null,
892
            true
893
        );
894
        $calendar_ids = [];
895
        // get all dates from calendar by current attendance
896
        foreach ($attendance_calendar as $cal) {
897
            $calendar_ids[] = $cal['id'];
898
        }
899
900
        // get count of presences by users inside current attendance and save like results
901
        if (count($user_ids) > 0) {
902
            foreach ($user_ids as $uid) {
903
                $count_presences = 0;
904
                if (count($calendar_ids) > 0) {
905
                    $sql = "SELECT count(presence) as count_presences
906
                            FROM $tbl_attendance_sheet
907
                            WHERE
908
                                c_id = $course_id AND
909
                                user_id = '$uid' AND
910
                                attendance_calendar_id IN (".implode(',', $calendar_ids).") AND
911
                                presence = 1";
912
                    $rs_count = Database::query($sql);
913
                    $row_count = Database::fetch_array($rs_count);
914
                    $count_presences = $row_count['count_presences'];
915
                }
916
917
                // save results
918
                $sql = "SELECT id FROM $tbl_attendance_result
919
                        WHERE
920
                            c_id = $course_id AND
921
                            user_id = '$uid' AND
922
                            attendance_id = '$attendanceId' ";
923
                $rs_check_result = Database::query($sql);
924
925
                if (Database::num_rows($rs_check_result) > 0) {
926
                    // update result
927
                    $sql = "UPDATE $tbl_attendance_result SET
928
                            score = '$count_presences'
929
                            WHERE
930
                                c_id = $course_id AND
931
                                user_id='$uid' AND
932
                                attendance_id='$attendanceId'";
933
                    Database::query($sql);
934
                } else {
935
                    // insert new result
936
                    $sql = "INSERT INTO $tbl_attendance_result SET
937
                            c_id = $course_id ,
938
                            user_id			= '$uid',
939
                            attendance_id 	= '$attendanceId',
940
                            score			= '$count_presences'";
941
                    Database::query($sql);
942
943
                    $insertId = Database::insert_id();
944
                    if ($insertId) {
945
                        $sql = "UPDATE $tbl_attendance_result SET id = iid WHERE iid = $insertId";
946
                        Database::query($sql);
947
                    }
948
                }
949
            }
950
        }
951
952
        // update attendance qualify max
953
        $count_done_calendar = self::get_done_attendance_calendar($attendanceId);
954
        $sql = "UPDATE $tbl_attendance SET
955
                    attendance_qualify_max = '$count_done_calendar'
956
                WHERE c_id = $course_id AND id = '$attendanceId'";
957
        Database::query($sql);
958
    }
959
960
    /**
961
     * update attendance_sheet_log table, is used as history of an attendance sheet.
962
     *
963
     * @param   int     Attendance id
964
     * @param   string  Last edit datetime
965
     * @param   string  Event type ('locked_attendance', 'done_attendance_sheet' ...)
966
     * @param   int     Last edit user id
967
     * @param   string  Calendar datetime value (optional, when event type is 'done_attendance_sheet')
968
     *
969
     * @return int Affected rows
970
     */
971
    public function saveAttendanceSheetLog(
972
        $attendanceId,
973
        $lastedit_date,
974
        $lastedit_type,
975
        $lastedit_user_id,
976
        $calendar_date_value = null
977
    ) {
978
        $course_id = api_get_course_int_id();
979
980
        // define table
981
        $tbl_attendance_sheet_log = Database::get_course_table(TABLE_ATTENDANCE_SHEET_LOG);
982
983
        // protect data
984
        $attendanceId = intval($attendanceId);
985
        $lastedit_user_id = intval($lastedit_user_id);
986
987
        if (isset($calendar_date_value)) {
988
            $calendar_date_value = $calendar_date_value;
989
        } else {
990
            $calendar_date_value = '';
991
        }
992
993
        // save data
994
        $params = [
995
            'c_id' => $course_id,
996
            'attendance_id' => $attendanceId,
997
            'lastedit_date' => $lastedit_date,
998
            'lastedit_type' => $lastedit_type,
999
            'lastedit_user_id' => $lastedit_user_id,
1000
            'calendar_date_value' => $calendar_date_value,
1001
        ];
1002
        $insertId = Database::insert($tbl_attendance_sheet_log, $params);
1003
        if ($insertId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $insertId of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1004
            $sql = "UPDATE $tbl_attendance_sheet_log SET id = iid WHERE iid = $insertId";
1005
            Database::query($sql);
1006
        }
1007
1008
        return $insertId;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $insertId could also return false which is incompatible with the documented return type integer. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
1009
    }
1010
1011
    /**
1012
     * Get number of done attendances inside current sheet.
1013
     *
1014
     * @param int attendance id
1015
     *
1016
     * @return int number of done attendances
1017
     */
1018
    public static function get_done_attendance_calendar($attendanceId)
1019
    {
1020
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1021
        $attendanceId = intval($attendanceId);
1022
        $course_id = api_get_course_int_id();
1023
        $sql = "SELECT count(done_attendance) as count
1024
                FROM $table
1025
                WHERE
1026
                    c_id = $course_id AND
1027
                    attendance_id = '$attendanceId' AND
1028
                    done_attendance = 1
1029
                ";
1030
        $rs = Database::query($sql);
1031
        $row = Database::fetch_array($rs);
1032
        $count = $row['count'];
1033
1034
        return $count;
1035
    }
1036
1037
    /**
1038
     * Get results of faults (absents) by user.
1039
     *
1040
     * @param int $user_id
1041
     * @param int $attendanceId
1042
     * @param int $groupId
1043
     *
1044
     * @return array results containing number of faults, total done attendance,
1045
     *               percent of faults and color depend on result (red, orange)
1046
     */
1047
    public function get_faults_of_user($user_id, $attendanceId, $groupId = null)
1048
    {
1049
        $user_id = intval($user_id);
1050
        $attendanceId = intval($attendanceId);
1051
        $results = [];
1052
        $calendar_count = self::get_number_of_attendance_calendar(
1053
            $attendanceId,
1054
            $groupId,
1055
            null,
1056
            $user_id
1057
        );
1058
        // $total_done_attendance 	= $attendance_data['attendance_qualify_max'];
1059
        $total_done_attendance = self::get_number_of_attendance_calendar(
1060
            $attendanceId,
1061
            $groupId,
1062
            true,
1063
            $user_id
1064
        );
1065
        $attendance_user_score = $this->get_user_score(
1066
            $user_id,
1067
            $attendanceId,
1068
            $groupId
1069
        );
1070
1071
        //This is the main change of the BT#1381
1072
        //$total_done_attendance = $calendar_count;
1073
1074
        // calculate results
1075
        $faults = $total_done_attendance - $attendance_user_score;
1076
1077
        if (empty($calendar_count)) {
1078
            $faults = 0;
1079
        }
1080
1081
        $faults = $faults > 0 ? $faults : 0;
1082
        $faults_porcent = $calendar_count > 0 ? round(($faults * 100) / $calendar_count, 0) : 0;
1083
        $results['faults'] = $faults;
1084
        $results['total'] = $calendar_count;
1085
        $results['faults_porcent'] = $faults_porcent;
1086
        $color_bar = '';
1087
1088
        if ($faults_porcent > 25) {
1089
            $color_bar = '#f28989';
1090
        } elseif ($faults_porcent > 10) {
1091
            $color_bar = '#F90';
1092
        }
1093
        $results['color_bar'] = $color_bar;
1094
1095
        return $results;
1096
    }
1097
1098
    /**
1099
     * Get results of faults average for all courses by user.
1100
     *
1101
     * @param int $user_id
1102
     *
1103
     * @return array results containing number of faults, total done attendance,
1104
     *               percentage of faults and color depend on result (red, orange)
1105
     */
1106
    public function get_faults_average_inside_courses($user_id)
1107
    {
1108
        // get all courses of current user
1109
        $courses = CourseManager::get_courses_list_by_user_id($user_id, true);
1110
        $user_id = intval($user_id);
1111
        $results = [];
1112
        $total_faults = $total_weight = $porcent = 0;
1113
        foreach ($courses as $course) {
1114
            //$course_code = $course['code'];
1115
            //$course_info = api_get_course_info($course_code);
1116
            $course_id = $course['real_id'];
1117
            $tbl_attendance_result = Database::get_course_table(TABLE_ATTENDANCE_RESULT);
1118
            $attendances_by_course = $this->get_attendances_list($course_id);
1119
1120
            foreach ($attendances_by_course as $attendance) {
1121
                // get total faults and total weight
1122
                $total_done_attendance = $attendance['attendance_qualify_max'];
1123
                $sql = "SELECT score
1124
                        FROM $tbl_attendance_result
1125
                        WHERE
1126
                            c_id = $course_id AND
1127
                            user_id = $user_id AND
1128
                            attendance_id = ".$attendance['id'];
1129
                $rs = Database::query($sql);
1130
                $score = 0;
1131
                if (Database::num_rows($rs) > 0) {
1132
                    $row = Database::fetch_array($rs);
1133
                    $score = $row['score'];
1134
                }
1135
                $faults = $total_done_attendance - $score;
1136
                $faults = $faults > 0 ? $faults : 0;
1137
                $total_faults += $faults;
1138
                $total_weight += $total_done_attendance;
1139
            }
1140
        }
1141
1142
        $porcent = $total_weight > 0 ? round(($total_faults * 100) / $total_weight, 0) : 0;
1143
        $results['faults'] = $total_faults;
1144
        $results['total'] = $total_weight;
1145
        $results['porcent'] = $porcent;
1146
1147
        return $results;
1148
    }
1149
1150
    /**
1151
     * Get results of faults average by course.
1152
     *
1153
     * @param int    $user_id
1154
     * @param string $course_code
1155
     * @param int Session id (optional)
1156
     *
1157
     * @return array results containing number of faults,
1158
     *               total done attendance, porcent of faults and color depend on result (red, orange)
1159
     */
1160
    public function get_faults_average_by_course(
1161
        $user_id,
1162
        $course_code,
1163
        $session_id = null
1164
    ) {
1165
        // Database tables and variables
1166
        $course_info = api_get_course_info($course_code);
1167
        $tbl_attendance_result = Database::get_course_table(TABLE_ATTENDANCE_RESULT);
1168
        $user_id = intval($user_id);
1169
        $results = [];
1170
        $total_faults = $total_weight = $porcent = 0;
1171
        $attendances_by_course = $this->get_attendances_list(
1172
            $course_info['real_id'],
1173
            $session_id
1174
        );
1175
1176
        foreach ($attendances_by_course as $attendance) {
1177
            // Get total faults and total weight
1178
            $total_done_attendance = $attendance['attendance_qualify_max'];
1179
            $sql = "SELECT score FROM $tbl_attendance_result
1180
                    WHERE
1181
                        c_id = {$course_info['real_id']} AND
1182
                        user_id = $user_id AND
1183
                        attendance_id=".$attendance['id'];
1184
            $rs = Database::query($sql);
1185
            $score = 0;
1186
            if (Database::num_rows($rs) > 0) {
1187
                $row = Database::fetch_array($rs);
1188
                $score = $row['score'];
1189
            }
1190
            $faults = $total_done_attendance - $score;
1191
            $faults = $faults > 0 ? $faults : 0;
1192
            $total_faults += $faults;
1193
            $total_weight += $total_done_attendance;
1194
        }
1195
1196
        $porcent = $total_weight > 0 ? round(($total_faults * 100) / $total_weight, 0) : 0;
1197
        $results['faults'] = $total_faults;
1198
        $results['total'] = $total_weight;
1199
        $results['porcent'] = $porcent;
1200
1201
        return $results;
1202
    }
1203
1204
    /**
1205
     * Get registered users' attendance sheet inside current course.
1206
     *
1207
     * @param int $attendanceId
1208
     * @param int $user_id      for showing data for only one user (optional)
1209
     * @param int $groupId
1210
     *
1211
     * @return array users attendance sheet data
1212
     */
1213
    public function get_users_attendance_sheet(
1214
        $attendanceId,
1215
        $user_id = 0,
1216
        $groupId = 0
1217
    ) {
1218
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
1219
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1220
        $attendance_calendar = $this->get_attendance_calendar(
1221
            $attendanceId,
1222
            'all',
1223
            null,
1224
            $groupId
1225
        );
1226
        $calendar_ids = [];
1227
        // get all dates from calendar by current attendance
1228
        foreach ($attendance_calendar as $cal) {
1229
            $calendar_ids[] = $cal['id'];
1230
        }
1231
1232
        $course_id = api_get_course_int_id();
1233
1234
        $data = [];
1235
        if (empty($user_id)) {
1236
            // get all registered users inside current course
1237
            $users = $this->get_users_rel_course();
1238
            $user_ids = array_keys($users);
1239
            if (count($calendar_ids) > 0 && count($user_ids) > 0) {
1240
                foreach ($user_ids as $uid) {
1241
                    $sql = "SELECT * FROM $tbl_attendance_sheet
1242
                            WHERE
1243
                                c_id = $course_id AND
1244
                                user_id = '$uid' AND
1245
                                attendance_calendar_id IN(".implode(',', $calendar_ids).")
1246
                            ";
1247
                    $res = Database::query($sql);
1248
                    if (Database::num_rows($res) > 0) {
1249
                        while ($row = Database::fetch_array($res)) {
1250
                            $data[$uid][$row['attendance_calendar_id']]['presence'] = $row['presence'];
1251
                        }
1252
                    }
1253
                }
1254
            }
1255
        } else {
1256
            // Get attendance for current user
1257
            $user_id = intval($user_id);
1258
            if (count($calendar_ids) > 0) {
1259
                $sql = "SELECT cal.date_time, att.presence
1260
                        FROM $tbl_attendance_sheet att
1261
                        INNER JOIN  $tbl_attendance_calendar cal
1262
                        ON cal.id = att.attendance_calendar_id
1263
                        WHERE
1264
                            att.c_id = $course_id AND
1265
                            cal.c_id =  $course_id AND
1266
                            att.user_id = '$user_id' AND
1267
                            att.attendance_calendar_id IN (".implode(',', $calendar_ids).")
1268
                        ORDER BY date_time";
1269
                $res = Database::query($sql);
1270
                if (Database::num_rows($res) > 0) {
1271
                    while ($row = Database::fetch_array($res)) {
1272
                        $row['date_time'] = api_convert_and_format_date($row['date_time'], null, date_default_timezone_get());
1273
                        $data[$user_id][] = $row;
1274
                    }
1275
                }
1276
            }
1277
        }
1278
1279
        return $data;
1280
    }
1281
1282
    /**
1283
     * Get next attendance calendar without presences (done attendances).
1284
     *
1285
     * @param int    attendance id
1286
     *
1287
     * @return int attendance calendar id
1288
     */
1289
    public function get_next_attendance_calendar_id($attendanceId)
1290
    {
1291
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1292
        $attendanceId = intval($attendanceId);
1293
        $course_id = api_get_course_int_id();
1294
1295
        $sql = "SELECT id FROM $table
1296
                WHERE
1297
                    c_id = $course_id AND
1298
                    attendance_id = '$attendanceId' AND
1299
                    done_attendance = 0
1300
                ORDER BY date_time
1301
                LIMIT 1";
1302
        $rs = Database::query($sql);
1303
        $next_calendar_id = 0;
1304
        if (Database::num_rows($rs) > 0) {
1305
            $row = Database::fetch_array($rs);
1306
            $next_calendar_id = $row['id'];
1307
        }
1308
1309
        return $next_calendar_id;
1310
    }
1311
1312
    /**
1313
     * Get next attendance calendar datetime without presences (done attendances).
1314
     *
1315
     * @param int    attendance id
1316
     *
1317
     * @return int UNIX time format datetime
1318
     */
1319
    public function getNextAttendanceCalendarDatetime($attendanceId)
1320
    {
1321
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1322
        $course_id = api_get_course_int_id();
1323
        $attendanceId = intval($attendanceId);
1324
        $sql = "SELECT id, date_time FROM $table
1325
                WHERE
1326
                    c_id = $course_id AND
1327
                    attendance_id = '$attendanceId' AND
1328
                    done_attendance = 0
1329
                ORDER BY date_time
1330
                LIMIT 1";
1331
        $rs = Database::query($sql);
1332
        $next_calendar_datetime = 0;
1333
        if (Database::num_rows($rs) > 0) {
1334
            $row = Database::fetch_array($rs);
1335
            $next_calendar_datetime = api_get_local_time($row['date_time']);
1336
        }
1337
1338
        return $next_calendar_datetime;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $next_calendar_datetime also could return the type string which is incompatible with the documented return type integer.
Loading history...
1339
    }
1340
1341
    /**
1342
     * Get user's score from current attendance.
1343
     *
1344
     * @param int $user_id
1345
     * @param int $attendanceId
1346
     * @param int $groupId
1347
     *
1348
     * @return int score
1349
     */
1350
    public function get_user_score($user_id, $attendanceId, $groupId = 0)
1351
    {
1352
        $tbl_attendance_result = Database::get_course_table(TABLE_ATTENDANCE_RESULT);
1353
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
1354
        $tbl_attendance_cal_rel_group = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1355
        $tbl_attendance_cal = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1356
        $user_id = intval($user_id);
1357
        $attendanceId = intval($attendanceId);
1358
        $groupId = (int) $groupId;
1359
        $course_id = api_get_course_int_id();
1360
        if (empty($groupId)) {
1361
            $sql = "SELECT score FROM $tbl_attendance_result
1362
                    WHERE
1363
                        c_id = $course_id AND
1364
                        user_id='$user_id' AND
1365
                        attendance_id='$attendanceId'";
1366
        } else {
1367
            $sql = "SELECT count(presence) as score FROM $tbl_attendance_sheet
1368
                    WHERE
1369
                        c_id = $course_id AND
1370
                        user_id='$user_id' AND
1371
                        presence = 1 AND
1372
                        attendance_calendar_id IN (
1373
                            SELECT calendar_id FROM $tbl_attendance_cal_rel_group crg
1374
                            INNER JOIN $tbl_attendance_cal c
1375
                            ON (crg.calendar_id = c.id)
1376
                            WHERE
1377
                                crg.c_id = $course_id AND
1378
                                crg.group_id = $groupId AND
1379
                                c.attendance_id = $attendanceId
1380
                        )
1381
                    ";
1382
        }
1383
        $rs = Database::query($sql);
1384
        $score = 0;
1385
        if (Database::num_rows($rs) > 0) {
1386
            $row = Database::fetch_array($rs);
1387
            $score = $row['score'];
1388
        }
1389
1390
        return $score;
1391
    }
1392
1393
    /**
1394
     * Get attendance calendar data by id.
1395
     *
1396
     * @param int    attendance calendar id
1397
     *
1398
     * @return array attendance calendar data
1399
     */
1400
    public function get_attendance_calendar_by_id($calendar_id)
1401
    {
1402
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1403
        $calendar_id = intval($calendar_id);
1404
        $course_id = api_get_course_int_id();
1405
        $sql = "SELECT * FROM $table
1406
                WHERE c_id = $course_id AND id = '$calendar_id' ";
1407
        $rs = Database::query($sql);
1408
        $data = [];
1409
        if (Database::num_rows($rs) > 0) {
1410
            while ($row = Database::fetch_array($rs)) {
1411
                $row['date_time'] = api_get_local_time($row['date_time']);
1412
                $data = $row;
1413
            }
1414
        }
1415
1416
        return $data;
1417
    }
1418
1419
    /**
1420
     * Get all attendance calendar data inside current attendance.
1421
     *
1422
     * @param int    $attendanceId
1423
     * @param string $type
1424
     * @param int    $calendar_id
1425
     * @param int    $groupId
1426
     * @param bool   $showAll      = false show group calendar items or not
1427
     *
1428
     * @return array attendance calendar data
1429
     */
1430
    public function get_attendance_calendar(
1431
        $attendanceId,
1432
        $type = 'all',
1433
        $calendar_id = null,
1434
        $groupId = 0,
1435
        $showAll = false
1436
    ) {
1437
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1438
        $tbl_acrg = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1439
        $attendanceId = intval($attendanceId);
1440
        $course_id = api_get_course_int_id();
1441
1442
        if ($showAll) {
1443
            $sql = "SELECT * FROM $tbl_attendance_calendar c
1444
                    WHERE c_id = $course_id AND attendance_id = '$attendanceId'";
1445
        } else {
1446
            $sql = "SELECT * FROM $tbl_attendance_calendar c
1447
                    WHERE
1448
                        c_id = $course_id AND
1449
                        attendance_id = '$attendanceId' AND
1450
                        id NOT IN (
1451
                            SELECT calendar_id FROM $tbl_acrg
1452
                            WHERE c_id = $course_id AND group_id != 0 AND group_id IS NOT NULL
1453
                        )
1454
                    ";
1455
        }
1456
1457
        if (!empty($groupId)) {
1458
            $groupId = intval($groupId);
1459
            $sql = "SELECT c.* FROM $tbl_attendance_calendar c
1460
                    INNER JOIN $tbl_acrg g
1461
                    ON c.c_id = g.c_id AND c.id = g.calendar_id
1462
                    WHERE
1463
                        c.c_id = $course_id AND
1464
                        g.group_id = '$groupId' AND
1465
                        c.attendance_id = '$attendanceId'
1466
                   ";
1467
        }
1468
1469
        if (!in_array($type, ['today', 'all', 'all_done', 'all_not_done', 'calendar_id'])) {
1470
            $type = 'all';
1471
        }
1472
1473
        switch ($type) {
1474
            case 'calendar_id':
1475
                $calendar_id = intval($calendar_id);
1476
                if (!empty($calendar_id)) {
1477
                    $sql .= " AND c.id = $calendar_id";
1478
                }
1479
                break;
1480
            case 'today':
1481
                //$sql .= ' AND DATE_FORMAT(date_time,"%d-%m-%Y") = DATE_FORMAT("'.api_get_utc_datetime().'", "%d-%m-%Y" )';
1482
                break;
1483
            case 'all_done':
1484
                $sql .= " AND done_attendance = 1 ";
1485
                break;
1486
            case 'all_not_done':
1487
                $sql .= " AND done_attendance = 0 ";
1488
                break;
1489
            case 'all':
1490
            default:
1491
                break;
1492
        }
1493
        $sql .= " ORDER BY date_time ";
1494
1495
        $rs = Database::query($sql);
1496
        $data = [];
1497
        if (Database::num_rows($rs) > 0) {
1498
            while ($row = Database::fetch_array($rs, 'ASSOC')) {
1499
                $row['db_date_time'] = $row['date_time'];
1500
                $row['date_time'] = api_get_local_time($row['date_time']);
1501
                $row['date'] = api_format_date($row['date_time'], DATE_FORMAT_SHORT);
1502
                $row['time'] = api_format_date($row['date_time'], TIME_NO_SEC_FORMAT);
1503
                $row['groups'] = $this->getGroupListByAttendanceCalendar($row['id'], $course_id);
1504
                if ($type == 'today') {
1505
                    if (date('d-m-Y', api_strtotime($row['date_time'], 'UTC')) == date('d-m-Y', time())) {
1506
                        $data[] = $row;
1507
                    }
1508
                } else {
1509
                    $data[] = $row;
1510
                }
1511
            }
1512
        }
1513
1514
        return $data;
1515
    }
1516
1517
    /**
1518
     * Get number of attendance calendar inside current attendance.
1519
     *
1520
     * @param int $attendanceId
1521
     * @param int $groupId
1522
     * @param $done_attendance
1523
     * @param int $userId
1524
     *
1525
     * @return int number of dates in attendance calendar
1526
     */
1527
    public static function get_number_of_attendance_calendar(
1528
        $attendanceId,
1529
        $groupId = 0,
1530
        $done_attendance = null,
1531
        $userId = 0
1532
    ) {
1533
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1534
        $calendarRelGroup = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1535
        $tbl_groupRelUser = Database::get_course_table(TABLE_GROUP_USER);
1536
        $attendanceId = intval($attendanceId);
1537
        $groupId = intval($groupId);
1538
        $course_id = api_get_course_int_id();
1539
1540
        $where_attendance = '';
1541
        if ($done_attendance) {
1542
            $where_attendance = ' done_attendance = 1 AND ';
1543
        }
1544
        if (empty($userId)) {
1545
            if (empty($groupId)) {
1546
                $sql = "SELECT count(a.id)
1547
                        FROM $tbl_attendance_calendar a
1548
                        WHERE
1549
                            c_id = $course_id AND
1550
                            $where_attendance
1551
                            attendance_id = '$attendanceId' AND
1552
                            id NOT IN (
1553
                                SELECT calendar_id FROM $calendarRelGroup
1554
                                WHERE
1555
                                    c_id = $course_id AND
1556
                                    group_id != 0 AND
1557
                                    group_id IS NOT NULL
1558
                            )
1559
                        ";
1560
            } else {
1561
                $sql = "SELECT count(a.id)
1562
                        FROM $tbl_attendance_calendar a
1563
                        INNER JOIN $calendarRelGroup g
1564
                        ON (a.id = g.calendar_id AND a.c_id = g.c_id)
1565
                        WHERE
1566
                            a.c_id = $course_id AND
1567
                            $where_attendance
1568
                            attendance_id = '$attendanceId' AND
1569
                            group_id = $groupId
1570
                        ";
1571
            }
1572
        } else {
1573
            if (empty($groupId)) {
1574
                $sql = "SELECT count(a.id)
1575
                        FROM $tbl_attendance_calendar a
1576
                        WHERE
1577
                            c_id = $course_id AND
1578
                            $where_attendance
1579
                            attendance_id = '$attendanceId' AND
1580
                            id NOT IN (
1581
                                SELECT calendar_id FROM $calendarRelGroup
1582
                                WHERE
1583
                                    c_id = $course_id AND
1584
                                    group_id != 0 AND
1585
                                    group_id IS NOT NULL AND
1586
                                    group_id NOT IN (
1587
                                        SELECT group_id
1588
                                        FROM $tbl_groupRelUser
1589
                                        WHERE user_id = $userId
1590
                                    )
1591
                            )
1592
                        ";
1593
            } else {
1594
                $sql = "SELECT count(a.id)
1595
                        FROM $tbl_attendance_calendar a
1596
                        INNER JOIN $calendarRelGroup g
1597
                        ON (a.id = g.calendar_id AND a.c_id = g.c_id)
1598
                        WHERE
1599
                            a.c_id = $course_id AND
1600
                            $where_attendance
1601
                            attendance_id = '$attendanceId' AND
1602
                            group_id = $groupId
1603
                        ";
1604
            }
1605
        }
1606
1607
        $rs = Database::query($sql);
1608
        $row = Database::fetch_row($rs);
1609
        $count = $row[0];
1610
1611
        return $count;
1612
    }
1613
1614
    /**
1615
     * Get count dates inside attendance calendar by attendance id.
1616
     *
1617
     * @param int $attendanceId
1618
     *
1619
     * @return int count of dates
1620
     */
1621
    public static function get_count_dates_inside_attendance_calendar($attendanceId)
1622
    {
1623
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1624
        $attendanceId = intval($attendanceId);
1625
        $course_id = api_get_course_int_id();
1626
        $sql = "SELECT count(id) FROM $tbl_attendance_calendar
1627
                WHERE
1628
                    c_id = $course_id AND
1629
                    attendance_id = '$attendanceId'";
1630
        $rs = Database::query($sql);
1631
        $count = 0;
1632
        if (Database::num_rows($rs) > 0) {
1633
            $row = Database::fetch_row($rs);
1634
            $count = $row[0];
1635
        }
1636
1637
        return $count;
1638
    }
1639
1640
    /**
1641
     * check if all calendar of an attendance is done.
1642
     *
1643
     * @param int $attendanceId
1644
     *
1645
     * @return bool True if all calendar is done, otherwise false
1646
     */
1647
    public static function is_all_attendance_calendar_done($attendanceId)
1648
    {
1649
        $attendanceId = intval($attendanceId);
1650
        $done_calendar = self::get_done_attendance_calendar($attendanceId);
1651
        $count_dates_in_calendar = self::get_count_dates_inside_attendance_calendar($attendanceId);
1652
        $number_of_dates = self::get_number_of_attendance_calendar($attendanceId);
1653
1654
        $result = false;
1655
        if ($number_of_dates && (intval($count_dates_in_calendar) == intval($done_calendar))) {
1656
            $result = true;
1657
        }
1658
1659
        return $result;
1660
    }
1661
1662
    /**
1663
     * check if an attendance is locked.
1664
     *
1665
     * @param int $attendanceId
1666
     * @param bool
1667
     *
1668
     * @return bool
1669
     */
1670
    public static function is_locked_attendance($attendanceId)
1671
    {
1672
        //use gradebook lock
1673
        $result = api_resource_is_locked_by_gradebook($attendanceId, LINK_ATTENDANCE);
1674
1675
        return $result;
1676
    }
1677
1678
    /**
1679
     * Add new datetime inside attendance calendar table.
1680
     *
1681
     * @param int   $attendanceId
1682
     * @param array $groupList
1683
     *
1684
     * @return int affected rows
1685
     */
1686
    public function attendance_calendar_add($attendanceId, $groupList = [])
1687
    {
1688
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1689
        $affected_rows = 0;
1690
        $attendanceId = intval($attendanceId);
1691
        $course_id = api_get_course_int_id();
1692
        // check if datetime already exists inside the table
1693
        /*$sql = "SELECT id FROM $tbl_attendance_calendar
1694
                WHERE
1695
                    c_id = $course_id AND
1696
                    date_time='".Database::escape_string($this->date_time)."' AND
1697
                    attendance_id = '$attendanceId'";
1698
        $rs = Database::query($sql);
1699
        if (Database::num_rows($rs) == 0) {*/
1700
        $params = [
1701
            'c_id' => $course_id,
1702
            'date_time' => $this->date_time,
1703
            'attendance_id' => $attendanceId,
1704
            'done_attendance' => 0,
1705
        ];
1706
        $id = Database::insert($tbl_attendance_calendar, $params);
1707
1708
        if ($id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1709
            $sql = "UPDATE $tbl_attendance_calendar SET id = iid WHERE iid = $id";
1710
            Database::query($sql);
1711
            $affected_rows++;
1712
        }
1713
        $this->addAttendanceCalendarToGroup($id, $course_id, $groupList);
0 ignored issues
show
Bug introduced by
It seems like $id can also be of type false; however, parameter $calendarId of Attendance::addAttendanceCalendarToGroup() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1713
        $this->addAttendanceCalendarToGroup(/** @scrutinizer ignore-type */ $id, $course_id, $groupList);
Loading history...
1714
        //}
1715
1716
        // update locked attendance
1717
        $is_all_calendar_done = self::is_all_attendance_calendar_done($attendanceId);
1718
        if (!$is_all_calendar_done) {
1719
            self::lock_attendance($attendanceId, false);
0 ignored issues
show
Bug Best Practice introduced by
The method Attendance::lock_attendance() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1719
            self::/** @scrutinizer ignore-call */ 
1720
                  lock_attendance($attendanceId, false);
Loading history...
1720
        } else {
1721
            self::lock_attendance($attendanceId);
1722
        }
1723
1724
        return $affected_rows;
1725
    }
1726
1727
    /**
1728
     * @param int   $calendarId
1729
     * @param int   $courseId
1730
     * @param array $groupList
1731
     *
1732
     * @return bool
1733
     */
1734
    public function addAttendanceCalendarToGroup($calendarId, $courseId, $groupList)
1735
    {
1736
        if (empty($groupList)) {
1737
            return false;
1738
        }
1739
1740
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1741
1742
        foreach ($groupList as $groupId) {
1743
            if (empty($groupId)) {
1744
                continue;
1745
            }
1746
1747
            $result = $this->getAttendanceCalendarGroup(
1748
                $calendarId,
1749
                $courseId,
1750
                $groupId
1751
            );
1752
1753
            if (empty($result)) {
1754
                $params = [
1755
                    'calendar_id' => $calendarId,
1756
                    'c_id' => $courseId,
1757
                    'group_id' => $groupId,
1758
                ];
1759
                Database::insert($table, $params);
1760
            }
1761
        }
1762
1763
        return true;
1764
    }
1765
1766
    /**
1767
     * @param int $calendarId
1768
     * @param int $courseId
1769
     *
1770
     * @return array
1771
     */
1772
    public function getGroupListByAttendanceCalendar($calendarId, $courseId)
1773
    {
1774
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1775
1776
        return Database::select(
1777
            '*',
1778
            $table,
1779
            ['where' => [
1780
                    'calendar_id = ? AND c_id = ?' => [$calendarId, $courseId],
1781
                ],
1782
            ]
1783
        );
1784
    }
1785
1786
    /**
1787
     * @param int $calendarId
1788
     * @param int $courseId
1789
     * @param int $groupId
1790
     *
1791
     * @return array
1792
     */
1793
    public function getAttendanceCalendarGroup($calendarId, $courseId, $groupId)
1794
    {
1795
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1796
1797
        return Database::select(
1798
            '*',
1799
            $table,
1800
            ['where' => [
1801
                    'calendar_id = ? AND c_id = ? AND group_id = ?' => [$calendarId, $courseId, $groupId],
1802
                ],
1803
            ]
1804
        );
1805
    }
1806
1807
    /**
1808
     * @param int $calendarId
1809
     * @param int $courseId
1810
     */
1811
    public function deleteAttendanceCalendarGroup($calendarId, $courseId)
1812
    {
1813
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1814
        Database::delete(
1815
            $table,
1816
            [
1817
                'calendar_id = ? AND c_id = ?' => [$calendarId, $courseId],
1818
            ]
1819
        );
1820
    }
1821
1822
    /**
1823
     * save repeated date inside attendance calendar table.
1824
     *
1825
     * @param int    $attendanceId
1826
     * @param int    $start_date   start date in tms
1827
     * @param int    $end_date     end date in tms
1828
     * @param string $repeat_type  daily, weekly, monthlyByDate
1829
     * @param array  $groupList
1830
     */
1831
    public function attendance_repeat_calendar_add(
1832
        $attendanceId,
1833
        $start_date,
1834
        $end_date,
1835
        $repeat_type,
1836
        $groupList = []
1837
    ) {
1838
        $attendanceId = intval($attendanceId);
1839
        // save start date
1840
        $datetimezone = api_get_utc_datetime($start_date);
1841
        $this->set_date_time($datetimezone);
1842
        $this->attendance_calendar_add($attendanceId, $groupList);
1843
1844
        // 86400 = 24 hours in seconds
1845
        // 604800 = 1 week in seconds
1846
        // Saves repeated dates
1847
        switch ($repeat_type) {
1848
            case 'daily':
1849
                $j = 1;
1850
                for ($i = $start_date + 86400; ($i <= $end_date); $i += 86400) {
1851
                    $datetimezone = api_get_utc_datetime($i);
1852
                    $this->set_date_time($datetimezone);
1853
                    $this->attendance_calendar_add($attendanceId, $groupList);
1854
                    $j++;
1855
                }
1856
                break;
1857
            case 'weekly':
1858
                $j = 1;
1859
                for ($i = $start_date + 604800; ($i <= $end_date); $i += 604800) {
1860
                    $datetimezone = api_get_utc_datetime($i);
1861
                    $this->set_date_time($datetimezone);
1862
                    $this->attendance_calendar_add($attendanceId, $groupList);
1863
                    $j++;
1864
                }
1865
                break;
1866
            case 'monthlyByDate':
1867
                $j = 1;
1868
                //@todo fix bug with february
1869
                for ($i = $start_date + 2419200; ($i <= $end_date); $i += 2419200) {
1870
                    $datetimezone = api_get_utc_datetime($i);
1871
                    $this->set_date_time($datetimezone);
1872
                    $this->attendance_calendar_add($attendanceId, $groupList);
1873
                    $j++;
1874
                }
1875
                break;
1876
        }
1877
    }
1878
1879
    /**
1880
     * edit a datetime inside attendance calendar table.
1881
     *
1882
     * @param	int	attendance calendar id
1883
     * @param	int	attendance id
1884
     *
1885
     * @return int affected rows
1886
     */
1887
    public function attendance_calendar_edit($calendar_id, $attendanceId)
1888
    {
1889
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1890
        $affected_rows = 0;
1891
        $attendanceId = intval($attendanceId);
1892
        $course_id = api_get_course_int_id();
1893
        // check if datetime already exists inside the table
1894
        $sql = "SELECT id FROM $tbl_attendance_calendar
1895
                WHERE
1896
                    c_id = $course_id AND
1897
                    date_time = '".Database::escape_string($this->date_time)."' AND
1898
                    attendance_id = '$attendanceId'";
1899
        $rs = Database::query($sql);
1900
1901
        if (Database::num_rows($rs) == 0) {
1902
            $sql = "UPDATE $tbl_attendance_calendar
1903
                    SET date_time='".Database::escape_string($this->date_time)."'
1904
                    WHERE c_id = $course_id AND id = '".intval($calendar_id)."'";
1905
            Database::query($sql);
1906
        }
1907
1908
        // update locked attendance
1909
        $is_all_calendar_done = self::is_all_attendance_calendar_done($attendanceId);
1910
        if (!$is_all_calendar_done) {
1911
            self::lock_attendance($attendanceId, false);
0 ignored issues
show
Bug Best Practice introduced by
The method Attendance::lock_attendance() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1911
            self::/** @scrutinizer ignore-call */ 
1912
                  lock_attendance($attendanceId, false);
Loading history...
1912
        } else {
1913
            self::lock_attendance($attendanceId);
1914
        }
1915
1916
        return $affected_rows;
1917
    }
1918
1919
    /**
1920
     * delete a datetime from attendance calendar table.
1921
     *
1922
     * @param	int		attendance calendar id
1923
     * @param	int		attendance id
1924
     * @param	bool true for removing all calendar inside current attendance, false for removing by calendar id
1925
     *
1926
     * @return int affected rows
1927
     */
1928
    public function attendance_calendar_delete(
1929
        $calendar_id,
1930
        $attendanceId,
1931
        $all_delete = false
1932
    ) {
1933
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1934
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
1935
1936
        $attendanceId = intval($attendanceId);
1937
        // get all registered users inside current course
1938
        $users = $this->get_users_rel_course();
1939
        $user_ids = array_keys($users);
1940
        $course_id = api_get_course_int_id();
1941
        $affected_rows = 0;
1942
        if ($all_delete) {
1943
            $attendance_calendar = $this->get_attendance_calendar($attendanceId);
1944
            // get all dates from calendar by current attendance
1945
            if (!empty($attendance_calendar)) {
1946
                foreach ($attendance_calendar as $cal) {
1947
                    // delete all data from attendance sheet
1948
                    $sql = "DELETE FROM $tbl_attendance_sheet
1949
                            WHERE c_id = $course_id AND attendance_calendar_id = '".intval($cal['id'])."'";
1950
                    Database::query($sql);
1951
                    // delete data from attendance calendar
1952
                    $sql = "DELETE FROM $tbl_attendance_calendar
1953
                            WHERE c_id = $course_id AND id = '".intval($cal['id'])."'";
1954
                    Database::query($sql);
1955
1956
                    $this->deleteAttendanceCalendarGroup($cal['id'], $course_id);
1957
                    $affected_rows++;
1958
                }
1959
            }
1960
        } else {
1961
            // delete just one row from attendance sheet by the calendar id
1962
            $sql = "DELETE FROM $tbl_attendance_sheet
1963
                    WHERE c_id = $course_id AND attendance_calendar_id = '".intval($calendar_id)."'";
1964
            Database::query($sql);
1965
            // delete data from attendance calendar
1966
            $sql = "DELETE FROM $tbl_attendance_calendar
1967
                    WHERE c_id = $course_id AND id = '".intval($calendar_id)."'";
1968
            Database::query($sql);
1969
1970
            $this->deleteAttendanceCalendarGroup($calendar_id, $course_id);
1971
            $affected_rows++;
1972
        }
1973
1974
        // update users' results
1975
        $this->updateUsersResults($user_ids, $attendanceId);
1976
1977
        return $affected_rows;
1978
    }
1979
1980
    /** Setters for fields of attendances tables */
1981
    public function set_session_id($session_id)
1982
    {
1983
        $this->session_id = $session_id;
1984
    }
1985
1986
    public function set_course_id($course_id)
1987
    {
1988
        $this->course_id = $course_id;
1989
    }
1990
1991
    public function set_date_time($datetime)
1992
    {
1993
        $this->date_time = $datetime;
1994
    }
1995
1996
    public function set_name($name)
1997
    {
1998
        $this->name = $name;
1999
    }
2000
2001
    public function set_description($description)
2002
    {
2003
        $this->description = $description;
2004
    }
2005
2006
    public function set_attendance_qualify_title($attendance_qualify_title)
2007
    {
2008
        $this->attendance_qualify_title = $attendance_qualify_title;
2009
    }
2010
2011
    public function set_attendance_weight($attendance_weight)
2012
    {
2013
        $this->attendance_weight = $attendance_weight;
2014
    }
2015
2016
    /** Getters for fields of attendances tables */
2017
    public function get_session_id()
2018
    {
2019
        return $this->session_id;
2020
    }
2021
2022
    public function get_course_id()
2023
    {
2024
        return $this->course_id;
2025
    }
2026
2027
    public function get_date_time()
2028
    {
2029
        return $this->date_time;
2030
    }
2031
2032
    public function get_name()
2033
    {
2034
        return $this->name;
2035
    }
2036
2037
    public function get_description()
2038
    {
2039
        return $this->description;
2040
    }
2041
2042
    public function get_attendance_qualify_title()
2043
    {
2044
        return $this->attendance_qualify_title;
2045
    }
2046
2047
    public function get_attendance_weight()
2048
    {
2049
        return $this->attendance_weight;
2050
    }
2051
2052
    /**
2053
     * @param string $startDate in UTC time
2054
     * @param string $endDate   in UTC time
2055
     *
2056
     * @return array
2057
     */
2058
    public function getAttendanceLogin($startDate, $endDate)
2059
    {
2060
        if (empty($startDate) ||
2061
            $startDate == '0000-00-00' ||
2062
            $startDate == '0000-00-00 00:00:00' ||
2063
            empty($endDate) ||
2064
            $endDate == '0000-00-00' ||
2065
            $endDate == '0000-00-00 00:00:00'
2066
        ) {
2067
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type array.
Loading history...
2068
        }
2069
2070
        $sessionId = api_get_session_id();
2071
        $courseCode = api_get_course_id();
2072
        $courseId = api_get_course_int_id();
2073
2074
        if (!empty($sessionId)) {
2075
            $users = CourseManager::get_user_list_from_course_code(
2076
                $courseCode,
2077
                $sessionId,
2078
                '',
2079
                'lastname',
2080
                0
2081
            );
2082
        } else {
2083
            $users = CourseManager::get_user_list_from_course_code(
2084
                $courseCode,
2085
                0,
2086
                '',
2087
                'lastname',
2088
                STUDENT
2089
            );
2090
        }
2091
2092
        $dateTimeStartOriginal = new DateTime($startDate);
2093
        $dateTimeStart = new DateTime($startDate);
2094
        $dateTimeEnd = new DateTime($endDate);
2095
        $interval = $dateTimeStart->diff($dateTimeEnd);
2096
        $days = intval($interval->format('%a'));
2097
2098
        $dateList = [$dateTimeStart->format('Y-m-d')];
2099
        $headers = [
2100
            get_lang('User'),
2101
            $dateTimeStart->format('Y-m-d'),
2102
        ];
2103
2104
        for ($i = 0; $i < $days; $i++) {
2105
            $dateTimeStart = $dateTimeStart->add(new DateInterval('P1D'));
2106
            $date = $dateTimeStart->format('Y-m-d');
2107
            $dateList[] = $date;
2108
            $headers[] = $date;
2109
        }
2110
2111
        $accessData = CourseManager::getCourseAccessPerCourseAndSession(
2112
            $courseId,
2113
            $sessionId,
2114
            $dateTimeStartOriginal->format('Y-m-d H:i:s'),
2115
            $dateTimeEnd->format('Y-m-d H:i:s')
2116
        );
2117
2118
        $results = [];
2119
        if (!empty($accessData)) {
2120
            foreach ($accessData as $data) {
2121
                $onlyDate = substr($data['login_course_date'], 0, 10);
2122
                $results[$data['user_id']][$onlyDate] = true;
2123
            }
2124
        }
2125
2126
        return [
2127
            'users' => $users,
2128
            'dateList' => $dateList,
2129
            'headers' => $headers,
2130
            'results' => $results,
2131
        ];
2132
    }
2133
2134
    /**
2135
     * @param string $startDate in UTC time
2136
     * @param string $endDate   in UTC time
2137
     *
2138
     * @return string
2139
     */
2140
    public function getAttendanceLoginTable($startDate, $endDate)
2141
    {
2142
        $data = $this->getAttendanceLogin($startDate, $endDate);
2143
        if (!$data) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $data of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
2144
            return null;
2145
        }
2146
2147
        $headers = $data['headers'];
2148
        $dateList = $data['dateList'];
2149
        $users = $data['users'];
2150
        $results = $data['results'];
2151
2152
        $table = new HTML_Table(['class' => 'data_table']);
2153
        $row = 0;
2154
        $column = 0;
2155
        foreach ($headers as $header) {
2156
            $table->setHeaderContents($row, $column, $header);
2157
            $column++;
2158
        }
2159
        $row = 1;
2160
        foreach ($users as $user) {
2161
            $table->setCellContents(
2162
                $row,
2163
                0,
2164
                $user['lastname'].' '.$user['firstname'].' ('.$user['username'].')'
2165
            );
2166
            $row++;
2167
        }
2168
2169
        $column = 1;
2170
        $row = 1;
2171
        foreach ($users as $user) {
2172
            foreach ($dateList as $date) {
2173
                $status = null;
2174
                if (isset($results[$user['user_id']]) &&
2175
                    isset($results[$user['user_id']][$date])
2176
                ) {
2177
                    $status = 'X';
2178
                }
2179
                $table->setCellContents($row, $column, $status);
2180
                $column++;
2181
            }
2182
            $row++;
2183
            $column = 1;
2184
        }
2185
2186
        return $table->toHtml();
2187
    }
2188
2189
    /**
2190
     * @param string $startDate in UTC time
2191
     * @param string $endDate   in UTC time
2192
     *
2193
     * @return string
2194
     */
2195
    public function exportAttendanceLogin($startDate, $endDate)
2196
    {
2197
        $data = $this->getAttendanceLogin($startDate, $endDate);
2198
2199
        if (!$data) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $data of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
2200
            return null;
2201
        }
2202
        $users = $data['users'];
2203
        $results = $data['results'];
2204
2205
        $table = new HTML_Table(['class' => 'data_table']);
2206
        $table->setHeaderContents(0, 0, get_lang('User'));
2207
        $table->setHeaderContents(0, 1, get_lang('Date'));
2208
2209
        $row = 1;
2210
        foreach ($users as $user) {
2211
            $table->setCellContents(
2212
                $row,
2213
                0,
2214
                $user['lastname'].' '.$user['firstname'].' ('.$user['username'].')'
2215
            );
2216
            $row++;
2217
        }
2218
        $table->setColAttributes(0, ['style' => 'width:28%']);
2219
2220
        $row = 1;
2221
        foreach ($users as $user) {
2222
            if (isset($results[$user['user_id']]) &&
2223
                !empty($results[$user['user_id']])
2224
            ) {
2225
                $dates = implode(', ', array_keys($results[$user['user_id']]));
2226
                $table->setCellContents($row, 1, $dates);
2227
            }
2228
            $row++;
2229
        }
2230
2231
        $tableToString = $table->toHtml();
2232
        $params = [
2233
            'filename' => get_lang('Attendance').'_'.api_get_utc_datetime(),
2234
            'pdf_title' => get_lang('Attendance'),
2235
            'course_code' => api_get_course_id(),
2236
            'show_real_course_teachers' => true,
2237
        ];
2238
        $pdf = new PDF('A4', null, $params);
2239
        $pdf->html_to_pdf_with_template($tableToString);
2240
    }
2241
}
2242