### Eclipse Workspace Patch 1.0
#P moodle19
Index: admin/xmldb/actions/get_db_directories/get_db_directories.class.php
===================================================================
RCS file: /cvsroot/moodle/moodle/admin/xmldb/actions/get_db_directories/get_db_directories.class.php,v
retrieving revision 1.8.2.2
diff -u -r1.8.2.2 get_db_directories.class.php
--- admin/xmldb/actions/get_db_directories/get_db_directories.class.php	19 Dec 2007 15:06:52 -0000	1.8.2.2
+++ admin/xmldb/actions/get_db_directories/get_db_directories.class.php	3 Jan 2008 10:18:22 -0000
@@ -70,111 +70,17 @@
         if (!isset($XMLDB->dbdirs)) {
             $XMLDB->dbdirs = array();
         }
-    /// First, the main one (lib/db)
-        $dbdir = new stdClass;
-        $dbdir->path = $CFG->libdir . '/db';
-        if (!isset($XMLDB->dbdirs[$dbdir->path])) {
-            $XMLDB->dbdirs[$dbdir->path] = $dbdir;
-        }
-        $XMLDB->dbdirs[$dbdir->path]->path_exists = file_exists($dbdir->path);  //Update status
 
-    /// Now, activity modules (mod/xxx/db)
-        if ($plugins = get_list_of_plugins('mod')) {
-            foreach ($plugins as $plugin) {
-                $dbdir = new stdClass;
-                $dbdir->path = $CFG->dirroot . '/mod/' . $plugin . '/db';
-                if (!isset($XMLDB->dbdirs[$dbdir->path])) {
-                    $XMLDB->dbdirs[$dbdir->path] = $dbdir;
-                }
-                $XMLDB->dbdirs[$dbdir->path]->path_exists = file_exists($dbdir->path);  //Update status
-            }
-        }
-
-    /// Now, assignment submodules (mod/assignment/type/xxx/db)
-        if ($plugins = get_list_of_plugins('mod/assignment/type')) {
-            foreach ($plugins as $plugin) {
-                $dbdir = new stdClass;
-                $dbdir->path = $CFG->dirroot . '/mod/assignment/type/' . $plugin . '/db';
-                if (!isset($XMLDB->dbdirs[$dbdir->path])) {
-                    $XMLDB->dbdirs[$dbdir->path] = $dbdir;
-                }
-                $XMLDB->dbdirs[$dbdir->path]->path_exists = file_exists($dbdir->path);  //Update status
-            }
-        }
-
-    /// Now, question types (question/type/xxx/db)
-        if ($plugins = get_list_of_plugins('question/type')) {
-            foreach ($plugins as $plugin) {
-                $dbdir = new stdClass;
-                $dbdir->path = $CFG->dirroot . '/question/type/' . $plugin . '/db';
-                if (!isset($XMLDB->dbdirs[$dbdir->path])) {
-                    $XMLDB->dbdirs[$dbdir->path] = $dbdir;
-                }
-                $XMLDB->dbdirs[$dbdir->path]->path_exists = file_exists($dbdir->path);  //Update status
-            }
-        }
-
-    /// Now, backup/restore stuff (backup/db)
-        $dbdir = new stdClass;
-        $dbdir->path = $CFG->dirroot . '/backup/db';
-        if (!isset($XMLDB->dbdirs[$dbdir->path])) {
-            $XMLDB->dbdirs[$dbdir->path] = $dbdir;
-        }
-        $XMLDB->dbdirs[$dbdir->path]->path_exists = file_exists($dbdir->path);  //Update status
-
-    /// Now, block system stuff (blocks/db)
-        $dbdir = new stdClass;
-        $dbdir->path = $CFG->dirroot . '/blocks/db';
-        if (!isset($XMLDB->dbdirs[$dbdir->path])) {
-            $XMLDB->dbdirs[$dbdir->path] = $dbdir;
-        }
-        $XMLDB->dbdirs[$dbdir->path]->path_exists = file_exists($dbdir->path);  //Update status
-
-    /// Now, blocks (blocks/xxx/db)
-        if ($plugins = get_list_of_plugins('blocks', 'db')) {
-            foreach ($plugins as $plugin) {
-                $dbdir = new stdClass;
-                $dbdir->path = $CFG->dirroot . '/blocks/' . $plugin . '/db';
-                if (!isset($XMLDB->dbdirs[$dbdir->path])) {
-                    $XMLDB->dbdirs[$dbdir->path] = $dbdir;
-                }
-                $XMLDB->dbdirs[$dbdir->path]->path_exists = file_exists($dbdir->path);  //Update status
-            }
-        }
-
-    /// Now, course formats (course/format/xxx/db)
-        if ($plugins = get_list_of_plugins('course/format', 'db')) {
-            foreach ($plugins as $plugin) {
-                $dbdir = new stdClass;
-                $dbdir->path = $CFG->dirroot . '/course/format/' . $plugin . '/db';
-                if (!isset($XMLDB->dbdirs[$dbdir->path])) {
-                    $XMLDB->dbdirs[$dbdir->path] = $dbdir;
-                }
-                $XMLDB->dbdirs[$dbdir->path]->path_exists = file_exists($dbdir->path);  //Update status
-            }
-        }
-
-    /// Now, enrolment plugins (enrol/xxx/db)
-        if ($plugins = get_list_of_plugins('enrol', 'db')) {
-            foreach ($plugins as $plugin) {
-                $dbdir = new stdClass;
-                $dbdir->path = $CFG->dirroot . '/enrol/' . $plugin . '/db';
-                if (!isset($XMLDB->dbdirs[$dbdir->path])) {
-                    $XMLDB->dbdirs[$dbdir->path] = $dbdir;
-                }
-                $XMLDB->dbdirs[$dbdir->path]->path_exists = file_exists($dbdir->path);  //Update status
-            }
-        }
-
-    /// Local database changes, if the local folder exists.
-        if (file_exists($CFG->dirroot . '/local')) {
+    /// get list of all dirs and create objects with status
+        $db_direcotries = get_db_directories();
+        foreach ($db_direcotries as $path) {
             $dbdir = new stdClass;
-            $dbdir->path = $CFG->dirroot . '/local/db';
+            $dbdir->path = $path;
             if (!isset($XMLDB->dbdirs[$dbdir->path])) {
                 $XMLDB->dbdirs[$dbdir->path] = $dbdir;
-            }
+             }
             $XMLDB->dbdirs[$dbdir->path]->path_exists = file_exists($dbdir->path);  //Update status
-        }
+         }
 
     /// Sort by key
         ksort($XMLDB->dbdirs);
