Completed
Push — master ( f77763...d3c71d )
by Julito
11:18
created

Attendance::set_date_time()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\ResourceLink;
6
use Chamilo\CoreBundle\Framework\Container;
7
use Chamilo\CourseBundle\Entity\CAttendance;
8
9
class Attendance
10
{
11
    // constants
12
    public const DONE_ATTENDANCE_LOG_TYPE = 'done_attendance_sheet';
13
    public const UPDATED_ATTENDANCE_LOG_TYPE = 'updated_attendance_sheet';
14
    public const LOCKED_ATTENDANCE_LOG_TYPE = 'locked_attendance_sheet';
15
    public $category_id;
16
    private $session_id;
17
    private $course_id;
18
    private $date_time;
19
    private $name;
20
    private $description;
21
    private $attendance_qualify_title;
22
    private $attendance_weight;
23
    private $course_int_id;
24
25
    /**
26
     * Get the total number of attendance inside current course and current session.
27
     *
28
     * @param int $active
29
     *
30
     * @return int
31
     *
32
     * @see SortableTable#get_total_number_of_items()
33
     */
34
    public static function getNumberOfAttendances()
35
    {
36
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
37
        $session_id = api_get_session_id();
38
        $condition_session = '';
39
40
        $active_plus = '';
41
        if ((isset($_GET['isStudentView']) && 'true' == $_GET['isStudentView']) ||
42
            !api_is_allowed_to_edit(null, true)
43
        ) {
44
            $active_plus = ' AND att.active = 1';
45
        }
46
47
        $sql = "SELECT COUNT(att.iid) AS total_number_of_items
48
                FROM $tbl_attendance att
49
                WHERE
50
                      active <> 2 $active_plus $condition_session  ";
51
        /*$active = (int) $active;
52
        if ($active === 1 || $active === 0) {
53
            $sql .= "AND att.active = $active";
54
        }*/
55
        $res = Database::query($sql);
56
        $obj = Database::fetch_object($res);
57
58
        return (int) $obj->total_number_of_items;
59
    }
60
61
    /**
62
     * Get attendance list only the id, name and attendance_qualify_max fields.
63
     *
64
     * @param int $course_id  course db name (optional)
65
     * @param int $session_id session id (optional)
66
     *
67
     * @return array attendances list
68
     */
69
    public function get_attendances_list($course_id = 0, $session_id = 0)
70
    {
71
        $table = Database::get_course_table(TABLE_ATTENDANCE);
72
        $course_id = (int) $course_id;
73
        if (empty($course_id)) {
74
            $course_id = api_get_course_int_id();
75
        }
76
77
        $session_id = !empty($session_id) ? (int) $session_id : api_get_session_id();
78
        $condition_session = api_get_session_condition($session_id);
79
80
        // Get attendance data
81
        $sql = "SELECT iid, name, attendance_qualify_max
82
                FROM $table
83
                WHERE active = 1 $condition_session ";
84
        $result = Database::query($sql);
85
        $data = [];
86
        if (Database::num_rows($result) > 0) {
87
            while ($row = Database::fetch_array($result, 'ASSOC')) {
88
                $data[$row['iid']] = $row;
89
            }
90
        }
91
92
        return $data;
93
    }
94
95
    /**
96
     * Get the attendances to display on the current page (fill the sortable-table).
97
     *
98
     * @param   int     offset of first user to recover
99
     * @param   int     Number of users to get
100
     * @param   int     Column to sort on
101
     * @param   string  Order (ASC,DESC)
102
     *
103
     * @see SortableTable#get_table_data($from)
104
     *
105
     * @return array
106
     */
107
    public static function get_attendance_data(
108
        $from,
109
        $number_of_items,
110
        $column,
111
        $direction
112
    ) {
113
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
114
        $course_id = api_get_course_int_id();
115
        $session_id = api_get_session_id();
116
        $condition_session = '';
117
        $column = (int) $column;
118
        $from = (int) $from;
119
        $number_of_items = (int) $number_of_items;
120
121
        if (!in_array($direction, ['ASC', 'DESC'])) {
122
            $direction = 'ASC';
123
        }
124
125
        $active_plus = '';
126
        if ((isset($_GET['isStudentView']) && 'true' == $_GET['isStudentView']) ||
127
            !api_is_allowed_to_edit(null, true)
128
        ) {
129
            $active_plus = ' AND att.active = 1';
130
        }
131
132
        $sql = "SELECT
133
                    att.iid AS col0,
134
                    att.name AS col1,
135
                    att.description AS col2,
136
                    att.attendance_qualify_max AS col3,
137
                    att.locked AS col4,
138
                    att.active AS col5
139
                FROM $tbl_attendance att
140
                WHERE
141
                    att.active <> 2
142
                     $active_plus $condition_session
143
                ORDER BY col$column $direction
144
                LIMIT $from,$number_of_items ";
145
146
        $res = Database::query($sql);
147
        $attendances = [];
148
        $user_info = api_get_user_info();
149
        $allowDelete = api_get_setting('allow_delete_attendance');
150
151
        $student_param = '';
152
        $studentRequestId = isset($_GET['student_id']) ? (int) $_GET['student_id'] : 0;
153
        if (api_is_drh() && !empty($studentRequestId)) {
154
            $student_param = '&student_id='.$studentRequestId;
155
        }
156
157
        while ($attendance = Database::fetch_row($res)) {
158
            $session_star = '';
159
            /*if ($session_id == $attendance[6]) {
160
                $session_star = api_get_session_image($session_id, $user_info['status']);
161
            }*/
162
163
            if (1 == $attendance[5]) {
164
                $isDrhOfCourse = CourseManager::isUserSubscribedInCourseAsDrh(
165
                    api_get_user_id(),
166
                    api_get_course_info()
167
                ) || api_is_drh();
168
                if (api_is_allowed_to_edit(null, true) || $isDrhOfCourse) {
169
                    // Link to edit
170
                    $attendance[1] = '<a href="index.php?'.api_get_cidreq().'&action=attendance_sheet_list&attendance_id='.$attendance[0].$student_param.'">'.$attendance[1].'</a>'.$session_star;
171
                } else {
172
                    // Link to view
173
                    $attendance[1] = '<a href="index.php?'.api_get_cidreq().'&action=attendance_sheet_list_no_edit&attendance_id='.$attendance[0].$student_param.'">'.$attendance[1].'</a>'.$session_star;
174
                }
175
            } else {
176
                $attendance[1] = '<a class="muted" href="index.php?'.api_get_cidreq().'&action=attendance_sheet_list&attendance_id='.$attendance[0].$student_param.'">'.$attendance[1].'</a>'.$session_star;
177
            }
178
179
            if (1 == $attendance[5]) {
180
                $attendance[3] = '<center>'.$attendance[3].'</center>';
181
            } else {
182
                $attendance[3] = '<center><span class="muted">'.$attendance[3].'</span></center>';
183
            }
184
185
            $attendance[3] = '<center>'.$attendance[3].'</center>';
186
            if (api_is_allowed_to_edit(null, true)) {
187
                $actions = '';
188
                $actions .= '<center>';
189
190
                if (api_is_platform_admin()) {
191
                    $actions .= '<a href="index.php?'.api_get_cidreq().'&action=attendance_edit&attendance_id='.$attendance[0].'">'.
192
                        Display::return_icon('edit.png', get_lang('Edit'), [], ICON_SIZE_SMALL).'</a>&nbsp;';
193
                    // Visible
194
                    if (1 == $attendance[5]) {
195
                        $actions .= '<a href="index.php?'.api_get_cidreq().'&action=attendance_set_invisible&attendance_id='.$attendance[0].'">'.
196
                            Display::return_icon('visible.png', get_lang('Hide'), [], ICON_SIZE_SMALL).'</a>';
197
                    } else {
198
                        $actions .= '<a href="index.php?'.api_get_cidreq().'&action=attendance_set_visible&attendance_id='.$attendance[0].'">'.
199
                            Display::return_icon('invisible.png', get_lang('Show'), [], ICON_SIZE_SMALL).'</a>';
200
                        $attendance[2] = '<span class="muted">'.$attendance[2].'</span>';
201
                    }
202
                    if ('true' === $allowDelete) {
203
                        $actions .= '<a href="index.php?'.api_get_cidreq().'&action=attendance_delete&attendance_id='.$attendance[0].'">'.
204
                            Display::return_icon('delete.png', get_lang('Delete'), [], ICON_SIZE_SMALL).'</a>';
205
                    }
206
                } else {
207
                    $is_locked_attendance = self::is_locked_attendance($attendance[0]);
208
                    if ($is_locked_attendance) {
209
                        $actions .= Display::return_icon('edit_na.png', get_lang('Edit')).'&nbsp;';
210
                        $actions .= Display::return_icon('visible.png', get_lang('Hide'));
211
                    } else {
212
                        $actions .= '<a href="index.php?'.api_get_cidreq().'&action=attendance_edit&attendance_id='.$attendance[0].'">'.
213
                            Display::return_icon('edit.png', get_lang('Edit'), [], ICON_SIZE_SMALL).'</a>&nbsp;';
214
215
                        if (1 == $attendance[5]) {
216
                            $actions .= ' <a href="index.php?'.api_get_cidreq().'&action=attendance_set_invisible&attendance_id='.$attendance[0].'">'.
217
                                Display::return_icon('visible.png', get_lang('Hide'), [], ICON_SIZE_SMALL).'</a>';
218
                        } else {
219
                            $actions .= ' <a href="index.php?'.api_get_cidreq().'&action=attendance_set_visible&attendance_id='.$attendance[0].'">'.
220
                                Display::return_icon('invisible.png', get_lang('Show'), [], ICON_SIZE_SMALL).'</a>';
221
                            $attendance[2] = '<span class="muted">'.$attendance[2].'</span>';
222
                        }
223
                        if ('true' === $allowDelete) {
224
                            $actions .= ' <a href="index.php?'.api_get_cidreq().'&action=attendance_delete&attendance_id='.$attendance[0].'">'.
225
                                Display::return_icon('delete.png', get_lang('Delete'), [], ICON_SIZE_SMALL).'</a>';
226
                        }
227
                    }
228
                }
229
230
                // display lock/unlock icon
231
                $is_done_all_calendar = self::is_all_attendance_calendar_done($attendance[0]);
232
233
                if ($is_done_all_calendar) {
234
                    $locked = $attendance[4];
235
                    if (0 == $locked) {
236
                        if (api_is_platform_admin()) {
237
                            $message_alert = get_lang('Are you sure you want to lock the attendance?');
238
                        } else {
239
                            $message_alert = get_lang('The attendance is not locked, which means your teacher is still able to modify it.');
240
                        }
241
                        $actions .= '&nbsp;<a
242
                            onclick="javascript:if(!confirm(\''.$message_alert.'\')) return false;"
243
                            href="index.php?'.api_get_cidreq().'&action=lock_attendance&attendance_id='.$attendance[0].'">'.
244
                            Display::return_icon('unlock.png', get_lang('Lock attendance')).'</a>';
245
                    } else {
246
                        if (api_is_platform_admin()) {
247
                            $actions .= '&nbsp;<a
248
                            onclick="javascript:if(!confirm(\''.get_lang('Are you sure you want to unlock the attendance?').'\')) return false;"
249
                            href="index.php?'.api_get_cidreq().'&action=unlock_attendance&attendance_id='.$attendance[0].'">'.
250
                                    Display::return_icon('locked.png', get_lang('Unlock attendance')).'</a>';
251
                        } else {
252
                            $actions .= '&nbsp;'.Display::return_icon('locked_na.png', get_lang('Locked attendance'));
253
                        }
254
                    }
255
                }
256
                $actions .= '</center>';
257
258
                $attendances[] = [
259
                    $attendance[0],
260
                    $attendance[1],
261
                    $attendance[2],
262
                    $attendance[3],
263
                    $actions,
264
                ];
265
            } else {
266
                $attendance[0] = '&nbsp;';
267
                $attendances[] = [
268
                    $attendance[0],
269
                    $attendance[1],
270
                    $attendance[2],
271
                    $attendance[3],
272
                ];
273
            }
274
        }
275
276
        return $attendances;
277
    }
278
279
    /**
280
     * Get the attendances by id to display on the current page.
281
     *
282
     * @param int $attendanceId
283
     *
284
     * @return array attendance data
285
     */
286
    public function get_attendance_by_id($attendanceId)
287
    {
288
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
289
        $attendanceId = (int) $attendanceId;
290
291
        $attendance_data = [];
292
        $sql = "SELECT * FROM $tbl_attendance
293
                WHERE iid = $attendanceId";
294
        $res = Database::query($sql);
295
        if (Database::num_rows($res) > 0) {
296
            while ($row = Database::fetch_array($res)) {
297
                $attendance_data = $row;
298
            }
299
        }
300
301
        return $attendance_data;
302
    }
303
304
    /**
305
     * Add attendances sheet inside table. This is the *list of* dates, not
306
     * a specific date in itself.
307
     *
308
     * @param  bool   true for adding link in gradebook or false otherwise (optional)
309
     *
310
     * @return int last attendance id
311
     */
312
    public function attendance_add($link_to_gradebook = false)
313
    {
314
        $_course = api_get_course_info();
315
        $table_link = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
316
        $session_id = api_get_session_id();
317
        $course_code = $_course['code'];
318
        $title_gradebook = $this->attendance_qualify_title;
319
        $value_calification = 0;
320
        $weight_calification = api_float_val($this->attendance_weight);
321
        $course = api_get_course_entity();
322
        $attendance = new CAttendance();
323
        $attendance
324
            ->setName($this->name)
325
            ->setDescription($this->description)
326
            ->setAttendanceQualifyTitle($title_gradebook)
327
            ->setAttendanceWeight($weight_calification)
328
            ->setParent($course)
329
            ->addCourseLink($course, api_get_session_entity())
330
        ;
331
332
        $repo = Container::getAttendanceRepository();
333
        $em = $repo->getEntityManager();
334
        $em->persist($attendance);
335
        $em->flush();
336
        $last_id = $attendance->getIid();
337
338
        // add link to gradebook
339
        if ($link_to_gradebook && !empty($this->category_id)) {
340
            $description = '';
341
            $link_info = GradebookUtils::isResourceInCourseGradebook(
342
                $course_code,
343
                7,
344
                $last_id,
345
                $session_id
346
            );
347
            $link_id = $link_info['id'];
348
            if (!$link_info) {
349
                GradebookUtils::add_resource_to_course_gradebook(
350
                    $this->category_id,
351
                    $course_code,
352
                    7,
353
                    $last_id,
354
                    $title_gradebook,
355
                    $weight_calification,
356
                    $value_calification,
357
                    $description,
358
                    1,
359
                    $session_id
360
                );
361
            } else {
362
                Database::query('UPDATE '.$table_link.' SET weight='.$weight_calification.' WHERE iid='.$link_id.'');
363
            }
364
        }
365
366
        return $last_id;
367
    }
368
369
    /**
370
     * edit attendances inside table.
371
     *
372
     * @param CAttendance $attendance
373
     * @param bool true for adding link in gradebook or false otherwise (optional)
374
     *
375
     * @return int last id
376
     */
377
    public function attendance_edit($attendance, $link_to_gradebook = false)
378
    {
379
        $_course = api_get_course_info();
380
        $table_link = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
381
        $session_id = api_get_session_id();
382
        $course_code = $_course['code'];
383
        $title_gradebook = $this->attendance_qualify_title;
384
        $value_calification = 0;
385
        $weight_calification = api_float_val($this->attendance_weight);
386
387
        if ($attendance) {
0 ignored issues
show
introduced by
$attendance is of type Chamilo\CourseBundle\Entity\CAttendance, thus it always evaluated to true.
Loading history...
388
            $attendanceId = $attendance->getIid();
389
            $attendance
390
                ->setName($this->name)
391
                ->setDescription($this->description)
392
                ->setAttendanceQualifyTitle($title_gradebook)
393
                ->setAttendanceWeight($weight_calification)
394
            ;
395
396
            $repo = Container::getAttendanceRepository();
397
            $repo->getEntityManager()->persist($attendance);
398
            $repo->getEntityManager()->flush();
399
400
            /*$params = [
401
                'name' => $this->name,
402
                'description' => $this->description,
403
                'attendance_qualify_title' => $title_gradebook,
404
                'attendance_weight' => $weight_calification,
405
            ];
406
            Database::update(
407
                $tbl_attendance,
408
                $params,
409
                ['c_id = ? AND id = ?' => [$course_id, $attendanceId]]
410
            );
411
            api_item_property_update(
412
                $_course,
413
                TOOL_ATTENDANCE,
414
                $attendanceId,
415
                "AttendanceUpdated",
416
                $user_id
417
            );*/
418
419
            // add link to gradebook
420
            if ($link_to_gradebook && !empty($this->category_id)) {
421
                $description = '';
422
                $link_info = GradebookUtils::isResourceInCourseGradebook(
423
                    $course_code,
424
                    7,
425
                    $attendanceId,
426
                    $session_id
427
                );
428
                if (!$link_info) {
429
                    GradebookUtils::add_resource_to_course_gradebook(
430
                        $this->category_id,
431
                        $course_code,
432
                        7,
433
                        $attendanceId,
434
                        $title_gradebook,
435
                        $weight_calification,
436
                        $value_calification,
437
                        $description,
438
                        1,
439
                        $session_id
440
                    );
441
                } else {
442
                    Database::query('UPDATE '.$table_link.' SET weight='.$weight_calification.' WHERE iid='.$link_info['id']);
443
                }
444
            }
445
446
            return $attendanceId;
447
        }
448
449
        return null;
450
    }
451
452
    /**
453
     * Restore attendance.
454
     *
455
     * @param int|array one or many attendances id
456
     *
457
     * @return int affected rows
458
     */
459
    public function attendance_restore($attendanceId)
460
    {
461
        $_course = api_get_course_info();
462
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
463
        $user_id = api_get_user_id();
464
        $course_id = $_course['real_id'];
465
        if (is_array($attendanceId)) {
466
            foreach ($attendanceId as $id) {
467
                $id = (int) $id;
468
                $sql = "UPDATE $tbl_attendance SET active = 1
469
                        WHERE iid = '$id'";
470
                $result = Database::query($sql);
471
                $affected_rows = Database::affected_rows($result);
472
                if (!empty($affected_rows)) {
473
                    // update row item property table
474
                    /*api_item_property_update(
475
                        $_course,
476
                        TOOL_ATTENDANCE,
477
                        $id,
478
                        'restore',
479
                        $user_id
480
                    );*/
481
                }
482
            }
483
        } else {
484
            $attendanceId = (int) $attendanceId;
485
            $sql = "UPDATE $tbl_attendance SET active = 1
486
                    WHERE iid = '$attendanceId'";
487
            $result = Database::query($sql);
488
            $affected_rows = Database::affected_rows($result);
489
            if (!empty($affected_rows)) {
490
                // update row item property table
491
                /*api_item_property_update(
492
                    $_course,
493
                    TOOL_ATTENDANCE,
494
                    $attendanceId,
495
                    'restore',
496
                    $user_id
497
                );*/
498
            }
499
        }
500
501
        return $affected_rows;
502
    }
503
504
    /**
505
     * Delete attendances.
506
     *
507
     * @param CAttendance $attendance one or many attendances id
508
     *
509
     * @return bool
510
     */
511
    public function attendance_delete(CAttendance $attendance)
512
    {
513
        $allowDeleteAttendance = api_get_setting('allow_delete_attendance');
514
        if ('true' !== $allowDeleteAttendance) {
515
            return false;
516
        }
517
518
        $repo = Container::getAttendanceRepository();
519
        $attendance->setActive(2);
520
        $repo->getEntityManager()->persist($attendance);
521
        $repo->getEntityManager()->flush();
522
523
        Skill::deleteSkillsFromItem($attendance->getIid(), ITEM_TYPE_ATTENDANCE);
524
525
        return true;
526
527
        /*$_course = api_get_course_info();
528
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
529
        $user_id = api_get_user_id();
530
        $course_id = $_course['real_id'];
531
532
        $attendanceId = (int) $attendanceId;
533
        $sql = "UPDATE $tbl_attendance SET active = 2
534
                WHERE c_id = $course_id AND id = '$attendanceId'";
535
536
        $result = Database::query($sql);
537
        $affected_rows = Database::affected_rows($result);
538
        if (!empty($affected_rows)) {
539
            // update row item property table
540
            api_item_property_update(
541
                $_course,
542
                TOOL_ATTENDANCE,
543
                $attendanceId,
544
                "delete",
545
                $user_id
546
            );
547
        }return $affected_rows;
548
        */
549
    }
550
551
    /**
552
     * Changes visibility.
553
     *
554
     * @param CAttendance $attendance one or many attendances id
555
     * @param int         $status
556
     *
557
     * @return int affected rows
558
     */
559
    public function changeVisibility(CAttendance $attendance, $status = 1)
560
    {
561
        $status = (int) $status;
562
563
        $repo = Container::getAttendanceRepository();
564
        $em = $repo->getEntityManager();
565
        $attendance->setActive($status);
566
        $em->persist($attendance);
567
        $em->flush();
568
569
        return true;
570
        /*
571
572
        $attendanceId = (int) $attendanceId;
573
        $sql = "UPDATE $tbl_attendance SET active = $status
574
                WHERE c_id = $course_id AND id = '$attendanceId'";
575
        $result = Database::query($sql);
576
        $affected_rows = Database::affected_rows($result);
577
        if (!empty($affected_rows)) {
578
            // update row item property table
579
            api_item_property_update(
580
                $_course,
581
                TOOL_ATTENDANCE,
582
                $attendanceId,
583
                $action,
584
                $user_id
585
            );
586
        }
587
588
        return $affected_rows;
589
        */
590
    }
591
592
    /**
593
     * Lock or unlock an attendance.
594
     *
595
     * @param bool    True to lock or false otherwise
596
     *
597
     * @return bool
598
     */
599
    public function lock(CAttendance $attendance, $lock = true)
600
    {
601
        $repo = Container::getAttendanceRepository();
602
        $em = $repo->getEntityManager();
603
        $attendance->setLocked($lock);
604
        $em->persist($attendance);
605
        $em->flush();
606
607
        return true;
608
609
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
0 ignored issues
show
Unused Code introduced by
$tbl_attendance = Databa...table(TABLE_ATTENDANCE) is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
610
        $course_id = api_get_course_int_id();
611
        $attendanceId = (int) $attendanceId;
612
        $locked = $lock ? 1 : 0;
613
        $upd = "UPDATE $tbl_attendance SET locked = $locked
614
                WHERE iid = $attendanceId";
615
        $result = Database::query($upd);
616
        $affected_rows = Database::affected_rows($result);
617
        if ($affected_rows && $lock) {
618
            // Save attendance sheet log
619
            $this->saveAttendanceSheetLog(
620
                $attendanceId,
621
                api_get_utc_datetime(),
622
                self::LOCKED_ATTENDANCE_LOG_TYPE,
623
                api_get_user_id()
624
            );
625
        }
626
627
        return $affected_rows;
628
    }
629
630
    /**
631
     * Get registered users inside current course.
632
     *
633
     * @param int $attendanceId attendance id for showing attendance result field (optional)
634
     * @param int $groupId
635
     *
636
     * @return array users data
637
     */
638
    public function get_users_rel_course($attendanceId = 0, $groupId = 0)
639
    {
640
        $current_session_id = api_get_session_id();
641
        $current_course_id = api_get_course_id();
642
        $currentCourseIntId = api_get_course_int_id();
643
        $studentInGroup = [];
644
645
        if (!empty($current_session_id)) {
646
            $a_course_users = CourseManager:: get_user_list_from_course_code(
647
                $current_course_id,
648
                $current_session_id,
649
                '',
650
                'lastname'
651
            );
652
        } else {
653
            $a_course_users = CourseManager:: get_user_list_from_course_code(
654
                $current_course_id,
655
                0,
656
                '',
657
                'lastname'
658
            );
659
        }
660
661
        if (!empty($groupId)) {
662
            $groupInfo = GroupManager::get_group_properties($groupId);
663
            $students = GroupManager::getStudents($groupInfo['iid']);
664
            if (!empty($students)) {
665
                foreach ($students as $student) {
666
                    $studentInGroup[$student['user_id']] = true;
667
                }
668
            }
669
        }
670
671
        // get registered users inside current course
672
        $a_users = [];
673
        foreach ($a_course_users as $key => $user_data) {
674
            $value = [];
675
            $uid = $user_data['user_id'];
676
            $userInfo = api_get_user_info($uid);
677
            $status = $user_data['status'];
678
679
            if (!empty($groupId)) {
680
                if (!isset($studentInGroup[$uid])) {
681
                    continue;
682
                }
683
            }
684
685
            $user_status_in_session = null;
686
            $user_status_in_course = null;
687
688
            if (api_get_session_id()) {
689
                $user_status_in_session = SessionManager::get_user_status_in_course_session(
690
                    $uid,
691
                    $currentCourseIntId,
692
                    $current_session_id
693
                );
694
            } else {
695
                $user_status_in_course = CourseManager::getUserInCourseStatus(
696
                    $uid,
697
                    $currentCourseIntId
698
                );
699
            }
700
701
            // Not taking into account DRH or COURSEMANAGER
702
            if ($uid <= 1 ||
703
                DRH == $status ||
704
                COURSEMANAGER == $user_status_in_course ||
705
                2 == $user_status_in_session
706
            ) {
707
                continue;
708
            }
709
710
            if (!empty($attendanceId)) {
711
                $user_faults = $this->get_faults_of_user(
712
                    $uid,
713
                    $attendanceId,
714
                    $groupId
715
                );
716
                $value['attendance_result'] = $user_faults['faults'].'/'.$user_faults['total'].' ('.$user_faults['faults_porcent'].'%)';
717
                $value['result_color_bar'] = $user_faults['color_bar'];
718
            }
719
720
            $photo = Display::img(
721
                $userInfo['avatar_small'],
722
                $userInfo['complete_name'],
723
                [],
724
                false
725
            );
726
727
            $value['photo'] = $photo;
728
            $value['firstname'] = $user_data['firstname'];
729
            $value['lastname'] = $user_data['lastname'];
730
            $value['username'] = $user_data['username'];
731
            $value['user_id'] = $uid;
732
733
            // Sending only 5 items in the array instead of 60
734
            $a_users[$key] = $value;
735
        }
736
737
        return $a_users;
738
    }
739
740
    /**
741
     * add attendances sheet inside table.
742
     *
743
     * @param int   $calendar_id   attendance calendar id
744
     * @param array $users_present present users during current class
745
     * @param int   $attendanceId
746
     *
747
     * @return int affected rows
748
     */
749
    public function attendance_sheet_add($calendar_id, $users_present, $attendanceId)
750
    {
751
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
752
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
753
754
        $calendar_id = (int) $calendar_id;
755
        $attendanceId = (int) $attendanceId;
756
        $users = $this->get_users_rel_course();
757
        $course_id = api_get_course_int_id();
758
759
        $user_ids = array_keys($users);
760
        $users_absent = array_diff($user_ids, $users_present);
761
        $affected_rows = 0;
762
763
        // get last edit type
764
        $calendar_data = $this->get_attendance_calendar_by_id($calendar_id);
765
        $lastedit_type = self::DONE_ATTENDANCE_LOG_TYPE;
766
        if ($calendar_data['done_attendance']) {
767
            $lastedit_type = self::UPDATED_ATTENDANCE_LOG_TYPE;
768
        }
769
770
        // save users present in class
771
        foreach ($users_present as $user_present) {
772
            $uid = (int) $user_present;
773
            // check if user already was registered with the $calendar_id
774
            $sql = "SELECT user_id FROM $tbl_attendance_sheet
775
                    WHERE c_id = $course_id AND user_id='$uid' AND attendance_calendar_id = '$calendar_id'";
776
            $rs = Database::query($sql);
777
            if (0 == Database::num_rows($rs)) {
778
                $sql = "INSERT INTO $tbl_attendance_sheet SET
779
                        c_id = $course_id,
780
                        user_id = '$uid',
781
                        attendance_calendar_id = '$calendar_id',
782
                        presence = 1";
783
                $result = Database::query($sql);
784
785
                $affected_rows += Database::affected_rows($result);
786
            } else {
787
                $sql = "UPDATE $tbl_attendance_sheet SET presence = 1
788
                        WHERE
789
                            c_id = $course_id AND
790
                            user_id ='$uid' AND
791
                            attendance_calendar_id = '$calendar_id'
792
                        ";
793
                $result = Database::query($sql);
794
                $affected_rows += Database::affected_rows($result);
795
            }
796
        }
797
798
        // save users absent in class
799
        foreach ($users_absent as $user_absent) {
800
            $uid = (int) $user_absent;
801
            // check if user already was registered with the $calendar_id
802
            $sql = "SELECT user_id FROM $tbl_attendance_sheet
803
                    WHERE c_id = $course_id AND user_id='$uid' AND attendance_calendar_id = '$calendar_id'";
804
            $rs = Database::query($sql);
805
            if (0 == Database::num_rows($rs)) {
806
                $sql = "INSERT INTO $tbl_attendance_sheet SET
807
                        c_id = $course_id,
808
                        user_id ='$uid',
809
                        attendance_calendar_id = '$calendar_id',
810
                        presence = 0";
811
                $result = Database::query($sql);
812
                $affected_rows += Database::affected_rows($result);
813
            } else {
814
                $sql = "UPDATE $tbl_attendance_sheet SET presence = 0
815
                        WHERE
816
                            c_id = $course_id AND
817
                            user_id ='$uid' AND
818
                            attendance_calendar_id = '$calendar_id'";
819
                $result = Database::query($sql);
820
                $affected_rows += Database::affected_rows($result);
821
            }
822
        }
823
824
        // update done_attendance inside attendance calendar table
825
        $sql = "UPDATE $tbl_attendance_calendar SET done_attendance = 1
826
                WHERE  iid = '$calendar_id'";
827
        Database::query($sql);
828
829
        // save users' results
830
        $this->updateUsersResults($user_ids, $attendanceId);
831
832
        if ($affected_rows) {
833
            //save attendance sheet log
834
            $this->saveAttendanceSheetLog(
835
                $attendanceId,
836
                api_get_utc_datetime(),
837
                $lastedit_type,
838
                api_get_user_id(),
839
                $calendar_data['date_time']
840
            );
841
        }
842
843
        return $affected_rows;
844
    }
845
846
    /**
847
     * update users' attendance results.
848
     *
849
     * @param array $user_ids     registered users inside current course
850
     * @param int   $attendanceId
851
     */
852
    public function updateUsersResults($user_ids, $attendanceId)
853
    {
854
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
855
        $tbl_attendance_result = Database::get_course_table(TABLE_ATTENDANCE_RESULT);
856
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
857
        $course_id = api_get_course_int_id();
858
        $attendanceId = (int) $attendanceId;
859
        // fill results about presence of students
860
        $attendance_calendar = $this->get_attendance_calendar(
861
            $attendanceId,
862
            'all',
863
            null,
864
            null,
865
            true
866
        );
867
        $calendar_ids = [];
868
        // get all dates from calendar by current attendance
869
        foreach ($attendance_calendar as $cal) {
870
            $calendar_ids[] = $cal['iid'];
871
        }
872
873
        // get count of presences by users inside current attendance and save like results
874
        if (count($user_ids) > 0) {
875
            foreach ($user_ids as $uid) {
876
                $uid = (int) $uid;
877
                $count_presences = 0;
878
                if (count($calendar_ids) > 0) {
879
                    $sql = "SELECT count(presence) as count_presences
880
                            FROM $tbl_attendance_sheet
881
                            WHERE
882
                                c_id = $course_id AND
883
                                user_id = '$uid' AND
884
                                attendance_calendar_id IN (".implode(',', $calendar_ids).') AND
885
                                presence = 1';
886
                    $rs_count = Database::query($sql);
887
                    $row_count = Database::fetch_array($rs_count);
888
                    $count_presences = $row_count['count_presences'];
889
                }
890
891
                // save results
892
                $sql = "SELECT iid FROM $tbl_attendance_result
893
                        WHERE
894
                            c_id = $course_id AND
895
                            user_id = '$uid' AND
896
                            attendance_id = '$attendanceId' ";
897
                $rs_check_result = Database::query($sql);
898
899
                if (Database::num_rows($rs_check_result) > 0) {
900
                    // update result
901
                    $sql = "UPDATE $tbl_attendance_result SET
902
                            score = '$count_presences'
903
                            WHERE
904
                                c_id = $course_id AND
905
                                user_id='$uid' AND
906
                                attendance_id='$attendanceId'";
907
                    Database::query($sql);
908
                } else {
909
                    // insert new result
910
                    $sql = "INSERT INTO $tbl_attendance_result SET
911
                            c_id = $course_id ,
912
                            user_id			= '$uid',
913
                            attendance_id 	= '$attendanceId',
914
                            score			= '$count_presences'";
915
                    Database::query($sql);
916
                    $insertId = Database::insert_id();
917
                }
918
            }
919
        }
920
921
        // update attendance qualify max
922
        $count_done_calendar = self::get_done_attendance_calendar($attendanceId);
923
        $sql = "UPDATE $tbl_attendance SET
924
                    attendance_qualify_max = '$count_done_calendar'
925
                WHERE iid = '$attendanceId'";
926
        Database::query($sql);
927
    }
928
929
    /**
930
     * update attendance_sheet_log table, is used as history of an attendance sheet.
931
     *
932
     * @param   int     Attendance id
933
     * @param   string  Last edit datetime
934
     * @param   string  Event type ('locked_attendance', 'done_attendance_sheet' ...)
935
     * @param   int     Last edit user id
936
     * @param   string  Calendar datetime value (optional, when event type is 'done_attendance_sheet')
937
     *
938
     * @return int Affected rows
939
     */
940
    public function saveAttendanceSheetLog(
941
        $attendanceId,
942
        $lastedit_date,
943
        $lastedit_type,
944
        $lastedit_user_id,
945
        $calendar_date_value = null
946
    ) {
947
        $course_id = api_get_course_int_id();
948
949
        // define table
950
        $tbl_attendance_sheet_log = Database::get_course_table(TABLE_ATTENDANCE_SHEET_LOG);
951
952
        // protect data
953
        $attendanceId = (int) $attendanceId;
954
        $lastedit_user_id = (int) $lastedit_user_id;
955
956
        if (isset($calendar_date_value)) {
957
            $calendar_date_value = $calendar_date_value;
958
        } else {
959
            $calendar_date_value = '';
960
        }
961
962
        // save data
963
        $params = [
964
            'c_id' => $course_id,
965
            'attendance_id' => $attendanceId,
966
            'lastedit_date' => $lastedit_date,
967
            'lastedit_type' => $lastedit_type,
968
            'lastedit_user_id' => $lastedit_user_id,
969
            'calendar_date_value' => $calendar_date_value,
970
        ];
971
972
        return Database::insert($tbl_attendance_sheet_log, $params);
973
    }
974
975
    /**
976
     * Get number of done attendances inside current sheet.
977
     *
978
     * @param int attendance id
979
     *
980
     * @return int number of done attendances
981
     */
982
    public static function get_done_attendance_calendar($attendanceId)
983
    {
984
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
985
        $attendanceId = (int) $attendanceId;
986
        $course_id = api_get_course_int_id();
987
        $sql = "SELECT count(done_attendance) as count
988
                FROM $table
989
                WHERE
990
                    attendance_id = '$attendanceId' AND
991
                    done_attendance = 1
992
                ";
993
        $rs = Database::query($sql);
994
        $row = Database::fetch_array($rs);
995
        $count = $row['count'];
996
997
        return $count;
998
    }
999
1000
    /**
1001
     * Get results of faults (absents) by user.
1002
     *
1003
     * @param int $user_id
1004
     * @param int $attendanceId
1005
     * @param int $groupId
1006
     *
1007
     * @return array results containing number of faults, total done attendance,
1008
     *               percent of faults and color depend on result (red, orange)
1009
     */
1010
    public function get_faults_of_user($user_id, $attendanceId, $groupId = null)
1011
    {
1012
        $user_id = (int) $user_id;
1013
        $attendanceId = (int) $attendanceId;
1014
        $results = [];
1015
        $calendar_count = self::get_number_of_attendance_calendar(
1016
            $attendanceId,
1017
            $groupId,
1018
            null,
1019
            $user_id
1020
        );
1021
        // $total_done_attendance 	= $attendance_data['attendance_qualify_max'];
1022
        $total_done_attendance = self::get_number_of_attendance_calendar(
1023
            $attendanceId,
1024
            $groupId,
1025
            true,
1026
            $user_id
1027
        );
1028
        $attendance_user_score = $this->get_user_score(
1029
            $user_id,
1030
            $attendanceId,
1031
            $groupId
1032
        );
1033
1034
        //This is the main change of the BT#1381
1035
        //$total_done_attendance = $calendar_count;
1036
1037
        // calculate results
1038
        $faults = $total_done_attendance - $attendance_user_score;
1039
1040
        if (empty($calendar_count)) {
1041
            $faults = 0;
1042
        }
1043
1044
        $faults = $faults > 0 ? $faults : 0;
1045
        $faults_porcent = $calendar_count > 0 ? round(($faults * 100) / $calendar_count, 0) : 0;
1046
        $results['faults'] = $faults;
1047
        $results['total'] = $calendar_count;
1048
        $results['faults_porcent'] = $faults_porcent;
1049
        $color_bar = '';
1050
1051
        if ($faults_porcent > 25) {
1052
            $color_bar = '#f28989';
1053
        } elseif ($faults_porcent > 10) {
1054
            $color_bar = '#F90';
1055
        }
1056
        $results['color_bar'] = $color_bar;
1057
1058
        return $results;
1059
    }
1060
1061
    /**
1062
     * Get results of faults average for all courses by user.
1063
     *
1064
     * @param int $user_id
1065
     *
1066
     * @return array results containing number of faults, total done attendance,
1067
     *               percentage of faults and color depend on result (red, orange)
1068
     */
1069
    public function get_faults_average_inside_courses($user_id)
1070
    {
1071
        // get all courses of current user
1072
        $courses = CourseManager::get_courses_list_by_user_id($user_id, true);
1073
        $user_id = (int) $user_id;
1074
        $results = [];
1075
        $total_faults = $total_weight = $porcent = 0;
1076
        foreach ($courses as $course) {
1077
            //$course_code = $course['code'];
1078
            //$course_info = api_get_course_info($course_code);
1079
            $course_id = $course['real_id'];
1080
            $tbl_attendance_result = Database::get_course_table(TABLE_ATTENDANCE_RESULT);
1081
            $attendances_by_course = $this->get_attendances_list($course_id);
1082
1083
            foreach ($attendances_by_course as $attendance) {
1084
                // get total faults and total weight
1085
                $total_done_attendance = $attendance['attendance_qualify_max'];
1086
                $sql = "SELECT score
1087
                        FROM $tbl_attendance_result
1088
                        WHERE
1089
                            c_id = $course_id AND
1090
                            user_id = $user_id AND
1091
                            attendance_id = ".$attendance['iid'];
1092
                $rs = Database::query($sql);
1093
                $score = 0;
1094
                if (Database::num_rows($rs) > 0) {
1095
                    $row = Database::fetch_array($rs);
1096
                    $score = $row['score'];
1097
                }
1098
                $faults = $total_done_attendance - $score;
1099
                $faults = $faults > 0 ? $faults : 0;
1100
                $total_faults += $faults;
1101
                $total_weight += $total_done_attendance;
1102
            }
1103
        }
1104
1105
        $porcent = $total_weight > 0 ? round(($total_faults * 100) / $total_weight, 0) : 0;
1106
        $results['faults'] = $total_faults;
1107
        $results['total'] = $total_weight;
1108
        $results['porcent'] = $porcent;
1109
1110
        return $results;
1111
    }
1112
1113
    /**
1114
     * Get results of faults average by course.
1115
     *
1116
     * @param int    $user_id
1117
     * @param string $course_code
1118
     * @param int Session id (optional)
1119
     *
1120
     * @return array results containing number of faults,
1121
     *               total done attendance, porcent of faults and color depend on result (red, orange)
1122
     */
1123
    public function get_faults_average_by_course(
1124
        $user_id,
1125
        $course_code,
1126
        $session_id = null
1127
    ) {
1128
        // Database tables and variables
1129
        $course_info = api_get_course_info($course_code);
1130
        $tbl_attendance_result = Database::get_course_table(TABLE_ATTENDANCE_RESULT);
1131
        $user_id = (int) $user_id;
1132
        $results = [];
1133
        $total_faults = $total_weight = $porcent = 0;
1134
        $attendances_by_course = $this->get_attendances_list(
1135
            $course_info['real_id'],
1136
            $session_id
1137
        );
1138
1139
        foreach ($attendances_by_course as $attendance) {
1140
            // Get total faults and total weight
1141
            $total_done_attendance = $attendance['attendance_qualify_max'];
1142
            $sql = "SELECT score FROM $tbl_attendance_result
1143
                    WHERE
1144
                        c_id = {$course_info['real_id']} AND
1145
                        user_id = $user_id AND
1146
                        attendance_id=".$attendance['iid'];
1147
            $rs = Database::query($sql);
1148
            $score = 0;
1149
            if (Database::num_rows($rs) > 0) {
1150
                $row = Database::fetch_array($rs);
1151
                $score = $row['score'];
1152
            }
1153
            $faults = $total_done_attendance - $score;
1154
            $faults = $faults > 0 ? $faults : 0;
1155
            $total_faults += $faults;
1156
            $total_weight += $total_done_attendance;
1157
        }
1158
1159
        $porcent = $total_weight > 0 ? round(($total_faults * 100) / $total_weight, 0) : 0;
1160
        $results['faults'] = $total_faults;
1161
        $results['total'] = $total_weight;
1162
        $results['porcent'] = $porcent;
1163
1164
        return $results;
1165
    }
1166
1167
    /**
1168
     * Get registered users' attendance sheet inside current course.
1169
     *
1170
     * @param int $attendanceId
1171
     * @param int $user_id      for showing data for only one user (optional)
1172
     * @param int $groupId
1173
     *
1174
     * @return array users attendance sheet data
1175
     */
1176
    public function get_users_attendance_sheet(
1177
        $attendanceId,
1178
        $user_id = 0,
1179
        $groupId = 0,
1180
        $course_id = 0,
1181
        DateTime $startDate = null,
1182
        DateTime $endDate = null
1183
    ) {
1184
        //Get actual course or by course_id
1185
        $course_id = (0 == $course_id) ? api_get_course_int_id() : (int) $course_id;
1186
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
1187
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1188
        $attendance_calendar = $this->get_attendance_calendar(
1189
            $attendanceId,
1190
            'all',
1191
            null,
1192
            $groupId,
1193
            true,
1194
            $course_id,
1195
            $startDate,
1196
            $endDate
1197
        );
1198
        $calendar_ids = [];
1199
        // get all dates from calendar by current attendance
1200
        foreach ($attendance_calendar as $cal) {
1201
            $calendar_ids[] = $cal['iid'];
1202
        }
1203
1204
        $whereDate = '';
1205
        if (!empty($startDate)) {
1206
            $whereDate .= " AND cal.date_time >= '".$startDate->format('Y-m-d H:i:s')."'";
1207
        }
1208
        if (!empty($endDate)) {
1209
            $whereDate .= " AND cal.date_time <= '".$endDate->format('Y-m-d H:i:s')."'";
1210
        }
1211
1212
        // moved at start of this function
1213
        // $course_id = api_get_course_int_id();
1214
1215
        $data = [];
1216
        if (empty($user_id)) {
1217
            // get all registered users inside current course
1218
            $users = $this->get_users_rel_course();
1219
            $user_ids = array_keys($users);
1220
            if (count($calendar_ids) > 0 && count($user_ids) > 0) {
1221
                foreach ($user_ids as $uid) {
1222
                    $uid = (int) $uid;
1223
                    $sql = "SELECT * FROM $tbl_attendance_sheet
1224
                            WHERE
1225
                                c_id = $course_id AND
1226
                                user_id = '$uid' AND
1227
                                attendance_calendar_id IN(".implode(',', $calendar_ids).')
1228
                            ';
1229
                    $res = Database::query($sql);
1230
                    if (Database::num_rows($res) > 0) {
1231
                        while ($row = Database::fetch_array($res)) {
1232
                            $data[$uid][$row['attendance_calendar_id']]['presence'] = $row['presence'];
1233
                        }
1234
                    }
1235
                }
1236
            }
1237
        } else {
1238
            // Get attendance for current user
1239
            $user_id = (int) $user_id;
1240
            if (count($calendar_ids) > 0) {
1241
                $sql = "SELECT cal.date_time, att.presence
1242
                        FROM $tbl_attendance_sheet att
1243
                        INNER JOIN  $tbl_attendance_calendar cal
1244
                        ON cal.iid = att.attendance_calendar_id
1245
                        WHERE
1246
                            att.c_id = $course_id AND
1247
                            cal.c_id =  $course_id AND
1248
                            att.user_id = '$user_id' AND
1249
                            att.attendance_calendar_id IN (".implode(',', $calendar_ids).")
1250
                            $whereDate
1251
                        ORDER BY date_time";
1252
                $res = Database::query($sql);
1253
                if (Database::num_rows($res) > 0) {
1254
                    while ($row = Database::fetch_array($res)) {
1255
                        $row['date_time'] = api_convert_and_format_date($row['date_time'], null, date_default_timezone_get());
1256
                        $data[$user_id][] = $row;
1257
                    }
1258
                }
1259
            }
1260
        }
1261
1262
        return $data;
1263
    }
1264
1265
    /**
1266
     * Get next attendance calendar without presences (done attendances).
1267
     *
1268
     * @param int    attendance id
1269
     *
1270
     * @return int attendance calendar id
1271
     */
1272
    public function get_next_attendance_calendar_id($attendanceId)
1273
    {
1274
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1275
        $attendanceId = (int) $attendanceId;
1276
        $course_id = api_get_course_int_id();
1277
1278
        $sql = "SELECT iid FROM $table
1279
                WHERE
1280
                    c_id = $course_id AND
1281
                    attendance_id = '$attendanceId' AND
1282
                    done_attendance = 0
1283
                ORDER BY date_time
1284
                LIMIT 1";
1285
        $rs = Database::query($sql);
1286
        $next_calendar_id = 0;
1287
        if (Database::num_rows($rs) > 0) {
1288
            $row = Database::fetch_array($rs);
1289
            $next_calendar_id = $row['iid'];
1290
        }
1291
1292
        return $next_calendar_id;
1293
    }
1294
1295
    /**
1296
     * Get next attendance calendar datetime without presences (done attendances).
1297
     *
1298
     * @param int    attendance id
1299
     *
1300
     * @return int UNIX time format datetime
1301
     */
1302
    public function getNextAttendanceCalendarDatetime($attendanceId)
1303
    {
1304
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1305
        $course_id = api_get_course_int_id();
1306
        $attendanceId = (int) $attendanceId;
1307
        $sql = "SELECT iid, date_time FROM $table
1308
                WHERE
1309
                    c_id = $course_id AND
1310
                    attendance_id = '$attendanceId' AND
1311
                    done_attendance = 0
1312
                ORDER BY date_time
1313
                LIMIT 1";
1314
        $rs = Database::query($sql);
1315
        $next_calendar_datetime = 0;
1316
        if (Database::num_rows($rs) > 0) {
1317
            $row = Database::fetch_array($rs);
1318
            $next_calendar_datetime = api_get_local_time($row['date_time']);
1319
        }
1320
1321
        return $next_calendar_datetime;
1322
    }
1323
1324
    /**
1325
     * Get user's score from current attendance.
1326
     *
1327
     * @param int $user_id
1328
     * @param int $attendanceId
1329
     * @param int $groupId
1330
     *
1331
     * @return int score
1332
     */
1333
    public function get_user_score($user_id, $attendanceId, $groupId = 0)
1334
    {
1335
        $tbl_attendance_result = Database::get_course_table(TABLE_ATTENDANCE_RESULT);
1336
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
1337
        $tbl_attendance_cal_rel_group = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1338
        $tbl_attendance_cal = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1339
        $user_id = (int) $user_id;
1340
        $attendanceId = (int) $attendanceId;
1341
        $groupId = (int) $groupId;
1342
        $course_id = api_get_course_int_id();
1343
1344
        if (empty($groupId)) {
1345
            $sql = "SELECT score FROM $tbl_attendance_result
1346
                    WHERE
1347
                        c_id = $course_id AND
1348
                        user_id='$user_id' AND
1349
                        attendance_id='$attendanceId'";
1350
        } else {
1351
            $sql = "SELECT count(presence) as score
1352
                    FROM $tbl_attendance_sheet
1353
                    WHERE
1354
                        c_id = $course_id AND
1355
                        user_id='$user_id' AND
1356
                        presence = 1 AND
1357
                        attendance_calendar_id IN (
1358
                            SELECT calendar_id FROM $tbl_attendance_cal_rel_group crg
1359
                            INNER JOIN $tbl_attendance_cal c
1360
                            ON (crg.calendar_id = c.iid)
1361
                            WHERE
1362
                                crg.c_id = $course_id AND
1363
                                crg.group_id = $groupId AND
1364
                                c.attendance_id = $attendanceId
1365
                        )
1366
                    ";
1367
        }
1368
        $rs = Database::query($sql);
1369
        $score = 0;
1370
        if (Database::num_rows($rs) > 0) {
1371
            $row = Database::fetch_array($rs);
1372
            $score = $row['score'];
1373
        }
1374
1375
        return $score;
1376
    }
1377
1378
    /**
1379
     * Get attendance calendar data by id.
1380
     *
1381
     * @param int    attendance calendar id
1382
     *
1383
     * @return array attendance calendar data
1384
     */
1385
    public function get_attendance_calendar_by_id($calendar_id)
1386
    {
1387
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1388
        $calendar_id = (int) $calendar_id;
1389
        $course_id = api_get_course_int_id();
1390
        $sql = "SELECT * FROM $table
1391
                WHERE c_id = $course_id AND iid = '$calendar_id' ";
1392
        $rs = Database::query($sql);
1393
        $data = [];
1394
        if (Database::num_rows($rs) > 0) {
1395
            while ($row = Database::fetch_array($rs)) {
1396
                $row['date_time'] = api_get_local_time($row['date_time']);
1397
                $data = $row;
1398
            }
1399
        }
1400
1401
        return $data;
1402
    }
1403
1404
    /**
1405
     * Get all attendance calendar data inside current attendance.
1406
     *
1407
     * @param int    $attendanceId
1408
     * @param string $type
1409
     * @param int    $calendar_id
1410
     * @param int    $groupId
1411
     * @param bool   $showAll      = false show group calendar items or not
1412
     * @param int      $course_id
1413
     * @param DateTime $startDate    Filter calendar with a start date
1414
     * @param DateTime $endDate      Filter calendar with a end date
1415
     *
1416
     * @return array attendance calendar data
1417
     */
1418
    public function get_attendance_calendar(
1419
        $attendanceId,
1420
        $type = 'all',
1421
        $calendar_id = null,
1422
        $groupId = 0,
1423
        $showAll = false,
1424
        $course_id = 0,
1425
        DateTime $startDate = null,
1426
        DateTime $endDate = null
1427
    ) {
1428
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1429
        $tbl_acrg = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1430
        $attendanceId = (int) $attendanceId;
1431
        $course_id = (0 == $course_id) ? api_get_course_int_id() : (int) $course_id;
1432
        $whereDate = '';
1433
        if (!empty($startDate)) {
1434
            $whereDate .= " AND c.date_time >= '".$startDate->format('Y-m-d H:i:s')."'";
1435
        }
1436
        if (!empty($endDate)) {
1437
            $whereDate .= " AND c.date_time <= '".$endDate->format('Y-m-d H:i:s')."'";
1438
        }
1439
        if ($showAll) {
1440
            $sql = "SELECT * FROM $tbl_attendance_calendar c
1441
                    WHERE c_id = $course_id
1442
                      AND attendance_id = '$attendanceId'
1443
                        $whereDate";
1444
        } else {
1445
            $sql = "SELECT * FROM $tbl_attendance_calendar c
1446
                    WHERE
1447
                        c_id = $course_id AND
1448
                        attendance_id = '$attendanceId' AND
1449
                        iid NOT IN (
1450
                            SELECT calendar_id FROM $tbl_acrg
1451
                            WHERE c_id = $course_id AND group_id != 0 AND group_id IS NOT NULL
1452
                        )
1453
                        $whereDate
1454
                    ";
1455
        }
1456
1457
        if (!empty($groupId)) {
1458
            $groupId = (int) $groupId;
1459
            $sql = "SELECT c.* FROM $tbl_attendance_calendar c
1460
                    INNER JOIN $tbl_acrg g
1461
                    ON c.c_id = g.c_id AND c.iid = g.calendar_id
1462
                    WHERE
1463
                        c.c_id = $course_id AND
1464
                        g.group_id = '$groupId' AND
1465
                        c.attendance_id = '$attendanceId'
1466
                   ";
1467
        }
1468
1469
        if (!in_array($type, ['today', 'all', 'all_done', 'all_not_done', 'calendar_id'])) {
1470
            $type = 'all';
1471
        }
1472
1473
        switch ($type) {
1474
            case 'calendar_id':
1475
                $calendar_id = (int) $calendar_id;
1476
                if (!empty($calendar_id)) {
1477
                    $sql .= " AND c.iid = $calendar_id";
1478
                }
1479
                break;
1480
            case 'today':
1481
                //$sql .= ' AND DATE_FORMAT(date_time,"%d-%m-%Y") = DATE_FORMAT("'.api_get_utc_datetime().'", "%d-%m-%Y" )';
1482
                break;
1483
            case 'all_done':
1484
                $sql .= ' AND done_attendance = 1 ';
1485
                break;
1486
            case 'all_not_done':
1487
                $sql .= ' AND done_attendance = 0 ';
1488
                break;
1489
            case 'all':
1490
            default:
1491
                break;
1492
        }
1493
        $sql .= ' ORDER BY date_time ';
1494
1495
        $rs = Database::query($sql);
1496
        $data = [];
1497
        if (Database::num_rows($rs) > 0) {
1498
            while ($row = Database::fetch_array($rs, 'ASSOC')) {
1499
                $row['db_date_time'] = $row['date_time'];
1500
                $row['date_time'] = api_get_local_time($row['date_time']);
1501
                $row['date'] = api_format_date($row['date_time'], DATE_FORMAT_SHORT);
1502
                $row['time'] = api_format_date($row['date_time'], TIME_NO_SEC_FORMAT);
1503
                $row['groups'] = $this->getGroupListByAttendanceCalendar($row['iid'], $course_id);
1504
                if ('today' === $type) {
1505
                    if (date('d-m-Y', api_strtotime($row['date_time'], 'UTC')) == date('d-m-Y', time())) {
1506
                        $data[] = $row;
1507
                    }
1508
                } else {
1509
                    $data[] = $row;
1510
                }
1511
            }
1512
        }
1513
1514
        return $data;
1515
    }
1516
1517
    /**
1518
     * Get number of attendance calendar inside current attendance.
1519
     *
1520
     * @param int $attendanceId
1521
     * @param int $groupId
1522
     * @param $done_attendance
1523
     * @param int $userId
1524
     *
1525
     * @return int number of dates in attendance calendar
1526
     */
1527
    public static function get_number_of_attendance_calendar(
1528
        $attendanceId,
1529
        $groupId = 0,
1530
        $done_attendance = null,
1531
        $userId = 0
1532
    ) {
1533
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1534
        $calendarRelGroup = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1535
        $tbl_groupRelUser = Database::get_course_table(TABLE_GROUP_USER);
1536
        $attendanceId = (int) $attendanceId;
1537
        $groupId = (int) $groupId;
1538
        $course_id = api_get_course_int_id();
1539
1540
        $where_attendance = '';
1541
        if ($done_attendance) {
1542
            $where_attendance = ' done_attendance = 1 AND ';
1543
        }
1544
        if (empty($userId)) {
1545
            if (empty($groupId)) {
1546
                $sql = "SELECT count(a.iid)
1547
                        FROM $tbl_attendance_calendar a
1548
                        WHERE
1549
                            $where_attendance
1550
                            attendance_id = '$attendanceId' AND
1551
                            iid NOT IN (
1552
                                SELECT calendar_id FROM $calendarRelGroup
1553
                                WHERE
1554
                                    c_id = $course_id AND
1555
                                    group_id != 0 AND
1556
                                    group_id IS NOT NULL
1557
                            )
1558
                        ";
1559
            } else {
1560
                $sql = "SELECT count(a.iid)
1561
                        FROM $tbl_attendance_calendar a
1562
                        INNER JOIN $calendarRelGroup g
1563
                        ON (a.iid = g.calendar_id)
1564
                        WHERE
1565
                            $where_attendance
1566
                            attendance_id = '$attendanceId' AND
1567
                            group_id = $groupId
1568
                        ";
1569
            }
1570
        } else {
1571
            if (empty($groupId)) {
1572
                $sql = "SELECT count(a.iid)
1573
                        FROM $tbl_attendance_calendar a
1574
                        WHERE
1575
                            c_id = $course_id AND
1576
                            $where_attendance
1577
                            attendance_id = '$attendanceId' AND
1578
                            iid NOT IN (
1579
                                SELECT calendar_id FROM $calendarRelGroup
1580
                                WHERE
1581
                                    c_id = $course_id AND
1582
                                    group_id != 0 AND
1583
                                    group_id IS NOT NULL AND
1584
                                    group_id NOT IN (
1585
                                        SELECT group_id
1586
                                        FROM $tbl_groupRelUser
1587
                                        WHERE user_id = $userId
1588
                                    )
1589
                            )
1590
                        ";
1591
            } else {
1592
                $sql = "SELECT count(a.iid)
1593
                        FROM $tbl_attendance_calendar a
1594
                        INNER JOIN $calendarRelGroup g
1595
                        ON (a.iid = g.calendar_id)
1596
                        WHERE
1597
                            a.c_id = $course_id AND
1598
                            $where_attendance
1599
                            attendance_id = '$attendanceId' AND
1600
                            group_id = $groupId
1601
                        ";
1602
            }
1603
        }
1604
1605
        $rs = Database::query($sql);
1606
        $row = Database::fetch_row($rs);
1607
1608
        return $row[0];
1609
    }
1610
1611
    /**
1612
     * Get count dates inside attendance calendar by attendance id.
1613
     *
1614
     * @param int $attendanceId
1615
     *
1616
     * @return int count of dates
1617
     */
1618
    public static function get_count_dates_inside_attendance_calendar($attendanceId)
1619
    {
1620
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1621
        $attendanceId = (int) $attendanceId;
1622
        $course_id = api_get_course_int_id();
1623
        $sql = "SELECT count(iid) FROM $tbl_attendance_calendar
1624
                WHERE
1625
                    attendance_id = '$attendanceId'";
1626
        $rs = Database::query($sql);
1627
        $count = 0;
1628
        if (Database::num_rows($rs) > 0) {
1629
            $row = Database::fetch_row($rs);
1630
            $count = $row[0];
1631
        }
1632
1633
        return $count;
1634
    }
1635
1636
    /**
1637
     * check if all calendar of an attendance is done.
1638
     *
1639
     * @param int $attendanceId
1640
     *
1641
     * @return bool True if all calendar is done, otherwise false
1642
     */
1643
    public static function is_all_attendance_calendar_done($attendanceId)
1644
    {
1645
        $attendanceId = (int) $attendanceId;
1646
        $done_calendar = self::get_done_attendance_calendar($attendanceId);
1647
        $count_dates_in_calendar = self::get_count_dates_inside_attendance_calendar($attendanceId);
1648
        $number_of_dates = self::get_number_of_attendance_calendar($attendanceId);
1649
1650
        $result = false;
1651
        if ($number_of_dates && intval($count_dates_in_calendar) == intval($done_calendar)) {
1652
            $result = true;
1653
        }
1654
1655
        return $result;
1656
    }
1657
1658
    /**
1659
     * check if an attendance is locked.
1660
     *
1661
     * @param int $attendanceId
1662
     * @param bool
1663
     *
1664
     * @return bool
1665
     */
1666
    public static function is_locked_attendance($attendanceId)
1667
    {
1668
        //  Use gradebook lock
1669
        return api_resource_is_locked_by_gradebook($attendanceId, LINK_ATTENDANCE);
1670
    }
1671
1672
    /**
1673
     * Add new datetime inside attendance calendar table.
1674
     *
1675
     * @param CAttendance $attendance
1676
     * @param array       $groupList
1677
     *
1678
     * @return int affected rows
1679
     */
1680
    public function attendance_calendar_add($attendance, $groupList = [])
1681
    {
1682
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1683
        $affected_rows = 0;
1684
        $attendanceId = $attendance->getIid();
1685
        $course_id = api_get_course_int_id();
1686
        // check if datetime already exists inside the table
1687
        /*$sql = "SELECT id FROM $tbl_attendance_calendar
1688
                WHERE
1689
                    c_id = $course_id AND
1690
                    date_time='".Database::escape_string($this->date_time)."' AND
1691
                    attendance_id = '$attendanceId'";
1692
        $rs = Database::query($sql);
1693
        if (Database::num_rows($rs) == 0) {*/
1694
        $params = [
1695
            'c_id' => $course_id,
1696
            'date_time' => $this->date_time,
1697
            'attendance_id' => $attendanceId,
1698
            'done_attendance' => 0,
1699
        ];
1700
        $id = Database::insert($tbl_attendance_calendar, $params);
1701
1702
        if ($id) {
1703
            $affected_rows++;
1704
        }
1705
        $this->addAttendanceCalendarToGroup($id, $course_id, $groupList);
1706
        //}
1707
1708
        // update locked attendance
1709
        $is_all_calendar_done = $this->is_all_attendance_calendar_done($attendanceId);
1710
        if (!$is_all_calendar_done) {
1711
            $this->lock($attendance, false);
1712
        } else {
1713
            $this->lock($attendance);
1714
        }
1715
1716
        return $affected_rows;
1717
    }
1718
1719
    /**
1720
     * @param int   $calendarId
1721
     * @param int   $courseId
1722
     * @param array $groupList
1723
     *
1724
     * @return bool
1725
     */
1726
    public function addAttendanceCalendarToGroup($calendarId, $courseId, $groupList)
1727
    {
1728
        if (empty($groupList)) {
1729
            return false;
1730
        }
1731
1732
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1733
        foreach ($groupList as $groupId) {
1734
            if (empty($groupId)) {
1735
                continue;
1736
            }
1737
1738
            $result = $this->getAttendanceCalendarGroup(
1739
                $calendarId,
1740
                $courseId,
1741
                $groupId
1742
            );
1743
1744
            if (empty($result)) {
1745
                $params = [
1746
                    'calendar_id' => $calendarId,
1747
                    'c_id' => $courseId,
1748
                    'group_id' => $groupId,
1749
                ];
1750
                Database::insert($table, $params);
1751
            }
1752
        }
1753
1754
        return true;
1755
    }
1756
1757
    /**
1758
     * @param int $calendarId
1759
     * @param int $courseId
1760
     *
1761
     * @return array
1762
     */
1763
    public function getGroupListByAttendanceCalendar($calendarId, $courseId)
1764
    {
1765
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1766
1767
        return Database::select(
1768
            '*',
1769
            $table,
1770
            [
1771
                'where' => [
1772
                    'calendar_id = ? AND c_id = ?' => [$calendarId, $courseId],
1773
                ],
1774
            ]
1775
        );
1776
    }
1777
1778
    /**
1779
     * @param int $calendarId
1780
     * @param int $courseId
1781
     * @param int $groupId
1782
     *
1783
     * @return array
1784
     */
1785
    public function getAttendanceCalendarGroup($calendarId, $courseId, $groupId)
1786
    {
1787
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1788
1789
        return Database::select(
1790
            '*',
1791
            $table,
1792
            [
1793
                'where' => [
1794
                    'calendar_id = ? AND c_id = ? AND group_id = ?' => [$calendarId, $courseId, $groupId],
1795
                ],
1796
            ]
1797
        );
1798
    }
1799
1800
    /**
1801
     * @param int $calendarId
1802
     * @param int $courseId
1803
     */
1804
    public function deleteAttendanceCalendarGroup($calendarId, $courseId)
1805
    {
1806
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1807
        Database::delete(
1808
            $table,
1809
            [
1810
                'calendar_id = ? AND c_id = ?' => [$calendarId, $courseId],
1811
            ]
1812
        );
1813
    }
1814
1815
    /**
1816
     * save repeated date inside attendance calendar table.
1817
     *
1818
     * @param CAttendance $attendance
1819
     * @param int         $start_date  start date in tms
1820
     * @param int         $end_date    end date in tms
1821
     * @param string      $repeat_type daily, weekly, monthlyByDate
1822
     * @param array       $groupList
1823
     */
1824
    public function attendance_repeat_calendar_add(
1825
        $attendance,
1826
        $start_date,
1827
        $end_date,
1828
        $repeat_type,
1829
        $groupList = []
1830
    ) {
1831
        $attendanceId = $attendance->getIid();
1832
        // save start date
1833
        $this->set_date_time(api_get_utc_datetime($start_date));
1834
        $this->attendance_calendar_add($attendance, $groupList);
1835
1836
        // 86400 = 24 hours in seconds
1837
        // 604800 = 1 week in seconds
1838
        // Saves repeated dates
1839
        switch ($repeat_type) {
1840
            case 'daily':
1841
                $j = 1;
1842
                for ($i = $start_date + 86400; ($i <= $end_date); $i += 86400) {
1843
                    $this->set_date_time(api_get_utc_datetime($i));
1844
                    $this->attendance_calendar_add($attendance, $groupList);
1845
                    $j++;
1846
                }
1847
                break;
1848
            case 'weekly':
1849
                $j = 1;
1850
                for ($i = $start_date + 604800; ($i <= $end_date); $i += 604800) {
1851
                    $this->set_date_time(api_get_utc_datetime($i));
1852
                    $this->attendance_calendar_add($attendance, $groupList);
1853
                    $j++;
1854
                }
1855
                break;
1856
            case 'monthlyByDate':
1857
                $j = 1;
1858
                //@todo fix bug with february
1859
                for ($i = $start_date + 2419200; ($i <= $end_date); $i += 2419200) {
1860
                    $this->set_date_time(api_get_utc_datetime($i));
1861
                    $this->attendance_calendar_add($attendanceId, $groupList);
1862
                    $j++;
1863
                }
1864
                break;
1865
        }
1866
    }
1867
1868
    /**
1869
     * edit a datetime inside attendance calendar table.
1870
     *
1871
     * @param int         $calendar_id
1872
     * @param CAttendance $attendance
1873
     *
1874
     * @return int affected rows
1875
     */
1876
    public function attendance_calendar_edit($calendar_id, $attendance)
1877
    {
1878
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1879
        $affected_rows = 0;
1880
        $attendanceId = $attendance->getIid();
1881
1882
        $course_id = api_get_course_int_id();
1883
        // check if datetime already exists inside the table
1884
        $sql = "SELECT iid FROM $tbl_attendance_calendar
1885
                WHERE
1886
                    c_id = $course_id AND
1887
                    date_time = '".Database::escape_string($this->date_time)."' AND
1888
                    attendance_id = '$attendanceId'";
1889
        $rs = Database::query($sql);
1890
1891
        if (0 == Database::num_rows($rs)) {
1892
            $sql = "UPDATE $tbl_attendance_calendar
1893
                    SET date_time='".Database::escape_string($this->date_time)."'
1894
                    WHERE c_id = $course_id AND iid = '".intval($calendar_id)."'";
1895
            Database::query($sql);
1896
        }
1897
1898
        // update locked attendance
1899
        $is_all_calendar_done = self::is_all_attendance_calendar_done($attendanceId);
1900
        if (!$is_all_calendar_done) {
1901
            $this->lock($attendance, false);
1902
        } else {
1903
            $this->lock($attendance);
1904
        }
1905
1906
        return $affected_rows;
1907
    }
1908
1909
    /**
1910
     * delete a datetime from attendance calendar table.
1911
     *
1912
     * @param	int		attendance calendar id
1913
     * @param	int		attendance id
1914
     * @param	bool true for removing all calendar inside current attendance, false for removing by calendar id
1915
     *
1916
     * @return int affected rows
1917
     */
1918
    public function attendance_calendar_delete(
1919
        $calendar_id,
1920
        $attendanceId,
1921
        $all_delete = false
1922
    ) {
1923
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1924
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
1925
1926
        $attendanceId = (int) $attendanceId;
1927
        $calendar_id = (int) $calendar_id;
1928
1929
        // get all registered users inside current course
1930
        $users = $this->get_users_rel_course();
1931
        $user_ids = array_keys($users);
1932
        $course_id = api_get_course_int_id();
1933
        $affected_rows = 0;
1934
        if ($all_delete) {
1935
            $attendance_calendar = $this->get_attendance_calendar($attendanceId);
1936
            // get all dates from calendar by current attendance
1937
            if (!empty($attendance_calendar)) {
1938
                foreach ($attendance_calendar as $cal) {
1939
                    // delete all data from attendance sheet
1940
                    $sql = "DELETE FROM $tbl_attendance_sheet
1941
                            WHERE c_id = $course_id AND attendance_calendar_id = '".intval($cal['iid'])."'";
1942
                    Database::query($sql);
1943
                    // delete data from attendance calendar
1944
                    $sql = "DELETE FROM $tbl_attendance_calendar
1945
                            WHERE c_id = $course_id AND iid = '".intval($cal['iid'])."'";
1946
                    Database::query($sql);
1947
1948
                    $this->deleteAttendanceCalendarGroup($cal['iid'], $course_id);
1949
                    $affected_rows++;
1950
                }
1951
            }
1952
        } else {
1953
            // delete just one row from attendance sheet by the calendar id
1954
            $sql = "DELETE FROM $tbl_attendance_sheet
1955
                    WHERE c_id = $course_id AND attendance_calendar_id = '".$calendar_id."'";
1956
            Database::query($sql);
1957
            // delete data from attendance calendar
1958
            $sql = "DELETE FROM $tbl_attendance_calendar
1959
                    WHERE c_id = $course_id AND iid = '".$calendar_id."'";
1960
            Database::query($sql);
1961
1962
            $this->deleteAttendanceCalendarGroup($calendar_id, $course_id);
1963
            $affected_rows++;
1964
        }
1965
1966
        // update users' results
1967
        $this->updateUsersResults($user_ids, $attendanceId);
1968
1969
        return $affected_rows;
1970
    }
1971
1972
    public function set_session_id($sessionId)
1973
    {
1974
        $this->session_id = $sessionId;
1975
    }
1976
1977
    public function set_course_id($course_id)
1978
    {
1979
        $this->course_id = $course_id;
1980
    }
1981
1982
    public function set_date_time($datetime)
1983
    {
1984
        $this->date_time = $datetime;
1985
    }
1986
1987
    public function set_name($name)
1988
    {
1989
        $this->name = $name;
1990
    }
1991
1992
    public function set_description($description)
1993
    {
1994
        $this->description = $description;
1995
    }
1996
1997
    public function set_attendance_qualify_title($attendance_qualify_title)
1998
    {
1999
        $this->attendance_qualify_title = $attendance_qualify_title;
2000
    }
2001
2002
    public function set_attendance_weight($attendance_weight)
2003
    {
2004
        $this->attendance_weight = $attendance_weight;
2005
    }
2006
2007
    /** Getters for fields of attendances tables */
2008
    public function get_session_id()
2009
    {
2010
        return $this->session_id;
2011
    }
2012
2013
    public function get_course_id()
2014
    {
2015
        return $this->course_id;
2016
    }
2017
2018
    public function get_date_time()
2019
    {
2020
        return $this->date_time;
2021
    }
2022
2023
    public function get_name()
2024
    {
2025
        return $this->name;
2026
    }
2027
2028
    public function get_description()
2029
    {
2030
        return $this->description;
2031
    }
2032
2033
    public function get_attendance_qualify_title()
2034
    {
2035
        return $this->attendance_qualify_title;
2036
    }
2037
2038
    public function get_attendance_weight()
2039
    {
2040
        return $this->attendance_weight;
2041
    }
2042
2043
    /**
2044
     * @param string $startDate in UTC time
2045
     * @param string $endDate   in UTC time
2046
     *
2047
     * @return array
2048
     */
2049
    public function getAttendanceLogin($startDate, $endDate)
2050
    {
2051
        if (empty($startDate) ||
2052
            '0000-00-00' === $startDate ||
2053
            '0000-00-00 00:00:00' === $startDate ||
2054
            empty($endDate) ||
2055
            '0000-00-00' === $endDate ||
2056
            '0000-00-00 00:00:00' === $endDate
2057
        ) {
2058
            return false;
2059
        }
2060
2061
        $sessionId = api_get_session_id();
2062
        $courseCode = api_get_course_id();
2063
        $courseId = api_get_course_int_id();
2064
2065
        if (!empty($sessionId)) {
2066
            $users = CourseManager::get_user_list_from_course_code(
2067
                $courseCode,
2068
                $sessionId,
2069
                '',
2070
                'lastname',
2071
                0
2072
            );
2073
        } else {
2074
            $users = CourseManager::get_user_list_from_course_code(
2075
                $courseCode,
2076
                0,
2077
                '',
2078
                'lastname',
2079
                STUDENT
2080
            );
2081
        }
2082
2083
        $dateTimeStartOriginal = new DateTime($startDate);
2084
        $dateTimeStart = new DateTime($startDate);
2085
        $dateTimeEnd = new DateTime($endDate);
2086
        $interval = $dateTimeStart->diff($dateTimeEnd);
2087
        $days = (int) $interval->format('%a');
2088
2089
        $dateList = [$dateTimeStart->format('Y-m-d')];
2090
        $headers = [
2091
            get_lang('User'),
2092
            $dateTimeStart->format('Y-m-d'),
2093
        ];
2094
2095
        for ($i = 0; $i < $days; $i++) {
2096
            $dateTimeStart = $dateTimeStart->add(new DateInterval('P1D'));
2097
            $date = $dateTimeStart->format('Y-m-d');
2098
            $dateList[] = $date;
2099
            $headers[] = $date;
2100
        }
2101
2102
        $accessData = CourseManager::getCourseAccessPerCourseAndSession(
2103
            $courseId,
2104
            $sessionId,
2105
            $dateTimeStartOriginal->format('Y-m-d H:i:s'),
2106
            $dateTimeEnd->format('Y-m-d H:i:s')
2107
        );
2108
2109
        $results = [];
2110
        if (!empty($accessData)) {
2111
            foreach ($accessData as $data) {
2112
                $onlyDate = substr($data['login_course_date'], 0, 10);
2113
                $results[$data['user_id']][$onlyDate] = true;
2114
            }
2115
        }
2116
2117
        return [
2118
            'users' => $users,
2119
            'dateList' => $dateList,
2120
            'headers' => $headers,
2121
            'results' => $results,
2122
        ];
2123
    }
2124
2125
    /**
2126
     * @param string $startDate in UTC time
2127
     * @param string $endDate   in UTC time
2128
     *
2129
     * @return string
2130
     */
2131
    public function getAttendanceLoginTable($startDate, $endDate)
2132
    {
2133
        $data = $this->getAttendanceLogin($startDate, $endDate);
2134
        if (!$data) {
2135
            return null;
2136
        }
2137
2138
        $headers = $data['headers'];
2139
        $dateList = $data['dateList'];
2140
        $users = $data['users'];
2141
        $results = $data['results'];
2142
2143
        $table = new HTML_Table(['class' => 'data_table']);
2144
        $row = 0;
2145
        $column = 0;
2146
        foreach ($headers as $header) {
2147
            $table->setHeaderContents($row, $column, $header);
2148
            $column++;
2149
        }
2150
        $row = 1;
2151
        foreach ($users as $user) {
2152
            $table->setCellContents(
2153
                $row,
2154
                0,
2155
                $user['lastname'].' '.$user['firstname'].' ('.$user['username'].')'
2156
            );
2157
            $row++;
2158
        }
2159
2160
        $column = 1;
2161
        $row = 1;
2162
        foreach ($users as $user) {
2163
            foreach ($dateList as $date) {
2164
                $status = null;
2165
                if (isset($results[$user['user_id']]) &&
2166
                    isset($results[$user['user_id']][$date])
2167
                ) {
2168
                    $status = 'X';
2169
                }
2170
                $table->setCellContents($row, $column, $status);
2171
                $column++;
2172
            }
2173
            $row++;
2174
            $column = 1;
2175
        }
2176
2177
        return $table->toHtml();
2178
    }
2179
2180
    /**
2181
     * @param string $startDate in UTC time
2182
     * @param string $endDate   in UTC time
2183
     *
2184
     * @return string
2185
     */
2186
    public function exportAttendanceLogin($startDate, $endDate)
2187
    {
2188
        $data = $this->getAttendanceLogin($startDate, $endDate);
2189
2190
        if (!$data) {
2191
            return null;
2192
        }
2193
        $users = $data['users'];
2194
        $results = $data['results'];
2195
2196
        $table = new HTML_Table(['class' => 'data_table']);
2197
        $table->setHeaderContents(0, 0, get_lang('User'));
2198
        $table->setHeaderContents(0, 1, get_lang('Date'));
2199
2200
        $row = 1;
2201
        foreach ($users as $user) {
2202
            $table->setCellContents(
2203
                $row,
2204
                0,
2205
                $user['lastname'].' '.$user['firstname'].' ('.$user['username'].')'
2206
            );
2207
            $row++;
2208
        }
2209
        $table->setColAttributes(0, ['style' => 'width:28%']);
2210
2211
        $row = 1;
2212
        foreach ($users as $user) {
2213
            if (isset($results[$user['user_id']]) &&
2214
                !empty($results[$user['user_id']])
2215
            ) {
2216
                $dates = implode(', ', array_keys($results[$user['user_id']]));
2217
                $table->setCellContents($row, 1, $dates);
2218
            }
2219
            $row++;
2220
        }
2221
2222
        $tableToString = $table->toHtml();
2223
        $params = [
2224
            'filename' => get_lang('Attendance').'_'.api_get_utc_datetime(),
2225
            'pdf_title' => get_lang('Attendance'),
2226
            'course_code' => api_get_course_id(),
2227
            'show_real_course_teachers' => true,
2228
        ];
2229
        $pdf = new PDF('A4', null, $params);
2230
        $pdf->html_to_pdf_with_template($tableToString);
2231
    }
2232
2233
    public function setAttendanceForm(FormValidator $form, CAttendance $attendance = null)
2234
    {
2235
        $skillList = [];
2236
        $header = get_lang('Create a new attendance list');
2237
        if ($attendance) {
2238
            $header = get_lang('Edit');
2239
            $form->addHidden('attendance_id', $attendance->getIid());
2240
        }
2241
        $form->addHeader($header);
2242
2243
        //$form->addElement('hidden', 'sec_token', $token);
2244
        $form->addText('title', get_lang('Title'), true);
2245
        $form->applyFilter('title', 'html_filter');
2246
        $form->addHtmlEditor(
2247
            'description',
2248
            get_lang('Description'),
2249
            false,
2250
            false,
2251
            ['ToolbarSet' => 'Basic', 'Width' => '100%', 'Height' => '150']
2252
        );
2253
2254
        $sessionId = api_get_session_id();
2255
2256
        // Advanced Parameters
2257
        if ((0 != $sessionId && Gradebook::is_active()) || 0 == $sessionId) {
2258
            $form->addButtonAdvancedSettings('id_qualify');
2259
            $form->addElement('html', '<div id="id_qualify_options" style="display:none">');
2260
2261
            // Qualify Attendance for gradebook option
2262
            $form->addElement(
2263
                'checkbox',
2264
                'attendance_qualify_gradebook',
2265
                '',
2266
                get_lang('Grade the attendance list in the assessment tool'),
2267
                'onclick="javascript: if(this.checked){document.getElementById(\'options_field\').style.display = \'block\';}else{document.getElementById(\'options_field\').style.display = \'none\';}"'
2268
            );
2269
            $form->addElement('html', '<div id="options_field" style="display:none">');
2270
2271
            GradebookUtils::load_gradebook_select_in_tool($form);
2272
2273
            $form->addElement('text', 'attendance_qualify_title', get_lang('Column header in Competences Report'));
2274
            $form->applyFilter('attendance_qualify_title', 'html_filter');
2275
            $form->addElement(
2276
                'text',
2277
                'attendance_weight',
2278
                get_lang('Weight in Report'),
2279
                'value="0.00" Style="width:40px" onfocus="javascript: this.select();"'
2280
            );
2281
            $form->applyFilter('attendance_weight', 'html_filter');
2282
            $form->addElement('html', '</div>');
2283
2284
            $skillList = Skill::addSkillsToForm($form, ITEM_TYPE_ATTENDANCE, $attendance ? $attendance->getIid() : 0);
2285
2286
            $form->addElement('html', '</div>');
2287
        }
2288
2289
        if ($attendance) {
2290
            $form->addButtonUpdate(get_lang('Update'));
2291
        } else {
2292
            $form->addButtonCreate(get_lang('Save'));
2293
        }
2294
2295
        if ($attendance) {
2296
            $default = [];
2297
            $default['title'] = Security::remove_XSS($attendance->getName());
2298
            $default['description'] = Security::remove_XSS($attendance->getDescription(), STUDENT);
2299
            $default['attendance_qualify_title'] = $attendance->getAttendanceQualifyTitle();
2300
            $default['attendance_weight'] = $attendance->getAttendanceWeight();
2301
            $default['skills'] = array_keys($skillList);
2302
2303
            $link_info = GradebookUtils::isResourceInCourseGradebook(
2304
                api_get_course_id(),
2305
                7,
2306
                $attendance->getIid(),
2307
                $sessionId
2308
            );
2309
            if ($link_info) {
2310
                $default['category_id'] = $link_info['category_id'];
2311
            }
2312
            $form->setDefaults($default);
2313
        }
2314
2315
        return $form;
2316
    }
2317
2318
    public function getCalendarSheet($edit, $attendanceId, $student_id)
2319
    {
2320
        $content = '';
2321
        $groupId = isset($_REQUEST['group_id']) ? $_REQUEST['group_id'] : null;
2322
        $filter_type = 'today';
2323
        if (!empty($_REQUEST['filter'])) {
2324
            $filter_type = $_REQUEST['filter'];
2325
        }
2326
2327
        $users_in_course = $this->get_users_rel_course($attendanceId, $groupId);
2328
        $is_locked_attendance = $this->is_locked_attendance($attendanceId);
2329
2330
        $attendant_calendar_all = $this->get_attendance_calendar(
2331
            $attendanceId,
2332
            'all',
2333
            null,
2334
            $groupId
2335
        );
2336
        $attendant_calendar = $this->get_attendance_calendar(
2337
            $attendanceId,
2338
            $filter_type,
2339
            null,
2340
            $groupId
2341
        );
2342
2343
        $isDrhOfCourse = CourseManager::isUserSubscribedInCourseAsDrh(
2344
                api_get_user_id(),
2345
                api_get_course_info()
2346
            ) || api_is_drh();
2347
        if (true == $edit) {
2348
            if (api_is_allowed_to_edit(null, true) || $isDrhOfCourse) {
2349
                $data['users_presence'] = $this->get_users_attendance_sheet(
2350
                    $attendanceId,
2351
                    0,
2352
                    $groupId
2353
                );
2354
            }
2355
        } else {
2356
            if (!empty($student_id)) {
2357
                $user_id = (int) $student_id;
2358
            } else {
2359
                $user_id = api_get_user_id();
2360
            }
2361
2362
            if (api_is_allowed_to_edit(null, true) ||
2363
                api_is_coach(api_get_session_id(), api_get_course_int_id()) ||
2364
                $isDrhOfCourse
2365
            ) {
2366
                $users_presence = $this->get_users_attendance_sheet(
2367
                    $attendanceId,
2368
                    0,
2369
                    $groupId
2370
                );
2371
            } else {
2372
                $users_presence = $this->get_users_attendance_sheet(
2373
                    $attendanceId,
2374
                    $user_id,
2375
                    $groupId
2376
                );
2377
            }
2378
2379
            $faults = $this->get_faults_of_user($user_id, $attendanceId, $groupId);
2380
        }
2381
2382
        $next_attendance_calendar_id = $this->get_next_attendance_calendar_id($attendanceId);
2383
        $next_attendance_calendar_datetime = $this->getNextAttendanceCalendarDatetime($attendanceId);
2384
2385
        if (api_is_allowed_to_edit(null, true) ||
2386
            api_is_coach(api_get_session_id(), api_get_course_int_id()) ||
2387
            $isDrhOfCourse
2388
        ) {
2389
            $groupId = isset($_REQUEST['group_id']) ? (int) ($_REQUEST['group_id']) : null;
2390
            $form = new FormValidator(
2391
                'filter',
2392
                'post',
2393
                'index.php?action=attendance_sheet_list&'.api_get_cidreq().'&attendance_id='.$attendanceId,
2394
                null,
2395
                [],
2396
                'inline'
2397
            );
2398
2399
            $values = [
2400
                'all' => get_lang('All'),
2401
                'today' => get_lang('Today'),
2402
                'all_done' => get_lang('All done'),
2403
                'all_not_done' => get_lang('All not done'),
2404
            ];
2405
            $today = api_convert_and_format_date(null, DATE_FORMAT_SHORT);
2406
            $exists_attendance_today = false;
2407
2408
            if (!empty($attendant_calendar_all)) {
2409
                $values[''] = '---------------';
2410
                foreach ($attendant_calendar_all as $attendance_date) {
2411
                    $includeCalendar = true;
2412
                    if (isset($attendance_date['groups']) && !empty($groupId)) {
2413
                        foreach ($attendance_date['groups'] as $group) {
2414
                            if ($groupId == $group['group_id']) {
2415
                                $includeCalendar = true;
2416
2417
                                break;
2418
                            } else {
2419
                                $includeCalendar = false;
2420
                            }
2421
                        }
2422
                    }
2423
2424
                    if ($today == $attendance_date['date']) {
2425
                        $exists_attendance_today = true;
2426
                    }
2427
                    if ($includeCalendar) {
2428
                        $values[$attendance_date['iid']] = $attendance_date['date_time'];
2429
                    }
2430
                }
2431
            }
2432
2433
            if (!$exists_attendance_today) {
2434
                $content .= Display::return_message(
2435
                    get_lang('There is no class scheduled today, try picking another day or add your attendance entry yourself using the action icons.'),
2436
                    'warning'
2437
                );
2438
            }
2439
2440
            $form->addSelect(
2441
                'filter',
2442
                get_lang('Filter'),
2443
                $values,
2444
                ['id' => 'filter_id', 'onchange' => 'submit();']
2445
            );
2446
2447
            $groupList = GroupManager::get_group_list(null, null, 1);
2448
            $groupIdList = ['--'];
2449
            foreach ($groupList as $group) {
2450
                $groupIdList[$group['iid']] = $group['name'];
2451
            }
2452
2453
            if (!empty($groupList)) {
2454
                $form->addSelect('group_id', get_lang('Group'), $groupIdList);
2455
            }
2456
2457
            if (isset($_REQUEST['filter'])) {
2458
                if (in_array($_REQUEST['filter'], array_keys($values))) {
2459
                    $default_filter = $_REQUEST['filter'];
2460
                }
2461
            } else {
2462
                $default_filter = 'today';
2463
            }
2464
2465
            $renderer = $form->defaultRenderer();
2466
            $renderer->setCustomElementTemplate(
2467
                '<div class="col-md-2">{label}</div><div class="col-md-10"> {element} </div>'
2468
            );
2469
2470
            $form->setDefaults(
2471
                [
2472
                    'filter' => $default_filter,
2473
                    'group_id' => $groupId,
2474
                ]
2475
            );
2476
2477
            if (!$is_locked_attendance || api_is_platform_admin()) {
2478
                $actionsLeft = '<a style="float:left;" href="index.php?'.api_get_cidreq().'&action=calendar_list&attendance_id='.$attendanceId.'">'.
2479
                    Display::return_icon('attendance_calendar.png', get_lang('Attendance calendar'), '', ICON_SIZE_MEDIUM).'</a>';
2480
                $actionsLeft .= '<a id="pdf_export" style="float:left;"  href="index.php?'.api_get_cidreq().'&action=attendance_sheet_export_to_pdf&attendance_id='.$attendanceId.'&filter='.$default_filter.'&group_id='.$groupId.'">'.
2481
                    Display::return_icon('pdf.png', get_lang('Export to PDF'), '', ICON_SIZE_MEDIUM).'</a>';
2482
2483
                $actionsRight = $form->returnForm();
2484
                $content .= Display::toolbarAction('toolbar-attendance', [$actionsLeft, $actionsRight]);
2485
            }
2486
2487
            $message_information = get_lang('The attendance sheets allow you to specify a list of dates in which you will report attendance to your courses');
2488
            if (!empty($message_information)) {
2489
                $message = '<strong>'.get_lang('Information').'</strong><br />';
2490
                $message .= $message_information;
2491
                $content .= Display::return_message($message, 'normal', false);
2492
            }
2493
2494
            if ($is_locked_attendance) {
2495
                $content .= Display::return_message(get_lang('The attendance sheet is locked.'), 'warning', false);
2496
            }
2497
2498
            $param_filter = '&filter='.Security::remove_XSS($default_filter).'&group_id='.$groupId;
2499
2500
            if (count($users_in_course) > 0) {
2501
                $form = '
2502
                <form method="post" action="index.php?action=attendance_sheet_add&'.api_get_cidreq().$param_filter.'&attendance_id='.$attendanceId.'">
2503
                    <div class="attendance-sheet-content" style="width:100%;background-color:#E1E1E1;margin-top:20px;">
2504
                        <div class="divTableWithFloatingHeader attendance-users-table" style="width:45%;float:left;margin:0px;padding:0px;">
2505
                            <table class="tableWithFloatingHeader data_table" width="100%">
2506
                                <thead>
2507
                                <tr class="tableFloatingHeader" style="position: absolute; top: 0px; left: 0px; visibility: hidden; margin:0px;padding:0px" >
2508
                                    <th width="10px">#</th>
2509
                                    <th width="10px">'.get_lang('Photo').'</th>
2510
                                    <th width="100px">'.get_lang('Last name').'</th>
2511
                                    <th width="100px">'.get_lang('First name').'</th>
2512
                                    <th width="100px">'.get_lang('Not attended').'</th>
2513
                                </tr>
2514
                                <tr class="tableFloatingHeaderOriginal" >
2515
                                    <th width="10px">#</th>
2516
                                    <th width="10px">'.get_lang('Photo').'</th>
2517
                                    <th width="150px">'.get_lang('Last name').'</th>
2518
                                    <th width="140px">'.get_lang('First name').'</th>
2519
                                    <th width="100px">'.get_lang('Not attended').'</th>
2520
                                </tr>
2521
                                </thead>
2522
                                <tbody>';
2523
2524
                $i = 1;
2525
                $class = '';
2526
                foreach ($users_in_course as $data) {
2527
                    $faults = 0;
2528
                    if (0 == $i % 2) {
2529
                        $class = 'row_odd';
2530
                    } else {
2531
                        $class = 'row_even';
2532
                    }
2533
                    $username = api_htmlentities(
2534
                        sprintf(get_lang('Login: %s'), $data['username']),
2535
                        ENT_QUOTES
2536
                    );
2537
2538
                    $form .= '<tr class="'.$class.'">
2539
                                <td><center>'.$i.'</center></td>
2540
                                <td>'.$data['photo'].'</td>
2541
                                <td><span title="'.$username.'">'.$data['lastname'].'</span></td>
2542
                                <td>'.$data['firstname'].'</td>
2543
                                <td>
2544
                                    <div class="attendance-faults-bar"
2545
                                    style="background-color:'.(!empty($data['result_color_bar']) ? $data['result_color_bar'] : 'none').'">
2546
                                        '.$data['attendance_result'].'
2547
                                    </div>
2548
                                </td>
2549
                            </tr>';
2550
2551
                    $i++;
2552
                }
2553
                $form .= '</tbody>
2554
                            </table>
2555
                        </div>';
2556
2557
                $form .= '<div
2558
                    class="divTableWithFloatingHeader attendance-calendar-table"
2559
                    style="margin:0px;padding:0px;float:left;width:55%;overflow:auto;overflow-y:hidden;">';
2560
                $form .= '<table class="tableWithFloatingHeader data_table" width="100%">';
2561
                $form .= '<thead>';
2562
                $result = null;
2563
2564
                if (count($attendant_calendar) > 0) {
2565
                    foreach ($attendant_calendar as $calendar) {
2566
                        $calendarId = $calendar['iid'];
2567
                        $date = $calendar['date'];
2568
                        $time = $calendar['time'];
2569
                        $datetime = '<div class="grey">'.$date.' - '.$time.'</div>';
2570
2571
                        $img_lock = Display::return_icon(
2572
                            'lock-closed.png',
2573
                            get_lang('Unlock date'),
2574
                            ['class' => 'img_lock', 'id' => 'datetime_column_'.$calendarId]
2575
                        );
2576
2577
                        if (!empty($calendar['done_attendance'])) {
2578
                            $datetime = '<div class="blue">'.$date.' - '.$time.'</div>';
2579
                        }
2580
                        $disabled_check = 'disabled = "true"';
2581
                        $input_hidden = '<input
2582
                            type="hidden" id="hidden_input_'.$calendarId.'" name="hidden_input[]" value="" disabled />';
2583
                        if ($next_attendance_calendar_id == $calendarId) {
2584
                            $input_hidden = '<input
2585
                                type="hidden" id="hidden_input_'.$calendarId.'" name="hidden_input[]" value="'.$calendarId.'" />';
2586
                            $disabled_check = '';
2587
                            $img_lock = Display::return_icon(
2588
                                'lock-closed.png',
2589
                                get_lang('Lock date'),
2590
                                ['class' => 'img_unlock', 'id' => 'datetime_column_'.$calendarId]
2591
                            );
2592
                        }
2593
2594
                        $result .= '<th>';
2595
                        $result .= '<div class="date-attendance">'.$datetime.'&nbsp;';
2596
                        if (api_is_allowed_to_edit(null, true)) {
2597
                            $result .= '<span id="attendance_lock" style="cursor:pointer">'.(!$is_locked_attendance || api_is_platform_admin() ? $img_lock : '').'</span>';
2598
                        }
2599
2600
                        if (false == $is_locked_attendance) {
2601
                            if (api_is_allowed_to_edit(null, true)) {
2602
                                $result .= '<input
2603
                                type="checkbox" class="checkbox_head_'.$calendarId.'" id="checkbox_head_'.$calendarId.'" '.$disabled_check.' checked="checked" />'.
2604
                                    $input_hidden.'</div></th>';
2605
                            }
2606
                        }
2607
                    }
2608
                } else {
2609
                    $result = '<th width="2000px"><span>
2610
                    <a href="index.php?'.api_get_cidreq().'&action=calendar_list&attendance_id='.$attendanceId.'">';
2611
                    $result .= Display::return_icon(
2612
                            'attendance_calendar.png',
2613
                            get_lang('Attendance calendar'),
2614
                            '',
2615
                            ICON_SIZE_MEDIUM
2616
                        ).' '.get_lang('Go to the attendance calendar');
2617
                    $result .= '</a></span></th>';
2618
                }
2619
2620
                $form .= '<tr
2621
                        class="tableFloatingHeader row_odd"
2622
                        style="position: absolute; top: 0px; left: 0px; visibility: hidden; margin:0px;padding:0px">';
2623
                $form .= $result;
2624
                $form .= '</tr>';
2625
                $form .= '<tr class="tableWithFloatingHeader row_odd tableFloatingHeaderOriginal">';
2626
                $form .= $result;
2627
                $form .= '</tr>';
2628
                $form .= '</thead>';
2629
                $form .= '<tbody>';
2630
                $i = 0;
2631
                foreach ($users_in_course as $user) {
2632
                    $class = '';
2633
                    if (0 == $i % 2) {
2634
                        $class = 'row_even';
2635
                    } else {
2636
                        $class = 'row_odd';
2637
                    }
2638
                    $form .= '<tr class="'.$class.'">';
2639
2640
                    if (count($attendant_calendar) > 0) {
2641
                        foreach ($attendant_calendar as $calendar) {
2642
                            $checked = 'checked';
2643
                            $presence = -1;
2644
2645
                            if (isset($users_presence[$user['user_id']][$calendar['iid']]['presence'])) {
2646
                                $presence = $users_presence[$user['user_id']][$calendar['iid']]['presence'];
2647
                                if (1 == (int) $presence) {
2648
                                    $checked = 'checked';
2649
                                } else {
2650
                                    $checked = '';
2651
                                }
2652
                            } else {
2653
                                //if the user wasn't registered at that time, consider unchecked
2654
                                if (0 == $next_attendance_calendar_datetime ||
2655
                                    $calendar['date_time'] < $next_attendance_calendar_datetime
2656
                                ) {
2657
                                    $checked = '';
2658
                                }
2659
                            }
2660
                            $disabled = 'disabled';
2661
                            $style_td = '';
2662
2663
                            if ($next_attendance_calendar_id == $calendar['iid']) {
2664
                                if (0 == $i % 2) {
2665
                                    $style_td = 'background-color:#eee;';
2666
                                } else {
2667
                                    $style_td = 'background-color:#dcdcdc;';
2668
                                }
2669
                                $disabled = '';
2670
                            }
2671
2672
                            $form .= '<td style="'.$style_td.'" class="checkboxes_col_'.$calendar['iid'].'">';
2673
                            $form .= '<div class="check">';
2674
2675
                            if (api_is_allowed_to_edit(null, true)) {
2676
                                if (!$is_locked_attendance || api_is_platform_admin()) {
2677
                                    $form .= '<input
2678
                                    type="checkbox" name="check_presence['.$calendar['iid'].'][]" value="'.$user['user_id'].'" '.$disabled.' '.$checked.' />';
2679
                                    $form .= '<span class="anchor_'.$calendar['iid'].'"></span>';
2680
                                } else {
2681
                                    $form .= $presence ? Display::return_icon(
2682
                                        'checkbox_on.png',
2683
                                        get_lang('Assistance'),
2684
                                        null,
2685
                                        ICON_SIZE_TINY
2686
                                    ) : Display::return_icon(
2687
                                        'checkbox_off.png',
2688
                                        get_lang('Assistance'),
2689
                                        null,
2690
                                        ICON_SIZE_TINY
2691
                                    );
2692
                                }
2693
                            } else {
2694
                                switch ($presence) {
2695
                                    case 1:
2696
                                        $form .= Display::return_icon('accept.png', get_lang('Attended'));
2697
2698
                                        break;
2699
                                    case 0:
2700
                                        $form .= Display::return_icon('exclamation.png', get_lang('Not attended'));
2701
2702
                                        break;
2703
                                    case -1:
2704
                                        break;
2705
                                }
2706
                            }
2707
2708
                            $form .= '</div>';
2709
                            $form .= '</td>';
2710
                        }
2711
                    } else {
2712
                        $calendarClass = null;
2713
                        if (isset($calendar)) {
2714
                            $calendarClass = 'checkboxes_col_'.$calendar['iid'];
2715
                        }
2716
                        $form .= '<td class="'.$calendarClass.'">';
2717
                        $form .= '<div>';
2718
                        $form .= '<center>&nbsp;</center>
2719
                                </div>
2720
                                </td>';
2721
                    }
2722
                    echo '</tr>';
2723
                    $i++;
2724
                }
2725
                $form .= '</tbody></table>';
2726
                $form .= '</div></div>';
2727
2728
                $form .= '<div class="row">
2729
                            <div class="col-md-12">';
2730
                if (!$is_locked_attendance || api_is_platform_admin()) {
2731
                    if (api_is_allowed_to_edit(null, true)) {
2732
                        $form .= '<button type="submit" class="btn btn-primary">'.get_lang('Save').'</button>';
2733
                    }
2734
                }
2735
                $form .= '</div>
2736
                        </div>
2737
                </form>';
2738
                $content .= $form;
2739
            } else {
2740
                $content .= Display::return_message(
2741
                    '<a href="'.api_get_path(WEB_CODE_PATH).'user/user.php?'.api_get_cidreq().'">'.
2742
                    get_lang('There are no registered learners inside the course').'</a>',
2743
                    'warning',
2744
                    false
2745
                );
2746
            }
2747
        } else {
2748
            $content .= Display::page_header(get_lang('Report of attendance sheets'));
2749
            if (!empty($users_presence)) {
2750
                $content .= '
2751
                <div>
2752
                    <table width="250px;">
2753
                        <tr>
2754
                            <td>'.get_lang('To attend').': </td>
2755
                            <td>
2756
                                <center>
2757
                                <div
2758
                                    class="attendance-faults-bar"
2759
                                    style="background-color:'.(!empty($faults['color_bar']) ? $faults['color_bar'] : 'none').'">
2760
                                        '.$faults['faults'].'/'.$faults['total'].' ('.$faults['faults_porcent'].'%)
2761
                                </div>
2762
                                </center>
2763
                            </td>
2764
                        </tr>
2765
                    </table>
2766
                </div>';
2767
            }
2768
2769
            $content .= '<table class="data_table">
2770
                <tr class="row_odd" >
2771
                    <th>'.get_lang('Attendance').'</th>
2772
                </tr>';
2773
2774
            if (!empty($users_presence)) {
2775
                $i = 0;
2776
                foreach ($users_presence[$user_id] as $presence) {
2777
                    $class = '';
2778
                    if (0 == $i % 2) {
2779
                        $class = 'row_even';
2780
                    } else {
2781
                        $class = 'row_odd';
2782
                    }
2783
2784
                    $check = $presence['presence'] ? Display::return_icon('checkbox_on.png', get_lang('Assistance'), null, ICON_SIZE_TINY) : Display::return_icon('checkbox_off.png', get_lang('Assistance'), null, ICON_SIZE_TINY);
2785
                    $content .= '<tr class="'.$class.'">
2786
                            <td>
2787
                                '.$check.'&nbsp; '.$presence['date_time'].'
2788
                            </td>
2789
                        </tr>';
2790
                }
2791
            } else {
2792
                $content .= '
2793
                        <tr>
2794
                            <td>
2795
                            <center>'.get_lang('You do not have attendances').'</center>
2796
                            </td>
2797
                        </tr>';
2798
            }
2799
            $content .= ' </table>';
2800
        }
2801
2802
        return $content;
2803
    }
2804
2805
    /**
2806
     * It's used to print attendance sheet.
2807
     *
2808
     * @param string $action
2809
     * @param int    $attendance_id
2810
     */
2811
    public function attendance_sheet_export_to_pdf(
2812
        $attendance_id,
2813
        $student_id = 0,
2814
        $course_id = ''
2815
    ) {
2816
        $courseInfo = api_get_course_info($course_id);
2817
        $this->set_course_id($courseInfo['code']);
2818
        $groupId = isset($_REQUEST['group_id']) ? $_REQUEST['group_id'] : null;
2819
        $data_array = [];
2820
        $data_array['attendance_id'] = $attendance_id;
2821
        $data_array['users_in_course'] = $this->get_users_rel_course($attendance_id, $groupId);
2822
2823
        $filter_type = 'today';
2824
2825
        if (!empty($_REQUEST['filter'])) {
2826
            $filter_type = $_REQUEST['filter'];
2827
        }
2828
2829
        $my_calendar_id = null;
2830
        if (is_numeric($filter_type)) {
2831
            $my_calendar_id = $filter_type;
2832
            $filter_type = 'calendar_id';
2833
        }
2834
2835
        $data_array['attendant_calendar'] = $this->get_attendance_calendar(
2836
            $attendance_id,
2837
            $filter_type,
2838
            $my_calendar_id,
2839
            $groupId
2840
        );
2841
2842
        if (api_is_allowed_to_edit(null, true) || api_is_drh()) {
2843
            $data_array['users_presence'] = $this->get_users_attendance_sheet($attendance_id, 0, $groupId);
2844
        } else {
2845
            if (!empty($student_id)) {
2846
                $user_id = (int) $student_id;
2847
            } else {
2848
                $user_id = api_get_user_id();
2849
            }
2850
            $data_array['users_presence'] = $this->get_users_attendance_sheet($attendance_id, $user_id, $groupId);
2851
            $data_array['faults'] = $this->get_faults_of_user($user_id, $attendance_id, $groupId);
2852
            $data_array['user_id'] = $user_id;
2853
        }
2854
2855
        $data_array['next_attendance_calendar_id'] = $this->get_next_attendance_calendar_id($attendance_id);
2856
2857
        // Set headers pdf.
2858
        $courseCategory = CourseManager::get_course_category($courseInfo['categoryCode']);
2859
        $teacherInfo = CourseManager::get_teacher_list_from_course_code($courseInfo['code']);
2860
        $teacherName = null;
2861
        foreach ($teacherInfo as $teacherData) {
2862
            if (null != $teacherName) {
2863
                $teacherName .= ' / ';
2864
            }
2865
            $teacherName .= api_get_person_name($teacherData['firstname'], $teacherData['lastname']);
2866
        }
2867
2868
        // Get data table
2869
        $data_table = [];
2870
        $head_table = ['#', get_lang('Name')];
2871
        foreach ($data_array['attendant_calendar'] as $class_day) {
2872
            $head_table[] =
2873
                api_format_date($class_day['date_time'], DATE_FORMAT_NUMBER_NO_YEAR).' '.
2874
                api_format_date($class_day['date_time'], TIME_NO_SEC_FORMAT);
2875
        }
2876
        $data_table[] = $head_table;
2877
        $data_attendant_calendar = $data_array['attendant_calendar'];
2878
        $data_users_presence = $data_array['users_presence'];
2879
        $count = 1;
2880
2881
        if (!empty($data_array['users_in_course'])) {
2882
            foreach ($data_array['users_in_course'] as $user) {
2883
                $cols = 1;
2884
                $result = [];
2885
                $result['count'] = $count;
2886
                $result['full_name'] = api_get_person_name($user['firstname'], $user['lastname']);
2887
                foreach ($data_array['attendant_calendar'] as $class_day) {
2888
                    if (1 == $class_day['done_attendance']) {
2889
                        if (1 == $data_users_presence[$user['user_id']][$class_day['id']]['presence']) {
2890
                            $result[$class_day['id']] = get_lang('P');
2891
                        } else {
2892
                            $result[$class_day['id']] = '<span style="color:red">'.get_lang('NP').'</span>';
2893
                        }
2894
                    } else {
2895
                        $result[$class_day['id']] = ' ';
2896
                    }
2897
                    $cols++;
2898
                }
2899
                $count++;
2900
                $data_table[] = $result;
2901
            }
2902
        }
2903
        $max_cols_per_page = 12; //10 dates + 2 name and number
2904
        $max_dates_per_page = $max_dates_per_page_original = $max_cols_per_page - 2; //10
2905
        $rows = count($data_table);
2906
2907
        if ($cols > $max_cols_per_page) {
2908
            $number_tables = round(($cols - 2) / $max_dates_per_page);
2909
            $headers = $data_table[0];
2910
            $all = [];
2911
            $tables = [];
2912
            $changed = 1;
2913
2914
            for ($i = 0; $i <= $rows; $i++) {
2915
                $row = isset($data_table[$i]) ? $data_table[$i] : null;
2916
                $key = 1;
2917
                $max_dates_per_page = 10;
2918
                $item = isset($data_table[$i]) ? $data_table[$i] : null;
2919
                $count_j = 0;
2920
2921
                if (!empty($item)) {
2922
                    foreach ($item as $value) {
2923
                        if ($count_j >= $max_dates_per_page) {
2924
                            $key++;
2925
                            $max_dates_per_page = $max_dates_per_page_original * $key;
2926
                            //magic hack
2927
                            $tables[$key][$i][] = $tables[1][$i][0];
2928
                            $tables[$key][$i][] = $tables[1][$i][1];
2929
                        }
2930
                        $tables[$key][$i][] = $value;
2931
                        $count_j++;
2932
                    }
2933
                }
2934
            }
2935
2936
            $content = null;
2937
            if (!empty($tables)) {
2938
                foreach ($tables as $sub_table) {
2939
                    $content .= Export::convert_array_to_html($sub_table).'<br /><br />';
2940
                }
2941
            }
2942
        } else {
2943
            $content = Export::convert_array_to_html(
2944
                $data_table,
2945
                ['header_attributes' => ['align' => 'center']]
2946
            );
2947
        }
2948
2949
        $params = [
2950
            'filename' => get_lang('Attendance').'-'.api_get_local_time(),
2951
            'pdf_title' => $courseInfo['title'],
2952
            'course_code' => $courseInfo['code'],
2953
            'add_signatures' => ['Drh', 'Teacher', 'Date'],
2954
            'pdf_teachers' => $teacherName,
2955
            'pdf_course_category' => $courseCategory ? $courseCategory['name'] : '',
2956
            'format' => 'A4-L',
2957
            'orientation' => 'L',
2958
        ];
2959
2960
        Export::export_html_to_pdf($content, $params);
2961
        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...
2962
    }
2963
2964
    /**
2965
     * Gets attendance base in the table:
2966
     * TABLE_STATISTIC_TRACK_E_COURSE_ACCESS.
2967
     *
2968
     * @param bool $showForm
2969
     * @param bool $exportToPdf
2970
     */
2971
    public function getAttendanceBaseInLogin($showForm = false, $exportToPdf = true)
2972
    {
2973
        $table = null;
2974
        $formToDisplay = null;
2975
        $startDate = null;
2976
        $endDate = null;
2977
2978
        $sessionId = api_get_session_id();
2979
        if ($showForm) {
2980
            $form = new FormValidator(
2981
                'search',
2982
                'post',
2983
                api_get_self().'?'.api_get_cidreq().'&action=calendar_logins'
2984
            );
2985
            $form->addDateRangePicker('range', get_lang('Date range'));
2986
            $form->addButton('submit', get_lang('Submit'));
2987
2988
            if ($form->validate()) {
2989
                $values = $form->getSubmitValues();
2990
                $startDate = api_get_utc_datetime($values['range_start']);
2991
                $endDate = api_get_utc_datetime($values['range_end']);
2992
            }
2993
            $formToDisplay = $form->returnForm();
2994
        } else {
2995
            if (!empty($sessionId)) {
2996
                $sessionInfo = api_get_session_info($sessionId);
2997
                $startDate = $sessionInfo['access_start_date'];
2998
                $endDate = $sessionInfo['access_end_date'];
2999
            }
3000
        }
3001
3002
        if ($exportToPdf) {
3003
            $result = $this->exportAttendanceLogin($startDate, $endDate);
3004
            if (empty($result)) {
3005
                api_not_allowed(true, get_lang('No data available'));
3006
            }
3007
        }
3008
3009
        $table = $this->getAttendanceLoginTable($startDate, $endDate);
3010
3011
        return [
3012
            'form' => $formToDisplay,
3013
            'table' => $table,
3014
        ];
3015
    }
3016
}
3017