Completed
Push — master ( 27e209...a08afa )
by Julito
186:04 queued 150:53
created

Attendance::set_name()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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

342
                /** @scrutinizer ignore-type */ $last_id,
Loading history...
343
                $session_id
344
            );
345
            $link_id = $link_info['id'];
346
            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...
347
                GradebookUtils::add_resource_to_course_gradebook(
348
                    $this->category_id,
349
                    $course_code,
350
                    7,
351
                    $last_id,
352
                    $title_gradebook,
353
                    $weight_calification,
354
                    $value_calification,
355
                    $description,
356
                    1,
357
                    $session_id
358
                );
359
            } else {
360
                Database::query('UPDATE '.$table_link.' SET weight='.$weight_calification.' WHERE id='.$link_id.'');
361
            }
362
        }
363
364
        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...
365
    }
366
367
    /**
368
     * edit attendances inside table
369
     * @param int attendance id
370
     * @param bool true for adding link in gradebook or false otherwise (optional)
371
     * @return int last id
372
     */
373
    public function attendance_edit($attendanceId, $link_to_gradebook = false)
374
    {
375
        $_course = api_get_course_info();
376
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
377
        $table_link = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
378
379
        $session_id = api_get_session_id();
380
        $user_id = api_get_user_id();
381
        $attendanceId = intval($attendanceId);
382
        $course_code = $_course['code'];
383
        $course_id = $_course['real_id'];
384
        $title_gradebook = $this->attendance_qualify_title;
385
        $value_calification = 0;
386
        $weight_calification = api_float_val($this->attendance_weight);
387
388
        if (!empty($attendanceId)) {
389
            $params = [
390
                'name' => $this->name,
391
                'description' => $this->description,
392
                'attendance_qualify_title' => $title_gradebook,
393
                'attendance_weight' => $weight_calification
394
            ];
395
            Database::update(
396
                $tbl_attendance,
397
                $params,
398
                ['c_id = ? AND id = ?' => [$course_id, $attendanceId]]
399
            );
400
401
            api_item_property_update(
402
                $_course,
403
                TOOL_ATTENDANCE,
404
                $attendanceId,
405
                "AttendanceUpdated",
406
                $user_id
407
            );
408
409
            // add link to gradebook
410
            if ($link_to_gradebook && !empty($this->category_id)) {
411
                $description = '';
412
                $link_info = GradebookUtils::isResourceInCourseGradebook(
413
                    $course_code,
414
                    7,
415
                    $attendanceId,
416
                    $session_id
417
                );
418
                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...
419
                    GradebookUtils::add_resource_to_course_gradebook(
420
                        $this->category_id,
421
                        $course_code,
422
                        7,
423
                        $attendanceId,
424
                        $title_gradebook,
425
                        $weight_calification,
426
                        $value_calification,
427
                        $description,
428
                        1,
429
                        $session_id
430
                    );
431
                } else {
432
                    Database::query('UPDATE '.$table_link.' SET weight='.$weight_calification.' WHERE id='.$link_info['id'].'');
433
                }
434
            }
435
436
            return $attendanceId;
437
        }
438
439
        return null;
440
    }
441
442
    /**
443
     * Restore attendance
444
     * @param int|array one or many attendances id
445
     * @return int affected rows
446
     */
447
    public function attendance_restore($attendanceId)
448
    {
449
        $_course = api_get_course_info();
450
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
451
        $user_id = api_get_user_id();
452
        $course_id = $_course['real_id'];
453
        if (is_array($attendanceId)) {
454
            foreach ($attendanceId as $id) {
455
                $id = intval($id);
456
                $sql = "UPDATE $tbl_attendance SET active = 1
457
                        WHERE c_id = $course_id AND id = '$id'";
458
                $result = Database::query($sql);
459
                $affected_rows = Database::affected_rows($result);
460
                if (!empty($affected_rows)) {
461
                    // update row item property table
462
                    api_item_property_update(
463
                        $_course,
464
                        TOOL_ATTENDANCE,
465
                        $id,
466
                        'restore',
467
                        $user_id
468
                    );
469
                }
470
            }
471
        } else {
472
            $attendanceId = intval($attendanceId);
473
            $sql = "UPDATE $tbl_attendance SET active = 1
474
                    WHERE c_id = $course_id AND id = '$attendanceId'";
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
                    $attendanceId,
483
                    'restore',
484
                    $user_id
485
                );
486
            }
487
        }
488
489
        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...
490
    }
491
492
    /**
493
     * Delete attendances
494
     * @param int|array $attendanceId one or many attendances id
495
     * @return int affected rows
496
     */
497
    public function attendance_delete($attendanceId)
498
    {
499
        $_course = api_get_course_info();
500
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
501
        $user_id = api_get_user_id();
502
        $course_id = $_course['real_id'];
503
504
        if (is_array($attendanceId)) {
505
            foreach ($attendanceId as $id) {
506
                $id = intval($id);
507
                $sql = "UPDATE $tbl_attendance SET active = 2
508
                        WHERE c_id = $course_id AND id = '$id'";
509
                $result = Database::query($sql);
510
                $affected_rows = Database::affected_rows($result);
511
                if (!empty($affected_rows)) {
512
                    // update row item property table
513
                    api_item_property_update(
514
                        $_course,
515
                        TOOL_ATTENDANCE,
516
                        $id,
517
                        "delete",
518
                        $user_id
519
                    );
520
                }
521
            }
522
        } else {
523
            $attendanceId = intval($attendanceId);
524
            $sql = "UPDATE $tbl_attendance SET active = 2
525
                    WHERE c_id = $course_id AND id = '$attendanceId'";
526
527
            $result = Database::query($sql);
528
            $affected_rows = Database::affected_rows($result);
529
            if (!empty($affected_rows)) {
530
                // update row item property table
531
                api_item_property_update(
532
                    $_course,
533
                    TOOL_ATTENDANCE,
534
                    $attendanceId,
535
                    "delete",
536
                    $user_id
537
                );
538
            }
539
        }
540
541
        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...
542
    }
543
544
    /**
545
     * Changes visibility
546
     * @param int|array $attendanceId one or many attendances id
547
     * @param int $status
548
     *
549
     * @return int affected rows
550
     */
551
    public function changeVisibility($attendanceId, $status = 1)
552
    {
553
        $_course = api_get_course_info();
554
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
555
        $user_id = api_get_user_id();
556
        $course_id = $_course['real_id'];
557
        $status = intval($status);
558
559
        $action = 'visible';
560
        if ($status == 0) {
561
            $action = 'invisible';
562
        }
563
564
        if (is_array($attendanceId)) {
565
            foreach ($attendanceId as $id) {
566
                $id = intval($id);
567
                $sql = "UPDATE $tbl_attendance SET active = $status
568
                        WHERE c_id = $course_id AND id = '$id'";
569
                $result = Database::query($sql);
570
                $affected_rows = Database::affected_rows($result);
571
                if (!empty($affected_rows)) {
572
                    // update row item property table
573
                    api_item_property_update(
574
                        $_course,
575
                        TOOL_ATTENDANCE,
576
                        $id,
577
                        $action,
578
                        $user_id
579
                    );
580
                }
581
            }
582
        } else {
583
            $attendanceId = intval($attendanceId);
584
            $sql = "UPDATE $tbl_attendance SET active = $status
585
                    WHERE c_id = $course_id AND id = '$attendanceId'";
586
            $result = Database::query($sql);
587
            $affected_rows = Database::affected_rows($result);
588
            if (!empty($affected_rows)) {
589
                // update row item property table
590
                api_item_property_update(
591
                    $_course,
592
                    TOOL_ATTENDANCE,
593
                    $attendanceId,
594
                    $action,
595
                    $user_id
596
                );
597
            }
598
        }
599
600
        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...
601
    }
602
603
    /**
604
     * Lock or unlock an attendance
605
     * @param   int     attendance id
606
     * @param   bool    True to lock or false otherwise
607
     *
608
     * @return int
609
     */
610
    public function lock_attendance($attendanceId, $lock = true)
