Completed
Push — master ( ac9b94...2050b8 )
by Julito
11:32
created

Attendance::set_name()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Framework\Container;
6
use Chamilo\CourseBundle\Entity\CAttendance;
7
use Chamilo\CourseBundle\Entity\CAttendanceCalendar;
8
9
class Attendance
10
{
11
    public const DONE_ATTENDANCE_LOG_TYPE = 'done_attendance_sheet';
12
    public const UPDATED_ATTENDANCE_LOG_TYPE = 'updated_attendance_sheet';
13
    public const LOCKED_ATTENDANCE_LOG_TYPE = 'locked_attendance_sheet';
14
    public $category_id;
15
    private $session_id;
16
    private $course_id;
17
    private $date_time;
18
    private $name;
19
    private $description;
20
    private $attendance_qualify_title;
21
    private $attendance_weight;
22
    private $course_int_id;
23
24
    /**
25
     * Get attendance list only the id, name and attendance_qualify_max fields.
26
     *
27
     * @param int $courseId
28
     * @param int $sessionId
29
     *
30
     * @return CAttendance[]
31
     */
32
    public function get_attendances_list($courseId = 0, $sessionId = 0)
33
    {
34
        $repo = Container::getAttendanceRepository();
35
36
        $course = api_get_course_entity($courseId);
37
        $session = api_get_session_entity($sessionId);
38
39
        $qb = $repo->getResourcesByCourse($course, $session, null);
40
        //$qb->select('resource');
41
        $qb->andWhere('resource.active = 1');
42
43
        return $qb->getQuery()->getResult();
44
45
        $table = Database::get_course_table(TABLE_ATTENDANCE);
0 ignored issues
show
Unused Code introduced by
$table = Database::get_c...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...
46
        $course_id = (int) $course_id;
47
        if (empty($course_id)) {
48
            $course_id = api_get_course_int_id();
49
        }
50
51
        $session_id = !empty($session_id) ? (int) $session_id : api_get_session_id();
52
        $condition_session = api_get_session_condition($session_id);
53
54
        // Get attendance data
55
        $sql = "SELECT iid, name, attendance_qualify_max
56
                FROM $table
57
                WHERE active = 1 $condition_session ";
58
        $result = Database::query($sql);
59
        $data = [];
60
        if (Database::num_rows($result) > 0) {
61
            while ($row = Database::fetch_array($result, 'ASSOC')) {
62
                $data[$row['iid']] = $row;
63
            }
64
        }
65
66
        return $data;
67
    }
68
69
    /**
70
     * Get the total number of attendance inside current course and current session.
71
     *
72
     * @return int
73
     *
74
     * @see SortableTable#get_total_number_of_items()
75
     */
76
    public static function getNumberOfAttendances()
77
    {
78
        $repo = Container::getAttendanceRepository();
79
80
        $course = api_get_course_entity(api_get_course_int_id());
81
        $session = api_get_session_entity(api_get_session_id());
82
        $group = api_get_group_entity(api_get_group_id());
83
84
        $qb = $repo->getResourcesByCourse($course, $session, $group);
85
        $qb->select('count(resource)');
86
        $qb->andWhere('resource.active <> 2');
87
88
        if ((isset($_GET['isStudentView']) && 'true' == $_GET['isStudentView']) ||
89
            !api_is_allowed_to_edit(null, true)
90
        ) {
91
            $qb
92
                ->andWhere('resource.active = :active')
93
                ->setParameter('active', 1);
94
            //$active_plus = ' AND att.active = 1';
95
        }
96
97
        return $qb->getQuery()->getSingleScalarResult();
98
99
        $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...
100
        $session_id = api_get_session_id();
101
        $condition_session = '';
102
103
        $active_plus = '';
104
        if ((isset($_GET['isStudentView']) && 'true' == $_GET['isStudentView']) ||
105
            !api_is_allowed_to_edit(null, true)
106
        ) {
107
            $active_plus = ' AND att.active = 1';
108
        }
109
110
        $sql = "SELECT COUNT(att.iid) AS total_number_of_items
111
                FROM $tbl_attendance att
112
                WHERE
113
                      active <> 2 $active_plus $condition_session  ";
114
        /*$active = (int) $active;
115
        if ($active === 1 || $active === 0) {
116
            $sql .= "AND att.active = $active";
117
        }*/
118
        $res = Database::query($sql);
119
        $obj = Database::fetch_object($res);
120
121
        return (int) $obj->total_number_of_items;
122
    }
123
124
    /**
125
     * Get the attendances to display on the current page (fill the sortable-table).
126
     *
127
     * @param   int     offset of first user to recover
128
     * @param   int     Number of users to get
129
     * @param   int     Column to sort on
130
     * @param   string  Order (ASC,DESC)
131
     *
132
     * @see SortableTable#get_table_data($from)
133
     *
134
     * @return array
135
     */
136
    public static function getAttendanceData(
137
        $from,
138
        $number_of_items,
139
        $column,
140
        $direction
141
    ) {
142
        $repo = Container::getAttendanceRepository();
143
144
        $course = api_get_course_entity(api_get_course_int_id());
145
        $session = api_get_session_entity(api_get_session_id());
146
        $group = api_get_group_entity(api_get_group_id());
147
148
        $qb = $repo->getResourcesByCourse($course, $session, $group);
149
        $qb->select('resource');
150
        $qb->andWhere('resource.active <> 2');
151
152
        if ((isset($_GET['isStudentView']) && 'true' == $_GET['isStudentView']) ||
153
            !api_is_allowed_to_edit(null, true)
154
        ) {
155
            $qb
156
                ->andWhere('resource.active = :active')
157
                ->setParameter('active', 1);
158
            //$active_plus = ' AND att.active = 1';
159
        }
160
161
        $qb
162
            ->setFirstResult($from)
163
            ->setMaxResults($number_of_items)
164
        ;
165
166
        if (!in_array($direction, ['ASC', 'DESC'])) {
167
            $direction = 'ASC';
168
        }
169
170
        $attendances = $qb->getQuery()->getResult();
171
172
        $allowDelete = api_get_setting('allow_delete_attendance');
173
        $student_param = '';
174
        $studentRequestId = isset($_GET['student_id']) ? (int) $_GET['student_id'] : 0;
175
        if (api_is_drh() && !empty($studentRequestId)) {
176
            $student_param = '&student_id='.$studentRequestId;
177
        }
178
179
        $list = [];
180
        /** @var CAttendance $attendance */
181
        foreach ($attendances as $attendance) {
182
            $row = [];
183
            $id = $attendance->getIid();
184
            $name = $attendance->getName();
185
            $active = $attendance->getActive();
186
            $session_star = '';
187
            /*if ($session_id == $attendance[6]) {
188
                $session_star = api_get_session_image($session_id, $user_info['status']);
189
            }*/
190
            if (1 == $active) {
191
                $isDrhOfCourse = CourseManager::isUserSubscribedInCourseAsDrh(
192
                    api_get_user_id(),
193
                    api_get_course_info()
194
                ) || api_is_drh();
195
                if ($isDrhOfCourse || api_is_allowed_to_edit(null, true)) {
196
                    // Link to edit
197
                    $row[1] = '<a href="index.php?'.api_get_cidreq().'&action=attendance_sheet_list&attendance_id='.$id.$student_param.'">'.$name.'</a>'.$session_star;
198
                } else {
199
                    // Link to view
200
                    $row[1] = '<a href="index.php?'.api_get_cidreq().'&action=attendance_sheet_list_no_edit&attendance_id='.$id.$student_param.'">'.$name.'</a>'.$session_star;
201
                }
202
            } else {
203
                $row[1] = '<a class="muted" href="index.php?'.api_get_cidreq().'&action=attendance_sheet_list&attendance_id='.$id.$student_param.'">'.$name.'</a>'.$session_star;
204
            }
205
206
            if (1 == $active) {
207
                $row[3] = '<center>'.$attendance->getAttendanceQualifyMax().'</center>';
208
            } else {
209
                $row[3] = '<center><span class="muted">'.$attendance->getAttendanceQualifyMax().'</span></center>';
210
            }
211
            $row[2] = '';
212
            $row[3] = '<center>'.$row[3].'</center>';
213
            if (api_is_allowed_to_edit(null, true)) {
214
                $actions = '';
215
                $actions .= '<center>';
216
                if (api_is_platform_admin()) {
217
                    $actions .= '<a href="index.php?'.api_get_cidreq().'&action=attendance_edit&attendance_id='.$id.'">'.
218
                        Display::return_icon('edit.png', get_lang('Edit'), [], ICON_SIZE_SMALL).'</a>&nbsp;';
219
                    // Visible
220
                    if (1 == $active) {
221
                        $actions .= '<a href="index.php?'.api_get_cidreq().'&action=attendance_set_invisible&attendance_id='.$id.'">'.
222
                            Display::return_icon('visible.png', get_lang('Hide'), [], ICON_SIZE_SMALL).'</a>';
223
                    } else {
224
                        $actions .= '<a href="index.php?'.api_get_cidreq().'&action=attendance_set_visible&attendance_id='.$id.'">'.
225
                            Display::return_icon('invisible.png', get_lang('Show'), [], ICON_SIZE_SMALL).'</a>';
226
                        $row[2] = '<span class="muted">'.$attendance->getDescription().'</span>';
227
                    }
228
                    if ('true' === $allowDelete) {
229
                        $actions .= '<a href="index.php?'.api_get_cidreq().'&action=attendance_delete&attendance_id='.$id.'">'.
230
                            Display::return_icon('delete.png', get_lang('Delete'), [], ICON_SIZE_SMALL).'</a>';
231
                    }
232
                } else {
233
                    $is_locked_attendance = self::is_locked_attendance($id);
234
                    if ($is_locked_attendance) {
235
                        $actions .= Display::return_icon('edit_na.png', get_lang('Edit')).'&nbsp;';
236
                        $actions .= Display::return_icon('visible.png', get_lang('Hide'));
237
                    } else {
238
                        $actions .= '<a href="index.php?'.api_get_cidreq().'&action=attendance_edit&attendance_id='.$id.'">'.
239
                            Display::return_icon('edit.png', get_lang('Edit'), [], ICON_SIZE_SMALL).'</a>&nbsp;';
240
241
                        if (1 == $active) {
242
                            $actions .= ' <a href="index.php?'.api_get_cidreq().'&action=attendance_set_invisible&attendance_id='.$id.'">'.
243
                                Display::return_icon('visible.png', get_lang('Hide'), [], ICON_SIZE_SMALL).'</a>';
244
                        } else {
245
                            $actions .= ' <a href="index.php?'.api_get_cidreq().'&action=attendance_set_visible&attendance_id='.$id.'">'.
246
                                Display::return_icon('invisible.png', get_lang('Show'), [], ICON_SIZE_SMALL).'</a>';
247
                            $row[2] = '<span class="muted">'.$attendance->getDescription().'</span>';
248
                        }
249
                        if ('true' === $allowDelete) {
250
                            $actions .= ' <a href="index.php?'.api_get_cidreq().'&action=attendance_delete&attendance_id='.$id.'">'.
251
                                Display::return_icon('delete.png', get_lang('Delete'), [], ICON_SIZE_SMALL).'</a>';
252
                        }
253
                    }
254
                }
255
256
                // display lock/unlock icon
257
                $is_done_all_calendar = self::is_all_attendance_calendar_done($id);
258
259
                if ($is_done_all_calendar) {
260
                    $locked = $attendance->getLocked();
261
                    if (0 == $locked) {
262
                        if (api_is_platform_admin()) {
263
                            $message_alert = get_lang('Are you sure you want to lock the attendance?');
264
                        } else {
265
                            $message_alert = get_lang('The attendance is not locked, which means your teacher is still able to modify it.');
266
                        }
267
                        $actions .= '&nbsp;<a
268
                            onclick="javascript:if(!confirm(\''.$message_alert.'\')) return false;"
269
                            href="index.php?'.api_get_cidreq().'&action=lock_attendance&attendance_id='.$id.'">'.
270
                            Display::return_icon('unlock.png', get_lang('Lock attendance')).'</a>';
271
                    } else {
272
                        if (api_is_platform_admin()) {
273
                            $actions .= '&nbsp;<a
274
                            onclick="javascript:if(!confirm(\''.get_lang('Are you sure you want to unlock the attendance?').'\')) return false;"
275
                            href="index.php?'.api_get_cidreq().'&action=unlock_attendance&attendance_id='.$id.'">'.
276
                                    Display::return_icon('locked.png', get_lang('Unlock attendance')).'</a>';
277
                        } else {
278
                            $actions .= '&nbsp;'.Display::return_icon('locked_na.png', get_lang('Locked attendance'));
279
                        }
280
                    }
281
                }
282
                $actions .= '</center>';
283
284
                $list[] = [
285
                    $id,
286
                    $row[1],
287
                    $row[2],
288
                    $row[3],
289
                    $actions,
290
                ];
291
            } else {
292
                $id = '&nbsp;';
293
                $list[] = [
294
                    $id,
295
                    $row[1],
296
                    $row[2],
297
                    $row[3],
298
                ];
299
            }
300
        }
301
302
        return $list;
303
    }
304
305
    /**
306
     * Get the attendances by id to display on the current page.
307
     *
308
     * @param int $attendanceId
309
     *
310
     * @return array attendance data
311
     */
312
    public function get_attendance_by_id($attendanceId)
313
    {
314
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
315
        $attendanceId = (int) $attendanceId;
316
317
        $attendance_data = [];
318
        $sql = "SELECT * FROM $tbl_attendance
319
                WHERE iid = $attendanceId";
320
        $res = Database::query($sql);
321
        if (Database::num_rows($res) > 0) {
322
            while ($row = Database::fetch_array($res)) {
323
                $attendance_data = $row;
324
            }
325
        }
326
327
        return $attendance_data;
328
    }
329
330
    /**
331
     * Add attendances sheet inside table. This is the *list of* dates, not
332
     * a specific date in itself.
333
     *
334
     * @param  bool   true for adding link in gradebook or false otherwise (optional)
335
     *
336
     * @return int last attendance id
337
     */
338
    public function attendance_add($link_to_gradebook = false)
339
    {
340
        $_course = api_get_course_info();
341
        $table_link = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
342
        $session_id = api_get_session_id();
343
        $course_code = $_course['code'];
344
        $title_gradebook = $this->attendance_qualify_title;
345
        $value_calification = 0;
346
        $weight_calification = api_float_val($this->attendance_weight);
347
        $course = api_get_course_entity();
348
        $attendance = new CAttendance();
349
        $attendance
350
            ->setName($this->name)
351
            ->setDescription($this->description)
352
            ->setAttendanceQualifyTitle($title_gradebook)
353
            ->setAttendanceWeight($weight_calification)
354
            ->setParent($course)
355
            ->addCourseLink($course, api_get_session_entity())
356
        ;
357
358
        $repo = Container::getAttendanceRepository();
359
        $repo->create($attendance);
360
        $last_id = $attendance->getIid();
361
362
        // add link to gradebook
363
        if ($link_to_gradebook && !empty($this->category_id)) {
364
            $description = '';
365
            $link_info = GradebookUtils::isResourceInCourseGradebook(
366
                $course_code,
367
                7,
368
                $last_id,
369
                $session_id
370
            );
371
            $link_id = $link_info['id'];
372
            if (!$link_info) {
373
                GradebookUtils::add_resource_to_course_gradebook(
374
                    $this->category_id,
375
                    $course_code,
376
                    7,
377
                    $last_id,
378
                    $title_gradebook,
379
                    $weight_calification,
380
                    $value_calification,
381
                    $description,
382
                    1,
383
                    $session_id
384
                );
385
            } else {
386
                Database::query('UPDATE '.$table_link.' SET weight='.$weight_calification.' WHERE iid='.$link_id.'');
387
            }
388
        }
389
390
        return $last_id;
391
    }
392
393
    /**
394
     * edit attendances inside table.
395
     *
396
     * @param CAttendance $attendance
397
     * @param bool true for adding link in gradebook or false otherwise (optional)
398
     *
399
     * @return int last id
400
     */
401
    public function attendance_edit($attendance, $link_to_gradebook = false)
402
    {
403
        $_course = api_get_course_info();
404
        $table_link = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
405
        $session_id = api_get_session_id();
406
        $course_code = $_course['code'];
407
        $title_gradebook = $this->attendance_qualify_title;
408
        $value_calification = 0;
409
        $weight_calification = api_float_val($this->attendance_weight);
410
411
        if ($attendance) {
0 ignored issues
show
introduced by
$attendance is of type Chamilo\CourseBundle\Entity\CAttendance, thus it always evaluated to true.
Loading history...
412
            $attendanceId = $attendance->getIid();
413
            $attendance
414
                ->setName($this->name)
415
                ->setDescription($this->description)
416
                ->setAttendanceQualifyTitle($title_gradebook)
417
                ->setAttendanceWeight($weight_calification)
418
            ;
419
420
            $repo = Container::getAttendanceRepository();
421
            $repo->update($attendance);
422
423
            /*$params = [
424
                'name' => $this->name,
425
                'description' => $this->description,
426
                'attendance_qualify_title' => $title_gradebook,
427
                'attendance_weight' => $weight_calification,
428
            ];
429
            Database::update(
430
                $tbl_attendance,
431
                $params,
432
                ['c_id = ? AND id = ?' => [$course_id, $attendanceId]]
433
            );
434
            api_item_property_update(
435
                $_course,
436
                TOOL_ATTENDANCE,
437
                $attendanceId,
438
                "AttendanceUpdated",
439
                $user_id
440
            );*/
441
442
            // add link to gradebook
443
            if ($link_to_gradebook && !empty($this->category_id)) {
444
                $description = '';
445
                $link_info = GradebookUtils::isResourceInCourseGradebook(
446
                    $course_code,
447
                    7,
448
                    $attendanceId,
449
                    $session_id
450
                );
451
                if (!$link_info) {
452
                    GradebookUtils::add_resource_to_course_gradebook(
453
                        $this->category_id,
454
                        $course_code,
455
                        7,
456
                        $attendanceId,
457
                        $title_gradebook,
458
                        $weight_calification,
459
                        $value_calification,
460
                        $description,
461
                        1,
462
                        $session_id
463
                    );
464
                } else {
465
                    Database::query('UPDATE '.$table_link.' SET weight='.$weight_calification.' WHERE iid='.$link_info['id']);
466
                }
467
            }
468
469
            return $attendanceId;
470
        }
471
472
        return null;
473
    }
474
475
    /**
476
     * Restore attendance.
477
     *
478
     * @param int|array one or many attendances id
479
     *
480
     * @return int affected rows
481
     */
482
    public function attendance_restore($attendanceId)
483
    {
484
        $_course = api_get_course_info();
485
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
486
        $user_id = api_get_user_id();
487
        $course_id = $_course['real_id'];
488
        if (is_array($attendanceId)) {
489
            foreach ($attendanceId as $id) {
490
                $id = (int) $id;
491
                $sql = "UPDATE $tbl_attendance SET active = 1
492
                        WHERE iid = '$id'";
493
                $result = Database::query($sql);
494
                $affected_rows = Database::affected_rows($result);
495
                if (!empty($affected_rows)) {
496
                    // update row item property table
497
                    /*api_item_property_update(
498
                        $_course,
499
                        TOOL_ATTENDANCE,
500
                        $id,
501
                        'restore',
502
                        $user_id
503
                    );*/
504
                }
505
            }
506
        } else {
507
            $attendanceId = (int) $attendanceId;
508
            $sql = "UPDATE $tbl_attendance SET active = 1
509
                    WHERE iid = '$attendanceId'";
510
            $result = Database::query($sql);
511
            $affected_rows = Database::affected_rows($result);
512
            if (!empty($affected_rows)) {
513
                // update row item property table
514
                /*api_item_property_update(
515
                    $_course,
516
                    TOOL_ATTENDANCE,
517
                    $attendanceId,
518
                    'restore',
519
                    $user_id
520
                );*/
521
            }
522
        }
523
524
        return $affected_rows;
525
    }
526
527
    /**
528
     * Delete attendances.
529
     *
530
     * @param CAttendance $attendance one or many attendances id
531
     *
532
     * @return bool
533
     */
534
    public function attendance_delete(CAttendance $attendance)
535
    {
536
        $allowDeleteAttendance = api_get_setting('allow_delete_attendance');
537
        if ('true' !== $allowDeleteAttendance) {
538
            return false;
539
        }
540
541
        $repo = Container::getAttendanceRepository();
542
        $attendance->setActive(2);
543
        $repo->update($attendance);
544
545
        Skill::deleteSkillsFromItem($attendance->getIid(), ITEM_TYPE_ATTENDANCE);
546
547
        return true;
548
549
        /*$_course = api_get_course_info();
550
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
551
        $user_id = api_get_user_id();
552
        $course_id = $_course['real_id'];
553
554
        $attendanceId = (int) $attendanceId;
555
        $sql = "UPDATE $tbl_attendance SET active = 2
556
                WHERE c_id = $course_id AND id = '$attendanceId'";
557
558
        $result = Database::query($sql);
559
        $affected_rows = Database::affected_rows($result);
560
        if (!empty($affected_rows)) {
561
            // update row item property table
562
            api_item_property_update(
563
                $_course,
564
                TOOL_ATTENDANCE,
565
                $attendanceId,
566
                "delete",
567
                $user_id
568
            );
569
        }return $affected_rows;
570
        */
571
    }
572
573
    /**
574
     * Changes visibility.
575
     *
576
     * @param CAttendance $attendance one or many attendances id
577
     * @param int         $status
578
     *
579
     * @return int affected rows
580
     */
581
    public function changeVisibility(CAttendance $attendance, $status = 1)
582
    {
583
        $status = (int) $status;
584
585
        $repo = Container::getAttendanceRepository();
586
        $attendance->setActive($status);
587
        $repo->update($attendance);
588
589
        return true;
590
        /*
591
592
        $attendanceId = (int) $attendanceId;
593
        $sql = "UPDATE $tbl_attendance SET active = $status
594
                WHERE c_id = $course_id AND id = '$attendanceId'";
595
        $result = Database::query($sql);
596
        $affected_rows = Database::affected_rows($result);
597
        if (!empty($affected_rows)) {
598
            // update row item property table
599
            api_item_property_update(
600
                $_course,
601
                TOOL_ATTENDANCE,
602
                $attendanceId,
603
                $action,
604
                $user_id
605
            );
606
        }
607
608
        return $affected_rows;
609
        */
610
    }
611
612
    /**
613
     * Lock or unlock an attendance.
614
     *
615
     * @param bool    True to lock or false otherwise
616
     *
617
     * @return bool
618
     */
619
    public function lock(CAttendance $attendance, $lock = true)
620
    {
621
        $repo = Container::getAttendanceRepository();
622
        $attendance->setLocked($lock);
623
        $repo->update($attendance);
624
625
        return true;
626
627
        $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...
628
        $course_id = api_get_course_int_id();
629
        $attendanceId = (int) $attendanceId;
630
        $locked = $lock ? 1 : 0;
631
        $upd = "UPDATE $tbl_attendance SET locked = $locked
632
                WHERE iid = $attendanceId";
633
        $result = Database::query($upd);
634
        $affected_rows = Database::affected_rows($result);
635
        if ($affected_rows && $lock) {
636
            // Save attendance sheet log
637
            $this->saveAttendanceSheetLog(
638
                $attendanceId,
639
                api_get_utc_datetime(),
640
                self::LOCKED_ATTENDANCE_LOG_TYPE,
641
                api_get_user_id()
642
            );
643
        }
644
645
        return $affected_rows;
646
    }
647
648
    /**
649
     * Get registered users inside current course.
650
     *
651
     * @param int $attendanceId attendance id for showing attendance result field (optional)
652
     * @param int $groupId
653
     *
654
     * @return array users data
655
     */
656
    public function get_users_rel_course($attendanceId = 0, $groupId = 0)
657
    {
658
        $current_session_id = api_get_session_id();
659
        $current_course_id = api_get_course_id();
660
        $currentCourseIntId = api_get_course_int_id();
661
        $studentInGroup = [];
662
663
        if (!empty($current_session_id)) {
664
            $a_course_users = CourseManager:: get_user_list_from_course_code(
665
                $current_course_id,
666
                $current_session_id,
667
                '',
668
                'lastname'
669
            );
670
        } else {
671
            $a_course_users = CourseManager:: get_user_list_from_course_code(
672
                $current_course_id,
673
                0,
674
                '',
675
                'lastname'
676
            );
677
        }
678
679
        if (!empty($groupId)) {
680
            $groupInfo = GroupManager::get_group_properties($groupId);
681
            $students = GroupManager::getStudents($groupInfo['iid']);
682
            if (!empty($students)) {
683
                foreach ($students as $student) {
684
                    $studentInGroup[$student['user_id']] = true;
685
                }
686
            }
687
        }
688
689
        // get registered users inside current course
690
        $a_users = [];
691
        foreach ($a_course_users as $key => $user_data) {
692
            $value = [];
693
            $uid = $user_data['user_id'];
694
            $userInfo = api_get_user_info($uid);
695
            $status = $user_data['status'];
696
697
            if (!empty($groupId)) {
698
                if (!isset($studentInGroup[$uid])) {
699
                    continue;
700
                }
701
            }
702
703
            $user_status_in_session = null;
704
            $user_status_in_course = null;
705
706
            if (api_get_session_id()) {
707
                $user_status_in_session = SessionManager::get_user_status_in_course_session(
708
                    $uid,
709
                    $currentCourseIntId,
710
                    $current_session_id
711
                );
712
            } else {
713
                $user_status_in_course = CourseManager::getUserInCourseStatus(
714
                    $uid,
715
                    $currentCourseIntId
716
                );
717
            }
718
719
            // Not taking into account DRH or COURSEMANAGER
720
            if ($uid <= 1 ||
721
                DRH == $status ||
722
                COURSEMANAGER == $user_status_in_course ||
723
                2 == $user_status_in_session
724
            ) {
725
                continue;
726
            }
727
728
            if (!empty($attendanceId)) {
729
                $user_faults = $this->get_faults_of_user(
730
                    $uid,
731
                    $attendanceId,
732
                    $groupId
733
                );
734
                $value['attendance_result'] = $user_faults['faults'].'/'.$user_faults['total'].' ('.$user_faults['faults_porcent'].'%)';
735
                $value['result_color_bar'] = $user_faults['color_bar'];
736
            }
737
738
            $photo = Display::img(
739
                $userInfo['avatar_small'],
740
                $userInfo['complete_name'],
741
                [],
742
                false
743
            );
744
745
            $value['photo'] = $photo;
746
            $value['firstname'] = $user_data['firstname'];
747
            $value['lastname'] = $user_data['lastname'];
748
            $value['username'] = $user_data['username'];
749
            $value['user_id'] = $uid;
750
751
            // Sending only 5 items in the array instead of 60
752
            $a_users[$key] = $value;
753
        }
754
755
        return $a_users;
756
    }
757
758
    /**
759
     * add attendances sheet inside table.
760
     *
761
     * @param int   $calendar_id   attendance calendar id
762
     * @param array $users_present present users during current class
763
     * @param int   $attendanceId
764
     *
765
     * @return int affected rows
766
     */
767
    public function attendance_sheet_add($calendar_id, $users_present, $attendanceId)
768
    {
769
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
770
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
771
772
        $calendar_id = (int) $calendar_id;
773
        $attendanceId = (int) $attendanceId;
774
        $users = $this->get_users_rel_course();
775
        $course_id = api_get_course_int_id();
776
777
        $user_ids = array_keys($users);
778
        $users_absent = array_diff($user_ids, $users_present);
779
        $affected_rows = 0;
780
781
        // get last edit type
782
        $calendar_data = $this->get_attendance_calendar_by_id($calendar_id);
783
        $lastedit_type = self::DONE_ATTENDANCE_LOG_TYPE;
784
        if ($calendar_data['done_attendance']) {
785
            $lastedit_type = self::UPDATED_ATTENDANCE_LOG_TYPE;
786
        }
787
788
        // save users present in class
789
        foreach ($users_present as $user_present) {
790
            $uid = (int) $user_present;
791
            // check if user already was registered with the $calendar_id
792
            $sql = "SELECT user_id FROM $tbl_attendance_sheet
793
                    WHERE c_id = $course_id AND user_id='$uid' AND attendance_calendar_id = '$calendar_id'";
794
            $rs = Database::query($sql);
795
            if (0 == Database::num_rows($rs)) {
796
                $sql = "INSERT INTO $tbl_attendance_sheet SET
797
                        c_id = $course_id,
798
                        user_id = '$uid',
799
                        attendance_calendar_id = '$calendar_id',
800
                        presence = 1";
801
                $result = Database::query($sql);
802
803
                $affected_rows += Database::affected_rows($result);
804
            } else {
805
                $sql = "UPDATE $tbl_attendance_sheet SET presence = 1
806
                        WHERE
807
                            c_id = $course_id AND
808
                            user_id ='$uid' AND
809
                            attendance_calendar_id = '$calendar_id'
810
                        ";
811
                $result = Database::query($sql);
812
                $affected_rows += Database::affected_rows($result);
813
            }
814
        }
815
816
        // save users absent in class
817
        foreach ($users_absent as $user_absent) {
818
            $uid = (int) $user_absent;
819
            // check if user already was registered with the $calendar_id
820
            $sql = "SELECT user_id FROM $tbl_attendance_sheet
821
                    WHERE c_id = $course_id AND user_id='$uid' AND attendance_calendar_id = '$calendar_id'";
822
            $rs = Database::query($sql);
823
            if (0 == Database::num_rows($rs)) {
824
                $sql = "INSERT INTO $tbl_attendance_sheet SET
825
                        c_id = $course_id,
826
                        user_id ='$uid',
827
                        attendance_calendar_id = '$calendar_id',
828
                        presence = 0";
829
                $result = Database::query($sql);
830
                $affected_rows += Database::affected_rows($result);
831
            } else {
832
                $sql = "UPDATE $tbl_attendance_sheet SET presence = 0
833
                        WHERE
834
                            c_id = $course_id AND
835
                            user_id ='$uid' AND
836
                            attendance_calendar_id = '$calendar_id'";
837
                $result = Database::query($sql);
838
                $affected_rows += Database::affected_rows($result);
839
            }
840
        }
841
842
        // update done_attendance inside attendance calendar table
843
        $sql = "UPDATE $tbl_attendance_calendar SET done_attendance = 1
844
                WHERE  iid = '$calendar_id'";
845
        Database::query($sql);
846
847
        // save users' results
848
        $this->updateUsersResults($user_ids, $attendanceId);
849
850
        if ($affected_rows) {
851
            //save attendance sheet log
852
            $this->saveAttendanceSheetLog(
853
                $attendanceId,
854
                api_get_utc_datetime(),
855
                $lastedit_type,
856
                api_get_user_id(),
857
                $calendar_data['date_time']
858
            );
859
        }
860
861
        return $affected_rows;
862
    }
863
864
    /**
865
     * update users' attendance results.
866
     *
867
     * @param array $user_ids     registered users inside current course
868
     * @param int   $attendanceId
869
     */
870
    public function updateUsersResults($user_ids, $attendanceId)
871
    {
872
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
873
        $tbl_attendance_result = Database::get_course_table(TABLE_ATTENDANCE_RESULT);
874
        $tbl_attendance = Database::get_course_table(TABLE_ATTENDANCE);
875
        $course_id = api_get_course_int_id();
876
        $attendanceId = (int) $attendanceId;
877
        // fill results about presence of students
878
        $attendance_calendar = $this->get_attendance_calendar(
879
            $attendanceId,
880
            'all',
881
            null,
882
            null,
883
            true
884
        );
885
        $calendar_ids = [];
886
        // get all dates from calendar by current attendance
887
        foreach ($attendance_calendar as $cal) {
888
            $calendar_ids[] = $cal['iid'];
889
        }
890
891
        // get count of presences by users inside current attendance and save like results
892
        if (count($user_ids) > 0) {
893
            foreach ($user_ids as $uid) {
894
                $uid = (int) $uid;
895
                $count_presences = 0;
896
                if (count($calendar_ids) > 0) {
897
                    $sql = "SELECT count(presence) as count_presences
898
                            FROM $tbl_attendance_sheet
899
                            WHERE
900
                                c_id = $course_id AND
901
                                user_id = '$uid' AND
902
                                attendance_calendar_id IN (".implode(',', $calendar_ids).') AND
903
                                presence = 1';
904
                    $rs_count = Database::query($sql);
905
                    $row_count = Database::fetch_array($rs_count);
906
                    $count_presences = $row_count['count_presences'];
907
                }
908
909
                // save results
910
                $sql = "SELECT iid FROM $tbl_attendance_result
911
                        WHERE
912
                            c_id = $course_id AND
913
                            user_id = '$uid' AND
914
                            attendance_id = '$attendanceId' ";
915
                $rs_check_result = Database::query($sql);
916
917
                if (Database::num_rows($rs_check_result) > 0) {
918
                    // update result
919
                    $sql = "UPDATE $tbl_attendance_result SET
920
                            score = '$count_presences'
921
                            WHERE
922
                                c_id = $course_id AND
923
                                user_id='$uid' AND
924
                                attendance_id='$attendanceId'";
925
                    Database::query($sql);
926
                } else {
927
                    // insert new result
928
                    $sql = "INSERT INTO $tbl_attendance_result SET
929
                            c_id = $course_id ,
930
                            user_id			= '$uid',
931
                            attendance_id 	= '$attendanceId',
932
                            score			= '$count_presences'";
933
                    Database::query($sql);
934
                    $insertId = Database::insert_id();
935
                }
936
            }
937
        }
938
939
        // update attendance qualify max
940
        $count_done_calendar = self::get_done_attendance_calendar($attendanceId);
941
        $sql = "UPDATE $tbl_attendance SET
942
                    attendance_qualify_max = '$count_done_calendar'
943
                WHERE iid = '$attendanceId'";
944
        Database::query($sql);
945
    }
946
947
    /**
948
     * update attendance_sheet_log table, is used as history of an attendance sheet.
949
     *
950
     * @param   int     Attendance id
951
     * @param   string  Last edit datetime
952
     * @param   string  Event type ('locked_attendance', 'done_attendance_sheet' ...)
953
     * @param   int     Last edit user id
954
     * @param   string  Calendar datetime value (optional, when event type is 'done_attendance_sheet')
955
     *
956
     * @return int Affected rows
957
     */
958
    public function saveAttendanceSheetLog(
959
        $attendanceId,
960
        $lastedit_date,
961
        $lastedit_type,
962
        $lastedit_user_id,
963
        $calendar_date_value = null
964
    ) {
965
        $course_id = api_get_course_int_id();
966
967
        // define table
968
        $tbl_attendance_sheet_log = Database::get_course_table(TABLE_ATTENDANCE_SHEET_LOG);
969
970
        // protect data
971
        $attendanceId = (int) $attendanceId;
972
        $lastedit_user_id = (int) $lastedit_user_id;
973
974
        if (isset($calendar_date_value)) {
975
            $calendar_date_value = $calendar_date_value;
976
        } else {
977
            $calendar_date_value = '';
978
        }
979
980
        // save data
981
        $params = [
982
            'c_id' => $course_id,
983
            'attendance_id' => $attendanceId,
984
            'lastedit_date' => $lastedit_date,
985
            'lastedit_type' => $lastedit_type,
986
            'lastedit_user_id' => $lastedit_user_id,
987
            'calendar_date_value' => $calendar_date_value,
988
        ];
989
990
        return Database::insert($tbl_attendance_sheet_log, $params);
991
    }
992
993
    /**
994
     * Get number of done attendances inside current sheet.
995
     *
996
     * @param int attendance id
997
     *
998
     * @return int number of done attendances
999
     */
1000
    public static function get_done_attendance_calendar($attendanceId)
1001
    {
1002
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1003
        $attendanceId = (int) $attendanceId;
1004
        $course_id = api_get_course_int_id();
1005
        $sql = "SELECT count(done_attendance) as count
1006
                FROM $table
1007
                WHERE
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 = $this->get_attendances_list($course_id);
1100
1101
            foreach ($attendances as $attendance) {
1102
                $attendanceId = $attendance->getIid();
1103
                // get total faults and total weight
1104
                $total_done_attendance = $attendance->getAttendanceQualifyMax();
1105
                $sql = "SELECT score
1106
                        FROM $tbl_attendance_result
1107
                        WHERE
1108
                            c_id = $course_id AND
1109
                            user_id = $user_id AND
1110
                            attendance_id = ".$attendanceId;
1111
                $rs = Database::query($sql);
1112
                $score = 0;
1113
                if (Database::num_rows($rs) > 0) {
1114
                    $row = Database::fetch_array($rs);
1115
                    $score = $row['score'];
1116
                }
1117
                $faults = $total_done_attendance - $score;
1118
                $faults = $faults > 0 ? $faults : 0;
1119
                $total_faults += $faults;
1120
                $total_weight += $total_done_attendance;
1121
            }
1122
        }
1123
1124
        $percent = $total_weight > 0 ? round(($total_faults * 100) / $total_weight, 0) : 0;
1125
        $results['faults'] = $total_faults;
1126
        $results['total'] = $total_weight;
1127
        $results['percent'] = $percent;
1128
1129
        return $results;
1130
    }
1131
1132
    /**
1133
     * Get results of faults average by course.
1134
     *
1135
     * @param int    $user_id
1136
     * @param string $course_code
1137
     * @param int Session id (optional)
1138
     *
1139
     * @return array results containing number of faults,
1140
     *               total done attendance, percent of faults and color depend on result (red, orange)
1141
     */
1142
    public function get_faults_average_by_course($user_id, $course_code, $session_id = null)
1143
    {
1144
        // Database tables and variables
1145
        $course_info = api_get_course_info($course_code);
1146
        $tbl_attendance_result = Database::get_course_table(TABLE_ATTENDANCE_RESULT);
1147
        $user_id = (int) $user_id;
1148
        $results = [];
1149
        $total_faults = $total_weight = $porcent = 0;
1150
        $attendances = $this->get_attendances_list($course_info['real_id'], $session_id);
1151
1152
        foreach ($attendances as $attendance) {
1153
            $attendanceId = $attendance->getIid();
1154
            // Get total faults and total weight
1155
            $total_done_attendance = $attendance->getAttendanceQualifyMax();
1156
            $sql = "SELECT score FROM $tbl_attendance_result
1157
                    WHERE
1158
                        c_id = {$course_info['real_id']} AND
1159
                        user_id = $user_id AND
1160
                        attendance_id=".$attendanceId;
1161
            $rs = Database::query($sql);
1162
            $score = 0;
1163
            if (Database::num_rows($rs) > 0) {
1164
                $row = Database::fetch_array($rs);
1165
                $score = $row['score'];
1166
            }
1167
            $faults = $total_done_attendance - $score;
1168
            $faults = $faults > 0 ? $faults : 0;
1169
            $total_faults += $faults;
1170
            $total_weight += $total_done_attendance;
1171
        }
1172
1173
        $percent = $total_weight > 0 ? round(($total_faults * 100) / $total_weight, 0) : 0;
1174
        $results['faults'] = $total_faults;
1175
        $results['total'] = $total_weight;
1176
        $results['percent'] = $percent;
1177
1178
        return $results;
1179
    }
1180
1181
    /**
1182
     * Get registered users' attendance sheet inside current course.
1183
     *
1184
     * @param int $attendanceId
1185
     * @param int $user_id      for showing data for only one user (optional)
1186
     * @param int $groupId
1187
     *
1188
     * @return array users attendance sheet data
1189
     */
1190
    public function get_users_attendance_sheet(
1191
        $attendanceId,
1192
        $user_id = 0,
1193
        $groupId = 0,
1194
        $course_id = 0,
1195
        DateTime $startDate = null,
1196
        DateTime $endDate = null
1197
    ) {
1198
        //Get actual course or by course_id
1199
        $course_id = (0 == $course_id) ? api_get_course_int_id() : (int) $course_id;
1200
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
1201
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1202
        $attendance_calendar = $this->get_attendance_calendar(
1203
            $attendanceId,
1204
            'all',
1205
            null,
1206
            $groupId,
1207
            true,
1208
            $course_id,
1209
            $startDate,
1210
            $endDate
1211
        );
1212
        $calendar_ids = [];
1213
        // get all dates from calendar by current attendance
1214
        foreach ($attendance_calendar as $cal) {
1215
            $calendar_ids[] = $cal['iid'];
1216
        }
1217
1218
        $whereDate = '';
1219
        if (!empty($startDate)) {
1220
            $whereDate .= " AND cal.date_time >= '".$startDate->format('Y-m-d H:i:s')."'";
1221
        }
1222
        if (!empty($endDate)) {
1223
            $whereDate .= " AND cal.date_time <= '".$endDate->format('Y-m-d H:i:s')."'";
1224
        }
1225
1226
        // moved at start of this function
1227
        // $course_id = api_get_course_int_id();
1228
1229
        $data = [];
1230
        if (empty($user_id)) {
1231
            // get all registered users inside current course
1232
            $users = $this->get_users_rel_course();
1233
            $user_ids = array_keys($users);
1234
            if (count($calendar_ids) > 0 && count($user_ids) > 0) {
1235
                foreach ($user_ids as $uid) {
1236
                    $uid = (int) $uid;
1237
                    $sql = "SELECT * FROM $tbl_attendance_sheet
1238
                            WHERE
1239
                                c_id = $course_id AND
1240
                                user_id = '$uid' AND
1241
                                attendance_calendar_id IN(".implode(',', $calendar_ids).')
1242
                            ';
1243
                    $res = Database::query($sql);
1244
                    if (Database::num_rows($res) > 0) {
1245
                        while ($row = Database::fetch_array($res)) {
1246
                            $data[$uid][$row['attendance_calendar_id']]['presence'] = $row['presence'];
1247
                        }
1248
                    }
1249
                }
1250
            }
1251
        } else {
1252
            // Get attendance for current user
1253
            $user_id = (int) $user_id;
1254
            if (count($calendar_ids) > 0) {
1255
                $sql = "SELECT cal.date_time, att.presence
1256
                        FROM $tbl_attendance_sheet att
1257
                        INNER JOIN  $tbl_attendance_calendar cal
1258
                        ON cal.iid = att.attendance_calendar_id
1259
                        WHERE
1260
                            att.c_id = $course_id AND
1261
                            att.user_id = '$user_id' AND
1262
                            att.attendance_calendar_id IN (".implode(',', $calendar_ids).")
1263
                            $whereDate
1264
                        ORDER BY date_time";
1265
                $res = Database::query($sql);
1266
                if (Database::num_rows($res) > 0) {
1267
                    while ($row = Database::fetch_array($res)) {
1268
                        $row['date_time'] = api_convert_and_format_date($row['date_time'], null, date_default_timezone_get());
1269
                        $data[$user_id][] = $row;
1270
                    }
1271
                }
1272
            }
1273
        }
1274
1275
        return $data;
1276
    }
1277
1278
    /**
1279
     * Get next attendance calendar without presences (done attendances).
1280
     *
1281
     * @param int    attendance id
1282
     *
1283
     * @return int attendance calendar id
1284
     */
1285
    public function get_next_attendance_calendar_id($attendanceId)
1286
    {
1287
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1288
        $attendanceId = (int) $attendanceId;
1289
        $course_id = api_get_course_int_id();
1290
1291
        $sql = "SELECT iid FROM $table
1292
                WHERE
1293
                    attendance_id = '$attendanceId' AND
1294
                    done_attendance = 0
1295
                ORDER BY date_time
1296
                LIMIT 1";
1297
        $rs = Database::query($sql);
1298
        $next_calendar_id = 0;
1299
        if (Database::num_rows($rs) > 0) {
1300
            $row = Database::fetch_array($rs);
1301
            $next_calendar_id = $row['iid'];
1302
        }
1303
1304
        return $next_calendar_id;
1305
    }
1306
1307
    /**
1308
     * Get next attendance calendar datetime without presences (done attendances).
1309
     *
1310
     * @param int    attendance id
1311
     *
1312
     * @return int UNIX time format datetime
1313
     */
1314
    public function getNextAttendanceCalendarDatetime($attendanceId)
1315
    {
1316
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1317
        $course_id = api_get_course_int_id();
1318
        $attendanceId = (int) $attendanceId;
1319
        $sql = "SELECT iid, date_time FROM $table
1320
                WHERE
1321
                    attendance_id = '$attendanceId' AND
1322
                    done_attendance = 0
1323
                ORDER BY date_time
1324
                LIMIT 1";
1325
        $rs = Database::query($sql);
1326
        $next_calendar_datetime = 0;
1327
        if (Database::num_rows($rs) > 0) {
1328
            $row = Database::fetch_array($rs);
1329
            $next_calendar_datetime = api_get_local_time($row['date_time']);
1330
        }
1331
1332
        return $next_calendar_datetime;
1333
    }
1334
1335
    /**
1336
     * Get user's score from current attendance.
1337
     *
1338
     * @param int $user_id
1339
     * @param int $attendanceId
1340
     * @param int $groupId
1341
     *
1342
     * @return int score
1343
     */
1344
    public function get_user_score($user_id, $attendanceId, $groupId = 0)
1345
    {
1346
        $tbl_attendance_result = Database::get_course_table(TABLE_ATTENDANCE_RESULT);
1347
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
1348
        $tbl_attendance_cal_rel_group = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1349
        $tbl_attendance_cal = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1350
        $user_id = (int) $user_id;
1351
        $attendanceId = (int) $attendanceId;
1352
        $groupId = (int) $groupId;
1353
        $course_id = api_get_course_int_id();
1354
1355
        if (empty($groupId)) {
1356
            $sql = "SELECT score FROM $tbl_attendance_result
1357
                    WHERE
1358
                        c_id = $course_id AND
1359
                        user_id='$user_id' AND
1360
                        attendance_id='$attendanceId'";
1361
        } else {
1362
            $sql = "SELECT count(presence) as score
1363
                    FROM $tbl_attendance_sheet
1364
                    WHERE
1365
                        c_id = $course_id AND
1366
                        user_id='$user_id' AND
1367
                        presence = 1 AND
1368
                        attendance_calendar_id IN (
1369
                            SELECT calendar_id FROM $tbl_attendance_cal_rel_group crg
1370
                            INNER JOIN $tbl_attendance_cal c
1371
                            ON (crg.calendar_id = c.iid)
1372
                            WHERE
1373
                                crg.c_id = $course_id AND
1374
                                crg.group_id = $groupId AND
1375
                                c.attendance_id = $attendanceId
1376
                        )
1377
                    ";
1378
        }
1379
        $rs = Database::query($sql);
1380
        $score = 0;
1381
        if (Database::num_rows($rs) > 0) {
1382
            $row = Database::fetch_array($rs);
1383
            $score = $row['score'];
1384
        }
1385
1386
        return $score;
1387
    }
1388
1389
    /**
1390
     * Get attendance calendar data by id.
1391
     *
1392
     * @param int    attendance calendar id
1393
     *
1394
     * @return array attendance calendar data
1395
     */
1396
    public function get_attendance_calendar_by_id($calendar_id)
1397
    {
1398
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1399
        $calendar_id = (int) $calendar_id;
1400
        $course_id = api_get_course_int_id();
1401
        $sql = "SELECT * FROM $table
1402
                WHERE iid = '$calendar_id' ";
1403
        $rs = Database::query($sql);
1404
        $data = [];
1405
        if (Database::num_rows($rs) > 0) {
1406
            while ($row = Database::fetch_array($rs)) {
1407
                $row['date_time'] = api_get_local_time($row['date_time']);
1408
                $data = $row;
1409
            }
1410
        }
1411
1412
        return $data;
1413
    }
1414
1415
    /**
1416
     * Get all attendance calendar data inside current attendance.
1417
     *
1418
     * @param int      $attendanceId
1419
     * @param string   $type
1420
     * @param int      $calendar_id
1421
     * @param int      $groupId
1422
     * @param bool     $showAll      = false show group calendar items or not
1423
     * @param int      $course_id
1424
     * @param DateTime $startDate    Filter calendar with a start date
1425
     * @param DateTime $endDate      Filter calendar with a end date
1426
     *
1427
     * @return array attendance calendar data
1428
     */
1429
    public function get_attendance_calendar(
1430
        $attendanceId,
1431
        $type = 'all',
1432
        $calendar_id = null,
1433
        $groupId = 0,
1434
        $showAll = false,
1435
        $course_id = 0,
1436
        DateTime $startDate = null,
1437
        DateTime $endDate = null
1438
    ) {
1439
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1440
        $tbl_acrg = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1441
        $attendanceId = (int) $attendanceId;
1442
        $course_id = 0 == $course_id ? api_get_course_int_id() : (int) $course_id;
1443
        $whereDate = '';
1444
        if (!empty($startDate)) {
1445
            $whereDate .= " AND c.date_time >= '".$startDate->format('Y-m-d H:i:s')."'";
1446
        }
1447
        if (!empty($endDate)) {
1448
            $whereDate .= " AND c.date_time <= '".$endDate->format('Y-m-d H:i:s')."'";
1449
        }
1450
        if ($showAll) {
1451
            $sql = "SELECT * FROM $tbl_attendance_calendar c
1452
                    WHERE
1453
                        attendance_id = '$attendanceId'
1454
                        $whereDate";
1455
        } else {
1456
            $sql = "SELECT * FROM $tbl_attendance_calendar c
1457
                    WHERE
1458
                        attendance_id = '$attendanceId' AND
1459
                        iid NOT IN (
1460
                            SELECT calendar_id FROM $tbl_acrg
1461
                            WHERE c_id = $course_id AND group_id != 0 AND group_id IS NOT NULL
1462
                        )
1463
                        $whereDate
1464
                    ";
1465
        }
1466
1467
        if (!empty($groupId)) {
1468
            $groupId = (int) $groupId;
1469
            $sql = "SELECT c.* FROM $tbl_attendance_calendar c
1470
                    INNER JOIN $tbl_acrg g
1471
                    ON c.iid = g.calendar_id
1472
                    WHERE
1473
                        g.group_id = '$groupId' AND
1474
                        c.attendance_id = '$attendanceId'
1475
                   ";
1476
        }
1477
1478
        if (!in_array($type, ['today', 'all', 'all_done', 'all_not_done', 'calendar_id'])) {
1479
            $type = 'all';
1480
        }
1481
1482
        switch ($type) {
1483
            case 'calendar_id':
1484
                $calendar_id = (int) $calendar_id;
1485
                if (!empty($calendar_id)) {
1486
                    $sql .= " AND c.iid = $calendar_id";
1487
                }
1488
                break;
1489
            case 'today':
1490
                //$sql .= ' AND DATE_FORMAT(date_time,"%d-%m-%Y") = DATE_FORMAT("'.api_get_utc_datetime().'", "%d-%m-%Y" )';
1491
                break;
1492
            case 'all_done':
1493
                $sql .= ' AND done_attendance = 1 ';
1494
                break;
1495
            case 'all_not_done':
1496
                $sql .= ' AND done_attendance = 0 ';
1497
                break;
1498
            case 'all':
1499
            default:
1500
                break;
1501
        }
1502
        $sql .= ' ORDER BY date_time ';
1503
1504
        $rs = Database::query($sql);
1505
        $data = [];
1506
        if (Database::num_rows($rs) > 0) {
1507
            while ($row = Database::fetch_array($rs, 'ASSOC')) {
1508
                $row['db_date_time'] = $row['date_time'];
1509
                $row['date_time'] = api_get_local_time($row['date_time']);
1510
                $row['date'] = api_format_date($row['date_time'], DATE_FORMAT_SHORT);
1511
                $row['time'] = api_format_date($row['date_time'], TIME_NO_SEC_FORMAT);
1512
                $row['groups'] = $this->getGroupListByAttendanceCalendar($row['iid'], $course_id);
1513
                if ('today' === $type) {
1514
                    if (date('d-m-Y', api_strtotime($row['date_time'], 'UTC')) == date('d-m-Y', time())) {
1515
                        $data[] = $row;
1516
                    }
1517
                } else {
1518
                    $data[] = $row;
1519
                }
1520
            }
1521
        }
1522
1523
        return $data;
1524
    }
1525
1526
    /**
1527
     * Get number of attendance calendar inside current attendance.
1528
     *
1529
     * @param int $attendanceId
1530
     * @param int $groupId
1531
     * @param $done_attendance
1532
     * @param int $userId
1533
     *
1534
     * @return int number of dates in attendance calendar
1535
     */
1536
    public static function get_number_of_attendance_calendar(
1537
        $attendanceId,
1538
        $groupId = 0,
1539
        $done_attendance = null,
1540
        $userId = 0
1541
    ) {
1542
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1543
        $calendarRelGroup = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1544
        $tbl_groupRelUser = Database::get_course_table(TABLE_GROUP_USER);
1545
        $attendanceId = (int) $attendanceId;
1546
        $groupId = (int) $groupId;
1547
        $course_id = api_get_course_int_id();
1548
1549
        $where_attendance = '';
1550
        if ($done_attendance) {
1551
            $where_attendance = ' done_attendance = 1 AND ';
1552
        }
1553
        if (empty($userId)) {
1554
            if (empty($groupId)) {
1555
                $sql = "SELECT count(a.iid)
1556
                        FROM $tbl_attendance_calendar a
1557
                        WHERE
1558
                            $where_attendance
1559
                            attendance_id = '$attendanceId' AND
1560
                            iid NOT IN (
1561
                                SELECT calendar_id FROM $calendarRelGroup
1562
                                WHERE
1563
                                    c_id = $course_id AND
1564
                                    group_id != 0 AND
1565
                                    group_id IS NOT NULL
1566
                            )
1567
                        ";
1568
            } else {
1569
                $sql = "SELECT count(a.iid)
1570
                        FROM $tbl_attendance_calendar a
1571
                        INNER JOIN $calendarRelGroup g
1572
                        ON (a.iid = g.calendar_id)
1573
                        WHERE
1574
                            $where_attendance
1575
                            attendance_id = '$attendanceId' AND
1576
                            group_id = $groupId
1577
                        ";
1578
            }
1579
        } else {
1580
            if (empty($groupId)) {
1581
                $sql = "SELECT count(a.iid)
1582
                        FROM $tbl_attendance_calendar a
1583
                        WHERE
1584
                            $where_attendance
1585
                            attendance_id = '$attendanceId' AND
1586
                            iid NOT IN (
1587
                                SELECT calendar_id FROM $calendarRelGroup
1588
                                WHERE
1589
                                    c_id = $course_id AND
1590
                                    group_id != 0 AND
1591
                                    group_id IS NOT NULL AND
1592
                                    group_id NOT IN (
1593
                                        SELECT group_id
1594
                                        FROM $tbl_groupRelUser
1595
                                        WHERE user_id = $userId
1596
                                    )
1597
                            )
1598
                        ";
1599
            } else {
1600
                $sql = "SELECT count(a.iid)
1601
                        FROM $tbl_attendance_calendar a
1602
                        INNER JOIN $calendarRelGroup g
1603
                        ON (a.iid = g.calendar_id)
1604
                        WHERE
1605
                            $where_attendance
1606
                            attendance_id = '$attendanceId' AND
1607
                            group_id = $groupId
1608
                        ";
1609
            }
1610
        }
1611
1612
        $rs = Database::query($sql);
1613
        $row = Database::fetch_row($rs);
1614
1615
        return $row[0];
1616
    }
1617
1618
    /**
1619
     * Get count dates inside attendance calendar by attendance id.
1620
     *
1621
     * @param int $attendanceId
1622
     *
1623
     * @return int count of dates
1624
     */
1625
    public static function get_count_dates_inside_attendance_calendar($attendanceId)
1626
    {
1627
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1628
        $attendanceId = (int) $attendanceId;
1629
        $course_id = api_get_course_int_id();
1630
        $sql = "SELECT count(iid) FROM $tbl_attendance_calendar
1631
                WHERE
1632
                    attendance_id = '$attendanceId'";
1633
        $rs = Database::query($sql);
1634
        $count = 0;
1635
        if (Database::num_rows($rs) > 0) {
1636
            $row = Database::fetch_row($rs);
1637
            $count = $row[0];
1638
        }
1639
1640
        return $count;
1641
    }
1642
1643
    /**
1644
     * check if all calendar of an attendance is done.
1645
     *
1646
     * @param int $attendanceId
1647
     *
1648
     * @return bool True if all calendar is done, otherwise false
1649
     */
1650
    public static function is_all_attendance_calendar_done($attendanceId)
1651
    {
1652
        $attendanceId = (int) $attendanceId;
1653
        $done_calendar = self::get_done_attendance_calendar($attendanceId);
1654
        $count_dates_in_calendar = self::get_count_dates_inside_attendance_calendar($attendanceId);
1655
        $number_of_dates = self::get_number_of_attendance_calendar($attendanceId);
1656
1657
        $result = false;
1658
        if ($number_of_dates && intval($count_dates_in_calendar) == intval($done_calendar)) {
1659
            $result = true;
1660
        }
1661
1662
        return $result;
1663
    }
1664
1665
    /**
1666
     * check if an attendance is locked.
1667
     *
1668
     * @param int $attendanceId
1669
     * @param bool
1670
     *
1671
     * @return bool
1672
     */
1673
    public static function is_locked_attendance($attendanceId)
1674
    {
1675
        //  Use gradebook lock
1676
        return api_resource_is_locked_by_gradebook($attendanceId, LINK_ATTENDANCE);
1677
    }
1678
1679
    /**
1680
     * Add new datetime inside attendance calendar table.
1681
     *
1682
     * @param CAttendance $attendance
1683
     * @param array       $groupList
1684
     *
1685
     * @return int affected rows
1686
     */
1687
    public function attendance_calendar_add($attendance, $groupList = [])
1688
    {
1689
        $attendanceId = $attendance->getIid();
1690
        $course_id = api_get_course_int_id();
1691
1692
        $calendar = new CAttendanceCalendar();
1693
        $calendar
1694
            ->setAttendanceId($attendanceId)
1695
            ->setDateTime(new Datetime($this->date_time))
1696
            ->setDoneAttendance(0);
1697
1698
        $em = Database::getManager();
1699
        $em->persist($calendar);
1700
        $em->flush();
1701
1702
        $this->addAttendanceCalendarToGroup($calendar->getIid(), $course_id, $groupList);
1703
1704
        // update locked attendance
1705
        $is_all_calendar_done = $this->is_all_attendance_calendar_done($attendanceId);
1706
        if (!$is_all_calendar_done) {
1707
            $this->lock($attendance, false);
1708
        } else {
1709
            $this->lock($attendance);
1710
        }
1711
1712
        return true;
1713
    }
1714
1715
    /**
1716
     * @param int   $calendarId
1717
     * @param int   $courseId
1718
     * @param array $groupList
1719
     *
1720
     * @return bool
1721
     */
1722
    public function addAttendanceCalendarToGroup($calendarId, $courseId, $groupList)
1723
    {
1724
        if (empty($groupList)) {
1725
            return false;
1726
        }
1727
1728
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1729
        foreach ($groupList as $groupId) {
1730
            if (empty($groupId)) {
1731
                continue;
1732
            }
1733
1734
            $result = $this->getAttendanceCalendarGroup(
1735
                $calendarId,
1736
                $courseId,
1737
                $groupId
1738
            );
1739
1740
            if (empty($result)) {
1741
                $params = [
1742
                    'calendar_id' => $calendarId,
1743
                    'c_id' => $courseId,
1744
                    'group_id' => $groupId,
1745
                ];
1746
                Database::insert($table, $params);
1747
            }
1748
        }
1749
1750
        return true;
1751
    }
1752
1753
    /**
1754
     * @param int $calendarId
1755
     * @param int $courseId
1756
     *
1757
     * @return array
1758
     */
1759
    public function getGroupListByAttendanceCalendar($calendarId, $courseId)
1760
    {
1761
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1762
1763
        return Database::select(
1764
            '*',
1765
            $table,
1766
            [
1767
                'where' => [
1768
                    'calendar_id = ? AND c_id = ?' => [$calendarId, $courseId],
1769
                ],
1770
            ]
1771
        );
1772
    }
1773
1774
    /**
1775
     * @param int $calendarId
1776
     * @param int $courseId
1777
     * @param int $groupId
1778
     *
1779
     * @return array
1780
     */
1781
    public function getAttendanceCalendarGroup($calendarId, $courseId, $groupId)
1782
    {
1783
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1784
1785
        return Database::select(
1786
            '*',
1787
            $table,
1788
            [
1789
                'where' => [
1790
                    'calendar_id = ? AND c_id = ? AND group_id = ?' => [$calendarId, $courseId, $groupId],
1791
                ],
1792
            ]
1793
        );
1794
    }
1795
1796
    /**
1797
     * @param int $calendarId
1798
     * @param int $courseId
1799
     */
1800
    public function deleteAttendanceCalendarGroup($calendarId, $courseId)
1801
    {
1802
        $table = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR_REL_GROUP);
1803
        Database::delete(
1804
            $table,
1805
            [
1806
                'calendar_id = ? AND c_id = ?' => [$calendarId, $courseId],
1807
            ]
1808
        );
1809
    }
1810
1811
    /**
1812
     * save repeated date inside attendance calendar table.
1813
     *
1814
     * @param CAttendance $attendance
1815
     * @param int         $start_date  start date in tms
1816
     * @param int         $end_date    end date in tms
1817
     * @param string      $repeat_type daily, weekly, monthlyByDate
1818
     * @param array       $groupList
1819
     */
1820
    public function attendance_repeat_calendar_add(
1821
        $attendance,
1822
        $start_date,
1823
        $end_date,
1824
        $repeat_type,
1825
        $groupList = []
1826
    ) {
1827
        $attendanceId = $attendance->getIid();
1828
        // save start date
1829
        $this->set_date_time(api_get_utc_datetime($start_date));
1830
        $this->attendance_calendar_add($attendance, $groupList);
1831
1832
        // 86400 = 24 hours in seconds
1833
        // 604800 = 1 week in seconds
1834
        // Saves repeated dates
1835
        switch ($repeat_type) {
1836
            case 'daily':
1837
                $j = 1;
1838
                for ($i = $start_date + 86400; ($i <= $end_date); $i += 86400) {
1839
                    $this->set_date_time(api_get_utc_datetime($i));
1840
                    $this->attendance_calendar_add($attendance, $groupList);
1841
                    $j++;
1842
                }
1843
                break;
1844
            case 'weekly':
1845
                $j = 1;
1846
                for ($i = $start_date + 604800; ($i <= $end_date); $i += 604800) {
1847
                    $this->set_date_time(api_get_utc_datetime($i));
1848
                    $this->attendance_calendar_add($attendance, $groupList);
1849
                    $j++;
1850
                }
1851
                break;
1852
            case 'monthlyByDate':
1853
                $j = 1;
1854
                //@todo fix bug with february
1855
                for ($i = $start_date + 2419200; ($i <= $end_date); $i += 2419200) {
1856
                    $this->set_date_time(api_get_utc_datetime($i));
1857
                    $this->attendance_calendar_add($attendanceId, $groupList);
1858
                    $j++;
1859
                }
1860
                break;
1861
        }
1862
    }
1863
1864
    /**
1865
     * edit a datetime inside attendance calendar table.
1866
     *
1867
     * @param int         $calendar_id
1868
     * @param CAttendance $attendance
1869
     *
1870
     * @return int affected rows
1871
     */
1872
    public function attendance_calendar_edit($calendar_id, $attendance)
1873
    {
1874
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1875
        $affected_rows = 0;
1876
        $attendanceId = $attendance->getIid();
1877
1878
        $course_id = api_get_course_int_id();
1879
        // check if datetime already exists inside the table
1880
        $sql = "SELECT iid FROM $tbl_attendance_calendar
1881
                WHERE
1882
                    date_time = '".Database::escape_string($this->date_time)."' AND
1883
                    attendance_id = '$attendanceId'";
1884
        $rs = Database::query($sql);
1885
1886
        if (0 == Database::num_rows($rs)) {
1887
            $sql = "UPDATE $tbl_attendance_calendar
1888
                    SET date_time='".Database::escape_string($this->date_time)."'
1889
                    WHERE iid = '".$calendar_id."'";
1890
            Database::query($sql);
1891
        }
1892
1893
        // update locked attendance
1894
        $is_all_calendar_done = self::is_all_attendance_calendar_done($attendanceId);
1895
        if (!$is_all_calendar_done) {
1896
            $this->lock($attendance, false);
1897
        } else {
1898
            $this->lock($attendance);
1899
        }
1900
1901
        return $affected_rows;
1902
    }
1903
1904
    /**
1905
     * delete a datetime from attendance calendar table.
1906
     *
1907
     * @param	int		attendance calendar id
1908
     * @param	int		attendance id
1909
     * @param	bool true for removing all calendar inside current attendance, false for removing by calendar id
1910
     *
1911
     * @return int affected rows
1912
     */
1913
    public function attendance_calendar_delete(
1914
        $calendar_id,
1915
        $attendanceId,
1916
        $all_delete = false
1917
    ) {
1918
        $tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
1919
        $tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
1920
1921
        $attendanceId = (int) $attendanceId;
1922
        $calendar_id = (int) $calendar_id;
1923
1924
        // get all registered users inside current course
1925
        $users = $this->get_users_rel_course();
1926
        $user_ids = array_keys($users);
1927
        $course_id = api_get_course_int_id();
1928
        $affected_rows = 0;
1929
        if ($all_delete) {
1930
            $attendance_calendar = $this->get_attendance_calendar($attendanceId);
1931
            // get all dates from calendar by current attendance
1932
            if (!empty($attendance_calendar)) {
1933
                foreach ($attendance_calendar as $cal) {
1934
                    // delete all data from attendance sheet
1935
                    $sql = "DELETE FROM $tbl_attendance_sheet
1936
                            WHERE c_id = $course_id AND attendance_calendar_id = '".intval($cal['iid'])."'";
1937
                    Database::query($sql);
1938
                    // delete data from attendance calendar
1939
                    $sql = "DELETE FROM $tbl_attendance_calendar
1940
                            WHERE iid = '".intval($cal['iid'])."'";
1941
                    Database::query($sql);
1942
1943
                    $this->deleteAttendanceCalendarGroup($cal['iid'], $course_id);
1944
                    $affected_rows++;
1945
                }
1946
            }
1947
        } else {
1948
            // delete just one row from attendance sheet by the calendar id
1949
            $sql = "DELETE FROM $tbl_attendance_sheet
1950
                    WHERE c_id = $course_id AND attendance_calendar_id = '".$calendar_id."'";
1951
            Database::query($sql);
1952
            // delete data from attendance calendar
1953
            $sql = "DELETE FROM $tbl_attendance_calendar
1954
                    WHERE iid = '".$calendar_id."'";
1955
            Database::query($sql);
1956
1957
            $this->deleteAttendanceCalendarGroup($calendar_id, $course_id);
1958
            $affected_rows++;
1959
        }
1960
1961
        // update users' results
1962
        $this->updateUsersResults($user_ids, $attendanceId);
1963
1964
        return $affected_rows;
1965
    }
1966
1967
    public function set_session_id($sessionId)
1968
    {
1969
        $this->session_id = $sessionId;
1970
    }
1971
1972
    public function set_course_id($course_id)
1973
    {
1974
        $this->course_id = $course_id;
1975
    }
1976
1977
    public function set_date_time($datetime)
1978
    {
1979
        $this->date_time = $datetime;
1980
    }
1981
1982
    public function set_name($name)
1983
    {
1984
        $this->name = $name;
1985
    }
1986
1987
    public function set_description($description)
1988
    {
1989
        $this->description = $description;
1990
    }
1991
1992
    public function set_attendance_qualify_title($attendance_qualify_title)
1993
    {
1994
        $this->attendance_qualify_title = $attendance_qualify_title;
1995
    }
1996
1997
    public function set_attendance_weight($attendance_weight)
1998
    {
1999
        $this->attendance_weight = $attendance_weight;
2000
    }
2001
2002
    /** Getters for fields of attendances tables */
2003
    public function get_session_id()
2004
    {
2005
        return $this->session_id;
2006
    }
2007
2008
    public function get_course_id()
2009
    {
2010
        return $this->course_id;
2011
    }
2012
2013
    public function get_date_time()
2014
    {
2015
        return $this->date_time;
2016
    }
2017
2018
    public function get_name()
2019
    {
2020
        return $this->name;
2021
    }
2022
2023
    public function get_description()
2024
    {
2025
        return $this->description;
2026
    }
2027
2028
    public function get_attendance_qualify_title()
2029
    {
2030
        return $this->attendance_qualify_title;
2031
    }
2032
2033
    public function get_attendance_weight()
2034
    {
2035
        return $this->attendance_weight;
2036
    }
2037
2038
    /**
2039
     * @param string $startDate in UTC time
2040
     * @param string $endDate   in UTC time
2041
     *
2042
     * @return array
2043
     */
2044
    public function getAttendanceLogin($startDate, $endDate)
2045
    {
2046
        if (empty($startDate) ||
2047
            '0000-00-00' === $startDate ||
2048
            '0000-00-00 00:00:00' === $startDate ||
2049
            empty($endDate) ||
2050
            '0000-00-00' === $endDate ||
2051
            '0000-00-00 00:00:00' === $endDate
2052
        ) {
2053
            return false;
2054
        }
2055
2056
        $sessionId = api_get_session_id();
2057
        $courseCode = api_get_course_id();
2058
        $courseId = api_get_course_int_id();
2059
2060
        if (!empty($sessionId)) {
2061
            $users = CourseManager::get_user_list_from_course_code(
2062
                $courseCode,
2063
                $sessionId,
2064
                '',
2065
                'lastname',
2066
                0
2067
            );
2068
        } else {
2069
            $users = CourseManager::get_user_list_from_course_code(
2070
                $courseCode,
2071
                0,
2072
                '',
2073
                'lastname',
2074
                STUDENT
2075
            );
2076
        }
2077
2078
        $dateTimeStartOriginal = new DateTime($startDate);
2079
        $dateTimeStart = new DateTime($startDate);
2080
        $dateTimeEnd = new DateTime($endDate);
2081
        $interval = $dateTimeStart->diff($dateTimeEnd);
2082
        $days = (int) $interval->format('%a');
2083
2084
        $dateList = [$dateTimeStart->format('Y-m-d')];
2085
        $headers = [
2086
            get_lang('User'),
2087
            $dateTimeStart->format('Y-m-d'),
2088
        ];
2089
2090
        for ($i = 0; $i < $days; $i++) {
2091
            $dateTimeStart = $dateTimeStart->add(new DateInterval('P1D'));
2092
            $date = $dateTimeStart->format('Y-m-d');
2093
            $dateList[] = $date;
2094
            $headers[] = $date;
2095
        }
2096
2097
        $accessData = CourseManager::getCourseAccessPerCourseAndSession(
2098
            $courseId,
2099
            $sessionId,
2100
            $dateTimeStartOriginal->format('Y-m-d H:i:s'),
2101
            $dateTimeEnd->format('Y-m-d H:i:s')
2102
        );
2103
2104
        $results = [];
2105
        if (!empty($accessData)) {
2106
            foreach ($accessData as $data) {
2107
                $onlyDate = substr($data['login_course_date'], 0, 10);
2108
                $results[$data['user_id']][$onlyDate] = true;
2109
            }
2110
        }
2111
2112
        return [
2113
            'users' => $users,
2114
            'dateList' => $dateList,
2115
            'headers' => $headers,
2116
            'results' => $results,
2117
        ];
2118
    }
2119
2120
    /**
2121
     * @param string $startDate in UTC time
2122
     * @param string $endDate   in UTC time
2123
     *
2124
     * @return string
2125
     */
2126
    public function getAttendanceLoginTable($startDate, $endDate)
2127
    {
2128
        $data = $this->getAttendanceLogin($startDate, $endDate);
2129
        if (!$data) {
2130
            return null;
2131
        }
2132
2133
        $headers = $data['headers'];
2134
        $dateList = $data['dateList'];
2135
        $users = $data['users'];
2136
        $results = $data['results'];
2137
2138
        $table = new HTML_Table(['class' => 'table table-hover table-striped data_table']);
2139
        $row = 0;
2140
        $column = 0;
2141
        foreach ($headers as $header) {
2142
            $table->setHeaderContents($row, $column, $header);
2143
            $column++;
2144
        }
2145
        $row = 1;
2146
        foreach ($users as $user) {
2147
            $table->setCellContents(
2148
                $row,
2149
                0,
2150
                $user['lastname'].' '.$user['firstname'].' ('.$user['username'].')'
2151
            );
2152
            $row++;
2153
        }
2154
2155
        $column = 1;
2156
        $row = 1;
2157
        foreach ($users as $user) {
2158
            foreach ($dateList as $date) {
2159
                $status = null;
2160
                if (isset($results[$user['user_id']]) &&
2161
                    isset($results[$user['user_id']][$date])
2162
                ) {
2163
                    $status = 'X';
2164
                }
2165
                $table->setCellContents($row, $column, $status);
2166
                $column++;
2167
            }
2168
            $row++;
2169
            $column = 1;
2170
        }
2171
2172
        return $table->toHtml();
2173
    }
2174
2175
    /**
2176
     * @param string $startDate in UTC time
2177
     * @param string $endDate   in UTC time
2178
     *
2179
     * @return string
2180
     */
2181
    public function exportAttendanceLogin($startDate, $endDate)
2182
    {
2183
        $data = $this->getAttendanceLogin($startDate, $endDate);
2184
2185
        if (!$data) {
2186
            return null;
2187
        }
2188
        $users = $data['users'];
2189
        $results = $data['results'];
2190
2191
        $table = new HTML_Table(['class' => 'table table-hover table-striped data_table']);
2192
        $table->setHeaderContents(0, 0, get_lang('User'));
2193
        $table->setHeaderContents(0, 1, get_lang('Date'));
2194
2195
        $row = 1;
2196
        foreach ($users as $user) {
2197
            $table->setCellContents(
2198
                $row,
2199
                0,
2200
                $user['lastname'].' '.$user['firstname'].' ('.$user['username'].')'
2201
            );
2202
            $row++;
2203
        }
2204
        $table->setColAttributes(0, ['style' => 'width:28%']);
2205
2206
        $row = 1;
2207
        foreach ($users as $user) {
2208
            if (isset($results[$user['user_id']]) &&
2209
                !empty($results[$user['user_id']])
2210
            ) {
2211
                $dates = implode(', ', array_keys($results[$user['user_id']]));
2212
                $table->setCellContents($row, 1, $dates);
2213
            }
2214
            $row++;
2215
        }
2216
2217
        $tableToString = $table->toHtml();
2218
        $params = [
2219
            'filename' => get_lang('Attendance').'_'.api_get_utc_datetime(),
2220
            'pdf_title' => get_lang('Attendance'),
2221
            'course_code' => api_get_course_id(),
2222
            'show_real_course_teachers' => true,
2223
        ];
2224
        $pdf = new PDF('A4', null, $params);
2225
        $pdf->html_to_pdf_with_template($tableToString);
2226
    }
2227
2228
    /**
2229
     * Return all course for a student between dates and order by key date (Y-m-d).
2230
     *
2231
     * @param int       $studentId
2232
     * @param \DateTime $startDate
2233
     * @param \DateTime $endDate
2234
     * @param bool      $orderDesc
2235
     *
2236
     * @return array
2237
     */
2238
    public function getCoursesWithAttendance(
2239
        $studentId = 0,
2240
        DateTime $startDate = null,
2241
        DateTime $endDate = null,
2242
        $orderDesc = false
2243
    ) {
2244
        // Lang variables
2245
        $presentString = get_lang('Present');
2246
        //$absentString = get_lang('Absent');
2247
        $absentString = '-';
2248
        // Lang variables
2249
        $attendanceLib = new Attendance();
2250
        $data = [];
2251
        /*
2252
         $specialCourses = CourseManager::returnSpecialCourses(
2253
            $studentId, false, false
2254
        );
2255
         */
2256
        $courses = CourseManager::returnCourses(
2257
            $studentId,
2258
            false,
2259
            false
2260
        );
2261
        /* Get course with (in_category) and without (not_category) category */
2262
        foreach ($courses as $coursesKey => $courseData) {
2263
            /*
2264
             * $coursesKey can be in_category or not_category for courses
2265
             * */
2266
            $totalCoursesNoCategory = count($courseData);
2267
            for ($i = 0; $i < $totalCoursesNoCategory; $i++) {
2268
                $courseItem = $courseData[$i];
2269
                $courseId = $courseItem['course_id'];
2270
2271
                /* Get all attendance by courses*/
2272
                $attendanceList = $attendanceLib->get_attendances_list($courseId);
2273
                $temp = [];
2274
                $sheetsProcessed = [];
2275
                $tempDate = [];
2276
                foreach ($attendanceList as $attendanceData) {
2277
                    $attendanceId = $attendanceData->getIid();
2278
                    $sheets = $attendanceLib->get_users_attendance_sheet(
2279
                        $attendanceId,
2280
                        $studentId,
2281
                        0,
2282
                        $courseId,
2283
                        $startDate,
2284
                        $endDate
2285
                    );
2286
2287
                    $sheetsProcessed[] = [];
2288
                    foreach ($sheets as $sheetData) {
2289
                        $totalb = count($sheetData);
2290
                        $tempDate = [];
2291
                        for ($ii = 0; $ii < $totalb; $ii++) {
2292
                            $attendancesProcess = $sheetData[$ii];
2293
                            if (!empty($attendancesProcess)) {
2294
                                $dateTemp = $attendancesProcess['0'];
2295
                                $attendancesProcess[0] = $attendancesProcess[1];
2296
                                $attendancesProcess[1] = $dateTemp;
2297
2298
                                $attendancesProcess[2] = $courseItem['title'];
2299
                                $attendancesProcess['courseTitle'] = $courseItem['title'];
2300
2301
                                $attendancesProcess[3] = $courseItem['real_id'];
2302
                                $attendancesProcess['courseId'] = $courseItem['real_id'];
2303
2304
                                $attendancesProcess[4] = $attendanceData->getName();
2305
                                $attendancesProcess['attendanceName'] = $attendanceData->getName();
2306
                                $attendancesProcess['courseCode'] = $courseItem['course_code'];
2307
2308
                                $attendancesProcess[5] = $attendanceId;
2309
                                $attendancesProcess['attendanceId'] = $attendanceId;
2310
                                if ($attendancesProcess['presence'] == 1) {
2311
                                    $attendancesProcess['presence'] = $presentString;
2312
                                    $attendancesProcess[0] = 1;
2313
                                } else {
2314
                                    $attendancesProcess['presence'] = $absentString;
2315
                                    $attendancesProcess[0] = 0;
2316
                                }
2317
                                $attendancesProcess['session'] = 0;
2318
                                $attendancesProcess['sessionName'] = '';
2319
                                $tempDate[] = $attendancesProcess;
2320
                                $dateKey = new DateTime($dateTemp);
2321
                                /*
2322
                                $attendancesProcess['teacher'] = '';
2323
                                if(isset($courseItem['teachers']) and isset($courseItem['teachers'][0])){
2324
                                    $attendancesProcess['teacher'] = $courseItem['teachers'][0]['fullname'];
2325
                                }
2326
                                */
2327
                                $data[$dateKey->format('Y-m-d')][] = $attendancesProcess;
2328
                            }
2329
                        }
2330
                    }
2331
                    $sheetsProcessed[] = $tempDate;
2332
                    $temp[] = $sheetsProcessed;
2333
                }
2334
                $courses['not_category'][$i]['attendanceSheet'] = $temp;
2335
            }
2336
        }
2337
2338
        /* Sessions */
2339
        $studentId = (int) $studentId;
2340
        $sql = "
2341
            SELECT
2342
                session_id,
2343
                c_id
2344
            FROM
2345
                session_rel_course_rel_user
2346
            WHERE
2347
                user_id = $studentId";
2348
2349
        $rs = Database::query($sql);
2350
        // get info from sessions
2351
        while ($row = Database::fetch_array($rs, 'ASSOC')) {
2352
            $courseId = $row['c_id'];
2353
            $sessionId = $row['session_id'];
2354
            $courseItem = api_get_course_info_by_id($courseId);
2355
2356
            $attendanceList = $attendanceLib->get_attendances_list(
2357
                $courseId,
2358
                $sessionId
2359
            );
2360
            $temp = [];
2361
            $sheetsProcessed = [];
2362
            $tempDate = [];
2363
            foreach ($attendanceList as $attendanceData) {
2364
                $attendanceId = $attendanceData->getIid();
2365
                $sheets = $attendanceLib->get_users_attendance_sheet(
2366
                    $attendanceId,
2367
                    $studentId,
2368
                    0,
2369
                    $courseId,
2370
                    $startDate,
2371
                    $endDate
2372
                );
2373
2374
                $sheetsProcessed[] = [];
2375
                foreach ($sheets as $sheetData) {
2376
                    $totalb = count($sheetData);
2377
                    $tempDate = [];
2378
                    for ($ii = 0; $ii < $totalb; $ii++) {
2379
                        $work = $sheetData[$ii];
2380
                        $attendancesProcess = $work;
2381
                        if (!empty($attendancesProcess)) {
2382
                            $dateTemp = $attendancesProcess['0'];
2383
                            $attendancesProcess[0] = $attendancesProcess[1];
2384
                            $attendancesProcess[1] = $dateTemp;
2385
                            $attendancesProcess[2] = $courseItem['title'];
2386
                            $attendancesProcess['courseTitle'] = $courseItem['title'];
2387
                            $attendancesProcess[3] = $courseItem['real_id'];
2388
                            $attendancesProcess['courseId'] = $courseItem['real_id'];
2389
                            $attendancesProcess[4] = $attendanceData->getName();
2390
                            $attendancesProcess['attendanceName'] = $attendanceData->getName();
2391
                            $attendancesProcess[5] = $attendanceId;
2392
                            $attendancesProcess['attendanceId'] = $attendanceId;
2393
                            $attendancesProcess['courseCode'] = $courseItem['official_code'];
2394
                            if ($attendancesProcess['presence'] == 1) {
2395
                                $attendancesProcess['presence'] = $presentString;
2396
                                $attendancesProcess[0] = 1;
2397
                            } else {
2398
                                $attendancesProcess['presence'] = $absentString;
2399
                                $attendancesProcess[0] = 0;
2400
                            }
2401
                            $attendancesProcess['session'] = $sessionId;
2402
                            $attendancesProcess['sessionName'] = api_get_session_name($sessionId);
2403
2404
                            $tempDate[] = $attendancesProcess;
2405
                            $dateKey = new DateTime($dateTemp);
2406
                            /*
2407
                            $attendancesProcess['teacher'] = '';
2408
                            if(isset($courseItem['tutor_name']) ){
2409
                                $attendancesProcess['teacher'] = $courseItem['tutor_name'];
2410
                            }
2411
                            */
2412
                            $data[$dateKey->format('Y-m-d')][] = $attendancesProcess;
2413
                        }
2414
                    }
2415
                }
2416
                $sheetsProcessed[] = $tempDate;
2417
                $temp[] = $sheetsProcessed;
2418
            }
2419
            $courses['session'][$i]['attendanceSheet'] = $temp;
2420
        }
2421
2422
        /* Order desc by date,  by default */
2423
        if ($orderDesc == true) {
2424
            ksort($data);
2425
        } else {
2426
            krsort($data);
2427
        }
2428
2429
        return $data;
2430
    }
2431
2432
    public function setAttendanceForm(FormValidator $form, CAttendance $attendance = null)
2433
    {
2434
        $skillList = [];
2435
        $header = get_lang('Create a new attendance list');
2436
        if ($attendance) {
2437
            $header = get_lang('Edit');
2438
            $form->addHidden('attendance_id', $attendance->getIid());
2439
        }
2440
        $form->addHeader($header);
2441
2442
        //$form->addElement('hidden', 'sec_token', $token);
2443
        $form->addText('title', get_lang('Title'), true);
2444
        $form->applyFilter('title', 'html_filter');
2445
        $form->addHtmlEditor(
2446
            'description',
2447
            get_lang('Description'),
2448
            false,
2449
            false,
2450
            ['ToolbarSet' => 'Basic', 'Width' => '100%', 'Height' => '150']
2451
        );
2452
2453
        $sessionId = api_get_session_id();
2454
2455
        // Advanced Parameters
2456
        if ((0 != $sessionId && Gradebook::is_active()) || 0 == $sessionId) {
2457
            $form->addButtonAdvancedSettings('id_qualify');
2458
            $form->addElement('html', '<div id="id_qualify_options" style="display:none">');
2459
2460
            // Qualify Attendance for gradebook option
2461
            $form->addElement(
2462
                'checkbox',
2463
                'attendance_qualify_gradebook',
2464
                '',
2465
                get_lang('Grade the attendance list in the assessment tool'),
2466
                'onclick="javascript: if(this.checked){document.getElementById(\'options_field\').style.display = \'block\';}else{document.getElementById(\'options_field\').style.display = \'none\';}"'
2467
            );
2468
            $form->addElement('html', '<div id="options_field" style="display:none">');
2469
2470
            GradebookUtils::load_gradebook_select_in_tool($form);
2471
2472
            $form->addElement('text', 'attendance_qualify_title', get_lang('Column header in Competences Report'));
2473
            $form->applyFilter('attendance_qualify_title', 'html_filter');
2474
            $form->addElement(
2475
                'text',
2476
                'attendance_weight',
2477
                get_lang('Weight in Report'),
2478
                'value="0.00" Style="width:40px" onfocus="javascript: this.select();"'
2479
            );
2480
            $form->applyFilter('attendance_weight', 'html_filter');
2481
            $form->addElement('html', '</div>');
2482
2483
            $skillList = Skill::addSkillsToForm($form, ITEM_TYPE_ATTENDANCE, $attendance ? $attendance->getIid() : 0);
2484
2485
            $form->addElement('html', '</div>');
2486
        }
2487
2488
        if ($attendance) {
2489
            $form->addButtonUpdate(get_lang('Update'));
2490
        } else {
2491
            $form->addButtonCreate(get_lang('Save'));
2492
        }
2493
2494
        if ($attendance) {
2495
            $default = [];
2496
            $default['title'] = Security::remove_XSS($attendance->getName());
2497
            $default['description'] = Security::remove_XSS($attendance->getDescription(), STUDENT);
2498
            $default['attendance_qualify_title'] = $attendance->getAttendanceQualifyTitle();
2499
            $default['attendance_weight'] = $attendance->getAttendanceWeight();
2500
            $default['skills'] = array_keys($skillList);
2501
2502
            $link_info = GradebookUtils::isResourceInCourseGradebook(
2503
                api_get_course_id(),
2504
                7,
2505
                $attendance->getIid(),
2506
                $sessionId
2507
            );
2508
            if ($link_info) {
2509
                $default['category_id'] = $link_info['category_id'];
2510
            }
2511
            $form->setDefaults($default);
2512
        }
2513
2514
        return $form;
2515
    }
2516
2517
    public function getCalendarSheet($edit, $attendanceId, $student_id)
2518
    {
2519
        $content = '';
2520
        $groupId = isset($_REQUEST['group_id']) ? $_REQUEST['group_id'] : null;
2521
        $filter_type = 'today';
2522
        if (!empty($_REQUEST['filter'])) {
2523
            $filter_type = $_REQUEST['filter'];
2524
        }
2525
2526
        $users_in_course = $this->get_users_rel_course($attendanceId, $groupId);
2527
        $is_locked_attendance = $this->is_locked_attendance($attendanceId);
2528
2529
        $attendant_calendar_all = $this->get_attendance_calendar(
2530
            $attendanceId,
2531
            'all',
2532
            null,
2533
            $groupId
2534
        );
2535
        $attendant_calendar = $this->get_attendance_calendar(
2536
            $attendanceId,
2537
            $filter_type,
2538
            null,
2539
            $groupId
2540
        );
2541
2542
        $isDrhOfCourse = CourseManager::isUserSubscribedInCourseAsDrh(
2543
                api_get_user_id(),
2544
                api_get_course_info()
2545
            ) || api_is_drh();
2546
        if (true == $edit) {
2547
            if (api_is_allowed_to_edit(null, true) || $isDrhOfCourse) {
2548
                $data['users_presence'] = $this->get_users_attendance_sheet(
2549
                    $attendanceId,
2550
                    0,
2551
                    $groupId
2552
                );
2553
            }
2554
        } else {
2555
            if (!empty($student_id)) {
2556
                $user_id = (int) $student_id;
2557
            } else {
2558
                $user_id = api_get_user_id();
2559
            }
2560
2561
            if (api_is_allowed_to_edit(null, true) ||
2562
                api_is_coach(api_get_session_id(), api_get_course_int_id()) ||
2563
                $isDrhOfCourse
2564
            ) {
2565
                $users_presence = $this->get_users_attendance_sheet(
2566
                    $attendanceId,
2567
                    0,
2568
                    $groupId
2569
                );
2570
            } else {
2571
                $users_presence = $this->get_users_attendance_sheet(
2572
                    $attendanceId,
2573
                    $user_id,
2574
                    $groupId
2575
                );
2576
            }
2577
2578
            $faults = $this->get_faults_of_user($user_id, $attendanceId, $groupId);
2579
        }
2580
2581
        $next_attendance_calendar_id = $this->get_next_attendance_calendar_id($attendanceId);
2582
        $next_attendance_calendar_datetime = $this->getNextAttendanceCalendarDatetime($attendanceId);
2583
2584
        if (api_is_allowed_to_edit(null, true) ||
2585
            api_is_coach(api_get_session_id(), api_get_course_int_id()) ||
2586
            $isDrhOfCourse
2587
        ) {
2588
            $groupId = isset($_REQUEST['group_id']) ? (int) ($_REQUEST['group_id']) : null;
2589
            $form = new FormValidator(
2590
                'filter',
2591
                'post',
2592
                'index.php?action=attendance_sheet_list&'.api_get_cidreq().'&attendance_id='.$attendanceId,
2593
                null,
2594
                [],
2595
                'inline'
2596
            );
2597
2598
            $values = [
2599
                'all' => get_lang('All'),
2600
                'today' => get_lang('Today'),
2601
                'all_done' => get_lang('All done'),
2602
                'all_not_done' => get_lang('All not done'),
2603
            ];
2604
            $today = api_convert_and_format_date(null, DATE_FORMAT_SHORT);
2605
            $exists_attendance_today = false;
2606
2607
            if (!empty($attendant_calendar_all)) {
2608
                $values[''] = '---------------';
2609
                foreach ($attendant_calendar_all as $attendance_date) {
2610
                    $includeCalendar = true;
2611
                    if (isset($attendance_date['groups']) && !empty($groupId)) {
2612
                        foreach ($attendance_date['groups'] as $group) {
2613
                            if ($groupId == $group['group_id']) {
2614
                                $includeCalendar = true;
2615
2616
                                break;
2617
                            } else {
2618
                                $includeCalendar = false;
2619
                            }
2620
                        }
2621
                    }
2622
2623
                    if ($today == $attendance_date['date']) {
2624
                        $exists_attendance_today = true;
2625
                    }
2626
                    if ($includeCalendar) {
2627
                        $values[$attendance_date['iid']] = $attendance_date['date_time'];
2628
                    }
2629
                }
2630
            }
2631
2632
            if (!$exists_attendance_today) {
2633
                $content .= Display::return_message(
2634
                    get_lang('There is no class scheduled today, try picking another day or add your attendance entry yourself using the action icons.'),
2635
                    'warning'
2636
                );
2637
            }
2638
2639
            $form->addSelect(
2640
                'filter',
2641
                get_lang('Filter'),
2642
                $values,
2643
                ['id' => 'filter_id', 'onchange' => 'submit();']
2644
            );
2645
2646
            $groupList = GroupManager::get_group_list(null, null, 1);
2647
            $groupIdList = ['--'];
2648
            foreach ($groupList as $group) {
2649
                $groupIdList[$group['iid']] = $group['name'];
2650
            }
2651
2652
            if (!empty($groupList)) {
2653
                $form->addSelect('group_id', get_lang('Group'), $groupIdList);
2654
            }
2655
2656
            if (isset($_REQUEST['filter'])) {
2657
                if (in_array($_REQUEST['filter'], array_keys($values))) {
2658
                    $default_filter = $_REQUEST['filter'];
2659
                }
2660
            } else {
2661
                $default_filter = 'today';
2662
            }
2663
2664
            $renderer = $form->defaultRenderer();
2665
            $renderer->setCustomElementTemplate(
2666
                '<div class="col-md-2">{label}</div><div class="col-md-10"> {element} </div>'
2667
            );
2668
2669
            $form->setDefaults(
2670
                [
2671
                    'filter' => $default_filter,
2672
                    'group_id' => $groupId,
2673
                ]
2674
            );
2675
2676
            if (!$is_locked_attendance || api_is_platform_admin()) {
2677
                $actionsLeft = '<a style="float:left;" href="index.php?'.api_get_cidreq().'&action=calendar_list&attendance_id='.$attendanceId.'">'.
2678
                    Display::return_icon('attendance_calendar.png', get_lang('Attendance calendar'), '', ICON_SIZE_MEDIUM).'</a>';
2679
                $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.'">'.
2680
                    Display::return_icon('pdf.png', get_lang('Export to PDF'), '', ICON_SIZE_MEDIUM).'</a>';
2681
2682
                $actionsRight = $form->returnForm();
2683
                $content .= Display::toolbarAction('toolbar-attendance', [$actionsLeft, $actionsRight]);
2684
            }
2685
2686
            $message_information = get_lang('The attendance sheets allow you to specify a list of dates in which you will report attendance to your courses');
2687
            if (!empty($message_information)) {
2688
                $message = '<strong>'.get_lang('Information').'</strong><br />';
2689
                $message .= $message_information;
2690
                $content .= Display::return_message($message, 'normal', false);
2691
            }
2692
2693
            if ($is_locked_attendance) {
2694
                $content .= Display::return_message(get_lang('The attendance sheet is locked.'), 'warning', false);
2695
            }
2696
2697
            $param_filter = '&filter='.Security::remove_XSS($default_filter).'&group_id='.$groupId;
2698
2699
            if (count($users_in_course) > 0) {
2700
                $form = '
2701
                <form method="post" action="index.php?action=attendance_sheet_add&'.api_get_cidreq().$param_filter.'&attendance_id='.$attendanceId.'">
2702
                    <div class="attendance-sheet-content" style="width:100%;background-color:#E1E1E1;margin-top:20px;">
2703
                        <div class="divTableWithFloatingHeader attendance-users-table" style="width:45%;float:left;margin:0px;padding:0px;">
2704
                            <table class="tableWithFloatingHeader data_table" width="100%">
2705
                                <thead>
2706
                                <tr class="tableFloatingHeader" style="position: absolute; top: 0px; left: 0px; visibility: hidden; margin:0px;padding:0px" >
2707
                                    <th width="10px">#</th>
2708
                                    <th width="10px">'.get_lang('Photo').'</th>
2709
                                    <th width="100px">'.get_lang('Last name').'</th>
2710
                                    <th width="100px">'.get_lang('First name').'</th>
2711
                                    <th width="100px">'.get_lang('Not attended').'</th>
2712
                                </tr>
2713
                                <tr class="tableFloatingHeaderOriginal" >
2714
                                    <th width="10px">#</th>
2715
                                    <th width="10px">'.get_lang('Photo').'</th>
2716
                                    <th width="150px">'.get_lang('Last name').'</th>
2717
                                    <th width="140px">'.get_lang('First name').'</th>
2718
                                    <th width="100px">'.get_lang('Not attended').'</th>
2719
                                </tr>
2720
                                </thead>
2721
                                <tbody>';
2722
2723
                $i = 1;
2724
                $class = '';
2725
                foreach ($users_in_course as $data) {
2726
                    $faults = 0;
2727
                    if (0 == $i % 2) {
2728
                        $class = 'row_odd';
2729
                    } else {
2730
                        $class = 'row_even';
2731
                    }
2732
                    $username = api_htmlentities(
2733
                        sprintf(get_lang('Login: %s'), $data['username']),
2734
                        ENT_QUOTES
2735
                    );
2736
2737
                    $form .= '<tr class="'.$class.'">
2738
                                <td><center>'.$i.'</center></td>
2739
                                <td>'.$data['photo'].'</td>
2740
                                <td><span title="'.$username.'">'.$data['lastname'].'</span></td>
2741
                                <td>'.$data['firstname'].'</td>
2742
                                <td>
2743
                                    <div class="attendance-faults-bar"
2744
                                    style="background-color:'.(!empty($data['result_color_bar']) ? $data['result_color_bar'] : 'none').'">
2745
                                        '.$data['attendance_result'].'
2746
                                    </div>
2747
                                </td>
2748
                            </tr>';
2749
2750
                    $i++;
2751
                }
2752
                $form .= '</tbody>
2753
                            </table>
2754
                        </div>';
2755
2756
                $form .= '<div
2757
                    class="divTableWithFloatingHeader attendance-calendar-table"
2758
                    style="margin:0px;padding:0px;float:left;width:55%;overflow:auto;overflow-y:hidden;">';
2759
                $form .= '<table class="tableWithFloatingHeader data_table" width="100%">';
2760
                $form .= '<thead>';
2761
                $result = null;
2762
2763
                if (count($attendant_calendar) > 0) {
2764
                    foreach ($attendant_calendar as $calendar) {
2765
                        $calendarId = $calendar['iid'];
2766
                        $date = $calendar['date'];
2767
                        $time = $calendar['time'];
2768
                        $datetime = '<div class="grey">'.$date.' - '.$time.'</div>';
2769
2770
                        $img_lock = Display::return_icon(
2771
                            'lock-closed.png',
2772
                            get_lang('Unlock date'),
2773
                            ['class' => 'img_lock', 'id' => 'datetime_column_'.$calendarId]
2774
                        );
2775
2776
                        if (!empty($calendar['done_attendance'])) {
2777
                            $datetime = '<div class="blue">'.$date.' - '.$time.'</div>';
2778
                        }
2779
                        $disabled_check = 'disabled = "true"';
2780
                        $input_hidden = '<input
2781
                            type="hidden" id="hidden_input_'.$calendarId.'" name="hidden_input[]" value="" disabled />';
2782
                        if ($next_attendance_calendar_id == $calendarId) {
2783
                            $input_hidden = '<input
2784
                                type="hidden" id="hidden_input_'.$calendarId.'" name="hidden_input[]" value="'.$calendarId.'" />';
2785
                            $disabled_check = '';
2786
                            $img_lock = Display::return_icon(
2787
                                'lock-closed.png',
2788
                                get_lang('Lock date'),
2789
                                ['class' => 'img_unlock', 'id' => 'datetime_column_'.$calendarId]
2790
                            );
2791
                        }
2792
2793
                        $result .= '<th>';
2794
                        $result .= '<div class="date-attendance">'.$datetime.'&nbsp;';
2795
                        if (api_is_allowed_to_edit(null, true)) {
2796
                            $result .= '<span id="attendance_lock" style="cursor:pointer">'.(!$is_locked_attendance || api_is_platform_admin() ? $img_lock : '').'</span>';
2797
                        }
2798
2799
                        if (false == $is_locked_attendance) {
2800
                            if (api_is_allowed_to_edit(null, true)) {
2801
                                $result .= '<input
2802
                                type="checkbox" class="checkbox_head_'.$calendarId.'" id="checkbox_head_'.$calendarId.'" '.$disabled_check.' checked="checked" />'.
2803
                                    $input_hidden.'</div></th>';
2804
                            }
2805
                        }
2806
                    }
2807
                } else {
2808
                    $result = '<th width="2000px"><span>
2809
                    <a href="index.php?'.api_get_cidreq().'&action=calendar_list&attendance_id='.$attendanceId.'">';
2810
                    $result .= Display::return_icon(
2811
                            'attendance_calendar.png',
2812
                            get_lang('Attendance calendar'),
2813
                            '',
2814
                            ICON_SIZE_MEDIUM
2815
                        ).' '.get_lang('Go to the attendance calendar');
2816
                    $result .= '</a></span></th>';
2817
                }
2818
2819
                $form .= '<tr
2820
                        class="tableFloatingHeader row_odd"
2821
                        style="position: absolute; top: 0px; left: 0px; visibility: hidden; margin:0px;padding:0px">';
2822
                $form .= $result;
2823
                $form .= '</tr>';
2824
                $form .= '<tr class="tableWithFloatingHeader row_odd tableFloatingHeaderOriginal">';
2825
                $form .= $result;
2826
                $form .= '</tr>';
2827
                $form .= '</thead>';
2828
                $form .= '<tbody>';
2829
                $i = 0;
2830
                foreach ($users_in_course as $user) {
2831
                    $class = '';
2832
                    if (0 == $i % 2) {
2833
                        $class = 'row_even';
2834
                    } else {
2835
                        $class = 'row_odd';
2836
                    }
2837
                    $form .= '<tr class="'.$class.'">';
2838
2839
                    if (count($attendant_calendar) > 0) {
2840
                        foreach ($attendant_calendar as $calendar) {
2841
                            $checked = 'checked';
2842
                            $presence = -1;
2843
2844
                            if (isset($users_presence[$user['user_id']][$calendar['iid']]['presence'])) {
2845
                                $presence = $users_presence[$user['user_id']][$calendar['iid']]['presence'];
2846
                                if (1 == (int) $presence) {
2847
                                    $checked = 'checked';
2848
                                } else {
2849
                                    $checked = '';
2850
                                }
2851
                            } else {
2852
                                //if the user wasn't registered at that time, consider unchecked
2853
                                if (0 == $next_attendance_calendar_datetime ||
2854
                                    $calendar['date_time'] < $next_attendance_calendar_datetime
2855
                                ) {
2856
                                    $checked = '';
2857
                                }
2858
                            }
2859
                            $disabled = 'disabled';
2860
                            $style_td = '';
2861
2862
                            if ($next_attendance_calendar_id == $calendar['iid']) {
2863
                                if (0 == $i % 2) {
2864
                                    $style_td = 'background-color:#eee;';
2865
                                } else {
2866
                                    $style_td = 'background-color:#dcdcdc;';
2867
                                }
2868
                                $disabled = '';
2869
                            }
2870
2871
                            $form .= '<td style="'.$style_td.'" class="checkboxes_col_'.$calendar['iid'].'">';
2872
                            $form .= '<div class="check">';
2873
2874
                            if (api_is_allowed_to_edit(null, true)) {
2875
                                if (!$is_locked_attendance || api_is_platform_admin()) {
2876
                                    $form .= '<input
2877
                                    type="checkbox" name="check_presence['.$calendar['iid'].'][]" value="'.$user['user_id'].'" '.$disabled.' '.$checked.' />';
2878
                                    $form .= '<span class="anchor_'.$calendar['iid'].'"></span>';
2879
                                } else {
2880
                                    $form .= $presence ? Display::return_icon(
2881
                                        'checkbox_on.png',
2882
                                        get_lang('Assistance'),
2883
                                        null,
2884
                                        ICON_SIZE_TINY
2885
                                    ) : Display::return_icon(
2886
                                        'checkbox_off.png',
2887
                                        get_lang('Assistance'),
2888
                                        null,
2889
                                        ICON_SIZE_TINY
2890
                                    );
2891
                                }
2892
                            } else {
2893
                                switch ($presence) {
2894
                                    case 1:
2895
                                        $form .= Display::return_icon('accept.png', get_lang('Attended'));
2896
2897
                                        break;
2898
                                    case 0:
2899
                                        $form .= Display::return_icon('exclamation.png', get_lang('Not attended'));
2900
2901
                                        break;
2902
                                    case -1:
2903
                                        break;
2904
                                }
2905
                            }
2906
2907
                            $form .= '</div>';
2908
                            $form .= '</td>';
2909
                        }
2910
                    } else {
2911
                        $calendarClass = null;
2912
                        if (isset($calendar)) {
2913
                            $calendarClass = 'checkboxes_col_'.$calendar['iid'];
2914
                        }
2915
                        $form .= '<td class="'.$calendarClass.'">';
2916
                        $form .= '<div>';
2917
                        $form .= '<center>&nbsp;</center>
2918
                                </div>
2919
                                </td>';
2920
                    }
2921
                    echo '</tr>';
2922
                    $i++;
2923
                }
2924
                $form .= '</tbody></table>';
2925
                $form .= '</div></div>';
2926
2927
                $form .= '<div class="row">
2928
                            <div class="col-md-12">';
2929
                if (!$is_locked_attendance || api_is_platform_admin()) {
2930
                    if (api_is_allowed_to_edit(null, true)) {
2931
                        $form .= '<button type="submit" class="btn btn-primary">'.get_lang('Save').'</button>';
2932
                    }
2933
                }
2934
                $form .= '</div>
2935
                        </div>
2936
                </form>';
2937
                $content .= $form;
2938
            } else {
2939
                $content .= Display::return_message(
2940
                    '<a href="'.api_get_path(WEB_CODE_PATH).'user/user.php?'.api_get_cidreq().'">'.
2941
                    get_lang('There are no registered learners inside the course').'</a>',
2942
                    'warning',
2943
                    false
2944
                );
2945
            }
2946
        } else {
2947
            $content .= Display::page_header(get_lang('Report of attendance sheets'));
2948
            if (!empty($users_presence)) {
2949
                $content .= '
2950
                <div>
2951
                    <table width="250px;">
2952
                        <tr>
2953
                            <td>'.get_lang('To attend').': </td>
2954
                            <td>
2955
                                <center>
2956
                                <div
2957
                                    class="attendance-faults-bar"
2958
                                    style="background-color:'.(!empty($faults['color_bar']) ? $faults['color_bar'] : 'none').'">
2959
                                        '.$faults['faults'].'/'.$faults['total'].' ('.$faults['faults_porcent'].'%)
2960
                                </div>
2961
                                </center>
2962
                            </td>
2963
                        </tr>
2964
                    </table>
2965
                </div>';
2966
            }
2967
2968
            $content .= '<table class="data_table">
2969
                <tr class="row_odd" >
2970
                    <th>'.get_lang('Attendance').'</th>
2971
                </tr>';
2972
2973
            if (!empty($users_presence)) {
2974
                $i = 0;
2975
                foreach ($users_presence[$user_id] as $presence) {
2976
                    $class = '';
2977
                    if (0 == $i % 2) {
2978
                        $class = 'row_even';
2979
                    } else {
2980
                        $class = 'row_odd';
2981
                    }
2982
2983
                    $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);
2984
                    $content .= '<tr class="'.$class.'">
2985
                            <td>
2986
                                '.$check.'&nbsp; '.$presence['date_time'].'
2987
                            </td>
2988
                        </tr>';
2989
                }
2990
            } else {
2991
                $content .= '
2992
                        <tr>
2993
                            <td>
2994
                            <center>'.get_lang('You do not have attendances').'</center>
2995
                            </td>
2996
                        </tr>';
2997
            }
2998
            $content .= ' </table>';
2999
        }
3000
3001
        return $content;
3002
    }
