From f4caf0df5e75a5355269311b23b55c6cecdcc354 Mon Sep 17 00:00:00 2001 From: skodak Date: Mon, 25 Aug 2008 22:02:49 +0000 Subject: [PATCH] MDL-15669 Check db schema vs install.xml - code by Andrei Bautu, with minor changes only (more strict checking) --- lib/ddl/database_manager.php | 97 ++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/lib/ddl/database_manager.php b/lib/ddl/database_manager.php index e07b84ca8b..f95a240b95 100644 --- a/lib/ddl/database_manager.php +++ b/lib/ddl/database_manager.php @@ -906,6 +906,103 @@ if (!is_object($xmldb_key)) { $this->execute_sql_arr($sqlarr); } + + /** + * Reads the install.xml files for Moodle core and modules and returns an array of + * xmldb_structure object with xmldb_table from these files. + * @return xmldb_structure schema from install.xml files + */ + public function get_install_xml_schema() { + global $CFG; + + $schema = new xmldb_structure('export'); + $schema->setVersion($CFG->version); + $dbdirs = get_db_directories(); + foreach ($dbdirs as $dbdir) { + $xmldb_file = new xmldb_file($dbdir.'/install.xml'); + if (!$xmldb_file->fileExists() or !$xmldb_file->loadXMLStructure()) { + continue; + } + $structure = $xmldb_file->getStructure(); + $tables = $structure->getTables(); + foreach ($tables as $table) { + $table->setPrevious(null); + $table->setNext(null); + $schema->addTable($table); + } + } + return $schema; + } + + /** + * Checks the database schema against a schema specified by an xmldb_structure object + * @param xmldb_structure $schema export schema describing all known tables + * @return array keyed by table name with array of difference messages as values + */ + public function check_database_schema(xmldb_structure $schema) { + $errors = array(); + + $dbtables = $this->mdb->get_tables(); + $tables = $schema->getTables(); + + //TODO: maybe add several levels error/warning + + // make sure that current and schema tables match exactly + foreach ($tables as $table) { + $tablename = $table->getName(); + if (empty($dbtables[$tablename])) { + if (!isset($errors[$tablename])) { + $errors[$tablename] = array(); + } + $errors[$tablename][] = "Table $tablename is missing in database."; //TODO: localize + continue; + } + + // a) check for required fields + $dbfields = $this->mdb->get_columns($tablename, false); + $fields = $table->getFields(); + foreach ($fields as $field) { + $fieldname = $field->getName(); + if (empty($dbfields[$fieldname])) { + if (!isset($errors[$tablename])) { + $errors[$tablename] = array(); + } + $errors[$tablename][] = "Field $fieldname is missing in table $tablename."; //TODO: localize + } + unset($dbfields[$fieldname]); + } + + // b) check for extra fields (indicates unsupported hacks) - modify install.xml if you want the script to continue ;-) + foreach ($dbfields as $fieldname=>$info) { + if (!isset($errors[$tablename])) { + $errors[$tablename] = array(); + } + $errors[$tablename][] = "Field $fieldname is not expected in table $tablename."; //TODO: localize + } + unset($dbtables[$tablename]); + } + + // look for unsupported tables - local custom tables should be in /local/db/install.xml ;-) + // if there is no prefix, we can not say if tale is ours :-( + if ($this->generator->prefix !== '') { + foreach ($dbtables as $tablename=>$unused) { + if (strpos($tablename, 'pma_') === 0) { + // ignore phpmyadmin tables for now + continue; + } + if (strpos($tablename, 'test') === 0) { + // ignore broken results of unit tests + continue; + } + if (!isset($errors[$tablename])) { + $errors[$tablename] = array(); + } + $errors[$tablename][] = "Table $tablename is not expected."; //TODO: localize + } + } + + return $errors; + } } -- 2.39.5