Index: lib/ddllib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/ddllib.php,v
retrieving revision 1.59.2.1
diff -u -r1.59.2.1 ddllib.php
--- lib/ddllib.php	3 Dec 2007 23:19:17 -0000	1.59.2.1
+++ lib/ddllib.php	3 Jan 2008 10:18:23 -0000
@@ -636,6 +636,193 @@
 }
 
 /**
+ * This function will all tables found in XMLDB file from db
+ *
+ * @uses $CFG, $db
+ * @param $file full path to the XML file to be used
+ * @param $feedback
+ * @return boolean (true on success, false on error)
+ */
+function delete_tables_from_xmldb_file($file, $feedback=true ) {
+
+    global $CFG, $db;
+
+    $status = true;
+
+
+    $xmldb_file = new XMLDBFile($file);
+
+    if (!$xmldb_file->fileExists()) {
+        return false;
+    }
+
+    $loaded    = $xmldb_file->loadXMLStructure();
+    $structure =& $xmldb_file->getStructure();
+
+    if (!$loaded || !$xmldb_file->isLoaded()) {
+    /// Show info about the error if we can find it
+        if ($feedback and $structure) {
+            if ($errors = $structure->getAllErrors()) {
+                notify('Errors found in XMLDB file: '. implode (', ', $errors));
+            }
+        }
+        return false;
+    }
+
+    if ($tables = $structure->getTables()) {
+        foreach($tables as $table) {
+            if (table_exists($table)) {
+                drop_table($table, true, $feedback);
+            }
+        }
+    }
+
+    return true;
+}
+
+/**
+ * Delete all plugin tables
+ * @name string name of plugin, used as table prefix
+ * @file string path to install.xml file
+ * @feedback boolean
+ */
+function drop_plugin_tables($name, $file, $feedback=true) {
+    global $CFG, $db;
+
+    // first try normal delete
+    if (delete_tables_from_xmldb_file($file, $feedback)) {
+        return true;
+    }
+
+    // then try to find all tables that start with name and are not in any xml file
+    $used_tables = get_used_table_names();
+
+    $tables = $db->MetaTables();
+    /// Iterate over, fixing id fields as necessary
+    foreach ($tables as $table) {
+        if (strlen($CFG->prefix)) {
+            if (strpos($table, $CFG->prefix) !== 0) {
+                continue;
+            }
+            $table = substr($table, strlen($CFG->prefix));
+        }
+        $table = strtolower($table);
+        if (strpos($table, $name) !== 0) {
+            continue;
+        }
+        if (in_array($table, $used_tables)) {
+            continue;
+        }
+
+        // found orphan table --> delete it
+        $table = new XMLDBTable($table);
+        if (table_exists($table)) {
+            drop_table($table, true, $feedback);
+        }
+    }
+
+    return true;
+}
+
+/**
+ * Returns names of all known tables == tables that moodle knowns about.
+ * @return array of lowercase table names
+ */
+function get_used_table_names() {
+    $table_names = array();
+    $dbdirs = get_db_directories();
+
+    foreach ($dbdirs as $dbdir) {
+        $file = $dbdir.'/install.xml';
+
+        $xmldb_file = new XMLDBFile($file);
+
+        if (!$xmldb_file->fileExists()) {
+            continue;
+        }
+
+        $loaded    = $xmldb_file->loadXMLStructure();
+        $structure =& $xmldb_file->getStructure();
+
+        if ($loaded and $tables = $structure->getTables()) {
+            foreach($tables as $table) {
+                $table_names[] = strtolower($table->name);
+            }
+        }
+    }
+
+    return $table_names;
+}
+
+/**
+ * Returns list of all directories where we expect install.xml files
+ * @return array of paths
+ */
+function get_db_directories() {
+    global $CFG;
+
+    $dbdirs = array();
+
+/// First, the main one (lib/db)
+    $dbdirs[] = $CFG->libdir.'/db';
+
+/// Now, activity modules (mod/xxx/db)
+    if ($plugins = get_list_of_plugins('mod')) {
+        foreach ($plugins as $plugin) {
+            $dbdirs[] = $CFG->dirroot.'/mod/'.$plugin.'/db';
+        }
+    }
+
+/// Now, assignment submodules (mod/assignment/type/xxx/db)
+    if ($plugins = get_list_of_plugins('mod/assignment/type')) {
+        foreach ($plugins as $plugin) {
+            $dbdirs[] = $CFG->dirroot.'/mod/assignment/type/'.$plugin.'/db';
+        }
+    }
+
+/// Now, question types (question/type/xxx/db)
+    if ($plugins = get_list_of_plugins('question/type')) {
+        foreach ($plugins as $plugin) {
+            $dbdirs[] = $CFG->dirroot.'/question/type/'.$plugin.'/db';
+        }
+    }
+
+/// Now, backup/restore stuff (backup/db)
+    $dbdirs[] = $CFG->dirroot.'/backup/db';
+
+/// Now, block system stuff (blocks/db)
+    $dbdirs[] = $CFG->dirroot.'/blocks/db';
+
+/// Now, blocks (blocks/xxx/db)
+    if ($plugins = get_list_of_plugins('blocks', 'db')) {
+        foreach ($plugins as $plugin) {
+            $dbdirs[] = $CFG->dirroot.'/blocks/'.$plugin.'/db';
+        }
+    }
+
+/// Now, course formats (course/format/xxx/db)
+    if ($plugins = get_list_of_plugins('course/format', 'db')) {
+        foreach ($plugins as $plugin) {
+            $dbdirs[] = $CFG->dirroot.'/course/format/'.$plugin.'/db';
+        }
+    }
+
+/// Now, enrolment plugins (enrol/xxx/db)
+    if ($plugins = get_list_of_plugins('enrol', 'db')) {
+        foreach ($plugins as $plugin) {
+            $dbdirs[] = $CFG->dirroot.'/enrol/'.$plugin.'/db';
+        }
+    }
+
+/// Local database changes, if the local folder exists.
+    if (file_exists($CFG->dirroot . '/local')) {
+        $dbdirs[] = $CFG->dirroot.'/local/db';
+    }
+
+    return $dbdirs;
+}
+
+/**
  * This function will create the table passed as argument with all its
  * fields/keys/indexes/sequences, everything based in the XMLDB object
  *
Index: admin/blocks.php
===================================================================
RCS file: /cvsroot/moodle/moodle/admin/blocks.php,v
retrieving revision 1.40.4.4
diff -u -r1.40.4.4 blocks.php
--- admin/blocks.php	19 Dec 2007 17:38:39 -0000	1.40.4.4
+++ admin/blocks.php	3 Jan 2008 10:18:22 -0000
@@ -100,25 +100,9 @@
                 notify("Error occurred while deleting the $strblockname record from blocks table");
             }
 
-            // Then the tables themselves
-            if ($tables = $db->Metatables()) {
-                $prefix = $CFG->prefix.$block->name;
-                $prefix2 = $CFG->prefix.'block_'.$block->name;
-                foreach ($tables as $table) {
-                    if (strpos($table, $prefix) === 0 || strpos($table, $prefix2) === 0) {
-                    /// If the match has been due to the 1st condition, debug to developers
-                        if (strpos($table, $prefix) === 0) {
-                            debugging('This block has some wrongly named tables. See Moodle Docs coding guidelines (and MDL-6786)', DEBUG_DEVELOPER);
-                        }
-                    /// Strip prefix from $table
-                        $table = preg_replace("/^{$CFG->prefix}/", '', $table);
-                        $xmldb_table = new XMLDBTable($table);
-                        if (!drop_table($xmldb_table, true, false)) {
-                            notify("ERROR: while trying to drop table $table");
-                        }
-                    }
-                }
-            }
+            drop_plugin_tables($block->name, "$CFG->dirroot/blocks/$block->name/db/install.xml", false); // old obsoleted table names
+            drop_plugin_tables('block_'.$block->name, "$CFG->dirroot/blocks/$block->name/db/install.xml", false);
+
             // Delete the capabilities that were defined by this block
             capabilities_cleanup('block/'.$block->name);
 
Index: admin/modules.php
===================================================================
RCS file: /cvsroot/moodle/moodle/admin/modules.php,v
retrieving revision 1.44.2.2
diff -u -r1.44.2.2 modules.php
--- admin/modules.php	19 Dec 2007 17:38:40 -0000	1.44.2.2
+++ admin/modules.php	3 Jan 2008 10:18:22 -0000
@@ -5,6 +5,7 @@
     require_once('../course/lib.php');
     require_once($CFG->libdir.'/adminlib.php');
     require_once($CFG->libdir.'/tablelib.php');
+    require_once($CFG->libdir.'/ddllib.php');
 
     // defines
     define('MODULE_TABLE','module_administration_table');
@@ -139,17 +140,8 @@
             }
 
             // Then the tables themselves
+            drop_plugin_tables($module->name, "$CFG->dirroot/mod/$module->name/db/install.xml", false);
 
-            if ($tables = $db->Metatables()) {
-                $prefix = $CFG->prefix.$module->name;
-                foreach ($tables as $table) {
-                    if (strpos($table, $prefix) === 0) {
-                        if (!execute_sql("DROP TABLE $table", false)) {
-                            notify("ERROR: while trying to drop table $table");
-                        }
-                    }
-                }
-            }
             // Delete the capabilities that were defined by this module
             capabilities_cleanup('mod/'.$module->name);
 

