mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 08:22:07 +02:00
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:
parent
89a5baaba1
commit
3ecf46a193
@ -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) {
|
||||
|
@ -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) {
|
||||
|
||||
|
@ -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
|
||||
|
@ -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(" ",$this->level*2)."<".$tagName."><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(" ",$this->level*2)."<".$tagName."><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(" ",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
|
||||
//echo $this->level.str_repeat(" ",$this->level*2)."</".$tagName."><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");
|
||||
|
@ -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
|
||||
|
@ -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';
|
||||
|
Loading…
x
Reference in New Issue
Block a user