timeline: if a section is set to hidden and the user is not capable of editing a...
[moodle-blog-course-format.git] / backup / backup_scheduled.php
blob4ab66d4694fbbb7bd66a37fe4c58edc3094a541d
1 <?php //$Id$
2 //This file contains all the code needed to execute scheduled backups
4 //This function is executed via moodle cron
5 //It prepares all the info and execute backups as necessary
6 function schedule_backup_cron() {
8 global $CFG;
10 $status = true;
12 $emailpending = false;
14 //Check for required functions...
15 if(!function_exists('utf8_encode')) {
16 mtrace(" ERROR: You need to add XML support to your PHP installation!");
17 return true;
20 //Get now
21 $now = time();
23 //First of all, we have to see if the scheduled is active and detect
24 //that there isn't another cron running
25 mtrace(" Checking backup status",'...');
26 $backup_config = backup_get_config();
27 if(!isset($backup_config->backup_sche_active) || !$backup_config->backup_sche_active) {
28 mtrace("INACTIVE");
29 return true;
30 } else if (isset($backup_config->backup_sche_running) && $backup_config->backup_sche_running) {
31 mtrace("RUNNING");
32 //Now check if it's a really running task or something very old looking
33 //for info in backup_logs to unlock status as necessary
34 $timetosee = 1800; //Half an hour looking for activity
35 $timeafter = time() - $timetosee;
36 $numofrec = count_records_select ("backup_log","time > $timeafter");
37 if (!$numofrec) {
38 $timetoseemin = $timetosee/60;
39 mtrace(" No activity in last ".$timetoseemin." minutes. Unlocking status");
40 } else {
41 mtrace(" Scheduled backup seems to be running. Execution delayed");
42 return true;
44 } else {
45 mtrace("OK");
46 //Mark backup_sche_running
47 backup_set_config("backup_sche_running","1");
50 //Now we get the main admin user (we'll use his timezone, mail...)
51 mtrace(" Getting admin info");
52 $admin = get_admin();
53 if (!$admin) {
54 $status = false;
57 //Delete old_entries from backup tables
58 if ($status) {
59 mtrace(" Deleting old data");
60 $status = backup_delete_old_data();
63 //Now we get a list of courses in the server
64 if ($status) {
65 mtrace(" Checking courses");
66 //First of all, we delete everything from backup tables related to deleted courses
67 mtrace(" Skipping deleted courses");
68 $skipped = 0;
69 if ($bckcourses = get_records('backup_courses')) {
70 foreach($bckcourses as $bckcourse) {
71 //Search if it exists
72 if (!$exists = get_record('course', 'id', "$bckcourse->courseid")) {
73 //Doesn't exist, so delete from backup tables
74 delete_records('backup_courses', 'courseid', "$bckcourse->courseid");
75 delete_records('backup_log', 'courseid', "$bckcourse->courseid");
76 $skipped++;
80 mtrace(" $skipped courses");
81 //Now process existing courses
82 $courses = get_records("course");
83 //For each course, we check (insert, update) the backup_course table
84 //with needed data
85 foreach ($courses as $course) {
86 if ($status) {
87 mtrace(" $course->fullname");
88 //We check if the course exists in backup_course
89 $backup_course = get_record("backup_courses","courseid",$course->id);
90 //If it doesn't exist, create
91 if (!$backup_course) {
92 $temp_backup_course->courseid = $course->id;
93 $newid = insert_record("backup_courses",$temp_backup_course);
94 //And get it from db
95 $backup_course = get_record("backup_courses","id",$newid);
97 //If it doesn't exist now, error
98 if (!$backup_course) {
99 mtrace(" ERROR (in backup_courses detection)");
100 $status = false;
101 continue;
103 // Skip backup of unavailable courses that have remained unmodified in a month
104 $skipped = false;
105 if (!$course->visible && ($now - $course->timemodified) > 31*24*60*60) { //Hidden + unmodified last month
106 mtrace(" SKIPPING - hidden+unmodified");
107 set_field("backup_courses","laststatus","3","courseid",$backup_course->courseid);
108 $skipped = true;
110 //Now we backup every non skipped course with nextstarttime < now
111 if (!$skipped && $backup_course->nextstarttime > 0 && $backup_course->nextstarttime < $now) {
112 //We have to send a email because we have included at least one backup
113 $emailpending = true;
114 //Only make the backup if laststatus isn't 2-UNFINISHED (uncontrolled error)
115 if ($backup_course->laststatus != 2) {
116 //Set laststarttime
117 $starttime = time();
118 set_field("backup_courses","laststarttime",$starttime,"courseid",$backup_course->courseid);
119 //Set course status to unfinished, the process will reset it
120 set_field("backup_courses","laststatus","2","courseid",$backup_course->courseid);
121 //Launch backup
122 $course_status = schedule_backup_launch_backup($course,$starttime);
123 //Set lastendtime
124 set_field("backup_courses","lastendtime",time(),"courseid",$backup_course->courseid);
125 //Set laststatus
126 if ($course_status) {
127 set_field("backup_courses","laststatus","1","courseid",$backup_course->courseid);
128 } else {
129 set_field("backup_courses","laststatus","0","courseid",$backup_course->courseid);
134 //Now, calculate next execution of the course
135 $nextstarttime = schedule_backup_next_execution ($backup_course,$backup_config,$now,$admin->timezone);
136 //Save it to db
137 set_field("backup_courses","nextstarttime",$nextstarttime,"courseid",$backup_course->courseid);
138 //Print it to screen as necessary
139 $showtime = "undefined";
140 if ($nextstarttime > 0) {
141 $showtime = userdate($nextstarttime,"",$admin->timezone);
143 mtrace(" Next execution: $showtime");
148 //Delete old logs
149 if (!empty($CFG->loglifetime)) {
150 mtrace(" Deleting old logs");
151 $loglifetime = $now - ($CFG->loglifetime * 86400);
152 delete_records_select("backup_log", "laststarttime < '$loglifetime'");
155 //Send email to admin if necessary
156 if ($emailpending) {
157 mtrace(" Sending email to admin");
158 $message = "";
160 //Get info about the status of courses
161 $count_all = count_records('backup_courses');
162 $count_ok = count_records('backup_courses','laststatus','1');
163 $count_error = count_records('backup_courses','laststatus','0');
164 $count_unfinished = count_records('backup_courses','laststatus','2');
165 $count_skipped = count_records('backup_courses','laststatus','3');
167 //Build the message text
168 //Summary
169 $message .= get_string('summary')."\n";
170 $message .= "==================================================\n";
171 $message .= " ".get_string('courses').": ".$count_all."\n";
172 $message .= " ".get_string('ok').": ".$count_ok."\n";
173 $message .= " ".get_string('skipped').": ".$count_skipped."\n";
174 $message .= " ".get_string('error').": ".$count_error."\n";
175 $message .= " ".get_string('unfinished').": ".$count_unfinished."\n\n";
177 //Reference
178 if ($count_error != 0 || $count_unfinished != 0) {
179 $message .= " ".get_string('backupfailed')."\n\n";
180 $dest_url = "$CFG->wwwroot/$CFG->admin/report/backups/index.php";
181 $message .= " ".get_string('backuptakealook','',$dest_url)."\n\n";
182 //Set message priority
183 $admin->priority = 1;
184 //Reset unfinished to error
185 set_field('backup_courses','laststatus','0','laststatus','2');
186 } else {
187 $message .= " ".get_string('backupfinished')."\n";
190 //Build the message subject
191 $site = get_site();
192 $prefix = $site->shortname.": ";
193 if ($count_error != 0 || $count_unfinished != 0) {
194 $prefix .= "[".strtoupper(get_string('error'))."] ";
196 $subject = $prefix.get_string("scheduledbackupstatus");
198 //Send the message
199 email_to_user($admin,$admin,$subject,$message);
203 //Everything is finished stop backup_sche_running
204 backup_set_config("backup_sche_running","0");
206 return $status;
209 //This function executes the ENTIRE backup of a course (passed as parameter)
210 //using all the scheduled backup preferences
211 function schedule_backup_launch_backup($course,$starttime = 0) {
213 $preferences = false;
214 $status = false;
216 mtrace(" Executing backup");
217 schedule_backup_log($starttime,$course->id,"Start backup course $course->fullname");
218 schedule_backup_log($starttime,$course->id," Phase 1: Checking and counting:");
219 $preferences = schedule_backup_course_configure($course,$starttime);
221 if ($preferences) {
222 schedule_backup_log($starttime,$course->id," Phase 2: Executing and copying:");
223 $status = schedule_backup_course_execute($preferences,$starttime);
226 if ($status && $preferences) {
227 //Only if the backup_sche_keep is set
228 if ($preferences->backup_keep) {
229 schedule_backup_log($starttime,$course->id," Phase 3: Deleting old backup files:");
230 $status = schedule_backup_course_delete_old_files($preferences,$starttime);
234 if ($status && $preferences) {
235 mtrace(" End backup OK");
236 schedule_backup_log($starttime,$course->id,"End backup course $course->fullname - OK");
237 } else {
238 mtrace(" End backup with ERROR");
239 schedule_backup_log($starttime,$course->id,"End backup course $course->fullname - ERROR!!");
242 return $status && $preferences;
245 //This function saves to backup_log all the needed process info
246 //to use it later. NOTE: If $starttime = 0 no info in saved
247 function schedule_backup_log($starttime,$courseid,$message) {
249 if ($starttime) {
250 $log->courseid = $courseid;
251 $log->time = time();
252 $log->laststarttime = $starttime;
253 $log->info = addslashes($message);
255 insert_record ("backup_log",$log);
260 //This function returns the next future GMT time to execute the course based in the
261 //configuration of the scheduled backups
262 function schedule_backup_next_execution ($backup_course,$backup_config,$now,$timezone) {
264 $result = -1;
266 //Get today's midnight GMT
267 $midnight = usergetmidnight($now,$timezone);
269 //Get today's day of week (0=Sunday...6=Saturday)
270 $date = usergetdate($now,$timezone);
271 $dayofweek = $date['wday'];
273 //Get number of days (from today) to execute backups
274 $scheduled_days = substr($backup_config->backup_sche_weekdays,$dayofweek).
275 $backup_config->backup_sche_weekdays;
276 $daysfromtoday = strpos($scheduled_days, "1");
278 //If some day has been found
279 if ($daysfromtoday !== false) {
280 //Calculate distance
281 $dist = ($daysfromtoday * 86400) + //Days distance
282 ($backup_config->backup_sche_hour*3600) + //Hours distance
283 ($backup_config->backup_sche_minute*60); //Minutes distance
284 $result = $midnight + $dist;
287 //If that time is past, call the function recursively to obtain the next valid day
288 if ($result > 0 && $result < time()) {
289 $result = schedule_backup_next_execution ($backup_course,$backup_config,$now + 86400,$timezone);
292 return $result;
297 //This function implements all the needed code to prepare a course
298 //to be in backup (insert temp info into backup temp tables).
299 function schedule_backup_course_configure($course,$starttime = 0) {
301 global $CFG;
303 $status = true;
305 schedule_backup_log($starttime,$course->id," checking parameters");
307 //Check the required variable
308 if (empty($course->id)) {
309 $status = false;
311 //Get scheduled backup preferences
312 $backup_config = backup_get_config();
314 //Checks backup_config pairs exist
315 if ($status) {
316 if (!isset($backup_config->backup_sche_modules)) {
317 $backup_config->backup_sche_modules = 1;
319 if (!isset($backup_config->backup_sche_withuserdata)) {
320 $backup_config->backup_sche_withuserdata = 1;
322 if (!isset($backup_config->backup_sche_metacourse)) {
323 $backup_config->backup_sche_metacourse = 1;
325 if (!isset($backup_config->backup_sche_users)) {
326 $backup_config->backup_sche_users = 1;
328 if (!isset($backup_config->backup_sche_logs)) {
329 $backup_config->backup_sche_logs = 0;
331 if (!isset($backup_config->backup_sche_userfiles)) {
332 $backup_config->backup_sche_userfiles = 1;
334 if (!isset($backup_config->backup_sche_coursefiles)) {
335 $backup_config->backup_sche_coursefiles = 1;
337 if (!isset($backup_config->backup_sche_sitefiles)) {
338 $backup_config->backup_sche_sitefiles = 1;
340 if (!isset($backup_config->backup_sche_gradebook_history)) {
341 $backup_config->backup_sche_gradebook_history = 0;
343 if (!isset($backup_config->backup_sche_messages)) {
344 $backup_config->backup_sche_messages = 0;
346 if (!isset($backup_config->backup_sche_blogs)) {
347 $backup_config->backup_sche_blogs = 0;
349 if (!isset($backup_config->backup_sche_active)) {
350 $backup_config->backup_sche_active = 0;
352 if (!isset($backup_config->backup_sche_weekdays)) {
353 $backup_config->backup_sche_weekdays = "0000000";
355 if (!isset($backup_config->backup_sche_hour)) {
356 $backup_config->backup_sche_hour = 00;
358 if (!isset($backup_config->backup_sche_minute)) {
359 $backup_config->backup_sche_minute = 00;
361 if (!isset($backup_config->backup_sche_destination)) {
362 $backup_config->backup_sche_destination = "";
364 if (!isset($backup_config->backup_sche_keep)) {
365 $backup_config->backup_sche_keep = 1;
369 if ($status) {
370 //Checks for the required files/functions to backup every mod
371 //And check if there is data about it
372 $count = 0;
373 if ($allmods = get_records("modules") ) {
374 foreach ($allmods as $mod) {
375 $modname = $mod->name;
376 $modfile = "$CFG->dirroot/mod/$modname/backuplib.php";
377 $modbackup = $modname."_backup_mods";
378 $modcheckbackup = $modname."_check_backup_mods";
379 if (file_exists($modfile)) {
380 include_once($modfile);
381 if (function_exists($modbackup) and function_exists($modcheckbackup)) {
382 $var = "exists_".$modname;
383 $$var = true;
384 $count++;
386 // PENNY NOTES: I have moved from here to the closing brace inside
387 // by two sets of ifs()
388 // to avoid the backup failing on a non existant backup.
389 // If the file/function/whatever doesn't exist, we don't want to set this
390 // this module in backup preferences at all.
391 //Check data
392 //Check module info
393 $var = "backup_".$modname;
394 if (!isset($$var)) {
395 $$var = $backup_config->backup_sche_modules;
397 //Now stores all the mods preferences into an array into preferences
398 $preferences->mods[$modname]->backup = $$var;
400 //Check include user info
401 $var = "backup_user_info_".$modname;
402 if (!isset($$var)) {
403 $$var = $backup_config->backup_sche_withuserdata;
405 //Now stores all the mods preferences into an array into preferences
406 $preferences->mods[$modname]->userinfo = $$var;
407 //And the name of the mod
408 $preferences->mods[$modname]->name = $modname;
414 // now set instances
415 if ($coursemods = get_course_mods($course->id)) {
416 foreach ($coursemods as $mod) {
417 if (array_key_exists($mod->modname,$preferences->mods)) { // we are to backup this module
418 if (empty($preferences->mods[$mod->modname]->instances)) {
419 $preferences->mods[$mod->modname]->instances = array(); // avoid warnings
421 $preferences->mods[$mod->modname]->instances[$mod->instance]->backup = $preferences->mods[$mod->modname]->backup;
422 $preferences->mods[$mod->modname]->instances[$mod->instance]->userinfo = $preferences->mods[$mod->modname]->userinfo;
423 // there isn't really a nice way to do this...
424 $preferences->mods[$mod->modname]->instances[$mod->instance]->name = get_field($mod->modname,'name','id',$mod->instance);
429 // finally, clean all the $preferences->mods[] not having instances. Nothing to backup about them
430 foreach ($preferences->mods as $modname => $mod) {
431 if (!isset($mod->instances)) {
432 unset($preferences->mods[$modname]);
437 //Convert other parameters
438 if ($status) {
439 $preferences->backup_metacourse = $backup_config->backup_sche_metacourse;
440 $preferences->backup_users = $backup_config->backup_sche_users;
441 $preferences->backup_logs = $backup_config->backup_sche_logs;
442 $preferences->backup_user_files = $backup_config->backup_sche_userfiles;
443 $preferences->backup_course_files = $backup_config->backup_sche_coursefiles;
444 $preferences->backup_site_files = $backup_config->backup_sche_sitefiles;
445 $preferences->backup_gradebook_history = $backup_config->backup_sche_gradebook_history;
446 $preferences->backup_messages = $backup_config->backup_sche_messages;
447 $preferences->backup_blogs = $backup_config->backup_sche_blogs;
448 $preferences->backup_course = $course->id;
449 $preferences->backup_destination = $backup_config->backup_sche_destination;
450 $preferences->backup_keep = $backup_config->backup_sche_keep;
453 //Calculate various backup preferences
454 if ($status) {
455 schedule_backup_log($starttime,$course->id," calculating backup name");
457 //Calculate the backup file name
458 $backup_name = backup_get_zipfile_name($course);
460 //Calculate the string to match the keep preference
461 $keep_name = backup_get_keep_name($course);
463 //Set them
464 $preferences->backup_name = $backup_name;
465 $preferences->keep_name = $keep_name;
467 //Roleasignments
468 $roles = get_records('role', '', '', 'sortorder');
469 foreach ($roles as $role) {
470 $preferences->backuproleassignments[$role->id] = $role;
473 //Another Info
474 backup_add_static_preferences($preferences);
477 //Calculate the backup unique code to allow simultaneus backups (to define
478 //the temp-directory name and records in backup temp tables
479 if ($status) {
480 $backup_unique_code = time();
481 $preferences->backup_unique_code = $backup_unique_code;
484 //Calculate necesary info to backup modules
485 if ($status) {
486 schedule_backup_log($starttime,$course->id," calculating modules data");
487 if ($allmods = get_records("modules") ) {
488 foreach ($allmods as $mod) {
489 $modname = $mod->name;
490 $modbackup = $modname."_backup_mods";
491 //If exists the lib & function
492 $var = "exists_".$modname;
493 if (isset($$var) && $$var) {
494 //Add hidden fields
495 $var = "backup_".$modname;
496 //Only if selected
497 if ($$var == 1) {
498 $var = "backup_user_info_".$modname;
499 //Call the check function to show more info
500 $modcheckbackup = $modname."_check_backup_mods";
501 schedule_backup_log($starttime,$course->id," $modname");
502 $modcheckbackup($course->id,$$var,$backup_unique_code);
509 //Now calculate the users
510 if ($status) {
511 schedule_backup_log($starttime,$course->id," calculating users");
512 //Decide about include users with messages, based on SITEID
513 if ($preferences->backup_messages && $preferences->backup_course == SITEID) {
514 $include_message_users = true;
515 } else {
516 $include_message_users = false;
518 //Decide about include users with blogs, based on SITEID
519 if ($preferences->backup_blogs && $preferences->backup_course == SITEID) {
520 $include_blog_users = true;
521 } else {
522 $include_blog_users = false;
524 user_check_backup($course->id,$backup_unique_code,$preferences->backup_users,$include_message_users, $include_blog_users);
527 //Now calculate the logs
528 if ($status) {
529 if ($preferences->backup_logs) {
530 schedule_backup_log($starttime,$course->id," calculating logs");
531 log_check_backup($course->id);
535 //Now calculate the userfiles
536 if ($status) {
537 if ($preferences->backup_user_files) {
538 schedule_backup_log($starttime,$course->id," calculating user files");
539 user_files_check_backup($course->id,$preferences->backup_unique_code);
543 //Now calculate the coursefiles
544 if ($status) {
545 if ($preferences->backup_course_files) {
546 schedule_backup_log($starttime,$course->id," calculating course files");
547 course_files_check_backup($course->id,$preferences->backup_unique_code);
551 //Now calculate the sitefiles
552 if ($status) {
553 if ($preferences->backup_site_files) {
554 schedule_backup_log($starttime,$course->id," calculating site files");
555 site_files_check_backup($course->id,$preferences->backup_unique_code);
559 //If everything is ok, return calculated preferences
560 if ($status) {
561 $status = $preferences;
564 return $status;
567 //TODO: Unify this function with backup_execute() to have both backups 100% equivalent. Moodle 2.0
569 //This function implements all the needed code to backup a course
570 //copying it to the desired destination (default if not specified)
571 function schedule_backup_course_execute($preferences,$starttime = 0) {
573 global $CFG;
575 $status = true;
577 //Some parts of the backup doesn't know about $preferences, so we
578 //put a copy of it inside that CFG (always global) to be able to
579 //use it. Then, when needed I search for preferences inside CFG
580 //Used to avoid some problems in full_tag() when preferences isn't
581 //set globally (i.e. in scheduled backups)
582 $CFG->backup_preferences = $preferences;
584 //Check for temp and backup and backup_unique_code directory
585 //Create them as needed
586 schedule_backup_log($starttime,$preferences->backup_course," checking temp structures");
587 $status = check_and_create_backup_dir($preferences->backup_unique_code);
588 //Empty backup dir
589 if ($status) {
590 schedule_backup_log($starttime,$preferences->backup_course," cleaning current dir");
591 $status = clear_backup_dir($preferences->backup_unique_code);
594 //Create the moodle.xml file
595 if ($status) {
596 schedule_backup_log($starttime,$preferences->backup_course," creating backup file");
597 //Obtain the xml file (create and open) and print prolog information
598 $backup_file = backup_open_xml($preferences->backup_unique_code);
599 //Prints general info about backup to file
600 if ($backup_file) {
601 schedule_backup_log($starttime,$preferences->backup_course," general info");
602 $status = backup_general_info($backup_file,$preferences);
603 } else {
604 $status = false;
607 //Prints course start (tag and general info)
608 if ($status) {
609 $status = backup_course_start($backup_file,$preferences);
612 //Metacourse information
613 if ($status && $preferences->backup_metacourse) {
614 schedule_backup_log($starttime,$preferences->backup_course," metacourse info");
615 $status = backup_course_metacourse($backup_file,$preferences);
618 //Block info
619 if ($status) {
620 schedule_backup_log($starttime,$preferences->backup_course," blocks info");
621 $status = backup_course_blocks($backup_file,$preferences);
624 //Section info
625 if ($status) {
626 schedule_backup_log($starttime,$preferences->backup_course," sections info");
627 $status = backup_course_sections($backup_file,$preferences);
630 //User info
631 if ($status) {
632 schedule_backup_log($starttime,$preferences->backup_course," user info");
633 $status = backup_user_info($backup_file,$preferences);
636 //If we have selected to backup messages and we are
637 //doing a SITE backup, let's do it
638 if ($status && $preferences->backup_messages && $preferences->backup_course == SITEID) {
639 schedule_backup_log($starttime,$preferences->backup_course," messages");
640 $status = backup_messages($backup_file,$preferences);
643 //If we have selected to backup blogs and we are
644 //doing a SITE backup, let's do it
645 if ($status && $preferences->backup_blogs && $preferences->backup_course == SITEID) {
646 schedule_backup_log($starttime,$preferences->backup_course," blogs");
647 $status = backup_blogs($backup_file,$preferences);
650 //If we have selected to backup quizzes, backup categories and
651 //questions structure (step 1). See notes on mod/quiz/backuplib.php
652 if ($status and $preferences->mods['quiz']->backup) {
653 schedule_backup_log($starttime,$preferences->backup_course," categories & questions");
654 $status = backup_question_categories($backup_file,$preferences);
657 //Print logs if selected
658 if ($status) {
659 if ($preferences->backup_logs) {
660 schedule_backup_log($starttime,$preferences->backup_course," logs");
661 $status = backup_log_info($backup_file,$preferences);
665 //Print scales info
666 if ($status) {
667 schedule_backup_log($starttime,$preferences->backup_course," scales");
668 $status = backup_scales_info($backup_file,$preferences);
671 //Print groups info
672 if ($status) {
673 schedule_backup_log($starttime,$preferences->backup_course," groups");
674 $status = backup_groups_info($backup_file,$preferences);
677 //Print groupings info
678 if ($status) {
679 schedule_backup_log($starttime,$preferences->backup_course," groupings");
680 $status = backup_groupings_info($backup_file,$preferences);
683 //Print groupings_groups info
684 if ($status) {
685 schedule_backup_log($starttime,$preferences->backup_course," groupings_groups");
686 $status = backup_groupings_groups_info($backup_file,$preferences);
689 //Print events info
690 if ($status) {
691 schedule_backup_log($starttime,$preferences->backup_course," events");
692 $status = backup_events_info($backup_file,$preferences);
695 //Print gradebook info
696 if ($status) {
697 schedule_backup_log($starttime,$preferences->backup_course," gradebook");
698 $status = backup_gradebook_info($backup_file,$preferences);
701 //Module info, this unique function makes all the work!!
702 //db export and module fileis copy
703 if ($status) {
704 $mods_to_backup = false;
705 //Check if we have any mod to backup
706 foreach ($preferences->mods as $module) {
707 if ($module->backup) {
708 $mods_to_backup = true;
711 //If we have to backup some module
712 if ($mods_to_backup) {
713 schedule_backup_log($starttime,$preferences->backup_course," modules");
714 //Start modules tag
715 $status = backup_modules_start ($backup_file,$preferences);
716 //Iterate over modules and call backup
717 foreach ($preferences->mods as $module) {
718 if ($module->backup and $status) {
719 schedule_backup_log($starttime,$preferences->backup_course," $module->name");
720 $status = backup_module($backup_file,$preferences,$module->name);
723 //Close modules tag
724 $status = backup_modules_end ($backup_file,$preferences);
728 //Backup course format data, if any.
729 if ($status) {
730 schedule_backup_log($starttime,$preferences->backup_course," course format data");
731 $status = backup_format_data($backup_file,$preferences);
734 //Prints course end
735 if ($status) {
736 $status = backup_course_end($backup_file,$preferences);
739 //Close the xml file and xml data
740 if ($backup_file) {
741 backup_close_xml($backup_file);
745 //Now, if selected, copy user files
746 if ($status) {
747 if ($preferences->backup_user_files) {
748 schedule_backup_log($starttime,$preferences->backup_course," copying user files");
749 $status = backup_copy_user_files ($preferences);
753 //Now, if selected, copy course files
754 if ($status) {
755 if ($preferences->backup_course_files) {
756 schedule_backup_log($starttime,$preferences->backup_course," copying course files");
757 $status = backup_copy_course_files ($preferences);
761 //Now, if selected, copy site files
762 if ($status) {
763 if ($preferences->backup_site_files) {
764 schedule_backup_log($starttime,$preferences->backup_course," copying site files");
765 $status = backup_copy_site_files ($preferences);
769 //Now, zip all the backup directory contents
770 if ($status) {
771 schedule_backup_log($starttime,$preferences->backup_course," zipping files");
772 $status = backup_zip ($preferences);
775 //Now, copy the zip file to course directory
776 if ($status) {
777 schedule_backup_log($starttime,$preferences->backup_course," copying backup");
778 $status = copy_zip_to_course_dir ($preferences);
781 //Now, clean temporary data (db and filesystem)
782 if ($status) {
783 schedule_backup_log($starttime,$preferences->backup_course," cleaning temp data");
784 $status = clean_temp_data ($preferences);
787 //Unset CFG->backup_preferences only needed in scheduled backups
788 unset ($CFG->backup_preferences);
790 return $status;
793 //This function deletes old backup files when the "keep" limit has been reached
794 //in the destination directory.
795 function schedule_backup_course_delete_old_files($preferences,$starttime=0) {
797 global $CFG;
799 $status = true;
801 //Calculate the directory to check
802 $dirtocheck = "";
803 //if $preferences->backup_destination isn't empty, then check that directory
804 if (!empty($preferences->backup_destination)) {
805 $dirtocheck = $preferences->backup_destination;
806 //else calculate standard backup directory location
807 } else {
808 $dirtocheck = $CFG->dataroot."/".$preferences->backup_course."/backupdata";
810 schedule_backup_log($starttime,$preferences->backup_course," checking $dirtocheck");
811 if ($CFG->debug > 7) {
812 mtrace(" Keeping backup files in $dirtocheck");
815 //Get all the files in $dirtocheck
816 $files = get_directory_list($dirtocheck,"",false);
817 //Get all matching files ($preferences->keep_name) from $files
818 $matchingfiles = array();
819 foreach ($files as $file) {
820 if (substr($file, 0, strlen($preferences->keep_name)) == $preferences->keep_name) {
821 $modifieddate = filemtime($dirtocheck."/".$file);
822 $matchingfiles[$modifieddate] = $file;
825 //Sort by key (modified date) to get the oldest first (instead of doing that by name
826 //because it could give us problems in some languages with different format names).
827 ksort($matchingfiles);
829 //Count matching files
830 $countmatching = count($matchingfiles);
831 schedule_backup_log($starttime,$preferences->backup_course," found $countmatching backup files");
832 mtrace(" found $countmatching backup files");
833 if ($preferences->backup_keep < $countmatching) {
834 schedule_backup_log($starttime,$preferences->backup_course," keep limit ($preferences->backup_keep) reached. Deleting old files");
835 mtrace(" keep limit ($preferences->backup_keep) reached. Deleting old files");
836 $filestodelete = $countmatching - $preferences->backup_keep;
837 $filesdeleted = 0;
838 foreach ($matchingfiles as $matchfile) {
839 if ($filesdeleted < $filestodelete) {
840 schedule_backup_log($starttime,$preferences->backup_course," $matchfile deleted");
841 mtrace(" $matchfile deleted");
842 $filetodelete = $dirtocheck."/".$matchfile;
843 unlink($filetodelete);
844 $filesdeleted++;
848 return $status;