Completed
Push — master ( c65fe1...e7429e )
by Julito
11:34
created

Attendance::deleteAttendanceCalendarGroup()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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