Passed
Push — 1.11.x ( 324be3...94e5bc )
by
unknown
12:25
created

Attendance::get_done_attendance_calendar()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 11
nc 1
nop 1
dl 0
loc 17
rs 9.9
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
            $addOfficialCode = api_get_configuration_value('attendance_add_official_code');
780
            if ($addOfficialCode) {
781
                $value['official_code'] = $user_data['official_code'];
782
            }
783
            $value['firstname'] = $user_data['firstname'];
784
            $value['lastname'] = $user_data['lastname'];
785
            $value['username'] = $user_data['username'];
786
            $value['user_id'] = $uid;
787
788
            // Sending only 5 items in the array instead of 60
789
            $a_users[$key] = $value;
790
        }
791
792
        return $a_users;
793
    }
794
795
    /**
796
     * add attendances sheet inside table.
797
     *
798
     * @param int   $calendar_id   attendance calendar id
799
     * @param array $users_present present users during current class
800
     * @param int   $attendanceId
801
     *
802
     * @return int affected rows
803
     */
804
    public function attendance_sheet_add($calendar_id, $users_present, $attendanceId)
805
    {
806
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
807
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
808
809
        $calendar_id = (int) $calendar_id;
810
        $attendanceId = (int) $attendanceId;
811
        $users = $this->get_users_rel_course();
812
        $course_id = api_get_course_int_id();
813
814
        $user_ids = array_keys($users);
815
        $users_absent = array_diff($user_ids, $users_present);
816
        $affected_rows = 0;
817
818
        // get last edit type
819
        $calendar_data = $this->get_attendance_calendar_by_id($calendar_id);
820
        $lastedit_type = self::DONE_ATTENDANCE_LOG_TYPE;
821
        if ($calendar_data['done_attendance']) {
822
            $lastedit_type = self::UPDATED_ATTENDANCE_LOG_TYPE;
823
        }
824
825
        // save users present in class
826
        foreach ($users_present as $user_present) {
827
            $uid = (int) $user_present;
828
            // check if user already was registered with the $calendar_id
829
            $sql = "SELECT user_id FROM $tbl_attendance_sheet
830
                    WHERE c_id = $course_id AND user_id='$uid' AND attendance_calendar_id = '$calendar_id'";
831
            $rs = Database::query($sql);
832
            if (Database::num_rows($rs) == 0) {
833
                $sql = "INSERT INTO $tbl_attendance_sheet SET
834
                        c_id = $course_id,
835
                        user_id = '$uid',
836
                        attendance_calendar_id = '$calendar_id',
837
                        presence = 1";
838
                $result = Database::query($sql);
839
840
                $affected_rows += Database::affected_rows($result);
841
            } else {
842
                $sql = "UPDATE $tbl_attendance_sheet SET presence = 1
843
                        WHERE
844
                            c_id = $course_id AND
845
                            user_id ='$uid' AND
846
                            attendance_calendar_id = '$calendar_id'
847
                        ";
848
                $result = Database::query($sql);
849
                $affected_rows += Database::affected_rows($result);
850
            }
851
        }
852
853
        // save users absent in class
854
        foreach ($users_absent as $user_absent) {
855
            $uid = intval($user_absent);
856
            // check if user already was registered with the $calendar_id
857
            $sql = "SELECT user_id FROM $tbl_attendance_sheet
858
                    WHERE c_id = $course_id AND user_id='$uid' AND attendance_calendar_id = '$calendar_id'";
859
            $rs = Database::query($sql);
860
            if (Database::num_rows($rs) == 0) {
861
                $sql = "INSERT INTO $tbl_attendance_sheet SET
862
                        c_id = $course_id,
863
                        user_id ='$uid',
864
                        attendance_calendar_id = '$calendar_id',
865
                        presence = 0";
866
                $result = Database::query($sql);
867
868
                Database::insert_id();
869
870
                $affected_rows += Database::affected_rows($result);
871
            } else {
872
                $sql = "UPDATE $tbl_attendance_sheet SET presence = 0
873
                        WHERE
874
                            c_id = $course_id AND
875
                            user_id ='$uid' AND
876
                            attendance_calendar_id = '$calendar_id'";
877
                $result = Database::query($sql);
878
                $affected_rows += Database::affected_rows($result);
879
            }
880
        }
881
882
        // update done_attendance inside attendance calendar table
883
        $sql = "UPDATE $tbl_attendance_calendar SET done_attendance = 1
884
                WHERE  c_id = $course_id AND id = '$calendar_id'";
885
        Database::query($sql);
886
887
        // save users' results
888
        $this->updateUsersResults($user_ids, $attendanceId);
889
890
        if ($affected_rows) {
891
            //save attendance sheet log
892
            $this->saveAttendanceSheetLog(
893
                $attendanceId,
894
                api_get_utc_datetime(),
895
                $lastedit_type,
896
                api_get_user_id(),
897
                $calendar_data['date_time']
898
            );
899
        }
900
901
        return $affected_rows;
902
    }
903
904
    /**
905
     * update users' attendance results.
906
     *
907
     * @param array $user_ids     registered users inside current course
908
     * @param int   $attendanceId
909
     */
910
    public function updateUsersResults($user_ids, $attendanceId)
911
    {
912
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
913
        $tbl_attendance_result = Database::get_course_table(TABLE_ATTENDANCE_RESULT);
914
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
915
        $course_id = api_get_course_int_id();
916
        $attendanceId = intval($attendanceId);
917
        // fill results about presence of students
918
        $attendance_calendar = $this->get_attendance_calendar(
919
            $attendanceId,
920
            'all',
921
            null,
922
            null,
923
            true
924
        );
925
        $calendar_ids = [];
926
        // get all dates from calendar by current attendance
927
        foreach ($attendance_calendar as $cal) {
928
            $calendar_ids[] = $cal['id'];
929
        }
930
931
        // get count of presences by users inside current attendance and save like results
932
        if (count($user_ids) > 0) {
933
            foreach ($user_ids as $uid) {
934
                $uid = (int) $uid;
935
                $count_presences = 0;
936
                if (count($calendar_ids) > 0) {
937
                    $sql = "SELECT count(presence) as count_presences
938
                            FROM $tbl_attendance_sheet
939
                            WHERE
940
                                c_id = $course_id AND
941
                                user_id = '$uid' AND
942
                                attendance_calendar_id IN (".implode(',', $calendar_ids).") AND
943
                                presence = 1";
944
                    $rs_count = Database::query($sql);
945
                    $row_count = Database::fetch_array($rs_count);
946
                    $count_presences = $row_count['count_presences'];
947
                }
948
949
                // save results
950
                $sql = "SELECT id FROM $tbl_attendance_result
951
                        WHERE
952
                            c_id = $course_id AND
953
                            user_id = '$uid' AND
954
                            attendance_id = '$attendanceId' ";
955
                $rs_check_result = Database::query($sql);
956
957
                if (Database::num_rows($rs_check_result) > 0) {
958
                    // update result
959
                    $sql = "UPDATE $tbl_attendance_result SET
960
                            score = '$count_presences'
961
                            WHERE
962
                                c_id = $course_id AND
963
                                user_id='$uid' AND
964
                                attendance_id='$attendanceId'";
965
                    Database::query($sql);
966
                } else {
967
                    // insert new result
968
                    $sql = "INSERT INTO $tbl_attendance_result SET
969
                            c_id = $course_id ,
970
                            user_id			= '$uid',
971
                            attendance_id 	= '$attendanceId',
972
                            score			= '$count_presences'";
973
                    Database::query($sql);
974
975
                    $insertId = Database::insert_id();
976
                    if ($insertId) {
977
                        $sql = "UPDATE $tbl_attendance_result SET id = iid WHERE iid = $insertId";
978
                        Database::query($sql);
979
                    }
980
                }
981
            }
982
        }
983
984
        // update attendance qualify max
985
        $count_done_calendar = self::get_done_attendance_calendar($attendanceId);
986
        $sql = "UPDATE $tbl_attendance SET
987
                    attendance_qualify_max = '$count_done_calendar'
988
                WHERE c_id = $course_id AND id = '$attendanceId'";
989
        Database::query($sql);
990
    }
991
992
    /**
993
     * update attendance_sheet_log table, is used as history of an attendance sheet.
994
     *
995
     * @param   int     Attendance id
996
     * @param   string  Last edit datetime
997
     * @param   string  Event type ('locked_attendance', 'done_attendance_sheet' ...)
998
     * @param   int     Last edit user id
999
     * @param   string  Calendar datetime value (optional, when event type is 'done_attendance_sheet')
1000
     *
1001
     * @return int Affected rows
1002
     */
1003
    public function saveAttendanceSheetLog(
1004
        $attendanceId,
1005
        $lastedit_date,
1006
        $lastedit_type,
1007
        $lastedit_user_id,
1008
        $calendar_date_value = null
1009
    ) {
1010
        $course_id = api_get_course_int_id();
1011
1012
        // define table
1013
        $tbl_attendance_sheet_log = Database::get_course_table(TABLE_ATTENDANCE_SHEET_LOG);
1014
1015
        // protect data
1016
        $attendanceId = intval($attendanceId);
1017
        $lastedit_user_id = intval($lastedit_user_id);
1018
1019
        if (isset($calendar_date_value)) {
1020
            $calendar_date_value = $calendar_date_value;
1021
        } else {
1022
            $calendar_date_value = '';
1023
        }
1024
1025
        // save data
1026
        $params = [
1027
            'c_id' => $course_id,
1028
            'attendance_id' => $attendanceId,
1029
            'lastedit_date' => $lastedit_date,
1030
            'lastedit_type' => $lastedit_type,
1031
            'lastedit_user_id' => $lastedit_user_id,
1032
            'calendar_date_value' => $calendar_date_value,
1033
        ];
1034
        $insertId = Database::insert($tbl_attendance_sheet_log, $params);
1035
        if ($insertId) {
1036
            $sql = "UPDATE $tbl_attendance_sheet_log SET id = iid WHERE iid = $insertId";
1037
            Database::query($sql);
1038
        }
1039
1040
        return $insertId;
1041
    }
