From: David Mudrak Date: Thu, 7 Jan 2010 20:57:58 +0000 (+0000) Subject: MDL-19937 workshop migration of Number of errors grading strategy and fixed some... X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=25e27d74614ca1b59b4f6effc17b203725c812ac;p=moodle.git MDL-19937 workshop migration of Number of errors grading strategy and fixed some forgotten todos --- diff --git a/mod/workshop/db/upgradelib.php b/mod/workshop/db/upgradelib.php index 37a6a1c092..323be61eb6 100644 --- a/mod/workshop/db/upgradelib.php +++ b/mod/workshop/db/upgradelib.php @@ -430,11 +430,8 @@ function workshop_upgrade_assessment_id_mappings() { /** * Returns the list of new element (dimension) ids * - * todo: this function is used in accumulative subtype. if it will not be used in any other subplugin, move it to the - * subplugin library - * * @param string $strategy the name of strategy subplugin that the element was migrated into - * @return array (int)workshopid => array (int)elementno => stdclass ->(int)newid ->(string)type + * @return array (int)workshopid => array (int)elementno => stdclass ->(int)newid {->(string)type} */ function workshop_upgrade_element_id_mappings($strategy) { global $DB; @@ -448,10 +445,12 @@ function workshop_upgrade_element_id_mappings($strategy) { } $info = new stdclass(); $info->newid = $old->newid; - if ($old->scale >= 0 and $old->scale <= 6) { - $info->type = 'scale'; - } else { - $info->type = 'value'; + if ($strategy == 'accumulative') { + if ($old->scale >= 0 and $old->scale <= 6) { + $info->type = 'scale'; + } else { + $info->type = 'value'; + } } $newids[$old->workshopid][$old->elementno] = $info; } diff --git a/mod/workshop/form/accumulative/db/install.php b/mod/workshop/form/accumulative/db/install.php index 78ae8df63f..1c36d6c9ab 100644 --- a/mod/workshop/form/accumulative/db/install.php +++ b/mod/workshop/form/accumulative/db/install.php @@ -28,7 +28,7 @@ * Post installation procedure */ function xmldb_workshopform_accumulative_install() { - global $DB; + global $CFG, $DB; require_once(dirname(__FILE__) . '/upgradelib.php'); // upgrade from old workshop 1.x if needed @@ -39,7 +39,7 @@ function xmldb_workshopform_accumulative_install() { * Post installation procedure recovery */ function xmldb_workshopform_accumulative_install_recovery() { - global $DB; + global $CFG, $DB; require_once(dirname(__FILE__) . '/upgradelib.php'); // continue upgrading from old workshop 1.x if needed diff --git a/mod/workshop/form/numerrors/db/install.php b/mod/workshop/form/numerrors/db/install.php new file mode 100644 index 0000000000..dfe33b81e3 --- /dev/null +++ b/mod/workshop/form/numerrors/db/install.php @@ -0,0 +1,47 @@ +. + +/** + * This file replaces the legacy STATEMENTS section in db/install.xml, + * lib.php/modulename_install() post installation hook and partially defaults.php + * + * @package workshopform_numerrors + * @copyright 2010 David Mudrak + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * Post installation procedure + */ +function xmldb_workshopform_numerrors_install() { + global $CFG, $DB; + require_once(dirname(__FILE__) . '/upgradelib.php'); + + // upgrade from old workshop 1.x if needed + workshopform_numerrors_upgrade_legacy(); +} + +/** + * Post installation procedure recovery + */ +function xmldb_workshopform_numerrors_install_recovery() { + global $CFG, $DB; + require_once(dirname(__FILE__) . '/upgradelib.php'); + + // continue upgrading from old workshop 1.x if needed + workshopform_numerrors_upgrade_legacy(); +} diff --git a/mod/workshop/form/numerrors/db/upgradelib.php b/mod/workshop/form/numerrors/db/upgradelib.php new file mode 100644 index 0000000000..9707cc4f22 --- /dev/null +++ b/mod/workshop/form/numerrors/db/upgradelib.php @@ -0,0 +1,185 @@ +. + +/** + * Functions used by some stages of number of errors grading upgrade + * + * @package workshopform_numerrors + * @copyright 2010 David Mudrak + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once($CFG->libdir.'/gradelib.php'); // grade_floatval() called here + +/** + * Check if there are some legacy workshop 1.x data to be migrated and upgrade them + * + * This must be called after workshop core migration has finished so that + * all assessments are already upgraded and tables are correctly renamed. + */ +function workshopform_numerrors_upgrade_legacy() { + global $CFG, $DB, $OUTPUT; + require_once($CFG->dirroot . '/mod/workshop/db/upgradelib.php'); + + if (!workshopform_numerrors_upgrade_legacy_needed()) { + return; + } + + // get the list of all legacy workshops using this grading strategy + if ($legacyworkshops = $DB->get_records('workshop_old', array('gradingstrategy' => 2), 'course,id', 'id')) { + echo $OUTPUT->notification('Copying assessment forms elements', 'notifysuccess'); + $legacyworkshops = array_keys($legacyworkshops); + // get some needed info about the workshops + $workshopinfos = $DB->get_records_list('workshop_old', 'id', $legacyworkshops, 'id', 'id,grade'); + // get the list of all accumulative form elements + list($workshopids, $params) = $DB->get_in_or_equal($legacyworkshops, SQL_PARAMS_NAMED); + $sql = "SELECT * + FROM {workshop_elements_old} + WHERE workshopid $workshopids + AND newid IS NULL"; + $rs = $DB->get_recordset_sql($sql, $params); + $newworkshopids = workshop_upgrade_workshop_id_mappings(); + $newelementids = array(); // (int)workshopid => array of (int)elementno => (int)newelementid + foreach ($rs as $old) { + // process the information about mapping + $newmapping = new stdclass(); + $newmapping->workshopid = $newworkshopids[$old->workshopid]; + $newmapping->nonegative = $old->elementno; + $newmapping->grade = $old->maxscore; + if ($old->maxscore > 0) { + $newmapping->grade = grade_floatval($old->maxscore / $workshopinfos[$old->workshopid]->grade * 100); + } else { + $newmapping->grade = 0; + } + $DB->delete_records('workshopform_numerrors_map', + array('workshopid' => $newmapping->workshopid, 'nonegative' => $newmapping->nonegative)); + $DB->insert_record('workshopform_numerrors_map', $newmapping); + // process the information about the element itself + if (trim($old->description) and $old->description <> '@@ GRADE_MAPPING_ELEMENT @@') { + $new = workshopform_numerrors_upgrade_element($old, $newworkshopids[$old->workshopid]); + $newid = $DB->insert_record('workshopform_numerrors', $new); + } else { + $newid = 0; + } + if (!isset($newelementids[$old->workshopid])) { + $newelementids[$old->workshopid] = array(); + } + $newelementids[$old->workshopid][$old->elementno] = $newid; + $DB->set_field('workshop_elements_old', 'newplugin', 'numerrors', array('id' => $old->id)); + $DB->set_field('workshop_elements_old', 'newid', $newid, array('id' => $old->id)); + + } + $rs->close(); + + // now we need to reload the legacy ids. Although we have them in $newelements after the first run, we must + // refetch them from DB so that this function can be called during recovery + $newelementids = workshop_upgrade_element_id_mappings('numerrors'); + + // migrate all grades for these elements (it est the values that reviewers put into forms) + $sql = "SELECT * + FROM {workshop_grades_old} + WHERE workshopid $workshopids + AND newid IS NULL"; + $rs = $DB->get_recordset_sql($sql, $params); + $newassessmentids = workshop_upgrade_assessment_id_mappings(); + foreach ($rs as $old) { + if (!isset($newelementids[$old->workshopid]) or !isset($newelementids[$old->workshopid][$old->elementno])) { + // orphaned grade - the assessment form element has been removed after the grade was recorded + continue; + } + $newelementinfo = $newelementids[$old->workshopid][$old->elementno]; + if ($newelementinfo->newid == 0 or $old->feedback == '@@ GRADE_ADJUSTMENT @@') { + // this is not a real grade - it was used just for mapping purposes + $DB->set_field('workshop_grades_old', 'newplugin', 'numerrors_map', array('id' => $old->id)); + $DB->set_field('workshop_grades_old', 'newid', 0, array('id' => $old->id)); + continue; + } + $new = workshopform_numerrors_upgrade_grade($old, $newassessmentids[$old->assessmentid], + $newelementids[$old->workshopid][$old->elementno]); + $newid = $DB->insert_record('workshop_grades', $new); + $DB->set_field('workshop_grades_old', 'newplugin', 'numerrors', array('id' => $old->id)); + $DB->set_field('workshop_grades_old', 'newid', $newid, array('id' => $old->id)); + } + $rs->close(); + } +} + +/** + * Transforms a given record from workshop_elements_old into an object to be saved into workshopform_numerrors + * + * @param stdclass $old legacy record from workshop_elements_old + * @param int $newworkshopid id of the new workshop instance that replaced the previous one + * @return stdclass to be saved in workshopform_numerrors + */ +function workshopform_numerrors_upgrade_element(stdclass $old, $newworkshopid) { + $new = new stdclass(); + $new->workshopid = $newworkshopid; + $new->sort = $old->elementno; + $new->description = $old->description; + $new->descriptionformat = FORMAT_HTML; + $new->grade0 = get_string('grade0default', 'workshopform_numerrors'); + $new->grade1 = get_string('grade1default', 'workshopform_numerrors'); + // calculate new weight of the element. Negative weights are not supported any more and + // are replaced with weight = 0. Legacy workshop did not store the raw weight but the index + // in the array of weights (see $WORKSHOP_EWEIGHTS in workshop 1.x) + // workshop 2.0 uses integer weights only (0-16) so all previous weights are multiplied by 4. + switch ($old->weight) { + case 8: $new->weight = 1; break; + case 9: $new->weight = 2; break; + case 10: $new->weight = 3; break; + case 11: $new->weight = 4; break; + case 12: $new->weight = 6; break; + case 13: $new->weight = 8; break; + case 14: $new->weight = 16; break; + default: $new->weight = 0; + } + return $new; +} + +/** + * Transforms given grade record + * + * @param stdclass $old + * @param int $newassessmentid + * @param stdclass $newdimensioninfo + * @return stdclass + */ +function workshopform_numerrors_upgrade_grade(stdclass $old, $newassessmentid, stdclass $newdimensioninfo) { + $new = new stdclass(); + $new->assessmentid = $newassessmentid; + $new->strategy = 'numerrors'; + $new->dimensionid = $newdimensioninfo->newid; + $new->grade = $old->grade; + $new->peercomment = $old->feedback; + $new->peercommentformat = FORMAT_HTML; + return $new; +} + +/** + * Check if the the migration from legacy workshop 1.9 is needed + * + * @return bool + */ +function workshopform_numerrors_upgrade_legacy_needed() { + global $CFG, $DB; + + $dbman = $DB->get_manager(); + if (!($dbman->table_exists('workshop_elements_old') and $dbman->table_exists('workshop_grades_old'))) { + return false; + } + return true; +} diff --git a/mod/workshop/form/numerrors/lib.php b/mod/workshop/form/numerrors/lib.php index 9ae5539239..612bd4545e 100644 --- a/mod/workshop/form/numerrors/lib.php +++ b/mod/workshop/form/numerrors/lib.php @@ -281,14 +281,46 @@ class workshop_numerrors_strategy implements workshop_strategy { * @see parent::get_assessments_recordset() */ public function get_assessments_recordset($restrict=null) { - // todo + global $DB; + + $sql = 'SELECT s.id AS submissionid, + a.id AS assessmentid, a.weight AS assessmentweight, a.reviewerid, a.gradinggrade, + g.dimensionid, g.grade + FROM {workshop_submissions} s + JOIN {workshop_assessments} a ON (a.submissionid = s.id) + JOIN {workshop_grades} g ON (g.assessmentid = a.id AND g.strategy = :strategy) + WHERE s.example=0 AND s.workshopid=:workshopid'; // to be cont. + $params = array('workshopid' => $this->workshop->id, 'strategy' => $this->workshop->strategy); + + if (is_null($restrict)) { + // update all users - no more conditions + } elseif (!empty($restrict)) { + list($usql, $uparams) = $DB->get_in_or_equal($restrict, SQL_PARAMS_NAMED); + $sql .= " AND a.reviewerid $usql"; + $params = array_merge($params, $uparams); + } else { + throw new coding_exception('Empty value is not a valid parameter here'); + } + + $sql .= ' ORDER BY s.id'; // this is important for bulk processing + + return $DB->get_recordset_sql($sql, $params); + } /** * @see parent::get_dimensions_info() */ public function get_dimensions_info() { - // todo + global $DB; + + $params = array('workshopid' => $this->workshop->id); + $dimrecords = $DB->get_records('workshopform_numerrors', array('workshopid' => $this->workshop->id), 'sort', 'id,weight'); + foreach ($dimrecords as $dimid => $dimrecord) { + $dimrecords[$dimid]->min = 0; + $dimrecords[$dimid]->max = 1; + } + return $dimrecords; } //////////////////////////////////////////////////////////////////////////////// @@ -426,7 +458,7 @@ class workshop_numerrors_strategy implements workshop_strategy { list($dimsql, $dimparams) = $DB->get_in_or_equal(array_keys($this->dimensions), SQL_PARAMS_NAMED); // beware! the caller may rely on the returned array is indexed by dimensionid $sql = "SELECT dimensionid, wg.* - FROM {workshop_grades} + FROM {workshop_grades} wg WHERE assessmentid = :assessmentid AND strategy= :strategy AND dimensionid $dimsql"; $params = array('assessmentid' => $assessment->id, 'strategy' => 'numerrors'); $params = array_merge($params, $dimparams);