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

Attendance::get_attendance_calendar()   F

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

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

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