MDL-54035 accesslib: separate role definition cache clear
Thanks to MDL-49398, we can separate the combined user session and role definition cache clearing function into two separate functions. At the same time, we want to identify and remove mark_dirty() calls that were added for role definition changes but were incorrectly left behind. Change highlights: - Remove unnecessary mark_dirty() calls performed after assign_capability(), unassign_capability(), delete_role(), deleted contexts, brand new contexts - Move role definition cache clear from the user-centric accesslib_clear_all_caches() to the newly created, role-dedicated accesslib_reset_role_cache()
This commit is contained in:
@@ -46,7 +46,6 @@ $controller = new $classformode[$mode]();
|
||||
|
||||
if (optional_param('submit', false, PARAM_BOOL) && data_submitted() && confirm_sesskey()) {
|
||||
$controller->process_submission();
|
||||
$syscontext->mark_dirty();
|
||||
$event = null;
|
||||
// Create event depending on mode.
|
||||
switch ($mode) {
|
||||
|
||||
@@ -123,9 +123,6 @@ abstract class core_role_capability_table_with_risks extends core_role_capabilit
|
||||
assign_capability($changedcap, $this->permissions[$changedcap],
|
||||
$this->roleid, $this->context->id, true);
|
||||
}
|
||||
|
||||
// Force accessinfo refresh for users visiting this context.
|
||||
$this->context->mark_dirty();
|
||||
}
|
||||
|
||||
public function display() {
|
||||
|
||||
@@ -85,12 +85,10 @@ switch ($action) {
|
||||
die;
|
||||
}
|
||||
if (!delete_role($roleid)) {
|
||||
// The delete failed, but mark the context dirty in case.
|
||||
$systemcontext->mark_dirty();
|
||||
// The delete failed.
|
||||
print_error('cannotdeleterolewithid', 'error', $baseurl, $roleid);
|
||||
}
|
||||
// Deleted a role sitewide...
|
||||
$systemcontext->mark_dirty();
|
||||
redirect($baseurl);
|
||||
break;
|
||||
|
||||
|
||||
@@ -445,9 +445,6 @@ class core_course_category implements renderable, cacheable_object, IteratorAggr
|
||||
$path = $parent->path . '/' . $newcategory->id;
|
||||
$DB->set_field('course_categories', 'path', $path, array('id' => $newcategory->id));
|
||||
|
||||
// We should mark the context as dirty.
|
||||
context_coursecat::instance($newcategory->id)->mark_dirty();
|
||||
|
||||
fix_course_sortorder();
|
||||
|
||||
// If this is data from form results, save embedded files and update description.
|
||||
|
||||
@@ -2450,9 +2450,6 @@ function create_course($data, $editoroptions = NULL) {
|
||||
// purge appropriate caches in case fix_course_sortorder() did not change anything
|
||||
cache_helper::purge_by_event('changesincourse');
|
||||
|
||||
// new context created - better mark it as dirty
|
||||
$context->mark_dirty();
|
||||
|
||||
// Trigger a course created event.
|
||||
$event = \core\event\course_created::create(array(
|
||||
'objectid' => $course->id,
|
||||
|
||||
@@ -985,7 +985,6 @@ class core_course_courselib_testcase extends advanced_testcase {
|
||||
$modulecontext = context_module::instance($assign1->cmid);
|
||||
assign_capability('moodle/course:manageactivities', CAP_PROHIBIT, $roleids['editingteacher'],
|
||||
$modulecontext);
|
||||
$modulecontext->mark_dirty();
|
||||
$this->assertFalse(course_can_delete_section($courseweeks, 1));
|
||||
$this->assertTrue(course_can_delete_section($courseweeks, 2));
|
||||
|
||||
@@ -3131,7 +3130,6 @@ class core_course_courselib_testcase extends advanced_testcase {
|
||||
$CFG->enableblogs = 0;
|
||||
// Disable view participants capability.
|
||||
assign_capability('moodle/course:viewparticipants', CAP_PROHIBIT, $roleid, $context);
|
||||
$context->mark_dirty();
|
||||
|
||||
$navoptions = course_get_user_navigation_options($context);
|
||||
$this->assertFalse($navoptions->blogs);
|
||||
|
||||
@@ -287,7 +287,6 @@ class core_grade_report_graderlib_testcase extends advanced_testcase {
|
||||
$context = context_course::instance($course->id);
|
||||
$managerroleid = $DB->get_field('role', 'id', array('shortname' => 'manager'));
|
||||
assign_capability('moodle/grade:viewhidden', CAP_PROHIBIT, $managerroleid, $context->id, true);
|
||||
$context->mark_dirty();
|
||||
$this->assertFalse(has_capability('moodle/grade:viewhidden', $context));
|
||||
|
||||
// Recreate the report. Confirm it returns successfully still.
|
||||
|
||||
+25
-29
@@ -62,6 +62,8 @@
|
||||
* <b>Name conventions</b>
|
||||
*
|
||||
* "ctx" means context
|
||||
* "ra" means role assignment
|
||||
* "rdef" means role definition
|
||||
*
|
||||
* <b>accessdata</b>
|
||||
*
|
||||
@@ -72,9 +74,7 @@
|
||||
* against userid in $ACCESSLIB_PRIVATE->accessdatabyuser).
|
||||
*
|
||||
* $accessdata is a multidimensional array, holding
|
||||
* role assignments (RAs), role-capabilities-perm sets
|
||||
* (role defs) and a list of courses we have loaded
|
||||
* data for.
|
||||
* role assignments (RAs), role switches and initialization time.
|
||||
*
|
||||
* Things are keyed on "contextpaths" (the path field of
|
||||
* the context table) for fast walking up/down the tree.
|
||||
@@ -201,6 +201,7 @@ function accesslib_clear_all_caches_for_unit_testing() {
|
||||
}
|
||||
|
||||
accesslib_clear_all_caches(true);
|
||||
accesslib_reset_role_cache();
|
||||
|
||||
unset($USER->access);
|
||||
}
|
||||
@@ -219,16 +220,32 @@ function accesslib_clear_all_caches($resetcontexts) {
|
||||
|
||||
$ACCESSLIB_PRIVATE->dirtycontexts = null;
|
||||
$ACCESSLIB_PRIVATE->accessdatabyuser = array();
|
||||
$ACCESSLIB_PRIVATE->cacheroledefs = array();
|
||||
|
||||
$cache = cache::make('core', 'roledefs');
|
||||
$cache->purge();
|
||||
|
||||
if ($resetcontexts) {
|
||||
context_helper::reset_caches();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Full reset of accesslib's private role cache. ONLY TO BE USED FROM THIS LIBRARY FILE!
|
||||
*
|
||||
* This reset does not touch global $USER.
|
||||
*
|
||||
* Note: Only use this when the roles that need a refresh are unknown.
|
||||
*
|
||||
* @see accesslib_clear_role_cache()
|
||||
*
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
function accesslib_reset_role_cache() {
|
||||
global $ACCESSLIB_PRIVATE;
|
||||
|
||||
$ACCESSLIB_PRIVATE->cacheroledefs = array();
|
||||
$cache = cache::make('core', 'roledefs');
|
||||
$cache->purge();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears accesslib's private cache of a specific role or roles. ONLY BE USED FROM THIS LIBRARY FILE!
|
||||
*
|
||||
@@ -1280,8 +1297,6 @@ function delete_role($roleid) {
|
||||
/**
|
||||
* Function to write context specific overrides, or default capabilities.
|
||||
*
|
||||
* NOTE: use $context->mark_dirty() after this
|
||||
*
|
||||
* @param string $capability string name
|
||||
* @param int $permission CAP_ constants
|
||||
* @param int $roleid role id
|
||||
@@ -1335,8 +1350,6 @@ function assign_capability($capability, $permission, $roleid, $contextid, $overw
|
||||
/**
|
||||
* Unassign a capability from a role.
|
||||
*
|
||||
* NOTE: use $context->mark_dirty() after this
|
||||
*
|
||||
* @param string $capability the name of the capability
|
||||
* @param int $roleid the role id
|
||||
* @param int|context $contextid null means all contexts
|
||||
@@ -2097,9 +2110,6 @@ function reset_role_capabilities($roleid) {
|
||||
|
||||
// Reset any cache of this role, including MUC.
|
||||
accesslib_clear_role_cache($roleid);
|
||||
|
||||
// Mark the system context dirty.
|
||||
context_system::instance()->mark_dirty();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2217,7 +2227,7 @@ function update_capabilities($component = 'moodle') {
|
||||
capabilities_cleanup($component, $filecaps);
|
||||
|
||||
// reset static caches
|
||||
accesslib_clear_all_caches(false);
|
||||
accesslib_reset_role_cache();
|
||||
|
||||
// Flush the cached again, as we have changed DB.
|
||||
cache::make('core', 'capabilities')->delete('core_capabilities');
|
||||
@@ -2381,8 +2391,6 @@ function is_inside_frontpage(context $context) {
|
||||
* @return stdClass or null if capability not found
|
||||
*/
|
||||
function get_capability_info($capabilityname) {
|
||||
global $ACCESSLIB_PRIVATE, $DB; // one request per page only
|
||||
|
||||
$caps = get_all_capabilities();
|
||||
|
||||
if (!isset($caps[$capabilityname])) {
|
||||
@@ -4592,7 +4600,6 @@ function role_change_permission($roleid, $context, $capname, $permission) {
|
||||
|
||||
if ($permission == CAP_INHERIT) {
|
||||
unassign_capability($capname, $roleid, $context->id);
|
||||
$context->mark_dirty();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4625,7 +4632,6 @@ function role_change_permission($roleid, $context, $capname, $permission) {
|
||||
// permission already set in parent context or parent - just unset in this context
|
||||
// we do this because we want as few overrides as possible for performance reasons
|
||||
unassign_capability($capname, $roleid, $context->id);
|
||||
$context->mark_dirty();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -4639,9 +4645,6 @@ function role_change_permission($roleid, $context, $capname, $permission) {
|
||||
|
||||
// assign the needed capability
|
||||
assign_capability($capname, $permission, $roleid, $context->id, true);
|
||||
|
||||
// force cap reloading
|
||||
$context->mark_dirty();
|
||||
}
|
||||
|
||||
|
||||
@@ -5066,8 +5069,6 @@ abstract class context extends stdClass implements IteratorAggregate {
|
||||
|
||||
$trans = $DB->start_delegated_transaction();
|
||||
|
||||
$this->mark_dirty();
|
||||
|
||||
$setdepth = '';
|
||||
if (($newparent->depth +1) != $this->_depth) {
|
||||
$diff = $newparent->depth - $this->_depth + 1;
|
||||
@@ -5189,11 +5190,6 @@ abstract class context extends stdClass implements IteratorAggregate {
|
||||
$DB->delete_records('context', array('id'=>$this->_id));
|
||||
// purge static context cache if entry present
|
||||
context::cache_remove($this);
|
||||
|
||||
// do not mark dirty contexts if parents unknown
|
||||
if (!is_null($this->_path) and $this->_depth > 0) {
|
||||
$this->mark_dirty();
|
||||
}
|
||||
}
|
||||
|
||||
// ====== context level related methods ======
|
||||
|
||||
@@ -354,6 +354,7 @@ class behat_util extends testing_util {
|
||||
|
||||
// Reset all static caches.
|
||||
accesslib_clear_all_caches(true);
|
||||
accesslib_reset_role_cache();
|
||||
// Reset the nasty strings list used during the last test.
|
||||
nasty_strings::reset_used_strings();
|
||||
|
||||
|
||||
@@ -5362,8 +5362,6 @@ function reset_course_userdata($data) {
|
||||
foreach ($children as $child) {
|
||||
role_unassign_all(array('contextid' => $child->id));
|
||||
}
|
||||
// Force refresh for logged in users.
|
||||
$context->mark_dirty();
|
||||
$status[] = array('component' => $componentstr, 'item' => get_string('deletelocalroles', 'role'), 'error' => false);
|
||||
}
|
||||
|
||||
|
||||
@@ -208,6 +208,7 @@ class phpunit_util extends testing_util {
|
||||
// reset all static caches
|
||||
\core\event\manager::phpunit_reset();
|
||||
accesslib_clear_all_caches(true);
|
||||
accesslib_reset_role_cache();
|
||||
get_string_manager()->reset_caches(true);
|
||||
reset_text_filters_cache(true);
|
||||
core_text::reset_caches();
|
||||
|
||||
@@ -196,7 +196,6 @@ class core_accesslib_testcase extends advanced_testcase {
|
||||
|
||||
// Prevent the capability for this user role.
|
||||
assign_capability($capability, CAP_PROHIBIT, $role->id, $coursecontext);
|
||||
$coursecontext->mark_dirty();
|
||||
$this->assertFalse(has_capability($capability, $coursecontext, $user->id));
|
||||
|
||||
// Again, we seed the cache first by checking initial enrolment,
|
||||
@@ -3212,7 +3211,7 @@ class core_accesslib_testcase extends advanced_testcase {
|
||||
$context = context_course::instance($course->id);
|
||||
$this->assertEquals($categorycontext, $context->get_parent_context());
|
||||
$dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
|
||||
$this->assertTrue(isset($dirty[$oldpath]));
|
||||
$this->assertFalse(isset($dirty[$oldpath]));
|
||||
$this->assertTrue(isset($dirty[$context->path]));
|
||||
|
||||
|
||||
@@ -3238,7 +3237,7 @@ class core_accesslib_testcase extends advanced_testcase {
|
||||
$DB->delete_records('cache_flags', array());
|
||||
$context->delete(); // Should delete also linked blocks.
|
||||
$dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
|
||||
$this->assertTrue(isset($dirty[$context->path]));
|
||||
$this->assertFalse(isset($dirty[$context->path]));
|
||||
$this->assertFalse($DB->record_exists('context', array('id'=>$context->id)));
|
||||
$this->assertFalse($DB->record_exists('context', array('id'=>$bicontext->id)));
|
||||
$this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_MODULE, 'instanceid'=>$testpages[4])));
|
||||
@@ -3258,7 +3257,7 @@ class core_accesslib_testcase extends advanced_testcase {
|
||||
$DB->delete_records('cache_flags', array());
|
||||
context_helper::delete_instance(CONTEXT_COURSE, $lastcourse);
|
||||
$dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
|
||||
$this->assertTrue(isset($dirty[$coursecontext->path]));
|
||||
$this->assertFalse(isset($dirty[$coursecontext->path]));
|
||||
$this->assertEquals(0, context_inspection::test_context_cache_size());
|
||||
$this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$lastcourse)));
|
||||
context_course::instance($lastcourse);
|
||||
|
||||
@@ -1669,7 +1669,6 @@ class core_questionlib_testcase extends advanced_testcase {
|
||||
foreach ($capabilities as $capname => $capvalue) {
|
||||
assign_capability($capname, $capvalue, $roleid, $context->id);
|
||||
}
|
||||
$context->mark_dirty();
|
||||
|
||||
$this->setUser($user);
|
||||
|
||||
@@ -1719,7 +1718,6 @@ class core_questionlib_testcase extends advanced_testcase {
|
||||
foreach ($capabilities as $capname => $capvalue) {
|
||||
assign_capability($capname, $capvalue, $roleid, $context->id);
|
||||
}
|
||||
$context->mark_dirty();
|
||||
|
||||
// Create the question.
|
||||
$qtype = 'truefalse';
|
||||
@@ -1771,7 +1769,6 @@ class core_questionlib_testcase extends advanced_testcase {
|
||||
foreach ($capabilities as $capname => $capvalue) {
|
||||
assign_capability($capname, $capvalue, $roleid, $context->id);
|
||||
}
|
||||
$context->mark_dirty();
|
||||
|
||||
// Create the question.
|
||||
$qtype = 'truefalse';
|
||||
@@ -1823,7 +1820,6 @@ class core_questionlib_testcase extends advanced_testcase {
|
||||
foreach ($capabilities as $capname => $capvalue) {
|
||||
assign_capability($capname, $capvalue, $roleid, $context->id);
|
||||
}
|
||||
$context->mark_dirty();
|
||||
|
||||
// Create the question.
|
||||
$qtype = 'truefalse';
|
||||
@@ -1881,8 +1877,6 @@ class core_questionlib_testcase extends advanced_testcase {
|
||||
foreach ($capabilities as $capname => $capvalue) {
|
||||
assign_capability($capname, $capvalue, $roleid, $newcontext->id);
|
||||
}
|
||||
$context->mark_dirty();
|
||||
$newcontext->mark_dirty();
|
||||
|
||||
// Create the question.
|
||||
$qtype = 'truefalse';
|
||||
@@ -1938,7 +1932,6 @@ class core_questionlib_testcase extends advanced_testcase {
|
||||
foreach ($capabilities as $capname => $capvalue) {
|
||||
assign_capability($capname, $capvalue, $roleid, $context->id);
|
||||
}
|
||||
$context->mark_dirty();
|
||||
|
||||
// Create the question.
|
||||
$question = $questiongenerator->create_question('truefalse', null, [
|
||||
|
||||
@@ -254,7 +254,6 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
// Remove the viewparticipants capability from one of the courses.
|
||||
$course5context = context_course::instance($course5->id);
|
||||
assign_capability('moodle/course:viewparticipants', CAP_PROHIBIT, $role->id, $course5context->id);
|
||||
$course5context->mark_dirty();
|
||||
|
||||
// Perform a search.
|
||||
list($contacts, $courses, $noncontacts) = \core_message\api::search_users($user1->id, 'search');
|
||||
|
||||
@@ -279,7 +279,6 @@ class mod_feedback_lib_testcase extends advanced_testcase {
|
||||
|
||||
$this->setUser($user);
|
||||
assign_capability('mod/feedback:complete', CAP_PROHIBIT, $studentrole->id, $context);
|
||||
$context->mark_dirty();
|
||||
|
||||
$factory = new \core_calendar\action_factory();
|
||||
$action = mod_feedback_core_calendar_provide_event_action($event, $factory);
|
||||
|
||||
@@ -155,7 +155,6 @@ class mod_forum_subscriptions_testcase extends advanced_testcase {
|
||||
$roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
|
||||
$context = \context_course::instance($course->id);
|
||||
assign_capability('moodle/course:viewhiddenactivities', CAP_ALLOW, $roleids['student'], $context);
|
||||
$context->mark_dirty();
|
||||
|
||||
// All of the unsubscribable forums should now be listed.
|
||||
$result = \mod_forum\subscriptions::get_unsubscribable_forums();
|
||||
@@ -906,7 +905,6 @@ class mod_forum_subscriptions_testcase extends advanced_testcase {
|
||||
$cm = get_coursemodule_from_instance('forum', $forum->id);
|
||||
$context = \context_module::instance($cm->id);
|
||||
assign_capability('mod/forum:allowforcesubscribe', CAP_PROHIBIT, $roleids['student'], $context);
|
||||
$context->mark_dirty();
|
||||
$this->assertFalse(has_capability('mod/forum:allowforcesubscribe', $context, $user->id));
|
||||
|
||||
// Check that the user is no longer subscribed to the forum.
|
||||
|
||||
@@ -102,7 +102,6 @@ class core_tag_external_testcase extends externallib_advanced_testcase {
|
||||
// User with editing and manage cap can also change the tag name,
|
||||
// make it standard and reset flag.
|
||||
assign_capability('moodle/tag:manage', CAP_ALLOW, $roleid, $context->id);
|
||||
$context->mark_dirty();
|
||||
$this->assertTrue(has_capability('moodle/tag:manage', $context));
|
||||
$result = core_tag_external::update_tags(array($updatetag));
|
||||
$result = external_api::clean_returnvalue(core_tag_external::update_tags_returns(), $result);
|
||||
|
||||
@@ -587,7 +587,6 @@ class core_userliblib_testcase extends advanced_testcase {
|
||||
|
||||
// Remove capability moodle/user:viewdetails in course 2.
|
||||
assign_capability('moodle/user:viewdetails', CAP_PROHIBIT, $studentrole->id, $coursecontext);
|
||||
$coursecontext->mark_dirty();
|
||||
// Set current user to user 1.
|
||||
$this->setUser($user1);
|
||||
// User 1 can see User 1's profile.
|
||||
@@ -693,13 +692,11 @@ class core_userliblib_testcase extends advanced_testcase {
|
||||
$systemcontext = context_system::instance();
|
||||
assign_capability('moodle/user:viewdetails', CAP_PREVENT, $managerrole->id, $systemcontext, true);
|
||||
assign_capability('moodle/user:viewalldetails', CAP_PREVENT, $managerrole->id, $systemcontext, true);
|
||||
$systemcontext->mark_dirty();
|
||||
|
||||
// And override these to 'Allow' in a specific course.
|
||||
$course4context = context_course::instance($course4->id);
|
||||
assign_capability('moodle/user:viewalldetails', CAP_ALLOW, $managerrole->id, $course4context, true);
|
||||
assign_capability('moodle/user:viewdetails', CAP_ALLOW, $managerrole->id, $course4context, true);
|
||||
$course4context->mark_dirty();
|
||||
|
||||
// The manager now shouldn't have viewdetails in the system or user context.
|
||||
$this->setUser($user9);
|
||||
|
||||
Reference in New Issue
Block a user