Attendance::get_attendance_calendar()   F
last analyzed

Complexity

Conditions 17
Paths 896

Size

Total Lines 98
Code Lines 64

Duplication

Lines 0
Ratio 0 %

Importance

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

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

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

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

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