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 .= " -
+
-
-
-
+
+
- + $title_error
- - -
-
- -
-
- - $start_date_error -
-
- - -
-
- -
-
- - $end_date_error -
-
- - +
+
+ +
+
+ + $start_date_error +
+
+
+
+ +
+
+ + $end_date_error +
+
- +
- + $limit_error
- " - - .form_buttons(array( - array( - 'class'=> 'submitAdminBtn', - 'text' => $langSubmit, - 'name' => 'newAttendance', - 'value'=> $langInsert - ), - array( - 'class'=> 'cancelAdminBtn ms-1', - 'href' => "$_SERVER[SCRIPT_NAME]?course=$course_code" - ) - )). - - - - " + " . form_buttons( + array( + array( + 'class' => 'submitAdminBtn', + 'text' => $langSubmit, + 'name' => $attendance_id === null ? 'attendanceBookCreate' : 'attendanceBookSettings', + 'value'=> $attendance_id === null ? $langInsert : $langAttendanceUpdate + ), + array( + 'class' => 'cancelAdminBtn ms-1', + 'href' => "$_SERVER[SCRIPT_NAME]?course=$course_code" + ) + ) + )."
@@ -870,7 +924,6 @@ function new_attendance() {
"; } - /** * @brief display user presences * @param int $attendance_id @@ -1053,112 +1106,6 @@ function display_all_users_presences($attendance_id) { } } -/** - * @brief insert/modify attendance settings - * @param int $attendance_id - */ -function attendance_settings($attendance_id) { - - global $tool_content, $course_code, $language, - $langTitle, $langAttendanceLimitNumber, - $langAttendanceUpdate, $langSubmit, $head_content, - $attendance, $langStart, $langEnd, $langImgFormsDes; - - load_js('bootstrap-datetimepicker'); - $head_content .= " - "; - $title_error = Session::getError('title'); - $title = Session::has('title') ? Session::get('title') : $attendance->title; - $start_date_error = Session::getError('start_date'); - $start_date = Session::has('start_date') ? Session::get('start_date') : DateTime::createFromFormat('Y-m-d H:i:s', $attendance->start_date)->format('d-m-Y H:i'); - $end_date_error = Session::getError('end_date'); - $end_date = Session::has('end_date') ? Session::get('end_date') : DateTime::createFromFormat('Y-m-d H:i:s', $attendance->end_date)->format('d-m-Y H:i'); - $limit_error = Session::getError('limit'); - $limit = Session::has('limit') ? Session::get('limit') : get_attendance_limit($attendance_id); - // update attendance title - $tool_content .= " - -
-
-
-
-
- -
- - $title_error -
-
- - -
-
- -
-
- - $start_date_error -
-
- - -
-
- -
-
- - $end_date_error -
-
- - -
- -
- - $limit_error -
-
-
- - - - ".form_buttons(array( - array( - 'class' => 'submitAdminBtn', - 'text' => $langSubmit, - 'name' => 'submitAttendanceBookSettings', - 'value'=> $langAttendanceUpdate - ), - array( - 'class' => 'cancelAdminBtn ms-1', - 'href' => "$_SERVER[SCRIPT_NAME]?course=$course_code" - ) - ))." - - - - -
- -
-
-
-
- $langImgFormsDes -
-
"; -} /** * @brief modify user attendance settings diff --git a/modules/attendance/index.php b/modules/attendance/index.php index 03ddfdcbd9..2c35a57e2f 100644 --- a/modules/attendance/index.php +++ b/modules/attendance/index.php @@ -348,11 +348,12 @@ className: 'cancelAdminBtn' redirect_to_home_page("modules/attendance/index.php?course=$course_code"); } - //add a new attendance - if (isset($_POST['newAttendance'])) { + // Create new attendance book + if (isset($_POST['attendanceBookCreate'])) { $v = new Valitron\Validator($_POST); - $v->rule('required', array('title', 'limit', 'start_date', 'end_date')); - $v->rule('numeric', array('limit')); + $v->rule('required', array('title', 'start_date', 'end_date')); + $v->rule('integer', array('limit')); + $v->rule('min', array('limit'), 0); $v->rule('date', array('start_date', 'end_date')); if (!empty($_POST['end_date'])) { $v->rule('dateBefore', 'start_date', $_POST['end_date']); @@ -365,7 +366,7 @@ className: 'cancelAdminBtn' )); if($v->validate()) { $newTitle = $_POST['title']; - $attendance_limit = intval($_POST['limit']); + $attendance_limit = empty($_POST['limit']) ? 0 : intval($_POST['limit']); $start_date = (new DateTime($_POST['start_date']))->format('Y-m-d H:i:s'); $end_date = (new DateTime($_POST['end_date']))->format('Y-m-d H:i:s'); $attendance_id = Database::get()->query("INSERT INTO attendance SET course_id = ?d, `limit` = ?d, active = 1, title = ?s, start_date = ?t, end_date = ?t", $course_id, $attendance_limit, $newTitle, $start_date, $end_date)->lastInsertID; @@ -593,8 +594,8 @@ className: 'cancelAdminBtn' } $tool_content .= "
"; - // update attendance settings - if (isset($_POST['submitAttendanceBookSettings'])) { + // Update attendance book settings + if (isset($_POST['attendanceBookSettings'])) { $v = new Valitron\Validator($_POST); $v->rule('required', array('title', 'limit', 'start_date', 'end_date')); $v->rule('numeric', array('limit')); @@ -736,15 +737,15 @@ className: 'cancelAdminBtn' $display = FALSE; } - elseif (isset($_GET['new'])) { - new_attendance(); // create new attendance + elseif (isset($_GET['new'])) { + attendance_book_form(); // create new attendance + $display = FALSE; + } elseif (isset($_GET['editSettings'])) { // attendance settings + attendance_book_form($attendance_id); $display = FALSE; } elseif (isset($_GET['editUsers'])) { // edit attendance users user_attendance_settings($attendance_id); $display = FALSE; - } elseif (isset($_GET['editSettings'])) { // attendance settings - attendance_settings($attendance_id); - $display = FALSE; } elseif (isset($_GET['addActivityAs'])) { //display available assignments attendance_display_available_assignments($attendance_id); $display = FALSE;