From 477f1d2b781bf9aeb692ed12d742ec1b8cc04212 Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Thu, 23 Jun 2011 13:38:15 +0200 Subject: [PATCH 1/9] MDLQA-1147 Fixed a typo in the exception class name Thanks Steve Turley for spotting and reporting this during the QA. --- backup/util/helper/convert_helper.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backup/util/helper/convert_helper.class.php b/backup/util/helper/convert_helper.class.php index 7301b4bb915..539f4f832dc 100644 --- a/backup/util/helper/convert_helper.class.php +++ b/backup/util/helper/convert_helper.class.php @@ -89,7 +89,7 @@ abstract class convert_helper { $filepath = $dirpath . '/moodle_backup.xml'; if (!is_dir($dirpath)) { - throw new converter_helper_exception('tmp_backup_directory_not_found', $dirpath); + throw new convert_helper_exception('tmp_backup_directory_not_found', $dirpath); } if (!file_exists($filepath)) { From acc9a7b9e26b6e0694bea070aa7df273ba625d28 Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Tue, 28 Jun 2011 20:10:06 +0200 Subject: [PATCH 2/9] MDL-28006 moodle1 converter provides new get_stash_or_default() method --- backup/converter/moodle1/lib.php | 16 ++++++++++ .../converter/moodle1/simpletest/testlib.php | 32 +++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/backup/converter/moodle1/lib.php b/backup/converter/moodle1/lib.php index dcee200c6e4..aef888e44c6 100644 --- a/backup/converter/moodle1/lib.php +++ b/backup/converter/moodle1/lib.php @@ -470,6 +470,22 @@ class moodle1_converter extends base_converter { } } + /** + * Restores a given stash or returns the given default if there is no such stash + * + * @param string $stashname name of the stash + * @param int $itemid optional id for multiple infos within the same stashname + * @param mixed $default information to return if the info has not been stashed previously + * @return mixed stashed data or the default value + */ + public function get_stash_or_default($stashname, $itemid = 0, $default = null) { + try { + return $this->get_stash($stashname, $itemid); + } catch (moodle1_convert_empty_storage_exception $e) { + return $default; + } + } + /** * Returns the list of existing stashes * diff --git a/backup/converter/moodle1/simpletest/testlib.php b/backup/converter/moodle1/simpletest/testlib.php index 44634e9f018..addc174d124 100644 --- a/backup/converter/moodle1/simpletest/testlib.php +++ b/backup/converter/moodle1/simpletest/testlib.php @@ -160,6 +160,38 @@ class moodle1_converter_test extends UnitTestCase { $converter->drop_stash_storage(); } + public function test_get_stash_or_default() { + $converter = convert_factory::get_converter('moodle1', $this->tempdir); + $converter->create_stash_storage(); + + $this->assertTrue(is_null($converter->get_stash_or_default('stashname'))); + $this->assertTrue(is_null($converter->get_stash_or_default('stashname', 7))); + $this->assertTrue('default' === $converter->get_stash_or_default('stashname', 0, 'default')); + $this->assertTrue(array('foo', 'bar') === $converter->get_stash_or_default('stashname', 42, array('foo', 'bar'))); + + //$converter->set_stash('stashname', 0); + //$this->assertFalse(is_null($converter->get_stash_or_default('stashname'))); // todo returns true now, this needs MDL-27713 to be fixed + + //$converter->set_stash('stashname', ''); + //$this->assertFalse(is_null($converter->get_stash_or_default('stashname'))); // todo returns true now, this needs MDL-27713 to be fixed + + //$converter->set_stash('stashname', array()); + //$this->assertFalse(is_null($converter->get_stash_or_default('stashname'))); // todo returns true now, this needs MDL-27713 to be fixed + + $converter->set_stash('stashname', 42); + $this->assertTrue(42 === $converter->get_stash_or_default('stashname')); + $this->assertTrue(is_null($converter->get_stash_or_default('stashname', 1))); + $this->assertTrue(42 === $converter->get_stash_or_default('stashname', 0, 61)); + + $converter->set_stash('stashname', array(42 => (object)array('id' => 42)), 18); + $stashed = $converter->get_stash_or_default('stashname', 18, 1984); + $this->assertIsA($stashed, 'array'); + $this->assertTrue(is_object($stashed[42])); + $this->assertTrue($stashed[42]->id === 42); + + $converter->drop_stash_storage(); + } + public function test_get_contextid() { $converter = convert_factory::get_converter('moodle1', $this->tempdir); From 544e0d5972501b9c07dfde498a417ee9aaae3be8 Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Tue, 28 Jun 2011 21:31:18 +0200 Subject: [PATCH 3/9] MDL-28006 moodle1 converter supports activity module grade items --- backup/converter/moodle1/handlerlib.php | 65 +++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 4 deletions(-) diff --git a/backup/converter/moodle1/handlerlib.php b/backup/converter/moodle1/handlerlib.php index 5c15bc279cb..beee357e877 100644 --- a/backup/converter/moodle1/handlerlib.php +++ b/backup/converter/moodle1/handlerlib.php @@ -52,6 +52,7 @@ abstract class moodle1_handlers_factory { new moodle1_roles_definition_handler($converter), new moodle1_question_bank_handler($converter), new moodle1_scales_handler($converter), + new moodle1_gradebook_handler($converter), ); $handlers = array_merge($handlers, self::get_plugin_handlers('mod', $converter)); @@ -927,10 +928,22 @@ class moodle1_course_outline_handler extends moodle1_xml_handler { $this->write_xml('module', $cminfo, array('/module/id', '/module/version')); $this->close_xml_writer(); - // todo: write proper grades.xml and roles.xml, for now we just make - // sure that those files are present + // write grades.xml + $this->open_xml_writer($directory.'/grades.xml'); + $this->xmlwriter->begin_tag('activity_gradebook'); + $gradeitems = $this->converter->get_stash_or_default('modgradeitem_'.$modname, $modinstanceid, array()); + if (!empty($gradeitems)) { + $this->xmlwriter->begin_tag('grade_items'); + foreach ($gradeitems as $gradeitem) { + $this->write_xml('grade_item', $gradeitem, array('/grade_item/id')); + } + $this->xmlwriter->end_tag('grade_items'); + } + $this->xmlwriter->end_tag('activity_gradebook'); + $this->close_xml_writer(); + + // todo: write proper roles.xml, for now we just make sure the file is present $this->make_sure_xml_exists($directory.'/roles.xml', 'roles'); - $this->make_sure_xml_exists($directory.'/grades.xml', 'activity_gradebook'); } } } @@ -1319,7 +1332,7 @@ class moodle1_scales_handler extends moodle1_handler { protected $fileman = null; /** - * Registers path that are not qtype-specific + * Registers paths */ public function get_paths() { return array( @@ -1372,6 +1385,50 @@ class moodle1_scales_handler extends moodle1_handler { } +/** + * Handles the conversion of the gradebook structures in the moodle.xml file + */ +class moodle1_gradebook_handler extends moodle1_xml_handler { + + /** + * Registers paths + */ + public function get_paths() { + return array( + new convert_path('gradebook_grade_item', '/MOODLE_BACKUP/COURSE/GRADEBOOK/GRADE_ITEMS/GRADE_ITEM'), + ); + } + + /** + * Processes one GRADE_ITEM data + */ + public function process_gradebook_grade_item(array $data, array $raw) { + + // here we use get_nextid() to get a nondecreasing sequence + $data['sortorder'] = $this->converter->get_nextid(); + + if ($data['itemtype'] === 'mod') { + return $this->process_mod_grade_item($data, $raw); + } + } + + /** + * Processes one GRADE_ITEM of the type 'mod' + */ + protected function process_mod_grade_item(array $data, array $raw) { + + $stashname = 'modgradeitem_'.$data['itemmodule']; + $stashitemid = $data['iteminstance']; + $gradeitems = $this->converter->get_stash_or_default($stashname, $stashitemid, array()); + + // typically there will be single item with itemnumber 0 + $gradeitems[$data['itemnumber']] = $data; + + $this->converter->set_stash($stashname, $gradeitems, $stashitemid); + } +} + + /** * Shared base class for activity modules, blocks and qtype handlers */ From cfab209904966a4c741e3f9169819ca248f2c9d0 Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Wed, 29 Jun 2011 00:09:09 +0200 Subject: [PATCH 4/9] MDL-28006 moodle1 converter supports grade categories and non-module grade items --- backup/converter/moodle1/handlerlib.php | 151 +++++++++++++++++++++++- 1 file changed, 149 insertions(+), 2 deletions(-) diff --git a/backup/converter/moodle1/handlerlib.php b/backup/converter/moodle1/handlerlib.php index beee357e877..5724237561f 100644 --- a/backup/converter/moodle1/handlerlib.php +++ b/backup/converter/moodle1/handlerlib.php @@ -931,7 +931,7 @@ class moodle1_course_outline_handler extends moodle1_xml_handler { // write grades.xml $this->open_xml_writer($directory.'/grades.xml'); $this->xmlwriter->begin_tag('activity_gradebook'); - $gradeitems = $this->converter->get_stash_or_default('modgradeitem_'.$modname, $modinstanceid, array()); + $gradeitems = $this->converter->get_stash_or_default('gradebook_modgradeitem_'.$modname, $modinstanceid, array()); if (!empty($gradeitems)) { $this->xmlwriter->begin_tag('grade_items'); foreach ($gradeitems as $gradeitem) { @@ -1390,15 +1390,56 @@ class moodle1_scales_handler extends moodle1_handler { */ class moodle1_gradebook_handler extends moodle1_xml_handler { + /** @var array of (int)gradecategoryid => (int|null)parentcategoryid */ + protected $categoryparent = array(); + /** * Registers paths */ public function get_paths() { return array( + new convert_path('gradebook', '/MOODLE_BACKUP/COURSE/GRADEBOOK'), + new convert_path( + 'gradebook_grade_category', '/MOODLE_BACKUP/COURSE/GRADEBOOK/GRADE_CATEGORIES/GRADE_CATEGORY', + array( + 'addfields' => array( + 'hidden' => 0, // upgrade step 2010011200 + ), + ) + ), new convert_path('gradebook_grade_item', '/MOODLE_BACKUP/COURSE/GRADEBOOK/GRADE_ITEMS/GRADE_ITEM'), ); } + /** + * Initializes the in-memory structures + * + * This should not be needed actually as the moodle.xml contains just one GRADEBOOK + * element. But who knows - maybe someone will want to write a mass conversion + * tool in the future (not me definitely ;-) + */ + public function on_gradebook_start() { + $this->categoryparent = array(); + } + + /** + * Processes one GRADE_LETTER data + * + * In Moodle 1.9, all grade_letters are from course context only. Therefore + * we put them here. + */ + public function process_gradebook_grade_letter(array $data, array $raw) { + $this->converter->set_stash('gradebook_gradeletter', $data, $data['id']); + } + + /** + * Processes one GRADE_CATEGORY data + */ + public function process_gradebook_grade_category(array $data, array $raw) { + $this->categoryparent[$data['id']] = $data['parent']; + $this->converter->set_stash('gradebook_gradecategory', $data, $data['id']); + } + /** * Processes one GRADE_ITEM data */ @@ -1409,6 +1450,12 @@ class moodle1_gradebook_handler extends moodle1_xml_handler { if ($data['itemtype'] === 'mod') { return $this->process_mod_grade_item($data, $raw); + + } else if (in_array($data['itemtype'], array('manual', 'course', 'category'))) { + return $this->process_nonmod_grade_item($data, $raw); + + } else { + $this->log('unsupported grade_item type', backup::LOG_ERROR, $data['itemtype']); } } @@ -1417,7 +1464,7 @@ class moodle1_gradebook_handler extends moodle1_xml_handler { */ protected function process_mod_grade_item(array $data, array $raw) { - $stashname = 'modgradeitem_'.$data['itemmodule']; + $stashname = 'gradebook_modgradeitem_'.$data['itemmodule']; $stashitemid = $data['iteminstance']; $gradeitems = $this->converter->get_stash_or_default($stashname, $stashitemid, array()); @@ -1425,6 +1472,106 @@ class moodle1_gradebook_handler extends moodle1_xml_handler { $gradeitems[$data['itemnumber']] = $data; $this->converter->set_stash($stashname, $gradeitems, $stashitemid); + + return $data; + } + + /** + * Processes one GRADE_ITEM of te type 'manual' or 'course' or 'category' + */ + protected function process_nonmod_grade_item(array $data, array $raw) { + + $stashname = 'gradebook_nonmodgradeitem'; + $stashitemid = $data['id']; + $this->converter->set_stash($stashname, $data, $stashitemid); + + return $data; + } + + /** + * Writes the collected information into gradebook.xml + */ + public function on_gradebook_end() { + + $this->open_xml_writer('gradebook.xml'); + $this->xmlwriter->begin_tag('gradebook'); + $this->write_grade_categories(); + $this->write_grade_items(); + $this->write_grade_letters(); + $this->write_grade_settings(); + $this->xmlwriter->end_tag('gradebook'); + $this->close_xml_writer(); + } + + /** + * Writes grade_categories + */ + protected function write_grade_categories() { + + $this->xmlwriter->begin_tag('grade_categories'); + foreach ($this->converter->get_stash_itemids('gradebook_gradecategory') as $gradecategoryid) { + $gradecategory = $this->converter->get_stash('gradebook_gradecategory', $gradecategoryid); + $path = $this->calculate_category_path($gradecategoryid); + $gradecategory['depth'] = count($path); + $gradecategory['path'] = '/'.implode('/', $path).'/'; + $this->write_xml('grade_category', $gradecategory, array('/grade_category/id')); + } + $this->xmlwriter->end_tag('grade_categories'); + } + + /** + * Calculates the path to the grade_category + * + * Moodle 1.9 backup does not store the grade_category's depth and path. This method is used + * to repopulate this information using the $this->categoryparent values. + * + * @param int $categoryid + * @return array of ids including the categoryid + */ + protected function calculate_category_path($categoryid) { + + if (!array_key_exists($categoryid, $this->categoryparent)) { + throw new moodle1_convert_exception('gradebook_unknown_categoryid', null, $categoryid); + } + + $path = array($categoryid); + $parent = $this->categoryparent[$categoryid]; + while (!is_null($parent)) { + array_unshift($path, $parent); + $parent = $this->categoryparent[$parent]; + if (in_array($parent, $path)) { + throw new moodle1_convert_exception('circular_reference_in_categories_tree'); + } + } + + return $path; + } + + /** + * Writes grade_items + */ + protected function write_grade_items() { + + $this->xmlwriter->begin_tag('grade_items'); + foreach ($this->converter->get_stash_itemids('gradebook_nonmodgradeitem') as $gradeitemid) { + $gradeitem = $this->converter->get_stash('gradebook_nonmodgradeitem', $gradeitemid); + $this->write_xml('grade_item', $gradeitem, array('/grade_item/id')); + } + $this->xmlwriter->end_tag('grade_items'); + } + + /** + * Writes grade_letters + */ + protected function write_grade_letters() { + // todo + } + + /** + * Writes grade_settings + */ + protected function write_grade_settings() { + // todo } } From d98100e4078fecc554e45d6710db3c781873e45f Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Wed, 29 Jun 2011 00:55:29 +0200 Subject: [PATCH 5/9] MDL-28006 moodle1 converter supports grade letters --- backup/converter/moodle1/handlerlib.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/backup/converter/moodle1/handlerlib.php b/backup/converter/moodle1/handlerlib.php index 5724237561f..be730cf5ebd 100644 --- a/backup/converter/moodle1/handlerlib.php +++ b/backup/converter/moodle1/handlerlib.php @@ -939,6 +939,7 @@ class moodle1_course_outline_handler extends moodle1_xml_handler { } $this->xmlwriter->end_tag('grade_items'); } + $this->write_xml('grade_letters', array()); // no grade_letters in module context in Moodle 1.9 $this->xmlwriter->end_tag('activity_gradebook'); $this->close_xml_writer(); @@ -1399,6 +1400,7 @@ class moodle1_gradebook_handler extends moodle1_xml_handler { public function get_paths() { return array( new convert_path('gradebook', '/MOODLE_BACKUP/COURSE/GRADEBOOK'), + new convert_path('gradebook_grade_letter', '/MOODLE_BACKUP/COURSE/GRADEBOOK/GRADE_LETTERS/GRADE_LETTER'), new convert_path( 'gradebook_grade_category', '/MOODLE_BACKUP/COURSE/GRADEBOOK/GRADE_CATEGORIES/GRADE_CATEGORY', array( @@ -1564,7 +1566,13 @@ class moodle1_gradebook_handler extends moodle1_xml_handler { * Writes grade_letters */ protected function write_grade_letters() { - // todo + + $this->xmlwriter->begin_tag('grade_letters'); + foreach ($this->converter->get_stash_itemids('gradebook_gradeletter') as $gradeletterid) { + $gradeletter = $this->converter->get_stash('gradebook_gradeletter', $gradeletterid); + $this->write_xml('grade_letter', $gradeletter, array('/grade_letter/id')); + } + $this->xmlwriter->end_tag('grade_letters'); } /** From ddefec8d14c24dd4dc3d09b8be5a152467992159 Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Wed, 29 Jun 2011 08:55:43 +0200 Subject: [PATCH 6/9] MDL-28006 moodle1 converter supports outcomes --- backup/converter/moodle1/handlerlib.php | 70 +++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/backup/converter/moodle1/handlerlib.php b/backup/converter/moodle1/handlerlib.php index be730cf5ebd..556760e2c9b 100644 --- a/backup/converter/moodle1/handlerlib.php +++ b/backup/converter/moodle1/handlerlib.php @@ -52,6 +52,7 @@ abstract class moodle1_handlers_factory { new moodle1_roles_definition_handler($converter), new moodle1_question_bank_handler($converter), new moodle1_scales_handler($converter), + new moodle1_outcomes_handler($converter), new moodle1_gradebook_handler($converter), ); @@ -1386,6 +1387,75 @@ class moodle1_scales_handler extends moodle1_handler { } +/** + * Handles the conversion of the outcomes + */ +class moodle1_outcomes_handler extends moodle1_xml_handler { + + /** @var moodle1_file_manager instance used to convert images embedded into outcome descriptions */ + protected $fileman = null; + + /** + * Registers paths + */ + public function get_paths() { + return array( + new convert_path('gradebook_grade_outcomes', '/MOODLE_BACKUP/COURSE/GRADEBOOK/GRADE_OUTCOMES'), + new convert_path( + 'gradebook_grade_outcome', '/MOODLE_BACKUP/COURSE/GRADEBOOK/GRADE_OUTCOMES/GRADE_OUTCOME', + array( + 'addfields' => array( + 'descriptionformat' => FORMAT_MOODLE, + ), + ) + ), + ); + } + + /** + * Prepares the file manager and starts writing outcomes.xml + */ + public function on_gradebook_grade_outcomes_start() { + + $syscontextid = $this->converter->get_contextid(CONTEXT_SYSTEM); + $this->fileman = $this->converter->get_file_manager($syscontextid, 'grade', 'outcome'); + + $this->open_xml_writer('outcomes.xml'); + $this->xmlwriter->begin_tag('outcomes_definition'); + } + + /** + * Processes GRADE_OUTCOME tags progressively + */ + public function process_gradebook_grade_outcome(array $data, array $raw) { + global $CFG; + + // replay the upgrade step 2009110400 + if ($CFG->texteditors !== 'textarea') { + $data['description'] = text_to_html($data['description'], false, false, true); + $data['descriptionformat'] = FORMAT_HTML; + } + + // convert course files embedded into the outcome description field + $this->fileman->itemid = $data['id']; + $data['description'] = moodle1_converter::migrate_referenced_files($data['description'], $this->fileman); + + // write the outcome data + $this->write_xml('outcome', $data, array('/outcome/id')); + + return $data; + } + + /** + * Closes outcomes.xml + */ + public function on_gradebook_grade_outcomes_end() { + $this->xmlwriter->end_tag('outcomes_definition'); + $this->close_xml_writer(); + } +} + + /** * Handles the conversion of the gradebook structures in the moodle.xml file */ From af66e7fea30783483090cd60d352f09ab7843add Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Wed, 29 Jun 2011 09:08:25 +0200 Subject: [PATCH 7/9] MDL-28006 code cleanup - there is nothing to do for grade_settings --- backup/converter/moodle1/handlerlib.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/backup/converter/moodle1/handlerlib.php b/backup/converter/moodle1/handlerlib.php index 556760e2c9b..1b3b39bc0f8 100644 --- a/backup/converter/moodle1/handlerlib.php +++ b/backup/converter/moodle1/handlerlib.php @@ -1570,7 +1570,6 @@ class moodle1_gradebook_handler extends moodle1_xml_handler { $this->write_grade_categories(); $this->write_grade_items(); $this->write_grade_letters(); - $this->write_grade_settings(); $this->xmlwriter->end_tag('gradebook'); $this->close_xml_writer(); } @@ -1644,13 +1643,6 @@ class moodle1_gradebook_handler extends moodle1_xml_handler { } $this->xmlwriter->end_tag('grade_letters'); } - - /** - * Writes grade_settings - */ - protected function write_grade_settings() { - // todo - } } From 3343677e0a7b629ecc8ba2d423fb7394fbf782ae Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Thu, 30 Jun 2011 15:17:03 +0200 Subject: [PATCH 8/9] MDL-28006 Fixed grades subpath handling Registering the grades subpath even if we do not process the grades yet. This is to prevent from incorrect considering the wrapper as an empty tag. --- backup/converter/moodle1/handlerlib.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/backup/converter/moodle1/handlerlib.php b/backup/converter/moodle1/handlerlib.php index 1b3b39bc0f8..dc10857a91f 100644 --- a/backup/converter/moodle1/handlerlib.php +++ b/backup/converter/moodle1/handlerlib.php @@ -1480,6 +1480,7 @@ class moodle1_gradebook_handler extends moodle1_xml_handler { ) ), new convert_path('gradebook_grade_item', '/MOODLE_BACKUP/COURSE/GRADEBOOK/GRADE_ITEMS/GRADE_ITEM'), + new convert_path('gradebook_grade_item_grades', '/MOODLE_BACKUP/COURSE/GRADEBOOK/GRADE_ITEMS/GRADE_ITEM/GRADE_GRADES'), ); } @@ -1560,6 +1561,12 @@ class moodle1_gradebook_handler extends moodle1_xml_handler { return $data; } + /** + * @todo + */ + public function on_gradebook_grade_item_grades_start() { + } + /** * Writes the collected information into gradebook.xml */ From d46badb176703faa9cd7a16674dae8913a468092 Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Thu, 30 Jun 2011 22:40:54 +0200 Subject: [PATCH 9/9] MDL-28006 restore - improved handling of gradebook 1.9 backups On contrary from a backup created in 2.0, the file gradebook.xml in the converted MBZ can contain the course grade_item without the corresponding grade_category record which is something restore_stepslib did not expect. This patch fixes two places: 1) the gradebook restore does not use mapped itemid but calls grade_category::fetch_course_category() to get the actual category to link the course_item with 2) after_execute makes sure that the mapping actually exists before trying to move the activities from the default root category --- backup/moodle2/restore_stepslib.php | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/backup/moodle2/restore_stepslib.php b/backup/moodle2/restore_stepslib.php index 6178a04c790..d070e316c24 100644 --- a/backup/moodle2/restore_stepslib.php +++ b/backup/moodle2/restore_stepslib.php @@ -146,12 +146,18 @@ class restore_gradebook_structure_step extends restore_structure_step { $data->courseid = $this->get_courseid(); - //manual grade items store category id in categoryid if ($data->itemtype=='manual') { + // manual grade items store category id in categoryid $data->categoryid = $this->get_mappingid('grade_category', $data->categoryid, NULL); - } //course and category grade items store their category id in iteminstance - else if ($data->itemtype=='course' || $data->itemtype=='category') { + } else if ($data->itemtype=='course') { + // course grade item stores their category id in iteminstance + $coursecat = grade_category::fetch_course_category($this->get_courseid()); + $data->iteminstance = $coursecat->id; + } else if ($data->itemtype=='category') { + // category grade items store their category id in iteminstance $data->iteminstance = $this->get_mappingid('grade_category', $data->iteminstance, NULL); + } else { + throw new restore_step_exception('unexpected_grade_item_type', $data->itemtype); } $data->scaleid = $this->get_mappingid('scale', $data->scaleid, NULL); @@ -291,12 +297,16 @@ class restore_gradebook_structure_step extends restore_structure_step { //if this is an activity grade item that needs to be put back in its correct category if (!empty($grade_item_backup->parentitemid)) { - $updateobj->categoryid = $this->get_mappingid('grade_category', $grade_item_backup->parentitemid); + $oldcategoryid = $this->get_mappingid('grade_category', $grade_item_backup->parentitemid, null); + if (!is_null($oldcategoryid)) { + $updateobj->categoryid = $oldcategoryid; + $DB->update_record('grade_items', $updateobj); + } } else { //mark course and category items as needing to be recalculated $updateobj->needsupdate=1; + $DB->update_record('grade_items', $updateobj); } - $DB->update_record('grade_items', $updateobj); } } $rs->close();