611
    {
612
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
613
        $course_id = api_get_course_int_id();
614
        $attendanceId = intval($attendanceId);
615
        $locked = ($lock) ? 1 : 0;
616
        $upd = "UPDATE $tbl_attendance SET locked = $locked
617
                WHERE c_id = $course_id AND id = $attendanceId";
618
        $result = Database::query($upd);
619
        $affected_rows = Database::affected_rows($result);
620
        if ($affected_rows && $lock) {
621
            // Save attendance sheet log
622
            $this->saveAttendanceSheetLog(
623
                $attendanceId,
624
                api_get_utc_datetime(),
625
                self::LOCKED_ATTENDANCE_LOG_TYPE,
626
                api_get_user_id()
627
            );
628
        }
629
        return $affected_rows;
630
    }
631
632
    /**
633
     * Get registered users inside current course
634
     * @param int $attendanceId attendance id for showing attendance result field (optional)
635
     * @param int $groupId
636
     * @return array  users data
637
     */
638
    public function get_users_rel_course($attendanceId = 0, $groupId = 0)
639
    {
640
        $current_session_id = api_get_session_id();
641
        $current_course_id  = api_get_course_id();
642
        $currentCourseIntId = api_get_course_int_id();
643
        $studentInGroup = [];
644
645
        if (!empty($current_session_id)) {
646
            $a_course_users = CourseManager:: get_user_list_from_course_code(
647
                $current_course_id,
648
                $current_session_id,
649
                '',
650
                'lastname'
651
            );
652
        } else {
653
            $a_course_users = CourseManager:: get_user_list_from_course_code(
654
                $current_course_id,
655
                0,
656
                '',
657
                'lastname'
658
            );
659
        }
660
661
        if (!empty($groupId)) {
662
            $groupInfo = GroupManager::get_group_properties($groupId);
663
            $students = GroupManager::getStudents($groupInfo['iid']);
664
            if (!empty($students)) {
665
                foreach ($students as $student) {
666
                    $studentInGroup[$student['user_id']] = true;
667
                }
668
            }
669
        }
670
671
        // get registered users inside current course
672
        $a_users = [];
673
        foreach ($a_course_users as $key => $user_data) {
674
            $value = [];
675
            $uid = $user_data['user_id'];
676
            $userInfo = api_get_user_info($uid);
677
            $status = $user_data['status'];
678
679
            if (!empty($groupId)) {
680
                if (!isset($studentInGroup[$uid])) {
681
                    continue;
682
                }
683
            }
684
685
            $user_status_in_session = null;
686
            $user_status_in_course  = null;
687
688
            if (api_get_session_id()) {
689
                $user_status_in_session = SessionManager::get_user_status_in_course_session(
690
                    $uid,
691
                    $currentCourseIntId,
692
                    $current_session_id
693
                );
694
            } else {
695
                $user_status_in_course = CourseManager::getUserInCourseStatus(
696
                    $uid,
697
                    $currentCourseIntId
698
                );
699
            }
700
701
            // Not taking into account DRH or COURSEMANAGER
702
            if ($uid <= 1 ||
703
                $status == DRH ||
704
                $user_status_in_course == COURSEMANAGER ||
705
                $user_status_in_session == 2
706
            ) {
707
                continue;
708
            }
709
710
            if (!empty($attendanceId)) {
711
                $user_faults = $this->get_faults_of_user(
712
                    $uid,
713
                    $attendanceId,
714
                    $groupId
715
                );
716
                $value['attendance_result'] = $user_faults['faults'].'/'.$user_faults['total'].' ('.$user_faults['faults_porcent'].'%)';
717
                $value['result_color_bar'] = $user_faults['color_bar'];
718
            }
719
720
            $photo = Display::img(
721
                $userInfo['avatar_small'],
722
                $userInfo['complete_name'],
723
                [],
724
                false
725
            );
726
727
            $value['photo'] = $photo;
728
            $value['firstname'] = $user_data['firstname'];
729
            $value['lastname'] = $user_data['lastname'];
730
            $value['username'] = $user_data['username'];
731
            $value['user_id'] = $uid;
732
733
            // Sending only 5 items in the array instead of 60
734
            $a_users[$key] = $value;
735
        }
736
737
        return $a_users;
738
    }
739
740
    /**
741
     * add attendances sheet inside table
742
     * @param int $calendar_id attendance calendar id
743
     * @param array $users_present present users during current class
744
     * @param int $attendanceId
745
     * @return int    affected rows
746
     */
747
    public function attendance_sheet_add($calendar_id, $users_present, $attendanceId)
748
    {
749
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
750
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
751
752
        $calendar_id = intval($calendar_id);
753
        $attendanceId = intval($attendanceId);
754
        $users = $this->get_users_rel_course();
755
        $course_id = api_get_course_int_id();
756
757
        $user_ids = array_keys($users);
758
        $users_absent = array_diff($user_ids, $users_present);
759
        $affected_rows = 0;
760
761
        // get last edit type
762
        $calendar_data = $this->get_attendance_calendar_by_id($calendar_id);
763
        $lastedit_type = self::DONE_ATTENDANCE_LOG_TYPE;
764
        if ($calendar_data['done_attendance']) {
765
            $lastedit_type = self::UPDATED_ATTENDANCE_LOG_TYPE;
766
        }
767
768
        // save users present in class
769
        foreach ($users_present as $user_present) {
770
            $uid = intval($user_present);
771
            // check if user already was registered with the $calendar_id
772
            $sql = "SELECT user_id FROM $tbl_attendance_sheet
773
                    WHERE c_id = $course_id AND user_id='$uid' AND attendance_calendar_id = '$calendar_id'";
774
            $rs  = Database::query($sql);
775
            if (Database::num_rows($rs) == 0) {
776
                $sql = "INSERT INTO $tbl_attendance_sheet SET
777
                        c_id = $course_id,
778
                        user_id = '$uid',
779
                        attendance_calendar_id = '$calendar_id',
780
                        presence = 1";
781
                $result = Database::query($sql);
782
783
                $affected_rows += Database::affected_rows($result);
784
            } else {
785
                $sql = "UPDATE $tbl_attendance_sheet SET presence = 1
786
                        WHERE
787
                            c_id = $course_id AND
788
                            user_id ='$uid' AND
789
                            attendance_calendar_id = '$calendar_id'
790
                        ";
791
                $result = Database::query($sql);
792
                $affected_rows += Database::affected_rows($result);
793
            }
794
        }
795
796
        // save users absent in class
797
        foreach ($users_absent as $user_absent) {
798
            $uid = intval($user_absent);
799
            // check if user already was registered with the $calendar_id
800
            $sql = "SELECT user_id FROM $tbl_attendance_sheet
801
                    WHERE c_id = $course_id AND user_id='$uid' AND attendance_calendar_id = '$calendar_id'";
802
            $rs  = Database::query($sql);
803
            if (Database::num_rows($rs) == 0) {
804
                $sql = "INSERT INTO $tbl_attendance_sheet SET
805
                        c_id = $course_id,
806
                        user_id ='$uid',
807
                        attendance_calendar_id = '$calendar_id',
808
                        presence = 0";
809
                $result = Database::query($sql);
810
811
                Database::insert_id();
812
813
                $affected_rows += Database::affected_rows($result);
814
            } else {
815
                $sql = "UPDATE $tbl_attendance_sheet SET presence = 0
816
                        WHERE
817
                            c_id = $course_id AND
818
                            user_id ='$uid' AND
819
                            attendance_calendar_id = '$calendar_id'";
820
                $result = Database::query($sql);
821
                $affected_rows += Database::affected_rows($result);
822
            }
823
        }
824
825
        // update done_attendance inside attendance calendar table
826
        $sql = "UPDATE $tbl_attendance_calendar SET done_attendance = 1
827
                WHERE  c_id = $course_id AND id = '$calendar_id'";
828
        Database::query($sql);
829
830
        // save users' results
831
        $this->updateUsersResults($user_ids, $attendanceId);
832
833
        if ($affected_rows) {
834
            //save attendance sheet log
835
            $this->saveAttendanceSheetLog(
836
                $attendanceId,
837
                api_get_utc_datetime(),
838
                $lastedit_type,
839
                api_get_user_id(),
840
                $calendar_data['date_time']
841
            );
842
        }
843
844
        return $affected_rows;
845
    }
