diff --git a/modules/attendance/enums.php b/modules/attendance/enums.php new file mode 100644 index 0000000000..5342da5969 --- /dev/null +++ b/modules/attendance/enums.php @@ -0,0 +1,63 @@ + 'winter', + Semester::SPRING => 'spring', + }; + } + + public function month_start(): int + { + return match($this) { + Semester::WINTER => 9, + Semester::SPRING => 3, + }; + } + + public function year_offset(): DateInterval + { + return match($this) { + Semester::WINTER => DateInterval::createFromDateString('0 days'), + Semester::SPRING => DateInterval::createFromDateString('-1 year'), + }; + } + + public static function fromMonth(int $month): self + { + return ($month >= self::SPRING->month_start() && $month < self::WINTER->month_start() ? self::SPRING : self::WINTER); + } +} +?> diff --git a/modules/attendance/functions.php b/modules/attendance/functions.php index 1e5b1209a4..6173af47c9 100644 --- a/modules/attendance/functions.php +++ b/modules/attendance/functions.php @@ -22,6 +22,7 @@ use PhpOffice\PhpSpreadsheet\IOFactory; require_once 'modules/progress/AttendanceEvent.php'; +require_once 'enums.php'; /** * @brief admin available attendances @@ -763,19 +764,61 @@ function update_user_attendance_activities($attendance_id, $uid) { } /** - * @brief create new attendance + * @brief Get current and upcoming semesters + * @param int $count Optional. How many (upcoming) semesters to fetch information for. By default, information for the current semester only is returned. + */ +function get_semester_info(int $count = 1) { + $semester = Semester::fromMonth(date('n')); + + $semester_cases = Semester::cases(); + // Seek the internal pointer to the correct index so it can wrap around + while (current($semester_cases) !== $semester) + next($semester_cases); + + $start = DateTime::createFromFormat('|', ''); // Zero-initialize it + $start->setDate(date('Y'), $semester->month_start(), 1); + + // Create $count periods to calculate the end and start of each upcoming semester + $intv = new DateInterval('P6M'); + $period = new DatePeriod($start, $intv, $count); + + $dates = []; + foreach ($period as $dt) + $dates[] = $dt; + + $ret = []; + for ($i = 0; $i < count($dates) - 1; $i++) { + $start = clone $dates[$i]; + $end = (clone $dates[$i+1])->modify('-1 second'); // 23:59:59 as the next semester starts at 00:00:00 + + // Calculate the academic year, not the year the semester starts + $academic_start = ((clone $dates[$i])->add($semester->year_offset()))->format('Y'); + $academic_end = $end->format('Y'); + + $ret[] = ['semester' => $semester, 'start' => $start, 'end' => $end, 'academic_year' => ['start' => $academic_start, 'end' => $academic_end]]; + + // Wrap around if needed + if (($semester = next($semester_cases)) === false) + $semester = reset($semester_cases); + } + + return $ret; +} + +/** + * @brief Display attendance book form + * @param type $attendance_id * @global string $tool_content * @global type $course_code - * @global type $langNewAttendance2 * @global type $langTitle * @global type $langSave * @global type $langInsert */ -function new_attendance() { +function attendance_book_form($attendance_id = null) { - global $tool_content, $course_code, $langNewAttendance2, $head_content, - $langTitle, $langSubmit, $langInsert, $langAttendanceLimitNumber, - $langStart, $langEnd, $language, $langImgFormsDes; + global $tool_content, $course_code, $head_content, $langTitle, $langSubmit, + $langInsert, $langAttendanceLimitNumber, $attendance_limit, $langStart, + $langEnd, $language, $langImgFormsDes, $langAttendanceUpdate, $attendance; load_js('bootstrap-datetimepicker'); $head_content .= " @@ -789,78 +832,89 @@ function new_attendance() { }); }); "; + + // Create new attendance book + if ($attendance_id === null) { + $title_default = ''; + // Calculate current semester to populate datepicker with sensible values + $semester_dates = get_semester_info()[0]; + $start_date_default = $semester_dates['start']->format('d-m-Y H:i'); + $end_date_default = $semester_dates['end']->format('d-m-Y H:i'); + // Assume a default of 2 classes per week, for 3 months, with two missed attendances (2*4*3)-2 + $limit_default = '22'; + + $action = "$_SERVER[SCRIPT_NAME]?course=$course_code"; + } else { // Edit attendance book + $title_default = $attendance->title; + $start_date_default = DateTime::createFromFormat('Y-m-d H:i:s', $attendance->start_date)->format('d-m-Y H:i'); + $end_date_default = DateTime::createFromFormat('Y-m-d H:i:s', $attendance->end_date)->format('d-m-Y H:i'); + $limit_default = get_attendance_limit($attendance_id); + + $action = "$_SERVER[SCRIPT_NAME]?course=$course_code&attendance_id=$attendance_id"; + } + $title_error = Session::getError('title'); - $title = Session::has('title') ? Session::get('title') : ''; + $title = Session::has('title') ? Session::get('title') : $title_default; $start_date_error = Session::getError('start_date'); - $start_date = Session::has('start_date') ? Session::get('start_date') : ''; + $start_date = Session::has('start_date') ? Session::get('start_date') : $start_date_default; $end_date_error = Session::getError('end_date'); - $end_date = Session::has('end_date') ? Session::get('end_date') : ''; + $end_date = Session::has('end_date') ? Session::get('end_date') : $end_date_default; + $limit_error = Session::getError('limit'); - $limit = Session::has('limit') ? Session::get('limit') : ''; + $limit = Session::has('limit') ? Session::get('limit') : $limit_default; $tool_content .= " -