diff --git a/lbplanner/classes/enums/SETTINGS.php b/lbplanner/classes/enums/SETTINGS.php new file mode 100644 index 00000000..84d236bb --- /dev/null +++ b/lbplanner/classes/enums/SETTINGS.php @@ -0,0 +1,44 @@ +. + +/** + * enum for setting keys + * + * @package local_lbplanner + * @subpackage enums + * @copyright 2025 NecodeIT + * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC-BY-NC-SA 4.0 International or later + */ + +namespace local_lbplanner\enums; + +// TODO: revert to native enums once we migrate to php8. + +use local_lbplanner\polyfill\Enum; + +/** + * The keys for plugin settings + */ +class SETTINGS extends Enum { + /** + * Key for the setting for how many days into the future a student should be able to reserve a slot. + */ + const SLOT_FUTURESIGHT = 'slot_futuresight'; + /** + * Key for the setting for how long a course should be expired for until it counts as outdated and gets culled. + */ + const COURSE_OUTDATERANGE = 'course_outdaterange'; +} diff --git a/lbplanner/classes/helpers/config_helper.php b/lbplanner/classes/helpers/config_helper.php index b52d3ec1..484bc9de 100644 --- a/lbplanner/classes/helpers/config_helper.php +++ b/lbplanner/classes/helpers/config_helper.php @@ -21,12 +21,14 @@ use customfield_select\field_controller; use local_modcustomfields\customfield\mod_handler; +use local_lbplanner\enums\SETTINGS; + /** * Helper class for config * * @package local_lbplanner * @subpackage helpers - * @copyright 2024 NecodeIT + * @copyright 2025 NecodeIT * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC-BY-NC-SA 4.0 International or later */ class config_helper { @@ -97,4 +99,20 @@ public static function get_category_id(): int { return intval($catid); } } + + /** + * Get the setting for how far into the future students should be able to reserve slots. + * @return int futuresight in number of days (0-6) + */ + public static function get_slot_futuresight(): int { + return get_config('local_lbplanner', SETTINGS::SLOT_FUTURESIGHT); + } + + /** + * Get the setting for how long after a course ends it should start being hidden in Eduplanner. + * @return int outdated range in number of seconds (>=0) + */ + public static function get_course_outdatedrange(): int { + return get_config('local_lbplanner', SETTINGS::COURSE_OUTDATERANGE); + } } diff --git a/lbplanner/classes/helpers/course_helper.php b/lbplanner/classes/helpers/course_helper.php index a4580178..20e30b8c 100644 --- a/lbplanner/classes/helpers/course_helper.php +++ b/lbplanner/classes/helpers/course_helper.php @@ -22,6 +22,7 @@ use DateTimeImmutable; use dml_exception; use dml_write_exception; + use local_lbplanner\model\course; /** @@ -90,6 +91,8 @@ public static function get_all_eduplanner_courses(bool $onlyenrolled=true): arra $userid = $USER->id; $lbptag = core_tag_tag::get_by_name(core_tag_collection::get_default(), self::EDUPLANNER_TAG, strictness:MUST_EXIST); + $courseexpireseconds = config_helper::get_course_outdatedrange(); + $courseexpiredate = (new DateTimeImmutable("{$courseexpireseconds} seconds ago"))->getTimestamp(); /* NOTE: We could use enrol_get_my_courses() and get_courses() here. But their perf is so abysmal that we have to roll our own function. @@ -104,7 +107,7 @@ public static function get_all_eduplanner_courses(bool $onlyenrolled=true): arra ue.status = :active AND e.status = :enabled AND ue.timestart <= :now - AND c.enddate > :ayearago + AND c.enddate > :courseexpiredate AND ti.tagid = :lbptagid AND ti.itemtype = \"course\"", [ @@ -112,7 +115,7 @@ public static function get_all_eduplanner_courses(bool $onlyenrolled=true): arra "active" => ENROL_USER_ACTIVE, "enabled" => ENROL_INSTANCE_ENABLED, "now" => time(), - "ayearago" => (new DateTimeImmutable('1 year ago'))->getTimestamp(), + "courseexpiredate" => $courseexpiredate, "lbptagid" => $lbptag->id, ] ); @@ -120,10 +123,10 @@ public static function get_all_eduplanner_courses(bool $onlyenrolled=true): arra $mdlcourses = $DB->get_records_sql(" SELECT c.* FROM {course} c INNER JOIN {tag_instance} ti ON (ti.itemid = c.id) - WHERE c.enddate > :ayearago AND ti.tagid = :lbptagid AND ti.itemtype = \"course\"", + WHERE c.enddate > :courseexpiredate AND ti.tagid = :lbptagid AND ti.itemtype = \"course\"", [ "now" => time(), - "ayearago" => (new DateTimeImmutable('1 year ago'))->getTimestamp(), + "courseexpiredate" => $courseexpiredate, "lbptagid" => $lbptag->id, ] ); @@ -157,8 +160,7 @@ public static function get_all_eduplanner_courses(bool $onlyenrolled=true): arra throw $e; } } - // Add name to fetched Course. - $fetchedcourse->set_fullname($mdlcourse->fullname); + // Add mdlcourse to fetched Course. $fetchedcourse->set_mdlcourse($mdlcourse); array_push($results, $fetchedcourse); } @@ -180,16 +182,4 @@ public static function check_access(int $courseid, int $userid): bool { } return is_enrolled($context, $userid, '', true); } - - /** - * gets the fullname from a course - * - * @param int $courseid the course id - * - * @return string the fullname of the course - * @throws dml_exception - */ - public static function get_fullname(int $courseid): string { - return get_course($courseid)->fullname; - } } diff --git a/lbplanner/classes/helpers/slot_helper.php b/lbplanner/classes/helpers/slot_helper.php index 24985f8d..cf1fd720 100644 --- a/lbplanner/classes/helpers/slot_helper.php +++ b/lbplanner/classes/helpers/slot_helper.php @@ -38,10 +38,6 @@ * Provides helper methods for any tables related with the planning function of the app */ class slot_helper { - /** - * how far into the future a user can reserve a slot - */ - const RESERVATION_RANGE_USER = 3; /** * how far into the future a supervisor can reserve a slot for a user */ diff --git a/lbplanner/classes/model/course.php b/lbplanner/classes/model/course.php index 26f49cae..77d35903 100644 --- a/lbplanner/classes/model/course.php +++ b/lbplanner/classes/model/course.php @@ -26,8 +26,6 @@ namespace local_lbplanner\model; use core_external\{external_single_structure, external_value}; -use DateTimeImmutable; -use local_lbplanner\helpers\course_helper; /** * Model class for course @@ -50,10 +48,6 @@ class course { * maximum size: 5 chars */ public string $shortname; - /** - * @var string $fullname the full name of this course - */ - private ?string $fullname; /** * @var string $color the color for this course as #RRGGBB */ @@ -83,7 +77,6 @@ public function __construct(int $id, int $courseid, int $userid, string $shortna $this->set_shortname($shortname); $this->set_color($color); $this->enabled = $enabled; - $this->fullname = null; $this->mdlcourse = null; } @@ -159,29 +152,6 @@ public function set_enabled(bool $enabled) { $this->enabled = $enabled; } - /** - * sets the cached fullname (mainly for deduplicating DB requests) - * TODO: remove in favour of cached mdluser - * @param string $fullname the cached fullname - */ - public function set_fullname(string $fullname) { - // If we already have a fullname stored and it's different, then we've found data inconsistency. - assert($this->fullname === null || $this->fullname === $fullname); - $this->fullname = $fullname; - } - - /** - * get the cached fullname - * @return string the cached fullname - */ - public function get_fullname(): string { - if ($this->fullname === null) { - $this->fullname = course_helper::get_fullname($this->courseid); - } - - return $this->fullname; - } - /** * Prepares a string to be eligible for shortname * @param string $shortname the shortname to be prepared @@ -197,18 +167,6 @@ public static function prepare_shortname(string $shortname): string { return strtoupper($shortname); } - /** - * Check if the course is outdated - * @param \stdClass $mdlcourse the moodle course object to check - * @return bool false if the course's end is one year or longer ago, true otherwise - */ - public static function check_year(\stdClass $mdlcourse): bool { - $enddate = $mdlcourse->enddate; - $now = new DateTimeImmutable(); - $dti = $now->setTimestamp($enddate); - return $now->diff($dti)->y >= 0; - } - /** * sets the associated moodle course (for caching) * @param \stdClass $mdlcourse @@ -226,7 +184,7 @@ public function set_mdlcourse(\stdClass $mdlcourse): void { */ public function get_mdlcourse(): \stdClass { if ($this->mdlcourse === null) { - $this->mdlcourse = get_course($this->id); + $this->mdlcourse = get_course($this->courseid); } return $this->mdlcourse; @@ -264,7 +222,7 @@ public function prepare_for_api(): array { 'id' => $this->id, 'courseid' => $this->courseid, 'userid' => $this->userid, - 'name' => $this->get_fullname(), + 'name' => $this->get_mdlcourse()->fullname, 'shortname' => $this->shortname, 'color' => $this->color, 'enabled' => $this->enabled ? 1 : 0, // Moodle's API uses int instead of bool. diff --git a/lbplanner/services/slots/book_reservation.php b/lbplanner/services/slots/book_reservation.php index 0cf98bd8..ab58ac43 100644 --- a/lbplanner/services/slots/book_reservation.php +++ b/lbplanner/services/slots/book_reservation.php @@ -22,6 +22,7 @@ use core_external\{external_api, external_function_parameters, external_single_structure, external_value}; use DateTimeZone; use local_lbplanner\enums\NOTIF_TRIGGER; +use local_lbplanner\helpers\config_helper; use local_lbplanner\helpers\notifications_helper; use local_lbplanner\helpers\slot_helper; use local_lbplanner\model\reservation; @@ -101,13 +102,13 @@ public static function book_reservation(int $slotid, string $date, int $userid): if ($userid === intval($USER->id)) { // Student reserving slot for themself. - $maxdays = slot_helper::RESERVATION_RANGE_USER; + $maxdays = config_helper::get_slot_futuresight(); $student = $USER; } else { // Supervisor reserving slot for student. slot_helper::assert_slot_supervisor($USER->id, $slotid); - $maxdays = slot_helper::RESERVATION_RANGE_USER; + $maxdays = slot_helper::RESERVATION_RANGE_SUPERVISOR; $student = core_user::get_user($userid, '*', MUST_EXIST); } diff --git a/lbplanner/services/slots/get_my_slots.php b/lbplanner/services/slots/get_my_slots.php index 0c7a5252..fb564848 100644 --- a/lbplanner/services/slots/get_my_slots.php +++ b/lbplanner/services/slots/get_my_slots.php @@ -17,7 +17,7 @@ namespace local_lbplanner_services; use core_external\{external_api, external_function_parameters, external_multiple_structure}; -use local_lbplanner\helpers\slot_helper; +use local_lbplanner\helpers\{config_helper, slot_helper}; use local_lbplanner\model\slot; /** @@ -48,7 +48,7 @@ public static function get_my_slots(): array { $myslots = slot_helper::filter_slots_for_user($allslots, $USER); - $returnslots = slot_helper::filter_slots_for_time($myslots, slot_helper::RESERVATION_RANGE_USER); + $returnslots = slot_helper::filter_slots_for_time($myslots, config_helper::get_slot_futuresight()); return array_map(fn(slot $slot) => $slot->prepare_for_api(), $returnslots); } diff --git a/lbplanner/settings.php b/lbplanner/settings.php index c9b50f27..65a84832 100644 --- a/lbplanner/settings.php +++ b/lbplanner/settings.php @@ -18,16 +18,43 @@ * Defines some settings * * @package local_lbplanner - * @copyright 2024 NecodeIT + * @copyright 2025 NecodeIT * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC-BY-NC-SA 4.0 International or later */ +use local_lbplanner\enums\SETTINGS; + defined('MOODLE_INTERNAL') || die; if ($hassiteconfig) { - $settings = new admin_settingpage('local_lbplanner', 'LB Planer'); + $settings = new admin_settingpage('local_lbplanner', 'EduPlanner'); $ADMIN->add('localplugins', $settings); - $settings->add(new admin_setting_configtext('local_lbplanner/activeyear', - 'Active year', 'Current year e.g.:"20/21" ', null, PARAM_TEXT)); + $futuresightsett = new admin_setting_configselect( + 'local_lbplanner/'.SETTINGS::SLOT_FUTURESIGHT, + 'Advance reservation limit', + 'Maximum number of days in advance students can reserve slots (0 = same day only).', + 3, + [ + 0 => "0 Days", + 1 => "1 Day", + 2 => "2 Days", + 3 => "3 Days", + 4 => "4 Days", + 5 => "5 Days", + 6 => "6 Days", + 7 => "7 Days", + ], + ); + $settings->add($futuresightsett); + + $outdaterangesett = new admin_setting_configduration( + 'local_lbplanner/'.SETTINGS::COURSE_OUTDATERANGE, + 'Mark courses as outdated after', + 'The maximum duration a course remains visible in EduPlanner after it ends.', + 31536000, // 1 non-leap year. + 86400, // In days. + ); + $outdaterangesett->set_min_duration(0); + $settings->add($outdaterangesett); } diff --git a/lbplanner/version.php b/lbplanner/version.php index 768f6dc9..1ac8a3c3 100644 --- a/lbplanner/version.php +++ b/lbplanner/version.php @@ -28,7 +28,7 @@ $plugin->maturity = MATURITY_BETA; $plugin->component = 'local_lbplanner'; $plugin->release = '1.0.2'; -$plugin->version = 202509050001; +$plugin->version = 202509120001; $plugin->dependencies = [ // Depend upon version 2023110600 of local_modcustomfields. 'local_modcustomfields' => 2023110600,