Changes in:
- Saving temp data to fs, instead of db
(mysql limit bug OUT)
- Modified clean directories (moodle standard delete dir
function seems to work wrong with large dirs
- Send info to browser continuosly to avoid timeouts.
- Increase php execution time limit
- More checks.
- Restore into existing course now works fine
- Create course_dir if it doesn't exist in the final step
of backup.
This commit is contained in:
+25
-6
@@ -866,13 +866,32 @@
|
||||
|
||||
global $CFG;
|
||||
|
||||
//Backup zip file name
|
||||
//Define zip location (from)
|
||||
$from_zip_file = $CFG->dataroot."/temp/backup/".$preferences->backup_unique_code."/".$preferences->backup_name;
|
||||
$to_zip_file = $CFG->dataroot."/".$preferences->backup_course."/".get_string("backupdir")."/".$preferences->backup_name;
|
||||
|
||||
//Check to directory
|
||||
$status = check_dir_exists(dirname($to_zip_file),true);
|
||||
|
||||
|
||||
//Define zip destination (course dir)
|
||||
$to_zip_file = $CFG->dataroot."/".$preferences->backup_course;
|
||||
|
||||
echo "<p>From: ".$from_zip_file."<br>"; //Debug
|
||||
|
||||
echo "<p>Checking: ".$to_zip_file."<br>"; //Debug
|
||||
|
||||
//Checks course dir exists
|
||||
$status = check_dir_exists($to_zip_file,true);
|
||||
|
||||
//Define zip destination (backup dir)
|
||||
$to_zip_file = $to_zip_file."/".get_string("backupdir");
|
||||
|
||||
echo "<p>Checking: ".$to_zip_file."<br>"; //Debug
|
||||
|
||||
//Checks backup dir exists
|
||||
$status = check_dir_exists($to_zip_file,true);
|
||||
|
||||
//Define zip destination (zip file)
|
||||
$to_zip_file = $to_zip_file."/".$preferences->backup_name;
|
||||
|
||||
echo "<p>To: ".$to_zip_file."<br>"; //Debug
|
||||
|
||||
//Copy zip file
|
||||
if ($status) {
|
||||
$status = backup_copy_file ($from_zip_file,$to_zip_file);
|
||||
|
||||
+124
-25
@@ -38,7 +38,7 @@
|
||||
foreach ($list as $file) {
|
||||
$file_path = $CFG->dataroot."/temp/backup/".$file;
|
||||
$moddate = filemtime($file_path);
|
||||
if ($status and $moddate < $delete_from) {
|
||||
if ($status && $moddate < $delete_from) {
|
||||
//If directory, recurse
|
||||
if (is_dir($file_path)) {
|
||||
$status = delete_dir_contents($file_path);
|
||||
@@ -92,36 +92,62 @@
|
||||
}
|
||||
|
||||
//Function to delete all the directory contents recursively
|
||||
//Copied from admin/delete.php
|
||||
function delete_dir_contents ($rootdir) {
|
||||
//Copied from the web !!
|
||||
function delete_dir_contents ($dir) {
|
||||
|
||||
$dir = opendir($rootdir);
|
||||
$slash = "/";
|
||||
|
||||
$status = true;
|
||||
// Create arrays to store files and directories
|
||||
$dir_files = array();
|
||||
$dir_subdirs = array();
|
||||
|
||||
while ($file = readdir($dir)) {
|
||||
if ($file != "." and $file != "..") {
|
||||
$fullfile = "$rootdir/$file";
|
||||
if (filetype($fullfile) == "dir") {
|
||||
delete_dir_contents($fullfile);
|
||||
if (!rmdir($fullfile)) {
|
||||
$status = false;
|
||||
}
|
||||
} else {
|
||||
if (!unlink("$fullfile")) {
|
||||
$status = false;
|
||||
}
|
||||
// Make sure we can delete it
|
||||
chmod($dir, 0777);
|
||||
|
||||
if ((($handle = opendir($dir))) == FALSE) {
|
||||
// The directory could not be opened
|
||||
return false;
|
||||
}
|
||||
|
||||
// Loop through all directory entries, and construct two temporary arrays containing files and sub directories
|
||||
while($entry = readdir($handle)) {
|
||||
if (is_dir($dir. $slash .$entry) && $entry != ".." && $entry != ".") {
|
||||
$dir_subdirs[] = $dir. $slash .$entry;
|
||||
}
|
||||
else if ($entry != ".." && $entry != ".") {
|
||||
$dir_files[] = $dir. $slash .$entry;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete all files in the curent directory return false and halt if a file cannot be removed
|
||||
for($i=0; $i<count($dir_files); $i++) {
|
||||
chmod($dir_files[$i], 0777);
|
||||
if (((unlink($dir_files[$i]))) == FALSE) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Empty sub directories and then remove the directory
|
||||
for($i=0; $i<count($dir_subdirs); $i++) {
|
||||
chmod($dir_subdirs[$i], 0777);
|
||||
if (delete_dir_contents($dir_subdirs[$i]) == FALSE) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if (rmdir($dir_subdirs[$i]) == FALSE) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir($dir);
|
||||
|
||||
return $status;
|
||||
|
||||
// Close directory
|
||||
closedir($handle);
|
||||
|
||||
// Success, every thing is gone return true
|
||||
return true;
|
||||
}
|
||||
|
||||
//Function to clear (empty) the contents of the backup_dir
|
||||
//Copied from admin/delete.php
|
||||
function clear_backup_dir($backup_unique_code) {
|
||||
|
||||
global $CFG;
|
||||
@@ -305,23 +331,50 @@
|
||||
}
|
||||
|
||||
//This function is used to insert records in the backup_ids table
|
||||
//If the info field is greater than max_db_storage, then its info
|
||||
//is saved to filesystem
|
||||
function backup_putid ($backup_unique_code, $table, $old_id, $new_id, $info="") {
|
||||
|
||||
global $CFG;
|
||||
|
||||
$max_db_storage = 128; //Max bytes to save to db, else save to file
|
||||
//MUST BE LOWER THAN 256 (VARCHAR LIMIT)
|
||||
|
||||
$status = true;
|
||||
|
||||
//First delete to avoid PK duplicates
|
||||
$status = backup_delid($backup_unique_code, $table, $old_id);
|
||||
|
||||
$status = execute_sql("INSERT INTO {$CFG->prefix}backup_ids
|
||||
(backup_code, table_name, old_id, new_id, info)
|
||||
VALUES
|
||||
($backup_unique_code, '$table', '$old_id', '$new_id', '$info')",false);
|
||||
//Now, serialize info
|
||||
$info_ser = serialize($info);
|
||||
|
||||
//Now, if the size of $info_ser > $max_db_storage, save it to filesystem and
|
||||
//insert a "infile" in the info field
|
||||
|
||||
if (strlen($info_ser) > $max_db_storage) {
|
||||
//Calculate filename (in current_backup_dir, $backup_unique_code_$table_$old_id.info)
|
||||
$filename = $CFG->dataroot."/temp/backup/".$backup_unique_code."/".$backup_unique_code."_".$table."_".$old_id.".info";
|
||||
//Save data to file
|
||||
$status = backup_data2file($filename,$info_ser);
|
||||
//Set info_to save
|
||||
$info_to_save = "infile";
|
||||
} else {
|
||||
//Saving to db, addslashes
|
||||
$info_to_save = addslashes($info_ser);
|
||||
}
|
||||
|
||||
//Now, insert the record
|
||||
if ($status) {
|
||||
$status = execute_sql("INSERT INTO {$CFG->prefix}backup_ids
|
||||
(backup_code, table_name, old_id, new_id, info)
|
||||
VALUES
|
||||
($backup_unique_code, '$table', '$old_id', '$new_id', '$info_to_save')",false);
|
||||
}
|
||||
return $status;
|
||||
}
|
||||
|
||||
//This function is used to delete recods from the backup_ids table
|
||||
//If the info field is "infile" then the file is deleted too
|
||||
function backup_delid ($backup_unique_code, $table, $old_id) {
|
||||
|
||||
global $CFG;
|
||||
@@ -336,16 +389,37 @@
|
||||
}
|
||||
|
||||
//This function is used to get a record from the backup_ids table
|
||||
//If the info field is "infile" then its info
|
||||
//is read from filesystem
|
||||
function backup_getid ($backup_unique_code, $table, $old_id) {
|
||||
|
||||
global $CFG;
|
||||
|
||||
$status = true;
|
||||
$status2 = true;
|
||||
|
||||
$status = get_record ("backup_ids","backup_code",$backup_unique_code,
|
||||
"table_name",$table,
|
||||
"old_id", $old_id);
|
||||
|
||||
//If info field = "infile", get file contents
|
||||
if ($status->info == "infile") {
|
||||
$filename = $CFG->dataroot."/temp/backup/".$backup_unique_code."/".$backup_unique_code."_".$table."_".$old_id.".info";
|
||||
//Read data from file
|
||||
$status2 = backup_file2data($filename,$info);
|
||||
if ($status2) {
|
||||
//unserialize data
|
||||
$status->info = unserialize($info);
|
||||
} else {
|
||||
$status = false;
|
||||
}
|
||||
} else {
|
||||
////First strip slashes
|
||||
$temp = stripslashes($status->info);
|
||||
//Now unserialize
|
||||
$status->info = unserialize($temp);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
@@ -378,5 +452,30 @@
|
||||
flush();
|
||||
}
|
||||
|
||||
//This function creates the filename and write data to it
|
||||
//returning status as result
|
||||
function backup_data2file ($file,&$data) {
|
||||
|
||||
$status = true;
|
||||
$status2 = true;
|
||||
|
||||
$f = fopen($file,"w");
|
||||
$status = fwrite($f,$data);
|
||||
$status2 = fclose($f);
|
||||
|
||||
return ($status && $status2);
|
||||
}
|
||||
|
||||
//This function read the filename and read data from it
|
||||
function backup_file2data ($file,&$data) {
|
||||
|
||||
$status = true;
|
||||
$status2 = true;
|
||||
|
||||
$f = fopen($file,"r");
|
||||
$data = fread ($f,filesize($file));
|
||||
$status2 = fclose($f);
|
||||
|
||||
return ($status && $status2);
|
||||
}
|
||||
?>
|
||||
|
||||
+42
-37
@@ -443,10 +443,7 @@
|
||||
//For each, user, take its info from backup_ids
|
||||
foreach ($info->users as $userid) {
|
||||
$rec = backup_getid($restore->backup_unique_code,"user",$userid);
|
||||
//First strip slashes
|
||||
$temp = stripslashes($rec->info);
|
||||
//Now unserialize
|
||||
$user = unserialize($temp);
|
||||
$user = $rec->info;
|
||||
//Calculate if it is a course user
|
||||
//Has role teacher or student or admin or coursecreator
|
||||
$is_course_user = ($user->roles[teacher] or $user->roles[student] or
|
||||
@@ -688,15 +685,17 @@
|
||||
//Now, if we have anything in info, we have to restore that mods
|
||||
//from backup_ids (calling every mod restore function)
|
||||
if ($info) {
|
||||
//Iterate over each module
|
||||
foreach ($info as $mod) {
|
||||
$modrestore = $mod->modtype."_restore_mods";
|
||||
if (function_exists($modrestore)) {
|
||||
//print_object ($mod); //Debug
|
||||
$status = $modrestore($mod,$restore);
|
||||
} else {
|
||||
//Something was wrong. Function should exist.
|
||||
$status = false;
|
||||
if ($info !== true) {
|
||||
//Iterate over each module
|
||||
foreach ($info as $mod) {
|
||||
$modrestore = $mod->modtype."_restore_mods";
|
||||
if (function_exists($modrestore)) {
|
||||
//print_object ($mod); //Debug
|
||||
$status = $modrestore($mod,$restore);
|
||||
} else {
|
||||
//Something was wrong. Function should exist.
|
||||
$status = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -714,23 +713,23 @@
|
||||
$status = true;
|
||||
|
||||
//We are going to iterate over each course_module saved in backup_ids
|
||||
$course_modules = get_records_sql("SELECT new_id,info as instance
|
||||
$course_modules = get_records_sql("SELECT old_id,new_id
|
||||
FROM {$CFG->prefix}backup_ids
|
||||
WHERE backup_code = '$restore->backup_unique_code' AND
|
||||
table_name = 'course_modules'");
|
||||
if ($course_modules) {
|
||||
foreach($course_modules as $cm) {
|
||||
//Get full record, using backup_getids
|
||||
$cm_module = backup_getid($restore->backup_unique_code,"course_modules",$cm->old_id);
|
||||
//Now we are going to the REAL course_modules to get its type (field module)
|
||||
$module = get_record("course_modules","id",$cm->new_id);
|
||||
$module = get_record("course_modules","id",$cm_module->new_id);
|
||||
if ($module) {
|
||||
//We know the module type id. Get the name from modules
|
||||
$type = get_record("modules","id",$module->module);
|
||||
if ($type) {
|
||||
//We know the type name and the old_id. Get its new_id
|
||||
//from backup_ids. It's the instance !!!
|
||||
$instance = get_record("backup_ids","backup_code",$restore->backup_unique_code,
|
||||
"table_name",$type->name,
|
||||
"old_id",$cm->instance);
|
||||
$instance = backup_getid($restore->backup_unique_code,$type->name,$cm_module->info);
|
||||
if ($instance) {
|
||||
//We have the new instance, so update the record in course_modules
|
||||
$module->instance = $instance->new_id;
|
||||
@@ -746,8 +745,6 @@
|
||||
$status = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$status = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -764,6 +761,7 @@
|
||||
class MoodleParser {
|
||||
|
||||
var $level = 0; //Level we are
|
||||
var $counter = 0; //Counter
|
||||
var $tree = array(); //Array of levels we are
|
||||
var $content = ""; //Content under current level
|
||||
var $todo = ""; //What we hav to do when parsing
|
||||
@@ -826,9 +824,6 @@
|
||||
$this->level++;
|
||||
$this->tree[$this->level] = $tagName;
|
||||
|
||||
//Output something to avoid browser timeouts...
|
||||
backup_flush();
|
||||
|
||||
//Check if we are into USERS zone
|
||||
//if ($this->tree[3] == "USERS") //Debug
|
||||
// echo $this->level.str_repeat(" ",$this->level*2)."<".$tagName."><br>\n"; //Debug
|
||||
@@ -840,6 +835,10 @@
|
||||
$this->level++;
|
||||
$this->tree[$this->level] = $tagName;
|
||||
|
||||
if ($tagName == "MOD" && $this->tree[3] == "MODULES") {
|
||||
echo "<P>MOD: ".strftime ("%X",time()),"-";
|
||||
}
|
||||
|
||||
//Output something to avoid browser timeouts...
|
||||
backup_flush();
|
||||
|
||||
@@ -1135,14 +1134,21 @@
|
||||
if ($this->level == 4) {
|
||||
switch ($tagName) {
|
||||
case "USER":
|
||||
//We've finalized a user, get it and save to db
|
||||
//First serialize
|
||||
$ser_temp = serialize($this->info->tempuser);
|
||||
//Now add slashes
|
||||
$sla_temp = addslashes($ser_temp);
|
||||
//Increment counter
|
||||
$this->counter++;
|
||||
//Save to db
|
||||
backup_putid($this->preferences->backup_unique_code,"user",$this->info->tempuser->id,
|
||||
null,$sla_temp);
|
||||
null,$this->info->tempuser);
|
||||
|
||||
//Do some output
|
||||
if ($this->counter % 10 == 0) {
|
||||
echo ".";
|
||||
if ($this->counter % 200 == 0) {
|
||||
echo "<br>";
|
||||
}
|
||||
backup_flush(300);
|
||||
}
|
||||
|
||||
//Delete temp obejct
|
||||
unset($this->info->tempuser);
|
||||
break;
|
||||
@@ -1298,6 +1304,7 @@
|
||||
//Speed up a lot (avoid parse all)
|
||||
if ($tagName == "USERS" and $this->level == 3) {
|
||||
$this->finished = true;
|
||||
$this->counter = 0;
|
||||
}
|
||||
|
||||
//Clear things
|
||||
@@ -1321,7 +1328,9 @@
|
||||
//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 MOD)
|
||||
echo "-XMLIZE: ".strftime ("%X",time()),"-";
|
||||
$data = xmlize($xml_data);
|
||||
echo strftime ("%X",time())."<p>";
|
||||
//traverse_xmlize($data); //Debug
|
||||
//print_object ($GLOBALS['traverse_array']); //Debug
|
||||
//$GLOBALS['traverse_array']=""; //Debug
|
||||
@@ -1331,21 +1340,17 @@
|
||||
$mod_type = $data["MOD"]["#"]["MODTYPE"]["0"]["#"];
|
||||
//Only if we've selected to restore it
|
||||
if ($this->preferences->mods[$mod_type]->restore) {
|
||||
//Serialize it
|
||||
$mod_temp = serialize($data);
|
||||
//Now add slashes
|
||||
$sla_mod_temp = addslashes($mod_temp);
|
||||
//Save to db
|
||||
$status = backup_putid($this->preferences->backup_unique_code,$mod_type,$mod_id,
|
||||
null,$sla_mod_temp);
|
||||
null,$data);
|
||||
//echo "<p>id: ".$mod_id."-".$mod_type." len.: ".strlen($sla_mod_temp)." to_db: ".$status."<p>"; //Debug
|
||||
//Create returning info
|
||||
$ret_info->id = $mod_id;
|
||||
$ret_info->modtype = $mod_type;
|
||||
$this->info[] = $ret_info;
|
||||
}
|
||||
//Reset info to empty
|
||||
$this->temp = "";
|
||||
//Reset temp
|
||||
unset($this->temp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1426,7 +1431,7 @@
|
||||
//Clear parser mem
|
||||
xml_parser_free($xml_parser);
|
||||
|
||||
if ($status) {
|
||||
if ($status && $info) {
|
||||
return $info;
|
||||
} else {
|
||||
return $status;
|
||||
|
||||
Reference in New Issue
Block a user