1042
1043
    /**
1044
     * Get number of done attendances inside current sheet.
1045
     *
1046
     * @param int attendance id
1047
     *
1048
     * @return int number of done attendances
1049
     */
1050
    public static function get_done_attendance_calendar($attendanceId)
1051
    {
1052
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1053
        $attendanceId = intval($attendanceId);
1054
        $course_id = api_get_course_int_id();
1055
        $sql = "SELECT count(done_attendance) as count
1056
                FROM $table
1057
                WHERE
1058
                    c_id = $course_id AND
1059
                    attendance_id = '$attendanceId' AND
1060
                    done_attendance = 1
1061
                ";
1062
        $rs = Database::query($sql);
1063
        $row = Database::fetch_array($rs);
1064
        $count = $row['count'];
1065
1066
        return $count;
1067
    }
1068
1069
    /**
1070
     * Get results of faults (absents) by user.
1071
     *
1072
     * @param int $user_id
1073
     * @param int $attendanceId
1074
     * @param int $groupId
1075
     *
1076
     * @return array results containing number of faults, total done attendance,
1077
     *               percent of faults and color depend on result (red, orange)
1078
     */
1079
    public function get_faults_of_user($user_id, $attendanceId, $groupId = null)
1080
    {
1081
        $user_id = intval($user_id);
1082
        $attendanceId = intval($attendanceId);
1083
        $results = [];
1084
        $calendar_count = self::get_number_of_attendance_calendar(
1085
            $attendanceId,
1086
            $groupId,
1087
            null,
1088
            $user_id
1089
        );
1090
        // $total_done_attendance 	= $attendance_data['attendance_qualify_max'];
1091
        $total_done_attendance = self::get_number_of_attendance_calendar(
1092
            $attendanceId,
1093
            $groupId,
1094
            true,
1095
            $user_id
1096
        );
1097
        $attendance_user_score = $this->get_user_score(
1098
            $user_id,
1099
            $attendanceId,
1100
            $groupId
1101
        );
1102
1103
        //This is the main change of the BT#1381
1104
        //$total_done_attendance = $calendar_count;
1105
1106
        // calculate results
1107
        $faults = $total_done_attendance - $attendance_user_score;
1108
1109
        if (empty($calendar_count)) {
1110
            $faults = 0;
1111
        }
1112
1113
        $faults = $faults > 0 ? $faults : 0;
1114
        $faults_porcent = $calendar_count > 0 ? round(($faults * 100) / $calendar_count, 0) : 0;
1115
        $results['faults'] = $faults;
1116
        $results['total'] = $calendar_count;
1117
        $results['faults_porcent'] = $faults_porcent;
1118
        $color_bar = '';
1119
1120
        if ($faults_porcent > 25) {
1121
            $color_bar = '#f28989';
1122
        } elseif ($faults_porcent > 10) {
1123
            $color_bar = '#F90';
1124
        }
1125
        $results['color_bar'] = $color_bar;
1126
1127
        return $results;
1128
    }
1129
1130
    /**
1131
     * Get results of faults average for all courses by user.
1132
     *
1133
     * @param int $user_id
1134
     *
1135
     * @return array results containing number of faults, total done attendance,
1136
     *               percentage of faults and color depend on result (red, orange)
1137
     */
1138
    public function get_faults_average_inside_courses($user_id)
1139
    {
1140
        // get all courses of current user
1141
        $courses = CourseManager::get_courses_list_by_user_id($user_id, true);
1142
        $user_id = intval($user_id);
1143
        $results = [];
1144
        $total_faults = $total_weight = $porcent = 0;
1145
        foreach ($courses as $course) {
1146
            //$course_code = $course['code'];
1147
            //$course_info = api_get_course_info($course_code);
1148
            $course_id = $course['real_id'];
1149
            $tbl_attendance_result = Database::get_course_table(TABLE_ATTENDANCE_RESULT);
1150
            $attendances_by_course = $this->get_attendances_list($course_id);
1151
1152
            foreach ($attendances_by_course as $attendance) {
1153
                // get total faults and total weight
1154
                $total_done_attendance = $attendance['attendance_qualify_max'];
1155
                $sql = "SELECT score
1156
                        FROM $tbl_attendance_result
1157
                        WHERE
1158
                            c_id = $course_id AND
1159
                            user_id = $user_id AND
1160
                            attendance_id = ".$attendance['id'];
1161
                $rs = Database::query($sql);
1162
                $score = 0;
1163
                if (Database::num_rows($rs) > 0) {
1164
                    $row = Database::fetch_array($rs);
1165
                    $score = $row['score'];
1166
                }
1167
                $faults = $total_done_attendance - $score;
1168
                $faults = $faults > 0 ? $faults : 0;
1169
                $total_faults += $faults;
1170
                $total_weight += $total_done_attendance;
1171
            }
1172
        }
1173
1174
        $porcent = $total_weight > 0 ? round(($total_faults * 100) / $total_weight, 0) : 0;
1175
        $results['faults'] = $total_faults;
1176
        $results['total'] = $total_weight;
1177
        $results['porcent'] = $porcent;
1178
1179
        return $results;
1180
    }
1181
1182
    /**
1183
     * Get results of faults average by course.
1184
     *
1185
     * @param int    $user_id
1186
     * @param string $course_code
1187
     * @param int Session id (optional)
1188
     *
1189
     * @return array results containing number of faults,
1190
     *               total done attendance, porcent of faults and color depend on result (red, orange)
1191
     */
1192
    public function get_faults_average_by_course(
1193
        $user_id,
1194
        $course_code,
1195
        $session_id = null
1196
    ) {
1197
        // Database tables and variables
1198
        $course_info = api_get_course_info($course_code);
1199
        $tbl_attendance_result = Database::get_course_table(TABLE_ATTENDANCE_RESULT);
1200
        $user_id = intval($user_id);
1201
        $results = [];
1202
        $total_faults = $total_weight = $porcent = 0;
1203
        $attendances_by_course = $this->get_attendances_list(
1204
            $course_info['real_id'],
1205
            $session_id
1206
        );
1207
1208
        foreach ($attendances_by_course as $attendance) {
1209
            // Get total faults and total weight
1210
            $total_done_attendance = $attendance['attendance_qualify_max'];
1211
            $sql = "SELECT score FROM $tbl_attendance_result
1212
                    WHERE
1213
                        c_id = {$course_info['real_id']} AND
1214
                        user_id = $user_id AND
1215
                        attendance_id=".$attendance['id'];
1216
            $rs = Database::query($sql);
1217
            $score = 0;
1218
            if (Database::num_rows($rs) > 0) {
1219
                $row = Database::fetch_array($rs);
1220
                $score = $row['score'];
1221
            }
1222
            $faults = $total_done_attendance - $score;
1223
            $faults = $faults > 0 ? $faults : 0;
1224
            $total_faults += $faults;
1225
            $total_weight += $total_done_attendance;
1226
        }
1227
1228
        $porcent = $total_weight > 0 ? round(($total_faults * 100) / $total_weight, 0) : 0;
1229
        $results['faults'] = $total_faults;
1230
        $results['total'] = $total_weight;
1231
        $results['porcent'] = $porcent;
1232
1233
        return $results;
1234
    }
1235
1236
    /**
1237
     * Get registered users' attendance sheet inside current course or course by id.
1238
     *
1239
     * @param int      $attendanceId
1240
     * @param int      $user_id      for showing data for only one user (optional)
1241
     * @param int      $groupId
1242
     * @param int      $course_id    if id = 0 get the current course
1243
     * @param DateTime $startDate    Filter atttendance sheet with a start date
1244
     * @param DateTime $endDate      Filter atttendance sheet with a end date
1245
     *
1246
     * @return array users attendance sheet data
1247
     */
1248
    public function get_users_attendance_sheet(
1249
        $attendanceId,
1250
        $user_id = 0,
1251
        $groupId = 0,
1252
        $course_id = 0,
1253
        DateTime $startDate = null,
1254
        DateTime $endDate = null
1255
    ) {
1256
        //Get actual course or by course_id
1257
        $course_id = (0 == $course_id) ? api_get_course_int_id() : (int) $course_id;
1258
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
1259
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1260
        $attendance_calendar = $this->get_attendance_calendar(
1261
            $attendanceId,
1262
            'all',
1263
            null,
1264
            $groupId,
1265
            true,
1266
            $course_id,
1267
            $startDate,
1268
            $endDate
1269
        );
1270
        $calendar_ids = [];
1271
        // get all dates from calendar by current attendance
1272
        foreach ($attendance_calendar as $cal) {
1273
            $calendar_ids[] = $cal['id'];
1274
        }
1275
1276
        $whereDate = '';
1277
        if (!empty($startDate)) {
1278
            $whereDate .= " AND cal.date_time >= '".$startDate->format('Y-m-d H:i:s')."'";
1279
        }
1280
        if (!empty($endDate)) {
1281
            $whereDate .= " AND cal.date_time <= '".$endDate->format('Y-m-d H:i:s')."'";
1282
        }
1283
1284
        // moved at start of this function
1285
        // $course_id = api_get_course_int_id();
1286
1287
        $data = [];
1288
        if (empty($user_id)) {
1289
            // get all registered users inside current course
1290
            $users = $this->get_users_rel_course();
1291
            $user_ids = array_keys($users);
1292
            if (count($calendar_ids) > 0 && count($user_ids) > 0) {
1293
                foreach ($user_ids as $uid) {
1294
                    $uid = (int) $uid;
1295
                    $sql = "SELECT * FROM $tbl_attendance_sheet
1296
                            WHERE
1297
                                c_id = $course_id AND
1298
                                user_id = '$uid' AND
1299
                                attendance_calendar_id IN(".implode(',', $calendar_ids).")
1300
                            ";
1301
                    $res = Database::query($sql);
1302
                    if (Database::num_rows($res) > 0) {
1303
                        while ($row = Database::fetch_array($res)) {
1304
                            $data[$uid][$row['attendance_calendar_id']]['presence'] = $row['presence'];
1305
                        }
1306
                    }
1307
                }
1308
            }
1309
        } else {
1310
            // Get attendance for current user
1311
            $user_id = (int) $user_id;
1312
            if (count($calendar_ids) > 0) {
1313
                $sql = "SELECT cal.date_time, att.presence, cal.iid as calendar_id
1314
                        FROM $tbl_attendance_sheet att
1315
                        INNER JOIN  $tbl_attendance_calendar cal
1316
                        ON cal.id = att.attendance_calendar_id
1317
                        WHERE
1318
                            att.c_id = $course_id AND
1319
                            cal.c_id =  $course_id AND
1320
                            att.user_id = '$user_id' AND
1321
                            att.attendance_calendar_id IN (".implode(',', $calendar_ids).")
1322
                            $whereDate
1323
                        ORDER BY date_time";
1324
                $res = Database::query($sql);
1325
                if (Database::num_rows($res) > 0) {
1326
                    while ($row = Database::fetch_array($res)) {
1327
                        $row['duration'] = Attendance::getAttendanceCalendarExtraFieldValue('duration', $row['calendar_id']);
1328
                        $row['date_time'] = api_get_local_time($row['date_time']);
1329
                        $row['date_time'] = api_convert_and_format_date($row['date_time'], null, date_default_timezone_get());
1330
                        $data[$user_id][] = $row;
1331
                    }
1332
                }
1333
            }
1334
        }
1335
1336
        return $data;
1337
    }
