dirroot/lib/ddllib.php")) {
// Moodle 1.8+
include_once "$CFG->dirroot/lib/ddllib.php";
}
function hotpot_update_to_v2_2() {
global $CFG;
$ok = true;
// remove the index on hotpot_questions.name
$table = 'hotpot_questions';
$field = 'name';
if (strtolower($CFG->dbfamily)=='postgres') {
$index = "{$CFG->prefix}{$table}_{$field}_idx";
} else {
$index = "{$table}_{$field}_idx";
}
hotpot_db_delete_index("{$CFG->prefix}$table", $index);
// add new hotpot_questions.md5key field (and index)
$table = 'hotpot_questions';
$field = 'md5key';
$ok = $ok && hotpot_db_update_field_type($table, '', $field, 'VARCHAR', 32, '', 'NOT NULL', '');
$ok = $ok && hotpot_db_add_index($table, $field);
// add new values hotpot_questions.md5key
$table = 'hotpot_questions';
if ($records = get_records($table)) {
foreach ($records as $record) {
$ok = $ok && set_field($table, 'md5key', md5($record->name), 'id', $record->id);
}
}
// remove the index on hotpot_strings.string
$table = 'hotpot_strings';
$field = 'string';
if (strtolower($CFG->dbfamily)=='postgres') {
$index = "{$CFG->prefix}{$table}_{$field}_idx";
} else {
$index = "{$table}_{$field}_idx";
}
hotpot_db_delete_index("{$CFG->prefix}$table", $index);
// add new hotpot_strings.md5key field (and index)
$table = 'hotpot_strings';
$field = 'md5key';
$ok = $ok && hotpot_db_update_field_type($table, '', $field, 'VARCHAR', 32, '', 'NOT NULL', '');
$ok = $ok && hotpot_db_add_index($table, $field);
// add new values hotpot_strings.md5key
$table = 'hotpot_strings';
if ($records = get_records($table)) {
foreach ($records as $record) {
$ok = $ok && set_field($table, 'md5key', md5($record->string), 'id', $record->id);
}
}
return $ok;
}
function hotpot_update_to_v2_1_21() {
global $CFG;
$ok = true;
if (strtolower($CFG->dbfamily)=='postgres') {
// ensure setting of default values on certain fields
// this was originally done in postgres7.php, but was found to be incompatible with PG7 :-(
$table="hotpot";
execute_sql("UPDATE {$CFG->prefix}$table SET studentfeedbackurl = '' WHERE studentfeedbackurl IS NULL");
$ok = $ok && hotpot_db_update_field_type($table, '', 'studentfeedbackurl', 'VARCHAR', 255, '', 'NOT NULL', '');
$ok = $ok && hotpot_db_update_field_type($table, '', 'studentfeedback', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 0);
$ok = $ok && hotpot_db_update_field_type($table, '', 'clickreporting', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 0);
$table="hotpot_attempts";
$ok = $ok && hotpot_db_update_field_type($table, '', 'score', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 0);
$ok = $ok && hotpot_db_update_field_type($table, '', 'penalties', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 0);
$ok = $ok && hotpot_db_update_field_type($table, '', 'status', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 1);
$table="hotpot_questions";
$ok = $ok && hotpot_db_update_field_type($table, '', 'type', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 0);
$table="hotpot_responses";
$ok = $ok && hotpot_db_update_field_type($table, '', 'score', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 0);
$ok = $ok && hotpot_db_update_field_type($table, '', 'weighting', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 0);
$ok = $ok && hotpot_db_update_field_type($table, '', 'correct', 'VARCHAR', 255, '', 'NOT NULL', '');
execute_sql("UPDATE {$CFG->prefix}$table SET wrong = '' WHERE wrong IS NULL");
$ok = $ok && hotpot_db_update_field_type($table, '', 'wrong', 'VARCHAR', 255, '', 'NOT NULL', '');
execute_sql("UPDATE {$CFG->prefix}$table SET ignored = '' WHERE ignored IS NULL");
$ok = $ok && hotpot_db_update_field_type($table, '', 'ignored', 'VARCHAR', 255, '', 'NOT NULL', '');
$ok = $ok && hotpot_db_update_field_type($table, '', 'hints', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 0);
$ok = $ok && hotpot_db_update_field_type($table, '', 'clues', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 0);
$ok = $ok && hotpot_db_update_field_type($table, '', 'checks', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 0);
$table="hotpot_strings";
$ok = $ok && hotpot_db_update_field_type($table, '', 'string', 'TEXT', '', '', 'NOT NULL', '');
}
return $ok;
}
function hotpot_update_to_v2_1_18() {
$ok = true;
// remove all orphan records (there shouldn't be any, but if there are they can mess up the utfdbmigrate)
$ok = $ok && hotpot_remove_orphans('hotpot_attempts', 'hotpot', 'hotpot');
$ok = $ok && hotpot_remove_orphans('hotpot_questions', 'hotpot', 'hotpot');
$ok = $ok && hotpot_remove_orphans('hotpot_responses', 'attempt', 'hotpot_attempts');
$ok = $ok && hotpot_remove_orphans('hotpot_responses', 'question', 'hotpot_questions');
$ok = $ok && hotpot_remove_orphans('hotpot_details', 'attempt', 'hotpot_attempts');
// allow negative weighting and scores
$ok = $ok && hotpot_denull_int_field('hotpot_responses', 'weighting', '6', false);
$ok = $ok && hotpot_denull_int_field('hotpot_responses', 'score', '6', false);
return $ok;
}
function hotpot_remove_orphans($secondarytable, $secondarykeyfield, $primarytable, $primarykeyfield='id') {
global $CFG,$db;
$ok = true;
// save and switch off SQL message echo
$debug = $db->debug;
$db->debug = false;
$records = get_records_sql("
SELECT
t2.$secondarykeyfield, t2.$secondarykeyfield
FROM
{$CFG->prefix}$secondarytable t2 LEFT JOIN {$CFG->prefix}$primarytable t1
ON (t2.$secondarykeyfield = t1.id)
WHERE
t1.$primarykeyfield IS NULL
");
// restore SQL message echo setting
$db->debug = $debug;
if ($records) {
$keys = implode(',', array_keys($records));
print "removing orphan record(s) from {$CFG->prefix}$secondarytable
";
$ok = $ok && execute_sql("DELETE FROM {$CFG->prefix}$secondarytable WHERE $secondarykeyfield IN ($keys)");
}
return $ok;
}
function hotpot_update_to_v2_1_17() {
global $CFG;
$ok = true;
// convert and disable null values on certain numeric fields
$ok = $ok && hotpot_denull_int_field('hotpot_attempts', 'starttime', '10');
$ok = $ok && hotpot_denull_int_field('hotpot_attempts', 'endtime', '10');
$ok = $ok && hotpot_denull_int_field('hotpot_attempts', 'score', '6');
$ok = $ok && hotpot_denull_int_field('hotpot_attempts', 'penalties', '6');
$ok = $ok && hotpot_denull_int_field('hotpot_attempts', 'timestart', '10');
$ok = $ok && hotpot_denull_int_field('hotpot_attempts', 'timefinish', '10');
$ok = $ok && hotpot_denull_int_field('hotpot_attempts', 'clickreportid', '10');
$ok = $ok && hotpot_denull_int_field('hotpot_questions', 'type', '4');
$ok = $ok && hotpot_denull_int_field('hotpot_questions', 'text', '10');
$ok = $ok && hotpot_denull_int_field('hotpot_responses', 'weighting', '6', false);
$ok = $ok && hotpot_denull_int_field('hotpot_responses', 'score', '6', false);
$ok = $ok && hotpot_denull_int_field('hotpot_responses', 'hints', '6');
$ok = $ok && hotpot_denull_int_field('hotpot_responses', 'clues', '6');
$ok = $ok && hotpot_denull_int_field('hotpot_responses', 'checks', '6');
return $ok;
}
function hotpot_denull_int_field($table, $field, $size, $unsigned=true) {
global $CFG;
$ok = true;
$ok = $ok && execute_sql("UPDATE {$CFG->prefix}$table SET $field=0 WHERE $field IS NULL", false);
if ($unsigned) {
$ok = $ok && execute_sql("UPDATE {$CFG->prefix}$table SET $field=0 WHERE $field<0", false);
}
$ok = $ok && hotpot_db_update_field_type($table, $field, $field, 'INTEGER', $size, $unsigned, 'NOT NULL', 0);
return $ok;
}
function hotpot_update_to_v2_1_16() {
global $CFG;
$ok = true;
// remove the questions name index
hotpot_db_delete_index("{$CFG->prefix}hotpot_questions", "hotpot_questions_name_idx");
hotpot_db_delete_index("{$CFG->prefix}hotpot_questions", "{$CFG->prefix}hotpot_questions_name_idx");
// make sure type of 'name' is a text field (not varchar 255)
$ok = $ok && hotpot_db_update_field_type('hotpot_questions', 'name', 'name', 'TEXT', '', '', 'NOT NULL', '');
if (strtolower($CFG->dbfamily)=='mysql') {
// set default values on certain VARCHAR(255) fields
$fields = array(
'hotpot' => 'studentfeedbackurl',
'hotpot_responses' => 'correct',
'hotpot_responses' => 'wrong',
'hotpot_responses' => 'ignored'
);
foreach ($fields as $table=>$field) {
execute_sql("UPDATE {$CFG->prefix}$table SET $field='' WHERE $field IS NULL");
$ok = $ok && hotpot_db_update_field_type($table, $field, $field, 'VARCHAR', 255, '', 'NOT NULL', '');
}
// remove $CFG->prefix from all index names
$ok = $ok && hotpot_index_remove_prefix('hotpot_attempts', 'hotpot');
$ok = $ok && hotpot_index_remove_prefix('hotpot_attempts', 'userid');
$ok = $ok && hotpot_index_remove_prefix('hotpot_details', 'attempt');
$ok = $ok && hotpot_index_remove_prefix('hotpot_questions', 'hotpot');
$ok = $ok && hotpot_index_remove_prefix('hotpot_responses', 'attempt');
$ok = $ok && hotpot_index_remove_prefix('hotpot_responses', 'question');
}
return $ok;
}
function hotpot_index_remove_prefix($table, $field) {
global $CFG;
hotpot_db_delete_index("{$CFG->prefix}$table", "{$CFG->prefix}{$table}_{$field}_idx");
hotpot_db_delete_index("{$CFG->prefix}$table", "{$table}_{$field}_idx");
return hotpot_db_add_index($table, $field);
}
function hotpot_update_to_v2_1_8() {
global $CFG;
$ok = true;
if (strtolower($CFG->dbfamily)=='postgres') {
// add, delete and rename certain fields and indexes
// that were not correctly setup by postgres7.sql
// hotpot
$table = 'hotpot';
if (hotpot_db_field_exists($table, 'microreporting')) {
$ok = $ok && hotpot_db_update_field_type($table, 'microreporting', 'clickreporting', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', '0');
}
}
return $ok;
}
function hotpot_update_to_v2_1_6() {
global $CFG;
$ok = true;
if (strtolower($CFG->dbfamily)=='postgres') {
// add, delete and rename certain fields and indexes
// that were not correctly setup by postgres7.sql
// hotpot
$table = 'hotpot';
if (hotpot_db_field_exists($table, 'studentfeedback') && !hotpot_db_field_exists($table, 'studentfeedbackurl')) {
$ok = $ok && hotpot_db_update_field_type($table, 'studentfeedback', 'studentfeedbackurl', 'VARCHAR', 255, '', 'NULL');
$ok = $ok && hotpot_db_update_field_type($table, '', 'studentfeedback', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', '0');
}
// hotpot_attempts
$table = 'hotpot_attempts';
$ok = $ok && hotpot_db_remove_field($table, 'groupid');
if (hotpot_db_field_exists($table, 'microreportid') && !hotpot_db_field_exists($table, 'clickreportid')) {
$ok = $ok && hotpot_db_update_field_type($table, 'microreportid', 'clickreportid', 'INTEGER', 10, 'UNSIGNED', 'NULL');
}
}
return $ok;
}
function hotpot_update_to_v2_1_2() {
global $CFG, $db;
$ok = true;
// save and switch off SQL message echo
$debug = $db->debug;
$db->debug = false;
// extract info about attempts by each user on each hotpot (cases where
// the user has only one attempt, or no "in progess" attempt are ignored)
$rs = $db->Execute("
SELECT userid, hotpot, COUNT(*), MIN(status)
FROM {$CFG->prefix}hotpot_attempts
GROUP BY userid, hotpot
HAVING COUNT(*)>1 AND MIN(status)=1
");
if ($rs && $rs->RecordCount()) {
$records = $rs->GetArray();
// start message to browser
print "adjusting status of ".count($records)." "in progress" attempts ... ";
// loop through records
foreach ($records as $record) {
// get all attempts by this user at this hotpot
$attempts = get_records_sql("
SELECT id, userid, hotpot, score, timestart, timefinish, status
FROM {$CFG->prefix}hotpot_attempts
WHERE userid = ".$record['userid']." AND hotpot=".$record['hotpot']."
ORDER BY timestart DESC, id DESC
");
unset($previous_timestart);
foreach ($attempts as $attempt) {
// if this attempt has a status of "in progress" and is not
// the most recent one in the group, set the status to "abandoned"
if ($attempt->status==1 && isset($previous_timestart)) {
$values = 'status=3';
if (empty($attempt->score)) {
$values .= ',score=0';
}
if (empty($attempt->timefinish)) {
$values .= ",timefinish=$previous_timestart";
}
execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET $values WHERE id=$attempt->id", false);
print ".";
hotpot_flush(300);
}
$previous_timestart = $attempt->timestart;
} // end foreach $attempts
} // end foreach $records
// finish message to browser
print $ok ? get_string('success') : 'failed';
print "
\n";
}
// restore SQL message echo setting
$db->debug = $debug;
return $ok;
}
function hotpot_update_to_v2_1() {
global $CFG, $db;
$ok = true;
// hotpot_questions: reduce size of "type" field to "4"
$ok = $ok && hotpot_db_update_field_type('hotpot_questions', 'type', 'type', 'INTEGER', 4, 'UNSIGNED', 'NULL');
// hotpot_questions: change type of "name" field to "text"
$ok = $ok && hotpot_db_update_field_type('hotpot_questions', 'name', 'name', 'TEXT', '', '', 'NOT NULL', '');
// hotpot_questions: nullify empty and non-numeric (shouldn't be any) values in "text" field
switch (strtolower($CFG->dbfamily)) {
case 'mysql' :
$NOT_REGEXP = 'NOT REGEXP';
break;
case 'postgres' :
$NOT_REGEXP = '!~';
break;
default:
$NOT_REGEXP = '';
break;
}
if ($NOT_REGEXP) {
$ok = $ok && execute_sql("UPDATE {$CFG->prefix}hotpot_questions SET text=NULL WHERE text $NOT_REGEXP '^[0-9]+$'");
}
// hotpot_questions: change type of "text" field to "INT(10)"
$ok = $ok && hotpot_db_update_field_type('hotpot_questions', 'text', 'text', 'INTEGER', 10, 'UNSIGNED', 'NULL');
// hotpot_attempts
// hotpot_attempts: move "details" to separate table
$table = 'hotpot_details';
if (hotpot_db_table_exists($table)) {
// do nothing
} else {
$ok = $ok && hotpot_create_table($table);
switch (strtolower($CFG->dbfamily)) {
case 'mysql' :
case 'postgres' :
$sql = "
INSERT INTO {$CFG->prefix}$table (attempt, details)
SELECT a.id AS attempt, a.details AS details
FROM {$CFG->prefix}hotpot_attempts a
WHERE
a.details IS NOT NULL AND a.details <> ''
AND a.details LIKE ''
";
break;
default:
$sql = '';
break;
}
if ($sql) {
$ok = $ok && execute_sql($sql);
}
}
// hotpot_attempts: remove the "details" field
$ok = $ok && hotpot_db_remove_field('hotpot_attempts', 'details');
// hotpot_attempts: create and set status field (1=in-progress, 2=timed-out, 3=abandoned, 4=completed)
$ok = $ok && hotpot_db_update_field_type('hotpot_attempts', '', 'status', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 1);
$ok = $ok && execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET status=1 WHERE timefinish=0 AND SCORE IS NULL");
$ok = $ok && execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET status=3 WHERE timefinish>0 AND SCORE IS NULL");
$ok = $ok && execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET status=4 WHERE timefinish>0 AND SCORE IS NOT NULL");
// hotpot_attempts: create and set clickreport fields
$ok = $ok && hotpot_db_update_field_type('hotpot', '', 'clickreporting', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 0);
$ok = $ok && hotpot_db_update_field_type('hotpot_attempts', '', 'clickreportid', 'INTEGER', 10, 'UNSIGNED', 'NULL');
$ok = $ok && execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET clickreportid=id WHERE clickreportid IS NULL");
// hotpot_attempts: create and set studentfeedback field (0=none, 1=formmail, 2=moodleforum, 3=moodlemessaging)
$ok = $ok && hotpot_db_update_field_type('hotpot', '', 'studentfeedback', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', '0');
$ok = $ok && hotpot_db_update_field_type('hotpot', '', 'studentfeedbackurl', 'VARCHAR', 255, '', 'NULL');
// add indexes
$ok = $ok && hotpot_db_add_index('hotpot_attempts', 'hotpot');
$ok = $ok && hotpot_db_add_index('hotpot_attempts', 'userid');
$ok = $ok && hotpot_db_add_index('hotpot_details', 'attempt');
$ok = $ok && hotpot_db_add_index('hotpot_questions', 'hotpot');
$ok = $ok && hotpot_db_add_index('hotpot_responses', 'attempt');
$ok = $ok && hotpot_db_add_index('hotpot_responses', 'question');
// hotpot_string: correct double-encoded HTML entities
$ok = $ok && execute_sql("
UPDATE {$CFG->prefix}hotpot_strings
SET string = REPLACE(string, '&','&')
WHERE string LIKE '%&#%'
AND (string LIKE '<' OR string LIKE '>')
");
// hotpot_question: remove questions which refer to deleted hotpots
if ($ok) {
// try and get all hotpot records
if ($records = get_records('hotpot')) {
$ids = implode(',', array_keys($records));
$sql = "DELETE FROM {$CFG->prefix}hotpot_questions WHERE hotpot NOT IN ($ids)";
} else {
// remove all question records (because there are no valid hotpot ids)
$sql = "TRUNCATE {$CFG->prefix}hotpot_questions";
}
print "Removing unused question records ...";
execute_sql($sql);
}
if ($ok) {
// remove old 'v6' templates folder (replaced by 'template' folder)
$ds = DIRECTORY_SEPARATOR;
$dir = "mod{$ds}hotpot{$ds}v6";
print "removing old templates ($dir) ... ";
if (hotpot_rm("$CFG->dirroot{$ds}$dir", false)) {
print get_string('success');
} else {
print "failed
Please remove '$CFG->dirroot{$ds}$dir' manually";
}
print "
\n";
}
return $ok;
}
function hotpot_update_to_v2_from_v1() {
global $CFG;
$ok = true;
// remove, alter and add fields in database
$table = 'hotpot';
if (hotpot_db_table_exists($table)) {
$ok = $ok && hotpot_update_fields($table);
} else {
$ok = $ok && hotpot_create_table($table);
}
$table = 'hotpot_attempts';
$oldtable = 'hotpot_events';
if (hotpot_db_table_exists($oldtable)) {
$ok = $ok && hotpot_update_fields($oldtable);
$ok = $ok && hotpot_db_append_table($oldtable, $table);
} else {
$ok = $ok && hotpot_create_table($table);
}
// create new tables (from mysql.sql)
$ok = $ok && hotpot_create_table('hotpot_questions');
$ok = $ok && hotpot_create_table('hotpot_responses');
$ok = $ok && hotpot_create_table('hotpot_strings');
// remove redundant scripts
$files = array('coursefiles.php', 'details.php', 'dummy.html', 'hotpot.php', 'hotpot2db.php');
foreach ($files as $file) {
$filepath = "$CFG->dirroot/mod/hotpot/$file";
if (file_exists($filepath)) {
@unlink($filepath); // don't worry about errors
}
}
return $ok;
}
function hotpot_update_to_v2_from_hotpotatoes() {
global $CFG;
$ok = true; // hope for the best!
// check we have the minimum required hotpot module
$minimum = 2005031400;
$module = get_record("modules", "name", "hotpot");
if (empty($module) || $module->version<$minimum) {
if ($module) {
print ("
The update to the HotPotatoes module requires at least version $minimum of the HotPot module.
"); print ("The current version of the HotPot module on this site is $module->version.
"); } print ("Please install the latest version of the HotPot module and then try the update again.
"); $ok = false; } else { // arrays to map foreign keys $new = array(); $new['hotpot'] = array(); $new['attempt'] = array(); $new['question'] = array(); $new['string'] = array(); // save and switch off SQL message echo global $db; $debug = $db->debug; $db->debug = false; // import hotpotatoes (and save old ids) $ok = $ok && hotpot_update_fields('hotpotatoes'); $ok = $ok && hotpot_transfer_records('hotpotatoes', 'hotpot', array(), 'hotpot', $new); // update course modules and logs $ok = $ok && hotpot_update_course_modules('hotpotatoes', 'hotpot', $new); // import hotpotatoes_strings (and save old ids) $ok = $ok && hotpot_transfer_records('hotpotatoes_strings', 'hotpot_strings', array(), 'string', $new); // import hotpotatoes_attempts (and save old ids) $ok = $ok && hotpot_transfer_records('hotpotatoes_attempts', 'hotpot_attempts', array('hotpotatoes'=>'hotpot'), 'attempt', $new); // import hotpotatoes_questions (and save old ids) $ok = $ok && hotpot_transfer_records('hotpotatoes_questions', 'hotpot_questions', array('hotpotatoes'=>'hotpot'), 'question', $new); // import hotpotatoes_responses $ok = $ok && hotpot_transfer_records('hotpotatoes_responses', 'hotpot_responses', array('attempt'=>'attempt', 'question'=>'question'), 'response', $new); // restore SQL message echo setting $db->debug = $debug; // remove the hotpotatoes tables, if the update went ok if ($ok) { // hotpot_db_remove_table('hotpotatoes'); // hotpot_db_remove_table('hotpotatoes_attempts'); // hotpot_db_remove_table('hotpotatoes_questions'); // hotpot_db_remove_table('hotpotatoes_responses'); // hotpot_db_remove_table('hotpotatoes_strings'); } // hide the hotpotatoes module (see admin/modules.php)) if ($ok && ($module = get_record("modules", "name", "hotpotatoes"))) { set_field("modules", "visible", "0", "id", $module->id); print 'All HotPotatoes activities have been imported to the HotPot module.
'."\n";
print 'The HotPotatoes module has been hidden and can safely be deleted from this Moodle site.
'."\n";
print ' Configuration -> Modules, then click "Delete" for "Hot Potatoes XML Quiz"
Thank you for using the HotPotatoes module.
';
print 'The HotPotatoes module has been replaced by
version 2 of the HotPot module. Enjoy!