Attendance::get_attendance_calendar()   F
last analyzed

Complexity

Conditions 17
Paths 896

Size

Total Lines 98
Code Lines 64

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 64
dl 0
loc 98
rs 1.1943
c 0
b 0
f 0
cc 17
nc 896
nop 8

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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

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

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