Passed
Push — master ( 96b7ea...43f231 )
by Julito
09:43
created

Attendance::attendance_sheet_export_to_pdf()   F

Complexity

Conditions 25
Paths 1728

Size

Total Lines 151
Code Lines 106

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 25
eloc 106
nc 1728
nop 3
dl 0
loc 151
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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