]> git.mjollnir.org Git - moodle.git/commitdiff
Blocks are now saved to and restored from course backups!
authordefacer <defacer>
Fri, 29 Oct 2004 17:07:11 +0000 (17:07 +0000)
committerdefacer <defacer>
Fri, 29 Oct 2004 17:07:11 +0000 (17:07 +0000)
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.

backup/backup_execute.html
backup/backuplib.php
backup/restore_execute.html
backup/restorelib.php
backup/version.php
lang/en/moodle.php

index feb268049d11ed999610f72cd256fe3889c099d8..12d151c0e87787f5f8adc763acf2859cbf1d8eac 100644 (file)
                 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) {
index a82729cfe522f71c232bf606ac33af8d0bcd8c6a..fa2b98cc4ffbc78179330f3627e99105181f8598 100644 (file)
         } 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));
 
             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));
 
     }
 
+    //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) {
 
index d31a79106534cc47e9cc86088c029fd764353d45..e2a9b31edd1c0cba1e0e3f57336f5a5eff15facc 100644 (file)
         }
     }
 
+    //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
index 8a62bdfb0197fc4ae63c4118428779d8ef184dd9..8cbb281a7d25e48fe3a610cc993c36a2e25c1cc2 100644 (file)
         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) {
 
             $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);
             $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) {
         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
             //    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     
                             case "COURSEFILES":
                                 $this->info->backup_course_files = $this->getContents();
                                 break;
+                            case 'BLOCKFORMAT':
+                                $this->info->backup_block_format = $this->getContents();
+                                break;
                         }
                     }
                     if ($this->level == 5) {
             }
         }
 
+        //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
         } 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");
index ae494cb05775d5d07b323e569fc0458c3d6bbd5e..b639643afc2a21a61addb8ab85db0a625e672e0c 100644 (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
index bceb049e78ac5b3f8d97f443a5bfd7a8c6946527..61fd973796efef837754936d7ae5551e6150007b 100644 (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';