1338
1339
    /**
1340
     * Get next attendance calendar without presences (done attendances).
1341
     *
1342
     * @param int    attendance id
1343
     *
1344
     * @return int attendance calendar id
1345
     */
1346
    public function get_next_attendance_calendar_id($attendanceId)
1347
    {
1348
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1349
        $attendanceId = (int) $attendanceId;
1350
        $course_id = api_get_course_int_id();
1351
1352
        $sql = "SELECT id FROM $table
1353
                WHERE
1354
                    c_id = $course_id AND
1355
                    attendance_id = '$attendanceId' AND
1356
                    done_attendance = 0
1357
                ORDER BY date_time
1358
                LIMIT 1";
1359
        $rs = Database::query($sql);
1360
        $next_calendar_id = 0;
1361
        if (Database::num_rows($rs) > 0) {
1362
            $row = Database::fetch_array($rs);
1363
            $next_calendar_id = $row['id'];
1364
        }
1365
1366
        return $next_calendar_id;
1367
    }
1368
1369
    /**
1370
     * Get next attendance calendar datetime without presences (done attendances).
1371
     *
1372
     * @param int    attendance id
1373
     *
1374
     * @return int UNIX time format datetime
1375
     */
1376
    public function getNextAttendanceCalendarDatetime($attendanceId)
1377
    {
1378
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1379
        $course_id = api_get_course_int_id();
1380
        $attendanceId = (int) $attendanceId;
1381
        $sql = "SELECT id, date_time FROM $table
1382
                WHERE
1383
                    c_id = $course_id AND
1384
                    attendance_id = '$attendanceId' AND
1385
                    done_attendance = 0
1386
                ORDER BY date_time
1387
                LIMIT 1";
1388
        $rs = Database::query($sql);
1389
        $next_calendar_datetime = 0;
1390
        if (Database::num_rows($rs) > 0) {
1391
            $row = Database::fetch_array($rs);
1392
            $next_calendar_datetime = api_get_local_time($row['date_time']);
1393
        }
1394
1395
        return $next_calendar_datetime;
1396
    }
1397
1398
    /**
1399
     * Get user's score from current attendance.
1400
     *
1401
     * @param int $user_id
1402
     * @param int $attendanceId
1403
     * @param int $groupId
1404
     *
1405
     * @return int score
1406
     */
1407
    public function get_user_score($user_id, $attendanceId, $groupId = 0)
1408
    {
1409
        $tbl_attendance_result = Database::get_course_table(TABLE_ATTENDANCE_RESULT);
1410
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
1411
        $tbl_attendance_cal_rel_group = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1412
        $tbl_attendance_cal = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1413
        $user_id = intval($user_id);
1414
        $attendanceId = intval($attendanceId);
1415
        $groupId = (int) $groupId;
1416
        $course_id = api_get_course_int_id();
1417
1418
        if (empty($groupId)) {
1419
            $sql = "SELECT score FROM $tbl_attendance_result
1420
                    WHERE
1421
                        c_id = $course_id AND
1422
                        user_id='$user_id' AND
1423
                        attendance_id='$attendanceId'";
1424
        } else {
1425
            $sql = "SELECT count(presence) as score FROM $tbl_attendance_sheet
1426
                    WHERE
1427
                        c_id = $course_id AND
1428
                        user_id='$user_id' AND
1429
                        presence = 1 AND
1430
                        attendance_calendar_id IN (
1431
                            SELECT calendar_id FROM $tbl_attendance_cal_rel_group crg
1432
                            INNER JOIN $tbl_attendance_cal c
1433
                            ON (crg.calendar_id = c.id)
1434
                            WHERE
1435
                                crg.c_id = $course_id AND
1436
                                crg.group_id = $groupId AND
1437
                                c.attendance_id = $attendanceId
1438
                        )
1439
                    ";
1440
        }
1441
        $rs = Database::query($sql);
1442
        $score = 0;
1443
        if (Database::num_rows($rs) > 0) {
1444
            $row = Database::fetch_array($rs);
1445
            $score = $row['score'];
1446
        }
1447
1448
        return $score;
1449
    }
1450
1451
    /**
1452
     * Get attendance calendar data by id.
1453
     *
1454
     * @param int    attendance calendar id
1455
     *
1456
     * @return array attendance calendar data
1457
     */
1458
    public function get_attendance_calendar_by_id($calendar_id)
1459
    {
1460
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1461
        $calendar_id = intval($calendar_id);
1462
        $course_id = api_get_course_int_id();
1463
        $sql = "SELECT * FROM $table
1464
                WHERE c_id = $course_id AND id = '$calendar_id' ";
1465
        $rs = Database::query($sql);
1466
        $data = [];
1467
        if (Database::num_rows($rs) > 0) {
1468
            while ($row = Database::fetch_array($rs)) {
1469
                $row['date_time'] = api_get_local_time($row['date_time']);
1470
                $data = $row;
1471
            }
1472
        }
1473
1474
        return $data;
1475
    }
1476
1477
    /**
1478
     * Get all attendance calendar data inside current attendance or by course id.
1479
     *
1480
     * @param int      $attendanceId
1481
     * @param string   $type
1482
     * @param int      $calendar_id
1483
     * @param int      $groupId
1484
     * @param bool     $showAll      = false show group calendar items or not
1485
     * @param int      $course_id
1486
     * @param DateTime $startDate    Filter calendar with a start date
1487
     * @param DateTime $endDate      Filter calendar with a end date
1488
     *
1489
     * @return array attendance calendar data
1490
     */
1491
    public function get_attendance_calendar(
1492
        $attendanceId,
1493
        $type = 'all',
1494
        $calendar_id = null,
1495
        $groupId = 0,
1496
        $showAll = false,
1497
        $course_id = 0,
1498
        DateTime $startDate = null,
1499
        DateTime $endDate = null
1500
    ) {
1501
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1502
        $tbl_acrg = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1503
        $attendanceId = intval($attendanceId);
1504
        $course_id = (0 == $course_id) ? api_get_course_int_id() : (int) $course_id;
1505
        $whereDate = '';
1506
        if (!empty($startDate)) {
1507
            $whereDate .= " AND c.date_time >= '".$startDate->format('Y-m-d H:i:s')."'";
1508
        }
1509
        if (!empty($endDate)) {
1510
            $whereDate .= " AND c.date_time <= '".$endDate->format('Y-m-d H:i:s')."'";
1511
        }
1512
        if ($showAll) {
1513
            $sql = "SELECT * FROM $tbl_attendance_calendar c
1514
                    WHERE c_id = $course_id
1515
                      AND attendance_id = '$attendanceId'
1516
                        $whereDate";
1517
        } else {
1518
            $sql = "SELECT * FROM $tbl_attendance_calendar c
1519
                    WHERE
1520
                        c_id = $course_id AND
1521
                        attendance_id = '$attendanceId' AND
1522
                        id NOT IN (
1523
                            SELECT calendar_id FROM $tbl_acrg
1524
                            WHERE c_id = $course_id AND group_id != 0 AND group_id IS NOT NULL
1525
                        )
1526
                        $whereDate
1527
                    ";
1528
        }
1529
1530
        if (!empty($groupId)) {
1531
            $groupId = intval($groupId);
1532
            $sql = "SELECT c.* FROM $tbl_attendance_calendar c
1533
                    INNER JOIN $tbl_acrg g
1534
                    ON c.c_id = g.c_id AND c.id = g.calendar_id
1535
                    WHERE
1536
                        c.c_id = $course_id AND
1537
                        g.group_id = '$groupId' AND
1538
                        c.attendance_id = '$attendanceId'
1539
                   ";
1540
        }
1541
1542
        if (!in_array($type, ['today', 'all', 'all_done', 'all_not_done', 'calendar_id'])) {
1543
            $type = 'all';
1544
        }
1545
1546
        switch ($type) {
1547
            case 'calendar_id':
1548
                $calendar_id = intval($calendar_id);
1549
                if (!empty($calendar_id)) {
1550
                    $sql .= " AND c.id = $calendar_id";
1551
                }
1552
                break;
1553
            case 'today':
1554
                //$sql .= ' AND DATE_FORMAT(date_time,"%d-%m-%Y") = DATE_FORMAT("'.api_get_utc_datetime().'", "%d-%m-%Y" )';
1555
                break;
1556
            case 'all_done':
1557
                $sql .= " AND done_attendance = 1 ";
1558
                break;
1559
            case 'all_not_done':
1560
                $sql .= " AND done_attendance = 0 ";
1561
                break;
1562
            case 'all':
1563
            default:
1564
                break;
1565
        }
1566
        $sql .= " ORDER BY date_time ";
1567
1568
        $rs = Database::query($sql);
1569
        $data = [];
1570
        if (Database::num_rows($rs) > 0) {
1571
            while ($row = Database::fetch_array($rs, 'ASSOC')) {
1572
                $row['db_date_time'] = $row['date_time'];
1573
                $row['date_time'] = api_get_local_time($row['date_time']);
1574
                $row['date'] = api_format_date($row['date_time'], DATE_FORMAT_SHORT);
1575
                $row['time'] = api_format_date($row['date_time'], TIME_NO_SEC_FORMAT);
1576
                $row['groups'] = $this->getGroupListByAttendanceCalendar($row['id'], $course_id);
1577
                $row['duration'] = Attendance::getAttendanceCalendarExtraFieldValue('duration', $row['id']);
1578
                if ($type == 'today') {
1579
                    if (date('d-m-Y', api_strtotime($row['date_time'], 'UTC')) == date('d-m-Y', time())) {
1580
                        $data[] = $row;
1581
                    }
1582
                } else {
1583
                    $data[] = $row;
1584
                }
1585
            }
1586
        }
1587
1588
        return $data;
1589
    }