3003
3004
    /**
3005
     * It's used to print attendance sheet.
3006
     *
3007
     * @param int $attendance_id
3008
     */
3009
    public function attendance_sheet_export_to_pdf(
3010
        $attendance_id,
3011
        $student_id = 0,
3012
        $course_id = ''
3013
    ) {
3014
        $courseInfo = api_get_course_info($course_id);
3015
        $this->set_course_id($courseInfo['code']);
3016
        $groupId = isset($_REQUEST['group_id']) ? $_REQUEST['group_id'] : null;
3017
        $data_array = [];
3018
        $data_array['attendance_id'] = $attendance_id;
3019
        $data_array['users_in_course'] = $this->get_users_rel_course($attendance_id, $groupId);
3020
3021
        $filter_type = 'today';
3022
3023
        if (!empty($_REQUEST['filter'])) {
3024
            $filter_type = $_REQUEST['filter'];
3025
        }
3026
3027
        $my_calendar_id = null;
3028
        if (is_numeric($filter_type)) {
3029
            $my_calendar_id = $filter_type;
3030
            $filter_type = 'calendar_id';
3031
        }
3032
3033
        $data_array['attendant_calendar'] = $this->get_attendance_calendar(
3034
            $attendance_id,
3035
            $filter_type,
3036
            $my_calendar_id,
3037
            $groupId
3038
        );
3039
3040
        if (api_is_allowed_to_edit(null, true) || api_is_drh()) {
3041
            $data_array['users_presence'] = $this->get_users_attendance_sheet($attendance_id, 0, $groupId);
3042
        } else {
3043
            if (!empty($student_id)) {
3044
                $user_id = (int) $student_id;
3045
            } else {
3046
                $user_id = api_get_user_id();
3047
            }
3048
            $data_array['users_presence'] = $this->get_users_attendance_sheet($attendance_id, $user_id, $groupId);
3049
            $data_array['faults'] = $this->get_faults_of_user($user_id, $attendance_id, $groupId);
3050
            $data_array['user_id'] = $user_id;
3051
        }
3052
3053
        $data_array['next_attendance_calendar_id'] = $this->get_next_attendance_calendar_id($attendance_id);
3054
3055
        // Set headers pdf.
3056
        $courseCategory = CourseManager::get_course_category($courseInfo['categoryCode']);
3057
        $teacherInfo = CourseManager::get_teacher_list_from_course_code($courseInfo['code']);
3058
        $teacherName = null;
3059
        foreach ($teacherInfo as $teacherData) {
3060
            if (null != $teacherName) {
3061
                $teacherName .= ' / ';
3062
            }
3063
            $teacherName .= api_get_person_name($teacherData['firstname'], $teacherData['lastname']);
3064
        }
3065
3066
        // Get data table
3067
        $data_table = [];
3068
        $head_table = ['#', get_lang('Name')];
3069
        foreach ($data_array['attendant_calendar'] as $class_day) {
3070
            $head_table[] =
3071
                api_format_date($class_day['date_time'], DATE_FORMAT_NUMBER_NO_YEAR).' '.
3072
                api_format_date($class_day['date_time'], TIME_NO_SEC_FORMAT);
3073
        }
3074
        $data_table[] = $head_table;
3075
        $data_attendant_calendar = $data_array['attendant_calendar'];
3076
        $data_users_presence = $data_array['users_presence'];
3077
        $count = 1;
3078
3079
        if (!empty($data_array['users_in_course'])) {
3080
            foreach ($data_array['users_in_course'] as $user) {
3081
                $cols = 1;
3082
                $result = [];
3083
                $result['count'] = $count;
3084
                $result['full_name'] = api_get_person_name($user['firstname'], $user['lastname']);
3085
                foreach ($data_array['attendant_calendar'] as $class_day) {
3086
                    if (1 == $class_day['done_attendance']) {
3087
                        if (1 == $data_users_presence[$user['user_id']][$class_day['iid']]['presence']) {
3088
                            $result[$class_day['iid']] = get_lang('P');
3089
                        } else {
3090
                            $result[$class_day['iid']] = '<span style="color:red">'.get_lang('NP').'</span>';
3091
                        }
3092
                    } else {
3093
                        $result[$class_day['iid']] = ' ';
3094
                    }
3095
                    $cols++;
3096
                }
3097
                $count++;
3098
                $data_table[] = $result;
3099
            }
3100
        }
3101
        $max_cols_per_page = 12; //10 dates + 2 name and number
3102
        $max_dates_per_page = $max_dates_per_page_original = $max_cols_per_page - 2; //10
3103
        $rows = count($data_table);
3104
3105
        if ($cols > $max_cols_per_page) {
3106
            $number_tables = round(($cols - 2) / $max_dates_per_page);
3107
            $headers = $data_table[0];
3108
            $all = [];
3109
            $tables = [];
3110
            $changed = 1;
3111
3112
            for ($i = 0; $i <= $rows; $i++) {
3113
                $row = isset($data_table[$i]) ? $data_table[$i] : null;
3114
                $key = 1;
3115
                $max_dates_per_page = 10;
3116
                $item = isset($data_table[$i]) ? $data_table[$i] : null;
3117
                $count_j = 0;
3118
3119
                if (!empty($item)) {
3120
                    foreach ($item as $value) {
3121
                        if ($count_j >= $max_dates_per_page) {
3122
                            $key++;
3123
                            $max_dates_per_page = $max_dates_per_page_original * $key;
3124
                            //magic hack
3125
                            $tables[$key][$i][] = $tables[1][$i][0];
3126
                            $tables[$key][$i][] = $tables[1][$i][1];
3127
                        }
3128
                        $tables[$key][$i][] = $value;
3129
                        $count_j++;
3130
                    }
3131
                }
3132
            }
3133
3134
            $content = null;
3135
            if (!empty($tables)) {
3136
                foreach ($tables as $sub_table) {
3137
                    $content .= Export::convert_array_to_html($sub_table).'<br /><br />';
3138
                }
3139
            }
3140
        } else {
3141
            $content = Export::convert_array_to_html(
3142
                $data_table,
3143
                ['header_attributes' => ['align' => 'center']]
3144
            );
3145
        }
3146
3147
        $params = [
3148
            'filename' => get_lang('Attendance').'-'.api_get_local_time(),
3149
            'pdf_title' => $courseInfo['title'],
3150
            'course_code' => $courseInfo['code'],
3151
            'add_signatures' => ['Drh', 'Teacher', 'Date'],
3152
            'pdf_teachers' => $teacherName,
3153
            'pdf_course_category' => $courseCategory ? $courseCategory['name'] : '',
3154
            'format' => 'A4-L',
3155
            'orientation' => 'L',
3156
        ];
3157
        Export::export_html_to_pdf($content, $params);
3158
        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...
3159
    }