846
847
    /**
848
     * update users' attendance results
849
     * @param array $user_ids registered users inside current course
850
     * @param int $attendanceId
851
     */
852
    public function updateUsersResults($user_ids, $attendanceId)
853
    {
854
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
855
        $tbl_attendance_result = Database::get_course_table(TABLE_ATTENDANCE_RESULT);
856
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
857
        $course_id = api_get_course_int_id();
858
        $attendanceId = intval($attendanceId);
859
        // fill results about presence of students
860
        $attendance_calendar = $this->get_attendance_calendar(
861
            $attendanceId,
862
            'all',
863
            null,
864
            null,
865
            true
866
        );
867
        $calendar_ids = [];
868
        // get all dates from calendar by current attendance
869
        foreach ($attendance_calendar as $cal) {
870
            $calendar_ids[] = $cal['id'];
871
        }
872
873
        // get count of presences by users inside current attendance and save like results
874
        if (count($user_ids) > 0) {
875
            foreach ($user_ids as $uid) {
876
                $count_presences = 0;
877
                if (count($calendar_ids) > 0) {
878
                    $sql = "SELECT count(presence) as count_presences
879
                            FROM $tbl_attendance_sheet
880
                            WHERE
881
                                c_id = $course_id AND
882
                                user_id = '$uid' AND
883
                                attendance_calendar_id IN (".implode(',', $calendar_ids).") AND
884
                                presence = 1";
885
                    $rs_count  = Database::query($sql);
886
                    $row_count = Database::fetch_array($rs_count);
887
                    $count_presences = $row_count['count_presences'];
888
                }
889
890
                // save results
891
                $sql = "SELECT id FROM $tbl_attendance_result
892
                        WHERE
893
                            c_id = $course_id AND
894
                            user_id = '$uid' AND
895
                            attendance_id = '$attendanceId' ";
896
                $rs_check_result = Database::query($sql);
897
898
                if (Database::num_rows($rs_check_result) > 0) {
899
                    // update result
900
                    $sql = "UPDATE $tbl_attendance_result SET
901
                            score = '$count_presences'
902
                            WHERE
903
                                c_id = $course_id AND
904
                                user_id='$uid' AND
905
                                attendance_id='$attendanceId'";
906
                    Database::query($sql);
907
                } else {
908
                    // insert new result
909
                    $sql = "INSERT INTO $tbl_attendance_result SET
910
                            c_id = $course_id ,
911
                            user_id			= '$uid',
912
                            attendance_id 	= '$attendanceId',
913
                            score			= '$count_presences'";
914
                    Database::query($sql);
915
916
                    $insertId = Database::insert_id();
917
                    if ($insertId) {
918
                        $sql = "UPDATE $tbl_attendance_result SET id = iid WHERE iid = $insertId";
919
                        Database::query($sql);
920
                    }
921
                }
922
            }
923
        }
924
925
        // update attendance qualify max
926
        $count_done_calendar = self::get_done_attendance_calendar($attendanceId);
927
        $sql = "UPDATE $tbl_attendance SET
928
                    attendance_qualify_max = '$count_done_calendar'
929
                WHERE c_id = $course_id AND id = '$attendanceId'";
930
        Database::query($sql);
931
    }
932
933
    /**
934
     * update attendance_sheet_log table, is used as history of an attendance sheet
935
     * @param   int     Attendance id
936
     * @param   string  Last edit datetime
937
     * @param   string  Event type ('locked_attendance', 'done_attendance_sheet' ...)
938
     * @param   int     Last edit user id
939
     * @param   string  Calendar datetime value (optional, when event type is 'done_attendance_sheet')
940
     * @return  int     Affected rows
941
     */
942
    public function saveAttendanceSheetLog(
943
        $attendanceId,
944
        $lastedit_date,
945
        $lastedit_type,
946
        $lastedit_user_id,
947
        $calendar_date_value = null
948
    ) {
949
        $course_id = api_get_course_int_id();
950
951
        // define table
952
        $tbl_attendance_sheet_log = Database::get_course_table(TABLE_ATTENDANCE_SHEET_LOG);
953
954
        // protect data
955
        $attendanceId = intval($attendanceId);
956
        $lastedit_user_id = intval($lastedit_user_id);
957
958
        if (isset($calendar_date_value)) {
959
            $calendar_date_value = $calendar_date_value;
960
        } else {
961
            $calendar_date_value = '';
962
        }
963
964
        // save data
965
        $params = [
966
            'c_id' => $course_id,
967
            'attendance_id' => $attendanceId,
968
            'lastedit_date' => $lastedit_date,
969
            'lastedit_type' => $lastedit_type,
970
            'lastedit_user_id' => $lastedit_user_id,
971
            'calendar_date_value' => $calendar_date_value,
972
        ];
973
        $insertId = Database::insert($tbl_attendance_sheet_log, $params);
974
        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...
975
            $sql = "UPDATE $tbl_attendance_sheet_log SET id = iid WHERE iid = $insertId";
976
            Database::query($sql);
977
        }
978
979
        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...
980
    }
981
982
    /**
983
     * Get number of done attendances inside current sheet
984
     * @param int attendance id
985
     * @return int number of done attendances
986
     */
987
    public static function get_done_attendance_calendar($attendanceId)
988
    {
989
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
990
        $attendanceId = intval($attendanceId);
991
        $course_id = api_get_course_int_id();
992
        $sql = "SELECT count(done_attendance) as count
993
                FROM $table
994
                WHERE
995
                    c_id = $course_id AND
996
                    attendance_id = '$attendanceId' AND
997
                    done_attendance = 1
998
                ";
999
        $rs  = Database::query($sql);
1000
        $row = Database::fetch_array($rs);
1001
        $count = $row['count'];
1002
1003
        return $count;
1004
    }
1005
1006
    /**
1007
     * Get results of faults (absents) by user
1008
     * @param int $user_id
1009
     * @param int $attendanceId
1010
     * @param int $groupId
1011
     *
1012
     * @return array results containing number of faults, total done attendance,
1013
     * percent of faults and color depend on result (red, orange)
1014
     */
1015
    public function get_faults_of_user($user_id, $attendanceId, $groupId = null)
1016
    {
1017
        $user_id = intval($user_id);
1018
        $attendanceId = intval($attendanceId);
1019
        $results = [];
1020
        $calendar_count = self::get_number_of_attendance_calendar(
1021
            $attendanceId,
1022
            $groupId,
1023
            null,
1024
            $user_id
1025
        );
1026
        // $total_done_attendance 	= $attendance_data['attendance_qualify_max'];
1027
        $total_done_attendance = self::get_number_of_attendance_calendar(
1028
            $attendanceId,
1029
            $groupId,
1030
            true,
1031
            $user_id
1032
        );
1033
        $attendance_user_score = $this->get_user_score(
1034
            $user_id,
1035
            $attendanceId,
1036
            $groupId
1037
        );
1038
1039
        //This is the main change of the BT#1381
1040
        //$total_done_attendance = $calendar_count;
1041
1042
        // calculate results
1043
        $faults = $total_done_attendance - $attendance_user_score;
1044
1045
        if (empty($calendar_count)) {
1046
            $faults = 0;
1047
        }
1048
1049
        $faults = $faults > 0 ? $faults : 0;
1050
        $faults_porcent = $calendar_count > 0 ? round(($faults * 100) / $calendar_count, 0) : 0;
1051
        $results['faults'] = $faults;
1052
        $results['total'] = $calendar_count;
1053
        $results['faults_porcent'] = $faults_porcent;
1054
        $color_bar = '';
1055
1056
        if ($faults_porcent > 25) {
1057
            $color_bar = '#f28989';
1058
        } elseif ($faults_porcent > 10) {
1059
            $color_bar = '#F90';
1060
        }
1061
        $results['color_bar'] = $color_bar;
1062
1063
        return $results;
1064
    }