1590
1591
    /**
1592
     * Get number of attendance calendar inside current attendance.
1593
     *
1594
     * @param int $attendanceId
1595
     * @param int $groupId
1596
     * @param $done_attendance
1597
     * @param int $userId
1598
     *
1599
     * @return int number of dates in attendance calendar
1600
     */
1601
    public static function get_number_of_attendance_calendar(
1602
        $attendanceId,
1603
        $groupId = 0,
1604
        $done_attendance = null,
1605
        $userId = 0
1606
    ) {
1607
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1608
        $calendarRelGroup = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1609
        $tbl_groupRelUser = Database::get_course_table(TABLE_GROUP_USER);
1610
        $attendanceId = intval($attendanceId);
1611
        $groupId = intval($groupId);
1612
        $course_id = api_get_course_int_id();
1613
1614
        $where_attendance = '';
1615
        if ($done_attendance) {
1616
            $where_attendance = ' done_attendance = 1 AND ';
1617
        }
1618
        if (empty($userId)) {
1619
            if (empty($groupId)) {
1620
                $sql = "SELECT count(a.id)
1621
                        FROM $tbl_attendance_calendar a
1622
                        WHERE
1623
                            c_id = $course_id AND
1624
                            $where_attendance
1625
                            attendance_id = '$attendanceId' AND
1626
                            id NOT IN (
1627
                                SELECT calendar_id FROM $calendarRelGroup
1628
                                WHERE
1629
                                    c_id = $course_id AND
1630
                                    group_id != 0 AND
1631
                                    group_id IS NOT NULL
1632
                            )
1633
                        ";
1634
            } else {
1635
                $sql = "SELECT count(a.id)
1636
                        FROM $tbl_attendance_calendar a
1637
                        INNER JOIN $calendarRelGroup g
1638
                        ON (a.id = g.calendar_id AND a.c_id = g.c_id)
1639
                        WHERE
1640
                            a.c_id = $course_id AND
1641
                            $where_attendance
1642
                            attendance_id = '$attendanceId' AND
1643
                            group_id = $groupId
1644
                        ";
1645
            }
1646
        } else {
1647
            if (empty($groupId)) {
1648
                $sql = "SELECT count(a.id)
1649
                        FROM $tbl_attendance_calendar a
1650
                        WHERE
1651
                            c_id = $course_id AND
1652
                            $where_attendance
1653
                            attendance_id = '$attendanceId' AND
1654
                            id NOT IN (
1655
                                SELECT calendar_id FROM $calendarRelGroup
1656
                                WHERE
1657
                                    c_id = $course_id AND
1658
                                    group_id != 0 AND
1659
                                    group_id IS NOT NULL AND
1660
                                    group_id NOT IN (
1661
                                        SELECT group_id
1662
                                        FROM $tbl_groupRelUser
1663
                                        WHERE user_id = $userId
1664
                                    )
1665
                            )
1666
                        ";
1667
            } else {
1668
                $sql = "SELECT count(a.id)
1669
                        FROM $tbl_attendance_calendar a
1670
                        INNER JOIN $calendarRelGroup g
1671
                        ON (a.id = g.calendar_id AND a.c_id = g.c_id)
1672
                        WHERE
1673
                            a.c_id = $course_id AND
1674
                            $where_attendance
1675
                            attendance_id = '$attendanceId' AND
1676
                            group_id = $groupId
1677
                        ";
1678
            }
1679
        }
1680
1681
        $rs = Database::query($sql);
1682
        $row = Database::fetch_row($rs);
1683
        $count = $row[0];
1684
1685
        return $count;
1686
    }
1687
1688
    /**
1689
     * Get count dates inside attendance calendar by attendance id.
1690
     *
1691
     * @param int $attendanceId
1692
     *
1693
     * @return int count of dates
1694
     */
1695
    public static function get_count_dates_inside_attendance_calendar($attendanceId)
1696
    {
1697
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1698
        $attendanceId = intval($attendanceId);
1699
        $course_id = api_get_course_int_id();
1700
        $sql = "SELECT count(id) FROM $tbl_attendance_calendar
1701
                WHERE
1702
                    c_id = $course_id AND
1703
                    attendance_id = '$attendanceId'";
1704
        $rs = Database::query($sql);
1705
        $count = 0;
1706
        if (Database::num_rows($rs) > 0) {
1707
            $row = Database::fetch_row($rs);
1708
            $count = $row[0];
1709
        }
1710
1711
        return $count;
1712
    }
1713
1714
    /**
1715
     * check if all calendar of an attendance is done.
1716
     *
1717
     * @param int $attendanceId
1718
     *
1719
     * @return bool True if all calendar is done, otherwise false
1720
     */
1721
    public static function is_all_attendance_calendar_done($attendanceId)
1722
    {
1723
        $attendanceId = (int) $attendanceId;
1724
        $done_calendar = self::get_done_attendance_calendar($attendanceId);
1725
        $count_dates_in_calendar = self::get_count_dates_inside_attendance_calendar($attendanceId);
1726
        $number_of_dates = self::get_number_of_attendance_calendar($attendanceId);
1727
1728
        $result = false;
1729
        if ($number_of_dates && intval($count_dates_in_calendar) == intval($done_calendar)) {
1730
            $result = true;
1731
        }
1732
1733
        return $result;
1734
    }
1735
1736
    /**
1737
     * check if an attendance is locked.
1738
     *
1739
     * @param int $attendanceId
1740
     * @param bool
1741
     *
1742
     * @return bool
1743
     */
1744
    public static function is_locked_attendance($attendanceId)
1745
    {
1746
        //  Use gradebook lock
1747
        $result = api_resource_is_locked_by_gradebook($attendanceId, LINK_ATTENDANCE);
1748
1749
        return $result;
1750
    }
1751
1752
    /**
1753
     * Add new datetime inside attendance calendar table.
1754
     *
1755
     * @param int   $attendanceId
1756
     * @param array $groupList
1757
     * @param array $extraValues
1758
     *
1759
     * @return int affected rows
1760
     */
1761
    public function attendance_calendar_add($attendanceId, $groupList = [], $extraValues = [])
1762
    {
1763
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1764
        $affected_rows = 0;
1765
        $attendanceId = intval($attendanceId);
1766
        $course_id = api_get_course_int_id();
1767
        // check if datetime already exists inside the table
1768
        /*$sql = "SELECT id FROM $tbl_attendance_calendar
1769
                WHERE
1770
                    c_id = $course_id AND
1771
                    date_time='".Database::escape_string($this->date_time)."' AND
1772
                    attendance_id = '$attendanceId'";
1773
        $rs = Database::query($sql);
1774
        if (Database::num_rows($rs) == 0) {*/
1775
        $params = [
1776
            'c_id' => $course_id,
1777
            'date_time' => $this->date_time,
1778
            'attendance_id' => $attendanceId,
1779
            'done_attendance' => 0,
1780
        ];
1781
        $id = Database::insert($tbl_attendance_calendar, $params);
1782
1783
        if ($id) {
1784
            $sql = "UPDATE $tbl_attendance_calendar SET id = iid WHERE iid = $id";
1785
            Database::query($sql);
1786
            $affected_rows++;
1787
1788
            if (!empty($extraValues)) {
1789
                // It saves extra fields values
1790
                $extraFieldValue = new ExtraFieldValue('attendance_calendar');
1791
                $extraValues['item_id'] = $id;
1792
                $extraFieldValue->saveFieldValues($extraValues);
1793
            }
1794
        }
1795
        $this->addAttendanceCalendarToGroup($id, $course_id, $groupList);
1796
        //}
1797
1798
        // update locked attendance
1799
        $is_all_calendar_done = self::is_all_attendance_calendar_done($attendanceId);
1800
        if (!$is_all_calendar_done) {
1801
            self::lock_attendance($attendanceId, false);
1802
        } else {
1803
            self::lock_attendance($attendanceId);
1804
        }
1805
1806
        return $affected_rows;
1807
    }
1808
1809
    /**
1810
     * @param int   $calendarId
1811
     * @param int   $courseId
1812
     * @param array $groupList
1813
     *
1814
     * @return bool
1815
     */
1816
    public function addAttendanceCalendarToGroup($calendarId, $courseId, $groupList)
1817
    {
1818
        if (empty($groupList)) {
1819
            return false;
1820
        }
1821
1822
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1823
        foreach ($groupList as $groupId) {
1824
            if (empty($groupId)) {
1825
                continue;
1826
            }
1827
1828
            $result = $this->getAttendanceCalendarGroup(
1829
                $calendarId,
1830
                $courseId,
1831
                $groupId
1832
            );
1833
1834
            if (empty($result)) {
1835
                $params = [
1836
                    'calendar_id' => $calendarId,
1837
                    'c_id' => $courseId,
1838
                    'group_id' => $groupId,
1839
                ];
1840
                Database::insert($table, $params);
1841
            }
1842
        }
1843
1844
        return true;
1845
    }
1846
1847
    /**
1848
     * @param int $calendarId
1849
     * @param int $courseId
1850
     *
1851
     * @return array
1852
     */
1853
    public function getGroupListByAttendanceCalendar($calendarId, $courseId)
1854
    {
1855
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1856
1857
        return Database::select(
1858
            '*',
1859
            $table,
1860
            [
1861
                'where' => [
1862
                    'calendar_id = ? AND c_id = ?' => [$calendarId, $courseId],
1863
                ],
1864
            ]
1865
        );
1866
    }
