Merge branch 'MDL-27635_m21' of git://github.com/rwijaya/moodle into MOODLE_21_STABLE
[moodle.git] / backup / backup_scheduled.php
blobcf396c0d846e3578101c8a1177f50ebe9574cac8
1 <?php
2 //This file contains all the code needed to execute scheduled backups
4 require_once($CFG->libdir.'/eventslib.php');
6 //This function is executed via moodle cron
7 //It prepares all the info and execute backups as necessary
8 function schedule_backup_cron() {
9 global $CFG, $DB;
11 $status = true;
13 $emailpending = false;
15 //Check for required functions...
16 if(!function_exists('utf8_encode')) {
17 mtrace(" ERROR: You need to add XML support to your PHP installation!");
18 return true;
21 //Get now
22 $now = time();
24 //First of all, we have to see if the scheduled is active and detect
25 //that there isn't another cron running
26 mtrace(" Checking backup status",'...');
27 $backup_config = backup_get_config();
28 if(!isset($backup_config->backup_sche_active) || !$backup_config->backup_sche_active) {
29 mtrace("INACTIVE");
30 return true;
31 } else if (isset($backup_config->backup_sche_running) && $backup_config->backup_sche_running) {
32 mtrace("RUNNING");
33 //Now check if it's a really running task or something very old looking
34 //for info in backup_logs to unlock status as necessary
35 $timetosee = 1800; //Half an hour looking for activity
36 $timeafter = time() - $timetosee;
37 $numofrec = $DB->count_records_select ("backup_log","time > ? AND backuptype = ?", array($timeafter, 'scheduledbackup'));
38 if (!$numofrec) {
39 $timetoseemin = $timetosee/60;
40 mtrace(" No activity in last ".$timetoseemin." minutes. Unlocking status");
41 } else {
42 mtrace(" Scheduled backup seems to be running. Execution delayed");
43 return true;
45 } else {
46 mtrace("OK");
47 //Mark backup_sche_running
48 backup_set_config("backup_sche_running","1");
51 //Now we get the main admin user (we'll use his timezone, mail...)
52 mtrace(" Getting admin info");
53 $admin = get_admin();
54 if (!$admin) {
55 $status = false;
58 //Delete old_entries from backup tables
59 if ($status) {
60 mtrace(" Deleting old data");
61 if (!backup_delete_old_data()) {;
62 $errorstr = "An error occurred deleting old backup data";
63 add_to_backup_log(time(),$preferences->backup_course,$errorstr,'scheduledbackup');
64 mtrace(" ".$errorstr);
68 //Now we get a list of courses in the server
69 if ($status) {
70 mtrace(" Checking courses");
71 //First of all, we delete everything from backup tables related to deleted courses
72 mtrace(" Skipping deleted courses");
73 $skipped = 0;
74 if ($bckcourses = $DB->get_records('backup_courses')) {
75 foreach($bckcourses as $bckcourse) {
76 //Search if it exists
77 if (!$exists = $DB->get_record('course', array('id'=>$bckcourse->courseid))) {
78 //Doesn't exist, so delete from backup tables
79 $DB->delete_records('backup_courses', array('courseid'=>$bckcourse->courseid));
80 $DB->delete_records('backup_log', array('courseid'=>$bckcourse->courseid));
81 $skipped++;
85 mtrace(" $skipped courses");
86 //Now process existing courses
87 $courses = $DB->get_records("course");
88 //For each course, we check (insert, update) the backup_course table
89 //with needed data
90 foreach ($courses as $course) {
91 if ($status) {
92 mtrace(" $course->fullname");
93 //We check if the course exists in backup_course
94 $backup_course = $DB->get_record("backup_courses", array("courseid"=>$course->id));
95 //If it doesn't exist, create
96 if (!$backup_course) {
97 $temp_backup_course->courseid = $course->id;
98 $newid = $DB->insert_record("backup_courses",$temp_backup_course);
99 //And get it from db
100 $backup_course = $DB->get_record("backup_courses", array("id"=>$newid));
102 //If it doesn't exist now, error
103 if (!$backup_course) {
104 mtrace(" ERROR (in backup_courses detection)");
105 $status = false;
106 continue;
108 // Skip backup of unavailable courses that have remained unmodified in a month
109 $skipped = false;
110 if (!$course->visible && ($now - $course->timemodified) > 31*24*60*60) { //Hidden + unmodified last month
111 mtrace(" SKIPPING - hidden+unmodified");
112 $DB->set_field("backup_courses","laststatus","3", array("courseid"=>$backup_course->courseid));
113 $skipped = true;
115 //Now we backup every non skipped course with nextstarttime < now
116 if (!$skipped && $backup_course->nextstarttime > 0 && $backup_course->nextstarttime < $now) {
117 //We have to send a email because we have included at least one backup
118 $emailpending = true;
119 //Only make the backup if laststatus isn't 2-UNFINISHED (uncontrolled error)
120 if ($backup_course->laststatus != 2) {
121 //Set laststarttime
122 $starttime = time();
123 $DB->set_field("backup_courses","laststarttime",$starttime, array("courseid"=>$backup_course->courseid));
124 //Set course status to unfinished, the process will reset it
125 $DB->set_field("backup_courses","laststatus","2", array("courseid"=>$backup_course->courseid));
126 //Launch backup
127 $course_status = schedule_backup_launch_backup($course,$starttime);
128 //Set lastendtime
129 $DB->set_field("backup_courses","lastendtime",time(), array("courseid"=>$backup_course->courseid));
130 //Set laststatus
131 if ($course_status) {
132 $DB->set_field("backup_courses","laststatus","1", array("courseid"=>$backup_course->courseid));
133 } else {
134 $DB->set_field("backup_courses","laststatus","0", array("courseid"=>$backup_course->courseid));
139 //Now, calculate next execution of the course
140 $nextstarttime = schedule_backup_next_execution ($backup_course,$backup_config,$now,$admin->timezone);
141 //Save it to db
142 $DB->set_field("backup_courses","nextstarttime",$nextstarttime, array("courseid"=>$backup_course->courseid));
143 //Print it to screen as necessary
144 $showtime = "undefined";
145 if ($nextstarttime > 0) {
146 $showtime = userdate($nextstarttime,"",$admin->timezone);
148 mtrace(" Next execution: $showtime");
153 //Delete old logs
154 if (!empty($CFG->loglifetime)) {
155 mtrace(" Deleting old logs");
156 $loglifetime = $now - ($CFG->loglifetime * 86400);
157 $DB->delete_records_select("backup_log", "laststarttime < ?", array($loglifetime));
160 //Send email to admin if necessary
161 if ($emailpending) {
162 mtrace(" Sending email to admin");
163 $message = "";
165 //Get info about the status of courses
166 $count_all = $DB->count_records('backup_courses');
167 $count_ok = $DB->count_records('backup_courses', array('laststatus'=>'1'));
168 $count_error = $DB->count_records('backup_courses', array('laststatus'=>'0'));
169 $count_unfinished = $DB->count_records('backup_courses', array('laststatus'=>'2'));
170 $count_skipped = $DB->count_records('backup_courses', array('laststatus'=>'3'));
172 //Build the message text
173 //Summary
174 $message .= get_string('summary')."\n";
175 $message .= "==================================================\n";
176 $message .= " ".get_string('courses').": ".$count_all."\n";
177 $message .= " ".get_string('ok').": ".$count_ok."\n";
178 $message .= " ".get_string('skipped').": ".$count_skipped."\n";
179 $message .= " ".get_string('error').": ".$count_error."\n";
180 $message .= " ".get_string('unfinished').": ".$count_unfinished."\n\n";
182 //Reference
183 if ($count_error != 0 || $count_unfinished != 0) {
184 $message .= " ".get_string('backupfailed')."\n\n";
185 $dest_url = "$CFG->wwwroot/$CFG->admin/report/backups/index.php";
186 $message .= " ".get_string('backuptakealook','',$dest_url)."\n\n";
187 //Set message priority
188 $admin->priority = 1;
189 //Reset unfinished to error
190 $DB->set_field('backup_courses','laststatus','0', array('laststatus'=>'2'));
191 } else {
192 $message .= " ".get_string('backupfinished')."\n";
195 //Build the message subject
196 $site = get_site();
197 $prefix = $site->shortname.": ";
198 if ($count_error != 0 || $count_unfinished != 0) {
199 $prefix .= "[".strtoupper(get_string('error'))."] ";
201 $subject = $prefix.get_string("scheduledbackupstatus");
203 //Send the message
204 $eventdata = new stdClass();
205 $eventdata->modulename = 'moodle';
206 $eventdata->userfrom = $admin;
207 $eventdata->userto = $admin;
208 $eventdata->subject = $subject;
209 $eventdata->fullmessage = $message;
210 $eventdata->fullmessageformat = FORMAT_PLAIN;
211 $eventdata->fullmessagehtml = '';
212 $eventdata->smallmessage = '';
213 message_send($eventdata);
216 //Everything is finished stop backup_sche_running
217 backup_set_config("backup_sche_running","0");
219 return $status;
222 //This function executes the ENTIRE backup of a course (passed as parameter)
223 //using all the scheduled backup preferences
224 function schedule_backup_launch_backup($course,$starttime = 0) {
226 $preferences = false;
227 $status = false;
229 mtrace(" Executing backup");
230 schedule_backup_log($starttime,$course->id,"Start backup course $course->fullname");
231 schedule_backup_log($starttime,$course->id," Phase 1: Checking and counting:");
232 $preferences = schedule_backup_course_configure($course,$starttime);
234 if ($preferences) {
235 schedule_backup_log($starttime,$course->id," Phase 2: Executing and copying:");
236 $status = schedule_backup_course_execute($preferences,$starttime);
239 if ($status && $preferences) {
240 //Only if the backup_sche_keep is set
241 if ($preferences->backup_keep) {
242 schedule_backup_log($starttime,$course->id," Phase 3: Deleting old backup files:");
243 $status = schedule_backup_course_delete_old_files($preferences,$starttime);
247 if ($status && $preferences) {
248 mtrace(" End backup OK");
249 schedule_backup_log($starttime,$course->id,"End backup course $course->fullname - OK");
250 } else {
251 mtrace(" End backup with ERROR");
252 schedule_backup_log($starttime,$course->id,"End backup course $course->fullname - ERROR!!");
255 return $status && $preferences;
258 //This function saves to backup_log all the needed process info
259 //to use it later. NOTE: If $starttime = 0 no info in saved
260 function schedule_backup_log($starttime,$courseid,$message) {
261 global $DB;
263 if ($starttime) {
264 add_to_backup_log($starttime,$courseid,$message, 'scheduledbackup');
269 //This function returns the next future GMT time to execute the course based in the
270 //configuration of the scheduled backups
271 function schedule_backup_next_execution ($backup_course,$backup_config,$now,$timezone) {
273 $result = -1;
275 //Get today's midnight GMT
276 $midnight = usergetmidnight($now,$timezone);
278 //Get today's day of week (0=Sunday...6=Saturday)
279 $date = usergetdate($now,$timezone);
280 $dayofweek = $date['wday'];
282 //Get number of days (from today) to execute backups
283 $scheduled_days = substr($backup_config->backup_sche_weekdays,$dayofweek).
284 $backup_config->backup_sche_weekdays;
285 $daysfromtoday = strpos($scheduled_days, "1");
287 //If some day has been found
288 if ($daysfromtoday !== false) {
289 //Calculate distance
290 $dist = ($daysfromtoday * 86400) + //Days distance
291 ($backup_config->backup_sche_hour*3600) + //Hours distance
292 ($backup_config->backup_sche_minute*60); //Minutes distance
293 $result = $midnight + $dist;
296 //If that time is past, call the function recursively to obtain the next valid day
297 if ($result > 0 && $result < time()) {
298 $result = schedule_backup_next_execution ($backup_course,$backup_config,$now + 86400,$timezone);
301 return $result;
306 //This function implements all the needed code to prepare a course
307 //to be in backup (insert temp info into backup temp tables).
308 function schedule_backup_course_configure($course,$starttime = 0) {
309 global $CFG, $DB;
311 $status = true;
313 schedule_backup_log($starttime,$course->id," checking parameters");
315 //Check the required variable
316 if (empty($course->id)) {
317 $status = false;
319 //Get scheduled backup preferences
320 $backup_config = backup_get_config();
322 //Checks backup_config pairs exist
323 if ($status) {
324 if (!isset($backup_config->backup_sche_modules)) {
325 $backup_config->backup_sche_modules = 1;
327 if (!isset($backup_config->backup_sche_withuserdata)) {
328 $backup_config->backup_sche_withuserdata = 1;
330 if (!isset($backup_config->backup_sche_metacourse)) {
331 $backup_config->backup_sche_metacourse = 1;
333 if (!isset($backup_config->backup_sche_users)) {
334 $backup_config->backup_sche_users = 1;
336 if (!isset($backup_config->backup_sche_logs)) {
337 $backup_config->backup_sche_logs = 0;
339 if (!isset($backup_config->backup_sche_userfiles)) {
340 $backup_config->backup_sche_userfiles = 1;
342 if (!isset($backup_config->backup_sche_coursefiles)) {
343 $backup_config->backup_sche_coursefiles = 1;
345 if (!isset($backup_config->backup_sche_sitefiles)) {
346 $backup_config->backup_sche_sitefiles = 1;
348 if (!isset($backup_config->backup_sche_gradebook_history)) {
349 $backup_config->backup_sche_gradebook_history = 0;
351 if (!isset($backup_config->backup_sche_messages)) {
352 $backup_config->backup_sche_messages = 0;
354 if (!isset($backup_config->backup_sche_blogs)) {
355 $backup_config->backup_sche_blogs = 0;
357 if (!isset($backup_config->backup_sche_active)) {
358 $backup_config->backup_sche_active = 0;
360 if (!isset($backup_config->backup_sche_weekdays)) {
361 $backup_config->backup_sche_weekdays = "0000000";
363 if (!isset($backup_config->backup_sche_hour)) {
364 $backup_config->backup_sche_hour = 00;
366 if (!isset($backup_config->backup_sche_minute)) {
367 $backup_config->backup_sche_minute = 00;
369 if (!isset($backup_config->backup_sche_destination)) {
370 $backup_config->backup_sche_destination = "";
372 if (!isset($backup_config->backup_sche_keep)) {
373 $backup_config->backup_sche_keep = 1;
377 if ($status) {
378 //Checks for the required files/functions to backup every mod
379 //And check if there is data about it
380 $count = 0;
381 if ($allmods = $DB->get_records("modules") ) {
382 foreach ($allmods as $mod) {
383 $modname = $mod->name;
384 $modfile = "$CFG->dirroot/mod/$modname/backuplib.php";
385 $modbackup = $modname."_backup_mods";
386 $modcheckbackup = $modname."_check_backup_mods";
387 if (file_exists($modfile)) {
388 include_once($modfile);
389 if (function_exists($modbackup) and function_exists($modcheckbackup)) {
390 $var = "exists_".$modname;
391 $$var = true;
392 $count++;
394 // PENNY NOTES: I have moved from here to the closing brace inside
395 // by two sets of ifs()
396 // to avoid the backup failing on a non existant backup.
397 // If the file/function/whatever doesn't exist, we don't want to set this
398 // this module in backup preferences at all.
399 //Check data
400 //Check module info
401 $var = "backup_".$modname;
402 if (!isset($$var)) {
403 $$var = $backup_config->backup_sche_modules;
405 //Now stores all the mods preferences into an array into preferences
406 $preferences->mods[$modname]->backup = $$var;
408 //Check include user info
409 $var = "backup_user_info_".$modname;
410 if (!isset($$var)) {
411 $$var = $backup_config->backup_sche_withuserdata;
413 //Now stores all the mods preferences into an array into preferences
414 $preferences->mods[$modname]->userinfo = $$var;
415 //And the name of the mod
416 $preferences->mods[$modname]->name = $modname;
422 // now set instances
423 if ($coursemods = get_course_mods($course->id)) {
424 foreach ($coursemods as $mod) {
425 if (array_key_exists($mod->modname,$preferences->mods)) { // we are to backup this module
426 if (empty($preferences->mods[$mod->modname]->instances)) {
427 $preferences->mods[$mod->modname]->instances = array(); // avoid warnings
429 $preferences->mods[$mod->modname]->instances[$mod->instance]->backup = $preferences->mods[$mod->modname]->backup;
430 $preferences->mods[$mod->modname]->instances[$mod->instance]->userinfo = $preferences->mods[$mod->modname]->userinfo;
431 // there isn't really a nice way to do this...
432 $preferences->mods[$mod->modname]->instances[$mod->instance]->name = $DB->get_field($mod->modname,'name', array('id'=>$mod->instance));
437 // finally, clean all the $preferences->mods[] not having instances. Nothing to backup about them
438 foreach ($preferences->mods as $modname => $mod) {
439 if (!isset($mod->instances)) {
440 unset($preferences->mods[$modname]);
445 //Convert other parameters
446 if ($status) {
447 $preferences->backup_metacourse = $backup_config->backup_sche_metacourse;
448 $preferences->backup_users = $backup_config->backup_sche_users;
449 $preferences->backup_logs = $backup_config->backup_sche_logs;
450 $preferences->backup_user_files = $backup_config->backup_sche_userfiles;
451 $preferences->backup_course_files = $backup_config->backup_sche_coursefiles;
452 $preferences->backup_site_files = $backup_config->backup_sche_sitefiles;
453 $preferences->backup_gradebook_history = $backup_config->backup_sche_gradebook_history;
454 $preferences->backup_messages = $backup_config->backup_sche_messages;
455 $preferences->backup_blogs = $backup_config->backup_sche_blogs;
456 $preferences->backup_course = $course->id;
457 $preferences->backup_destination = $backup_config->backup_sche_destination;
458 $preferences->backup_keep = $backup_config->backup_sche_keep;
461 //Calculate various backup preferences
462 if ($status) {
463 schedule_backup_log($starttime,$course->id," calculating backup name");
465 //Calculate the backup file name
466 $backup_name = backup_get_zipfile_name($course);
468 //Calculate the string to match the keep preference
469 $keep_name = backup_get_keep_name($course);
471 //Set them
472 $preferences->backup_name = $backup_name;
473 $preferences->keep_name = $keep_name;
475 //Roleasignments
476 $roles = get_all_roles();
477 foreach ($roles as $role) {
478 $preferences->backuproleassignments[$role->id] = $role;
481 //Another Info
482 backup_add_static_preferences($preferences);
485 //Calculate the backup unique code to allow simultaneus backups (to define
486 //the temp-directory name and records in backup temp tables
487 if ($status) {
488 $backup_unique_code = time();
489 $preferences->backup_unique_code = $backup_unique_code;
492 //Calculate necesary info to backup modules
493 if ($status) {
494 schedule_backup_log($starttime,$course->id," calculating modules data");
495 if ($allmods = $DB->get_records("modules") ) {
496 foreach ($allmods as $mod) {
497 $modname = $mod->name;
498 $modbackup = $modname."_backup_mods";
499 //If exists the lib & function
500 $var = "exists_".$modname;
501 if (isset($$var) && $$var) {
502 //Add hidden fields
503 $var = "backup_".$modname;
504 //Only if selected
505 if ($$var == 1) {
506 $var = "backup_user_info_".$modname;
507 //Call the check function to show more info
508 $modcheckbackup = $modname."_check_backup_mods";
509 schedule_backup_log($starttime,$course->id," $modname");
510 $modcheckbackup($course->id,$$var,$backup_unique_code);
517 //Now calculate the users
518 if ($status) {
519 schedule_backup_log($starttime,$course->id," calculating users");
520 //Decide about include users with messages, based on SITEID
521 if ($preferences->backup_messages && $preferences->backup_course == SITEID) {
522 $include_message_users = true;
523 } else {
524 $include_message_users = false;
526 //Decide about include users with blogs, based on SITEID
527 if ($preferences->backup_blogs && $preferences->backup_course == SITEID) {
528 $include_blog_users = true;
529 } else {
530 $include_blog_users = false;
532 user_check_backup($course->id,$backup_unique_code,$preferences->backup_users,$include_message_users, $include_blog_users);
535 //Now calculate the logs
536 if ($status) {
537 if ($preferences->backup_logs) {
538 schedule_backup_log($starttime,$course->id," calculating logs");
539 log_check_backup($course->id);
543 //Now calculate the userfiles
544 if ($status) {
545 if ($preferences->backup_user_files) {
546 schedule_backup_log($starttime,$course->id," calculating user files");
547 user_files_check_backup($course->id,$preferences->backup_unique_code);
551 //Now calculate the coursefiles
552 if ($status) {
553 if ($preferences->backup_course_files) {
554 schedule_backup_log($starttime,$course->id," calculating course files");
555 course_files_check_backup($course->id,$preferences->backup_unique_code);
559 //Now calculate the sitefiles
560 if ($status) {
561 if ($preferences->backup_site_files) {
562 schedule_backup_log($starttime,$course->id," calculating site files");
563 site_files_check_backup($course->id,$preferences->backup_unique_code);
567 //If everything is ok, return calculated preferences
568 if ($status) {
569 $status = $preferences;
572 return $status;
575 //TODO: Unify this function with backup_execute() to have both backups 100% equivalent. Moodle 2.0
577 //This function implements all the needed code to backup a course
578 //copying it to the desired destination (default if not specified)
579 function schedule_backup_course_execute($preferences,$starttime = 0) {
581 global $CFG;
583 $status = true;
585 //Some parts of the backup doesn't know about $preferences, so we
586 //put a copy of it inside that CFG (always global) to be able to
587 //use it. Then, when needed I search for preferences inside CFG
588 //Used to avoid some problems in full_tag() when preferences isn't
589 //set globally (i.e. in scheduled backups)
590 $CFG->backup_preferences = $preferences;
592 //Check for temp and backup and backup_unique_code directory
593 //Create them as needed
594 schedule_backup_log($starttime,$preferences->backup_course," checking temp structures");
595 $status = check_and_create_backup_dir($preferences->backup_unique_code);
596 //Empty backup dir
597 if ($status) {
598 schedule_backup_log($starttime,$preferences->backup_course," cleaning current dir");
599 $status = clear_backup_dir($preferences->backup_unique_code);
602 //Create the moodle.xml file
603 if ($status) {
604 schedule_backup_log($starttime,$preferences->backup_course," creating backup file");
605 //Obtain the xml file (create and open) and print prolog information
606 $backup_file = backup_open_xml($preferences->backup_unique_code);
607 //Prints general info about backup to file
608 if ($backup_file) {
609 schedule_backup_log($starttime,$preferences->backup_course," general info");
610 $status = backup_general_info($backup_file,$preferences);
611 } else {
612 $status = false;
615 //Prints course start (tag and general info)
616 if ($status) {
617 $status = backup_course_start($backup_file,$preferences);
620 //Metacourse information
621 if ($status && $preferences->backup_metacourse) {
622 schedule_backup_log($starttime,$preferences->backup_course," metacourse info");
623 $status = backup_course_metacourse($backup_file,$preferences);
626 //Block info
627 if ($status) {
628 schedule_backup_log($starttime,$preferences->backup_course," blocks info");
629 $status = backup_course_blocks($backup_file,$preferences);
632 //Section info
633 if ($status) {
634 schedule_backup_log($starttime,$preferences->backup_course," sections info");
635 $status = backup_course_sections($backup_file,$preferences);
638 //User info
639 if ($status) {
640 schedule_backup_log($starttime,$preferences->backup_course," user info");
641 $status = backup_user_info($backup_file,$preferences);
644 //If we have selected to backup messages and we are
645 //doing a SITE backup, let's do it
646 if ($status && $preferences->backup_messages && $preferences->backup_course == SITEID) {
647 schedule_backup_log($starttime,$preferences->backup_course," messages");
648 $status = backup_messages($backup_file,$preferences);
651 //If we have selected to backup blogs and we are
652 //doing a SITE backup, let's do it
653 if ($status && $preferences->backup_blogs && $preferences->backup_course == SITEID) {
654 schedule_backup_log($starttime,$preferences->backup_course," blogs");
655 $status = backup_blogs($backup_file,$preferences);
658 //If we have selected to backup quizzes, backup categories and
659 //questions structure (step 1). See notes on mod/quiz/backuplib.php
660 if ($status and $preferences->mods['quiz']->backup) {
661 schedule_backup_log($starttime,$preferences->backup_course," categories & questions");
662 $status = backup_question_categories($backup_file,$preferences);
665 //Print logs if selected
666 if ($status) {
667 if ($preferences->backup_logs) {
668 schedule_backup_log($starttime,$preferences->backup_course," logs");
669 $status = backup_log_info($backup_file,$preferences);
673 //Print scales info
674 if ($status) {
675 schedule_backup_log($starttime,$preferences->backup_course," scales");
676 $status = backup_scales_info($backup_file,$preferences);
679 //Print groups info
680 if ($status) {
681 schedule_backup_log($starttime,$preferences->backup_course," groups");
682 $status = backup_groups_info($backup_file,$preferences);
685 //Print groupings info
686 if ($status) {
687 schedule_backup_log($starttime,$preferences->backup_course," groupings");
688 $status = backup_groupings_info($backup_file,$preferences);
691 //Print groupings_groups info
692 if ($status) {
693 schedule_backup_log($starttime,$preferences->backup_course," groupings_groups");
694 $status = backup_groupings_groups_info($backup_file,$preferences);
697 //Print events info
698 if ($status) {
699 schedule_backup_log($starttime,$preferences->backup_course," events");
700 $status = backup_events_info($backup_file,$preferences);
703 //Print gradebook info
704 if ($status) {
705 schedule_backup_log($starttime,$preferences->backup_course," gradebook");
706 $status = backup_gradebook_info($backup_file,$preferences);
709 //Module info, this unique function makes all the work!!
710 //db export and module fileis copy
711 if ($status) {
712 $mods_to_backup = false;
713 //Check if we have any mod to backup
714 foreach ($preferences->mods as $module) {
715 if ($module->backup) {
716 $mods_to_backup = true;
719 //If we have to backup some module
720 if ($mods_to_backup) {
721 schedule_backup_log($starttime,$preferences->backup_course," modules");
722 //Start modules tag
723 $status = backup_modules_start ($backup_file,$preferences);
724 //Iterate over modules and call backup
725 foreach ($preferences->mods as $module) {
726 if ($module->backup and $status) {
727 schedule_backup_log($starttime,$preferences->backup_course," $module->name");
728 $status = backup_module($backup_file,$preferences,$module->name);
731 //Close modules tag
732 $status = backup_modules_end ($backup_file,$preferences);
736 //Backup course format data, if any.
737 if ($status) {
738 schedule_backup_log($starttime,$preferences->backup_course," course format data");
739 $status = backup_format_data($backup_file,$preferences);
742 //Prints course end
743 if ($status) {
744 $status = backup_course_end($backup_file,$preferences);
747 //Close the xml file and xml data
748 if ($backup_file) {
749 backup_close_xml($backup_file);
753 //Now, if selected, copy user files
754 if ($status) {
755 if ($preferences->backup_user_files) {
756 schedule_backup_log($starttime,$preferences->backup_course," copying user files");
757 $status = backup_copy_user_files ($preferences);
761 //Now, if selected, copy course files
762 if ($status) {
763 if ($preferences->backup_course_files) {
764 schedule_backup_log($starttime,$preferences->backup_course," copying course files");
765 $status = backup_copy_course_files ($preferences);
769 //Now, if selected, copy site files
770 if ($status) {
771 if ($preferences->backup_site_files) {
772 schedule_backup_log($starttime,$preferences->backup_course," copying site files");
773 $status = backup_copy_site_files ($preferences);
777 //Now, zip all the backup directory contents
778 if ($status) {
779 schedule_backup_log($starttime,$preferences->backup_course," zipping files");
780 $status = backup_zip ($preferences);
783 //Now, copy the zip file to course directory
784 if ($status) {
785 schedule_backup_log($starttime,$preferences->backup_course," copying backup");
786 $status = copy_zip_to_course_dir ($preferences);
789 //Now, clean temporary data (db and filesystem)
790 if ($status) {
791 schedule_backup_log($starttime,$preferences->backup_course," cleaning temp data");
792 $status = clean_temp_data ($preferences);
795 //Unset CFG->backup_preferences only needed in scheduled backups
796 unset ($CFG->backup_preferences);
798 return $status;
801 //This function deletes old backup files when the "keep" limit has been reached
802 //in the destination directory.
803 function schedule_backup_course_delete_old_files($preferences,$starttime=0) {
805 global $CFG;
807 $status = true;
809 //Calculate the directory to check
810 $dirtocheck = "";
811 //if $preferences->backup_destination isn't empty, then check that directory
812 if (!empty($preferences->backup_destination)) {
813 $dirtocheck = $preferences->backup_destination;
814 //else calculate standard backup directory location
815 } else {
816 $dirtocheck = $CFG->dataroot."/".$preferences->backup_course."/backupdata";
818 schedule_backup_log($starttime,$preferences->backup_course," checking $dirtocheck");
819 if ($CFG->debug > 7) {
820 mtrace(" Keeping backup files in $dirtocheck");
823 //Get all the files in $dirtocheck
824 $files = get_directory_list($dirtocheck,"",false);
825 //Get all matching files ($preferences->keep_name) from $files
826 $matchingfiles = array();
827 foreach ($files as $file) {
828 if (substr($file, 0, strlen($preferences->keep_name)) == $preferences->keep_name) {
829 $modifieddate = filemtime($dirtocheck."/".$file);
830 $matchingfiles[$modifieddate] = $file;
833 //Sort by key (modified date) to get the oldest first (instead of doing that by name
834 //because it could give us problems in some languages with different format names).
835 ksort($matchingfiles);
837 //Count matching files
838 $countmatching = count($matchingfiles);
839 schedule_backup_log($starttime,$preferences->backup_course," found $countmatching backup files");
840 mtrace(" found $countmatching backup files");
841 if ($preferences->backup_keep < $countmatching) {
842 schedule_backup_log($starttime,$preferences->backup_course," keep limit ($preferences->backup_keep) reached. Deleting old files");
843 mtrace(" keep limit ($preferences->backup_keep) reached. Deleting old files");
844 $filestodelete = $countmatching - $preferences->backup_keep;
845 $filesdeleted = 0;
846 foreach ($matchingfiles as $matchfile) {
847 if ($filesdeleted < $filestodelete) {
848 schedule_backup_log($starttime,$preferences->backup_course," $matchfile deleted");
849 mtrace(" $matchfile deleted");
850 $filetodelete = $dirtocheck."/".$matchfile;
851 unlink($filetodelete);
852 $filesdeleted++;
856 return $status;