1065
1066
    /**
1067
     * Get results of faults average for all courses by user
1068
     * @param int $user_id
1069
     * @return array  results containing number of faults, total done attendance,
1070
     * percentage of faults and color depend on result (red, orange)
1071
     */
1072
    public function get_faults_average_inside_courses($user_id)
1073
    {
1074
        // get all courses of current user
1075
        $courses = CourseManager::get_courses_list_by_user_id($user_id, true);
1076
        $user_id = intval($user_id);
1077
        $results = [];
1078
        $total_faults = $total_weight = $porcent = 0;
1079
        foreach ($courses as $course) {
1080
            //$course_code = $course['code'];
1081
            //$course_info = api_get_course_info($course_code);
1082
            $course_id = $course['real_id'];
1083
            $tbl_attendance_result = Database::get_course_table(TABLE_ATTENDANCE_RESULT);
1084
            $attendances_by_course = $this->get_attendances_list($course_id);
1085
1086
            foreach ($attendances_by_course as $attendance) {
1087
                // get total faults and total weight
1088
                $total_done_attendance = $attendance['attendance_qualify_max'];
1089
                $sql = "SELECT score
1090
                        FROM $tbl_attendance_result
1091
                        WHERE
1092
                            c_id = $course_id AND
1093
                            user_id = $user_id AND
1094
                            attendance_id = ".$attendance['id'];
1095
                $rs = Database::query($sql);
1096
                $score = 0;
1097
                if (Database::num_rows($rs) > 0) {
1098
                    $row = Database::fetch_array($rs);
1099
                    $score = $row['score'];
1100
                }
1101
                $faults = $total_done_attendance - $score;
1102
                $faults = $faults > 0 ? $faults : 0;
1103
                $total_faults += $faults;
1104
                $total_weight += $total_done_attendance;
1105
            }
1106
        }
1107
1108
        $porcent = $total_weight > 0 ? round(($total_faults * 100) / $total_weight, 0) : 0;
1109
        $results['faults'] = $total_faults;
1110
        $results['total'] = $total_weight;
1111
        $results['porcent'] = $porcent;
1112
1113
        return $results;
1114
    }
1115
1116
    /**
1117
     * Get results of faults average by course
1118
     * @param int $user_id
1119
     * @param string $course_code
1120
     * @param int Session id (optional)
1121
     * @return array  results containing number of faults,
1122
     * total done attendance, porcent of faults and color depend on result (red, orange)
1123
     */
1124
    public function get_faults_average_by_course(
1125
        $user_id,
1126
        $course_code,
1127
        $session_id = null
1128
    ) {
1129
        // Database tables and variables
1130
        $course_info = api_get_course_info($course_code);
1131
        $tbl_attendance_result = Database::get_course_table(TABLE_ATTENDANCE_RESULT);
1132
        $user_id = intval($user_id);
1133
        $results = [];
1134
        $total_faults = $total_weight = $porcent = 0;
1135
        $attendances_by_course = $this->get_attendances_list(
1136
            $course_info['real_id'],
1137
            $session_id
1138
        );
1139
1140
        foreach ($attendances_by_course as $attendance) {
1141
            // Get total faults and total weight
1142
            $total_done_attendance = $attendance['attendance_qualify_max'];
1143
            $sql = "SELECT score FROM $tbl_attendance_result
1144
                    WHERE
1145
                        c_id = {$course_info['real_id']} AND
1146
                        user_id = $user_id AND
1147
                        attendance_id=".$attendance['id'];
1148
            $rs = Database::query($sql);
1149
            $score = 0;
1150
            if (Database::num_rows($rs) > 0) {
1151
                $row = Database::fetch_array($rs);
1152
                $score = $row['score'];
1153
            }
1154
            $faults = $total_done_attendance - $score;
1155
            $faults = $faults > 0 ? $faults : 0;
1156
            $total_faults += $faults;
1157
            $total_weight += $total_done_attendance;
1158
        }
1159
1160
        $porcent = $total_weight > 0 ? round(($total_faults * 100) / $total_weight, 0) : 0;
1161
        $results['faults'] = $total_faults;
1162
        $results['total'] = $total_weight;
1163
        $results['porcent'] = $porcent;
1164
1165
        return $results;
1166
    }
1167
1168
    /**
1169
     * Get registered users' attendance sheet inside current course
1170
     * @param int $attendanceId
1171
     * @param int $user_id for showing data for only one user (optional)
1172
     * @param int $groupId
1173
     * @return array  users attendance sheet data
1174
     */
1175
    public function get_users_attendance_sheet(
1176
        $attendanceId,
1177
        $user_id = 0,
1178
        $groupId = 0
1179
    ) {
1180
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
1181
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1182
        $attendance_calendar = $this->get_attendance_calendar(
1183
            $attendanceId,
1184
            'all',
1185
            null,
1186
            $groupId
1187
        );
1188
        $calendar_ids = [];
1189
        // get all dates from calendar by current attendance
1190
        foreach ($attendance_calendar as $cal) {
1191
            $calendar_ids[] = $cal['id'];
1192
        }
1193
1194
        $course_id = api_get_course_int_id();
1195
1196
        $data = [];
1197
        if (empty($user_id)) {
1198
            // get all registered users inside current course
1199
            $users = $this->get_users_rel_course();
1200
            $user_ids = array_keys($users);
1201
            if (count($calendar_ids) > 0 && count($user_ids) > 0) {
1202
                foreach ($user_ids as $uid) {
1203
                    $sql = "SELECT * FROM $tbl_attendance_sheet
1204
                            WHERE
1205
                                c_id = $course_id AND
1206
                                user_id = '$uid' AND
1207
                                attendance_calendar_id IN(".implode(',', $calendar_ids).")
1208
                            ";
1209
                    $res = Database::query($sql);
1210
                    if (Database::num_rows($res) > 0) {
1211
                        while ($row = Database::fetch_array($res)) {
1212
                            $data[$uid][$row['attendance_calendar_id']]['presence'] = $row['presence'];
1213
                        }
1214
                    }
1215
                }
1216
            }
1217
        } else {
1218
            // Get attendance for current user
1219
            $user_id = intval($user_id);
1220
            if (count($calendar_ids) > 0) {
1221
                $sql = "SELECT cal.date_time, att.presence
1222
                        FROM $tbl_attendance_sheet att
1223
                        INNER JOIN  $tbl_attendance_calendar cal
1224
                        ON cal.id = att.attendance_calendar_id
1225
                        WHERE
1226
                            att.c_id = $course_id AND
1227
                            cal.c_id =  $course_id AND
1228
                            att.user_id = '$user_id' AND
1229
                            att.attendance_calendar_id IN (".implode(',', $calendar_ids).")
1230
                        ORDER BY date_time";
1231
                $res = Database::query($sql);
1232
                if (Database::num_rows($res) > 0) {
1233
                    while ($row = Database::fetch_array($res)) {
1234
                        $row['date_time'] = api_convert_and_format_date($row['date_time'], null, date_default_timezone_get());
1235
                        $data[$user_id][] = $row;
1236
                    }
1237
                }
1238
            }
1239
        }
1240
1241
        return $data;
1242
    }
1243
1244
    /**
1245
     * Get next attendance calendar without presences (done attendances)
1246
     * @param int    attendance id
1247
     * @return int attendance calendar id
1248
     */
1249
    public function get_next_attendance_calendar_id($attendanceId)
1250
    {
1251
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1252
        $attendanceId = intval($attendanceId);
1253
        $course_id = api_get_course_int_id();
1254
1255
        $sql = "SELECT id FROM $table
1256
                WHERE
1257
                    c_id = $course_id AND
1258
                    attendance_id = '$attendanceId' AND
1259
                    done_attendance = 0
1260
                ORDER BY date_time
1261
                LIMIT 1";
1262
        $rs = Database::query($sql);
1263
        $next_calendar_id = 0;
1264
        if (Database::num_rows($rs) > 0) {
1265
            $row = Database::fetch_array($rs);
1266
            $next_calendar_id = $row['id'];
1267
        }
1268
1269
        return $next_calendar_id;
1270
    }
