]> git.mjollnir.org Git - moodle.git/commitdiff
MDL-17556: Improve performance of get_fast_modinfo when courses have many activities
authorsam_marshall <sam_marshall>
Thu, 18 Dec 2008 17:52:29 +0000 (17:52 +0000)
committersam_marshall <sam_marshall>
Thu, 18 Dec 2008 17:52:29 +0000 (17:52 +0000)
course/lib.php
course/view.php
lib/accesslib.php

index f897235c308bf8074db06d82f8adec3907abca87..e05f950ad5de10b222ec44df6e6594c17b01c73d 100644 (file)
@@ -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);
             }
index 51870e5e933fa4bae68cfd9b7d1cf36a6acbde71..48e65d0e767bf13dd4705fea2daf14d0c0075f17 100644 (file)
@@ -39,6 +39,7 @@
         }
     }
 
+    preload_course_contexts($course->id);
     if (!$context = get_context_instance(CONTEXT_COURSE, $course->id)) {
         print_error('nocontext');
     }
index ba6b9507e8e70ff843651a374d9f3688bc360b30..481cc646cfdfb2618c6f4e073dd0ee453f17ab03 100755 (executable)
@@ -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.