|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 //This file contains all the general function needed (file manipulation...) 00003 //not directly part of the backup/restore utility plus some constants 00004 00005 // Define "restoreto" options 00006 define('RESTORETO_CURRENT_DELETING', 0); 00007 define('RESTORETO_CURRENT_ADDING', 1); 00008 define('RESTORETO_NEW_COURSE', 2); 00009 define('RESTORETO_EXISTING_DELETING', 3); 00010 define('RESTORETO_EXISTING_ADDING', 4); 00011 00012 require_once($CFG->libdir . '/completionlib.php'); 00013 00014 //Sets a name/value pair in config_plugin table 00015 function backup_set_config($name, $value) { 00016 return set_config($name, $value, 'backup'); 00017 } 00018 00019 //Gets all the information from config_plugin table 00020 function backup_get_config() { 00021 $backup_config = get_config('backup'); 00022 return (object)$backup_config; 00023 } 00024 00025 //Delete old data in backup tables (if exists) 00026 //Four hours seem to be appropiate now that backup is stable 00027 function backup_delete_old_data() { 00028 global $CFG, $DB; 00029 00030 //Change this if you want !! 00031 $hours = 4; 00032 //End change this 00033 $seconds = $hours * 60 * 60; 00034 $delete_from = time()-$seconds; 00035 //Now delete from tables 00036 $status = $DB->execute("DELETE FROM {backup_ids} 00037 WHERE backup_code < ?", array($delete_from)); 00038 if ($status) { 00039 $status = $DB->execute("DELETE FROM {backup_files} 00040 WHERE backup_code < ?", array($delete_from)); 00041 } 00042 //Now, delete old directory (if exists) 00043 if ($status) { 00044 $status = backup_delete_old_dirs($delete_from); 00045 } 00046 return($status); 00047 } 00048 00049 //Function to delete dirs/files into temp/backup directory 00050 //older than $delete_from 00051 function backup_delete_old_dirs($delete_from) { 00052 00053 global $CFG; 00054 00055 $status = true; 00056 //Get files and directories in the temp backup dir witout descend 00057 $list = get_directory_list($CFG->tempdir."/backup", "", false, true, true); 00058 foreach ($list as $file) { 00059 $file_path = $CFG->tempdir."/backup/".$file; 00060 $moddate = filemtime($file_path); 00061 if ($status && $moddate < $delete_from) { 00062 //If directory, recurse 00063 if (is_dir($file_path)) { 00064 $status = delete_dir_contents($file_path); 00065 //There is nothing, delete the directory itself 00066 if ($status) { 00067 $status = rmdir($file_path); 00068 } 00069 //If file 00070 } else { 00071 unlink("$file_path"); 00072 } 00073 } 00074 } 00075 00076 return $status; 00077 } 00078 00079 //Function to check and create the needed dir to 00080 //save all the backup 00081 function check_and_create_backup_dir($backup_unique_code) { 00082 global $CFG; 00083 00084 $status = check_dir_exists($CFG->tempdir."",true); 00085 if ($status) { 00086 $status = check_dir_exists($CFG->tempdir."/backup",true); 00087 } 00088 if ($status) { 00089 $status = check_dir_exists($CFG->tempdir."/backup/".$backup_unique_code,true); 00090 } 00091 00092 return $status; 00093 } 00094 00095 //Function to delete all the directory contents recursively 00096 //it supports a excluded dit too 00097 //Copied from the web !! 00098 function delete_dir_contents ($dir,$excludeddir="") { 00099 global $CFG; 00100 00101 if (!is_dir($dir)) { 00102 // if we've been given a directory that doesn't exist yet, return true. 00103 // this happens when we're trying to clear out a course that has only just 00104 // been created. 00105 return true; 00106 } 00107 $slash = "/"; 00108 00109 // Create arrays to store files and directories 00110 $dir_files = array(); 00111 $dir_subdirs = array(); 00112 00113 // Make sure we can delete it 00114 chmod($dir, $CFG->directorypermissions); 00115 00116 if ((($handle = opendir($dir))) == FALSE) { 00117 // The directory could not be opened 00118 return false; 00119 } 00120 00121 // Loop through all directory entries, and construct two temporary arrays containing files and sub directories 00122 while (false !== ($entry = readdir($handle))) { 00123 if (is_dir($dir. $slash .$entry) && $entry != ".." && $entry != "." && $entry != $excludeddir) { 00124 $dir_subdirs[] = $dir. $slash .$entry; 00125 } 00126 else if ($entry != ".." && $entry != "." && $entry != $excludeddir) { 00127 $dir_files[] = $dir. $slash .$entry; 00128 } 00129 } 00130 00131 // Delete all files in the curent directory return false and halt if a file cannot be removed 00132 $countdirfiles = count($dir_files); 00133 for ($i=0; $i<$countdirfiles; $i++) { 00134 chmod($dir_files[$i], $CFG->directorypermissions); 00135 if (((unlink($dir_files[$i]))) == FALSE) { 00136 return false; 00137 } 00138 } 00139 00140 // Empty sub directories and then remove the directory 00141 $countdirsubdirs = count($dir_subdirs); 00142 for($i=0; $i<$countdirsubdirs; $i++) { 00143 chmod($dir_subdirs[$i], $CFG->directorypermissions); 00144 if (delete_dir_contents($dir_subdirs[$i]) == FALSE) { 00145 return false; 00146 } 00147 else { 00148 if (remove_dir($dir_subdirs[$i]) == FALSE) { 00149 return false; 00150 } 00151 } 00152 } 00153 00154 // Close directory 00155 closedir($handle); 00156 00157 // Success, every thing is gone return true 00158 return true; 00159 } 00160 00161 //Function to clear (empty) the contents of the backup_dir 00162 function clear_backup_dir($backup_unique_code) { 00163 global $CFG; 00164 00165 $rootdir = $CFG->tempdir."/backup/".$backup_unique_code; 00166 00167 //Delete recursively 00168 $status = delete_dir_contents($rootdir); 00169 00170 return $status; 00171 } 00172 00173 //Returns the module type of a course_module's id in a course 00174 function get_module_type ($courseid,$moduleid) { 00175 global $DB; 00176 00177 $results = $DB->get_records_sql("SELECT cm.id, m.name 00178 FROM {course_modules} cm, {modules} m 00179 WHERE cm.course = ? AND cm.id = ? AND 00180 m.id = cm.module", array($courseid, $moduleid)); 00181 00182 if ($results) { 00183 $name = $results[$moduleid]->name; 00184 } else { 00185 $name = false; 00186 } 00187 return $name; 00188 } 00189 00190 //This function return the names of all directories under a give directory 00191 //Not recursive 00192 function list_directories ($rootdir) { 00193 00194 $results = null; 00195 00196 $dir = opendir($rootdir); 00197 while (false !== ($file=readdir($dir))) { 00198 if ($file=="." || $file=="..") { 00199 continue; 00200 } 00201 if (is_dir($rootdir."/".$file)) { 00202 $results[$file] = $file; 00203 } 00204 } 00205 closedir($dir); 00206 return $results; 00207 } 00208 00209 //This function return the names of all directories and files under a give directory 00210 //Not recursive 00211 function list_directories_and_files ($rootdir) { 00212 00213 $results = ""; 00214 00215 $dir = opendir($rootdir); 00216 while (false !== ($file=readdir($dir))) { 00217 if ($file=="." || $file=="..") { 00218 continue; 00219 } 00220 $results[$file] = $file; 00221 } 00222 closedir($dir); 00223 return $results; 00224 } 00225 00226 //This function clean data from backup tables and 00227 //delete all temp files used 00228 function clean_temp_data ($preferences) { 00229 global $CFG, $DB; 00230 00231 $status = true; 00232 00233 //true->do it, false->don't do it. To debug if necessary. 00234 if (true) { 00235 //Now delete from tables 00236 $status = $DB->delete_records('backup_ids', array('backup_code'=>$preferences->backup_unique_code)) 00237 && $DB->delete_records('backup_files', array('backup_code'=>$preferences->backup_unique_code)); 00238 00239 //Now, delete temp directory (if exists) 00240 $file_path = $CFG->tempdir."/backup/".$preferences->backup_unique_code; 00241 if (is_dir($file_path)) { 00242 $status = delete_dir_contents($file_path); 00243 //There is nothing, delete the directory itself 00244 if ($status) { 00245 $status = rmdir($file_path); 00246 } 00247 } 00248 } 00249 return $status; 00250 } 00251 00252 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00253 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00254 //This functions are used to copy any file or directory ($from_file) 00255 //to a new file or directory ($to_file). It works recursively and 00256 //mantains file perms. 00257 //I've copied it from: http://www.php.net/manual/en/function.copy.php 00258 //Little modifications done 00259 00260 function backup_copy_file ($from_file,$to_file,$log_clam=false) { 00261 global $CFG; 00262 00263 if (is_file($from_file)) { 00264 //echo "<br />Copying ".$from_file." to ".$to_file; //Debug 00265 //$perms=fileperms($from_file); 00266 //return copy($from_file,$to_file) && chmod($to_file,$perms); 00267 umask(0000); 00268 if (copy($from_file,$to_file)) { 00269 chmod($to_file,$CFG->directorypermissions); 00270 if (!empty($log_clam)) { 00271 //clam_log_upload($to_file,null,true); 00272 } 00273 return true; 00274 } 00275 return false; 00276 } 00277 else if (is_dir($from_file)) { 00278 return backup_copy_dir($from_file,$to_file); 00279 } 00280 else{ 00281 //echo "<br />Error: not file or dir ".$from_file; //Debug 00282 return false; 00283 } 00284 } 00285 00286 function backup_copy_dir($from_file,$to_file) { 00287 global $CFG; 00288 00289 $status = true; // Initialize this, next code will change its value if needed 00290 00291 if (!is_dir($to_file)) { 00292 //echo "<br />Creating ".$to_file; //Debug 00293 umask(0000); 00294 $status = mkdir($to_file,$CFG->directorypermissions); 00295 } 00296 $dir = opendir($from_file); 00297 while (false !== ($file=readdir($dir))) { 00298 if ($file=="." || $file=="..") { 00299 continue; 00300 } 00301 $status = backup_copy_file ("$from_file/$file","$to_file/$file"); 00302 } 00303 closedir($dir); 00304 return $status; 00305 } 00307 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00308 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00309 00317 function backup_is_same_site(&$restore) { 00318 global $CFG; 00319 static $hashedsiteid = null; 00320 if (is_null($hashedsiteid)) { 00321 $hashedsiteid = md5(get_site_identifier()); 00322 } 00323 if (!empty($restore->original_siteidentifier)) { 00324 return $restore->original_siteidentifier == $hashedsiteid; 00325 } else { 00326 return $restore->original_wwwroot == $CFG->wwwroot; 00327 } 00328 } 00329 00330 //This function is used to insert records in the backup_ids table 00331 //If the info field is greater than max_db_storage, then its info 00332 //is saved to filesystem 00333 function backup_putid($backup_unique_code, $table, $old_id, $new_id, $info="") { 00334 global $CFG, $DB; 00335 00336 $max_db_storage = 128; //Max bytes to save to db, else save to file 00337 00338 $status = true; 00339 00340 //First delete to avoid PK duplicates 00341 $status = backup_delid($backup_unique_code, $table, $old_id); 00342 00343 //Now, serialize info 00344 $info_ser = serialize($info); 00345 00346 //Now, if the size of $info_ser > $max_db_storage, save it to filesystem and 00347 //insert a "infile" in the info field 00348 00349 if (strlen($info_ser) > $max_db_storage) { 00350 //Calculate filename (in current_backup_dir, $backup_unique_code_$table_$old_id.info) 00351 $filename = $CFG->tempdir."/backup/".$backup_unique_code."/".$backup_unique_code."_".$table."_".$old_id.".info"; 00352 //Save data to file 00353 $status = backup_data2file($filename,$info_ser); 00354 //Set info_to save 00355 $info_to_save = "infile"; 00356 } else { 00357 //Saving to db 00358 $info_to_save = $info_ser; 00359 } 00360 00361 //Now, insert the record 00362 if ($status) { 00363 //Build the record 00364 $rec = new stdClass(); 00365 $rec->backup_code = $backup_unique_code; 00366 $rec->table_name = $table; 00367 $rec->old_id = $old_id; 00368 $rec->new_id = ($new_id === null? 0 : $new_id); 00369 $rec->info = $info_to_save; 00370 00371 $DB->insert_record('backup_ids', $rec, false); 00372 } 00373 return $status; 00374 } 00375 00376 //This function is used to delete recods from the backup_ids table 00377 //If the info field is "infile" then the file is deleted too 00378 function backup_delid ($backup_unique_code, $table, $old_id) { 00379 global $DB; 00380 return $DB->delete_records('backup_ids', array('backup_code'=>$backup_unique_code, 'table_name'=>$table, 'old_id'=>$old_id)); 00381 } 00382 00383 //This function is used to get a record from the backup_ids table 00384 //If the info field is "infile" then its info 00385 //is read from filesystem 00386 function backup_getid ($backup_unique_code, $table, $old_id) { 00387 global $CFG, $DB; 00388 00389 $status = true; 00390 $status2 = true; 00391 00392 $status = $DB->get_record("backup_ids", array("backup_code"=>$backup_unique_code, 00393 "table_name"=>$table, "old_id"=>$old_id)); 00394 00395 //If info field = "infile", get file contents 00396 if (!empty($status->info) && $status->info == "infile") { 00397 $filename = $CFG->tempdir."/backup/".$backup_unique_code."/".$backup_unique_code."_".$table."_".$old_id.".info"; 00398 //Read data from file 00399 $status2 = backup_file2data($filename,$info); 00400 if ($status2) { 00401 //unserialize data 00402 $status->info = unserialize($info); 00403 } else { 00404 $status = false; 00405 } 00406 } else { 00407 //Only if status (record exists) 00408 if (!empty($status->info)) { 00409 if ($status->info === 'needed') { 00410 // TODO: ugly hack - fix before 1.9.1 00411 debugging('Incorrect string "needed" in $status->info, please fix the code (table:'.$table.'; old_id:'.$old_id.').', DEBUG_DEVELOPER); 00412 } else { 00414 $temp = $status->info; 00415 //Now unserialize 00416 $status->info = unserialize($temp); 00417 } 00418 } 00419 } 00420 00421 return $status; 00422 } 00423 00424 //This function is used to add slashes (and decode from UTF-8 if needed) 00425 //It's used intensivelly when restoring modules and saving them in db 00426 function backup_todb ($data) { 00427 // MDL-10770 00428 if ($data === '$@NULL@$') { 00429 return null; 00430 } else { 00431 return restore_decode_absolute_links($data); 00432 } 00433 } 00434 00435 //This function is used to check that every necessary function to 00436 //backup/restore exists in the current php installation. Thanks to 00437 //gregb@crowncollege.edu by the idea. 00438 function backup_required_functions($justcheck=false) { 00439 00440 if(!function_exists('utf8_encode')) { 00441 if (empty($justcheck)) { 00442 print_error('needphpext', '', '', 'XML'); 00443 } else { 00444 return false; 00445 } 00446 } 00447 00448 return true; 00449 } 00450 00451 //This function send n white characters to the browser and flush the 00452 //output buffer. Used to avoid browser timeouts and to show the progress. 00453 function backup_flush($n=0,$time=false) { 00454 if (defined('RESTORE_SILENTLY_NOFLUSH')) { 00455 return; 00456 } 00457 if ($time) { 00458 $ti = strftime("%X",time()); 00459 } else { 00460 $ti = ""; 00461 } 00462 echo str_repeat(" ", $n) . $ti . "\n"; 00463 flush(); 00464 } 00465 00466 //This function creates the filename and write data to it 00467 //returning status as result 00468 function backup_data2file ($file,&$data) { 00469 00470 $status = true; 00471 $status2 = true; 00472 00473 $f = fopen($file,"w"); 00474 $status = fwrite($f,$data); 00475 $status2 = fclose($f); 00476 00477 return ($status && $status2); 00478 } 00479 00480 //This function read the filename and read data from it 00481 function backup_file2data ($file,&$data) { 00482 00483 $status = true; 00484 $status2 = true; 00485 00486 $f = fopen($file,"r"); 00487 $data = fread ($f,filesize($file)); 00488 $status2 = fclose($f); 00489 00490 return ($status && $status2); 00491 }