1271
1272
    /**
1273
     * Get next attendance calendar datetime without presences (done attendances)
1274
     * @param int    attendance id
1275
     * @return int UNIX time format datetime
1276
     */
1277
    public function getNextAttendanceCalendarDatetime($attendanceId)
1278
    {
1279
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1280
        $course_id = api_get_course_int_id();
1281
        $attendanceId = intval($attendanceId);
1282
        $sql = "SELECT id, date_time FROM $table
1283
                WHERE
1284
                    c_id = $course_id AND
1285
                    attendance_id = '$attendanceId' AND
1286
                    done_attendance = 0
1287
                ORDER BY date_time
1288
                LIMIT 1";
1289
        $rs = Database::query($sql);
1290
        $next_calendar_datetime = 0;
1291
        if (Database::num_rows($rs) > 0) {
1292
            $row = Database::fetch_array($rs);
1293
            $next_calendar_datetime = api_get_local_time($row['date_time']);
1294
        }
1295
1296
        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...
1297
    }
1298
1299
    /**
1300
     * Get user's score from current attendance
1301
     * @param int $user_id
1302
     * @param int $attendanceId
1303
     * @param int $groupId
1304
     * @return int score
1305
     */
1306
    public function get_user_score($user_id, $attendanceId, $groupId = 0)
1307
    {
1308
        $tbl_attendance_result = Database::get_course_table(TABLE_ATTENDANCE_RESULT);
1309
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
1310
        $tbl_attendance_cal_rel_group = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1311
        $tbl_attendance_cal = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1312
        $user_id = intval($user_id);
1313
        $attendanceId = intval($attendanceId);
1314
        $groupId = (int) $groupId;
1315
        $course_id = api_get_course_int_id();
1316
        if (empty($groupId)) {
1317
            $sql = "SELECT score FROM $tbl_attendance_result
1318
                    WHERE
1319
                        c_id = $course_id AND
1320
                        user_id='$user_id' AND
1321
                        attendance_id='$attendanceId'";
1322
        } else {
1323
            $sql = "SELECT count(presence) as score FROM $tbl_attendance_sheet
1324
                    WHERE
1325
                        c_id = $course_id AND
1326
                        user_id='$user_id' AND
1327
                        presence = 1 AND
1328
                        attendance_calendar_id IN (
1329
                            SELECT calendar_id FROM $tbl_attendance_cal_rel_group crg
1330
                            INNER JOIN $tbl_attendance_cal c
1331
                            ON (crg.calendar_id = c.id)
1332
                            WHERE
1333
                                crg.c_id = $course_id AND
1334
                                crg.group_id = $groupId AND
1335
                                c.attendance_id = $attendanceId
1336
                        )
1337
                    ";
1338
        }
1339
        $rs = Database::query($sql);
1340
        $score = 0;
1341
        if (Database::num_rows($rs) > 0) {
1342
            $row = Database::fetch_array($rs);
1343
            $score = $row['score'];
1344
        }
1345
1346
        return $score;
1347
    }
1348
1349
    /**
1350
     * Get attendance calendar data by id
1351
     * @param int    attendance calendar id
1352
     * @return array attendance calendar data
1353
     */
1354
    public function get_attendance_calendar_by_id($calendar_id)
1355
    {
1356
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1357
        $calendar_id = intval($calendar_id);
1358
        $course_id = api_get_course_int_id();
1359
        $sql = "SELECT * FROM $table
1360
                WHERE c_id = $course_id AND id = '$calendar_id' ";
1361
        $rs = Database::query($sql);
1362
        $data = [];
1363
        if (Database::num_rows($rs) > 0) {
1364
            while ($row = Database::fetch_array($rs)) {
1365
                $row['date_time'] = api_get_local_time($row['date_time']);
1366
                $data = $row;
1367
            }
1368
        }
1369
1370
        return $data;
1371
    }
1372
1373
    /**
1374
     * Get all attendance calendar data inside current attendance
1375
     * @param int $attendanceId
1376
     * @param string $type
1377
     * @param int $calendar_id
1378
     * @param int $groupId
1379
     * @param bool $showAll = false show group calendar items or not
1380
     *
1381
     * @return array attendance calendar data
1382
     */
1383
    public function get_attendance_calendar(
1384
        $attendanceId,
1385
        $type = 'all',
1386
        $calendar_id = null,
1387
        $groupId = 0,
1388
        $showAll = false
1389
    ) {
1390
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1391
        $tbl_acrg = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1392
        $attendanceId = intval($attendanceId);
1393
        $course_id = api_get_course_int_id();
1394
1395
        if ($showAll) {
1396
            $sql = "SELECT * FROM $tbl_attendance_calendar c
1397
                    WHERE c_id = $course_id AND attendance_id = '$attendanceId'";
1398
        } else {
1399
            $sql = "SELECT * FROM $tbl_attendance_calendar c
1400
                    WHERE
1401
                        c_id = $course_id AND
1402
                        attendance_id = '$attendanceId' AND
1403
                        id NOT IN (
1404
                            SELECT calendar_id FROM $tbl_acrg
1405
                            WHERE c_id = $course_id AND group_id != 0 AND group_id IS NOT NULL
1406
                        )
1407
                    ";
1408
        }
1409
1410
        if (!empty($groupId)) {
1411
            $groupId = intval($groupId);
1412
            $sql = "SELECT c.* FROM $tbl_attendance_calendar c
1413
                    INNER JOIN $tbl_acrg g
1414
                    ON c.c_id = g.c_id AND c.id = g.calendar_id
1415
                    WHERE
1416
                        c.c_id = $course_id AND
1417
                        g.group_id = '$groupId' AND
1418
                        c.attendance_id = '$attendanceId'
1419
                   ";
1420
        }
1421
1422
        if (!in_array($type, ['today', 'all', 'all_done', 'all_not_done', 'calendar_id'])) {
1423
            $type = 'all';
1424
        }
1425
1426
        switch ($type) {
1427
            case 'calendar_id':
1428
                $calendar_id = intval($calendar_id);
1429
                if (!empty($calendar_id)) {
1430
                    $sql .= " AND c.id = $calendar_id";
1431
                }
1432
                break;
1433
            case 'today':
1434
                //$sql .= ' AND DATE_FORMAT(date_time,"%d-%m-%Y") = DATE_FORMAT("'.api_get_utc_datetime().'", "%d-%m-%Y" )';
1435
                break;
1436
            case 'all_done':
1437
                $sql .= " AND done_attendance = 1 ";
1438
                break;
1439
            case 'all_not_done':
1440
                $sql .= " AND done_attendance = 0 ";
1441
                break;
1442
            case 'all':
1443
            default:
1444
                break;
1445
        }
1446
        $sql .= " ORDER BY date_time ";
1447
1448
        $rs = Database::query($sql);
1449
        $data = [];
1450
        if (Database::num_rows($rs) > 0) {
1451
            while ($row = Database::fetch_array($rs, 'ASSOC')) {
1452
                $row['db_date_time'] = $row['date_time'];
1453
                $row['date_time'] = api_get_local_time($row['date_time']);
1454
                $row['date'] = api_format_date($row['date_time'], DATE_FORMAT_SHORT);
1455
                $row['time'] = api_format_date($row['date_time'], TIME_NO_SEC_FORMAT);
1456
                $row['groups'] = $this->getGroupListByAttendanceCalendar($row['id'], $course_id);
1457
                if ($type == 'today') {
1458
                    if (date('d-m-Y', api_strtotime($row['date_time'], 'UTC')) == date('d-m-Y', time())) {
1459
                        $data[] = $row;
1460
                    }
1461
                } else {
1462
                    $data[] = $row;
1463
                }
1464
            }
1465
        }
1466
1467
        return $data;
1468
    }
1469
1470
    /**
1471
     * Get number of attendance calendar inside current attendance
1472
     * @param int $attendanceId
1473
     * @param int $groupId
1474
     * @param $done_attendance
1475
     * @param int $userId
1476
     * @return int number of dates in attendance calendar
1477
     */
