Fixes bug MDL-8057, "Backup/restore code not considered in new groups code"

This commit is contained in:
nfreear 2007-01-20 09:28:26 +00:00
parent 9467ab7ddf
commit d8aa3550bb
9 changed files with 468 additions and 27 deletions

View File

@ -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>';

View File

@ -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) {

View File

@ -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) {

View File

@ -123,12 +123,13 @@ function groups_db_get_groups_for_user($userid, $courseid) {
* @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 @@ function groups_db_group_belongs_to_course($groupid, $courseid) {
* @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 @@ function groups_db_create_group($courseid, $groupsettings = false) {
$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 @@ function groups_db_create_group($courseid, $groupsettings = false) {
* @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 @@ function groups_db_add_member($groupid, $userid) {
$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);
}

View File

@ -54,6 +54,19 @@ function groups_get_members($groupid, $membertype = false) {
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 @@ function groups_get_groups_for_current_user($courseid) {
* @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);
}
/**
@ -178,6 +191,28 @@ function groups_group_exists($groupid) {
return groups_db_group_exists($groupid);
}
/**
* 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
@ -263,6 +298,14 @@ function groups_create_group($courseid, $groupsettings = false) {
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 @@ function groups_add_member($groupid, $userid) {
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

View File

@ -30,6 +30,25 @@ function groups_get_groupings($courseid) {
}
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 @@ function groups_get_groups_in_grouping($groupingid) {
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_get_grouping_for_coursemodule($coursemoduleid) {
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

View File

@ -56,7 +56,7 @@ function get_groups($courseid, $userid=0) {
$groupids = groups_get_groups($courseid);
}
return groups_groupids_to_groups($groupids, $courseid);
return groups_groupids_to_groups($groupids, $courseid, $alldata=true);
}

View File

@ -160,18 +160,32 @@ function groups_groupid_to_group($groupid) {
/**
* 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

View File

@ -297,6 +297,7 @@ $string['creatingcourseroles'] = 'Creating course level role assignments and ove
$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['writingeventsinfo'] = 'Writing events info';
$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';