MDL-17556: Improve performance of get_fast_modinfo when courses have many activities

This commit is contained in:
sam_marshall 2008-12-18 17:52:29 +00:00
parent 6093af9bc4
commit 00653161b5
3 changed files with 57 additions and 12 deletions

@ -1121,15 +1121,8 @@ function &get_fast_modinfo(&$course, $userid=0) {
$modlurals = array();
$cmids = array();
$contexts = null;
foreach ($info as $mod) {
$cmids[$mod->cm] = $mod->cm;
}
if ($cmids) {
// preload all module contexts with one query
$contexts = get_context_instance(CONTEXT_MODULE, $cmids);
}
// If we haven't already preloaded contexts for the course, do it now
preload_course_contexts($course->id);
foreach ($info as $mod) {
if (empty($mod->name)) {
@ -1178,7 +1171,8 @@ function &get_fast_modinfo(&$course, $userid=0) {
$modlurals[$cm->modname] = get_string('modulenameplural', $cm->modname);
}
$cm->modplural = $modlurals[$cm->modname];
$modcontext = get_context_instance(CONTEXT_MODULE,$cm->id);
if(!empty($CFG->enableavailability)) {
// Unfortunately the next call really wants to call
// get_fast_modinfo, but that would be recursive, so we fake up a
@ -1201,11 +1195,11 @@ function &get_fast_modinfo(&$course, $userid=0) {
} else {
$cm->available=true;
}
if ((!$cm->visible or !$cm->available) and !has_capability('moodle/course:viewhiddenactivities', $contexts[$cm->id], $userid)) {
if ((!$cm->visible or !$cm->available) and !has_capability('moodle/course:viewhiddenactivities', $modcontext, $userid)) {
$cm->uservisible = false;
} else if (!empty($CFG->enablegroupings) and !empty($cm->groupmembersonly)
and !has_capability('moodle/site:accessallgroups', $contexts[$cm->id], $userid)) {
and !has_capability('moodle/site:accessallgroups', $modcontext, $userid)) {
if (is_null($modinfo->groups)) {
$modinfo->groups = groups_get_user_groups($course->id, $userid);
}

@ -39,6 +39,7 @@
}
}
preload_course_contexts($course->id);
if (!$context = get_context_instance(CONTEXT_COURSE, $course->id)) {
print_error('nocontext');
}

@ -2407,6 +2407,56 @@ function cleanup_contexts() {
return true;
}
/**
* Preloads all contexts relating to a course: course, modules, and blocks.
*
* @param int $courseid Course ID
*/
function preload_course_contexts($courseid) {
global $context_cache, $context_cache_id, $CFG, $DB;
// Users can call this multiple times without doing any harm
static $preloadedcourses=array();
if(array_key_exists($courseid,$preloadedcourses)) {
return;
}
$rs=$DB->get_recordset_sql("
SELECT
x.instanceid, x.id, x.contextlevel, x.path, x.depth
FROM
{course_modules} cm
INNER JOIN {context} x ON x.instanceid=cm.id
WHERE
cm.course=?
AND x.contextlevel=".CONTEXT_MODULE."
UNION ALL
SELECT
x.instanceid, x.id, x.contextlevel, x.path, x.depth
FROM
{block_instance} bi
INNER JOIN {context} x ON x.instanceid=bi.id
WHERE
bi.pageid=?
AND bi.pagetype='course-view'
AND x.contextlevel=".CONTEXT_BLOCK."
UNION ALL
SELECT
x.instanceid, x.id, x.contextlevel, x.path, x.depth
FROM
{context} x
WHERE
x.instanceid=?
AND x.contextlevel=".CONTEXT_COURSE."
",array($courseid,$courseid,$courseid)); // Note, repetition of parameter annoying but required
foreach($rs as $context) {
$context_cache[$context->contextlevel][$context->instanceid] = $context;
$context_cache_id[$context->id] = $context;
}
$rs->close();
$preloadedcourses[$courseid]=true;
}
/**
* Get the context instance as an object. This function will create the
* context instance if it does not exist yet.