1478
    public static function get_number_of_attendance_calendar(
1479
        $attendanceId,
1480
        $groupId = 0,
1481
        $done_attendance = null,
1482
        $userId = 0
1483
    ) {
1484
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1485
        $calendarRelGroup = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1486
        $tbl_groupRelUser = Database::get_course_table(TABLE_GROUP_USER);
1487
        $attendanceId = intval($attendanceId);
1488
        $groupId = intval($groupId);
1489
        $course_id = api_get_course_int_id();
1490
1491
        $where_attendance = '';
1492
        if ($done_attendance) {
1493
            $where_attendance = ' done_attendance = 1 AND ';
1494
        }
1495
        if (empty($userId)) {
1496
            if (empty($groupId)) {
1497
                $sql = "SELECT count(a.id)
1498
                        FROM $tbl_attendance_calendar a
1499
                        WHERE
1500
                            c_id = $course_id AND
1501
                            $where_attendance
1502
                            attendance_id = '$attendanceId' AND
1503
                            id NOT IN (
1504
                                SELECT calendar_id FROM $calendarRelGroup
1505
                                WHERE
1506
                                    c_id = $course_id AND
1507
                                    group_id != 0 AND
1508
                                    group_id IS NOT NULL
1509
                            )
1510
                        ";
1511
            } else {
1512
                $sql = "SELECT count(a.id)
1513
                        FROM $tbl_attendance_calendar a
1514
                        INNER JOIN $calendarRelGroup g
1515
                        ON (a.id = g.calendar_id AND a.c_id = g.c_id)
1516
                        WHERE
1517
                            a.c_id = $course_id AND
1518
                            $where_attendance
1519
                            attendance_id = '$attendanceId' AND
1520
                            group_id = $groupId
1521
                        ";
1522
            }
1523
        } else {
1524
            if (empty($groupId)) {
1525
                $sql = "SELECT count(a.id)
1526
                        FROM $tbl_attendance_calendar a
1527
                        WHERE
1528
                            c_id = $course_id AND
1529
                            $where_attendance
1530
                            attendance_id = '$attendanceId' AND
1531
                            id NOT IN (
1532
                                SELECT calendar_id FROM $calendarRelGroup
1533
                                WHERE
1534
                                    c_id = $course_id AND
1535
                                    group_id != 0 AND
1536
                                    group_id IS NOT NULL AND
1537
                                    group_id NOT IN (
1538
                                        SELECT group_id
1539
                                        FROM $tbl_groupRelUser
1540
                                        WHERE user_id = $userId
1541
                                    )
1542
                            )
1543
                        ";
1544
            } else {
1545
                $sql = "SELECT count(a.id)
1546
                        FROM $tbl_attendance_calendar a
1547
                        INNER JOIN $calendarRelGroup g
1548
                        ON (a.id = g.calendar_id AND a.c_id = g.c_id)
1549
                        WHERE
1550
                            a.c_id = $course_id AND
1551
                            $where_attendance
1552
                            attendance_id = '$attendanceId' AND
1553
                            group_id = $groupId
1554
                        ";
1555
            }
1556
        }
1557
1558
        $rs = Database::query($sql);
1559
        $row = Database::fetch_row($rs);
1560
        $count = $row[0];
1561
1562
        return $count;
1563
    }
1564
1565
    /**
1566
     * Get count dates inside attendance calendar by attendance id
1567
     * @param int $attendanceId
1568
     * @return int     count of dates
1569
     */
1570
    public static function get_count_dates_inside_attendance_calendar($attendanceId)
1571
    {
1572
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1573
        $attendanceId = intval($attendanceId);
1574
        $course_id = api_get_course_int_id();
1575
        $sql = "SELECT count(id) FROM $tbl_attendance_calendar
1576
                WHERE
1577
                    c_id = $course_id AND
1578
                    attendance_id = '$attendanceId'";
1579
        $rs = Database::query($sql);
1580
        $count = 0;
1581
        if (Database::num_rows($rs) > 0) {
1582
            $row = Database::fetch_row($rs);
1583
            $count = $row[0];
1584
        }
1585
        return $count;
1586
    }
1587
1588
    /**
1589
     * check if all calendar of an attendance is done
1590
     * @param   int     $attendanceId
1591
     * @return  bool    True if all calendar is done, otherwise false
1592
     */
1593
    public static function is_all_attendance_calendar_done($attendanceId)
1594
    {
1595
        $attendanceId = intval($attendanceId);
1596
        $done_calendar = self::get_done_attendance_calendar($attendanceId);
1597
        $count_dates_in_calendar = self::get_count_dates_inside_attendance_calendar($attendanceId);
1598
        $number_of_dates = self::get_number_of_attendance_calendar($attendanceId);
1599
1600
        $result = false;
1601
        if ($number_of_dates && (intval($count_dates_in_calendar) == intval($done_calendar))) {
1602
            $result = true;
1603
        }
1604
        return $result;
1605
    }
1606
1607
    /**
1608
     * check if an attendance is locked
1609
     * @param int $attendanceId
1610
     * @param bool
1611
     * @return bool
1612
     */
1613
    public static function is_locked_attendance($attendanceId)
1614
    {
1615
        //use gradebook lock
1616
        $result = api_resource_is_locked_by_gradebook($attendanceId, LINK_ATTENDANCE);
1617
1618
        return $result;
1619
    }
1620
1621
    /**
1622
     * Add new datetime inside attendance calendar table
1623
     * @param    int $attendanceId
1624
     * @param    array $groupList
1625
     * @return    int affected rows
1626
     */
1627
    public function attendance_calendar_add($attendanceId, $groupList = [])
1628
    {
1629
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1630
        $affected_rows = 0;
1631
        $attendanceId = intval($attendanceId);
1632
        $course_id = api_get_course_int_id();
1633
        // check if datetime already exists inside the table
1634
        /*$sql = "SELECT id FROM $tbl_attendance_calendar
1635
                WHERE
1636
                    c_id = $course_id AND
1637
                    date_time='".Database::escape_string($this->date_time)."' AND
1638
                    attendance_id = '$attendanceId'";
1639
        $rs = Database::query($sql);
1640
        if (Database::num_rows($rs) == 0) {*/
1641
        $params = [
1642
            'c_id' =>  $course_id,
1643
            'date_time' => $this->date_time,
1644
            'attendance_id' => $attendanceId,
1645
            'done_attendance' => 0
1646
        ];
1647
        $id = Database::insert($tbl_attendance_calendar, $params);
1648
1649
        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...
1650
            $sql = "UPDATE $tbl_attendance_calendar SET id = iid WHERE iid = $id";
1651
            Database::query($sql);
1652
            $affected_rows++;
1653
        }
1654
        $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

1654
        $this->addAttendanceCalendarToGroup(/** @scrutinizer ignore-type */ $id, $course_id, $groupList);
Loading history...
1655
        //}
1656
1657
        // update locked attendance
1658
        $is_all_calendar_done = self::is_all_attendance_calendar_done($attendanceId);
1659
        if (!$is_all_calendar_done) {
1660
            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

1660
            self::/** @scrutinizer ignore-call */ 
1661
                  lock_attendance($attendanceId, false);
Loading history...
1661
        } else {
1662
            self::lock_attendance($attendanceId);
1663
        }
1664
        return $affected_rows;
1665
    }
1666
1667
    /**
1668
     * @param int $calendarId
1669
     * @param int $courseId
1670
     * @param array $groupList
1671
     *
1672
     * @return bool
1673
     */
1674
    public function addAttendanceCalendarToGroup($calendarId, $courseId, $groupList)
1675
    {
1676
        if (empty($groupList)) {
1677
            return false;
1678
        }
1679
1680
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1681
1682
        foreach ($groupList as $groupId) {
1683
            if (empty($groupId)) {
1684
                continue;
1685
            }
1686
1687
            $result = $this->getAttendanceCalendarGroup(
1688
                $calendarId,
1689
                $courseId,
1690
                $groupId
1691
            );
1692
1693
            if (empty($result)) {
1694
                $params = [
1695
                    'calendar_id' => $calendarId,
1696
                    'c_id' => $courseId,
1697
                    'group_id' => $groupId,
1698
                ];
1699
                Database::insert($table, $params);
1700
            }
1701
        }
1702
1703
        return true;
1704
    }
