From 3c1a874dd04308c4734e6a1f85388327ce1d1ffa Mon Sep 17 00:00:00 2001 From: Binon Date: Mon, 23 Jun 2025 13:23:32 +0100 Subject: [PATCH 1/3] Added validation on self entrol check --- local/telconfig/classes/observer.php | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/local/telconfig/classes/observer.php b/local/telconfig/classes/observer.php index 1eb7a13e75e..9d8c886e764 100644 --- a/local/telconfig/classes/observer.php +++ b/local/telconfig/classes/observer.php @@ -23,7 +23,7 @@ public static function enrol_instance_changed(\core\event\base $event): void { // Get enrol instance $enrol = $DB->get_record('enrol', ['id' => $event->objectid], '*', MUST_EXIST); - + // Only act if it's for 'self' enrolment. if (!isset($event->other['enrol']) || $event->other['enrol'] !== 'self') { return; @@ -59,12 +59,27 @@ public static function local_course_updated(\core\event\base $event): void { try { $course = $DB->get_record('course', ['id' => $event->objectid], '*', MUST_EXIST); + // Only proceed if the course has self enrolment enabled + if (!self::is_course_self_enrollable($course->id)) { + return; + } + // Rebuild and send metadata to API (as an update). $data = course_data_builder::build_course_metadata($course); helper::send_findwise_api($data); } catch (\dml_exception $e) { - debugging("Failed to process course update: " . $e->getMessage(), DEBUG_DEVELOPER); + debugging("Failed to process local course update: " . $e->getMessage(), DEBUG_DEVELOPER); } + } + + private static function is_course_self_enrollable(int $courseid): bool { + global $DB; + + return $DB->record_exists('enrol', [ + 'courseid' => $courseid, + 'enrol' => 'self', + 'status' => ENROL_INSTANCE_ENABLED, + ]); } } From f8d9406a77d47a72c57a69589823c52553821f05 Mon Sep 17 00:00:00 2001 From: Binon Date: Tue, 24 Jun 2025 16:20:56 +0100 Subject: [PATCH 2/3] Courses can be searched using section name and resource name --- .../telconfig/classes/course_data_builder.php | 68 ++++++++++++++++++- local/telconfig/classes/observer.php | 53 +++++++++++++++ local/telconfig/db/events.php | 12 ++++ 3 files changed, 132 insertions(+), 1 deletion(-) diff --git a/local/telconfig/classes/course_data_builder.php b/local/telconfig/classes/course_data_builder.php index b7db93fd8fa..a07b09d659f 100644 --- a/local/telconfig/classes/course_data_builder.php +++ b/local/telconfig/classes/course_data_builder.php @@ -40,7 +40,19 @@ public static function build_course_metadata($course): array { // Extract tags require_once($CFG->dirroot . '/tag/lib.php'); $tags = \core_tag_tag::get_item_tags('core', 'course', $course->id); - $keywords = array_map(fn($tag) => strtolower($tag->rawname), $tags); + $keywords = array_reduce($tags, function ($carry, $tag) { + return array_merge($carry, self::tokenize_keywords($tag->rawname)); + }, []); + + + // Merge in section and resource keywords + $keywords = array_merge( + $keywords, + self::get_section_keywords($course), + self::get_resource_keywords($course) + ); + + $keywords = array_values(array_unique($keywords)); // Prepare data $data = [ @@ -66,4 +78,58 @@ public static function build_course_metadata($course): array { return []; // Always return an array } } + + private static function get_section_keywords($course): array { + $keywords = []; + $modinfo = get_fast_modinfo($course); + $sections = $modinfo->get_section_info_all(); + + foreach ($sections as $section) { + if (!empty($section->name)) { + $keywords = array_merge($keywords, self::tokenize_keywords($section->name)); + } + } + + return $keywords; + } + + private static function get_resource_keywords($course): array { + global $DB; + $keywords = []; + $coursemodules = $DB->get_records('course_modules', ['course' => $course->id]); + + foreach ($coursemodules as $cm) { + // Skip if module is marked for deletion + if (!empty($cm->deletioninprogress)) { + continue; + } + + // Get module type (e.g., 'resource', 'quiz', etc.) + $module = $DB->get_record('modules', ['id' => $cm->module], '*', IGNORE_MISSING); + if (!$module) { + continue; + } + + // Dynamically get the module instance (e.g., from 'resource', 'quiz', etc.) + $instancetable = $module->name; + $instance = $DB->get_record($instancetable, ['id' => $cm->instance], '*', IGNORE_MISSING); + if ($instance && !empty($instance->name)) { + $keywords = array_merge($keywords, self::tokenize_keywords($instance->name)); + } + } + + return $keywords; + } + + private static function tokenize_keywords(string $input): array { + $input = strtolower(trim($input)); + if (empty($input)) { + return []; + } + + $tokens = preg_split('/\s+/', $input); // split on spaces + $keywords = array_merge([$input], $tokens); // include full phrase and individual words + + return array_unique($keywords); // remove duplicates + } } diff --git a/local/telconfig/classes/observer.php b/local/telconfig/classes/observer.php index 9d8c886e764..83ca54caf77 100644 --- a/local/telconfig/classes/observer.php +++ b/local/telconfig/classes/observer.php @@ -73,6 +73,59 @@ public static function local_course_updated(\core\event\base $event): void { } } + /** + * Triggered when a section is updated. + * + * @param \core\event\base $event + * @return void + */ + public static function local_section_updated(\core\event\base $event): void { + global $DB; + + try { + $section = $DB->get_record('course_sections', ['id' => $event->objectid], '*', MUST_EXIST); + $course = $DB->get_record('course', ['id' => $event->courseid], '*', MUST_EXIST); + + // Only proceed if the course has self enrolment enabled + if (!self::is_course_self_enrollable($course->id)) { + return; + } + + // Handle the update, e.g., send new metadata + $data = course_data_builder::build_course_metadata($course); // or enrich this with section title + helper::send_findwise_api($data); + + } catch (\Throwable $e) { + debugging('Failed in local section_updated: ' . $e->getMessage(), DEBUG_DEVELOPER); + } + } + + /** + * Triggered when a module is updated. + * + * @param \core\event\base $event + * @return void + */ + public static function local_module_updated(\core\event\base $event): void { + global $DB; + + try { + $cm = get_coursemodule_from_id(null, $event->objectid, 0, false, MUST_EXIST); + $course = $DB->get_record('course', ['id' => $cm->course], '*', MUST_EXIST); + + // Only proceed if the course has self enrolment enabled + if (!self::is_course_self_enrollable($course->id)) { + return; + } + + // Build metadata + $data = course_data_builder::build_course_metadata($course); // or enrich with mod/section name + helper::send_findwise_api($data); + + } catch (\Throwable $e) { + debugging('Failed in local module_updated: ' . $e->getMessage(), DEBUG_DEVELOPER); + } + } private static function is_course_self_enrollable(int $courseid): bool { global $DB; diff --git a/local/telconfig/db/events.php b/local/telconfig/db/events.php index d6b56b72b4c..4e6d53fe206 100644 --- a/local/telconfig/db/events.php +++ b/local/telconfig/db/events.php @@ -13,4 +13,16 @@ 'priority' => 9999, 'internal' => false, ], + [ + 'eventname' => '\core\event\course_section_updated', + 'callback' => '\local_telconfig\observer::local_section_updated', + 'priority' => 9999, + 'internal' => false, + ], + [ + 'eventname' => '\core\event\course_module_updated', + 'callback' => '\local_telconfig\observer::local_module_updated', + 'priority' => 9999, + 'internal' => false, + ], ]; From 752a9b8fecfecb832a574860fe8801b0ff3f59db Mon Sep 17 00:00:00 2001 From: Binon Date: Wed, 25 Jun 2025 16:14:13 +0100 Subject: [PATCH 3/3] removing/hiding activity and resources are now triggered --- .../telconfig/classes/course_data_builder.php | 23 +++++++++------ local/telconfig/classes/observer.php | 17 ++++++----- local/telconfig/db/events.php | 28 +++++++++++++++++-- 3 files changed, 49 insertions(+), 19 deletions(-) diff --git a/local/telconfig/classes/course_data_builder.php b/local/telconfig/classes/course_data_builder.php index a07b09d659f..f37e27a4bb4 100644 --- a/local/telconfig/classes/course_data_builder.php +++ b/local/telconfig/classes/course_data_builder.php @@ -41,7 +41,7 @@ public static function build_course_metadata($course): array { require_once($CFG->dirroot . '/tag/lib.php'); $tags = \core_tag_tag::get_item_tags('core', 'course', $course->id); $keywords = array_reduce($tags, function ($carry, $tag) { - return array_merge($carry, self::tokenize_keywords($tag->rawname)); + return array_merge($carry, self::tokenise_keywords($tag->rawname)); }, []); @@ -85,9 +85,13 @@ private static function get_section_keywords($course): array { $sections = $modinfo->get_section_info_all(); foreach ($sections as $section) { - if (!empty($section->name)) { - $keywords = array_merge($keywords, self::tokenize_keywords($section->name)); + // Skip hidden sections + if (!$section->uservisible || !$section->visible || empty($section->name)) { + continue; } + + // Tokenise and merge keywords + $keywords = array_merge($keywords, self::tokenise_keywords($section->name)); } return $keywords; @@ -95,12 +99,14 @@ private static function get_section_keywords($course): array { private static function get_resource_keywords($course): array { global $DB; - $keywords = []; + $keywords = []; + + // Now fetch all course modules from DB $coursemodules = $DB->get_records('course_modules', ['course' => $course->id]); foreach ($coursemodules as $cm) { - // Skip if module is marked for deletion - if (!empty($cm->deletioninprogress)) { + // Skip deleted or hidden modules + if (!empty($cm->deletioninprogress) || empty($cm->visible)) { continue; } @@ -114,14 +120,15 @@ private static function get_resource_keywords($course): array { $instancetable = $module->name; $instance = $DB->get_record($instancetable, ['id' => $cm->instance], '*', IGNORE_MISSING); if ($instance && !empty($instance->name)) { - $keywords = array_merge($keywords, self::tokenize_keywords($instance->name)); + $keywords = array_merge($keywords, self::tokenise_keywords($instance->name)); } } return $keywords; } - private static function tokenize_keywords(string $input): array { + + private static function tokenise_keywords(string $input): array { $input = strtolower(trim($input)); if (empty($input)) { return []; diff --git a/local/telconfig/classes/observer.php b/local/telconfig/classes/observer.php index 83ca54caf77..98f13d006ba 100644 --- a/local/telconfig/classes/observer.php +++ b/local/telconfig/classes/observer.php @@ -79,13 +79,12 @@ public static function local_course_updated(\core\event\base $event): void { * @param \core\event\base $event * @return void */ - public static function local_section_updated(\core\event\base $event): void { + public static function local_section_changed(\core\event\base $event): void { global $DB; - try { - $section = $DB->get_record('course_sections', ['id' => $event->objectid], '*', MUST_EXIST); + try { $course = $DB->get_record('course', ['id' => $event->courseid], '*', MUST_EXIST); - + // Only proceed if the course has self enrolment enabled if (!self::is_course_self_enrollable($course->id)) { return; @@ -96,7 +95,7 @@ public static function local_section_updated(\core\event\base $event): void { helper::send_findwise_api($data); } catch (\Throwable $e) { - debugging('Failed in local section_updated: ' . $e->getMessage(), DEBUG_DEVELOPER); + debugging('Error handling local section change: ' . $e->getMessage(), DEBUG_DEVELOPER); } } @@ -106,12 +105,12 @@ public static function local_section_updated(\core\event\base $event): void { * @param \core\event\base $event * @return void */ - public static function local_module_updated(\core\event\base $event): void { + public static function local_module_changed(\core\event\base $event): void { global $DB; try { - $cm = get_coursemodule_from_id(null, $event->objectid, 0, false, MUST_EXIST); - $course = $DB->get_record('course', ['id' => $cm->course], '*', MUST_EXIST); + $courseid = $event->courseid; + $course = $DB->get_record('course', ['id' => $courseid], '*', MUST_EXIST); // Only proceed if the course has self enrolment enabled if (!self::is_course_self_enrollable($course->id)) { @@ -123,7 +122,7 @@ public static function local_module_updated(\core\event\base $event): void { helper::send_findwise_api($data); } catch (\Throwable $e) { - debugging('Failed in local module_updated: ' . $e->getMessage(), DEBUG_DEVELOPER); + debugging('Error handling local module change: ' . $e->getMessage(), DEBUG_DEVELOPER); } } private static function is_course_self_enrollable(int $courseid): bool { diff --git a/local/telconfig/db/events.php b/local/telconfig/db/events.php index 4e6d53fe206..29da2fc800d 100644 --- a/local/telconfig/db/events.php +++ b/local/telconfig/db/events.php @@ -13,15 +13,39 @@ 'priority' => 9999, 'internal' => false, ], + [ + 'eventname' => '\core\event\course_section_created', + 'callback' => '\local_telconfig\observer::local_section_changed', + 'priority' => 9999, + 'internal' => false, + ], [ 'eventname' => '\core\event\course_section_updated', - 'callback' => '\local_telconfig\observer::local_section_updated', + 'callback' => '\local_telconfig\observer::local_section_changed', + 'priority' => 9999, + 'internal' => false, + ], + [ + 'eventname' => '\core\event\course_section_deleted', + 'callback' => '\local_telconfig\observer::local_section_changed', + 'priority' => 9999, + 'internal' => false, + ], + [ + 'eventname' => '\core\event\course_module_created', + 'callback' => '\local_telconfig\observer::local_module_changed', 'priority' => 9999, 'internal' => false, ], [ 'eventname' => '\core\event\course_module_updated', - 'callback' => '\local_telconfig\observer::local_module_updated', + 'callback' => '\local_telconfig\observer::local_module_changed', + 'priority' => 9999, + 'internal' => false, + ], + [ + 'eventname' => '\core\event\course_module_deleted', + 'callback' => '\local_telconfig\observer::local_module_changed', 'priority' => 9999, 'internal' => false, ],