Index: admin/cliupgrade.php
===================================================================
RCS file: /cvsroot/moodle/moodle/admin/cliupgrade.php,v
retrieving revision 1.23
diff -u -r1.23 cliupgrade.php
--- admin/cliupgrade.php 22 Jun 2008 22:53:41 -0000 1.23
+++ admin/cliupgrade.php 6 Jul 2008 19:50:25 -0000
@@ -599,7 +599,8 @@
$str .= "\r\n";
$database = $databases[$CONFFILE['dbtype']];
- $dbconfig = $database->export_dbconfig($CONFFILE['dbhost'], $CONFFILE['dbuser'], $CONFFILE['dbpass'], $CONFFILE['dbname'], false, $CONFFILE['prefix']);
+ $database->store_settings($CONFFILE['dbhost'], $CONFFILE['dbuser'], $CONFFILE['dbpass'], $CONFFILE['dbname'], false, $CONFFILE['prefix']);
+ $dbconfig = $database->export_dbconfig();
foreach ($dbconfig as $key=>$value) {
$key = str_pad($key, 9);
Index: admin/settings/misc.php
===================================================================
RCS file: /cvsroot/moodle/moodle/admin/settings/misc.php,v
retrieving revision 1.19
diff -u -r1.19 misc.php
--- admin/settings/misc.php 25 May 2008 11:37:45 -0000 1.19
+++ admin/settings/misc.php 6 Jul 2008 15:34:55 -0000
@@ -17,6 +17,8 @@
// XMLDB editor
$ADMIN->add('misc', new admin_externalpage('xmldbeditor', get_string('xmldbeditor'), "$CFG->wwwroot/$CFG->admin/xmldb/"));
+ // Database mover tool
+ $ADMIN->add('misc', new admin_externalpage('dbmover', get_string('dbmover'), "$CFG->wwwroot/$CFG->admin/dbmover/"));
// hidden scripts linked from elsewhere
Index: install.php
===================================================================
RCS file: /cvsroot/moodle/moodle/install.php,v
retrieving revision 1.105
diff -u -r1.105 install.php
--- install.php 22 Jun 2008 22:53:40 -0000 1.105
+++ install.php 6 Jul 2008 19:50:19 -0000
@@ -154,6 +154,7 @@
require_once($CFG->libdir.'/environmentlib.php');
require_once($CFG->libdir.'/xmlize.php');
require_once($CFG->libdir.'/componentlib.class.php');
+require_once($CFG->libdir.'/dml/moodle_database.php');
require_once($CFG->dirroot.'/version.php');
/// Set version and release
@@ -161,22 +162,7 @@
$INSTALL['release'] = $release;
/// list all supported drivers - unsupported must be installed manually ;-)
-$supported = array (
- 'mysqli_adodb',
- 'mysql_adodb',
- 'postgres7_adodb',
- 'mssql_n_adodb',
- 'mssql_adodb',
- 'odbc_mssql_adodb',
- 'oci8po_adodb',
- 'sqlite3_pdo',
-);
-$databases = array ();
-foreach($supported as $driver) {
- $classname = $driver.'_moodle_database';
- require_once ("$CFG->libdir/dml/$classname.php");
- $databases[$driver] = new $classname ();
-}
+$databases =& moodle_database::get_all_drivers();
/// guess the www root
if ($INSTALL['wwwroot'] == '') {
@@ -461,7 +447,8 @@
$str .= "\r\n";
$DB = $databases[$INSTALL['dbtype']];
- $dbconfig = $DB->export_dbconfig($INSTALL['dbhost'], $INSTALL['dbuser'], $INSTALL['dbpass'], $INSTALL['dbname'], false, $INSTALL['prefix']);
+ $DB->store_settings($INSTALL['dbhost'], $INSTALL['dbuser'], $INSTALL['dbpass'], $INSTALL['dbname'], false, $INSTALL['prefix']);
+ $dbconfig = $DB->export_dbconfig();
foreach ($dbconfig as $key=>$value) {
$key = str_pad($key, 9);
Index: lang/en_utf8/moodle.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lang/en_utf8/moodle.php,v
retrieving revision 1.185
diff -u -r1.185 moodle.php
--- lang/en_utf8/moodle.php 28 May 2008 03:13:11 -0000 1.185
+++ lang/en_utf8/moodle.php 8 Jul 2008 07:56:16 -0000
@@ -356,6 +356,7 @@
$string['datemostrecentlast'] = 'Date - most recent last';
$string['day'] = 'day';
$string['days'] = 'days';
+$string['dbmover'] = 'Database mover';
$string['decodinginternallinks'] = 'Decoding internal links';
$string['default'] = 'Default';
$string['defaultcoursefullname'] = 'Course Fullname 101';
@@ -508,7 +509,7 @@
$a->admin';
$string['emailpasswordconfirmationsubject'] = '$a: Change password confirmation';
$string['emailpasswordconfirmmaybesent'] = '
If you supplied a correct username or email address then an email should have been sent to you.
- It contains easy instructions to confirm and complete this password change.
+
It contains easy instructions to confirm and complete this password change.
If you continue to have difficulty, please contact the site administrator.
';
$string['emailpasswordconfirmsent'] = 'An email should have been sent to your address at $a.
It contains easy instructions to confirm and complete this password change.
Index: lib/ddl/database_manager.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/ddl/database_manager.php,v
retrieving revision 1.10
diff -u -r1.10 database_manager.php
--- lib/ddl/database_manager.php 15 Jun 2008 10:32:52 -0000 1.10
+++ lib/ddl/database_manager.php 6 Jul 2008 23:52:24 -0000
@@ -91,7 +91,7 @@
$result = $this->mdb->change_database_structure($sql);
if ($feedback and !$result) {
- notify('' . get_string('error') . '');
+ notify('' . get_string('error') . ' ' . $this->mdb->get_last_error() . '');
}
return $result;
@@ -425,11 +425,11 @@
}
/**
- * This function will load one entire XMLDB file, generating all the needed
- * SQL statements, specific for each RDBMS ($CFG->dbtype) and, finally, it
- * will execute all those statements against the DB.
+ * This function will load one entire XMLDB file and call install_from_xmldb_structure.
*
* @param $file full path to the XML file to be used
+ * @param boolean $continue to specify if must continue on error (true) or stop (false)
+ * @param boolean $feedback to specify to show status info (true) or not (false)
* @return boolean (true on success, false on error)
*/
public function install_from_xmldb_file($file, $continue=true, $feedback=true) {
@@ -450,8 +450,19 @@
return false;
}
- $xmldb_structure = $xmldb_file->getStructure();
+ return $this->install_from_xmldb_structure($xmldb_file->getStructure(), $continue, $feedback);
+ }
+ /**
+ * This function will generate all the needed SQL statements, specific for each
+ * RDBMS ($CFG->dbtype) and, finally, it will execute all those statements against the DB.
+ *
+ * @param object $structure xmldb_structure object
+ * @param boolean $continue to specify if must continue on error (true) or stop (false)
+ * @param boolean $feedback to specify to show status info (true) or not (false)
+ * @return boolean (true on success, false on error)
+ */
+ public function install_from_xmldb_structure($xmldb_structure, $continue=true, $feedback=true) {
/// Do this function silenty (to avoid output in install/upgrade process)
$olddbdebug = $this->mdb->get_debug();
$this->mdb->set_debug(false);
@@ -461,9 +472,7 @@
}
$this->mdb->set_debug($olddbdebug);
-
$result = $this->execute_sql_arr($sqlarr, $continue, $feedback);
-
return $result;
}
@@ -1152,6 +1161,14 @@
return $this->execute_sql_arr($sqlarr, $continue, $feedback);
}
+
+ /*
+ * Returns the SQL generator managed by this object.
+ * @return object SQL generator instance
+ */
+ public function get_generator() {
+ return $this->generator;
+ }
}
?>
Index: lib/ddl/sqlite_sql_generator.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/ddl/sqlite_sql_generator.php,v
retrieving revision 1.1
diff -u -r1.1 sqlite_sql_generator.php
--- lib/ddl/sqlite_sql_generator.php 22 Jun 2008 21:35:07 -0000 1.1
+++ lib/ddl/sqlite_sql_generator.php 29 Jun 2008 21:18:55 -0000
@@ -49,7 +49,7 @@
public $sequence_only = true; //To avoid to output the rest of the field specs, leaving only the name and the sequence_name publiciable
public $sequence_extra_code = false; //Does the generator need to add extra code to generate the sequence fields
- public $sequence_name = 'INTEGER PRIMARY KEY AUTOINCREMENT'; //Particular name for inline sequences in this generator
+ public $sequence_name = 'INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL'; //Particular name for inline sequences in this generator
public $unsigned_allowed = false; // To define in the generator must handle unsigned information
public $enum_extra_code = false; //Does the generator need to add extra code to generate code for the enums in the table
Index: lib/dml/database_column_info.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/dml/database_column_info.php,v
retrieving revision 1.3
diff -u -r1.3 database_column_info.php
--- lib/dml/database_column_info.php 12 Jun 2008 15:18:11 -0000 1.3
+++ lib/dml/database_column_info.php 30 Jun 2008 06:51:14 -0000
@@ -119,9 +119,11 @@
$this->has_default = false;
$this->default_value = null;
$this->unique = true;
+ break;
case 'C':
$this->auto_increment = false;
$this->binary = false;
+ break;
}
}
}
Index: lib/dml/moodle_database.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/dml/moodle_database.php,v
retrieving revision 1.37
diff -u -r1.37 moodle_database.php
--- lib/dml/moodle_database.php 4 Jul 2008 12:05:04 -0000 1.37
+++ lib/dml/moodle_database.php 6 Jul 2008 19:48:32 -0000
@@ -122,12 +122,10 @@
/**
* Returns db related part of config.php
- * Note: can be used before connect()
+ * Note: can be used before connect() if store_settings is called to cache the connection parameters
* @return string
*/
- public function export_dbconfig($dbhost, $dbuser, $dbpass, $dbname, $dbpersist, $prefix, array $dboptions=null) {
- $this->store_settings($dbhost, $dbuser, $dbpass, $dbname, $dbpersist, $prefix, $dboptions);
-
+ public function export_dbconfig() {
$cfg = new stdClass();
$cfg->dbtype = $this->get_dbtype();
$cfg->dblibrary = $this->get_dblibrary();
@@ -168,7 +166,7 @@
* @param array $dboptions driver specific options
* @return void
*/
- protected function store_settings($dbhost, $dbuser, $dbpass, $dbname, $dbpersist, $prefix, array $dboptions=null) {
+ public function store_settings($dbhost, $dbuser, $dbpass, $dbname, $dbpersist, $prefix, array $dboptions=null) {
$this->dbhost = $dbhost;
$this->dbuser = $dbuser;
$this->dbpass = $dbpass;
@@ -1489,4 +1487,48 @@
public function perf_get_queries() {
return $this->writes + $this->reads;
}
+
+ /*
+ * Return an array with names of supported database drivers.
+ * @return array $arr array with supported driver names
+ */
+ public static function get_supported_drivers() {
+ return array (
+ 'mysqli_adodb',
+ 'mysql_adodb',
+ 'postgres7_adodb',
+ 'mssql_n_adodb',
+ 'mssql_adodb',
+ 'odbc_mssql_adodb',
+ 'oci8po_adodb',
+ 'sqlite3_pdo',
+ );
+ }
+
+ /*
+ * Returns a moodle_database object for the specified database driver.
+ * @param $external true is this is not the moodle default database
+ * @return object $obj moodle_database object
+ */
+ public static function get_driver($driver, $external = false) {
+ global $CFG;
+ $classname = $driver.'_moodle_database';
+ require_once ("$CFG->libdir/dml/$classname.php");
+ return new $classname ($external);
+ }
+
+ /*
+ * Returns an array with moodle_database objects for all supported database drivers,
+ * indexed by driver name.
+ * @param $external true is this is not the moodle default database
+ * @return array $arr array with moodle_database objects
+ */
+ public static function get_all_drivers($external = false) {
+ $databases = array ();
+ $supported =& moodle_database::get_supported_drivers();
+ foreach($supported as $driver) {
+ $databases[$driver] =& moodle_database::get_driver($driver, $external);
+ }
+ return $databases;
+ }
}
Index: lib/dml/pdo_moodle_database.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/dml/pdo_moodle_database.php,v
retrieving revision 1.7
diff -u -r1.7 pdo_moodle_database.php
--- lib/dml/pdo_moodle_database.php 22 Jun 2008 22:53:41 -0000 1.7
+++ lib/dml/pdo_moodle_database.php 6 Jul 2008 12:52:16 -0000
@@ -177,7 +177,18 @@
* @return bool success
*/
public function change_database_structure($sql) {
- return $this->execute($sql);
+ try {
+ $this->lastError = null;
+ if($this->debug) {
+ $this->debug_query($sql);
+ }
+ $this->pdb->exec($sql);
+ return true;
+ } catch (PDOException $ex) {
+ $this->lastError = $ex->getMessage();
+ $this->report_error($sql, null, $ex);
+ return false;
+ }
}
public function delete_records_select($table, $select, array $params=null) {
Index: lib/dml/postgres7_adodb_moodle_database.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/dml/postgres7_adodb_moodle_database.php,v
retrieving revision 1.15
diff -u -r1.15 postgres7_adodb_moodle_database.php
--- lib/dml/postgres7_adodb_moodle_database.php 22 Jun 2008 22:53:41 -0000 1.15
+++ lib/dml/postgres7_adodb_moodle_database.php 6 Jul 2008 19:50:58 -0000
@@ -73,8 +73,6 @@
* @return string
*/
public function export_dbconfig($dbhost, $dbuser, $dbpass, $dbname, $dbpersist, $prefix, array $dboptions=null) {
- $this->store_settings($dbhost, $dbuser, $dbpass, $dbname, $dbpersist, $prefix, $dboptions);
-
$cfg = new stdClass();
$cfg->dbtype = $this->get_dbtype();
$cfg->dblibrary = $this->get_dblibrary();
Index: lib/dml/sqlite3_pdo_moodle_database.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/dml/sqlite3_pdo_moodle_database.php,v
retrieving revision 1.2
diff -u -r1.2 sqlite3_pdo_moodle_database.php
--- lib/dml/sqlite3_pdo_moodle_database.php 22 Jun 2008 22:05:59 -0000 1.2
+++ lib/dml/sqlite3_pdo_moodle_database.php 30 Jun 2008 06:45:50 -0000
@@ -110,7 +110,7 @@
*/
public function get_tables() {
$tables = array();
- $sql = 'SELECT name FROM sqlite_master WHERE type="table"';
+ $sql = 'SELECT name FROM sqlite_master WHERE type="table" ORDER BY name';
if($this->debug) {
$this->debug_query($sql);
}
@@ -132,13 +132,14 @@
*/
public function get_indexes($table) {
$indexes = array();
- $sql = 'SELECT * FROM sqlite_master WHERE type="index" AND tbl_name="'. $this->prefix . $table . '"';
+ $sql = 'PRAGMA index_list('. $this->prefix . $table . ')';
if($this->debug) {
$this->debug_query($sql);
}
$rsindexes = $this->pdb->query($sql);
foreach($rsindexes as $index) {
- $index = strtolower($index['name']);
+ $unique = (boolean)$index['unique'];
+ $index = $index['name'];
$sql = 'PRAGMA index_info("' . $index . '")';
if($this->debug) {
$this->debug_query($sql);
@@ -149,6 +150,7 @@
$columns[] = strtolower($row['name']);
}
$index = strtolower($index);
+ $indexes[$index]['unique'] = $unique;
$indexes[$index]['columns'] = $columns;
}
return $indexes;
@@ -188,6 +190,9 @@
'primary_key' => (boolean)$row['pk'],
'has_default' => !is_null($row['dflt_value']),
'default_value' => $row['dflt_value'],
+ 'auto_increment' => false,
+ 'binary' => false,
+ //'unsigned' => false,
);
$type = explode('(', $row['type']);
$columninfo['type'] = strtolower($type[0]);
@@ -204,6 +209,7 @@
case 'int': // int integer
if($columninfo['primary_key'] && preg_match('/' . $columninfo['name'] . '\W*integer\W*primary\W*key\W*autoincrement/im', $createsql)) {
$columninfo['meta_type'] = 'R';
+ $columninfo['auto_increment'] = true;
} else {
$columninfo['meta_type'] = 'I';
}
@@ -225,11 +231,13 @@
case 'blo': // blob
case 'non': // none
$columninfo['meta_type'] = 'B';
+ $columninfo['binary'] = true;
break;
case 'boo': // boolean
case 'bit': // bit
case 'log': // logical
$columninfo['meta_type'] = 'L';
+ $columninfo['max_length'] = 1;
break;
case 'tim': // timestamp
$columninfo['meta_type'] = 'T';
@@ -238,7 +246,6 @@
$columninfo['meta_type'] = 'D';
break;
}
-
$columns[$columninfo['name']] = new database_column_info($columninfo);
}
--- admin/dbmover/dbmover_form.php
+++ admin/dbmover/dbmover_form.php
@@ -0,0 +1,67 @@
+libdir.'/formslib.php');
+require_once($CFG->libdir.'/dml/moodle_database.php');
+
+class dbmover_form extends moodleform {
+
+ function definition() {
+ global $CFG;
+ $mform = $this->_form;
+
+ $drivers =& moodle_database::get_all_drivers();
+ foreach($drivers as $key => $driver) {
+ $drivers[$key] = $driver->get_name();
+ }
+
+ $mform->addElement('header', 'database', get_string('destinationdb', 'dbmover'));
+
+ $obj = $mform->addElement('select', 'dbtype', get_string('dbtype', 'install'), $drivers);
+ $obj->setValue($CFG->dbtype . '_' .$CFG->dblibrary);
+
+ $obj = $mform->addElement('text', 'dbhost', get_string('dbhost', 'install'));
+ $obj->setValue($CFG->dbhost);
+ $mform->setType('dbhost', PARAM_RAW);
+
+ $obj = $mform->addElement('text', 'dbname', get_string('database','install'));
+ $obj->setValue($CFG->dbname);
+ $mform->setType('dbname', PARAM_RAW);
+
+ $obj = $mform->addElement('text', 'dbuser', get_string('user'));
+ $obj->setValue($CFG->dbuser);
+ $mform->setType('dbuser', PARAM_RAW);
+
+ $obj = $mform->addElement('passwordunmask', 'dbpass', get_string('password'));
+ $obj->setValue($CFG->dbpass);
+ $mform->setType('dbpass', PARAM_RAW);
+
+ $obj = $mform->addElement('text', 'prefix', get_string('dbprefix', 'install'));
+ $obj->setValue($CFG->prefix);
+ $mform->setType('prefix', PARAM_RAW);
+
+ $mform->addElement('header', 'data', get_string('datatransfer', 'dbmover'));
+ // visible elements
+ $obj = $mform->addElement('radio', 'datasource', get_string('datasource', 'dbmover'), get_string('dbdataexists', 'dbmover'), 0);
+
+ $obj = array();
+ $obj[] = $mform->createElement('radio', 'datasource', '', get_string('dbcopywithfile', 'dbmover'), 1);
+ $obj[] = $mform->createElement('checkbox', 'savefile', '', get_string('savefile', 'dbmover'));
+ $obj[] = $mform->createElement('checkbox', 'downloadfile', '', get_string('downloadfile', 'dbmover'));
+ $obj = $mform->addElement('group', 'grp1', '', $obj, null, false);
+
+ $obj = $mform->addElement('radio', 'datasource', '', get_string('dbcopyonthefly', 'dbmover'), 2);
+ $obj = $mform->addElement('radio', 'datasource', '', get_string('dbdatafile', 'dbmover'), 3);
+ $mform->setType('datasource', PARAM_INT);
+
+ $obj = $mform->addElement('file', 'datafile', get_string('file'), 'size="40"');
+ $mform->addRule('file', get_string('required'), 'required', null, 'client');
+
+ $this->add_action_buttons(false, get_string('dbmove', 'dbmover'));
+ }
+
+ public function get_upload_filepath($elname) {
+ return @$this->_upload_manager->files[$elname]['tmp_name'];
+ }
+
+}
+?>
--- admin/dbmover/dbmoverlib.php
+++ admin/dbmover/dbmoverlib.php
@@ -0,0 +1,134 @@
+dirroot . '/config.php');
+ $file_put_contents($CFG->dirroot . '/config-old.php', $config);
+ $dbconfig = $database->export_dbconfig();
+
+ foreach ($dbconfig as $key=>$value) {
+ $newvalue = '$CFG->'. str_pad($key, 9) . ' = ' . var_export($value, true) . ';';
+ $config = preg_replace('/\\$CFG->'. $key . '\s*=.*;/x', $newvalue, $config, -1, $count);
+ if(!$count) {
+ $config = str_replace('$CFG->prefix', $newvalue . "\r\n" . '$CFG->prefix', $config);
+ }
+ }
+ file_put_contents($CFG->dirroot . '/config.php', $config);
+ }
+ return true;
+}
+
+function dbmover_get_data($tablename) {
+ global $DB;
+ $statement =& new xmldb_statement($tablename . '_data');
+ $statement->setType(XMLDB_STATEMENT_INSERT);
+ $statement->setTable($tablename);
+ $rs = $DB->get_recordset_sql('SELECT * FROM {' . $tablename . '}');
+ foreach($rs as $row) {
+ $row = (array)$row;
+ foreach($row as $k => $v) {
+ $row[$k] = "'" . htmlspecialchars($v, ENT_QUOTES) . "'";
+ }
+ $text = '(' . implode(',', array_keys($row)) . ') VALUES (' . implode(',', $row) . ')';
+ $statement->addSentence($text);
+ }
+ return $statement;
+}
+
+
+function dbmover_transfer_onthefly($database) {
+ $generator = $database->get_manager()->get_generator();
+
+ $dbdirs = get_db_directories();
+ foreach ($dbdirs as $dbdir) {
+ $xmldb_file = new xmldb_file($dbdir.'/install.xml');
+ if (!($xmldb_file->fileExists() && $xmldb_file->loadXMLStructure())) {
+ continue;
+ }
+ $structure =& $xmldb_file->getStructure();
+ $tables =& $structure->getTables();
+
+ foreach($tables as $table) {
+ $sqls = $generator->getCreateTableSQL($table);
+ foreach($sqls as $sql) {
+ $database->change_database_structure($sql);
+ }
+
+ $sqls = $generator->getExecuteStatementSQL(dbmover_get_data($table->getName()));
+ foreach($sqls as $sql) {
+ $database->change_database_structure($sql);
+ }
+ }
+ }
+}
+
+function dbmover_get_structure() {
+ $export =& new xmldb_structure('export');
+ $dbdirs = get_db_directories();
+ foreach ($dbdirs as $dbdir) {
+ $xmldb_file = new xmldb_file($dbdir.'/install.xml');
+ if (!($xmldb_file->fileExists() && $xmldb_file->loadXMLStructure())) {
+ continue;
+ }
+ $structure =& $xmldb_file->getStructure();
+ $tables =& $structure->getTables();
+
+ foreach($tables as $table) {
+ $table->setPrevious(null);
+ $table->setNext(null);
+ $export->addTable($table);
+ $export->addStatement(dbmover_get_data($table->getName()));
+ }
+ }
+ return $export;
+}
+
+function dbmover_read_structure($file) {
+ $xmldb_file = new xmldb_file();
+ if (!($xmldb_file->fileExists() && $xmldb_file->loadXMLStructure())) {
+ return null;
+ }
+ return $xmldb_file->getStructure();
+}
+
+function dbmover_database_connect($data, $createonfail = true) {
+ global $CFG, $DB;
+ if($CFG->dbtype . '_' .$CFG->dblibrary == $data->dbtype && $CFG->dbhost == $data->dbhost &&
+ $CFG->dbname == $data->dbname && $CFG->dbuser == $data->dbuser && $CFG->dbpass == $data->dbpass) {
+ return $DB;
+ }
+ $database = moodle_database::get_all_drivers();
+ $database = $database[$data->dbtype];
+
+ if(!$database->connect($data->dbhost, $data->dbuser, $data->dbpass, $data->dbname, false, $data->prefix) &&
+ (!$createonfail ||
+ !($database->create_database($data->dbhost, $data->dbuser, $data->dbpass, $data->dbname) &&
+ $database->connect($data->dbhost, $data->dbuser, $data->dbpass, $data->dbname, false, $data->prefix)))) {
+ return null;
+ }
+ return $database;
+}
+
+function dbmover_save_structure($structure, $path = null) {
+ global $CFG;
+ if(is_null($path)) {
+ $path = $CFG->dataroot . '/database-' . $structure->getVersion() . '.xml';
+ }
+ $structure->path = $path;
+ $structure->calculateHash(true);
+ return file_put_contents($path, $structure->xmlOutput());
+}
+
+function dbmover_print_structure($structure, $httpheader = 'Content-Type: application/xhtml+xml') {
+ if($httpheader) {
+ header($httpheader);
+ }
+ echo $structure->xmlOutput();
+}
+
+function dbmover_transfer_structure($structure, $database) {
+ // TODO: clean destination database before sending new data
+ $manager =& $database->get_manager();
+ $manager->install_from_xmldb_structure($structure);
+}
--- admin/dbmover/index.php
+++ admin/dbmover/index.php
@@ -0,0 +1,97 @@
+libdir.'/adminlib.php');
+
+ require_login();
+ require_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM));
+
+ require_once($CFG->dirroot.'/admin/dbmover/dbmoverlib.php');
+ require_once($CFG->dirroot.'/admin/dbmover/dbmover_form.php');
+
+ admin_externalpage_setup('dbmover');
+ //create form
+ $form = new dbmover_form();
+ global $DB;
+ if ($data = $form->get_data()) {
+ @set_time_limit(0);
+ if(!$database = dbmover_database_connect($data, $data->datasource != 0)) {
+ $error = get_string('dbnotsetup', 'debug');
+ } else {
+ switch($data->datasource) {
+ default:
+ case 0:
+ if($DB != $database) {
+ dbmover_rewrite_config($database);
+ }
+ break;
+ case 1:
+ @raise_memory_limit('128M');
+ $structure = dbmover_get_structure();
+ if(@$data->savefile) {
+ dbmover_save_structure($structure);
+ }
+ if($DB != $database) {
+ dbmover_transfer_structure($structure, $database);
+ dbmover_rewrite_config($database);
+ }
+ if(@$data->downloadfile) {
+ dbmover_print_structure($structure);
+ exit();
+ }
+ break;
+ case 2:
+ if($DB != $database) {
+ dbmover_transfer_onthefly($database);
+ dbmover_rewrite_config($database);
+ }
+ break;
+ case 3:
+ @raise_memory_limit('128M');
+ $structure = dbmover_read_structure($form->get_upload_filepath('file'));
+ if($structure) {
+ dbmover_transfer_structure($structure, $database);
+ dbmover_rewrite_config($database);
+ } else {
+ $error = get_string('invalidxmldbstructure', 'dbmover');
+ }
+ break;
+ }
+ }
+ if(!@$error) {
+ redirect($CFG->wwwroot.'/admin/dbmover', get_string('transfersuccess', 'dbmover'));
+ }
+ }
+
+ admin_externalpage_print_header();
+ if(@$error) {
+ print_error($error);
+ }
+ $form->display();
+ admin_externalpage_print_footer();
--- lang/en_utf8/dbmover.php
+++ lang/en_utf8/dbmover.php
@@ -0,0 +1,14 @@
+