1705
1706
    /**
1707
     * @param int $calendarId
1708
     * @param int $courseId
1709
     *
1710
     * @return array
1711
     */
1712
    public function getGroupListByAttendanceCalendar($calendarId, $courseId)
1713
    {
1714
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1715
        return Database::select(
1716
            '*',
1717
            $table,
1718
            ['where'=>
1719
                [
1720
                    'calendar_id = ? AND c_id = ?' => [$calendarId, $courseId]
1721
                ]
1722
            ]
1723
        );
1724
    }
1725
1726
    /**
1727
     * @param int $calendarId
1728
     * @param int $courseId
1729
     * @param int $groupId
1730
     * @return array
1731
     */
1732
    public function getAttendanceCalendarGroup($calendarId, $courseId, $groupId)
1733
    {
1734
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1735
        return Database::select(
1736
            '*',
1737
            $table,
1738
            ['where'=>
1739
                [
1740
                    'calendar_id = ? AND c_id = ? AND group_id = ?' => [$calendarId, $courseId, $groupId]
1741
                ]
1742
            ]
1743
        );
1744
    }
1745
1746
    /**
1747
     * @param int $calendarId
1748
     * @param int $courseId
1749
     *
1750
     */
1751
    public function deleteAttendanceCalendarGroup($calendarId, $courseId)
1752
    {
1753
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1754
        Database::delete(
1755
            $table,
1756
            [
1757
                'calendar_id = ? AND c_id = ?' => [$calendarId, $courseId]
1758
            ]
1759
        );
1760
    }
1761
1762
    /**
1763
     * save repeated date inside attendance calendar table
1764
     * @param int $attendanceId
1765
     * @param int $start_date start date in tms
1766
     * @param int $end_date end date in tms
1767
     * @param string $repeat_type daily, weekly, monthlyByDate
1768
     * @param array $groupList
1769
     */
1770
    public function attendance_repeat_calendar_add(
1771
        $attendanceId,
1772
        $start_date,
1773
        $end_date,
1774
        $repeat_type,
1775
        $groupList = []
1776
    ) {
1777
        $attendanceId = intval($attendanceId);
1778
        // save start date
1779
        $datetimezone = api_get_utc_datetime($start_date);
1780
        $this->set_date_time($datetimezone);
1781
        $this->attendance_calendar_add($attendanceId, $groupList);
1782
1783
        // 86400 = 24 hours in seconds
1784
        // 604800 = 1 week in seconds
1785
        // Saves repeated dates
1786
        switch ($repeat_type) {
1787
            case 'daily':
1788
                $j = 1;
1789
                for ($i = $start_date + 86400; ($i <= $end_date); $i += 86400) {
1790
                    $datetimezone = api_get_utc_datetime($i);
1791
                    $this->set_date_time($datetimezone);
1792
                    $this->attendance_calendar_add($attendanceId, $groupList);
1793
                    $j++;
1794
                }
1795
                break;
1796
            case 'weekly':
1797
                $j = 1;
1798
                for ($i = $start_date + 604800; ($i <= $end_date); $i += 604800) {
1799
                    $datetimezone = api_get_utc_datetime($i);
1800
                    $this->set_date_time($datetimezone);
1801
                    $this->attendance_calendar_add($attendanceId, $groupList);
1802
                    $j++;
1803
                }
1804
                break;
1805
            case 'monthlyByDate':
1806
                $j = 1;
1807
                //@todo fix bug with february
1808
                for ($i = $start_date + 2419200; ($i <= $end_date); $i += 2419200) {
1809
                    $datetimezone = api_get_utc_datetime($i);
1810
                    $this->set_date_time($datetimezone);
1811
                    $this->attendance_calendar_add($attendanceId, $groupList);
1812
                    $j++;
1813
                }
1814
                break;
1815
        }
1816
    }
1817
1818
    /**
1819
     * edit a datetime inside attendance calendar table
1820
     * @param	int	attendance calendar id
1821
     * @param	int	attendance id
1822
     * @return	int affected rows
1823
     */
1824
    public function attendance_calendar_edit($calendar_id, $attendanceId)
1825
    {
1826
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1827
        $affected_rows = 0;
1828
        $attendanceId = intval($attendanceId);
1829
        $course_id = api_get_course_int_id();
1830
        // check if datetime already exists inside the table
1831
        $sql = "SELECT id FROM $tbl_attendance_calendar
1832
                WHERE
1833
                    c_id = $course_id AND
1834
                    date_time = '".Database::escape_string($this->date_time)."' AND
1835
                    attendance_id = '$attendanceId'";
1836
        $rs = Database::query($sql);
1837
1838
        if (Database::num_rows($rs) == 0) {
1839
            $sql = "UPDATE $tbl_attendance_calendar
1840
                    SET date_time='".Database::escape_string($this->date_time)."'
1841
                    WHERE c_id = $course_id AND id = '".intval($calendar_id)."'";
1842
            Database::query($sql);
1843
        }
1844
1845
        // update locked attendance
1846
        $is_all_calendar_done = self::is_all_attendance_calendar_done($attendanceId);
1847
        if (!$is_all_calendar_done) {
1848
            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

1848
            self::/** @scrutinizer ignore-call */ 
1849
                  lock_attendance($attendanceId, false);
Loading history...
1849
        } else {
1850
            self::lock_attendance($attendanceId);
1851
        }
1852
1853
        return $affected_rows;
1854
    }
1855
1856
    /**
1857
     * delete a datetime from attendance calendar table
1858
     * @param	int		attendance calendar id
1859
     * @param	int		attendance id
1860
     * @param	bool true for removing all calendar inside current attendance, false for removing by calendar id
1861
     * @return	int affected rows
1862
     */
1863
    public function attendance_calendar_delete(
1864
        $calendar_id,
1865
        $attendanceId,
1866
        $all_delete = false
1867
    ) {
1868
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1869
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
1870
1871
        $attendanceId = intval($attendanceId);
1872
        // get all registered users inside current course
1873
        $users = $this->get_users_rel_course();
1874
        $user_ids = array_keys($users);
1875
        $course_id = api_get_course_int_id();
1876
        $affected_rows = 0;
1877
        if ($all_delete) {
1878
            $attendance_calendar = $this->get_attendance_calendar($attendanceId);
1879
            // get all dates from calendar by current attendance
1880
            if (!empty($attendance_calendar)) {
1881
                foreach ($attendance_calendar as $cal) {
1882
                    // delete all data from attendance sheet
1883
                    $sql = "DELETE FROM $tbl_attendance_sheet
1884
                            WHERE c_id = $course_id AND attendance_calendar_id = '".intval($cal['id'])."'";
1885
                    Database::query($sql);
1886
                    // delete data from attendance calendar
1887
                    $sql = "DELETE FROM $tbl_attendance_calendar
1888
                            WHERE c_id = $course_id AND id = '".intval($cal['id'])."'";
1889
                    Database::query($sql);
1890
1891
                    $this->deleteAttendanceCalendarGroup($cal['id'], $course_id);
1892
                    $affected_rows++;
1893
                }
1894
            }
1895
        } else {
1896
            // delete just one row from attendance sheet by the calendar id
1897
            $sql = "DELETE FROM $tbl_attendance_sheet
1898
                    WHERE c_id = $course_id AND attendance_calendar_id = '".intval($calendar_id)."'";
1899
            Database::query($sql);
1900
            // delete data from attendance calendar
1901
            $sql = "DELETE FROM $tbl_attendance_calendar
1902
                    WHERE c_id = $course_id AND id = '".intval($calendar_id)."'";
1903
            Database::query($sql);
1904
1905
            $this->deleteAttendanceCalendarGroup($calendar_id, $course_id);
1906
            $affected_rows++;
1907
        }
1908
1909
        // update users' results
1910
        $this->updateUsersResults($user_ids, $attendanceId);
1911
1912
        return $affected_rows;
1913
    }
1914
1915
    /** Setters for fields of attendances tables **/
1916
    public function set_session_id($session_id)