1867
1868
    /**
1869
     * @param int $calendarId
1870
     * @param int $courseId
1871
     * @param int $groupId
1872
     *
1873
     * @return array
1874
     */
1875
    public function getAttendanceCalendarGroup($calendarId, $courseId, $groupId)
1876
    {
1877
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1878
1879
        return Database::select(
1880
            '*',
1881
            $table,
1882
            [
1883
                'where' => [
1884
                    'calendar_id = ? AND c_id = ? AND group_id = ?' => [$calendarId, $courseId, $groupId],
1885
                ],
1886
            ]
1887
        );
1888
    }
1889
1890
    /**
1891
     * @param int $calendarId
1892
     * @param int $courseId
1893
     */
1894
    public function deleteAttendanceCalendarGroup($calendarId, $courseId)
1895
    {
1896
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1897
        Database::delete(
1898
            $table,
1899
            [
1900
                'calendar_id = ? AND c_id = ?' => [$calendarId, $courseId],
1901
            ]
1902
        );
1903
    }
1904
1905
    /**
1906
     * save repeated date inside attendance calendar table.
1907
     *
1908
     * @param int    $attendanceId
1909
     * @param int    $start_date   start date in tms
1910
     * @param int    $end_date     end date in tms
1911
     * @param string $repeat_type  daily, weekly, biweekly, xdays, monthlyByDate
1912
     * @param array  $groupList
1913
     */
1914
    public function attendance_repeat_calendar_add(
1915
        $attendanceId,
1916
        $start_date,
1917
        $end_date,
1918
        $repeat_type,
1919
        $groupList = [],
1920
        $extraValues = []
1921
    ) {
1922
        $attendanceId = intval($attendanceId);
1923
        // save start date
1924
        $datetimezone = api_get_utc_datetime($start_date);
1925
        $this->set_date_time($datetimezone);
1926
        $this->attendance_calendar_add($attendanceId, $groupList, $extraValues);
1927
1928
        // 86400 = 24 hours in seconds
1929
        // 604800 = 1 week in seconds
1930
        // 1296000 = 2 weeks in seconds
1931
        // 2419200 = 1 month in seconds
1932
        // 86400 x xdays = interval by x days (in seconds)
1933
        // Saves repeated dates
1934
        $seconds = 0;
1935
        switch ($repeat_type) {
1936
            case 'daily':
1937
                $seconds = 86400;
1938
                break;
1939
            case 'weekly':
1940
                $seconds = 604800;
1941
                break;
1942
            case 'biweekly':
1943
                $seconds = 1296000;
1944
                break;
1945
            case 'monthlyByDate':
1946
                $seconds = 2419200;
1947
                break;
1948
            case 'xdays':
1949
                $seconds = isset($extraValues['xdays_number']) ? (int) $extraValues['xdays_number'] * 86400 : 0;
1950
                break;
1951
        }
1952
1953
        if ($seconds > 0) {
1954
            $j = 1;
1955
            for ($i = $start_date + $seconds; ($i <= $end_date); $i += $seconds) {
1956
                $datetimezone = api_get_utc_datetime($i);
1957
                $this->set_date_time($datetimezone);
1958
                $this->attendance_calendar_add($attendanceId, $groupList, $extraValues);
1959
                $j++;
1960
            }
1961
        }
1962
    }
1963
1964
    /**
1965
     * Gets the value of a attendance calendar extra field. Returns null if it was not found.
1966
     *
1967
     * @param string $variable   Name of the extra field
1968
     * @param string $calendarId Calendar id
1969
     *
1970
     * @return string Value
1971
     */
1972
    public static function getAttendanceCalendarExtraFieldValue($variable, $calendarId)
1973
    {
1974
        if (true !== api_get_configuration_value('attendance_calendar_set_duration')) {
1975
            return false;
1976
        }
1977
1978
        $extraFieldValues = new ExtraFieldValue('attendance_calendar');
1979
        $result = $extraFieldValues->get_values_by_handler_and_field_variable($calendarId, $variable);
1980
        if (!empty($result['value'])) {
1981
            return $result['value'];
1982
        }
1983
1984
        return null;
1985
    }
1986
1987
    /**
1988
     * edit a datetime inside attendance calendar table.
1989
     *
1990
     * @param int	attendance calendar id
1991
     * @param int	attendance id
1992
     * @param array extra values
1993
     *
1994
     * @return int affected rows
1995
     */
1996
    public function attendance_calendar_edit($calendar_id, $attendanceId, $extraValues = [])
1997
    {
1998
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1999
        $affected_rows = 0;
2000
        $attendanceId = intval($attendanceId);
2001
        $course_id = api_get_course_int_id();
2002
        // check if datetime already exists inside the table
2003
        $sql = "SELECT id FROM $tbl_attendance_calendar
2004
                WHERE
2005
                    c_id = $course_id AND
2006
                    date_time = '".Database::escape_string($this->date_time)."' AND
2007
                    attendance_id = '$attendanceId'";
2008
        $rs = Database::query($sql);
2009
2010
        if (Database::num_rows($rs) == 0) {
2011
            $sql = "UPDATE $tbl_attendance_calendar
2012
                    SET date_time='".Database::escape_string($this->date_time)."'
2013
                    WHERE c_id = $course_id AND id = '".intval($calendar_id)."'";
2014
            Database::query($sql);
2015
        }
2016
2017
        // It saves extra fields values
2018
        $extraFieldValue = new ExtraFieldValue('attendance_calendar');
2019
        $extraValues['item_id'] = $calendar_id;
2020
        $extraFieldValue->saveFieldValues($extraValues);
2021
2022
        // update locked attendance
2023
        $is_all_calendar_done = self::is_all_attendance_calendar_done($attendanceId);
2024
        if (!$is_all_calendar_done) {
2025
            self::lock_attendance($attendanceId, false);
2026
        } else {
2027
            self::lock_attendance($attendanceId);
2028
        }
2029
2030
        return $affected_rows;
2031
    }
2032
2033
    /**
2034
     * delete a datetime from attendance calendar table.
2035
     *
2036
     * @param	int		attendance calendar id
2037
     * @param	int		attendance id
2038
     * @param	bool true for removing all calendar inside current attendance, false for removing by calendar id
2039
     *
2040
     * @return int affected rows
2041
     */
2042
    public function attendance_calendar_delete(
2043
        $calendar_id,
2044
        $attendanceId,
2045
        $all_delete = false
2046
    ) {
2047
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
2048
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
2049
2050
        $attendanceId = intval($attendanceId);
2051
        $calendar_id = (int) $calendar_id;
2052
2053
        // get all registered users inside current course
2054
        $users = $this->get_users_rel_course();
2055
        $user_ids = array_keys($users);
2056
        $course_id = api_get_course_int_id();
2057
        $affected_rows = 0;
2058
        if ($all_delete) {
2059
            $attendance_calendar = $this->get_attendance_calendar($attendanceId);
2060
            // get all dates from calendar by current attendance
2061
            if (!empty($attendance_calendar)) {
2062
                foreach ($attendance_calendar as $cal) {
2063
                    // delete all data from attendance sheet
2064
                    $sql = "DELETE FROM $tbl_attendance_sheet
2065
                            WHERE c_id = $course_id AND attendance_calendar_id = '".intval($cal['id'])."'";
2066
                    Database::query($sql);
2067
                    // delete data from attendance calendar
2068
                    $sql = "DELETE FROM $tbl_attendance_calendar
2069
                            WHERE c_id = $course_id AND id = '".intval($cal['id'])."'";
2070
                    Database::query($sql);
2071
2072
                    $this->deleteAttendanceCalendarGroup($cal['id'], $course_id);
2073
                    $affected_rows++;
2074
                }
2075
            }
2076
        } else {
2077
            // delete just one row from attendance sheet by the calendar id
2078
            $sql = "DELETE FROM $tbl_attendance_sheet
2079
                    WHERE c_id = $course_id AND attendance_calendar_id = '".$calendar_id."'";
2080
            Database::query($sql);
2081
            // delete data from attendance calendar
2082
            $sql = "DELETE FROM $tbl_attendance_calendar
2083
                    WHERE c_id = $course_id AND id = '".$calendar_id."'";
2084
            Database::query($sql);
2085
2086
            $this->deleteAttendanceCalendarGroup($calendar_id, $course_id);
2087
            $affected_rows++;
2088
        }
2089
2090
        // update users' results
2091
        $this->updateUsersResults($user_ids, $attendanceId);
2092
2093
        return $affected_rows;
2094
    }
2095
2096
    public function set_session_id($sessionId)
2097
    {
2098
        $this->session_id = $sessionId;
2099
    }
2100
2101
    public function set_course_id($course_id)
2102
    {
2103
        $this->course_id = $course_id;
2104
    }
2105
2106
    public function set_date_time($datetime)
2107
    {
2108
        $this->date_time = $datetime;
2109
    }
2110
2111
    public function set_name($name)
2112
    {
2113
        $this->name = $name;
2114
    }
2115
2116
    public function set_description($description)
2117
    {
2118
        $this->description = $description;
2119
    }
2120
2121
    public function set_attendance_qualify_title($attendance_qualify_title)
2122
    {
2123
        $this->attendance_qualify_title = $attendance_qualify_title;
2124
    }
2125
2126
    public function set_attendance_weight($attendance_weight)
2127
    {
2128
        $this->attendance_weight = $attendance_weight;
2129
    }
2130
2131
    /** Getters for fields of attendances tables */
2132
    public function get_session_id()
2133
    {
2134
        return $this->session_id;
2135
    }
2136
2137
    public function get_course_id()
2138
    {
2139
        return $this->course_id;
2140
    }
2141
2142
    public function get_date_time()
2143
    {
2144
        return $this->date_time;
2145
    }
2146
2147
    public function get_name()
2148
    {
2149
        return $this->name;
2150
    }
2151
2152
    public function get_description()
2153
    {
2154
        return $this->description;
2155
    }
2156
2157
    public function get_attendance_qualify_title()
2158
    {
2159
        return $this->attendance_qualify_title;
2160
    }
2161
2162
    public function get_attendance_weight()
2163
    {
2164
        return $this->attendance_weight;
2165
    }
