Skip to content

Commit

Permalink
MDL-34441 improve error handling when migrating databases
Browse files Browse the repository at this point in the history
  • Loading branch information
skodak committed Jul 22, 2012
1 parent a197c41 commit 3ce26ee
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 40 deletions.
2 changes: 1 addition & 1 deletion admin/tool/dbtransfer/database_export_form.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

defined('MOODLE_INTERNAL') || die;

require_once $CFG->libdir.'/formslib.php';
require_once($CFG->libdir.'/formslib.php');


/**
Expand Down
60 changes: 39 additions & 21 deletions admin/tool/dbtransfer/database_transfer_form.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,51 +24,69 @@

defined('MOODLE_INTERNAL') || die;

require_once $CFG->libdir.'/formslib.php';
require_once($CFG->libdir.'/formslib.php');
require_once(__DIR__.'/locallib.php');


/**
* Definition of db transfer settings form.
*/
class database_transfer_form extends moodleform {

function definition() {
/**
* Define transfer form.
*/
protected function definition() {
global $CFG;

$mform = $this->_form;

$mform->addElement('header', 'database', get_string('dbtransfer', 'tool_dbtransfer'));

$supported = array (
'mysqli/native',
'pgsql/native',
'mssql/native',
'oci/native',
'sqlsrv/native',
);
$drivers = array();
foreach($supported as $driver) {
list($dbtype, $dblibrary) = explode('/', $driver);
$targetdb = moodle_database::get_driver_instance($dbtype, $dblibrary);
if ($targetdb->driver_installed() !== true) {
continue;
}
$drivers[$driver] = $driver;
}
$drivers = tool_dbtransfer_get_drivers();
$drivers = array_reverse($drivers, true);
$drivers[''] = get_string('choosedots');
$drivers = array_reverse($drivers, true);

$mform->addElement('select', 'driver', get_string('dbtype', 'install'), $drivers);
$mform->addElement('text', 'dbhost', get_string('dbhost', 'install'));
$mform->addElement('text', 'dbname', get_string('database', 'install'));
$mform->addElement('text', 'dbuser', get_string('user'));
$mform->addElement('text', 'dbpass', get_string('password'));
$mform->addElement('passwordunmask', 'dbpass', get_string('password'));
$mform->addElement('text', 'prefix', get_string('dbprefix', 'install'));
$mform->addElement('text', 'dbport', get_string('dbport', 'install'));
$mform->addElement('text', 'dbsocket', get_string('databasesocket', 'install'));
if ($CFG->ostype !== 'WINDOWS') {
$mform->addElement('text', 'dbsocket', get_string('databasesocket', 'install'));
} else {
$mform->addElement('hidden', 'dbsocket');
}

$mform->addRule('driver', get_string('required'), 'required', null);
$mform->addRule('dbhost', get_string('required'), 'required', null);
$mform->addRule('dbname', get_string('required'), 'required', null);
$mform->addRule('dbuser', get_string('required'), 'required', null);
$mform->addRule('dbpass', get_string('required'), 'required', null);
$mform->addRule('prefix', get_string('required'), 'required', null);
if (!isset($drivers['mysqli/native'])) {
$mform->addRule('prefix', get_string('required'), 'required', null);
}

$this->add_action_buttons(false, get_string('transferdata', 'tool_dbtransfer'));
}

/**
* Validate prefix is present for non-mysql drivers.
* @param array $data
* @param array $files
* @return array
*/
public function validation($data, $files) {
$errors = parent::validation($data, $files);
if ($data['driver'] !== 'mysqli/native') {
// This is a bloody hack, let's pretend we do not need to look at db family...
if ($data['prefix'] === '') {
$errors['prefix'] = get_string('required');
}
}
return $errors;
}
}
45 changes: 27 additions & 18 deletions admin/tool/dbtransfer/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

// Create the form.
$form = new database_transfer_form();
$problem = '';

// If we have valid input.
if ($data = $form->get_data()) {
Expand All @@ -46,33 +47,41 @@
if ($data->dbsocket) {
$dboptions['dbsocket'] = $data->dbsocket;
}
if (!$targetdb->connect($data->dbhost, $data->dbuser, $data->dbpass, $data->dbname, $data->prefix, $dboptions)) {
throw new dbtransfer_exception('notargetconectexception', null, "$CFG->wwwroot/$CFG->admin/tool/dbtransfer/");
}
if ($targetdb->get_tables()) {
throw new dbtransfer_exception('targetdatabasenotempty', null, "$CFG->wwwroot/$CFG->admin/tool/dbtransfer/");
try {
$targetdb->connect($data->dbhost, $data->dbuser, $data->dbpass, $data->dbname, $data->prefix, $dboptions);
if ($targetdb->get_tables()) {
$problem .= get_string('targetdatabasenotempty', 'tool_dbtransfer');
}
} catch (moodle_exception $e) {
$problem .= html_writer::tag('h3', get_string('notargetconectexception', 'tool_dbtransfer'));
$problem .= $e->getMessage().'<br />'.$e->debuginfo;
}

// Start output.
echo $OUTPUT->header();
$data->dbtype = $dbtype;
echo $OUTPUT->heading(get_string('transferringdbto', 'tool_dbtransfer', $data));
if ($problem === '') {
// Start output.
echo $OUTPUT->header();
$data->dbtype = $dbtype;
echo $OUTPUT->heading(get_string('transferringdbto', 'tool_dbtransfer', $data));

// Do the transfer.
$feedback = new html_list_progress_trace();
tool_dbtransfer_transfer_database($DB, $targetdb, $feedback);
$feedback->finished();
// Do the transfer.
$feedback = new html_list_progress_trace();
tool_dbtransfer_transfer_database($DB, $targetdb, $feedback);
$feedback->finished();

// Finish up.
echo $OUTPUT->notification(get_string('success'), 'notifysuccess');
echo $OUTPUT->continue_button("$CFG->wwwroot/$CFG->admin/");
echo $OUTPUT->footer();
die;
// Finish up.
echo $OUTPUT->notification(get_string('success'), 'notifysuccess');
echo $OUTPUT->continue_button("$CFG->wwwroot/$CFG->admin/");
echo $OUTPUT->footer();
die;
}
}

// Otherwise display the settings form.
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('transferdbtoserver', 'tool_dbtransfer'));
echo '<p>', get_string('transferdbintro', 'tool_dbtransfer'), "</p>\n\n";
$form->display();
if ($problem !== '') {
echo $OUTPUT->box($problem, 'generalbox error');
}
echo $OUTPUT->footer();
1 change: 1 addition & 0 deletions admin/tool/dbtransfer/lang/en/tool_dbtransfer.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
$string['exportdata'] = 'Export data';
$string['notargetconectexception'] = 'Can not connect target database, sorry.';
$string['pluginname'] = 'Database transfer';
$string['targetdatabasenotempty'] = 'Target database must not contain any tables with given prefix!';
$string['transferdata'] = 'Transfer data';
$string['transferdbintro'] = 'This script will transfer the entire contents of this database to another database server.';
$string['transferdbtoserver'] = 'Transfer this Moodle database to another server';
Expand Down
37 changes: 37 additions & 0 deletions admin/tool/dbtransfer/locallib.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,40 @@ function tool_dbtransfer_transfer_database(moodle_database $sourcedb, moodle_dat
$var = new database_mover($sourcedb, $targetdb, true, $feedback);
$var->export_database(null);
}

/**
* Returns list of fully working database drivers present in system.
* @return array
*/
function tool_dbtransfer_get_drivers() {
global $CFG;

$files = new RegexIterator(new DirectoryIterator("$CFG->libdir/dml"), '|^.*_moodle_database\.php$|');
$drivers = array();

foreach ($files as $file) {
$matches = null;
preg_match('|^([a-z0-9]+)_([a-z]+)_moodle_database\.php$|', $file->getFilename(), $matches);
if (!$matches) {
continue;
}
$dbtype = $matches[1];
$dblibrary = $matches[2];

if ($dbtype === 'sqlite3') {
// Ignored unfinished.
continue;
}

$targetdb = moodle_database::get_driver_instance($dbtype, $dblibrary, false);
if ($targetdb->driver_installed() !== true) {
continue;
}

$driver = $dbtype.'/'.$dblibrary;

$drivers[$driver] = $targetdb->get_name();
};

return $drivers;
}

0 comments on commit 3ce26ee

Please sign in to comment.