Completed
Push — master ( b0cc9f...9dadb1 )
by Julito
12:24
created

Attendance::get_faults_average_by_course()   A

Complexity

Conditions 5
Paths 10

Size

Total Lines 42
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

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