2166
2167
    /**
2168
     * @param string $startDate in UTC time
2169
     * @param string $endDate   in UTC time
2170
     *
2171
     * @return array
2172
     */
2173
    public function getAttendanceLogin($startDate, $endDate)
2174
    {
2175
        if (empty($startDate) ||
2176
            $startDate == '0000-00-00' ||
2177
            $startDate == '0000-00-00 00:00:00' ||
2178
            empty($endDate) ||
2179
            $endDate == '0000-00-00' ||
2180
            $endDate == '0000-00-00 00:00:00'
2181
        ) {
2182
            return false;
2183
        }
2184
2185
        $sessionId = api_get_session_id();
2186
        $courseCode = api_get_course_id();
2187
        $courseId = api_get_course_int_id();
2188
2189
        if (!empty($sessionId)) {
2190
            $users = CourseManager::get_user_list_from_course_code(
2191
                $courseCode,
2192
                $sessionId,
2193
                '',
2194
                'lastname',
2195
                0
2196
            );
2197
        } else {
2198
            $users = CourseManager::get_user_list_from_course_code(
2199
                $courseCode,
2200
                0,
2201
                '',
2202
                'lastname',
2203
                STUDENT
2204
            );
2205
        }
2206
2207
        $dateTimeStartOriginal = new DateTime($startDate);
2208
        $dateTimeStart = new DateTime($startDate);
2209
        $dateTimeEnd = new DateTime($endDate);
2210
        $interval = $dateTimeStart->diff($dateTimeEnd);
2211
        $days = intval($interval->format('%a'));
2212
2213
        $dateList = [$dateTimeStart->format('Y-m-d')];
2214
        $headers = [
2215
            get_lang('User'),
2216
            $dateTimeStart->format('Y-m-d'),
2217
        ];
2218
2219
        for ($i = 0; $i < $days; $i++) {
2220
            $dateTimeStart = $dateTimeStart->add(new DateInterval('P1D'));
2221
            $date = $dateTimeStart->format('Y-m-d');
2222
            $dateList[] = $date;
2223
            $headers[] = $date;
2224
        }
2225
2226
        $accessData = CourseManager::getCourseAccessPerCourseAndSession(
2227
            $courseId,
2228
            $sessionId,
2229
            $dateTimeStartOriginal->format('Y-m-d H:i:s'),
2230
            $dateTimeEnd->format('Y-m-d H:i:s')
2231
        );
2232
2233
        $results = [];
2234
        if (!empty($accessData)) {
2235
            foreach ($accessData as $data) {
2236
                $onlyDate = substr($data['login_course_date'], 0, 10);
2237
                $results[$data['user_id']][$onlyDate] = true;
2238
            }
2239
        }
2240
2241
        return [
2242
            'users' => $users,
2243
            'dateList' => $dateList,
2244
            'headers' => $headers,
2245
            'results' => $results,
2246
        ];
2247
    }
2248
2249
    /**
2250
     * @param string $startDate in UTC time
2251
     * @param string $endDate   in UTC time
2252
     *
2253
     * @return string
2254
     */
2255
    public function getAttendanceLoginTable($startDate, $endDate)
2256
    {
2257
        $data = $this->getAttendanceLogin($startDate, $endDate);
2258
        if (!$data) {
2259
            return null;
2260
        }
2261
2262
        $headers = $data['headers'];
2263
        $dateList = $data['dateList'];
2264
        $users = $data['users'];
2265
        $results = $data['results'];
2266
2267
        $table = new HTML_Table(['class' => 'table table-hover table-striped data_table']);
2268
        $row = 0;
2269
        $column = 0;
2270
        foreach ($headers as $header) {
2271
            $table->setHeaderContents($row, $column, $header);
2272
            $column++;
2273
        }
2274
        $row = 1;
2275
        foreach ($users as $user) {
2276
            $table->setCellContents(
2277
                $row,
2278
                0,
2279
                $user['lastname'].' '.$user['firstname'].' ('.$user['username'].')'
2280
            );
2281
            $row++;
2282
        }
2283
2284
        $column = 1;
2285
        $row = 1;
2286
        foreach ($users as $user) {
2287
            foreach ($dateList as $date) {
2288
                $status = null;
2289
                if (isset($results[$user['user_id']]) &&
2290
                    isset($results[$user['user_id']][$date])
2291
                ) {
2292
                    $status = 'X';
2293
                }
2294
                $table->setCellContents($row, $column, $status);
2295
                $column++;
2296
            }
2297
            $row++;
2298
            $column = 1;
2299
        }
2300
2301
        return $table->toHtml();
2302
    }
2303
2304
    /**
2305
     * @param string $startDate in UTC time
2306
     * @param string $endDate   in UTC time
2307
     *
2308
     * @return string
2309
     */
2310
    public function exportAttendanceLogin($startDate, $endDate)
2311
    {
2312
        $data = $this->getAttendanceLogin($startDate, $endDate);
2313
2314
        if (!$data) {
2315
            return null;
2316
        }
2317
        $users = $data['users'];
2318
        $results = $data['results'];
2319
2320
        $table = new HTML_Table(['class' => 'table table-hover table-striped data_table']);
2321
        $table->setHeaderContents(0, 0, get_lang('User'));
2322
        $table->setHeaderContents(0, 1, get_lang('Date'));
2323
2324
        $row = 1;
2325
        foreach ($users as $user) {
2326
            $table->setCellContents(
2327
                $row,
2328
                0,
2329
                $user['lastname'].' '.$user['firstname'].' ('.$user['username'].')'
2330
            );
2331
            $row++;
2332
        }
2333
        $table->setColAttributes(0, ['style' => 'width:28%']);
2334
2335
        $row = 1;
2336
        foreach ($users as $user) {
2337
            if (isset($results[$user['user_id']]) &&
2338
                !empty($results[$user['user_id']])
2339
            ) {
2340
                $dates = implode(', ', array_keys($results[$user['user_id']]));
2341
                $table->setCellContents($row, 1, $dates);
2342
            }
2343
            $row++;
2344
        }
2345
2346
        $tableToString = $table->toHtml();
2347
        $params = [
2348
            'filename' => get_lang('Attendance').'_'.api_get_utc_datetime(),
2349
            'pdf_title' => get_lang('Attendance'),
2350
            'course_code' => api_get_course_id(),
2351
            'show_real_course_teachers' => true,
2352
        ];
2353
        $pdf = new PDF('A4', null, $params);
2354
        $pdf->html_to_pdf_with_template($tableToString);
2355
    }
2356
2357
    /**
2358
     * Return all course for a student between dates and order by key date (Y-m-d).
2359
     *
2360
     * @param int       $studentId
2361
     * @param \DateTime $startDate
2362
     * @param \DateTime $endDate
2363
     * @param bool      $orderDesc
2364
     *
2365
     * @return array
2366
     */
