Passed
Push — master ( cb50ee...221dc3 )
by Julito
07:56
created

Attendance::getAttendanceList()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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