9704c866 |
1 | <?php //$Id$ |
52376d94 |
2 | //This file contains all the general function needed (file manipulation...) |
3 | //not directly part of the backup/restore utility |
afbe3de8 |
4 | |
8930f900 |
5 | require_once($CFG->dirroot.'/lib/uploadlib.php'); |
6 | |
de4746a8 |
7 | //Sets a name/value pair in backup_config table |
8 | function backup_set_config($name, $value) { |
9 | if (get_field("backup_config", "name", "name", $name)) { |
348d6827 |
10 | return set_field("backup_config", "value", addslashes($value), "name", $name); |
de4746a8 |
11 | } else { |
348d6827 |
12 | $config = new object(); |
de4746a8 |
13 | $config->name = $name; |
348d6827 |
14 | $config->value = addslashes($value); |
de4746a8 |
15 | return insert_record("backup_config", $config); |
16 | } |
17 | } |
18 | |
19 | //Gets all the information from backup_config table |
20 | function backup_get_config() { |
21 | $backup_config = null; |
37afa39a |
22 | if ($configs = get_records("backup_config")) { |
de4746a8 |
23 | foreach ($configs as $config) { |
24 | $backup_config[$config->name] = $config->value; |
25 | } |
26 | } |
49b95c30 |
27 | return (object)$backup_config; |
de4746a8 |
28 | } |
29 | |
b0778a76 |
30 | //Delete old data in backup tables (if exists) |
dfd02290 |
31 | //Four hours seem to be appropiate now that backup is stable |
b0778a76 |
32 | function backup_delete_old_data() { |
674b30f5 |
33 | |
34 | global $CFG; |
35 | |
b0778a76 |
36 | //Change this if you want !! |
dfd02290 |
37 | $hours = 4; |
b0778a76 |
38 | //End change this |
dfd02290 |
39 | $seconds = $hours * 60 * 60; |
b0778a76 |
40 | $delete_from = time()-$seconds; |
41 | //Now delete from tables |
674b30f5 |
42 | $status = execute_sql("DELETE FROM {$CFG->prefix}backup_ids |
43 | WHERE backup_code < '$delete_from'",false); |
44 | if ($status) { |
45 | $status = execute_sql("DELETE FROM {$CFG->prefix}backup_files |
46 | WHERE backup_code < '$delete_from'",false); |
47 | } |
3b8bad6f |
48 | //Now, delete old directory (if exists) |
49 | if ($status) { |
50 | $status = backup_delete_old_dirs($delete_from); |
51 | } |
b0778a76 |
52 | return($status); |
53 | } |
674b30f5 |
54 | |
3b8bad6f |
55 | //Function to delete dirs/files into temp/backup directory |
56 | //older than $delete_from |
57 | function backup_delete_old_dirs($delete_from) { |
58 | |
59 | global $CFG; |
60 | |
61 | $status = true; |
41bac9d0 |
62 | //Get files and directories in the temp backup dir witout descend |
63 | $list = get_directory_list($CFG->dataroot."/temp/backup", "", false, true, true); |
3b8bad6f |
64 | foreach ($list as $file) { |
65 | $file_path = $CFG->dataroot."/temp/backup/".$file; |
66 | $moddate = filemtime($file_path); |
af9cd955 |
67 | if ($status && $moddate < $delete_from) { |
cfb9c525 |
68 | //If directory, recurse |
69 | if (is_dir($file_path)) { |
70 | $status = delete_dir_contents($file_path); |
71 | //There is nothing, delete the directory itself |
72 | if ($status) { |
73 | $status = rmdir($file_path); |
74 | } |
75 | //If file |
76 | } else { |
77 | unlink("$file_path"); |
3b8bad6f |
78 | } |
79 | } |
80 | } |
81 | |
82 | return $status; |
83 | } |
84 | |
674b30f5 |
85 | //Function to check and create the needed dir to |
86 | //save all the backup |
87 | function check_and_create_backup_dir($backup_unique_code) { |
88 | |
89 | global $CFG; |
90 | |
91 | $status = check_dir_exists($CFG->dataroot."/temp",true); |
92 | if ($status) { |
93 | $status = check_dir_exists($CFG->dataroot."/temp/backup",true); |
94 | } |
95 | if ($status) { |
96 | $status = check_dir_exists($CFG->dataroot."/temp/backup/".$backup_unique_code,true); |
97 | } |
98 | |
99 | return $status; |
100 | } |
101 | |
102 | //Function to delete all the directory contents recursively |
35ea1594 |
103 | //it supports a excluded dit too |
af9cd955 |
104 | //Copied from the web !! |
35ea1594 |
105 | function delete_dir_contents ($dir,$excludeddir="") { |
674b30f5 |
106 | |
9e3775db |
107 | if (!is_dir($dir)) { |
108 | // if we've been given a directory that doesn't exist yet, return true. |
109 | // this happens when we're trying to clear out a course that has only just |
110 | // been created. |
111 | return true; |
112 | } |
af9cd955 |
113 | $slash = "/"; |
674b30f5 |
114 | |
af9cd955 |
115 | // Create arrays to store files and directories |
116 | $dir_files = array(); |
117 | $dir_subdirs = array(); |
674b30f5 |
118 | |
af9cd955 |
119 | // Make sure we can delete it |
120 | chmod($dir, 0777); |
121 | |
122 | if ((($handle = opendir($dir))) == FALSE) { |
123 | // The directory could not be opened |
124 | return false; |
125 | } |
126 | |
127 | // Loop through all directory entries, and construct two temporary arrays containing files and sub directories |
128 | while($entry = readdir($handle)) { |
35ea1594 |
129 | if (is_dir($dir. $slash .$entry) && $entry != ".." && $entry != "." && $entry != $excludeddir) { |
af9cd955 |
130 | $dir_subdirs[] = $dir. $slash .$entry; |
131 | } |
35ea1594 |
132 | else if ($entry != ".." && $entry != "." && $entry != $excludeddir) { |
af9cd955 |
133 | $dir_files[] = $dir. $slash .$entry; |
134 | } |
135 | } |
136 | |
137 | // Delete all files in the curent directory return false and halt if a file cannot be removed |
138 | for($i=0; $i<count($dir_files); $i++) { |
139 | chmod($dir_files[$i], 0777); |
140 | if (((unlink($dir_files[$i]))) == FALSE) { |
141 | return false; |
142 | } |
143 | } |
144 | |
145 | // Empty sub directories and then remove the directory |
146 | for($i=0; $i<count($dir_subdirs); $i++) { |
147 | chmod($dir_subdirs[$i], 0777); |
148 | if (delete_dir_contents($dir_subdirs[$i]) == FALSE) { |
149 | return false; |
150 | } |
151 | else { |
152 | if (rmdir($dir_subdirs[$i]) == FALSE) { |
153 | return false; |
674b30f5 |
154 | } |
155 | } |
156 | } |
674b30f5 |
157 | |
af9cd955 |
158 | // Close directory |
159 | closedir($handle); |
160 | |
161 | // Success, every thing is gone return true |
162 | return true; |
674b30f5 |
163 | } |
164 | |
165 | //Function to clear (empty) the contents of the backup_dir |
674b30f5 |
166 | function clear_backup_dir($backup_unique_code) { |
167 | |
168 | global $CFG; |
169 | |
170 | $rootdir = $CFG->dataroot."/temp/backup/".$backup_unique_code; |
171 | |
172 | //Delete recursively |
173 | $status = delete_dir_contents($rootdir); |
174 | |
175 | return $status; |
176 | } |
3b8bad6f |
177 | |
cfb9c525 |
178 | //Returns the module type of a course_module's id in a course |
179 | function get_module_type ($courseid,$moduleid) { |
180 | |
181 | global $CFG; |
182 | |
183 | $results = get_records_sql ("SELECT cm.id, m.name |
184 | FROM {$CFG->prefix}course_modules cm, |
185 | {$CFG->prefix}modules m |
186 | WHERE cm.course = '$courseid' AND |
187 | cm.id = '$moduleid' AND |
188 | m.id = cm.module"); |
189 | |
190 | if ($results) { |
191 | $name = $results[$moduleid]->name; |
192 | } else { |
193 | $name = false; |
194 | } |
52376d94 |
195 | return $name; |
667d2f2a |
196 | } |
197 | |
198 | //This function return the names of all directories under a give directory |
199 | //Not recursive |
200 | function list_directories ($rootdir) { |
97a49e63 |
201 | |
202 | $results = null; |
667d2f2a |
203 | |
204 | $dir = opendir($rootdir); |
205 | while ($file=readdir($dir)) { |
206 | if ($file=="." || $file=="..") { |
207 | continue; |
208 | } |
209 | if (is_dir($rootdir."/".$file)) { |
210 | $results[$file] = $file; |
211 | } |
212 | } |
213 | closedir($dir); |
214 | return $results; |
215 | } |
216 | |
217 | //This function return the names of all directories and files under a give directory |
218 | //Not recursive |
219 | function list_directories_and_files ($rootdir) { |
3a4b33c3 |
220 | |
221 | $results = ""; |
667d2f2a |
222 | |
223 | $dir = opendir($rootdir); |
224 | while ($file=readdir($dir)) { |
225 | if ($file=="." || $file=="..") { |
226 | continue; |
227 | } |
228 | $results[$file] = $file; |
229 | } |
230 | closedir($dir); |
231 | return $results; |
232 | } |
233 | |
47846965 |
234 | //This function clean data from backup tables and |
235 | //delete all temp files used |
236 | function clean_temp_data ($preferences) { |
237 | |
47846965 |
238 | global $CFG; |
239 | |
240 | $status = true; |
241 | |
242 | //true->do it, false->don't do it. To debug if necessary. |
243 | if (true) { |
244 | //Now delete from tables |
245 | $status = execute_sql("DELETE FROM {$CFG->prefix}backup_ids |
af478c0b |
246 | WHERE backup_code = '$preferences->backup_unique_code'",false); |
47846965 |
247 | if ($status) { |
248 | $status = execute_sql("DELETE FROM {$CFG->prefix}backup_files |
af478c0b |
249 | WHERE backup_code = '$preferences->backup_unique_code'",false); |
47846965 |
250 | } |
251 | //Now, delete temp directory (if exists) |
252 | $file_path = $CFG->dataroot."/temp/backup/".$preferences->backup_unique_code; |
253 | if (is_dir($file_path)) { |
254 | $status = delete_dir_contents($file_path); |
255 | //There is nothing, delete the directory itself |
256 | if ($status) { |
257 | $status = rmdir($file_path); |
258 | } |
259 | } |
260 | } |
261 | return $status; |
262 | } |
263 | |
efead3b9 |
264 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
265 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
266 | //This functions are used to copy any file or directory ($from_file) |
267 | //to a new file or directory ($to_file). It works recursively and |
268 | //mantains file perms. |
269 | //I've copied it from: http://www.php.net/manual/en/function.copy.php |
270 | //Little modifications done |
271 | |
d27920b9 |
272 | function backup_copy_file ($from_file,$to_file,$log_clam=false) { |
f654deea |
273 | |
274 | global $CFG; |
275 | |
efead3b9 |
276 | if (is_file($from_file)) { |
7ef0797d |
277 | //echo "<br />Copying ".$from_file." to ".$to_file; //Debug |
f654deea |
278 | //$perms=fileperms($from_file); |
279 | //return copy($from_file,$to_file) && chmod($to_file,$perms); |
280 | umask(0000); |
9704c866 |
281 | if (copy($from_file,$to_file)) { |
282 | chmod($to_file,$CFG->directorypermissions); |
d27920b9 |
283 | if (!empty($log_clam)) { |
284 | clam_log_upload($to_file,null,true); |
285 | } |
8930f900 |
286 | return true; |
287 | } |
288 | return false; |
efead3b9 |
289 | } |
290 | else if (is_dir($from_file)) { |
291 | return backup_copy_dir($from_file,$to_file); |
292 | } |
293 | else{ |
7ef0797d |
294 | //echo "<br />Error: not file or dir ".$from_file; //Debug |
efead3b9 |
295 | return false; |
296 | } |
cfb9c525 |
297 | } |
efead3b9 |
298 | |
299 | function backup_copy_dir($from_file,$to_file) { |
93808667 |
300 | |
301 | global $CFG; |
302 | |
615b4a13 |
303 | $status = true; // Initialize this, next code will change its value if needed |
304 | |
efead3b9 |
305 | if (!is_dir($to_file)) { |
7ef0797d |
306 | //echo "<br />Creating ".$to_file; //Debug |
f654deea |
307 | umask(0000); |
41923e75 |
308 | $status = mkdir($to_file,$CFG->directorypermissions); |
efead3b9 |
309 | } |
310 | $dir = opendir($from_file); |
311 | while ($file=readdir($dir)) { |
312 | if ($file=="." || $file=="..") { |
313 | continue; |
314 | } |
4f6ae69e |
315 | $status = backup_copy_file ("$from_file/$file","$to_file/$file"); |
efead3b9 |
316 | } |
4f6ae69e |
317 | closedir($dir); |
318 | return $status; |
efead3b9 |
319 | } |
320 | ///Ends copy file/dirs functions |
321 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
322 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
7641819d |
323 | |
10dcde40 |
324 | |
325 | function upgrade_backup_db($continueto) { |
326 | /// This function upgrades the backup tables, if necessary |
327 | /// It's called from admin/index.php, also backup.php and restore.php |
7641819d |
328 | |
6e4dc10f |
329 | global $CFG, $db; |
10dcde40 |
330 | |
331 | require_once ("$CFG->dirroot/backup/version.php"); // Get code versions |
332 | |
333 | if (empty($CFG->backup_version)) { // Backup has never been installed. |
334 | $strdatabaseupgrades = get_string("databaseupgrades"); |
a36f058e |
335 | print_header($strdatabaseupgrades, $strdatabaseupgrades, $strdatabaseupgrades, "", |
371a32e3 |
336 | upgrade_get_javascript(), false, " ", " "); |
10dcde40 |
337 | |
583fad99 |
338 | upgrade_log_start(); |
94ab72f8 |
339 | print_heading('backup'); |
10dcde40 |
340 | $db->debug=true; |
94ab72f8 |
341 | |
342 | /// Both old .sql files and new install.xml are supported |
343 | /// but we priorize install.xml (XMLDB) if present |
344 | $status = false; |
db8bd7a6 |
345 | if (file_exists($CFG->dirroot . '/backup/db/install.xml')) { |
94ab72f8 |
346 | $status = install_from_xmldb_file($CFG->dirroot . '/backup/db/install.xml'); //New method |
347 | } else if (file_exists($CFG->dirroot . '/backup/db/' . $CFG->dbtype . '.sql')) { |
348 | $status = modify_database($CFG->dirroot . '/backup/db/' . $CFG->dbtype . '.sql'); //Old method |
349 | } |
350 | |
351 | $db->debug = false; |
352 | if ($status) { |
e9346b95 |
353 | if (set_config("backup_version", $backup_version) and set_config("backup_release", $backup_release)) { |
99c8a100 |
354 | //initialize default backup settings now |
6e4dc10f |
355 | $adminroot = admin_get_root(); |
356 | apply_default_settings($adminroot->locate('backups')); |
10dcde40 |
357 | notify(get_string("databasesuccess"), "green"); |
8549af11 |
358 | notify(get_string("databaseupgradebackups", "", $backup_version), "green"); |
10dcde40 |
359 | print_continue($continueto); |
acdd790f |
360 | print_footer('none'); |
10dcde40 |
361 | exit; |
7641819d |
362 | } else { |
10dcde40 |
363 | error("Upgrade of backup system failed! (Could not update version in config table)"); |
7641819d |
364 | } |
10dcde40 |
365 | } else { |
366 | error("Backup tables could NOT be set up successfully!"); |
7641819d |
367 | } |
10dcde40 |
368 | } |
369 | |
94ab72f8 |
370 | /// Upgrading code starts here |
371 | $oldupgrade = false; |
372 | $newupgrade = false; |
373 | if (is_readable($CFG->dirroot . '/backup/db/' . $CFG->dbtype . '.php')) { |
374 | include_once($CFG->dirroot . '/backup/db/' . $CFG->dbtype . '.php'); // defines old upgrading function |
375 | $oldupgrade = true; |
376 | } |
db8bd7a6 |
377 | if (is_readable($CFG->dirroot . '/backup/db/upgrade.php')) { |
94ab72f8 |
378 | include_once($CFG->dirroot . '/backup/db/upgrade.php'); // defines new upgrading function |
379 | $newupgrade = true; |
380 | } |
10dcde40 |
381 | |
382 | if ($backup_version > $CFG->backup_version) { // Upgrade tables |
7641819d |
383 | $strdatabaseupgrades = get_string("databaseupgrades"); |
371a32e3 |
384 | print_header($strdatabaseupgrades, $strdatabaseupgrades, $strdatabaseupgrades, '', upgrade_get_javascript()); |
10dcde40 |
385 | |
583fad99 |
386 | upgrade_log_start(); |
94ab72f8 |
387 | print_heading('backup'); |
388 | |
389 | /// Run de old and new upgrade functions for the module |
390 | $oldupgrade_function = 'backup_upgrade'; |
391 | $newupgrade_function = 'xmldb_backup_upgrade'; |
392 | |
393 | /// First, the old function if exists |
394 | $oldupgrade_status = true; |
395 | if ($oldupgrade && function_exists($oldupgrade_function)) { |
396 | $db->debug = true; |
397 | $oldupgrade_status = $oldupgrade_function($CFG->backup_version); |
398 | } else if ($oldupgrade) { |
399 | notify ('Upgrade function ' . $oldupgrade_function . ' was not available in ' . |
400 | '/backup/db/' . $CFG->dbtype . '.php'); |
401 | } |
10dcde40 |
402 | |
94ab72f8 |
403 | /// Then, the new function if exists and the old one was ok |
404 | $newupgrade_status = true; |
405 | if ($newupgrade && function_exists($newupgrade_function) && $oldupgrade_status) { |
406 | $db->debug = true; |
407 | $newupgrade_status = $newupgrade_function($CFG->backup_version); |
408 | } else if ($newupgrade) { |
409 | notify ('Upgrade function ' . $newupgrade_function . ' was not available in ' . |
410 | '/backup/db/upgrade.php'); |
411 | } |
412 | |
413 | $db->debug=false; |
414 | /// Now analyze upgrade results |
415 | if ($oldupgrade_status && $newupgrade_status) { // No upgrading failed |
e9346b95 |
416 | if (set_config("backup_version", $backup_version) and set_config("backup_release", $backup_release)) { |
10dcde40 |
417 | notify(get_string("databasesuccess"), "green"); |
8549af11 |
418 | notify(get_string("databaseupgradebackups", "", $backup_version), "green"); |
10dcde40 |
419 | print_continue($continueto); |
acdd790f |
420 | print_footer('none'); |
10dcde40 |
421 | exit; |
422 | } else { |
423 | error("Upgrade of backup system failed! (Could not update version in config table)"); |
424 | } |
425 | } else { |
10dcde40 |
426 | error("Upgrade failed! See backup/version.php"); |
7641819d |
427 | } |
10dcde40 |
428 | |
429 | } else if ($backup_version < $CFG->backup_version) { |
583fad99 |
430 | upgrade_log_start(); |
10dcde40 |
431 | notify("WARNING!!! The code you are using is OLDER than the version that made these databases!"); |
7641819d |
432 | } |
94ab72f8 |
433 | upgrade_log_finish(); |
7641819d |
434 | } |
10dcde40 |
435 | |
7ba74615 |
436 | |
437 | //This function is used to insert records in the backup_ids table |
af9cd955 |
438 | //If the info field is greater than max_db_storage, then its info |
439 | //is saved to filesystem |
7ba74615 |
440 | function backup_putid ($backup_unique_code, $table, $old_id, $new_id, $info="") { |
441 | |
442 | global $CFG; |
af9cd955 |
443 | |
444 | $max_db_storage = 128; //Max bytes to save to db, else save to file |
7ba74615 |
445 | |
446 | $status = true; |
447 | |
448 | //First delete to avoid PK duplicates |
449 | $status = backup_delid($backup_unique_code, $table, $old_id); |
450 | |
af9cd955 |
451 | //Now, serialize info |
452 | $info_ser = serialize($info); |
453 | |
454 | //Now, if the size of $info_ser > $max_db_storage, save it to filesystem and |
455 | //insert a "infile" in the info field |
456 | |
457 | if (strlen($info_ser) > $max_db_storage) { |
458 | //Calculate filename (in current_backup_dir, $backup_unique_code_$table_$old_id.info) |
459 | $filename = $CFG->dataroot."/temp/backup/".$backup_unique_code."/".$backup_unique_code."_".$table."_".$old_id.".info"; |
460 | //Save data to file |
461 | $status = backup_data2file($filename,$info_ser); |
462 | //Set info_to save |
463 | $info_to_save = "infile"; |
464 | } else { |
465 | //Saving to db, addslashes |
466 | $info_to_save = addslashes($info_ser); |
467 | } |
468 | |
469 | //Now, insert the record |
470 | if ($status) { |
d8e24b78 |
471 | //Build the record |
472 | $rec->backup_code = $backup_unique_code; |
473 | $rec->table_name = $table; |
474 | $rec->old_id = $old_id; |
062a84a6 |
475 | $rec->new_id = ($new_id === null? 0 : $new_id); |
d8e24b78 |
476 | $rec->info = $info_to_save; |
15a6cf33 |
477 | |
478 | if (!insert_record('backup_ids', $rec, false)) { |
479 | $status = false; |
480 | } |
af9cd955 |
481 | } |
7ba74615 |
482 | return $status; |
483 | } |
484 | |
485 | //This function is used to delete recods from the backup_ids table |
af9cd955 |
486 | //If the info field is "infile" then the file is deleted too |
7ba74615 |
487 | function backup_delid ($backup_unique_code, $table, $old_id) { |
488 | |
489 | global $CFG; |
490 | |
491 | $status = true; |
492 | |
493 | $status = execute_sql("DELETE FROM {$CFG->prefix}backup_ids |
494 | WHERE backup_code = $backup_unique_code AND |
495 | table_name = '$table' AND |
496 | old_id = '$old_id'",false); |
497 | return $status; |
498 | } |
a2c7397c |
499 | |
500 | //This function is used to get a record from the backup_ids table |
af9cd955 |
501 | //If the info field is "infile" then its info |
502 | //is read from filesystem |
a2c7397c |
503 | function backup_getid ($backup_unique_code, $table, $old_id) { |
504 | |
505 | global $CFG; |
506 | |
507 | $status = true; |
af9cd955 |
508 | $status2 = true; |
a2c7397c |
509 | |
510 | $status = get_record ("backup_ids","backup_code",$backup_unique_code, |
511 | "table_name",$table, |
512 | "old_id", $old_id); |
513 | |
af9cd955 |
514 | //If info field = "infile", get file contents |
9a7538a3 |
515 | if (!empty($status->info) && $status->info == "infile") { |
af9cd955 |
516 | $filename = $CFG->dataroot."/temp/backup/".$backup_unique_code."/".$backup_unique_code."_".$table."_".$old_id.".info"; |
517 | //Read data from file |
518 | $status2 = backup_file2data($filename,$info); |
519 | if ($status2) { |
520 | //unserialize data |
521 | $status->info = unserialize($info); |
522 | } else { |
523 | $status = false; |
524 | } |
525 | } else { |
783ab2b0 |
526 | //Only if status (record exists) |
527 | if ($status) { |
528 | ////First strip slashes |
529 | $temp = stripslashes($status->info); |
530 | //Now unserialize |
531 | $status->info = unserialize($temp); |
532 | } |
af9cd955 |
533 | } |
534 | |
a2c7397c |
535 | return $status; |
536 | } |
6d18c5a2 |
537 | |
fd5ca378 |
538 | //This function is used to add slashes (and decode from UTF-8 if needed) |
6d18c5a2 |
539 | //It's used intensivelly when restoring modules and saving them in db |
540 | function backup_todb ($data) { |
810944af |
541 | return restore_decode_absolute_links(addslashes($data)); |
6d18c5a2 |
542 | } |
543 | |
fe3c84ab |
544 | //This function is used to check that every necessary function to |
545 | //backup/restore exists in the current php installation. Thanks to |
546 | //gregb@crowncollege.edu by the idea. |
f90666aa |
547 | function backup_required_functions($justcheck=false) { |
fe3c84ab |
548 | |
d2c94f4b |
549 | if(!function_exists('utf8_encode')) { |
f90666aa |
550 | if (empty($justcheck)) { |
551 | error('You need to add XML support to your PHP installation'); |
552 | } else { |
553 | return false; |
554 | } |
fe3c84ab |
555 | } |
556 | |
f90666aa |
557 | return true; |
fe3c84ab |
558 | } |
60b420af |
559 | |
560 | //This function send n white characters to the browser and flush the |
561 | //output buffer. Used to avoid browser timeouts and to show the progress. |
562 | function backup_flush($n=0,$time=false) { |
f90666aa |
563 | if (defined('RESTORE_SILENTLY_NOFLUSH')) { |
564 | return; |
565 | } |
60b420af |
566 | if ($time) { |
567 | $ti = strftime("%X",time()); |
568 | } else { |
569 | $ti = ""; |
570 | } |
571 | echo str_repeat(" ", $n) . $ti . "\n"; |
572 | flush(); |
573 | } |
fe3c84ab |
574 | |
af9cd955 |
575 | //This function creates the filename and write data to it |
576 | //returning status as result |
577 | function backup_data2file ($file,&$data) { |
578 | |
579 | $status = true; |
580 | $status2 = true; |
581 | |
582 | $f = fopen($file,"w"); |
583 | $status = fwrite($f,$data); |
584 | $status2 = fclose($f); |
585 | |
586 | return ($status && $status2); |
587 | } |
fe3c84ab |
588 | |
af9cd955 |
589 | //This function read the filename and read data from it |
590 | function backup_file2data ($file,&$data) { |
591 | |
592 | $status = true; |
593 | $status2 = true; |
594 | |
595 | $f = fopen($file,"r"); |
596 | $data = fread ($f,filesize($file)); |
597 | $status2 = fclose($f); |
598 | |
599 | return ($status && $status2); |
600 | } |
f90666aa |
601 | |
602 | /** this function will restore an entire backup.zip into the specified course |
603 | * using standard moodle backup/restore functions, but silently. |
604 | * @param string $pathtofile the absolute path to the backup file. |
605 | * @param int $destinationcourse the course id to restore to. |
606 | * @param boolean $emptyfirst whether to delete all coursedata first. |
607 | * @param boolean $userdata whether to include any userdata that may be in the backup file. |
9e3775db |
608 | * @param array $preferences optional, 0 will be used. Can contain: |
609 | * metacourse |
610 | * logs |
611 | * course_files |
612 | * messages |
f90666aa |
613 | */ |
9e3775db |
614 | function import_backup_file_silently($pathtofile,$destinationcourse,$emptyfirst=false,$userdata=false, $preferences=array()) { |
f90666aa |
615 | global $CFG,$SESSION,$USER; // is there such a thing on cron? I guess so.. |
9e3775db |
616 | global $restore; // ick |
f90666aa |
617 | if (empty($USER)) { |
618 | $USER = get_admin(); |
619 | $USER->admin = 1; // not sure why, but this doesn't get set |
620 | } |
621 | |
622 | define('RESTORE_SILENTLY',true); // don't output all the stuff to us. |
623 | |
624 | $debuginfo = 'import_backup_file_silently: '; |
625 | $cleanupafter = false; |
626 | $errorstr = ''; // passed by reference to restore_precheck to get errors from. |
627 | |
628 | if (!$course = get_record('course','id',$destinationcourse)) { |
629 | mtrace($debuginfo.'Course with id $destinationcourse was not a valid course!'); |
630 | return false; |
631 | } |
632 | |
633 | // first check we have a valid file. |
634 | if (!file_exists($pathtofile) || !is_readable($pathtofile)) { |
635 | mtrace($debuginfo.'File '.$pathtofile.' either didn\'t exist or wasn\'t readable'); |
636 | return false; |
637 | } |
638 | |
639 | // now make sure it's a zip file |
640 | require_once($CFG->dirroot.'/lib/filelib.php'); |
641 | $filename = substr($pathtofile,strrpos($pathtofile,'/')+1); |
642 | $mimetype = mimeinfo("type", $filename); |
643 | if ($mimetype != 'application/zip') { |
644 | mtrace($debuginfo.'File '.$pathtofile.' was of wrong mimetype ('.$mimetype.')' ); |
645 | return false; |
646 | } |
647 | |
648 | // restore_precheck wants this within dataroot, so lets put it there if it's not already.. |
649 | if (strstr($pathtofile,$CFG->dataroot) === false) { |
650 | // first try and actually move it.. |
651 | if (!check_dir_exists($CFG->dataroot.'/temp/backup/',true)) { |
652 | mtrace($debuginfo.'File '.$pathtofile.' outside of dataroot and couldn\'t move it! '); |
653 | return false; |
654 | } |
655 | if (!copy($pathtofile,$CFG->dataroot.'/temp/backup/'.$filename)) { |
656 | mtrace($debuginfo.'File '.$pathtofile.' outside of dataroot and couldn\'t move it! '); |
657 | return false; |
658 | } else { |
659 | $pathtofile = 'temp/backup/'.$filename; |
660 | $cleanupafter = true; |
661 | } |
662 | } else { |
663 | // it is within dataroot, so take it off the path for restore_precheck. |
664 | $pathtofile = substr($pathtofile,strlen($CFG->dataroot.'/')); |
665 | } |
666 | |
667 | if (!backup_required_functions()) { |
668 | mtrace($debuginfo.'Required function check failed (see backup_required_functions)'); |
669 | return false; |
670 | } |
671 | |
672 | @ini_set("max_execution_time","3000"); |
8891e81c |
673 | raise_memory_limit("192M"); |
f90666aa |
674 | |
675 | if (!$backup_unique_code = restore_precheck($destinationcourse,$pathtofile,$errorstr,true)) { |
676 | mtrace($debuginfo.'Failed restore_precheck (error was '.$errorstr.')'); |
677 | return false; |
678 | } |
679 | |
9e3775db |
680 | $SESSION->restore = new StdClass; |
f90666aa |
681 | |
682 | // add on some extra stuff we need... |
9e3775db |
683 | $SESSION->restore->metacourse = $restore->metacourse = (isset($preferences['restore_metacourse']) ? $preferences['restore_metacourse'] : 0); |
684 | $SESSION->restore->restoreto = $restore->restoreto = 1; |
685 | $SESSION->restore->users = $restore->users = $userdata; |
686 | $SESSION->restore->logs = $restore->logs = (isset($preferences['restore_logs']) ? $preferences['restore_logs'] : 0); |
687 | $SESSION->restore->user_files = $restore->user_files = $userdata; |
688 | $SESSION->restore->messages = $restore->messages = (isset($preferences['restore_messages']) ? $preferences['restore_messages'] : 0); |
689 | $SESSION->restore->course_id = $restore->course_id = $destinationcourse; |
690 | $SESSION->restore->restoreto = 1; |
691 | $SESSION->restore->course_id = $destinationcourse; |
692 | $SESSION->restore->deleting = $emptyfirst; |
693 | $SESSION->restore->restore_course_files = $restore->course_files = (isset($preferences['restore_course_files']) ? $preferences['restore_course_files'] : 0); |
694 | $SESSION->restore->backup_version = $SESSION->info->backup_backup_version; |
695 | $SESSION->restore->course_startdateoffset = $course->startdate - $SESSION->course_header->course_startdate; |
696 | |
697 | restore_setup_for_check($SESSION->restore,$backup_unique_code); |
f90666aa |
698 | |
699 | // maybe we need users (defaults to 2 in restore_setup_for_check) |
700 | if (!empty($userdata)) { |
701 | $SESSION->restore->users = 1; |
702 | } |
703 | |
704 | // we also need modules... |
705 | if ($allmods = get_records("modules")) { |
706 | foreach ($allmods as $mod) { |
707 | $modname = $mod->name; |
708 | //Now check that we have that module info in the backup file |
709 | if (isset($SESSION->info->mods[$modname]) && $SESSION->info->mods[$modname]->backup == "true") { |
710 | $SESSION->restore->mods[$modname]->restore = true; |
711 | $SESSION->restore->mods[$modname]->userinfo = $userdata; |
712 | } |
9e3775db |
713 | else { |
714 | // avoid warnings |
715 | $SESSION->restore->mods[$modname]->restore = false; |
716 | $SESSION->restore->mods[$modname]->userinfo = false; |
717 | } |
f90666aa |
718 | } |
719 | } |
9e3775db |
720 | $restore = clone($SESSION->restore); |
f90666aa |
721 | if (!restore_execute($SESSION->restore,$SESSION->info,$SESSION->course_header,$errorstr)) { |
722 | mtrace($debuginfo.'Failed restore_execute (error was '.$errorstr.')'); |
723 | return false; |
724 | } |
725 | return true; |
726 | } |
727 | |
9e3775db |
728 | /** |
729 | * Function to backup an entire course silently and create a zipfile. |
730 | * |
731 | * @param int $courseid the id of the course |
732 | * @param array $prefs see {@link backup_generate_preferences_artificially} |
733 | */ |
734 | function backup_course_silently($courseid, $prefs, &$errorstring) { |
735 | global $CFG, $preferences; // global preferences here because something else wants it :( |
736 | define('BACKUP_SILENTLY', 1); |
737 | if (!$course = get_record('course', 'id', $courseid)) { |
738 | debugging("Couldn't find course with id $courseid in backup_course_silently"); |
739 | return false; |
740 | } |
741 | $preferences = backup_generate_preferences_artificially($course, $prefs); |
742 | if (backup_execute($preferences, $errorstring)) { |
743 | return $CFG->dataroot . '/' . $course->id . '/backupdata/' . $preferences->backup_name; |
744 | } |
745 | else { |
746 | return false; |
747 | } |
748 | } |
749 | |
750 | /** |
751 | * Function to generate the $preferences variable that |
752 | * backup uses. This will back up all modules and instances in a course. |
753 | * |
754 | * @param object $course course object |
755 | * @param array $prefs can contain: |
756 | backup_metacourse |
757 | backup_users |
758 | backup_logs |
759 | backup_user_files |
760 | backup_course_files |
761 | backup_messages |
762 | * and if not provided, they will not be included. |
763 | */ |
764 | |
765 | function backup_generate_preferences_artificially($course, $prefs) { |
766 | global $CFG; |
767 | $preferences = new StdClass; |
768 | $preferences->backup_unique_code = time(); |
769 | $preferences->backup_name = backup_get_zipfile_name($course, $preferences->backup_unique_code); |
770 | $count = 0; |
771 | |
772 | if ($allmods = get_records("modules") ) { |
773 | foreach ($allmods as $mod) { |
774 | $modname = $mod->name; |
775 | $modfile = "$CFG->dirroot/mod/$modname/backuplib.php"; |
776 | $modbackup = $modname."_backup_mods"; |
777 | $modbackupone = $modname."_backup_one_mod"; |
778 | $modcheckbackup = $modname."_check_backup_mods"; |
779 | if (!file_exists($modfile)) { |
780 | continue; |
781 | } |
782 | include_once($modfile); |
783 | if (!function_exists($modbackup) || !function_exists($modcheckbackup)) { |
784 | continue; |
785 | } |
786 | $var = "exists_".$modname; |
787 | $preferences->$var = true; |
788 | $count++; |
789 | // check that there are instances and we can back them up individually |
790 | if (!count_records('course_modules','course',$course->id,'module',$mod->id) || !function_exists($modbackupone)) { |
791 | continue; |
792 | } |
793 | $var = 'exists_one_'.$modname; |
794 | $preferences->$var = true; |
795 | $varname = $modname.'_instances'; |
796 | $preferences->$varname = get_all_instances_in_course($modname,$course); |
797 | foreach ($preferences->$varname as $instance) { |
798 | $preferences->mods[$modname]->instances[$instance->id]->name = $instance->name; |
799 | $var = 'backup_'.$modname.'_instance_'.$instance->id; |
800 | $preferences->$var = true; |
801 | $preferences->mods[$modname]->instances[$instance->id]->backup = true; |
802 | $var = 'backup_user_info_'.$modname.'_instance_'.$instance->id; |
803 | $preferences->$var = true; |
804 | $preferences->mods[$modname]->instances[$instance->id]->userinfo = true; |
805 | $var = 'backup_'.$modname.'_instances'; |
806 | $preferences->$var = 1; // we need this later to determine what to display in modcheckbackup. |
807 | } |
808 | |
809 | //Check data |
810 | //Check module info |
811 | $preferences->mods[$modname]->name = $modname; |
812 | |
813 | $var = "backup_".$modname; |
814 | $preferences->$var = true; |
815 | $preferences->mods[$modname]->backup = true; |
816 | |
817 | //Check include user info |
818 | $var = "backup_user_info_".$modname; |
819 | $preferences->$var = true; |
820 | $preferences->mods[$modname]->userinfo = true; |
821 | |
822 | } |
823 | } |
824 | |
825 | //Check other parameters |
826 | $preferences->backup_metacourse = (isset($prefs['backup_metacourse']) ? $prefs['backup_metacourse'] : 0); |
827 | $preferences->backup_users = (isset($prefs['backup_users']) ? $prefs['backup_users'] : 0); |
828 | $preferences->backup_logs = (isset($prefs['backup_logs']) ? $prefs['backup_logs'] : 0); |
829 | $preferences->backup_user_files = (isset($prefs['backup_user_files']) ? $prefs['backup_user_files'] : 0); |
830 | $preferences->backup_course_files = (isset($prefs['backup_course_files']) ? $prefs['backup_course_files'] : 0); |
831 | $preferences->backup_messages = (isset($prefs['backup_messages']) ? $prefs['backup_messages'] : 0); |
832 | $preferences->backup_course = $course->id; |
833 | backup_add_static_preferences($preferences); |
834 | return $preferences; |
835 | } |
836 | |
837 | |
afbe3de8 |
838 | ?> |