function xmldb_hotpot_upgrade($oldversion = 0) { global $CFG, $THEME, $db; $result = true; //===== 1.9.0 upgrade line ======// if ($result && $oldversion < 2007101512) { // save and disable setting to display debugging messages $debug = $db->debug; $db->debug = false; notify('Fixing hotpot grades, this may take a while if there are many hotpots...', 'notifysuccess'); hotpot_fix_grades(); // restore $db->debug $db->debug = $debug; } // update hotpot grades from sites earlier than Moodle 1.9, 27th March 2008 if ($result && $oldversion < 2007101513) { // ensure "hotpot_update_grades" function is available require_once $CFG->dirroot . '/mod/hotpot/lib.php'; // save and disable setting to display debugging messages $debug = $db->debug; $db->debug = false; notify('Processing hotpot grades, this may take a while if there are many hotpots...', 'notifysuccess'); hotpot_update_grades(); // restore $db->debug $db->debug = $debug; } return $result; }
function hotpot_delete_selected_attempts(&$hotpot, $del) { global $DB; $select = ''; $params = array('hotpotid' => $hotpot->id); switch ($del) { case 'all': $select = "hotpot=:hotpotid"; break; case 'abandoned': $select = "hotpot=:hotpotid AND status=" . HOTPOT_STATUS_ABANDONED; break; case 'selection': $ids = array(); $data = (array) data_submitted(); foreach ($data as $name => $value) { if (preg_match('/^box\\d+$/', $name)) { $ids[] = intval($value); } } if (count($ids)) { list($ids, $idparams) = $DB->get_in_or_equal($ids, SQL_PARAMS_NAMED, 'crid0'); $params = array_merge($params, $idparams); $select = "hotpot=:hotpotid AND clickreportid {$ids}"; } break; } // delete attempts using $select, if it is set if ($select) { $table = 'hotpot_attempts'; if ($attempts = $DB->get_records_select($table, $select, $params)) { hotpot_delete_and_notify($table, $select, $params, get_string('attempts', 'quiz')); $select = 'attempt IN (' . implode(',', array_keys($attempts)) . ')'; $params = array(); hotpot_delete_and_notify('hotpot_details', $select, $params, get_string('rawdetails', 'hotpot')); hotpot_delete_and_notify('hotpot_responses', $select, $params, get_string('answer', 'quiz')); // update grades for all users for this hotpot hotpot_update_grades($hotpot); } } }
function hotpot_delete_selected_attempts(&$hotpot, $del) { $select = ''; switch ($del) { case 'all': $select = "hotpot='{$hotpot->id}'"; break; case 'abandoned': $select = "hotpot='{$hotpot->id}' AND status=" . HOTPOT_STATUS_ABANDONED; break; case 'selection': $ids = array(); $data = (array) data_submitted(); foreach ($data as $name => $value) { if (preg_match('/^box\\d+$/', $name)) { $ids[] = intval($value); } } if (count($ids)) { $select = "hotpot='{$hotpot->id}' AND clickreportid IN (" . implode(',', $ids) . ")"; } break; } // delete attempts using $select, if it is set if ($select) { $table = 'hotpot_attempts'; if ($attempts = get_records_select($table, $select)) { hotpot_delete_and_notify($table, $select, get_string('attempts', 'quiz')); $select = 'attempt IN (' . implode(',', array_keys($attempts)) . ')'; hotpot_delete_and_notify('hotpot_details', $select, get_string('rawdetails', 'hotpot')); hotpot_delete_and_notify('hotpot_responses', $select, get_string('answer', 'quiz')); // update grades for all users for this hotpot hotpot_update_grades($hotpot); } } }
// (N.B. this does NOT remove the attempt record, just the responses) delete_records("hotpot_responses", "attempt", $attempt->id); } } // remove slashes added by lib/setup.php $attempt->details = stripslashes($attempt->details); // add details of this attempt hotpot_add_attempt_details($attempt); // add slashes again, so the details can be added to the database $attempt->details = addslashes($attempt->details); // update the attempt record if (!update_record("hotpot_attempts", $attempt)) { error("Could not update attempt record: " . $db->ErrorMsg(), $next_url); } // update grades for this user hotpot_update_grades($hotpot, $attempt->userid); // get previous attempt details record, if any $details_exist = record_exists("hotpot_details", "attempt", $attempt->id); // delete/update/add the attempt details record if (empty($attempt->details)) { if ($details_exist) { delete_records("hotpot_details", "attempt", $attempt->id); } } else { if ($details_exist) { set_field("hotpot_details", "details", $attempt->details, "attempt", $attempt->id); } else { unset($details); $details->attempt = $attempt->id; $details->details = $attempt->details; if (!insert_record("hotpot_details", $details)) {
/** * Update grades in central gradebook * this function is called from db/upgrade.php * it is initially called with no arguments, which forces it to get a list of all hotpots * it then iterates through the hotpots, calling itself to create a grade record for each hotpot * * @param object $hotpot null means all hotpots * @param int $userid specific user only, 0 means all users */ function hotpot_update_grades($hotpot = null, $userid = 0, $nullifnone = true) { global $CFG; if (!function_exists('grade_update')) { require_once $CFG->libdir . '/gradelib.php'; } if (is_null($hotpot)) { // update (=create) grades for all hotpots $sql = "\n SELECT h.*, cm.idnumber as cmidnumber\n FROM {$CFG->prefix}hotpot h, {$CFG->prefix}course_modules cm, {$CFG->prefix}modules m\n WHERE m.name='hotpot' AND m.id=cm.module AND cm.instance=h.id"; if ($rs = get_recordset_sql($sql)) { while ($hotpot = rs_fetch_next_record($rs)) { hotpot_update_grades($hotpot, 0, false); } rs_close($rs); } } else { // update (=create) grade for a single hotpot if ($grades = hotpot_get_user_grades($hotpot, $userid)) { hotpot_grade_item_update($hotpot, $grades); } else { if ($userid && $nullifnone) { // no grades for this user, but we must force the creation of a "null" grade record $grade = new object(); $grade->userid = $userid; $grade->rawgrade = null; hotpot_grade_item_update($hotpot, $grade); } else { // no grades and no userid hotpot_grade_item_update($hotpot); } } } }
/** * store * * @param xxx $hotpot */ public static function store($hotpot) { global $CFG, $DB, $USER; if (empty($hotpot->attempt)) { return; // no attempt record - shouldn't happen !! } if ($hotpot->attempt->userid != $USER->id) { return; // wrong userid - shouldn't happen !! } // update quiz attempt fields using incoming data $hotpot->attempt->score = max(0, optional_param(self::scorefield, 0, PARAM_INT)); $hotpot->attempt->status = max(0, optional_param('status', 0, PARAM_INT)); $hotpot->attempt->redirect = max(0, optional_param('redirect', 0, PARAM_INT)); $hotpot->attempt->details = optional_param(self::detailsfield, '', PARAM_RAW); // update timemodified for this attempt $hotpot->attempt->timemodified = $hotpot->time; // time values, e.g. "2008-09-12 16:18:18 +0900", // need to be converted to numeric date stamps $timefields = array('starttime', 'endtime'); foreach ($timefields as $timefield) { $hotpot->attempt->{$timefield} = 0; // default if ($time = optional_param($timefield, '', PARAM_RAW)) { // make sure the timezone has a "+" sign // Note: sometimes it gets stripped (by optional_param?) $time = preg_replace('/(?<= )\\d{4}$/', '+$0', trim($time)); // convert $time to numeric date stamp // PHP4 gives -1 on error, whereas PHP5 give false $time = strtotime($time); if ($time && $time > 0) { $hotpot->attempt->{$timefield} = $time; } } } unset($timefields, $timefield, $time); // set finish times $hotpot->attempt->timefinish = $hotpot->time; // increment quiz attempt duration $startfield = self::durationstartfield; // "starttime" or "timestart" $finishfield = self::durationfinishfield; // "endtime" or "timefinish" $duration = $hotpot->attempt->{$finishfield} - $hotpot->attempt->{$startfield}; if (empty($hotpot->attempt->duration)) { $hotpot->attempt->duration = $duration; } else { if ($duration > 0) { $hotpot->attempt->duration += $duration; } } unset($duration, $startfield, $finishfield); // set clickreportid, (for click reporting) $hotpot->attempt->clickreportid = $hotpot->attempt->id; // check if there are any previous results stored for this attempt // this could happen if ... // - the quiz has been resumed // - clickreporting is enabled for this quiz if ($DB->get_field('hotpot_attempts', 'timefinish', array('id' => $hotpot->attempt->id))) { if ($hotpot->clickreporting) { // self::can_clickreporting() // add quiz attempt record for each form submission // records are linked via the "clickreportid" field // update timemodified and status in previous records in this clickreportid group $DB->set_field('hotpot_attempts', 'timemodified', $hotpot->time, array('clickreportid' => $hotpot->attempt->clickreportid)); $DB->set_field('hotpot_attempts', 'status', $hotpot->attempt->status, array('clickreportid' => $hotpot->attempt->clickreportid)); // add new attempt record unset($hotpot->attempt->id); if (!($hotpot->attempt->id = $DB->insert_record('hotpot_attempts', $hotpot->attempt))) { print_error('error_insertrecord', 'hotpot', '', 'hotpot_attempts'); } } else { // remove previous responses for this attempt, if required // (N.B. this does NOT remove the attempt record, just the responses) $DB->delete_records('hotpot_responses', array('attemptid' => $hotpot->attempt->id)); } } // add details of this quiz attempt, if required // "hotpot_storedetails" is set by administrator // Site Admin -> Modules -> Activities -> HotPot if ($CFG->hotpot_storedetails) { // delete/update/add the details record if ($DB->record_exists('hotpot_details', array('attemptid' => $hotpot->attempt->id))) { $DB->set_field('hotpot_details', 'details', $hotpot->attempt->details, array('attemptid' => $hotpot->attempt->id)); } else { $details = (object) array('attemptid' => $hotpot->attempt->id, 'details' => $hotpot->attempt->details); if (!$DB->insert_record('hotpot_details', $details, false)) { print_error('error_insertrecord', 'hotpot', '', 'hotpot_details'); } unset($details); } } // add details of this attempt self::store_details($hotpot->attempt); // update the attempt record if (!$DB->update_record('hotpot_attempts', $hotpot->attempt)) { print_error('error_updaterecord', 'hotpot', '', 'hotpot_attempts'); } // regrade the quiz to take account of the latest quiz attempt score hotpot_update_grades($hotpot->to_stdclass(), $hotpot->attempt->userid); }
/** * xmldb_hotpot_upgrade * * @param xxx $oldversion * @return xxx */ function xmldb_hotpot_upgrade($oldversion) { global $CFG, $DB; // this flag will be set to true if any upgrade needs to empty the HotPot cache $empty_cache = false; $dbman = $DB->get_manager(); //===== 1.9.0 upgrade line ======// // update hotpot grades from sites earlier than Moodle 1.9, 27th March 2008 $newversion = 2007101511; if ($oldversion < $newversion) { // ensure "hotpot_upgrade_grades" function is available require_once $CFG->dirroot . '/mod/hotpot/lib.php'; hotpot_upgrade_grades(); upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2008011200; if ($oldversion < $newversion) { // remove unused config setting unset_config('hotpot_initialdisable'); upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080301; if ($oldversion < $newversion) { // remove unused config settings unset_config('hotpot_showtimes'); unset_config('hotpot_excelencodings'); // modify table: hotpot $table = new xmldb_table('hotpot'); // expected structure of hotpot table when we start this upgrade: // (i.e. this is how things were at the end of Moodle 1.9) // id, course, name, summary, timeopen, timeclose, location, reference, // outputformat, navigation, studentfeedback, studentfeedbackurl, // forceplugins, shownextquiz, review, grade, grademethod, attempts, // password, subnet, clickreporting, timecreated, timemodified // convert, move and rename fields ($newname => $oldfield) $fields = array('outputformat' => new xmldb_field('outputformat', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL), 'timeopen' => new xmldb_field('timeopen', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'studentfeedbackurl'), 'timeclose' => new xmldb_field('timeclose', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'timeopen'), 'grademethod' => new xmldb_field('grademethod', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'grade'), 'sourcefile' => new xmldb_field('reference', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'name'), 'sourcelocation' => new xmldb_field('location', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'sourcefile'), 'entrytext' => new xmldb_field('summary', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'sourcelocation'), 'reviewoptions' => new xmldb_field('review', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'), 'attemptlimit' => new xmldb_field('attempts', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'reviewoptions'), 'gradeweighting' => new xmldb_field('grade', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'attemptlimit')); foreach ($fields as $newname => $field) { if ($dbman->field_exists($table, $field)) { xmldb_hotpot_fix_previous_field($dbman, $table, $field); $dbman->change_field_type($table, $field); if ($field->getName() != $newname) { $dbman->rename_field($table, $field, $newname); } } } // add fields $fields = array(new xmldb_field('sourcefile', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'name'), new xmldb_field('sourcetype', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'sourcefile'), new xmldb_field('sourceitemid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'sourcetype'), new xmldb_field('sourcelocation', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'sourceitemid'), new xmldb_field('configfile', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'sourcelocation'), new xmldb_field('configitemid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'configfile'), new xmldb_field('configlocation', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'configitemid'), new xmldb_field('entrycm', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'configlocation'), new xmldb_field('entrygrade', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '100', 'entrycm'), new xmldb_field('entrypage', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'entrygrade'), new xmldb_field('entrytext', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'entrypage'), new xmldb_field('entryformat', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'entrytext'), new xmldb_field('entryoptions', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'entryformat'), new xmldb_field('exitpage', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'entryoptions'), new xmldb_field('exittext', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'exitpage'), new xmldb_field('exitformat', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'exittext'), new xmldb_field('exitoptions', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'exitformat'), new xmldb_field('exitcm', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'exitoptions'), new xmldb_field('title', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '3', 'navigation'), new xmldb_field('stopbutton', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'title'), new xmldb_field('stoptext', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'stopbutton'), new xmldb_field('usefilters', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'stoptext'), new xmldb_field('useglossary', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'usefilters'), new xmldb_field('usemediafilter', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'useglossary'), new xmldb_field('timelimit', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'timeclose'), new xmldb_field('delay1', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'timelimit'), new xmldb_field('delay2', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'delay1'), new xmldb_field('delay3', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '2', 'delay2'), new xmldb_field('discarddetails', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'clickreporting')); foreach ($fields as $field) { if (!$dbman->field_exists($table, $field)) { xmldb_hotpot_fix_previous_field($dbman, $table, $field); $dbman->add_field($table, $field); } } // remove field: forceplugins (replaced by "usemediafilter") $field = new xmldb_field('forceplugins', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); if ($dbman->field_exists($table, $field)) { $DB->execute('UPDATE {hotpot} SET ' . "usemediafilter='moodle'" . ' WHERE forceplugins=1'); $dbman->drop_field($table, $field); } // remove field: shownextquiz (replaced by "exitcm") $field = new xmldb_field('shownextquiz', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); if ($dbman->field_exists($table, $field)) { // set exitcm to show next HotPot: -4 = hotpot::ACTIVITY_SECTION_HOTPOT $DB->execute('UPDATE {hotpot} SET exitcm=-4 WHERE shownextquiz=1'); $dbman->drop_field($table, $field); } // append "id" to fields that are foreign keys in other hotpot tables $fields = array('hotpot_attempts' => array('hotpot'), 'hotpot_details' => array('attempt'), 'hotpot_questions' => array('hotpot'), 'hotpot_responses' => array('attempt', 'question')); foreach ($fields as $tablename => $fieldnames) { $table = new xmldb_table($tablename); foreach ($fieldnames as $fieldname) { $field = new xmldb_field($fieldname, XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); if ($dbman->field_exists($table, $field)) { // maybe we should remove all indexes and keys // using this $fieldname before we rename the field $dbman->rename_field($table, $field, $fieldname . 'id'); } } } // create new table: hotpot_cache $table = new xmldb_table('hotpot_cache'); if (!$dbman->table_exists($table)) { $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); $table->add_field('hotpotid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); $table->add_field('slasharguments', XMLDB_TYPE_CHAR, '1', null, XMLDB_NOTNULL); $table->add_field('hotpot_enableobfuscate', XMLDB_TYPE_CHAR, '1', null, XMLDB_NOTNULL); $table->add_field('hotpot_enableswf', XMLDB_TYPE_CHAR, '1', null, XMLDB_NOTNULL); $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL); $table->add_field('sourcefile', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL); $table->add_field('sourcetype', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL); $table->add_field('sourcelocation', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL); $table->add_field('sourcelastmodified', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL); $table->add_field('sourceetag', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL); $table->add_field('configfile', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL); $table->add_field('configlocation', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); $table->add_field('configlastmodified', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL); $table->add_field('configetag', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL); $table->add_field('navigation', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); $table->add_field('title', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); $table->add_field('stopbutton', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, null, null, '0'); $table->add_field('stoptext', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL); $table->add_field('usefilters', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, null, null, '0'); $table->add_field('useglossary', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, null, null, '0'); $table->add_field('usemediafilter', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, '0'); $table->add_field('studentfeedback', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0'); $table->add_field('studentfeedbackurl', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL); $table->add_field('timelimit', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); $table->add_field('delay3', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '-1'); $table->add_field('clickreporting', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); $table->add_field('content', XMLDB_TYPE_TEXT, 'medium', null, XMLDB_NOTNULL); $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL); $table->add_field('md5key', XMLDB_TYPE_CHAR, '32', null, XMLDB_NOTNULL); // Add keys to table hotpot_cache $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); $table->add_key('hotpotid', XMLDB_KEY_FOREIGN, array('hotpotid'), 'hotpot', array('id')); // Add indexes to table hotpot_cache $table->add_index('hotpotid-md5key', XMLDB_INDEX_NOTUNIQUE, array('hotpotid', 'md5key')); $dbman->create_table($table); } // add new logging actions log_update_descriptions('mod/hotpot'); // hotpot savepoint reached upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080302; if ($oldversion < $newversion) { // navigation setting of "none" is now "0" (was "6") $DB->execute('UPDATE {hotpot} SET navigation=0 WHERE navigation=6'); // navigation's "give up" button, is replaced by the "stopbutton" field $DB->execute('UPDATE {hotpot} SET stopbutton=0 WHERE navigation=5'); $DB->execute('UPDATE {hotpot} SET navigation=0 WHERE navigation=5'); upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080303; if ($oldversion < $newversion) { // modify table: hotpot_attempts $table = new xmldb_table('hotpot_attempts'); // add field: timemodified $field = new xmldb_field('timemodified', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); $DB->execute('UPDATE {hotpot_attempts} SET timemodified = timefinish WHERE timemodified=0'); $DB->execute('UPDATE {hotpot_attempts} SET timemodified = timestart WHERE timemodified=0'); } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080305; if ($oldversion < $newversion) { // modify table: hotpot $table = new xmldb_table('hotpot'); // change fields // - entrycm (-> signed) // - outputformat (-> varchar) // - timelimit (-> signed) // - delay3 (-> signed) // - attemptlimit (-> unsigned) // - gradeweighting (-> unsigned) // - grademethod (-> unsigned) $fields = array(new xmldb_field('entrycm', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'), new xmldb_field('outputformat', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL), new xmldb_field('timelimit', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'), new xmldb_field('delay3', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '2'), new xmldb_field('attemptlimit', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'), new xmldb_field('gradeweighting', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'), new xmldb_field('grademethod', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0')); foreach ($fields as $field) { if ($dbman->field_exists($table, $field)) { xmldb_hotpot_fix_previous_field($dbman, $table, $field); $dbman->change_field_type($table, $field); } } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080306; if ($oldversion < $newversion) { // modify table: hotpot $table = new xmldb_table('hotpot'); // rename field: gradelimit -> gradeweighting $field = new xmldb_field('gradelimit', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); if ($dbman->field_exists($table, $field)) { $dbman->rename_field($table, $field, 'gradeweighting'); } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080308; if ($oldversion < $newversion) { // add display fields to hotpot // (these fields were missing from access.xml so won't be on new sites) $tables = array('hotpot' => array(new xmldb_field('title', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '3', 'navigation'), new xmldb_field('stopbutton', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'title'), new xmldb_field('stoptext', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'stopbutton'), new xmldb_field('usefilters', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'stoptext'), new xmldb_field('useglossary', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'usefilters'), new xmldb_field('usemediafilter', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'useglossary'))); foreach ($tables as $tablename => $fields) { $table = new xmldb_table($tablename); foreach ($fields as $field) { xmldb_hotpot_fix_previous_field($dbman, $table, $field); if ($dbman->field_exists($table, $field)) { $dbman->change_field_type($table, $field); } else { $dbman->add_field($table, $field); } } } $table = new xmldb_table('hotpot'); $field = new xmldb_field('forceplugins', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); if ($dbman->field_exists($table, $field)) { $DB->execute('UPDATE {hotpot} SET ' . "usemediafilter='moodle'" . ' WHERE forceplugins=1'); $dbman->drop_field($table, $field); } // force certain fields to be not null $tables = array('hotpot' => array(new xmldb_field('entrygrade', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '100')), 'hotpot_cache' => array(new xmldb_field('stopbutton', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'), new xmldb_field('usefilters', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'), new xmldb_field('useglossary', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'), new xmldb_field('studentfeedback', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'))); foreach ($tables as $tablename => $fields) { $table = new xmldb_table($tablename); foreach ($fields as $field) { if ($dbman->field_exists($table, $field)) { $dbman->change_field_type($table, $field); } } } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080309; if ($oldversion < $newversion) { // force certain text fields to be not null $tables = array('hotpot' => array(new xmldb_field('sourcefile', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL), new xmldb_field('entrytext', XMLDB_TYPE_TEXT, 'small', null, XMLDB_NOTNULL), new xmldb_field('exittext', XMLDB_TYPE_TEXT, 'small', null, XMLDB_NOTNULL), new xmldb_field('stoptext', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL))); foreach ($tables as $tablename => $fields) { $table = new xmldb_table($tablename); foreach ($fields as $field) { if ($dbman->field_exists($table, $field)) { $fieldname = $field->getName(); $DB->set_field_select($tablename, $fieldname, '', "{$fieldname} IS NULL"); $dbman->change_field_type($table, $field); } } } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080311; if ($oldversion < $newversion) { require_once $CFG->dirroot . '/mod/hotpot/locallib.php'; ///////////////////////////////////// /// new file storage migrate code /// ///////////////////////////////////// // set up sql strings to select HotPots with Moodle 1.x file paths (i.e. no leading slash) $strupdating = get_string('migratingfiles', 'hotpot'); $select = 'h.*, cm.id AS cmid'; $from = '{hotpot} h, {course_modules} cm, {modules} m'; $where = 'm.name=? AND m.id=cm.module AND cm.instance=h.id AND h.sourcefile<>?' . ' AND ' . $DB->sql_like('h.sourcefile', '?', false, false, true); // NOT LIKE $params = array('hotpot', '', '/%', 0); $orderby = 'h.course, h.id'; // get HotPot records that need to be updated if ($count = $DB->count_records_sql("SELECT COUNT('x') FROM {$from} WHERE {$where}", $params)) { $rs = $DB->get_recordset_sql("SELECT {$select} FROM {$from} WHERE {$where} ORDER BY {$orderby}", $params); } else { $rs = false; } if ($rs) { $i = 0; $bar = new progress_bar('hotpotmigratefiles', 500, true); // get file storage object $fs = get_file_storage(); if (class_exists('context_course')) { $sitecontext = context_course::instance(SITEID); } else { $sitecontext = get_context_instance(CONTEXT_COURSE, SITEID); } $coursecontext = null; $modulecontext = null; foreach ($rs as $hotpot) { // apply for more script execution time (3 mins) upgrade_set_timeout(); // get course context for this $hotpot if ($coursecontext === null || $coursecontext->instanceid != $hotpot->course) { if (class_exists('context_course')) { $coursecontext = context_course::instance($hotpot->course); } else { $coursecontext = get_context_instance(CONTEXT_COURSE, $hotpot->course); } } // get module context for this $hotpot/$task if ($modulecontext === null || $modulecontext->instanceid != $hotpot->cmid) { if (class_exists('context_module')) { $modulecontext = context_module::instance($hotpot->cmid); } else { $modulecontext = get_context_instance(CONTEXT_MODULE, $hotpot->cmid); } } // actually there shouldn't be any urls in HotPot activities, // but this code will also be used to convert QuizPort to TaskChain if (preg_match('/^https?:\\/\\//i', $hotpot->sourcefile)) { $url = $hotpot->sourcefile; $path = parse_url($url, PHP_URL_PATH); } else { $url = ''; $path = $hotpot->sourcefile; } $path = clean_param($path, PARAM_PATH); // this information should be enough to access the file // if it has been migrated into Moodle 2.0 file system $old_filename = basename($path); $old_filepath = dirname($path); if ($old_filepath == '.' || $old_filepath == '') { $old_filepath = '/'; } else { $old_filepath = '/' . ltrim($old_filepath, '/'); // require leading slash $old_filepath = rtrim($old_filepath, '/') . '/'; // require trailing slash } // update $hotpot->sourcefile, if necessary if ($hotpot->sourcefile != $old_filepath . $old_filename) { $hotpot->sourcefile = $old_filepath . $old_filename; $DB->set_field('hotpot', 'sourcefile', $hotpot->sourcefile, array('id' => $hotpot->id)); } // set $courseid and $contextid from $task->$location // of where we expect to find the $file // 0 : HOTPOT_LOCATION_COURSEFILES // 1 : HOTPOT_LOCATION_SITEFILES // 2 : HOTPOT_LOCATION_WWW (not used) if ($hotpot->sourcelocation) { $courseid = SITEID; $contextid = $sitecontext->id; } else { $courseid = $hotpot->course; $contextid = $coursecontext->id; } // we expect to need the $filehash to get a file that has been migrated $filehash = sha1('/' . $contextid . '/course/legacy/0' . $old_filepath . $old_filename); // we might also need the old file path, if the file has not been migrated $oldfilepath = $CFG->dataroot . '/' . $courseid . $old_filepath . $old_filename; // set parameters used to add file to filearea // (sortorder=1 siginifies the "mainfile" in this filearea) $file_record = array('contextid' => $modulecontext->id, 'component' => 'mod_hotpot', 'filearea' => 'sourcefile', 'sortorder' => 1, 'itemid' => 0, 'filepath' => $old_filepath, 'filename' => $old_filename); // initialize sourcefile settings $hotpot->sourcefile = $old_filepath . $old_filename; $hotpot->sourcetype = ''; $hotpot->sourceitemid = 0; if ($file = $fs->get_file($modulecontext->id, 'mod_hotpot', 'sourcefile', 0, $old_filepath, $old_filename)) { // file already exists for this context - shouldn't happen !! // maybe an earlier upgrade failed for some reason ? // anyway we must do this check, so that create_file_from_xxx() does not abort } else { if ($url) { // file is on an external url - unusual ?! $file = false; // $fs->create_file_from_url($file_record, $url); } else { if ($file = $fs->get_file_by_hash($filehash)) { // $file has already been migrated to Moodle's file system // this is the route we expect most people to come :-) $file = $fs->create_file_from_storedfile($file_record, $file); } else { if (file_exists($oldfilepath)) { // $file still exists on server's filesystem - unusual ?! $file = $fs->create_file_from_pathname($file_record, $oldfilepath); } else { // file was not migrated and is not on server's filesystem $file = false; } } } } // if source file did not exist, notify user of the problem if (empty($file)) { if ($url) { $msg = "course_modules.id={$hotpot->cmid}, url={$url}"; } else { $msg = "course_modules.id={$hotpot->cmid}, path={$path}"; } $params = array('update' => $hotpot->cmid, 'onclick' => 'this.target="_blank"'); $msg = html_writer::link(new moodle_url('/course/modedit.php', $params), $msg); $msg = get_string('sourcefilenotfound', 'hotpot', $msg); echo html_writer::tag('div', $msg, array('class' => 'notifyproblem')); } // set $hotpot->sourcetype if ($pos = strrpos($hotpot->sourcefile, '.')) { $filetype = substr($hotpot->sourcefile, $pos + 1); switch ($filetype) { case 'jcl': $hotpot->sourcetype = 'hp_6_jcloze_xml'; break; case 'jcw': $hotpot->sourcetype = 'hp_6_jcross_xml'; break; case 'jmt': $hotpot->sourcetype = 'hp_6_jmatch_xml'; break; case 'jmx': $hotpot->sourcetype = 'hp_6_jmix_xml'; break; case 'jqz': $hotpot->sourcetype = 'hp_6_jquiz_xml'; break; case 'rhb': $hotpot->sourcetype = 'hp_6_rhubarb_xml'; break; case 'sqt': $hotpot->sourcetype = 'hp_6_sequitur_xml'; break; case 'htm': case 'html': default: if ($file) { $pathnamehash = $fs->get_pathname_hash($modulecontext->id, 'mod_hotpot', 'sourcefile', 0, $old_filepath, $old_filename); if ($contenthash = $DB->get_field('files', 'contenthash', array('pathnamehash' => $pathnamehash))) { $l1 = $contenthash[0] . $contenthash[1]; $l2 = $contenthash[2] . $contenthash[3]; if (file_exists("{$CFG->dataroot}/filedir/{$l1}/{$l2}/{$contenthash}")) { $hotpot->sourcetype = hotpot::get_sourcetype($file); } else { $msg = html_writer::link(new moodle_url('/course/modedit.php', array('update' => $hotpot->cmid)), "course_modules.id={$hotpot->cmid}, path={$path}"); $msg .= html_writer::empty_tag('br'); $msg .= "filedir path={$l1}/{$l2}/{$contenthash}"; $msg = get_string('sourcefilenotfound', 'hotpot', $msg); echo html_writer::tag('div', $msg, array('class' => 'notifyproblem')); } } } } } // JMatch has 2 output formats // 14 : v6 : drop down menus : hp_6_jmatch_xml_v6 // 15 : v6+ : drag-and-drop : hp_6_jmatch_xml_v6_plus // JMix has 2 output formats // 14 : v6 : links : hp_6_jmix_xml_v6 // 15 : v6+ : drag-and-drop : hp_6_jmix_xml_v6_plus // since drag-and-drop is the "best" outputformat for both types of quiz, // we only need to worry about HotPots whose outputformat was 14 (="v6") // set $hotpot->outputformat if ($hotpot->outputformat == 14 && ($hotpot->sourcetype == 'hp_6_jmatch_xml' || $hotpot->sourcetype == 'hp_6_jmix_xml')) { $hotpot->outputformat = $hotpot->sourcetype . '_v6'; } else { $hotpot->outputformat = ''; // = "best" output format } $DB->update_record('hotpot', $hotpot); // update progress bar $i++; $bar->update($i, $count, $strupdating . ": ({$i}/{$count})"); } $rs->close(); } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080316; if ($oldversion < $newversion) { // because the HotPot activities were probably hidden until now // we need to reset the course caches (using "course/lib.php") require_once $CFG->dirroot . '/course/lib.php'; $courseids = array(); if ($hotpots = $DB->get_records('hotpot', null, '', 'id,course')) { foreach ($hotpots as $hotpot) { $courseids[$hotpot->course] = true; } $courseids = array_keys($courseids); } unset($hotpots, $hotpot); foreach ($courseids as $courseid) { rebuild_course_cache($courseid, true); } unset($courseids, $courseid); // reset theme cache to force inclusion of new hotpot css theme_reset_all_caches(); upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080325; if ($oldversion < $newversion) { $table = new xmldb_table('hotpot'); $fieldnames = array('sourceitemid', 'configitemid'); foreach ($fieldnames as $fieldname) { $field = new xmldb_field($fieldname); if ($dbman->field_exists($table, $field)) { $dbman->drop_field($table, $field); } } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080330; if ($oldversion < $newversion) { require_once $CFG->dirroot . '/mod/hotpot/lib.php'; hotpot_refresh_events(); } $newversion = 2010080333; if ($oldversion < $newversion) { update_capabilities('mod/hotpot'); upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080339; if ($oldversion < $newversion) { $table = new xmldb_table('hotpot'); $field = new xmldb_field('exitgrade', XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'exitcm'); xmldb_hotpot_fix_previous_field($dbman, $table, $field); if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080340; if ($oldversion < $newversion) { // force all text fields to be long text, the default for Moodle 2.3 and later $tables = array('hotpot' => array(new xmldb_field('entrytext', XMLDB_TYPE_TEXT, 'long', null, XMLDB_NOTNULL), new xmldb_field('exittext', XMLDB_TYPE_TEXT, 'long', null, XMLDB_NOTNULL)), 'hotpot_cache' => array(new xmldb_field('content', XMLDB_TYPE_TEXT, 'long', null, XMLDB_NOTNULL)), 'hotpot_details' => array(new xmldb_field('details', XMLDB_TYPE_TEXT, 'long', null, XMLDB_NOTNULL)), 'hotpot_questions' => array(new xmldb_field('name', XMLDB_TYPE_TEXT, 'long', null, XMLDB_NOTNULL)), 'hotpot_strings' => array(new xmldb_field('string', XMLDB_TYPE_TEXT, 'long', null, XMLDB_NOTNULL))); foreach ($tables as $tablename => $fields) { $table = new xmldb_table($tablename); foreach ($fields as $field) { if ($dbman->field_exists($table, $field)) { $fieldname = $field->getName(); $DB->set_field_select($tablename, $fieldname, '', "{$fieldname} IS NULL"); $dbman->change_field_type($table, $field); } } } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080342; if ($oldversion < $newversion) { // force all MySQL integer fields to be signed, the default for Moodle 2.3 and later if ($DB->get_dbfamily() == 'mysql') { $prefix = $DB->get_prefix(); $tables = $DB->get_tables(); foreach ($tables as $table) { if (substr($table, 0, 6) == 'hotpot') { $rs = $DB->get_recordset_sql("SHOW COLUMNS FROM {$CFG->prefix}{$table} WHERE type LIKE '%unsigned%'"); foreach ($rs as $column) { // copied from as "lib/db/upgradelib.php" $type = preg_replace('/\\s*unsigned/i', 'signed', $column->type); $notnull = $column->null === 'NO' ? 'NOT NULL' : 'NULL'; $default = is_null($column->default) || $column->default === '' ? '' : "DEFAULT '{$column->default}'"; $autoinc = stripos($column->extra, 'auto_increment') === false ? '' : 'AUTO_INCREMENT'; $sql = "ALTER TABLE `{$prefix}{$table}` MODIFY COLUMN `{$column->field}` {$type} {$notnull} {$default} {$autoinc}"; $DB->change_database_structure($sql); } } } } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080353; if ($oldversion < $newversion) { // remove any unwanted "course_files" folders that may have been created // when restoring Moodle 1.9 HotPot activities to a Moodle 2.x site // select all HotPot activities which have a "course_files" folder // but whose "sourcefile" path does not require such a folder $select = 'f.*,' . 'h.id AS hotpotid,' . 'h.sourcefile AS sourcefile'; $from = '{hotpot} h,' . '{course_modules} cm,' . '{context} c,' . '{files} f'; $where = $DB->sql_like('h.sourcefile', '?', false, false, true) . ' AND h.id=cm.instance' . ' AND cm.id=c.instanceid' . ' AND c.id=f.contextid' . ' AND f.component=?' . ' AND f.filearea=?' . ' AND f.filepath=?' . ' AND f.filename=?'; $params = array('/course_files/%', 'mod_hotpot', 'sourcefile', '/course_files/', '.'); if ($filerecords = $DB->get_records_sql("SELECT {$select} FROM {$from} WHERE {$where}", $params)) { $fs = get_file_storage(); foreach ($filerecords as $filerecord) { $file = $fs->get_file_instance($filerecord); xmldb_hotpot_move_file($file, '/'); } } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080366; if ($oldversion < $newversion) { if ($hotpots = $DB->get_records_select('hotpot', $DB->sql_like('sourcefile', '?'), array('%http://localhost/19/99/%'))) { foreach ($hotpots as $hotpot) { $sourcefile = str_replace('http://localhost/19/99/', '', $hotpot->sourcefile); $DB->set_field('hotpot', 'sourcefile', $sourcefile, array('id' => $hotpot->id)); } } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2010080370; if ($oldversion < $newversion) { require_once $CFG->dirroot . '/mod/hotpot/locallib.php'; $reviewoptions = 0; list($times, $items) = hotpot::reviewoptions_times_items(); foreach ($times as $timename => $timevalue) { foreach ($items as $itemname => $itemvalue) { $reviewoptions += $timevalue & $itemvalue; } } // $reviewoptions should now be set to 62415 $DB->set_field('hotpot', 'reviewoptions', $reviewoptions); upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2013111685; if ($oldversion < $newversion) { $tables = array('hotpot' => array(new xmldb_field('allowpaste', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0', 'stoptext')), 'hotpot_cache' => array(new xmldb_field('hotpot_bodystyles', XMLDB_TYPE_CHAR, '8', null, XMLDB_NOTNULL, null, null, 'slasharguments'), new xmldb_field('sourcerepositoryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'sourcelocation'), new xmldb_field('configrepositoryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'configlocation'), new xmldb_field('allowpaste', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0', 'stoptext'))); foreach ($tables as $table => $fields) { $table = new xmldb_table($table); foreach ($fields as $field) { xmldb_hotpot_fix_previous_field($dbman, $table, $field); if ($dbman->field_exists($table, $field)) { $dbman->change_field_type($table, $field); } else { $dbman->add_field($table, $field); } } } upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2014011694; if ($oldversion < $newversion) { require_once $CFG->dirroot . '/mod/hotpot/lib.php'; hotpot_update_grades(); upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } $newversion = 2014042111; if ($oldversion < $newversion) { $empty_cache = true; upgrade_mod_savepoint(true, "{$newversion}", 'hotpot'); } if ($empty_cache) { $DB->delete_records('hotpot_cache'); } return true; }
/** * delete_attempts * * @param xxx $selected */ public function delete_attempts($selected, $onlymyattempts = true) { global $DB, $USER; if ($this->can_deleteallattempts()) { $userid = 0; // i.e. any user } else { if ($this->can_deletemyattempts()) { $userid = $USER->id; $onlymyattempts = true; } else { return; // user is not allowed to delete attempts } } if ($onlymyattempts) { // get attempts for this user only $this->get_attempts(); } else { // get attempts for any users $this->get_attempts($selected, $userid); } if (empty($selected) || !$this->attempts) { return; // nothing to do } $ids = array(); $userids = array(); foreach ($selected as $id => $delete) { if ($delete && array_key_exists($id, $this->attempts)) { $userid = $this->attempts[$id]->userid; if ($this->can_deleteallattempts() || $this->can_deletemyattempts() && $userid == $USER->id) { $ids[] = $id; $userids[$userid] = true; unset($this->attempts[$id]); } } } if (count($ids)) { $DB->delete_records_list('hotpot_attempts', 'id', $ids); $DB->delete_records_list('hotpot_details', 'attemptid', $ids); $DB->delete_records_list('hotpot_responses', 'attemptid', $ids); $userids = array_keys($userids); $stdclass = $this->to_stdclass(); foreach ($userids as $userid) { hotpot_update_grades($stdclass, $userid); } } }
/** * Update grades in central gradebook * * @param object $hotpot null means all hotpots * @param int $userid specific user only, 0 mean all */ function hotpot_update_grades($hotpot = null, $userid = 0, $nullifnone = true) { global $CFG; if (!function_exists('grade_update')) { //workaround for buggy PHP versions require_once $CFG->libdir . '/gradelib.php'; } if ($hotpot) { if ($grades = hotpot_get_user_grades($hotpot, $userid)) { hotpot_grade_item_update($hotpot, $grades); } else { if ($userid && $nullifnone) { $grade = new object(); $grade->userid = $userid; $grade->rawgrade = null; hotpot_grade_item_update($hotpot, $grade); } else { hotpot_grade_item_update($hotpot); } } } else { $sql = "SELECT h.*, cm.idnumber as cmidnumber\n FROM {$CFG->prefix}hotpot h, {$CFG->prefix}course_modules cm, {$CFG->prefix}modules m\n WHERE m.name='hotpot' AND m.id=cm.module AND cm.instance=s.id"; if ($rs = get_recordset_sql($sql)) { while ($hotpot = rs_fetch_next_record($rs)) { hotpot_update_grades($hotpot, 0, false); } rs_close($rs); } } }
/** * Update all grades in gradebook. * this function is called from db/upgrade.php * it iterates through the hotpots, calling hotpot_update_grades() to create a grade record for each hotpot * @global object */ function hotpot_upgrade_grades() { global $DB; // upgrade (=create) grades for all hotpots $sql = "\n SELECT COUNT('x')\n FROM {hotpot} h, {course_modules} cm, {modules} m\n WHERE m.name='hotpot' AND m.id=cm.module AND cm.instance=h.id"; $count = $DB->count_records_sql($sql); $sql = "\n SELECT h.*, cm.idnumber AS cmidnumber\n FROM {hotpot} h, {course_modules} cm, {modules} m\n WHERE m.name='hotpot' AND m.id=cm.module AND cm.instance=h.id"; if ($rs = $DB->get_recordset_sql($sql)) { // too much debug output $pbar = new progress_bar('hotpotupgradegrades', 500, true); $i = 0; foreach ($rs as $hotpot) { $i++; upgrade_set_timeout(60 * 5); // set up timeout, may also abort execution hotpot_update_grades($hotpot, 0, false); $pbar->update($i, $count, "Updating Hotpot grades ({$i}/{$count})."); } $rs->close(); } }
/** * Update hotpot grades in the gradebook * * Needed by grade_update_mod_grades() in lib/gradelib.php * * @param stdclass $hotpot instance object with extra cmidnumber and modname property * @param integer $userid >0 update grade of specific user only, 0 means all participants * @param boolean $nullifnone TRUE = force creation of NULL grade if this user has no grade * @return boolean TRUE if successful, FALSE otherwise * @return void */ function hotpot_update_grades($hotpot = null, $userid = 0, $nullifnone = true) { global $CFG, $DB; // get hotpot object require_once $CFG->dirroot . '/mod/hotpot/locallib.php'; if ($hotpot === null) { // update/create grades for all hotpots // set up sql strings $strupdating = get_string('updatinggrades', 'hotpot'); $select = 'h.*, cm.idnumber AS cmidnumber'; $from = '{hotpot} h, {course_modules} cm, {modules} m'; $where = 'h.id = cm.instance AND cm.module = m.id AND m.name = ?'; $params = array('hotpot'); // get previous record index (if any) if (!($config = $DB->get_record('config', array('name' => 'hotpot_update_grades')))) { $config = (object) array('id' => 0, 'name' => 'hotpot_update_grades', 'value' => '0'); } $i_min = intval($config->value); if ($i_max = $DB->count_records_sql("SELECT COUNT('x') FROM {$from} WHERE {$where}", $params)) { if ($rs = $DB->get_recordset_sql("SELECT {$select} FROM {$from} WHERE {$where}", $params)) { $bar = new progress_bar('hotpotupgradegrades', 500, true); $i = 0; foreach ($rs as $hotpot) { // update grade if ($i >= $i_min) { upgrade_set_timeout(); // apply for more time (3 mins) hotpot_update_grades($hotpot, $userid, $nullifnone); } // update progress bar $i++; $bar->update($i, $i_max, $strupdating . ": ({$i}/{$i_max})"); // update record index if ($i > $i_min) { $config->value = "{$i}"; if ($config->id) { $DB->update_record('config', $config); } else { $config->id = $DB->insert_record('config', $config); } } } $rs->close(); } } // delete the record index if ($config->id) { $DB->delete_records('config', array('id' => $config->id)); } return; // finish here } // sanity check on $hotpot->id if (!isset($hotpot->id)) { return false; } if ($hotpot->grademethod == hotpot::GRADEMETHOD_AVERAGE || $hotpot->gradeweighting < 100) { $precision = 1; } else { $precision = 0; } $weighting = $hotpot->gradeweighting / 100; // set the SQL string to determine the $grade switch ($hotpot->grademethod) { case hotpot::GRADEMETHOD_HIGHEST: $gradefield = "ROUND(MAX(score) * {$weighting}, {$precision}) AS grade"; break; case hotpot::GRADEMETHOD_AVERAGE: // the 'AVG' function skips abandoned quizzes, so use SUM(score)/COUNT(id) $gradefield = "ROUND(SUM(score)/COUNT(id) * {$weighting}, {$precision}) AS grade"; break; case hotpot::GRADEMETHOD_FIRST: $gradefield = "ROUND(score * {$weighting}, {$precision})"; $gradefield = $DB->sql_concat('timestart', "'_'", $gradefield); $gradefield = "MIN({$gradefield}) AS grade"; break; case hotpot::GRADEMETHOD_LAST: $gradefield = "ROUND(score * {$weighting}, {$precision})"; $gradefield = $DB->sql_concat('timestart', "'_'", $gradefield); $gradefield = "MAX({$gradefield}) AS grade"; break; default: return false; // shouldn't happen !! } $select = 'timefinish>0 AND hotpotid= ?'; $params = array($hotpot->id); if ($userid) { $select .= ' AND userid = ?'; $params[] = $userid; } $sql = "SELECT userid, {$gradefield} FROM {hotpot_attempts} WHERE {$select} GROUP BY userid"; $grades = array(); if ($hotpotgrades = $DB->get_records_sql_menu($sql, $params)) { foreach ($hotpotgrades as $hotpotuserid => $hotpotgrade) { if ($hotpot->grademethod == hotpot::GRADEMETHOD_FIRST || $hotpot->grademethod == hotpot::GRADEMETHOD_LAST) { // remove left hand characters in $gradefield (up to and including the underscore) $pos = strpos($hotpotgrade, '_') + 1; $hotpotgrade = substr($hotpotgrade, $pos); } $grades[$hotpotuserid] = (object) array('userid' => $hotpotuserid, 'rawgrade' => $hotpotgrade); } } if (count($grades)) { hotpot_grade_item_update($hotpot, $grades); } else { if ($userid && $nullifnone) { // no grades for this user, but we must force the creation of a "null" grade record hotpot_grade_item_update($hotpot, (object) array('userid' => $userid, 'rawgrade' => null)); } else { // no grades and no userid hotpot_grade_item_update($hotpot); } } }
/** * Update hotpot grades in the gradebook * * Needed by grade_update_mod_grades() in lib/gradelib.php * * @param stdclass $hotpot instance object with extra cmidnumber and modname property * @param integer $userid >0 update grade of specific user only, 0 means all participants * @param boolean $nullifnone TRUE = force creation of NULL grade if this user has no grade * @return boolean TRUE if successful, FALSE otherwise * @return void */ function hotpot_update_grades($hotpot = null, $userid = 0, $nullifnone = true) { global $CFG, $DB; // get hotpot object require_once $CFG->dirroot . '/mod/hotpot/locallib.php'; if ($hotpot === null) { // update/create grades for all hotpots // set up sql strings $strupdating = get_string('updatinggrades', 'mod_hotpot'); $select = 'h.*, cm.idnumber AS cmidnumber'; $from = '{hotpot} h, {course_modules} cm, {modules} m'; $where = 'h.id = cm.instance AND cm.module = m.id AND m.name = ?'; $params = array('hotpot'); // get previous record index (if any) $configname = 'update_grades'; $configvalue = get_config('mod_hotpot', $configname); if (is_numeric($configvalue)) { $i_min = intval($configvalue); } else { $i_min = 0; } if ($i_max = $DB->count_records_sql("SELECT COUNT('x') FROM {$from} WHERE {$where}", $params)) { if ($rs = $DB->get_recordset_sql("SELECT {$select} FROM {$from} WHERE {$where}", $params)) { if (defined('CLI_SCRIPT') && CLI_SCRIPT) { $bar = false; } else { $bar = new progress_bar('hotpotupgradegrades', 500, true); } $i = 0; foreach ($rs as $hotpot) { // update grade if ($i >= $i_min) { upgrade_set_timeout(); // apply for more time (3 mins) hotpot_update_grades($hotpot, $userid, $nullifnone); } // update progress bar $i++; if ($bar) { $bar->update($i, $i_max, $strupdating . ": ({$i}/{$i_max})"); } // update record index if ($i > $i_min) { set_config($configname, $i, 'mod_hotpot'); } } $rs->close(); } } // delete the record index unset_config($configname, 'mod_hotpot'); return; // finish here } // sanity check on $hotpot->id if (!isset($hotpot->id)) { return false; } $grades = hotpot_get_grades($hotpot, $userid); if (count($grades)) { hotpot_grade_item_update($hotpot, $grades); } else { if ($userid && $nullifnone) { // no grades for this user, but we must force the creation of a "null" grade record hotpot_grade_item_update($hotpot, (object) array('userid' => $userid, 'rawgrade' => null)); } else { // no grades and no userid hotpot_grade_item_update($hotpot); } } }