This commit is contained in:
Huong Nguyen 2024-11-13 14:25:42 +07:00
commit a97260296d
No known key found for this signature in database
GPG Key ID: 40D88AB693A3E72A
7 changed files with 167 additions and 1 deletions

View File

@ -0,0 +1,8 @@
issueNumber: MDL-83185
notes:
core_courseformat:
- message: >-
Add core_courseformat\base::invalidate_all_session_caches to reset course editor cache for all users when course is changed.
This method can be used as an alternative to core_courseformat\base::session_cache_reset for resetting the cache for the current user
in case the change in the course should be reflected for all users.
type: improved

View File

@ -283,6 +283,20 @@ abstract class base {
return self::session_cache_reset($course);
}
/**
* Prune a course state cache for all open sessions.
*
* Most course edits does not require to invalidate the cache for all users
* because the cache relies on the course cacherev value. However, there are
* actions like editing the groups that do not change the course cacherev.
*
* @param \stdClass $course
* @return void
*/
public static function invalidate_all_session_caches_for_course(stdClass $course): void {
\cache_helper::invalidate_by_event('changesincoursestate', [$course->id]);
}
/**
* Returns the format name used by this course
*

View File

@ -0,0 +1,55 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_courseformat;
use core_group\hook\after_group_membership_added;
use core_group\hook\after_group_membership_removed;
/**
* Hook listener for course format
*
* @package core_courseformat
* @copyright 2024 Laurent David <laurent.david@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class hook_listener {
/**
* Add members to group room when a new member is added to the group.
*
* @param after_group_membership_added $hook The group membership added hook.
*/
public static function add_members_to_group(
after_group_membership_added $hook,
): void {
$group = $hook->groupinstance;
$course = get_course($group->courseid);
base::invalidate_all_session_caches_for_course($course);
}
/**
* Remove members from the room when a member is removed from group room.
*
* @param after_group_membership_removed $hook The group membership removed hook.
*/
public static function remove_members_from_group(
after_group_membership_removed $hook,
): void {
$group = $hook->groupinstance;
$course = get_course($group->courseid);
base::invalidate_all_session_caches_for_course($course);
}
}

View File

@ -996,6 +996,84 @@ class base_test extends advanced_testcase {
$this->assertFalse($format->is_section_visible($modinfostudent->get_section_info(1)));
$this->assertFalse($format->is_section_visible($modinfostudent->get_section_info(2)));
}
/**
* Test can_sections_be_removed_from_navigation().
*
* @covers ::session_cache
* @covers ::session_cache_reset
* @covers ::session_cache_reset_all
* @covers ::invalidate_all_session_caches_for_course
*/
public function test_session_caches_methods(): void {
global $DB;
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$course1 = $generator->create_course(['format' => 'topics']);
$course2 = $generator->create_course(['format' => 'topics']);
// Force some cacherev to the course.
$course1->cacherev = 12345;
$course2->cacherev = 67890;
$DB->set_field('course', 'cacherev', $course1->cacherev, ['id' => $course1->id]);
$DB->set_field('course', 'cacherev', $course2->cacherev, ['id' => $course2->id]);
$teacher = $generator->create_and_enrol($course1, 'editingteacher');
$generator->enrol_user($teacher->id, $course2->id, 'editingteacher');
$this->setUser($teacher);
// The cache key uses time() as hash. To not wait a second between calls we fake an initial value.
$statecache = cache::make('core', 'courseeditorstate');
$statecache->set($course1->id, $course1->cacherev . '_11111');
$statecache->set($course2->id, $course2->cacherev . '_22222');
$course1cachekey = \core_courseformat\base::session_cache($course1);
// Validate the method returns the same value when called twice.
$course1cachekeyagain = \core_courseformat\base::session_cache($course1);
$this->assertEquals($course1cachekey, $course1cachekeyagain);
// Validate other course has a diferent cache key.
$course2cachekey = \core_courseformat\base::session_cache($course2);
$this->assertNotEquals($course1cachekey, $course2cachekey);
// Reset the specific course cache.
\core_courseformat\base::session_cache_reset($course1);
$resetcachekey = \core_courseformat\base::session_cache($course1);
$this->assertNotEquals($course1cachekey, $resetcachekey);
$reset2cachekey = \core_courseformat\base::session_cache($course2);
$this->assertEquals($course2cachekey, $reset2cachekey);
// Return to the initial value.
$statecache->set($course1->id, $course1->cacherev . '_11111');
$statecache->set($course2->id, $course2->cacherev . '_22222');
// Reset all user course caches.
\core_courseformat\base::session_cache_reset_all();
$resetallcachekey = \core_courseformat\base::session_cache($course1);
$this->assertNotEquals($course1cachekey, $resetallcachekey);
$resetall2cachekey = \core_courseformat\base::session_cache($course2);
$this->assertNotEquals($course2cachekey, $resetall2cachekey);
// Return to the initial value.
$statecache->set($course1->id, $course1->cacherev . '_11111');
$statecache->set($course2->id, $course2->cacherev . '_22222');
// Invalidate cache on course 1.
\core_courseformat\base::invalidate_all_session_caches_for_course($course1);
$invalidatecachekey = \core_courseformat\base::session_cache($course1);
$this->assertNotEquals($course1cachekey, $invalidatecachekey);
$invalidate2cachekey = \core_courseformat\base::session_cache($course2);
$this->assertEquals($course2cachekey, $invalidate2cachekey);
}
}
/**

View File

@ -239,6 +239,9 @@ $definitions = array(
'mode' => cache_store::MODE_SESSION,
'simplekeys' => true,
'simpledata' => true,
'invalidationevents' => [
'changesincoursestate',
],
],
// Course actions instances cache.
'courseactionsinstances' => [

View File

@ -45,6 +45,14 @@ $callbacks = [
'hook' => \core_group\hook\after_group_membership_removed::class,
'callback' => \core_communication\hook_listener::class . '::remove_members_from_group_room',
],
[
'hook' => \core_group\hook\after_group_membership_added::class,
'callback' => \core_courseformat\hook_listener::class . '::add_members_to_group',
],
[
'hook' => \core_group\hook\after_group_membership_removed::class,
'callback' => \core_courseformat\hook_listener::class . '::remove_members_from_group',
],
[
'hook' => \core_course\hook\after_course_created::class,
'callback' => \core_communication\hook_listener::class . '::create_course_communication',

View File

@ -29,7 +29,7 @@
defined('MOODLE_INTERNAL') || die();
$version = 2024110800.00; // YYYYMMDD = weekly release date of this DEV branch.
$version = 2024110800.01; // YYYYMMDD = weekly release date of this DEV branch.
// RR = release increments - 00 in DEV branches.
// .XX = incremental changes.
$release = '5.0dev (Build: 20241108)'; // Human-friendly version name