Commit ec41d0e0 authored by Robert Lyon's avatar Robert Lyon Committed by Aaron Wells

Bug 1467368: Allowing the main menu structure to be cached

This will allow the rendering of the main nav to use less resources.

The cached menus are saved for each institution into the
institution_config table for these types of menus:

adminnav     - site administration navigation
instadminnav - institution admin navigation
staffnav     - site staff admin navigation
inststaffnav - institution staff admin navigation
standardnav  - navigation seen in normal section of site

To clear cache menus call clear_menu_cache($institution)

Change-Id: I3b58090830b6d28f10f24e23abeef775c6863aa5
Signed-off-by: Robert Lyon's avatarRobert Lyon <robertl@catalyst.net.nz>
parent dd0e1dab
......@@ -33,6 +33,7 @@ if ($disable && !call_static_method(generate_class_name($plugintype, $pluginname
if ($enable || $disable) {
require_once(get_config('libroot') . 'upgrade.php');
clear_menu_cache();
activate_plugin_form($plugintype, get_record($plugintype . '_installed', 'name', $pluginname));
}
......@@ -103,6 +104,7 @@ function pluginconfig_submit(Pieform $form, $values) {
}
if ($success) {
clear_menu_cache();
$form->json_reply(PIEFORM_OK, get_string('settingssaved'));
}
else {
......
......@@ -929,6 +929,8 @@ function siteoptions_submit(Pieform $form, $values) {
)
);
}
// Need to clear the cached menus in case site config changes effect them.
clear_menu_cache();
$message = get_string('siteoptionsset', 'admin');
if ($oldtheme != $values['theme']) {
......
......@@ -31,6 +31,7 @@ raise_memory_limit('256M');
$data = array(
'key' => $name
);
if ($install) {
if (!get_config('installed')) {
if ($name == 'localpreinst' || $name == 'localpostinst') {
......@@ -65,6 +66,9 @@ if ($install) {
}
if (!empty($upgrade)) {
// clear out menu cache to allow upgraded site to remake cached menus
clear_menu_cache();
if (!empty($upgrade->errormsg)) {
$data['newversion'] = $upgrade->torelease . ' (' . $upgrade->to . ')' ;
$data['install'] = false;
......
......@@ -721,6 +721,8 @@ function institution_submit(Pieform $form, $values) {
$newinstitution = new Institution($institution);
$newinstitution->displayname = $values['displayname'];
$oldinstitution = get_record('institution', 'name', $institution);
// Clear out any cached menus for this institution
clear_menu_cache($institution);
}
$newinstitution->showonlineusers = !isset($values['showonlineusers']) ? 2 : $values['showonlineusers'];
......
......@@ -1077,10 +1077,6 @@ function set_config_plugin_instance($plugintype, $pluginname, $pluginid, $key, $
/**
* Fetch an institution configuration (from either the "institution" or "institution_config" table)
*
* TODO: If needed, create a corresponding set_config_institution(). This would be most useful if there's
* a situation where you need to manipulate individual institution configs. If you want to manipulate
* them in batch, you can use the Institution class's __set() and commit() methods.
*
* @param string $institutionname
* @param string $key
* @return mixed The value of the key or NULL if the key is not valid
......@@ -1098,7 +1094,7 @@ function get_config_institution($institutionname, $key) {
try {
$inst = new Institution($institutionname);
// Cache it (in $CFG so if we ever write set_config_institution() we can make it update the cache)
// Cache it in $CFG so we can make set_config_institution() update the cache
if (!isset($CFG->fetchedinst)) {
$CFG->fetchedinst = new stdClass();
}
......@@ -1113,6 +1109,36 @@ function get_config_institution($institutionname, $key) {
return $inst->{$key};
}
/**
* Set or update an institution config value.
*
* @param string $institutionname The institution name
* @param string $key The config name
* @param string $value The config's new value
* @return boolean Whether or not the config was updated successfully
*/
function set_config_institution($institutionname, $key, $value) {
global $CFG;
if (isset($CFG->fetchedinst->{$institutionname})) {
$inst = $CFG->fetchedinst->{$institutionname};
}
else {
// No cache hit, so instatiate a new Institution object
try {
$inst = new Institution($institutionname);
}
catch (ParamOutOfRangeException $e) {
return null;
}
}
if (isset($inst)) {
$inst->{$key} = $value;
$inst->commit();
return true;
}
return false;
}
/**
* Fetch a config setting for the specified user's institutions (from either the "institution" or "institution_config" table)
......
......@@ -2894,48 +2894,101 @@ function mahara_standard_nav() {
* @return array
*/
function main_nav() {
global $USER;
$cachemenu = false;
// Get the first institution
$institution = !empty(array_keys($USER->get('institutions'))[0]) ? array_keys($USER->get('institutions'))[0] : 'mahara';
$menutype = '';
if (in_admin_section()) {
global $USER, $SESSION;
if ($USER->get('admin')) {
$menu = admin_nav();
$menutype = 'adminnav';
if (!($cachemenu = get_config_institution($institution, 'adminnav'))) {
$menu = admin_nav();
}
}
else if ($USER->is_institutional_admin()) {
$menu = institutional_admin_nav();
$menutype = 'instadminnav';
if (!($cachemenu = get_config_institution($institution, 'instadminnav'))) {
$menu = institutional_admin_nav();
}
}
else if ($USER->get('staff')) {
$menu = staff_nav();
$menutype = 'staffnav';
if (!($cachemenu = get_config_institution($institution, 'staffnav'))) {
$menu = staff_nav();
}
}
else {
$menu = institutional_staff_nav();
$menutype = 'inststaffnav';
if (!($cachemenu = get_config_institution($institution, 'inststaffnav'))) {
$menu = institutional_staff_nav();
}
}
}
else {
// Build the menu structure for the site
$menu = mahara_standard_nav();
$menutype = 'standardnav';
if (!($cachemenu = get_config_institution($institution, 'standardnav'))) {
$menu = mahara_standard_nav();
}
}
$menu = array_filter($menu, create_function('$a', 'return empty($a["ignore"]);'));
// enable plugins to augment the menu structure
foreach (array('artefact', 'interaction', 'module', 'auth') as $plugintype) {
if ($plugins = plugins_installed($plugintype)) {
foreach ($plugins as &$plugin) {
if (safe_require_plugin($plugintype, $plugin->name)) {
$plugin_menu = call_static_method(generate_class_name($plugintype,$plugin->name), 'menu_items');
$menu = array_merge($menu, $plugin_menu);
if ($cachemenu) {
$menu = json_decode($cachemenu, true);
}
else {
$menu = array_filter($menu, create_function('$a', 'return empty($a["ignore"]);'));
// enable plugins to augment the menu structure
foreach (array('artefact', 'interaction', 'module', 'auth') as $plugintype) {
if ($plugins = plugins_installed($plugintype)) {
foreach ($plugins as &$plugin) {
if (safe_require_plugin($plugintype, $plugin->name)) {
$plugin_menu = call_static_method(generate_class_name($plugintype,$plugin->name), 'menu_items');
$menu = array_merge($menu, $plugin_menu);
}
}
}
}
set_config_institution($institution, $menutype, json_encode($menu));
}
// local_main_nav_update allows sites to customise the menu by munging the $menu array.
// as there is no internal way to know if the local_main_nav array has changed we keep it outside the cached menu
if (function_exists('local_main_nav_update')) {
local_main_nav_update($menu);
}
$menu_structure = find_menu_children($menu, '');
return $menu_structure;
}
/**
* Clear the cached menu so that the next visit to the site will recreate the cache.
*
* @param string $institution Optional institution name if we only want to delete cache from a certain institution
*/
function clear_menu_cache($institution = null) {
if ($institution) {
try {
delete_records_sql("DELETE FROM {institution_config} WHERE field IN ('adminnav','instadminnav','staffnav','inststaffnav','standardnav') AND institution = ?", array($institution));
}
catch (SQLException $e) {
// Institution_config table may not exist on install/upgrade at this point
}
}
else {
try {
delete_records_sql("DELETE FROM {institution_config} WHERE field IN ('adminnav','instadminnav','staffnav','inststaffnav','standardnav')", array());
}
catch (SQLException $e) {
// Institution_config table may not exist on install/upgrade at this point
}
}
}
function right_nav() {
global $USER, $THEME;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment