navigation MDL-20521 Fixed caching issue with admin tree

Added methods that allow a navigation cache to be marked as volatile so that it is destroyed on shutdown, forcing the next page to load to completely regenerate the navigation structure.
Caches are marked as volatile automatically if the load is within the system context, and can optionally be marked as volatile by calling PAGE->navigation->clear_cache() if desired.
This commit is contained in:
samhemelryk 2009-10-12 05:39:32 +00:00
parent fa8431d74f
commit f5b5a82203
3 changed files with 71 additions and 6 deletions

View File

@ -12,6 +12,7 @@ require_login(0, false);
$PAGE->set_context(get_context_instance(CONTEXT_SYSTEM));
$PAGE->set_url($CFG->admin . '/settings.php', array('section' => $section));
$PAGE->set_pagetype('admin-setting-' . $section);
$PAGE->navigation->clear_cache();
$adminroot = admin_get_root(); // need all settings
$settingspage = $adminroot->locate($section, true);

View File

@ -5218,6 +5218,8 @@ function admin_externalpage_setup($section, $extrabutton = '',
if ($PAGE->user_allowed_editing() && $adminediting != -1) {
$USER->editing = $adminediting;
}
$PAGE->navigation->clear_cache();
}
/**

View File

@ -31,6 +31,11 @@ if (!function_exists('get_all_sections')) {
require_once($CFG->dirroot.'/course/lib.php');
}
/**
* The name that will be used to seperate the navigation cache within SESSION
*/
define('NAVIGATION_CACHE_NAME', 'navigation');
/**
* This class is used to represent a node in a navigation tree
*
@ -772,7 +777,7 @@ class global_navigation extends navigation_node {
$this->text = get_string('home');
$this->forceopen = true;
$this->action = new moodle_url($CFG->wwwroot);
$this->cache = new navigation_cache('navigation');
$this->cache = new navigation_cache(NAVIGATION_CACHE_NAME);
$PAGE->requires->string_for_js('moveallsidetabstoblock','moodle');
$regenerate = optional_param('regenerate', null, PARAM_TEXT);
if ($regenerate==='navigation') {
@ -820,7 +825,8 @@ class global_navigation extends navigation_node {
$depth = 0;
switch ($contextlevel) {
case CONTEXT_SYSTEM:
case CONTEXT_SYSTEM:
$this->cache->volatile();
$depth = $this->load_for_category(false);
break;
case CONTEXT_COURSECAT:
@ -1560,6 +1566,13 @@ class global_navigation extends navigation_node {
}
return 0;
}
/**
* This function marks the cache as volatile so it is cleared during shutdown
*/
public function clear_cache() {
$this->cache->volatile();
}
}
/**
@ -2011,7 +2024,7 @@ class navbar extends navigation_node {
* @param bool $firstnode
* @return string HTML
*/
protected function parse_branch_to_html($navarray, $firstnode=true, $moreafterthis) {
protected function parse_branch_to_html($navarray, $firstnode=true, $moreafterthis=false) {
$separator = get_separator();
$output = '';
if ($firstnode===true) {
@ -2126,7 +2139,7 @@ class settings_navigation extends navigation_node {
// before we try anything
$this->page->navigation->initialise();
// Initialise the navigation cache
$this->cache = new navigation_cache('navigation');
$this->cache = new navigation_cache(NAVIGATION_CACHE_NAME);
}
/**
* Initialise the settings navigation based on the current context
@ -2143,6 +2156,7 @@ class settings_navigation extends navigation_node {
$this->context = $this->page->context;
switch ($this->context->contextlevel) {
case CONTEXT_SYSTEM:
$this->cache->volatile();
$adminkey = $this->load_administration_settings();
$settingskey = $this->load_user_settings(SITEID);
break;
@ -2278,7 +2292,7 @@ class settings_navigation extends navigation_node {
if (!function_exists('admin_get_root')) {
require_once($CFG->dirroot.'/lib/adminlib.php');
}
$adminroot = admin_get_root();
$adminroot = admin_get_root(false, false);
$branchkey = $this->add(get_string('administrationsite'),new moodle_url($CFG->wwwroot.'/admin/'), self::TYPE_SETTING);
$referencebranch = $this->get($branchkey);
foreach ($adminroot->children as $adminbranch) {
@ -3001,6 +3015,13 @@ class settings_navigation extends navigation_node {
}
}
}
/**
* This function marks the cache as volatile so it is cleared during shutdown
*/
public function clear_cache() {
$this->cache->volatile();
}
}
/**
@ -3135,6 +3156,8 @@ class navigation_cache {
const CACHEUSERID = 1;
/** @var int */
const CACHEVALUE = 2;
/** @var null|array An array of navigation cache areas to expire on shutdown */
public static $volatilecaches;
/**
* Contructor for the cache. Requires two arguments
@ -3187,7 +3210,7 @@ class navigation_cache {
public function __set($key, $information) {
$this->set($key, $information);
}
/**
* Sets some information against the cache (session) for later retrieval
*
@ -3249,4 +3272,43 @@ class navigation_cache {
}
}
}
/**
* Marks the cache as being volatile (likely to change)
*
* Any caches marked as volatile will be destroyed at the on shutdown by
* {@link navigation_node::destroy_volatile_caches()} which is registered
* as a shutdown function if any caches are marked as volatile.
*
* @param bool $setting True to destroy the cache false not too
*/
public function volatile($setting = true) {
if (self::$volatilecaches===null) {
self::$volatilecaches = array();
register_shutdown_function(array('navigation_cache','destroy_volatile_caches'));
}
if ($setting) {
self::$volatilecaches[$this->area] = $this->area;
} else if (array_key_exists($this->area, self::$volatilecaches)) {
unset(self::$volatilecaches[$this->area]);
}
}
/**
* Destroys all caches marked as volatile
*
* This function is static and works in conjunction with the static volatilecaches
* property of navigation cache.
* Because this function is static it manually resets the cached areas back to an
* empty array.
*/
public static function destroy_volatile_caches() {
global $SESSION;
if (is_array(self::$volatilecaches) && count(self::$volatilecaches)>0) {
foreach (self::$volatilecaches as $area) {
$SESSION->navcache->{$area} = array();
}
}
}
}