From 30049cce7ac6999b31e3835572060cf6c15ef7a7 Mon Sep 17 00:00:00 2001
From: Penny Leach <penny@mjollnir.org>
Date: Tue, 7 Oct 2008 15:51:54 +0100
Subject: [PATCH] [UPSTREAM] implemented local hooks for backup & restore

---
 backup/backuplib.php    |   10 ++++++++
 backup/restorelib.php   |   58 +++++++++++++++++++++++++++++++++++++++++++++++
 lang/en_utf8/moodle.php |    1 +
 lib/locallib.php        |   52 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 121 insertions(+), 0 deletions(-)

diff --git a/backup/backuplib.php b/backup/backuplib.php
index d0e479d..0a9ab35 100644
--- a/backup/backuplib.php
+++ b/backup/backuplib.php
@@ -734,6 +734,16 @@
             write_role_assignments_xml($bf, $preferences, $context, 3);
             //Print header end
             fwrite ($bf,end_tag("HEADER",2,true));
+
+            // go look for any local data to backup at the course level
+            if (file_exists($CFG->dirroot . '/local/lib.php')) {
+                require_once($CFG->dirroot . '/local/lib.php');
+                if (function_exists('local_course_backup')) {
+                    fwrite($bf, start_tag('LOCAL', 2, true));
+                    $status = $status && local_course_backup($bf, $course, 3);
+                    fwrite($bf, end_tag('LOCAL', 2, true));
+                }
+            }
         } else {
            $status = false;
         }
diff --git a/backup/restorelib.php b/backup/restorelib.php
index ebf585d..32186f5 100644
--- a/backup/restorelib.php
+++ b/backup/restorelib.php
@@ -1238,6 +1238,23 @@ define('RESTORE_GROUPS_GROUPINGS', 3);
         return true;
     }
 
+    function restore_create_local_coursedata($restore, $xml_file) {
+        global $CFG;
+        if (!file_exists($CFG->dirroot . '/local/lib.php')) {
+            return true;
+        }
+        require_once($CFG->dirroot . '/local/lib.php');
+        if (!function_exists('local_course_restore_createdata')) {
+            return true;
+        }
+        if (!defined('RESTORE_SILENTLY')) {
+            echo "<li>".get_string("creatinglocalcoursedata");
+        }
+        $info = restore_read_xml($xml_file, 'LOCAL', false);
+
+        return local_course_restore_createdata($restore->course_id, $info);
+    }
+
     //This function creates all the metacourse data from xml, notifying
     //about each incidence
     function restore_create_metacourse($restore,$xml_file) {
@@ -4498,6 +4515,12 @@ define('RESTORE_GROUPS_GROUPINGS', 3);
             //    echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n";   //Debug
         }
 
+        function startElementCourseLocal($parser, $tagName, $attrs) {
+            //Refresh properties
+            $this->level++;
+            $this->tree[$this->level] = $tagName;
+        }
+
         //This is the startTag handler we use where we are reading the blocks zone (todo="BLOCKS")
         function startElementBlocks($parser, $tagName, $attrs) {
             //Refresh properties
@@ -5332,6 +5355,29 @@ define('RESTORE_GROUPS_GROUPINGS', 3);
 
         }
 
+        function endElementCourseLocal($parser, $tagName) {
+            global $CFG;
+            if ($this->tree[3] == 'LOCAL') {
+                // someone's written some local data, see if we have a processor to import it.
+                if (file_exists($CFG->dirroot . '/local/lib.php')) {
+                    require_once($CFG->dirroot . '/local/lib.php');
+                    if (function_exists('local_course_restore_getdata')) {
+                        local_course_restore_getdata($this, $tagName, 4, $errorstr);
+                    }
+                }
+            }
+
+            if ($this->tree[3] == 'LOCAL' && $tagName == 'LOCAL') {
+                $this->finished = true;
+            }
+
+            //Clear things
+            $this->tree[$this->level] = '';
+            $this->level--;
+            $this->content = "";
+        }
+
+
         //This is the endTag handler we use where we are reading the sections zone (todo="BLOCKS")
         function endElementBlocks($parser, $tagName) {
             //Check if we are into BLOCKS zone
@@ -7119,6 +7165,8 @@ define('RESTORE_GROUPS_GROUPINGS', 3);
             xml_set_element_handler($xml_parser, "startElementRoles", "endElementRoles");
         } else if ($todo == "COURSE_HEADER") {
             xml_set_element_handler($xml_parser, "startElementCourseHeader", "endElementCourseHeader");
+        } else if ($todo == 'LOCAL') {
+            xml_set_element_handler($xml_parser, 'startElementCourseLocal', 'endElementCourseLocal');
         } else if ($todo == 'BLOCKS') {
             xml_set_element_handler($xml_parser, "startElementBlocks", "endElementBlocks");
         } else if ($todo == "SECTIONS") {
@@ -7771,6 +7819,16 @@ define('RESTORE_GROUPS_GROUPINGS', 3);
             }
         }
 
