Skip to content

Commit

Permalink
Merge branch 'MDL-28006-convert-gradebook' of git://github.com/mudrd8…
Browse files Browse the repository at this point in the history
…mz/moodle
  • Loading branch information
stronk7 committed Jun 30, 2011
2 parents b1273d0 + d46badb commit 7ace3a2
Show file tree
Hide file tree
Showing 5 changed files with 349 additions and 10 deletions.
289 changes: 285 additions & 4 deletions backup/converter/moodle1/handlerlib.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ public static function get_handlers(moodle1_converter $converter) {
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),
);

$handlers = array_merge($handlers, self::get_plugin_handlers('mod', $converter));
Expand Down Expand Up @@ -927,10 +929,23 @@ public function on_course_modules_end() {
$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('gradebook_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->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();

// 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');
}
}
}
Expand Down Expand Up @@ -1319,7 +1334,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(
Expand Down Expand Up @@ -1372,6 +1387,272 @@ public function process_scale(array $data, array $raw) {
}


/**
* 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
*/
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_letter', '/MOODLE_BACKUP/COURSE/GRADEBOOK/GRADE_LETTERS/GRADE_LETTER'),
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'),
new convert_path('gradebook_grade_item_grades', '/MOODLE_BACKUP/COURSE/GRADEBOOK/GRADE_ITEMS/GRADE_ITEM/GRADE_GRADES'),
);
}

/**
* 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
*/
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);

} 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']);
}
}

/**
* Processes one GRADE_ITEM of the type 'mod'
*/
protected function process_mod_grade_item(array $data, array $raw) {

$stashname = 'gradebook_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);

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;
}

/**
* @todo
*/
public function on_gradebook_grade_item_grades_start() {
}

/**
* 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->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() {

$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');
}
}


/**
* Shared base class for activity modules, blocks and qtype handlers
*/
Expand Down
16 changes: 16 additions & 0 deletions backup/converter/moodle1/lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,22 @@ public function get_stash($stashname, $itemid = 0) {
}
}

/**
* 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
*
Expand Down
32 changes: 32 additions & 0 deletions backup/converter/moodle1/simpletest/testlib.php
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,38 @@ public function test_stash_storage() {
$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);

Expand Down
Loading

0 comments on commit 7ace3a2

Please sign in to comment.