From 9ec63757d7a121a505882a5f53b232d27e6b8598 Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Mon, 4 Jan 2010 18:33:23 +0000 Subject: [PATCH] MDL-19937 migration of form elements and grades - accumulation grading strategy --- mod/workshop/db/upgradelib.php | 53 ++- mod/workshop/form/accumulative/db/install.php | 47 +++ .../form/accumulative/db/upgradelib.php | 316 ++++++++++++++++++ .../en_utf8/workshopform_accumulative.php | 15 + 4 files changed, 429 insertions(+), 2 deletions(-) create mode 100644 mod/workshop/form/accumulative/db/install.php create mode 100644 mod/workshop/form/accumulative/db/upgradelib.php diff --git a/mod/workshop/db/upgradelib.php b/mod/workshop/db/upgradelib.php index 787204085a..37a6a1c092 100644 --- a/mod/workshop/db/upgradelib.php +++ b/mod/workshop/db/upgradelib.php @@ -149,7 +149,7 @@ function workshop_upgrade_prepare_20_tables() { * @return void */ function workshop_upgrade_module_instances() { - global $CFG, $DB, $OUTPUT; + global $CFG, $DB; upgrade_set_timeout(); $moduleid = $DB->get_field('modules', 'id', array('name' => 'workshop'), MUST_EXIST); @@ -238,7 +238,7 @@ function workshop_upgrade_workshop_id_mappings() { * @return void */ function workshop_upgrade_submissions() { - global $CFG, $DB, $OUTPUT; + global $CFG, $DB; upgrade_set_timeout(); $newworkshopids = workshop_upgrade_workshop_id_mappings(); @@ -408,3 +408,52 @@ function workshop_upgrade_transform_assessment(stdClass $old, $newsubmissionid, return $new; } + +/** + * Returns the list of new assessment ids + * + * @return array (int)oldid => (int)newid + */ +function workshop_upgrade_assessment_id_mappings() { + global $DB; + + $oldrecords = $DB->get_records('workshop_assessments_old', null, 'id', 'id,newid'); + $newids = array(); + foreach ($oldrecords as $oldid => $oldrecord) { + if ($oldrecord->id and $oldrecord->newid) { + $newids[$oldid] = $oldrecord->newid; + } + } + return $newids; +} + +/** + * 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 + */ +function workshop_upgrade_element_id_mappings($strategy) { + global $DB; + + $oldrecords = $DB->get_records('workshop_elements_old', array('newplugin' => $strategy), + 'workshopid,elementno', 'id,workshopid,elementno,scale,newid'); + $newids = array(); + foreach ($oldrecords as $old) { + if (!isset($newids[$old->workshopid])) { + $newids[$old->workshopid] = array(); + } + $info = new stdclass(); + $info->newid = $old->newid; + if ($old->scale >= 0 and $old->scale <= 6) { + $info->type = 'scale'; + } else { + $info->type = 'value'; + } + $newids[$old->workshopid][$old->elementno] = $info; + } + return $newids; +} diff --git a/mod/workshop/form/accumulative/db/install.php b/mod/workshop/form/accumulative/db/install.php new file mode 100644 index 0000000000..259c399705 --- /dev/null +++ b/mod/workshop/form/accumulative/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 mod-workshop + * @copyright 2009 David Mudrak + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * Post installation procedure + */ +function xmldb_workshopform_accumulative_install() { + global $DB; + require_once(dirname(__FILE__) . '/upgradelib.php'); + + // upgrade from old workshop 1.x if needed + workshopform_allocation_upgrade_legacy(); +} + +/** + * Post installation procedure recovery + */ +function xmldb_workshopform_accumulative_install_recovery() { + global $DB; + require_once(dirname(__FILE__) . '/upgradelib.php'); + + // continue upgrading from old workshop 1.x if needed + workshopform_allocation_upgrade_legacy(); +} diff --git a/mod/workshop/form/accumulative/db/upgradelib.php b/mod/workshop/form/accumulative/db/upgradelib.php new file mode 100644 index 0000000000..ce9d34847c --- /dev/null +++ b/mod/workshop/form/accumulative/db/upgradelib.php @@ -0,0 +1,316 @@ +. + +/** + * Functions used by some stages of accumulative grading upgrade + * + * @package mod-workshopform-accumulative + * @copyright 2009 David Mudrak + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * 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_allocation_upgrade_legacy() { + global $CFG, $DB, $OUTPUT; + require_once($CFG->dirroot . '/mod/workshop/db/upgradelib.php'); + + if (!workshopform_allocation_upgrade_legacy_needed()) { + return; + } + + // get the list of all legacy workshops using this grading strategy + if ($legacyworkshops = $DB->get_records('workshop_old', array('gradingstrategy' => 1), 'course,id', 'id')) { + echo $OUTPUT->notification('Copying assessment forms elements', 'notifysuccess'); + $legacyworkshops = array_keys($legacyworkshops); + // 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 + // prepare system (global) scales to replace the legacy in-built ones + $newscaleids = workshopform_allocation_upgrade_scales(); + foreach ($rs as $old) { + $new = workshopform_allocation_upgrade_element($old, $newscaleids, $newworkshopids[$old->workshopid]); + $newid = $DB->insert_record('workshopform_accumulative', $new); + if (!isset($newelementids[$old->workshopid])) { + $newelementids[$old->workshopid] = array(); + } + $newelementids[$old->workshopid][$old->elementno] = $newid; + $DB->set_field('workshop_elements_old', 'newplugin', 'accumulative', 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('accumulative'); + + // 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; + } + $new = workshopform_allocation_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', 'accumulative', 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_accumulative + * + * @param stdclass $old legacy record from workshop_elements_old + * @param array $newscaleids mapping from old scale types into new standard ones + * @param int $newworkshopid id of the new workshop instance that replaced the previous one + * @return stdclass to be saved in workshopform_accumulative + */ +function workshopform_allocation_upgrade_element(stdclass $old, array $newscaleids, $newworkshopid) { + $new = new stdclass(); + $new->workshopid = $newworkshopid; + $new->sort = $old->elementno; + $new->description = $old->description; + $new->descriptionformat = FORMAT_HTML; + // calculate new grade/scale of the element + if ($old->scale >= 0 and $old->scale <= 6 and isset($newscaleids[$old->scale])) { + $new->grade = -$newscaleids[$old->scale]; + } elseif ($old->scale == 7) { + $new->grade = 10; + } elseif ($old->scale == 8) { + $new->grade = 20; + } elseif ($old->scale == 9) { + $new->grade = 100; + } else { + $new->grade = 0; // something is wrong + } + // 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_allocation_upgrade_grade(stdclass $old, $newassessmentid, stdclass $newdimensioninfo) { + $new = new stdclass(); + $new->assessmentid = $newassessmentid; + $new->strategy = 'accumulative'; + $new->dimensionid = $newdimensioninfo->newid; + if ($newdimensioninfo->type == 'value') { + $new->grade = $old->grade; + } elseif ($newdimensioninfo->type == 'scale') { + // in workshop 1.x, scale items are numbered starting from 0 but Moodle in-built scales start numbering from 1 + $new->grade = $old->grade + 1; + } + $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_allocation_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; +} + +/** + * Creates new standard (global) scales to replace the legacy workshop ones + * + * In workshop 1.x, scale field in workshop_elements had the following meaning: + * 0 | 2 point Yes/No scale + * 1 | 2 point Present/Absent scale + * 2 | 2 point Correct/Incorrect scale + * 3 | 3 point Good/Poor scale + * 4 | 4 point Excellent/Very Poor scale + * 5 | 5 point Excellent/Very Poor scale + * 6 | 7 point Excellent/Very Poor scale + * 7 | Score out of 10 + * 8 | Score out of 20 + * 9 | Score out of 100 + * + * @return array (int)oldscale => (int)newscaleid + */ +function workshopform_allocation_upgrade_scales() { + global $DB, $CFG, $USER; + require_once($CFG->libdir . '/gradelib.php'); + + $sql = 'SELECT DISTINCT scale + FROM {workshop_elements_old} + WHERE newplugin IS NULL'; + $oldscales = $DB->get_records_sql($sql); + $newscales = array(); + foreach($oldscales as $oldscale => $whatever) { + switch ($oldscale) { + case 0: + $data = new stdclass(); + $data->courseid = 0; + $data->userid = $USER->id; + $data->name = get_string('scalename0', 'workshopform_accumulative'); + $data->scale = implode(',', array(get_string('no'), get_string('yes'))); + $data->description = ''; + $data->descriptionformat = FORMAT_HTML; + + $scale = new grade_scale(); + grade_scale::set_properties($scale, $data); + $newscales[0] = $scale->insert('mod/workshop'); + break; + case 1: + $data = new stdclass(); + $data->courseid = 0; + $data->userid = $USER->id; + $data->name = get_string('scalename1', 'workshopform_accumulative'); + $data->scale = implode(',', array(get_string('absent', 'workshopform_accumulative'), + get_string('present', 'workshopform_accumulative'))); + $data->description = ''; + $data->descriptionformat = FORMAT_HTML; + + $scale = new grade_scale(); + grade_scale::set_properties($scale, $data); + $newscales[1] = $scale->insert('mod/workshop'); + break; + case 2: + $data = new stdclass(); + $data->courseid = 0; + $data->userid = $USER->id; + $data->name = get_string('scalename2', 'workshopform_accumulative'); + $data->scale = implode(',', array(get_string('incorrect', 'workshopform_accumulative'), + get_string('correct', 'workshopform_accumulative'))); + $data->description = ''; + $data->descriptionformat = FORMAT_HTML; + + $scale = new grade_scale(); + grade_scale::set_properties($scale, $data); + $newscales[2] = $scale->insert('mod/workshop'); + break; + case 3: + $data = new stdclass(); + $data->courseid = 0; + $data->userid = $USER->id; + $data->name = get_string('scalename3', 'workshopform_accumulative'); + $data->scale = implode(',', array('* ' . get_string('poor', 'workshopform_accumulative'), + '**', + '*** ' . get_string('good', 'workshopform_accumulative'))); + $data->description = ''; + $data->descriptionformat = FORMAT_HTML; + + $scale = new grade_scale(); + grade_scale::set_properties($scale, $data); + $newscales[3] = $scale->insert('mod/workshop'); + break; + case 4: + $data = new stdclass(); + $data->courseid = 0; + $data->userid = $USER->id; + $data->name = get_string('scalename4', 'workshopform_accumulative'); + $data->scale = implode(',', array('* ' . get_string('verypoor', 'workshopform_accumulative'), + '**', + '***', + '**** ' . get_string('excellent', 'workshopform_accumulative'))); + $data->description = ''; + $data->descriptionformat = FORMAT_HTML; + + $scale = new grade_scale(); + grade_scale::set_properties($scale, $data); + $newscales[4] = $scale->insert('mod/workshop'); + break; + case 5: + $data = new stdclass(); + $data->courseid = 0; + $data->userid = $USER->id; + $data->name = get_string('scalename5', 'workshopform_accumulative'); + $data->scale = implode(',', array('* ' . get_string('verypoor', 'workshopform_accumulative'), + '**', + '***', + '****', + '***** ' . get_string('excellent', 'workshopform_accumulative'))); + $data->description = ''; + $data->descriptionformat = FORMAT_HTML; + + $scale = new grade_scale(); + grade_scale::set_properties($scale, $data); + $newscales[5] = $scale->insert('mod/workshop'); + break; + case 6: + $data = new stdclass(); + $data->courseid = 0; + $data->userid = $USER->id; + $data->name = get_string('scalename6', 'workshopform_accumulative'); + $data->scale = implode(',', array('* ' . get_string('verypoor', 'workshopform_accumulative'), + '**', + '***', + '****', + '*****', + '******', + '******* ' . get_string('excellent', 'workshopform_accumulative'))); + $data->description = ''; + $data->descriptionformat = FORMAT_HTML; + + $scale = new grade_scale(); + grade_scale::set_properties($scale, $data); + $newscales[6] = $scale->insert('mod/workshop'); + break; + } + } + + return $newscales; +} diff --git a/mod/workshop/form/accumulative/lang/en_utf8/workshopform_accumulative.php b/mod/workshop/form/accumulative/lang/en_utf8/workshopform_accumulative.php index 7dbcd96f6e..de06c94c3a 100644 --- a/mod/workshop/form/accumulative/lang/en_utf8/workshopform_accumulative.php +++ b/mod/workshop/form/accumulative/lang/en_utf8/workshopform_accumulative.php @@ -25,11 +25,26 @@ defined('MOODLE_INTERNAL') || die(); +$string['absent'] = 'Absent'; $string['addmoredimensions'] = 'Blanks for $a more aspects'; +$string['correct'] = 'Correct'; $string['dimensioncomment'] = 'Comment'; $string['dimensiondescription'] = 'Description'; $string['dimensiongrade'] = 'Grade'; $string['dimensionmaxgrade'] = 'Best possible grade / Scale to use'; $string['dimensionnumber'] = 'Aspect $a'; $string['dimensionweight'] = 'Weight'; +$string['excellent'] = 'Excellent'; +$string['good'] = 'Good'; +$string['incorrect'] = 'Incorrect'; $string['pluginname'] = 'Accumulative grading'; +$string['poor'] = 'Poor'; +$string['present'] = 'Present'; +$string['scalename0'] = 'Yes/No (2 point)'; +$string['scalename1'] = 'Present/Absent (2 point)'; +$string['scalename2'] = 'Correct/Incorrect (2 point)'; +$string['scalename3'] = 'Good/Poor (3 point)'; +$string['scalename4'] = 'Excellent/Very poor (4 point)'; +$string['scalename5'] = 'Excellent/Very poor (5 point)'; +$string['scalename6'] = 'Excellent/Very poor (7 point)'; +$string['verypoor'] = 'Very poor'; -- 2.39.5