course/index: move orphan fixups to an optimised fix_coursecategory_orphans()
authormartinlanghoff <martinlanghoff>
Wed, 12 Sep 2007 02:56:36 +0000 (02:56 +0000)
committermartinlanghoff <martinlanghoff>
Wed, 12 Sep 2007 02:56:36 +0000 (02:56 +0000)
Move the fixups for orphan courses to the newly minted
fix_coursecategory_orphans() -- and optimise it to take only 1 dbquery for
the common case.

If we do find lots of orphans, we issue 2 updates per orphan.

This cuts down dbqueries drastically - we used to have 2x the number of
courses in the site.

course/index.php
lib/datalib.php

index 9efa48513e022f79565bc03e54830592586acfcb..9dad679ac95d08864b74e29afb7c74f59c7562af 100644 (file)
         }
     }
 
-/// Find the default category (the one with the lowest ID)
-    $categories = get_categories();
-    $default = 99999;
-    foreach ($categories as $category) {
-        if ($category->id < $default) {
-            $default = $category->id;
-        }
-    }
-
 /// Find any orphan courses that don't yet have a valid category and set to default
-    if ($courses = get_courses(NULL,NULL,'c.id, c.category, c.sortorder, c.visible')) {
-        foreach ($courses as $course) {
-            if ($course->category and !isset($categories[$course->category])) {
-                set_field('course', 'category', $default, 'id', $course->id);
-            }
-        }
-    }
+    fix_coursecategory_orphans();
 
+/// Should be a no-op 99% of the cases
     fix_course_sortorder();
 
 /// Print form for creating new categories
index f473cb5842e107f29b2e3da8ffcbe3f244b6f3e2..67d85f943d2840d2ec2899d235ecde5ab53b16b2 100644 (file)
@@ -1019,6 +1019,49 @@ function fix_course_sortorder($categoryid=0, $n=0, $safe=0, $depth=0, $path='')
     return $n+1;
 }
 
+/**
+ * Ensure all courses have a valid course category
+ * useful if a category has been removed manually
+ **/
+function fix_coursecategory_orphans() {
+
+    global $CFG;
+
+    // Note: the handling of sortorder here is arguably
+    // open to race conditions. Hard to fix here, unlikely
+    // to hit anyone in production.
+
+    $sql = "SELECT c.id, c.category, c.shortname
+            FROM {$CFG->prefix}course c
+            LEFT OUTER JOIN {$CFG->prefix}course_categories cc ON c.category=cc.id
+            WHERE cc.id IS NULL AND c.id != " . SITEID;
+
+    $rs = get_recordset_sql($sql);
+
+    if ($rs->RecordCount()){ // we have some orphans
+
+        // the "default" category is the lowest numbered...
+        $default   = get_field_sql("SELECT MIN(id)
+                                    FROM {$CFG->prefix}course_categories");
+        $sortorder = get_field_sql("SELECT MAX(sortorder)
+                                    FROM {$CFG->prefix}course
+                                    WHERE category=$default");
+
+
+        begin_sql();
+        $tx = true;
+        while ($tx && $course = rs_fetch_next_record($rs)) {
+            $tx = $tx && set_field('course', 'category',  $default,     'id', $course->id);
+            $tx = $tx && set_field('course', 'sortorder', ++$sortorder, 'id', $course->id);
+        }
+        if ($tx) {
+            commit_sql();
+        } else {
+            rollback_sql();
+        }
+    }
+}
+
 /**
  * List of remote courses that a user has access to via MNET.
  * Works only on the IDP