diff --git a/.upgradenotes/MDL-83542-2024111110343257.yml b/.upgradenotes/MDL-83542-2024111110343257.yml new file mode 100644 index 00000000000..f4fd2616c47 --- /dev/null +++ b/.upgradenotes/MDL-83542-2024111110343257.yml @@ -0,0 +1,7 @@ +issueNumber: MDL-83542 +notes: + core_courseformat: + - message: >- + Add after_course_content_updated hook triggered when a course content is + updated (module modified, ...) through edition. + type: improved diff --git a/course/format/classes/external/create_module.php b/course/format/classes/external/create_module.php index 3345a9284e3..46f99c008db 100644 --- a/course/format/classes/external/create_module.php +++ b/course/format/classes/external/create_module.php @@ -127,8 +127,11 @@ class create_module extends external_api { // Execute the action. $actions->$action($updates, $course, $modname, $targetsectionnum, $targetcmid); - // Any state action mark the state cache as dirty. - course_format::session_cache_reset($course); + // Dispatch the hook for post course content update. + $hook = new \core_courseformat\hook\after_course_content_updated( + course: $course + ); + \core\di::get(\core\hook\manager::class)->dispatch($hook); return json_encode($updates); } diff --git a/course/format/classes/external/update_course.php b/course/format/classes/external/update_course.php index 134c050f129..cf2eed8e94f 100644 --- a/course/format/classes/external/update_course.php +++ b/course/format/classes/external/update_course.php @@ -119,8 +119,11 @@ class update_course extends external_api { // Execute the action. $actions->$action($updates, $course, $ids, $targetsectionid, $targetcmid); - // Any state action mark the state cache as dirty. - course_format::session_cache_reset($course); + // Dispatch the hook for post course content update. + $hook = new \core_courseformat\hook\after_course_content_updated( + course: $course, + ); + \core\di::get(\core\hook\manager::class)->dispatch($hook); return json_encode($updates); } diff --git a/course/format/classes/hook/after_course_content_updated.php b/course/format/classes/hook/after_course_content_updated.php new file mode 100644 index 00000000000..cd83080b794 --- /dev/null +++ b/course/format/classes/hook/after_course_content_updated.php @@ -0,0 +1,42 @@ +. + +namespace core_courseformat\hook; +use stdClass; + +/** + * Hook after course content has been updated. + * + * This hook will be dispatched after any content (module, section or other) has been updated in a course. + * + * @package core_courseformat + * @copyright 2024 Laurent David + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +#[\core\attribute\label('Allows plugins or features to perform actions after course content has been updated.')] +#[\core\attribute\tags('course')] +class after_course_content_updated { + /** + * Constructor for the hook. + * + * @param stdClass $course The course instance. + */ + public function __construct( + /** @var stdClass The course instance */ + public readonly stdClass $course, + ) { + } +} diff --git a/course/format/classes/hook_listener.php b/course/format/classes/hook_listener.php index b1a6188f788..042538f1d45 100644 --- a/course/format/classes/hook_listener.php +++ b/course/format/classes/hook_listener.php @@ -16,6 +16,7 @@ namespace core_courseformat; +use core_courseformat\hook\after_course_content_updated; use core_course\hook\before_course_viewed; use core_group\hook\after_group_membership_added; use core_group\hook\after_group_membership_removed; @@ -70,4 +71,15 @@ class hook_listener { } } } + + /** + * Reset cache for the current user in a course when a course content is updated. + * + * @param after_course_content_updated $hook The course module created hook. + */ + public static function course_content_updated( + after_course_content_updated $hook, + ): void { + base::session_cache_reset($hook->course); + } } diff --git a/course/format/update.php b/course/format/update.php index 0de542bf962..fd42b3dcc55 100644 --- a/course/format/update.php +++ b/course/format/update.php @@ -121,7 +121,10 @@ if (!is_callable([$actions, $action])) { // Execute the action. $actions->$action($updates, $course, $ids, $targetsectionid, $targetcmid); -// Any state action mark the state cache as dirty. -course_format::session_cache_reset($course); +// Dispatch the hook for post course content update. +$hook = new \core_courseformat\hook\after_course_content_updated( + course: $course, +); +\core\di::get(\core\hook\manager::class)->dispatch($hook); redirect($returnurl); diff --git a/lib/db/hooks.php b/lib/db/hooks.php index 69adf0b714a..0c55a43d70f 100644 --- a/lib/db/hooks.php +++ b/lib/db/hooks.php @@ -53,6 +53,10 @@ $callbacks = [ 'hook' => \core_group\hook\after_group_membership_removed::class, 'callback' => \core_courseformat\hook_listener::class . '::remove_members_from_group', ], + [ + 'hook' => \core_courseformat\hook\after_course_content_updated::class, + 'callback' => \core_courseformat\hook_listener::class . '::course_content_updated', + ], [ 'hook' => \core_course\hook\after_course_created::class, 'callback' => \core_communication\hook_listener::class . '::create_course_communication',