Blocks are now saved to and restored from course backups!

Backward compatibility is maintained, i.e. you can restore ANY version
backups without problems in 1.5. When "adding backup data to an existing
course", no blocks are added. I 'm not sure what the correct behavior
would be in this case.

When restoring a backup from Moodle <= 1.2, the new course SHOULD be given
default blocks when it is restored. I have not actually tested this, my
tests were with version 1.3 and 1.4 backup format.
This commit is contained in:
defacer 2004-10-29 17:07:11 +00:00
parent 89a5baaba1
commit 3ecf46a193
6 changed files with 264 additions and 17 deletions

View File

@ -166,6 +166,13 @@
notify("An error occurred while backing up course start");
}
}
echo "<li>".get_string("blocks");
//Blocks information
if ($status) {
if (!$status = backup_course_blocks($backup_file,$preferences)) {
notify("An error occurred while backing up course blocks");
}
}
echo "<li>".get_string("sections");
//Section info
if ($status) {

View File

@ -521,6 +521,8 @@
} else {
fwrite ($bf,full_tag("COURSEFILES",3,false,"false"));
}
//The mode of writing the block data
fwrite ($bf,full_tag('BLOCKFORMAT',3,false,'instances'));
fwrite ($bf,end_tag("DETAILS",2,true));
@ -564,7 +566,6 @@
fwrite ($bf,full_tag("SUMMARY",3,false,$course->summary));
fwrite ($bf,full_tag("FORMAT",3,false,$course->format));
fwrite ($bf,full_tag("SHOWGRADES",3,false,$course->showgrades));
fwrite ($bf,full_tag("BLOCKINFO",3,false,blocks_get_block_names($course->blockinfo)));
fwrite ($bf,full_tag("NEWSITEMS",3,false,$course->newsitems));
fwrite ($bf,full_tag("TEACHER",3,false,$course->teacher));
fwrite ($bf,full_tag("TEACHERS",3,false,$course->teachers));
@ -605,6 +606,51 @@
}
//Prints course's sections info (table block_instance)
function backup_course_blocks ($bf,$preferences) {
global $CFG;
$status = true;
// Read all of the block table
$blocks = blocks_get_record();
$page = new stdClass;
$page->id = $preferences->backup_course;
$page->type = MOODLE_PAGE_COURSE;
if ($instances = blocks_get_by_page($page)) {
//Blocks open tag
fwrite ($bf,start_tag('BLOCKS',2,true));
//Iterate over every block
foreach ($instances as $position) {
foreach ($position as $instance) {
//If we somehow have a block with an invalid id, skip it
if(empty($blocks[$instance->blockid]->name)) {
continue;
}
//Begin Block
fwrite ($bf,start_tag('BLOCK',3,true));
fwrite ($bf,full_tag('NAME',4,false,$blocks[$instance->blockid]->name));
fwrite ($bf,full_tag('PAGEID',4,false,$instance->pageid));
fwrite ($bf,full_tag('PAGETYPE',4,false,$instance->pagetype));
fwrite ($bf,full_tag('POSITION',4,false,$instance->position));
fwrite ($bf,full_tag('WEIGHT',4,false,$instance->weight));
fwrite ($bf,full_tag('VISIBLE',4,false,$instance->visible));
fwrite ($bf,full_tag('CONFIGDATA',4,false,$instance->configdata));
//End Block
fwrite ($bf,end_tag('BLOCK',3,true));
}
}
//Blocks close tag
$status = fwrite ($bf,end_tag('BLOCKS',2,true));
}
return $status;
}
//Prints course's sections info (table course_sections)
function backup_course_sections ($bf,$preferences) {

View File

@ -108,6 +108,67 @@
}
}
//Bring back the course blocks
if($status) {
echo '<li>'.get_string('creatingblocks');
//If we are deleting and bringing into a course or making a new course, same situation
if($restore->restoreto == 0 || $restore->restoreto == 2) {
delete_records('block_instance', 'pageid', $course_header->course_id, 'pagetype', MOODLE_PAGE_COURSE);
if(empty($info->backup_block_format)) {
This is a backup from Moodle < 1.5
if(empty($course_header->blockinfo)) {
// Looks like it's from Moodle < 1.3. Let's give the course default blocks...
$newpage = new stdClass;
$newpage->type = MOODLE_PAGE_COURSE;
$newpage->id = $course_header->course_id;
blocks_repopulate_page($newpage);
}
else {
// We just have a blockinfo field, this is a legacy 1.4 or 1.3 backup
$blockrecords = get_records_select('block', '', '', 'name, id');
$temp_blocks_l = array();
$temp_blocks_r = array();
@list($temp_blocks_l, $temp_blocks_r) = explode(':', $course_header->blockinfo);
$temp_blocks = array(BLOCK_POS_LEFT => explode(',', $temp_blocks_l), BLOCK_POS_RIGHT => explode(',', $temp_blocks_r));
foreach($temp_blocks as $blockposition => $blocks) {
$blockweight = 0;
foreach($blocks as $blockname) {
if(!isset($blockrecords[$blockname])) {
// We don't know anything about this block!
continue;
}
$blockinstance = new stdClass;
$blockinstance->blockid = $blockrecords[$blockname]->id;
$blockinstance->pageid = $course_header->course_id;
$blockinstance->pagetype = MOODLE_PAGE_COURSE;
$blockinstance->position = $blockposition;
$blockinstance->weight = $blockweight;
if(substr($blockname, 0, 1) == '-') {
$blockname = substr($blockname, 1);
$blockinstance->visible = 0;
}
else {
$blockinstance->visible = 1;
}
if(!$status = insert_record('block_instance', $blockinstance)) {
notify('Error while creating the course blocks');
}
++$blockweight;
}
}
}
}
else if($info->backup_block_format == 'instances') {
if(!$status = restore_create_block_instances($restore,$xml_file)) {
notify('Error while creating the course blocks');
}
}
}
//Otherwise we are bringing into a course which already has blocks
else {
}
}
//Now create the course_sections and their associated course_modules
if ($status) {
//Into new course

View File

@ -252,6 +252,15 @@
return $info;
}
//This function read the xml file and store its data from the sections in a object
function restore_read_xml_blocks ($xml_file) {
//We call the main read_xml function, with todo = BLOCKS
$info = restore_read_xml ($xml_file,'BLOCKS',false);
return $info;
}
//This function read the xml file and store its data from the sections in a object
function restore_read_xml_sections ($xml_file) {
@ -521,7 +530,6 @@
$course->summary = restore_decode_absolute_links(addslashes($course_header->course_summary));
$course->format = addslashes($course_header->course_format);
$course->showgrades = addslashes($course_header->course_showgrades);
$course->blockinfo = addslashes($course_header->blockinfo);
$course->newsitems = addslashes($course_header->course_newsitems);
$course->teacher = addslashes($course_header->course_teacher);
$course->teachers = addslashes($course_header->course_teachers);
@ -543,20 +551,6 @@
$course->hiddensections = addslashes($course_header->course_hiddensections);
$course->timecreated = addslashes($course_header->course_timecreated);
$course->timemodified = addslashes($course_header->course_timemodified);
//Adjust blockinfo field.
//If the info doesn't exist in backup, we create defaults, else we recode it
//to current site blocks.
if (!$course->blockinfo) {
//Create blockinfo default content
if ($course->format == "social") {
$course->blockinfo = blocks_get_default_blocks (NULL,"participants,search_forums,calendar_month,calendar_upcoming,social_activities,recent_activity,admin,course_list");
} else {
//For topics and weeks formats (default built in the function)
$course->blockinfo = blocks_get_default_blocks();
}
} else {
$course->blockinfo = blocks_get_block_ids($course->blockinfo);
}
//Now insert the record
$newid = insert_record("course",$course);
if ($newid) {
@ -572,6 +566,65 @@
return $status;
}
//This function creates all the block_instances from xml when restoring in a
//new course
function restore_create_block_instances($restore,$xml_file) {
$status = true;
//Check it exists
if (!file_exists($xml_file)) {
$status = false;
}
//Get info from xml
if ($status) {
$info = restore_read_xml_blocks($xml_file);
}
$maxweights = array();
if(!empty($info->instances)) {
$blocks = get_records_select('block', '', '', 'name, id, multiple');
foreach($info->instances as $instance) {
if(!isset($blocks[$instance->name])) {
//We are trying to restore a block we don't have...
continue;
}
//If its the first block we add to a new position, start weight counter equal to 0.
if(empty($maxweights[$instance->position])) {
$maxweights[$instance->position] = 0;
}
//If the instance weight is greater than the weight counter (we skipped some earlier
//blocks most probably), bring it back in line.
if($instance->weight > $maxweights[$instance->position]) {
$instance->weight = $maxweights[$instance->position];
}
//If we have already added this block once and multiples aren't allowed, disregard it
if(!empty($blocks[$instance->name]->added)) {
continue;
}
//Add this instance
$instance->blockid = $blocks[$instance->name]->id;
$instance->pageid = $restore->course_id;
if(!insert_record('block_instance', $instance)) {
$status = false;
break;
}
//Now we can increment the weight counter
++$maxweights[$instance->position];
//Keep track of block types we have already added
$blocks[$instance->name]->added = true;
}
}
return $status;
}
//This function creates all the course_sections and course_modules from xml
//when restoring in a new course or simply checks sections and create records
//in backup_ids when restoring in a existing course
@ -1875,6 +1928,20 @@
// echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
}
//This is the startTag handler we use where we are reading the blocks zone (todo="BLOCKS")
function startElementBlocks($parser, $tagName, $attrs) {
//Refresh properties
$this->level++;
$this->tree[$this->level] = $tagName;
//Output something to avoid browser timeouts...
backup_flush();
//Check if we are into BLOCKS zone
//if ($this->tree[3] == "BLOCKS") //Debug
// echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
}
//This is the startTag handler we use where we are reading the sections zone (todo="SECTIONS")
function startElementSections($parser, $tagName, $attrs) {
//Refresh properties
@ -2126,6 +2193,9 @@
case "COURSEFILES":
$this->info->backup_course_files = $this->getContents();
break;
case 'BLOCKFORMAT':
$this->info->backup_block_format = $this->getContents();
break;
}
}
if ($this->level == 5) {
@ -2285,6 +2355,65 @@
}
}
//This is the endTag handler we use where we are reading the sections zone (todo="SECTIONS")
function endElementBlocks($parser, $tagName) {
//Check if we are into BLOCKS zone
if ($this->tree[3] == 'BLOCKS') {
//if (trim($this->content)) //Debug
// echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
//echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
//Dependig of different combinations, do different things
if ($this->level == 4) {
switch ($tagName) {
case 'BLOCK':
//We've finalized a block, get it
$this->info->instances[] = $this->info->tempinstance;
unset($this->info->tempinstance);
break;
default:
die($tagName);
}
}
if ($this->level == 5) {
switch ($tagName) {
case 'NAME':
$this->info->tempinstance->name = $this->getContents();
break;
case 'PAGEID':
$this->info->tempinstance->pageid = $this->getContents();
break;
case 'PAGETYPE':
$this->info->tempinstance->pagetype = $this->getContents();
break;
case 'POSITION':
$this->info->tempinstance->position = $this->getContents();
break;
case 'WEIGHT':
$this->info->tempinstance->weight = $this->getContents();
break;
case 'VISIBLE':
$this->info->tempinstance->visible = $this->getContents();
break;
case 'CONFIGDATA':
$this->info->tempinstance->configdata = $this->getContents();
break;
}
}
}
//Clear things
$this->tree[$this->level] = '';
$this->level--;
$this->content = "";
//Stop parsing if todo = BLOCKS and tagName = BLOCKS (en of the tag, of course)
//Speed up a lot (avoid parse all)
//WARNING: ONLY EXIT IF todo = BLOCKS (thus tree[3] = "BLOCKS") OTHERWISE
// THE BLOCKS TAG IN THE HEADER WILL TERMINATE US!
if ($this->tree[3] == 'BLOCKS' && $tagName == 'BLOCKS') {
$this->finished = true;
}
}
//This is the endTag handler we use where we are reading the sections zone (todo="SECTIONS")
function endElementSections($parser, $tagName) {
//Check if we are into SECTIONS zone
@ -2957,6 +3086,9 @@
} else if ($todo == "COURSE_HEADER") {
//Define handlers to that zone
xml_set_element_handler($xml_parser, "startElementCourseHeader", "endElementCourseHeader");
} else if ($todo == 'BLOCKS') {
//Define handlers to that zone
xml_set_element_handler($xml_parser, "startElementBlocks", "endElementBlocks");
} else if ($todo == "SECTIONS") {
//Define handlers to that zone
xml_set_element_handler($xml_parser, "startElementSections", "endElementSections");

View File

@ -5,6 +5,6 @@
// database (backup_version) to determine whether upgrades should
// be performed (see db/backup_*.php)
$backup_version = 2004083122; // The current version is a date (YYYYMMDDXX)
$backup_version = 2004102900; // The current version is a date (YYYYMMDDXX)
$backup_release = "1.5 development"; // User-friendly version number

View File

@ -259,6 +259,7 @@ $string['createaccount'] = 'Create my new account';
$string['createfolder'] = 'Create a folder in $a';
$string['createuserandpass'] = 'Create a new username and password to log in with';
$string['createziparchive'] = 'Create zip archive';
$string['creatingblocks'] = 'Creating blocks';
$string['creatingcategoriesandquestions'] = 'Creating categories and questions';
$string['creatingcoursemodules'] = 'Creating course modules';
$string['creatingevents'] = 'Creating events';