3160
3161
    /**
3162
     * Gets attendance base in the table:
3163
     * TABLE_STATISTIC_TRACK_E_COURSE_ACCESS.
3164
     *
3165
     * @param bool $showForm
3166
     * @param bool $exportToPdf
3167
     */
3168
    public function getAttendanceBaseInLogin($showForm = false, $exportToPdf = true)
3169
    {
3170
        $table = null;
3171
        $formToDisplay = null;
3172
        $startDate = null;
3173
        $endDate = null;
3174
3175
        $sessionId = api_get_session_id();
3176
        if ($showForm) {
3177
            $form = new FormValidator(
3178
                'search',
3179
                'post',
3180
                api_get_self().'?'.api_get_cidreq().'&action=calendar_logins'
3181
            );
3182
            $form->addDateRangePicker('range', get_lang('Date range'));
3183
            $form->addButton('submit', get_lang('Submit'));
3184
3185
            if ($form->validate()) {
3186
                $values = $form->getSubmitValues();
3187
                $startDate = api_get_utc_datetime($values['range_start']);
3188
                $endDate = api_get_utc_datetime($values['range_end']);
3189
            }
3190
            $formToDisplay = $form->returnForm();
3191
        } else {
3192
            if (!empty($sessionId)) {
3193
                $sessionInfo = api_get_session_info($sessionId);
3194
                $startDate = $sessionInfo['access_start_date'];
3195
                $endDate = $sessionInfo['access_end_date'];
3196
            }
3197
        }
3198
3199
        if ($exportToPdf) {
3200
            $result = $this->exportAttendanceLogin($startDate, $endDate);
3201
            if (empty($result)) {
3202
                api_not_allowed(true, get_lang('No data available'));
3203
            }
3204
        }
3205
3206
        $table = $this->getAttendanceLoginTable($startDate, $endDate);
3207
3208
        return [
3209
            'form' => $formToDisplay,
3210
            'table' => $table,
3211
        ];
3212
    }
3213
}
3214