+        if ($status) {
+            if (!$status = restore_create_local_coursedata($restore, $xml_file)) {
+                if (!defined('RESTORE_SILENTLY')) {
+                    notify("Failed to restore local course data");
+                } else {
+                    $errorstr = "Failed to restore local course data";
+                }
+                return false;
+            }
+        }
 
         //Now create categories and questions as needed
         if ($status) {
diff --git a/lang/en_utf8/moodle.php b/lang/en_utf8/moodle.php
index 4558d02..729677f 100644
--- a/lang/en_utf8/moodle.php
+++ b/lang/en_utf8/moodle.php
@@ -321,6 +321,7 @@ $string['creatinggroups'] = 'Creating groups';
 $string['creatinggroupings'] = 'Creating groupings';
 $string['creatinggroupingsgroups'] = 'Adding groups into groupings';
 $string['creatinglogentries'] = 'Creating log entries';
+$string['creatinglocalcoursedata'] = 'Creating any local custom course data';
 $string['creatingmessagesinfo'] = 'Creating messages info';
 $string['creatingmetacoursedata'] = 'Creating metacourse info';
 $string['creatingmodroles'] = 'Creating module level role assignments and overrides';
diff --git a/lib/locallib.php b/lib/locallib.php
index 3f5dfef..8fdfba4 100644
--- a/lib/locallib.php
+++ b/lib/locallib.php
@@ -101,6 +101,58 @@
  * In there, implement the function local_delete_course($courseid). This
  * function will then be called whenever the functions remove_course_contents()
  * or delete_course() from moodlelib are called.
+ *
+ * Course backup and restore
+ * -------------------------
+ *
+ * If you've added some extra course-level information,
+ * you can add hooks to run local code during both backup & restore.
+ * To have this code run, create the file called local/lib.php
+ * Inside, implement these three functions:
+ *
+ * --- begin function skeleton --
+ * implement the local hook to run some custom code at course backup time.
+ * see lib/locallib.php
+ *
+ * @param filehandle $bf open file handle for writing to
+ * @param stdclass object $course course we're backing up
+ * @param integer $startlevel level we're currently using
+ *
+ * @return boolean
+ * function local_course_backup($bf, $course, $startlevel) {
+ *     // write out any extra XML you want using the standard start_tag, full_tag and end_tag methods.
+ * }
+ * --- end function skeleton --
+ *
+ * --- begin function skeleton --
+ * implement the local hook to run some custom code at course restore time.
+ * see lib/locallib.php
+ *
+ * @param object $parser      moodleparser object, passed by reference
+ * @param string $tagname     current tag being read
+ * @param int    $level       current depth of XML where LOCAL tag is found +1
+ * @param string $errorstring string to fill with errors
+ *
+ * @return boolean
+ * function local_course_restore_getdata(&$parser, $tagname, $level, &$errorstr) {
+ *     // using the parser methods, cache in the $parser->info object somewhere the result of reading each tag.
+ *     // you may need to employ dirty hack methods to keep track of where you are.
+ * }
+ * --- end function skeleton --
+ *
+ * --- begin function skeleton --
+ * implement the local hook to run some custom code at course restore time.
+ * see lib/locallib.php
+ *
+ * @param int $courseid the id of the course to restore into
+ * @param stdclass $data the data the parser has created
+ *
+ * @return boolean
+ * function local_course_restore_createdata($courseid, $data) {
+ *     // insert data to the database.
+ * }
+ * --- end function skeleton --
+ *
  */
 
 /**
-- 
1.5.6.5

