Attendance::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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