1917
    {
1918
        $this->session_id = $session_id;
1919
    }
1920
1921
    public function set_course_id($course_id)
1922
    {
1923
        $this->course_id = $course_id;
1924
    }
1925
1926
    public function set_date_time($datetime)
1927
    {
1928
        $this->date_time = $datetime;
1929
    }
1930
1931
    public function set_name($name)
1932
    {
1933
        $this->name = $name;
1934
    }
1935
1936
    public function set_description($description)
1937
    {
1938
        $this->description = $description;
1939
    }
1940
1941
    public function set_attendance_qualify_title($attendance_qualify_title)
1942
    {
1943
        $this->attendance_qualify_title = $attendance_qualify_title;
1944
    }
1945
1946
    public function set_attendance_weight($attendance_weight)
1947
    {
1948
        $this->attendance_weight = $attendance_weight;
1949
    }
1950
1951
    /** Getters for fields of attendances tables **/
1952
    public function get_session_id()
1953
    {
1954
        return $this->session_id;
1955
    }
1956
1957
    public function get_course_id()
1958
    {
1959
        return $this->course_id;
1960
    }
1961
1962
    public function get_date_time()
1963
    {
1964
        return $this->date_time;
1965
    }
1966
1967
    public function get_name()
1968
    {
1969
        return $this->name;
1970
    }
1971
1972
    public function get_description()
1973
    {
1974
        return $this->description;
1975
    }
1976
1977
    public function get_attendance_qualify_title()
1978
    {
1979
        return $this->attendance_qualify_title;
1980
    }
1981
1982
    public function get_attendance_weight()
1983
    {
1984
        return $this->attendance_weight;
1985
    }
1986
1987
    /**
1988
     * @param string $startDate in UTC time
1989
     * @param string $endDate in UTC time
1990
     *
1991
     * @return array
1992
     */
1993
    public function getAttendanceLogin($startDate, $endDate)
1994
    {
1995
        if (empty($startDate) ||
1996
            $startDate == '0000-00-00' ||
1997
            $startDate == '0000-00-00 00:00:00' ||
1998
            empty($endDate) ||
1999
            $endDate == '0000-00-00' ||
2000
            $endDate == '0000-00-00 00:00:00'
2001
        ) {
2002
            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...
2003
        }
2004
2005
        $sessionId = api_get_session_id();
2006
        $courseCode = api_get_course_id();
2007
        $courseId = api_get_course_int_id();
2008
2009
        if (!empty($sessionId)) {
2010
            $users = CourseManager::get_user_list_from_course_code(
2011
                $courseCode,
2012
                $sessionId,
2013
                '',
2014
                'lastname',
2015
                0
2016
            );
2017
        } else {
2018
            $users = CourseManager::get_user_list_from_course_code(
2019
                $courseCode,
2020
                0,
2021
                '',
2022
                'lastname',
2023
                STUDENT
2024
            );
2025
        }
2026
2027
        $dateTimeStartOriginal = new DateTime($startDate);
2028
        $dateTimeStart = new DateTime($startDate);
2029
        $dateTimeEnd = new DateTime($endDate);
2030
        $interval = $dateTimeStart->diff($dateTimeEnd);
2031
        $days = intval($interval->format('%a'));
2032
2033
        $dateList = [$dateTimeStart->format('Y-m-d')];
2034
        $headers = [
2035
            get_lang('User'),
2036
            $dateTimeStart->format('Y-m-d')
2037
        ];
2038
2039
        for ($i = 0; $i < $days; $i++) {
2040
            $dateTimeStart = $dateTimeStart->add(new DateInterval('P1D'));
2041
            $date = $dateTimeStart->format('Y-m-d');
2042
            $dateList[] = $date;
2043
            $headers[] = $date;
2044
        }
2045
2046
        $accessData = CourseManager::getCourseAccessPerCourseAndSession(
2047
            $courseId,
2048
            $sessionId,
2049
            $dateTimeStartOriginal->format('Y-m-d H:i:s'),
2050
            $dateTimeEnd->format('Y-m-d H:i:s')
2051
        );
2052
2053
        $results = [];
2054
        if (!empty($accessData)) {
2055
            foreach ($accessData as $data) {
2056
                $onlyDate = substr($data['login_course_date'], 0, 10);
2057
                $results[$data['user_id']][$onlyDate] = true;
2058
            }
2059
        }
2060
2061
        return [
2062
            'users' => $users,
2063
            'dateList' => $dateList,
2064
            'headers' => $headers,
2065
            'results' => $results
2066
        ];
2067
    }
2068
2069
    /**
2070
     * @param string $startDate in UTC time
2071
     * @param string $endDate in UTC time
2072
     *
2073
     * @return string
2074
     */
2075
    public function getAttendanceLoginTable($startDate, $endDate)
2076
    {
2077
        $data = $this->getAttendanceLogin($startDate, $endDate);
2078
        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...
2079
            return null;
2080
        }
2081
2082
        $headers = $data['headers'];
2083
        $dateList = $data['dateList'];
2084
        $users = $data['users'];
2085
        $results = $data['results'];
2086
2087
        $table = new HTML_Table(['class' => 'data_table']);
2088
        $row = 0;
2089
        $column = 0;
2090
        foreach ($headers as $header) {
2091
            $table->setHeaderContents($row, $column, $header);
2092
            $column++;
2093
        }
2094
        $row = 1;
2095
        foreach ($users as $user) {
2096
            $table->setCellContents(
2097
                $row,
2098
                0,
2099
                $user['lastname'].' '.$user['firstname'].' ('.$user['username'].')'
2100
            );
2101
            $row++;
2102
        }
2103
2104
        $column = 1;
2105
        $row = 1;
2106
        foreach ($users as $user) {
2107
            foreach ($dateList as $date) {
2108
                $status = null;
2109
                if (isset($results[$user['user_id']]) &&
2110
                    isset($results[$user['user_id']][$date])
2111
                ) {
2112
                    $status = 'X';
2113
                }
2114
                $table->setCellContents($row, $column, $status);
2115
                $column++;
2116
            }
2117
            $row++;
2118
            $column = 1;
2119
        }
2120
2121
        return $table->toHtml();
2122
    }
2123
2124
    /**
2125
     * @param string $startDate in UTC time
2126
     * @param string $endDate in UTC time
2127
     *
2128
     * @return string
2129
     */
2130
    public function exportAttendanceLogin($startDate, $endDate)
2131
    {
2132
        $data = $this->getAttendanceLogin($startDate, $endDate);
2133
2134
        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...
2135
            return null;
2136
        }
2137
        $users = $data['users'];
2138
        $results = $data['results'];
2139
2140
        $table = new HTML_Table(['class' => 'data_table']);
2141
        $table->setHeaderContents(0, 0, get_lang('User'));
2142
        $table->setHeaderContents(0, 1, get_lang('Date'));
2143
2144
        $row = 1;
2145
        foreach ($users as $user) {
2146
            $table->setCellContents(
2147
                $row,
2148
                0,
2149
                $user['lastname'].' '.$user['firstname'].' ('.$user['username'].')'
2150
            );
2151
            $row++;
2152
        }
2153
        $table->setColAttributes(0, ['style' => 'width:28%']);
2154
2155
        $row = 1;
2156
        foreach ($users as $user) {
2157
            if (isset($results[$user['user_id']]) &&
2158
                !empty($results[$user['user_id']])
2159
            ) {
2160
                $dates = implode(', ', array_keys($results[$user['user_id']]));
2161
                $table->setCellContents($row, 1, $dates);
2162
            }
2163
            $row++;
2164
        }
2165
2166
        $tableToString = $table->toHtml();
2167
        $params = [
2168
            'filename' => get_lang('Attendance').'_'.api_get_utc_datetime(),
2169
            'pdf_title' => get_lang('Attendance'),
2170
            'course_code' => api_get_course_id(),
2171
            'show_real_course_teachers' => true
2172
        ];
2173
        $pdf = new PDF('A4', null, $params);
2174
        $pdf->html_to_pdf_with_template($tableToString);
2175
    }
2176
}
2177