2367
    public function getCoursesWithAttendance(
2368
        $studentId = 0,
2369
        DateTime $startDate = null,
2370
        DateTime $endDate = null,
2371
        $orderDesc = false
2372
    ) {
2373
        // Lang variables
2374
        $presentString = get_lang('Present');
2375
        //$absentString = get_lang('Absent');
2376
        $absentString = '-';
2377
        // Lang variables
2378
        $attendanceLib = new Attendance();
2379
        $data = [];
2380
        /*
2381
         $specialCourses = CourseManager::returnSpecialCourses(
2382
            $studentId, false, false
2383
        );
2384
         */
2385
        $courses = CourseManager::returnCourses(
2386
            $studentId,
2387
            false,
2388
            false
2389
        );
2390
        /* Get course with (in_category) and without (not_category) category */
2391
        foreach ($courses as $courseData) {
2392
            /*
2393
             * $coursesKey can be in_category or not_category for courses
2394
             * */
2395
            $totalCoursesNoCategory = count($courseData);
2396
            for ($i = 0; $i < $totalCoursesNoCategory; $i++) {
2397
                $courseItem = $courseData[$i];
2398
                $courseId = $courseItem['course_id'];
2399
2400
                /* Get all attendance by courses*/
2401
                $attenances = $attendanceLib->get_attendances_list($courseId);
2402
                $temp = [];
2403
                $sheetsProccessed = [];
2404
                $tempDate = [];
2405
                foreach ($attenances as $attendanceData) {
2406
                    $attendanceId = $attendanceData['id'];
2407
                    $sheets = $attendanceLib->get_users_attendance_sheet(
2408
                        $attendanceId,
2409
                        $studentId,
2410
                        0,
2411
                        $courseId,
2412
                        $startDate,
2413
                        $endDate
2414
                    );
2415
2416
                    $sheetsProccessed[] = [];
2417
                    foreach ($sheets as $sheetData) {
2418
                        $totalb = count($sheetData);
2419
                        $tempDate = [];
2420
                        for ($ii = 0; $ii < $totalb; $ii++) {
2421
                            $attendancesProccess = $sheetData[$ii];
2422
                            if (!empty($attendancesProccess)) {
2423
                                $dateTemp = $attendancesProccess['0'];
2424
                                $attendancesProccess[0] = $attendancesProccess[1];
2425
                                $attendancesProccess[1] = $dateTemp;
2426
2427
                                $attendancesProccess[2] = $courseItem['title'];
2428
                                $attendancesProccess['courseTitle'] = $courseItem['title'];
2429
2430
                                $attendancesProccess[3] = $courseItem['real_id'];
2431
                                $attendancesProccess['courseId'] = $courseItem['real_id'];
2432
2433
                                $attendancesProccess[4] = $attendanceData['name'];
2434
                                $attendancesProccess['attendanceName'] = $attendanceData['name'];
2435
                                $attendancesProccess['courseCode'] = $courseItem['course_code'];
2436
2437
                                $attendancesProccess[5] = $attendanceData['id'];
2438
                                $attendancesProccess['attendanceId'] = $attendanceData['id'];
2439
                                if ($attendancesProccess['presence'] == 1) {
2440
                                    $attendancesProccess['presence'] = $presentString;
2441
                                    $attendancesProccess[0] = 1;
2442
                                } else {
2443
                                    $attendancesProccess['presence'] = $absentString;
2444
                                    $attendancesProccess[0] = 0;
2445
                                }
2446
                                $attendancesProccess['session'] = 0;
2447
                                $attendancesProccess['sessionName'] = '';
2448
                                $tempDate[] = $attendancesProccess;
2449
                                $dateKey = new DateTime($dateTemp);
2450
                                /*
2451
                                $attendancesProccess['teacher'] = '';
2452
                                if(isset($courseItem['teachers']) and isset($courseItem['teachers'][0])){
2453
                                    $attendancesProccess['teacher'] = $courseItem['teachers'][0]['fullname'];
2454
                                }
2455
                                */
2456
                                $data[$dateKey->format('Y-m-d')][] = $attendancesProccess;
2457
                            }
2458
                        }
2459
                    }
2460
                    $sheetsProccessed[] = $tempDate;
2461
                    $temp[] = $sheetsProccessed;
2462
                }
2463
                $courses['not_category'][$i]['attendanceSheet'] = $temp;
2464
            }
2465
        }
2466
2467
        /* Sessions */
2468
        $studentId = (int) $studentId;
2469
        $sql = "
2470
            SELECT
2471
                session_id,
2472
                c_id
2473
            FROM
2474
                session_rel_course_rel_user
2475
            WHERE
2476
                user_id = $studentId";
2477
2478
        $rs = Database::query($sql);
2479
        // get info from sessions
2480
        while ($row = Database::fetch_array($rs, 'ASSOC')) {
2481
            $courseId = $row['c_id'];
2482
            $sessionId = $row['session_id'];
2483
            $courseItem = api_get_course_info_by_id($courseId);
2484
2485
            $attenances = $attendanceLib->get_attendances_list(
2486
                $courseId,
2487
                $sessionId
2488
            );
2489
            $temp = [];
2490
            $sheetsProccessed = [];
2491
            $tempDate = [];
2492
            foreach ($attenances as $attendanceData) {
2493
                $attendanceId = $attendanceData['id'];
2494
                $sheets = $attendanceLib->get_users_attendance_sheet(
2495
                    $attendanceId,
2496
                    $studentId,
2497
                    0,
2498
                    $courseId,
2499
                    $startDate,
2500
                    $endDate
2501
                );
2502
2503
                $sheetsProccessed[] = [];
2504
                foreach ($sheets as $sheetData) {
2505
                    $totalb = count($sheetData);
2506
                    $tempDate = [];
2507
                    for ($ii = 0; $ii < $totalb; $ii++) {
2508
                        $work = $sheetData[$ii];
2509
                        $attendancesProccess = $work;
2510
                        if (!empty($attendancesProccess)) {
2511
                            $dateTemp = $attendancesProccess['0'];
2512
                            $attendancesProccess[0] = $attendancesProccess[1];
2513
                            $attendancesProccess[1] = $dateTemp;
2514
                            $attendancesProccess[2] = $courseItem['title'];
2515
                            $attendancesProccess['courseTitle'] = $courseItem['title'];
2516
                            $attendancesProccess[3] = $courseItem['real_id'];
2517
                            $attendancesProccess['courseId'] = $courseItem['real_id'];
2518
                            $attendancesProccess[4] = $attendanceData['name'];
2519
                            $attendancesProccess['attendanceName'] = $attendanceData['name'];
2520
                            $attendancesProccess[5] = $attendanceData['id'];
2521
                            $attendancesProccess['attendanceId'] = $attendanceData['id'];
2522
                            $attendancesProccess['courseCode'] = $courseItem['official_code'];
2523
                            if ($attendancesProccess['presence'] == 1) {
2524
                                $attendancesProccess['presence'] = $presentString;
2525
                                $attendancesProccess[0] = 1;
2526
                            } else {
2527
                                $attendancesProccess['presence'] = $absentString;
2528
                                $attendancesProccess[0] = 0;
2529
                            }
2530
                            $attendancesProccess['session'] = $sessionId;
2531
                            $attendancesProccess['sessionName'] = api_get_session_name($sessionId);
2532
2533
                            $tempDate[] = $attendancesProccess;
2534
                            $dateKey = new DateTime($dateTemp);
2535
                            /*
2536
                            $attendancesProccess['teacher'] = '';
2537
                            if(isset($courseItem['tutor_name']) ){
2538
                                $attendancesProccess['teacher'] = $courseItem['tutor_name'];
2539
                            }
2540
                            */
2541
                            $data[$dateKey->format('Y-m-d')][] = $attendancesProccess;
2542
                        }
2543
                    }
2544
                }
2545
                $sheetsProccessed[] = $tempDate;
2546
                $temp[] = $sheetsProccessed;
2547
            }
2548
            $courses['session'][$i]['attendanceSheet'] = $temp;
2549
        }
2550
2551
        /* Order desc by date,  by default */
2552
        if ($orderDesc == true) {
2553
            ksort($data);
2554
        } else {
2555
            krsort($data);
2556
        }
2557
2558
        return $data;
2559
    }
2560
2561
    /**
2562
     * Clean a sing of a user in attendance sheet.
2563
     *
2564
     * @param $userId
2565
     * @param $attendanceCalendarId
2566
     *
2567
     * @return false or void when it is deleted.
2568
     */
2569
    public function deleteSignature(
2570
        $userId,
2571
        $attendanceCalendarId,
2572
        $attendanceId
2573
    ) {
2574
        $allowSignature = api_get_configuration_value('enable_sign_attendance_sheet');
2575
        if (!$allowSignature) {
2576
            return false;
2577
        }
2578
2579
        $courseId = api_get_course_int_id();
2580
        $em = Database::getManager();
2581
        $criteria = [
2582
            'userId' => $userId,
2583
            'attendanceCalendarId' => $attendanceCalendarId,
2584
            'cId' => $courseId,
2585
        ];
2586
2587
        $repo = $em->getRepository('ChamiloCourseBundle:CAttendanceSheet');
2588
        $attendanceSheet = $repo->findOneBy($criteria);
2589
2590
        if ($attendanceSheet) {
2591
            /** @var CAttendanceSheet $attendanceSheet */
2592
            $attendanceSheet->setPresence(0);
2593
            $attendanceSheet->setSignature('');
2594
2595
            $em->persist($attendanceSheet);
2596
            $em->flush();
2597
            $this->updateUsersResults([$userId], $attendanceId);
2598
        }
2599
    }
2600
2601
    /**
2602
     * It checks if the calendar in a attendance sheet is blocked.
2603
     *
2604
     * @param $calendarId
2605
     *
2606
     * @return bool
2607
     */
2608
    public function isCalendarBlocked($calendarId)
2609
    {
2610
        $em = Database::getManager();
2611
        $repo = $em->getRepository('ChamiloCourseBundle:CAttendanceCalendar');
2612
2613
        $blocked = 0;
2614
        $attendanceCalendar = $repo->find($calendarId);
2615
        /** @var CAttendanceCalendar $attendanceCalendar */
2616
        if ($attendanceCalendar) {
2617
            $blocked = (int) $attendanceCalendar->getBlocked();
2618
        }
2619
2620
        $isBlocked = (1 === $blocked);
2621
2622
        return $isBlocked;
2623
    }
2624
2625
    /**
2626
     * It blocks/unblocks the calendar in attendance sheet.
2627
     *
2628
     * @param $calendarId
2629
     *
2630
     * @throws \Doctrine\ORM\ORMException
2631
     * @throws \Doctrine\ORM\OptimisticLockException
2632
     */
2633
    public function updateCalendarBlocked($calendarId)
2634
    {
2635
        $em = Database::getManager();
2636
        $repo = $em->getRepository('ChamiloCourseBundle:CAttendanceCalendar');
2637
        $attendanceCalendar = $repo->find($calendarId);
2638
2639
        /** @var CAttendanceCalendar $attendanceCalendar */
2640
        if ($attendanceCalendar) {
2641
            $blocked = !$this->isCalendarBlocked($calendarId);
2642
            $attendanceCalendar->setBlocked($blocked);
2643
            $em->persist($attendanceCalendar);
2644
            $em->flush();
2645
        }
2646
    }
2647
2648
    /**
2649
     * Get the user sign in attendance sheet.
2650
     *
2651
     * @param $userId
2652
     * @param $attendanceCalendarId
2653
     *
2654
     * @return false|string
2655
     */
2656
    public function getSignature(
2657
        $userId,
2658
        $attendanceCalendarId
2659
    ) {
2660
        $allowSignature = api_get_configuration_value('enable_sign_attendance_sheet');
2661
        if (!$allowSignature) {
2662
            return false;
2663
        }
2664
2665
        $courseId = api_get_course_int_id();
2666
        $em = Database::getManager();
2667
        $repo = $em->getRepository('ChamiloCourseBundle:CAttendanceSheet');
2668
2669
        $criteria = [
2670
            'userId' => $userId,
2671
            'attendanceCalendarId' => $attendanceCalendarId,
2672
            'cId' => $courseId,
2673
        ];
2674
        $attendanceSheet = $repo->findOneBy($criteria);
2675
2676
        $signature = "";
2677
        if ($attendanceSheet) {
2678
            /** @var CAttendanceSheet $attendanceSheet */
2679
            $signature = $attendanceSheet->getSignature();
2680
        }
2681
2682
        return $signature;
2683
    }
2684
2685
    /**
2686
     * Exports the attendance sheet to Xls format.
2687
     */
