Index: group/lib/utillib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/group/lib/utillib.php,v
retrieving revision 1.5
diff -u -r1.5 utillib.php
--- group/lib/utillib.php	17 Jan 2007 13:56:11 -0000	1.5
+++ group/lib/utillib.php	20 Jan 2007 09:24:03 -0000
@@ -160,18 +160,32 @@
 /**
  * Given an array of group IDs get an array of group objects.
  * TODO: quick and dirty. Replace with SQL?
+ * @param $groupids Array of group IDs.
+ * @param $courseid Default false, or Course ID.
+ * @param $alldata Default false, or get complete record for group.
+ * @param array Array of group objects, with basic or all data.
  */
-function groups_groupids_to_groups($groupids, $courseid=false) {
+function groups_groupids_to_groups($groupids, $courseid=false, $alldata=false) {
     if (! $groupids) {
         return false;
     }
     $groups = array();
     foreach ($groupids as $id) {
-        $groups[] = groups_get_group_settings($id, $courseid);
+        $groups[] = groups_get_group_settings($id, $courseid, $alldata);
     }
     return $groups;
 }
 
+function groups_groupingids_to_groupings($groupingids) {
+    if (! $groupingids) {
+        return false;
+    }
+    $groupings = array();
+    foreach ($groupingids as $id) {
+        $groupings[] = groups_get_grouping_settings($id);
+    }
+    return $groupings;
+}
 
 /**
  * Gets the user object for a given userid. Can't find a function anywhere to 
Index: group/lib/basicgrouplib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/group/lib/basicgrouplib.php,v
retrieving revision 1.6
diff -u -r1.6 basicgrouplib.php
--- group/lib/basicgrouplib.php	17 Jan 2007 13:56:11 -0000	1.6
+++ group/lib/basicgrouplib.php	20 Jan 2007 09:24:02 -0000
@@ -54,6 +54,19 @@
     return $userids;
 }
 
+/**
+ * Return member records, for backup.
+ */
+function groups_get_member_records($groupid) {
+    if (!$groupid) {
+        return false;
+    }
+    $members = get_records('groups_members', 'groupid ', $groupid, '', 
+                          $fields='id, userid, timeadded');
+
+    return $members;
+}
+
 
 /**
  * Gets the groups to which a user belongs for a specified course. 
@@ -103,8 +116,8 @@
  * @param int $groupid The id of the gruop
  * @return object The group settings object 
  */
-function groups_get_group_settings($groupid, $courseid=false) {
-	return groups_db_get_group_settings($groupid, $courseid);
+function groups_get_group_settings($groupid, $courseid=false, $alldata=false) {
+	return groups_db_get_group_settings($groupid, $courseid, $alldata);
 }
 
 /**
@@ -179,6 +192,28 @@
 }
 
 /**
+ * Determine if a course ID, group name and description match a group in the database.
+ *   For backup/restorelib.php
+ * @return mixed A group-like object with $group->id, or false.
+ */
+function groups_group_matches($courseid, $grp_name, $grp_description) {
+//$gro_db->id; $gro_db = get_record("groups","courseid",$restore->course_id,"name",$gro->name,"description",$gro->description);    
+    global $CFG;
+    $sql = "SELECT g.id, g.name, g.description
+        FROM {$CFG->prefix}groups AS g
+        INNER JOIN {$CFG->prefix}groups_courses_groups AS cg ON g.id = cg.groupid
+        WHERE g.name = '$grp_name'
+        AND g.description = '$grp_description'
+        AND cg.courseid = '$courseid'";
+    $records = get_records_sql($sql);
+    $group = false;
+    if ($records) {
+        $group = $records[0];
+    } 
+    return $group;
+}
+
+/**
  * Determines if a specified user is a member of a specified group
  * @param int $groupid The group about which the request has been made
  * @param int $userid The user about which the request has been made
@@ -263,6 +298,14 @@
 	return groups_db_create_group($courseid, $groupsettings);
 }
 
+/**
+ * Restore a group for a specified course.
+ *   For backup/restorelib.php 
+ */
+function groups_restore_group($courseid, $groupsettings) {
+    return groups_db_create_group($courseid, $groupsettings, $copytime=true);
+}
+
 
 /**
  * Sets the information about a group
@@ -301,6 +344,23 @@
 	return $useradded;
 }
 
+/**
+ * Restore a user to the group specified in $member.
+ *   For backup/restorelib.php
+ * @param $member object Group member object.
+ */
+function groups_restore_member($member) {
+    $alreadymember = groups_is_member($member->groupid, $member->userid);
+    if (! groups_group_exists($member->groupid)) {
+        return false;
+    } elseif ($alreadymember) {
+        return true;
+    } else {
+        $useradded = groups_db_add_member($member->groupid, $member->userid, $member->timeadded);
+    }
+    return true;
+}
+
 
 /*****************************
         Deletion functions  
Index: group/lib/groupinglib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/group/lib/groupinglib.php,v
retrieving revision 1.6
diff -u -r1.6 groupinglib.php
--- group/lib/groupinglib.php	17 Jan 2007 16:13:21 -0000	1.6
+++ group/lib/groupinglib.php	20 Jan 2007 09:24:02 -0000
@@ -30,6 +30,25 @@
 }
 
 
+function groups_get_grouping_records($courseid) {
+    /*$groupingids = groups_db_get_groupings($courseid);
+    if (! $groupingids) {
+        return false;
+    }
+    $groupings = groups_groupingids_to_groupings($groupingids);
+*/
+    global $CFG;
+    if (! $courseid) {
+        return false;
+    }
+    $sql = "SELECT gg.*
+        FROM {$CFG->prefix}groups_groupings AS gg
+        INNER JOIN {$CFG->prefix}groups_courses_groupings AS cg ON gg.id = cg.groupingid
+        WHERE cg.courseid = '$courseid'";
+    $groupings = get_records_sql($sql);
+    return $groupings;
+}
+
 /**
  * Gets a list of the groups in a specified grouping
  * @param int $groupingid The id of the grouping
@@ -40,6 +59,17 @@
     return groups_db_get_groups_in_grouping($groupingid);
 }
 
+function groups_get_groups_in_grouping_records($groupingid) {
+    if (! $groupingid) {
+        return false;
+    }
+    $grouping_groups = get_records('groups_groupings_groups', 'groupingid ', 
+                              $groupingid, '', $fields='id, groupid, timeadded');
+    
+    return $grouping_groups;
+}
+
+
 /** 
  * Gets the groupings that a group belongs to 
  * @param int $groupid The id of the group
@@ -252,8 +282,29 @@
 function groups_grouping_exists($groupingid) {
 	return groups_db_grouping_exists($groupingid);
 }
- 
- /**
+
+/**
+ * Determine if a course ID, grouping name and description match a grouping in the database.
+ *   For backup/restorelib.php
+ * @return mixed A grouping-like object with $grouping->id, or false.
+ */
+function groups_grouping_matches($courseid, $gg_name, $gg_description) {
+    global $CFG;
+    $sql = "SELECT gg.id, gg.name, gg.description
+        FROM {$CFG->prefix}groups_groupings AS gg
+        INNER JOIN {$CFG->prefix}groups_courses_groupings AS cg ON gg.id = cg.groupingid
+        WHERE gg.name = '$gg_name'
+        AND gg.description = '$gg_description'
+        AND cg.courseid = '$courseid'";
+    $records = get_records_sql($sql);
+    $grouping = false;
+    if ($records) {
+        $grouping = $records[0];
+    } 
+    return $grouping;
+}
+
+/**
   * Determines if a group belongs to a specified grouping
   * @param int $groupid The id of the group
   * @param int $groupingid The id of the grouping
Index: group/lib/legacylib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/group/lib/legacylib.php,v
retrieving revision 1.4
diff -u -r1.4 legacylib.php
--- group/lib/legacylib.php	3 Jan 2007 04:55:20 -0000	1.4
+++ group/lib/legacylib.php	20 Jan 2007 09:24:03 -0000
@@ -56,7 +56,7 @@
 		$groupids = groups_get_groups($courseid);
 	}
 
-	return groups_groupids_to_groups($groupids, $courseid);
+	return groups_groupids_to_groups($groupids, $courseid, $alldata=true);
 }
 
 
Index: backup/restorelib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/backup/restorelib.php,v
retrieving revision 1.217
diff -u -r1.217 restorelib.php
--- backup/restorelib.php	17 Jan 2007 01:00:08 -0000	1.217
+++ backup/restorelib.php	20 Jan 2007 09:24:01 -0000
@@ -286,6 +286,16 @@
         return $info;
     }
 
+    //This function read the xml file and store its data from the groupings in
+    //backup_ids->info db (and grouping's id in $info)
+    function restore_read_xml_groupings ($restore,$xml_file) {
+
+        //We call the main read_xml function, with todo = GROUPINGS
+        $info = restore_read_xml ($xml_file,"GROUPINGS",$restore);
+
+        return $info;
+    }
+
     //This function read the xml file and store its data from the events (course) in
     //backup_ids->info db (and event's id in $info)
     function restore_read_xml_events ($restore,$xml_file) {
@@ -2140,10 +2150,15 @@
                         //print_object ($GLOBALS['traverse_array']);                                                  //Debug
                         //$GLOBALS['traverse_array']="";                                                              //Debug
                         //Now build the GROUP record structure
-                        $gro->courseid = backup_todb($info['GROUP']['#']['COURSEID']['0']['#']);
+                        $gro = new Object();
+                        ///$gro->courseid = backup_todb($info['GROUP']['#']['COURSEID']['0']['#']);
                         $gro->name = backup_todb($info['GROUP']['#']['NAME']['0']['#']);
                         $gro->description = backup_todb($info['GROUP']['#']['DESCRIPTION']['0']['#']);
-                        $gro->password = backup_todb($info['GROUP']['#']['PASSWORD']['0']['#']);
+                        if (isset($info['GROUP']['#']['ENROLMENTKEY']['0']['#'])) {
+                            $gro->enrolmentkey = backup_todb($info['GROUP']['#']['ENROLMENTKEY']['0']['#']);
+                        } else { //if (! isset($gro->enrolment)) {
+                            $gro->enrolmentkey = backup_todb($info['GROUP']['#']['PASSWORD']['0']['#']);
+                        }
                         $gro->lang = backup_todb($info['GROUP']['#']['LANG']['0']['#']);
                         $gro->theme = backup_todb($info['GROUP']['#']['THEME']['0']['#']);
                         $gro->picture = backup_todb($info['GROUP']['#']['PICTURE']['0']['#']);
@@ -2152,8 +2167,8 @@
                         $gro->timemodified = backup_todb($info['GROUP']['#']['TIMEMODIFIED']['0']['#']);
                 
                         //Now search if that group exists (by name and description field) in 
-                        //restore->course_id course 
-                        $gro_db = get_record("groups","courseid",$restore->course_id,"name",$gro->name,"description",$gro->description);
+                        //restore->course_id course
+                        $gro_db = groups_group_matches($restore->course_id, $gro->name, $gro->description); 
                         //If it doesn't exist, create
                         if (!$gro_db) {
                             $create_group = true;
@@ -2170,7 +2185,7 @@
                             }
 
                             //The structure is equal to the db, so insert the group
-                            $newid = insert_record ("groups",$gro);
+                            $newid = groups_restore_group($restore->course_id, $gro);
                         } else { 
                             //get current group id
                             $newid = $gro_db->id;
@@ -2216,6 +2231,7 @@
             //$GLOBALS['traverse_array']="";                                                              //Debug
 
             //Now, build the GROUPS_MEMBERS record structure
+            $group_member = new Object();
             $group_member->groupid = $group_id;
             $group_member->userid = backup_todb($mem_info['#']['USERID']['0']['#']);
             $group_member->timeadded = backup_todb($mem_info['#']['TIMEADDED']['0']['#']);
@@ -2227,7 +2243,124 @@
             }
 
             //The structure is equal to the db, so insert the groups_members
-            $newid = insert_record ("groups_members",$group_member);
+            $newid = groups_restore_member($group_member);
+            //Do some output
+            if (($i+1) % 50 == 0) {
+                if (!defined('RESTORE_SILENTLY')) {
+                    echo ".";
+                    if (($i+1) % 1000 == 0) {
+                        echo "<br />";
+                    }
+                }
+                backup_flush(300);
+            }
+            
+            if (!$newid) {
+                $status = false;
+            }
+        }
+
+        return $status;
+    }
+    
+    //This function creates all the groupings
+    function restore_create_groupings($restore,$xml_file) {
+
+        global $CFG, $db;
+
+        $status = true;
+        $status2 = true;
+        //Check it exists
+        if (!file_exists($xml_file)) {
+            $status = false;
+        }
+        //Get info from xml
+        if ($status) {
+            //groupings will contain the old_id of every group
+            //in backup_ids->info will be the real info (serialized)
+            $groupings = restore_read_xml_groupings($restore,$xml_file);
+        }
+        //Now, if we have anything in groupings, we have to restore that grouping
+        if ($groupings) {
+            if ($groupings !== true) {
+                //Iterate over each group
+                foreach ($groupings as $grouping) {
+                    //Get record from backup_ids
+                    $data = backup_getid($restore->backup_unique_code,"groupings",$grouping->id);
+                    //Init variables
+                    $create_grouping = false;
+
+                    if ($data) {
+                        //Now get completed xmlized object
+                        $info = $data->info;
+                        //Now build the GROUPING record structure
+                        $gro = new Object();
+                        ///$gro->id = backup_todb($info['GROUPING']['#']['ID']['0']['#']);
+                        $gro->name = backup_todb($info['GROUPING']['#']['NAME']['0']['#']);
+                        $gro->description = backup_todb($info['GROUPING']['#']['DESCRIPTION']['0']['#']);
+                        $gro->timecreated = backup_todb($info['GROUPING']['#']['TIMECREATED']['0']['#']);
+                
+                        //Now search if that group exists (by name and description field) in 
+                        //restore->course_id course
+                        $gro_db = groups_grouping_matches($restore->course_id, $gro->name, $gro->description); 
+                        //If it doesn't exist, create
+                        if (!$gro_db) {
+                            $create_grouping = true;
+                        }
+                        //If we must create the group
+                        if ($create_grouping) {
+
+                            //The structure is equal to the db, so insert the grouping TODO: RESTORE.
+                            $newid = groups_create_grouping($restore->course_id, $gro);
+                        } else { 
+                            //get current group id
+                            $newid = $gro_db->id;
+                        }
+                        if ($newid) {
+                            //We have the newid, update backup_ids
+                            backup_putid($restore->backup_unique_code,"groupings",
+                                         $grouping->id, $newid);
+                        }
+                        //Now restore links from groupings to groups
+                        $status2 = restore_create_groupings_groups($newid,$info,$restore);
+                    }   
+                }
+                //(Now, restore grouping_files)
+            }
+        } else {
+            $status = false;
+        } 
+        return ($status && $status2);
+    }
+    
+    //This function restores the groups_members
+    function restore_create_groupings_groups($grouping_id,$info,$restore) {
+
+        global $CFG;
+
+        $status = true;
+
+        //Get the members array
+        $members = $info['GROUPING']['#']['GROUPS']['0']['#']['GROUP'];
+
+        //Iterate over members
+        for($i = 0; $i < sizeof($members); $i++) {
+            $mem_info = $members[$i];
+            //Now, build the GROUPINGS_GROUPS record structure
+            $gro_member = new Object();
+            $gro_member->groupingid = $grouping_id;
+            $gro_member->groupid = backup_todb($mem_info['#']['GROUPID']['0']['#']);
+            $gro_member->timeadded = backup_todb($mem_info['#']['TIMEADDED']['0']['#']);
+
+            //We have to recode the userid field
+            ///$user = backup_getid($restore->backup_unique_code,"user",$group_member->userid);
+            $group = backup_getid($restore->backup_unique_code,"group",$gro_member->groupid);
+            if ($group) {
+                $gro_member->groupid = $group->new_id;
+            }
+
+            //The structure is equal to the db, so link the groups to the groupings. TODO: RESTORE.
+            $newid = groups_add_group_to_grouping($gro_member->groupid, $gro_member->groupingid);
             //Do some output
             if (($i+1) % 50 == 0) {
                 if (!defined('RESTORE_SILENTLY')) {
@@ -3332,6 +3465,33 @@
                 }
             }
         }
+        
+        function startElementGroupings($parser, $tagName, $attrs) { //TODO:
+            //Refresh properties
+            $this->level++;
+            $this->tree[$this->level] = $tagName;
+
+            //if ($tagName == "GROUPING" && $this->tree[3] == "GROUPINGS") {                                 //Debug
+            //    echo "<P>GROUPING: ".strftime ("%X",time()),"-";                                        //Debug
+            //}                                                                                        //Debug
+
+            //Output something to avoid browser timeouts...
+            backup_flush();
+
+            //Check if we are into GROUPINGS zone
+            //if ($this->tree[3] == "GROUPINGS")                                                           //Debug
+            //    echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n";   //Debug
+
+            //If we are under a GROUPING tag under a GROUPINGS zone, accumule it
+            if (isset($this->tree[4]) and isset($this->tree[3])) {
+                if (($this->tree[4] == "GROUPING") and ($this->tree[3] == "GROUPINGS")) {
+                    if (!isset($this->temp)) {
+                        $this->temp = "";
+                    }
+                    $this->temp .= "<".$tagName.">";
+                }
+            }
+        }
 
         //This is the startTag handler we use where we are reading the events zone (todo="EVENTS")
         function startElementEvents($parser, $tagName, $attrs) {
@@ -4909,6 +5069,7 @@
                     $status = backup_putid($this->preferences->backup_unique_code,"groups",$group_id,
                                      null,$data);
                     //Create returning info
+                    $ret_info = new Object();
                     $ret_info->id = $group_id;
                     $this->info[] = $ret_info;
                     //Reset temp
@@ -4929,6 +5090,50 @@
 
         }
 
+        //This is the endTag handler we use where we are reading the groups zone (todo="GROUPINGS")
+        function endElementGroupings($parser, $tagName) { //TODO:
+            //Check if we are into GROUPS zone
+            if ($this->tree[3] == "GROUPINGS") {
+                //Acumulate data to info (content + close tag)
+                //Reconvert: strip htmlchars again and trim to generate xml data
+                if (!isset($this->temp)) {
+                    $this->temp = "";
+                }
+                $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
+                //If we've finished a group, xmlize it an save to db
+                if (($this->level == 4) and ($tagName == "GROUPING")) {
+                    //Prepend XML standard header to info gathered
+                    $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
+                    //Call to xmlize for this portion of xml data (one GROUPING)
+                    $data = xmlize($xml_data,0);
+                    //Now, save data to db. We'll use it later
+                    //Get id and from data
+                    $grouping_id = $data["GROUPING"]["#"]["ID"]["0"]["#"];
+                    //Save to db
+                    $status = backup_putid($this->preferences->backup_unique_code,"groupings",$grouping_id,
+                                     null,$data);
+                    //Create returning info
+                    $ret_info = new Object();
+                    $ret_info->id = $grouping_id;
+                    $this->info[] = $ret_info;
+                    //Reset temp
+                    unset($this->temp);
+                }
+            }
+
+            //Stop parsing if todo = GROUPINGS and tagName = GROUPING (en of the tag, of course)
+            //Speed up a lot (avoid parse all)
+            if ($tagName == "GROUPINGS" and $this->level == 3) {
+                $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 events zone (todo="EVENTS")
         function endElementEvents($parser, $tagName) {
             //Check if we are into EVENTS zone
@@ -5170,6 +5375,9 @@
         } else if ($todo == "GROUPS") {
             //Define handlers to that zone
             xml_set_element_handler($xml_parser, "startElementGroups", "endElementGroups");
+        } else if ($todo == "GROUPINGS") {
+            //Define handlers to that zone
+            xml_set_element_handler($xml_parser, "startElementGroupings", "endElementGroupings");
         } else if ($todo == "EVENTS") {
             //Define handlers to that zone
             xml_set_element_handler($xml_parser, "startElementEvents", "endElementEvents");
@@ -5841,6 +6049,24 @@
                 echo '</li>';
             }
         }
+
+        //Now create groupings as needed
+        if ($status) {
+            if (!defined('RESTORE_SILENTLY')) {
+                echo "<li>".get_string("creatinggroupings");
+            }
+            if (!$status = restore_create_groupings($restore,$xml_file)) {
+                if (!defined('RESTORE_SILENTLY')) {
+                    notify("Could not restore groupings!");
+                } else {
+                    $errorstr = "Could not restore groupings!";
+                    return false;
+                }
+            }
+            if (!defined('RESTORE_SILENTLY')) {
+                echo '</li>';
+            }
+        }
         
         //Now create events as needed
         if ($status) {
Index: backup/backup_execute.html
===================================================================
RCS file: /cvsroot/moodle/moodle/backup/backup_execute.html,v
retrieving revision 1.46
diff -u -r1.46 backup_execute.html
--- backup/backup_execute.html	11 Dec 2006 15:47:25 -0000	1.46
+++ backup/backup_execute.html	20 Jan 2007 09:23:47 -0000
@@ -171,6 +171,14 @@
             }
         }
 
+        //Print groupings info
+        if ($status) {
+            echo "<li>".get_string("writinggroupingsinfo").'</li>';
+            if (!$status = backup_groupings_info($backup_file,$preferences)) {
+                notify("An error occurred while backing up groupings");
+            }
+        }
+
         //Print groups info
         if ($status) {
             echo "<li>".get_string("writinggroupsinfo").'</li>';
Index: backup/backuplib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/backup/backuplib.php,v
retrieving revision 1.134
diff -u -r1.134 backuplib.php
--- backup/backuplib.php	16 Jan 2007 02:52:51 -0000	1.134
+++ backup/backuplib.php	20 Jan 2007 09:23:50 -0000
@@ -1635,7 +1635,7 @@
 
     //Backup groups info
     function backup_groups_info($bf,$preferences) {
-    
+
         global $CFG;
 
         $status = true;
@@ -1654,10 +1654,10 @@
                 fwrite ($bf,start_tag("GROUP",3,true));
                 //Output group contents
                 fwrite ($bf,full_tag("ID",4,false,$group->id));
-                fwrite ($bf,full_tag("COURSEID",4,false,$group->courseid));
+                ///fwrite ($bf,full_tag("COURSEID",4,false,$group->courseid));
                 fwrite ($bf,full_tag("NAME",4,false,$group->name));
                 fwrite ($bf,full_tag("DESCRIPTION",4,false,$group->description));
-                fwrite ($bf,full_tag("PASSWORD",4,false,$group->password));
+                fwrite ($bf,full_tag("ENROLMENTKEY",4,false,$group->enrolmentkey)); //TODO:
                 fwrite ($bf,full_tag("LANG",4,false,$group->lang));
                 fwrite ($bf,full_tag("THEME",4,false,$group->theme));
                 fwrite ($bf,full_tag("PICTURE",4,false,$group->picture));
@@ -1683,7 +1683,7 @@
         }
         return ($status && $status2);
     }
-
+    
     //Backup groups_members info
     function backup_groups_members_info($bf,$preferences,$groupid) {
   
@@ -1692,7 +1692,7 @@
         $status = true;
 
         //Get groups_members
-        $groups_members = groups_get_members($groupid); //TODO:check.
+        $groups_members = groups_get_member_records($groupid);
         
         //Pring groups_members header
         if ($groups_members) {
@@ -1714,6 +1714,74 @@
         return $status;
     }
 
+    //Backup groupings info
+    function backup_groupings_info($bf,$preferences) {
+    
+        global $CFG;
+
+        $status = true;
+        $status2 = true;
+
+        //Get groups 
+        $groupings = groups_get_grouping_records($preferences->backup_course);
+
+        //Pring groups header
+        if ($groupings) {
+            //Pring groups header
+            fwrite ($bf,start_tag("GROUPINGS",2,true));
+            //Iterate
+            foreach ($groupings as $grouping) {
+                //Begin group tag
+                fwrite ($bf,start_tag("GROUPING",3,true));
+                //Output group contents
+                fwrite ($bf,full_tag("ID",4,false,$grouping->id));
+                fwrite ($bf,full_tag("NAME",4,false,$grouping->name));
+                fwrite ($bf,full_tag("DESCRIPTION",4,false,$grouping->description));
+                fwrite ($bf,full_tag("TIMECREATED",4,false,$grouping->timecreated));
+
+                $status2 = backup_groupids_info($bf,$preferences,$grouping->id);
+
+                //End group tag
+                fwrite ($bf,end_tag("GROUPING",3,true));
+            }
+            //End groups tag
+            $status = fwrite ($bf,end_tag("GROUPINGS",2,true));
+
+            //(Now save grouping_files)
+        }
+        return ($status && $status2);
+    }
+
+    //Backup groupings-groups info
+    function backup_groupids_info($bf,$preferences,$groupingid) {
+  
+        global $CFG;
+        
+        $status = true;
+
+        //Get groups_members
+        $grouping_groups = groups_get_groups_in_grouping_records($groupingid) ;
+        
+        //Pring groups_members header
+        if ($grouping_groups) {
+            //Pring groups_members header
+            fwrite ($bf,start_tag("GROUPS",4,true));
+            //Iterate
+            foreach ($grouping_groups as $group2) {
+                //Begin group tag
+                fwrite ($bf,start_tag("GROUP",5,true));
+                //Output group_member contents
+                fwrite ($bf,full_tag("GROUPID",6,false,$group2->groupid));
+                fwrite ($bf,full_tag("TIMEADDED",6,false,$group2->timeadded)); //TODO:
+                //End group tag
+                fwrite ($bf,end_tag("GROUP",5,true));
+            }
+            //End groups_members tag
+            $status = fwrite ($bf,end_tag("GROUPS",4,true));
+        }
+        return $status;
+    }
+
     //Start the modules tag
     function backup_modules_start ($bf,$preferences) {
       
Index: lang/en_utf8/moodle.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lang/en_utf8/moodle.php,v
retrieving revision 1.100
diff -u -r1.100 moodle.php
--- lang/en_utf8/moodle.php	19 Jan 2007 11:10:10 -0000	1.100
+++ lang/en_utf8/moodle.php	20 Jan 2007 09:24:06 -0000
@@ -297,6 +297,7 @@
 $string['creatingevents'] = 'Creating events';
 $string['creatinggradebook'] = 'Creating gradebook';
 $string['creatinggroups'] = 'Creating groups';
+$string['creatinggroupings'] = 'Creating groupings';
 $string['creatinglogentries'] = 'Creating log entries';
 $string['creatingmessagesinfo'] = 'Creating messages info';
 $string['creatingmetacoursedata'] = 'Creating metacourse info';
@@ -1498,6 +1499,7 @@
 $string['writinggeneralinfo'] = 'Writing general info';
 $string['writinggradebookinfo'] = 'Writing gradebook info';
 $string['writinggroupsinfo'] = 'Writing groups info';
+$string['writinggroupingsinfo'] = 'Writing groupings info';
 $string['writingheader'] = 'Writing header';
 $string['writingloginfo'] = 'Writing logs info';
 $string['writingmessagesinfo'] = 'Writing messages info';
Index: group/db/dbbasicgrouplib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/group/db/dbbasicgrouplib.php,v
retrieving revision 1.7
diff -u -r1.7 dbbasicgrouplib.php
--- group/db/dbbasicgrouplib.php	17 Jan 2007 14:33:29 -0000	1.7
+++ group/db/dbbasicgrouplib.php	20 Jan 2007 09:24:02 -0000
@@ -123,12 +123,13 @@
  * @param $courseid Optionally add the course ID, for backwards compatibility.
  * @return object The group settings object 
  */
-function groups_db_get_group_settings($groupid, $courseid=false) {
+function groups_db_get_group_settings($groupid, $courseid=false, $alldata=false) {
    if (!$groupid) {
         $groupsettings = false;
     } else {
         global $CFG;
-        $sql = "SELECT id, name, description, lang, theme, picture, hidepicture 
+        $select = ($alldata) ? '*' : 'id, name, description, lang, theme, picture, hidepicture';
+        $sql = "SELECT $select
                 FROM {$CFG->prefix}groups
                 WHERE id = $groupid";
         $groupsettings = get_record_sql($sql);
@@ -234,16 +235,19 @@
  * @param int $courseid The course to create the group for
  * @return int The id of the group created or false if the create failed.
  */
-function groups_db_create_group($courseid, $groupsettings = false) {
+function groups_db_create_group($courseid, $groupsettings=false, $copytime=false) {
 	// Check we have a valid course id
     if (!$courseid) {
         $groupid = false; 
     } else {      
     	$groupsettings = groups_set_default_group_settings($groupsettings);
-    		
+
     	$record = $groupsettings;
-        $record->timecreated = time();
-        $record->timemodified = time();
+        if (! $copytime) {
+            $now = time();
+            $record->timecreated = $now;
+            $record->timemodified = $now;
+        }
         //print_r($record);
         $groupid = insert_record('groups', $record);
 
@@ -251,7 +255,11 @@
             $record2 = new Object();
 	        $record2->courseid = $courseid;
 	        $record2->groupid = $groupid;
-	        $record2->timeadded = time();
+           if ($copytime) {
+                $record2->timeadded = $record->timemodified;
+            } else {
+                $record2->timeadded = $now;
+            }
 	        $groupadded = insert_record('groups_courses_groups', $record2);
 	        if (!$groupadded) {
 	        	$groupid = false;
@@ -268,7 +276,7 @@
  * @param int $userid   The user id
  * @return boolean True if user added successfully, false otherwise. 
  */
-function groups_db_add_member($groupid, $userid) {
+function groups_db_add_member($groupid, $userid, $copytime=false) {
 	// Check that the user and group are valid
     if (!$userid or !$groupid or !groups_db_group_exists($groupid)) {
         $useradded = false;
@@ -280,7 +288,11 @@
         $record = new Object();
 		$record->groupid = $groupid;
 		$record->userid = $userid;
-		$record->timeadded = time();
+        if ($copytime) {
+            $record->timeadded = $copytime;
+        } else {
+		    $record->timeadded = time();
+        }
 		$useradded = insert_record($table = 'groups_members', $record);
 	}
 
