Passed
Push — master ( 0c074a...115052 )
by Julito
10:13 queued 12s
created

Attendance::attendance_sheet_export_to_pdf()   F

Complexity

Conditions 25
Paths 1728

Size

Total Lines 150
Code Lines 106

Duplication

Lines 0
Ratio 0 %

Importance

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