2688
    public function exportAttendanceSheetToXls(
2689
        int $attendanceId,
2690
        int $studentId,
2691
        string $courseCode,
2692
        int $groupId,
2693
        string $filterType,
2694
        ?int $myCalendarId
2695
    ) {
2696
        $users = $this->get_users_rel_course($attendanceId, $groupId);
2697
        $calendar = $this->get_attendance_calendar(
2698
            $attendanceId,
2699
            $filterType,
2700
            $myCalendarId,
2701
            $groupId
2702
        );
2703
2704
        if (!empty($studentId)) {
2705
            $userId = $studentId;
2706
        } else {
2707
            $userId = api_get_user_id();
2708
        }
2709
        $courseInfo = api_get_course_info($courseCode);
2710
2711
        $userPresence = [];
2712
        if (api_is_allowed_to_edit(null, true) || api_is_drh()) {
2713
            $userPresence = $this->get_users_attendance_sheet($attendanceId, 0, $groupId);
2714
        } else {
2715
            $userPresence = $this->get_users_attendance_sheet($attendanceId, $userId, $groupId);
2716
        }
2717
2718
        // Set headers pdf.
2719
        $teacherInfo = CourseManager::get_teacher_list_from_course_code($courseInfo['code']);
2720
        $teacherName = null;
2721
        foreach ($teacherInfo as $teacherData) {
2722
            if ($teacherName != null) {
2723
                $teacherName = $teacherName." / ";
2724
            }
2725
            $teacherName .= api_get_person_name($teacherData['firstname'], $teacherData['lastname']);
2726
        }
2727
2728
        // Get data table
2729
        $dataTable = [];
2730
        $addOfficialCode = api_get_configuration_value('attendance_add_official_code');
2731
        if ($addOfficialCode) {
2732
            $headTable = ['#', get_lang('OfficialCode'), get_lang('Name')];
2733
        } else {
2734
            $headTable = ['#', get_lang('Name')];
2735
        }
2736
        foreach ($calendar as $classDay) {
2737
            $labelDuration = !empty($classDay['duration']) ? get_lang('Duration').' : '.$classDay['duration'] : '';
2738
            $headTable[] =
2739
                api_format_date($classDay['date_time'], DATE_FORMAT_NUMBER_NO_YEAR).' '.
2740
                api_format_date($classDay['date_time'], TIME_NO_SEC_FORMAT).' '.
2741
                $labelDuration;
2742
        }
2743
        $dataTable[] = $headTable;
2744
        $dataUsersPresence = $userPresence;
2745
        $count = 1;
2746
2747
        if (!empty($users)) {
2748
            foreach ($users as $user) {
2749
                $cols = 1;
2750
                $result = [];
2751
                $result['count'] = $count;
2752
                if ($addOfficialCode) {
2753
                    $result['official_code'] = $user['official_code'];
2754
                }
2755
                $result['full_name'] = api_get_person_name($user['firstname'], $user['lastname']);
2756
                foreach ($calendar as $classDay) {
2757
                    $commentInfo = $this->getComment($user['user_id'], $classDay['id']);
2758
                    $comment = '';
2759
                    if (!empty($commentInfo['comment'])) {
2760
                        $comment .= $commentInfo['comment'];
2761
                    }
2762
                    if (!empty($commentInfo['author'])) {
2763
                        $comment .= ' - '.get_lang('Author').': '.$commentInfo['author'];
2764
                    }
2765
                    $txtComment = !empty($comment) ? '[comment]'.$comment : '';
2766
                    if (1 == (int) $classDay['done_attendance']) {
2767
                        if (1 == (int) $dataUsersPresence[$user['user_id']][$classDay['id']]['presence']) {
2768
                            $result[$classDay['id']] = get_lang('UserAttendedSymbol').$txtComment;
2769
                        } else {
2770
                            $result[$classDay['id']] = get_lang('UserNotAttendedSymbol').$txtComment;
2771
                        }
2772
                    } else {
2773
                        $result[$classDay['id']] = ' ';
2774
                    }
2775
                    $cols++;
2776
                }
2777
                $count++;
2778
                $dataTable[] = $result;
2779
            }
2780
        }
2781
2782
        $filename = get_lang('Attendance').'-'.api_get_local_time();
2783
        Export::arrayToXlsAndComments($dataTable, $filename);
2784
2785
        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...
2786
    }
2787
2788
    /**
2789
     * Get the user comment in attendance sheet.
2790
     *
2791
     * @return false|array The comment text and the author.
2792
     */
2793
    public function getComment(
2794
        int $userId,
2795
        int $attendanceCalendarId
2796
    ) {
2797
        $allowComment = api_get_configuration_value('attendance_allow_comments');
2798
        if (!$allowComment) {
2799
            return false;
2800
        }
2801
2802
        $courseId = api_get_course_int_id();
2803
        $em = Database::getManager();
2804
        $repo = $em->getRepository('ChamiloCourseBundle:CAttendanceSheet');
2805
2806
        $criteria = [
2807
            'userId' => $userId,
2808
            'attendanceCalendarId' => $attendanceCalendarId,
2809
            'cId' => $courseId,
2810
        ];
2811
        $attendanceSheet = $repo->findOneBy($criteria);
2812
2813
        $comment = "";
2814
        if ($attendanceSheet) {
2815
            /** @var CAttendanceSheet $attendanceSheet */
2816
            $attendanceSheetId = $attendanceSheet->getIid();
2817
2818
            $criteria = [
2819
                'userId' => $userId,
2820
                'attendanceSheetId' => $attendanceSheetId,
2821
            ];
2822
2823
            $repo = $em->getRepository('ChamiloCourseBundle:CAttendanceResultComment');
2824
            $attendanceResultComment = $repo->findOneBy($criteria);
2825
2826
            $author = '';
2827
            /** @var CAttendanceResultComment $attendanceResultComment */
2828
            if ($attendanceResultComment) {
2829
                $comment = $attendanceResultComment->getComment();
2830
                $authorId = $attendanceResultComment->getAuthorUserId();
2831
                if (!empty($authorId)) {
2832
                    $authorInfo = api_get_user_info($authorId);
2833
                    $author = api_get_person_name($authorInfo['firstname'], $authorInfo['lastname']);
2834
                }
2835
            }
2836
        }
2837
2838
        $commentInfo = [
2839
            'comment' => $comment,
2840
            'author' => $author,
2841
        ];
2842
2843
        return $commentInfo;
2844
    }
2845
2846
    /**
2847
     * Saves the user comment from attendance sheet.
2848
     *
2849
     * @return false
2850
     */
2851
    public function saveComment(
2852
        int $userId,
2853
        int $attendanceCalendarId,
2854
        string $comment,
2855
        int $attendanceId
2856
    ) {
2857
        $allowComment = api_get_configuration_value('attendance_allow_comments');
2858
        if (!$allowComment) {
2859
            return false;
2860
        }
2861
2862
        $courseId = api_get_course_int_id();
2863
        $em = Database::getManager();
2864
        $criteria = [
2865
            'userId' => $userId,
2866
            'attendanceCalendarId' => $attendanceCalendarId,
2867
            'cId' => $courseId,
2868
        ];
2869
2870
        $repo = $em->getRepository('ChamiloCourseBundle:CAttendanceSheet');
2871
        $attendanceSheet = $repo->findOneBy($criteria);
2872
2873
        /** @var CAttendanceSheet $attendanceSheet */
2874
        if (!$attendanceSheet) {
2875
            $attendanceSheet = new CAttendanceSheet();
2876
            $attendanceSheet
2877
                ->setCId($courseId)
2878
                ->setPresence(0)
2879
                ->setUserId($userId)
2880
                ->setAttendanceCalendarId($attendanceCalendarId);
2881
2882
            $em->persist($attendanceSheet);
2883
            $em->flush();
2884
        }
2885
        $this->updateUsersResults([$userId], $attendanceId);
2886
2887
        $attendanceSheetId = $attendanceSheet->getIid();
2888
2889
        // It saves the comment in the current attendance sheet
2890
        $criteria = [
2891
            'userId' => $userId,
2892
            'attendanceSheetId' => $attendanceSheetId,
2893
        ];
2894
2895
        $repo = $em->getRepository('ChamiloCourseBundle:CAttendanceResultComment');
2896
        $attendanceResultComment = $repo->findOneBy($criteria);
2897
2898
        /** @var CAttendanceResultComment $attendanceResultComment */
2899
        if ($attendanceResultComment) {
2900
            $attendanceResultComment->setComment($comment);
2901
            $attendanceResultComment->setUpdatedAt(api_get_utc_datetime(null, false, true));
2902
            $attendanceResultComment->setAuthorUserId(api_get_user_id());
2903
            $em->persist($attendanceResultComment);
2904
            $em->flush();
2905
        } else {
2906
            $attendanceResultComment = new CAttendanceResultComment();
2907
            $attendanceResultComment
2908
                ->setAttendanceSheetId($attendanceSheetId)
2909
                ->setUserId($userId)
2910
                ->setComment($comment)
2911
                ->setAuthorUserId(api_get_user_id());
2912
2913
            $em->persist($attendanceResultComment);
2914
            $em->flush();
2915
        }
2916
    }
2917
2918
    /**
2919
     * It saves the user sign from attendance sheet.
2920
     *
2921
     * @param $userId
2922
     * @param $attendanceCalendarId
2923
     * @param $file string in base64
2924
     *
2925
     * @return false or void when it is saved.
2926
     */
2927
    public function saveSignature(
2928
        $userId,
2929
        $attendanceCalendarId,
2930
        $file,
2931
        $attendanceId,
2932
        $courseId = null
2933
    ) {
2934
        $allowSignature = api_get_configuration_value('enable_sign_attendance_sheet');
2935
        if (!$allowSignature) {
2936
            return false;
2937
        }
2938
        if (!isset($courseId)) {
2939
            $courseId = api_get_course_int_id();
2940
        }
2941
        $em = Database::getManager();
2942
        $criteria = [
2943
            'userId' => $userId,
2944
            'attendanceCalendarId' => $attendanceCalendarId,
2945
            'cId' => $courseId,
2946
        ];
2947
2948
        $repo = $em->getRepository('ChamiloCourseBundle:CAttendanceSheet');
2949
        $attendanceSheet = $repo->findOneBy($criteria);
2950
2951
        /** @var CAttendanceSheet $attendanceSheet */
2952
        if ($attendanceSheet) {
2953
            $attendanceSheet->setPresence(1);
2954
            $attendanceSheet->setSignature($file);
2955
            $em->persist($attendanceSheet);
2956
            $em->flush();
2957
        } else {
2958
            $attendanceSheet = new CAttendanceSheet();
2959
            $attendanceSheet
2960
                ->setCId($courseId)
2961
                ->setPresence(1)
2962
                ->setUserId($userId)
2963
                ->setAttendanceCalendarId($attendanceCalendarId)
2964
                ->setSignature($file);
2965
2966
            $em->persist($attendanceSheet);
2967
            $em->flush();
2968
        }
2969
        $this->updateUsersResults([$userId], $attendanceId);
2970
    }
2971
}
2972