Moodle release 1.9.15
[moodle.git] / backup / backuplib.php
blobf48774989ea1a2b7aca95ed2886806d8e704b066
1 <?php //$Id$
2 //This file contains all the function needed in the backup utility
3 //except the mod-related funtions that are into every backuplib.php inside
4 //every mod directory
6 /**
7 * This function calculates the users to be added to backup based in the
8 * settings defined at backup. All the resulting user ids are sent to
9 * backup_ids for later usage.
10 * @param int $courseid id of the course to backup
11 * @param int $backup_unique_code unique code of the backup being executed
12 * @param int $backup_unique_code setting specifying what users to export (0=all, 1=needed, 2=none)
13 * @param int $backup_messages flag (true/false) defining if messages must be
14 * considered to extract needed users
15 * @param int $backup_blogs flag (true/false) defining if blogs must be
16 * considered to extract needed users
17 * @return array one array (key, value) sumarizing the result of the function (number of users)
19 function user_check_backup($courseid,$backup_unique_code,$backup_users,$backup_messages,$backup_blogs) {
21 $context = get_context_instance(CONTEXT_COURSE, $courseid);
22 $count_users = 0;
23 $backupable_users = array();
25 if ($backup_users == 0) { /// All users
26 $backupable_users = backup_get_all_users();
28 } else if ($backup_users == 1) { /// Needed users
30 /// Calculate needed users (calling every xxxx_get_participants function + scales users
31 /// + messages users + blogs users)
32 $needed_users = backup_get_needed_users($courseid, $backup_messages, $backup_blogs);
34 /// Calculate enrolled users (having course:view cap)
35 $enrolled_users = backup_get_enrolled_users($courseid);
37 /// Calculate backupable users (needed + enrolled)
38 /// First, needed
39 $backupable_users = $needed_users;
41 /// Now, enrolled
42 if ($enrolled_users) {
43 foreach ($enrolled_users as $enrolled_user) {
44 $backupable_users[$enrolled_user->id]->id = $enrolled_user->id;
49 /// If we have backupable users
50 if ($backupable_users) {
51 /// Iterate over users putting their roles
52 foreach ($backupable_users as $backupable_user) {
53 $backupable_user->info = "";
55 /// Is needed user or enrolled user, mark it as needed
56 if (isset($needed_users[$backupable_user->id]) || isset($enrolled_users[$backupable_user->id])) {
57 $backupable_user->info .= "needed";
58 } /// Yu: also needed because they can view course
59 /// might need another variable
61 /// Now create the backup_id record
62 $backupids_rec->backup_code = $backup_unique_code;
63 $backupids_rec->table_name = "user";
64 $backupids_rec->old_id = $backupable_user->id;
65 $backupids_rec->info = $backupable_user->info;
67 /// TODO: Change this call inserting to a standard backup_putid() call
68 /// And read data acordingly with backup_getid() when needed.
69 /// TODO: Also analyse it the "needed" info is really needed for anything. Drop if not.
70 /// Insert the user to the backup_ids table. backup_user_info() will use that info
71 $status = insert_record('backup_ids', $backupids_rec, false);
72 $count_users++;
74 /// Do some output
75 backup_flush(30);
78 /// Prepare Info
79 /// Gets the user data
80 $info[0][0] = get_string("users");
81 $info[0][1] = $count_users;
83 return $info;
86 //Returns every needed user (participant) in a course
87 //It uses the xxxx_get_participants() function
88 //Also it search for users having messages and
89 //users having blogs
90 //WARNING: It returns only NEEDED users, not every
91 // every student and teacher in the course, so it
92 //must be merged with backup_get_enrrolled_users !!
94 function backup_get_needed_users ($courseid, $includemessages=false, $includeblogs=false) {
96 global $CFG;
98 $result = false;
100 $course_modules = get_records_sql ("SELECT cm.id, m.name, cm.instance
101 FROM {$CFG->prefix}modules m,
102 {$CFG->prefix}course_modules cm
103 WHERE m.id = cm.module and
104 cm.course = '$courseid'");
106 if ($course_modules) {
107 //Iterate over each module
108 foreach ($course_modules as $course_module) {
109 $modlib = "$CFG->dirroot/mod/$course_module->name/lib.php";
110 $modgetparticipants = $course_module->name."_get_participants";
111 if (file_exists($modlib)) {
112 include_once($modlib);
113 if (function_exists($modgetparticipants)) {
114 $module_participants = $modgetparticipants($course_module->instance);
115 //Add them to result
116 if ($module_participants) {
117 foreach ($module_participants as $module_participant) {
118 $result[$module_participant->id]->id = $module_participant->id;
126 //Now, add message users if necessary
127 if ($includemessages) {
128 include_once("$CFG->dirroot/message/lib.php");
129 //Get users
130 $messageusers = message_get_participants();
131 //Add message users to results
132 if ($messageusers) {
133 foreach ($messageusers as $messageuser) {
134 //If id != 0
135 if ($messageuser->id !=0) {
136 $result[$messageuser->id]->id = $messageuser->id;
142 //Now, add blog users if necessary
143 if ($includeblogs) {
144 include_once("$CFG->dirroot/blog/lib.php");
145 //Get users
146 $blogusers = blog_get_participants();
147 //Add blog users to results
148 if ($blogusers) {
149 foreach ($blogusers as $bloguser) {
150 //If id != 0
151 if ($bloguser->id !=0) {
152 $result[$bloguser->id]->id = $bloguser->id;
158 return $result;
162 //Returns every enrolled user (student and teacher) in a course
164 function backup_get_enrolled_users ($courseid) {
166 global $CFG;
168 // get all users with moodle/course:view capability, this will include people
169 // assigned at cat level, or site level
170 // but it should be ok if they have no direct assignment at course, mod, block level
171 return get_users_by_capability(get_context_instance(CONTEXT_COURSE, $courseid), 'moodle/course:view', '', '', '', '', '', '', false);
174 //Returns all users ids (every record in users table)
175 function backup_get_all_users() {
177 return get_records('user', '', '', '', 'id, id');
180 //Calculate the number of log entries to backup
181 //Return an array of info (name,value)
182 function log_check_backup($course) {
184 global $CFG;
186 //Now execute the count
187 $ids = count_records("log","course",$course);
189 //Gets the user data
190 $info[0][0] = get_string("logs");
191 if ($ids) {
192 $info[0][1] = $ids;
193 } else {
194 $info[0][1] = 0;
197 return $info;
200 //Calculate the number of user files to backup
201 //Under $CFG->dataroot/users
202 //Return an array of info (name,value)
203 function user_files_check_backup($course,$backup_unique_code) {
205 global $CFG;
206 $count = 0;
208 $backup_users = get_recordset_select("backup_ids",
209 "backup_code='$backup_unique_code' AND table_name='user'", "", "id, old_id");
211 while ($user = rs_fetch_next_record($backup_users)) {
212 //Is this user needed in the backup?
213 $userdir = make_user_directory($user->old_id, true);
214 if (check_dir_exists($userdir)) {
215 $count++;
217 //Do some output
218 backup_flush(30);
220 rs_close($backup_users);
221 //Gets the user data
222 $info[0][0] = get_string('userswithfiles', 'moodle');
223 $info[0][1] = $count;
225 return $info;
229 * Calculate the number of course files to backup
230 * under $CFG->dataroot/$course, except $CFG->moddata, and backupdata
231 * and put them (their path) in backup_ids
232 * Return an array of info (name,value)
234 function course_files_check_backup($course, $backup_unique_code) {
236 global $CFG;
238 $rootdir = $CFG->dataroot."/$course";
239 //Check if directory exists
240 if (is_dir($rootdir)) {
241 //Get files and directories without descend
242 $coursedirs = get_directory_list($rootdir,$CFG->moddata,false,true,true);
243 $backupdata_dir = "backupdata";
244 foreach ($coursedirs as $dir) {
245 //Check it isn't backupdata_dir
246 if (strpos($dir,$backupdata_dir)!==0) {
247 //Insert them into backup_files
248 $status = execute_sql("INSERT INTO {$CFG->prefix}backup_files
249 (backup_code, file_type, path)
250 VALUES
251 ('$backup_unique_code','course','".addslashes($dir)."')",false);
253 //Do some output
254 backup_flush(30);
258 //Now execute the select
259 $ids = get_records_sql("SELECT DISTINCT b.path, b.old_id
260 FROM {$CFG->prefix}backup_files b
261 WHERE backup_code = '$backup_unique_code' AND
262 file_type = 'course'");
263 //Gets the user data
264 $info = array();
265 $info[0] = array();
266 $info[0][0] = get_string("files");
267 if ($ids) {
268 $info[0][1] = count($ids);
269 } else {
270 $info[0][1] = 0;
273 return $info;
277 * Calculate the number of site files to backup
278 * under $CFG->dataroot/SITEID
279 * Their path is already in backup_ids, put there by modules check_backup functions.
280 * Modules only put in paths of files that are used.
282 * Return an array of info (name,value)
284 function site_files_check_backup($course, $backup_unique_code) {
285 global $CFG;
287 //execute the select, records have been inserted by modules during their ****_check_backup_mods function.
288 $ids = get_records_sql("SELECT DISTINCT b.path
289 FROM {$CFG->prefix}backup_files b
290 WHERE backup_code = '$backup_unique_code' AND
291 file_type = 'site'");
292 //Gets the user data
293 $info = array();
294 $info[0] = array();
295 $info[0][0] = get_string('files');
296 if ($ids) {
297 $info[0][1] = count($ids);
298 } else {
299 $info[0][1] = 0;
302 return $info;
305 //Function to check and create the needed moddata dir to
306 //save all the mod backup files. We always name it moddata
307 //to be able to restore it, but in restore we check for
308 //$CFG->moddata !!
309 function check_and_create_moddata_dir($backup_unique_code) {
311 global $CFG;
313 $status = check_dir_exists($CFG->dataroot."/temp/backup/".$backup_unique_code."/moddata",true);
315 return $status;
318 //Function to check and create the "user_files" dir to
319 //save all the user files we need from "users" dir
320 function check_and_create_user_files_dir($backup_unique_code) {
322 global $CFG;
324 $status = check_dir_exists($CFG->dataroot."/temp/backup/".$backup_unique_code."/user_files",true);
326 return $status;
329 //Function to check and create the "group_files" dir to
330 //save all the user files we need from "groups" dir
331 function check_and_create_group_files_dir($backup_unique_code) {
333 global $CFG;
335 $status = check_dir_exists($CFG->dataroot."/temp/backup/".$backup_unique_code."/group_files",true);
337 return $status;
340 //Function to check and create the "course_files" dir to
341 //save all the course files we need from "CFG->datadir/course" dir
342 function check_and_create_course_files_dir($backup_unique_code) {
344 global $CFG;
346 $status = check_dir_exists($CFG->dataroot."/temp/backup/".$backup_unique_code."/course_files",true);
348 return $status;
351 //Function to check and create the "site_files" dir to
352 //save all the course files we need from "CFG->datadir/SITEID" dir
353 function check_and_create_site_files_dir($backup_unique_code) {
355 global $CFG;
357 $status = check_dir_exists($CFG->dataroot."/temp/backup/".$backup_unique_code."/site_files",true);
359 return $status;
362 //Function to create, open and write header of the xml file
363 function backup_open_xml($backup_unique_code) {
365 global $CFG;
367 $status = true;
369 //Open for writing
371 $file = $CFG->dataroot."/temp/backup/".$backup_unique_code."/moodle.xml";
372 $backup_file = fopen($file,"w");
373 //Writes the header
374 $status = fwrite ($backup_file,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
375 if ($status) {
376 $status = fwrite ($backup_file,start_tag("MOODLE_BACKUP",0,true));
378 if ($status) {
379 return $backup_file;
380 } else {
381 return false;
385 //Close the file
386 function backup_close_xml($backup_file) {
387 $status = fwrite ($backup_file,end_tag("MOODLE_BACKUP",0,true));
388 return fclose($backup_file);
391 //Return the xml start tag
392 function start_tag($tag,$level=0,$endline=false,$attributes=null) {
393 if ($endline) {
394 $endchar = "\n";
395 } else {
396 $endchar = "";
398 $attrstring = '';
399 if (!empty($attributes) && is_array($attributes)) {
400 foreach ($attributes as $key => $value) {
401 $attrstring .= " ".xml_tag_safe_content($key)."=\"".
402 xml_tag_safe_content($value)."\"";
405 return str_repeat(" ",$level*2)."<".strtoupper($tag).$attrstring.">".$endchar;
408 //Return the xml end tag
409 function end_tag($tag,$level=0,$endline=true) {
410 if ($endline) {
411 $endchar = "\n";
412 } else {
413 $endchar = "";
415 return str_repeat(" ",$level*2)."</".strtoupper($tag).">".$endchar;
418 //Return the start tag, the contents and the end tag
419 function full_tag($tag,$level=0,$endline=true,$content,$attributes=null) {
421 global $CFG;
422 //Here we encode absolute links
423 // MDL-10770
424 if (is_null($content)) {
425 $content = '$@NULL@$';
426 } else {
427 $content = backup_encode_absolute_links($content);
429 $st = start_tag($tag,$level,$endline,$attributes);
431 $co = xml_tag_safe_content($content);
433 $et = end_tag($tag,0,true);
435 return $st.$co.$et;
439 function xml_tag_safe_content($content) {
440 global $CFG;
441 //If enabled, we strip all the control chars (\x0-\x1f) from the text but tabs (\x9),
442 //newlines (\xa) and returns (\xd). The delete control char (\x7f) is also included.
443 //because they are forbiden in XML 1.0 specs. The expression below seems to be
444 //UTF-8 safe too because it simply ignores the rest of characters.
445 $content = preg_replace("/[\x-\x8\xb-\xc\xe-\x1f\x7f]/is","",$content);
446 $content = preg_replace("/\r\n|\r/", "\n", htmlspecialchars($content));
447 return $content;
450 //Prints General info about the course
451 //name, moodle_version (internal and release), backup_version, date, info in file...
452 function backup_general_info ($bf,$preferences) {
454 global $CFG;
456 fwrite ($bf,start_tag("INFO",1,true));
458 //The name of the backup
459 fwrite ($bf,full_tag("NAME",2,false,$preferences->backup_name));
460 //The moodle_version
461 fwrite ($bf,full_tag("MOODLE_VERSION",2,false,$preferences->moodle_version));
462 fwrite ($bf,full_tag("MOODLE_RELEASE",2,false,$preferences->moodle_release));
463 //The backup_version
464 fwrite ($bf,full_tag("BACKUP_VERSION",2,false,$preferences->backup_version));
465 fwrite ($bf,full_tag("BACKUP_RELEASE",2,false,$preferences->backup_release));
466 //The date
467 fwrite ($bf,full_tag("DATE",2,false,$preferences->backup_unique_code));
468 //The original site wwwroot
469 fwrite ($bf,full_tag("ORIGINAL_WWWROOT",2,false,$CFG->wwwroot));
470 //The original site identifier. MD5 hashed for security.
471 fwrite ($bf,full_tag("ORIGINAL_SITE_IDENTIFIER_HASH",2,false,md5(get_site_identifier())));
472 //The zip method used
473 if (!empty($CFG->zip)) {
474 $zipmethod = 'external';
475 } else {
476 $zipmethod = 'internal';
478 //Indicate if it includes external MNET users
479 $sql = "SELECT b.old_id
480 FROM {$CFG->prefix}backup_ids b
481 JOIN {$CFG->prefix}user u ON b.old_id=u.id
482 WHERE b.backup_code = '$preferences->backup_unique_code'
483 AND b.table_name = 'user' AND u.mnethostid != '{$CFG->mnet_localhost_id}'";
484 if (record_exists_sql($sql)) {
485 fwrite ($bf,full_tag("MNET_REMOTEUSERS",2,false,'true'));
487 fwrite ($bf,full_tag("ZIP_METHOD",2,false,$zipmethod));
488 //Te includes tag
489 fwrite ($bf,start_tag("DETAILS",2,true));
490 //Now, go to mod element of preferences to print its status
491 foreach ($preferences->mods as $element) {
492 //Calculate info
493 $included = "false";
494 $userinfo = "false";
495 if ($element->backup) {
496 $included = "true";
497 if ($element->userinfo) {
498 $userinfo = "true";
501 //Prints the mod start
502 fwrite ($bf,start_tag("MOD",3,true));
503 fwrite ($bf,full_tag("NAME",4,false,$element->name));
504 fwrite ($bf,full_tag("INCLUDED",4,false,$included));
505 fwrite ($bf,full_tag("USERINFO",4,false,$userinfo));
507 if (isset($preferences->mods[$element->name]->instances)
508 && is_array($preferences->mods[$element->name]->instances)
509 && count($preferences->mods[$element->name]->instances)) {
510 fwrite ($bf, start_tag("INSTANCES",4,true));
511 foreach ($preferences->mods[$element->name]->instances as $id => $object) {
512 if (!empty($object->backup)) {
513 //Calculate info
514 $included = "false";
515 $userinfo = "false";
516 if ($object->backup) {
517 $included = "true";
518 if ($object->userinfo) {
519 $userinfo = "true";
522 fwrite ($bf, start_tag("INSTANCE",5,true));
523 fwrite ($bf, full_tag("ID",5,false,$id));
524 fwrite ($bf, full_tag("NAME",5,false,$object->name));
525 fwrite ($bf, full_tag("INCLUDED",5,false,$included)) ;
526 fwrite ($bf, full_tag("USERINFO",5,false,$userinfo));
527 fwrite ($bf, end_tag("INSTANCE",5,true));
530 fwrite ($bf, end_tag("INSTANCES",4,true));
534 //Print the end
535 fwrite ($bf,end_tag("MOD",3,true));
537 //The metacourse in backup
538 if ($preferences->backup_metacourse == 1) {
539 fwrite ($bf,full_tag("METACOURSE",3,false,"true"));
540 } else {
541 fwrite ($bf,full_tag("METACOURSE",3,false,"false"));
543 //The user in backup
544 if ($preferences->backup_users == 1) {
545 fwrite ($bf,full_tag("USERS",3,false,"course"));
546 } else if ($preferences->backup_users == 0) {
547 fwrite ($bf,full_tag("USERS",3,false,"all"));
548 } else {
549 fwrite ($bf,full_tag("USERS",3,false,"none"));
551 //The logs in backup
552 if ($preferences->backup_logs == 1) {
553 fwrite ($bf,full_tag("LOGS",3,false,"true"));
554 } else {
555 fwrite ($bf,full_tag("LOGS",3,false,"false"));
557 //The user files
558 if ($preferences->backup_user_files == 1) {
559 fwrite ($bf,full_tag("USERFILES",3,false,"true"));
560 } else {
561 fwrite ($bf,full_tag("USERFILES",3,false,"false"));
563 //The course files
564 if ($preferences->backup_course_files == 1) {
565 fwrite ($bf,full_tag("COURSEFILES",3,false,"true"));
566 } else {
567 fwrite ($bf,full_tag("COURSEFILES",3,false,"false"));
569 //The site files
570 if ($preferences->backup_site_files == 1) {
571 fwrite ($bf,full_tag("SITEFILES",3,false,"true"));
572 } else {
573 fwrite ($bf,full_tag("SITEFILES",3,false,"false"));
575 //The gradebook histories
576 if (empty($CFG->disablegradehistory) && $preferences->backup_gradebook_history == 1) {
577 fwrite ($bf,full_tag("GRADEBOOKHISTORIES",3,false,"true"));
578 } else {
579 fwrite ($bf,full_tag("GRADEBOOKHISTORIES",3,false,"false"));
581 //The messages in backup
582 if ($preferences->backup_messages == 1 && $preferences->backup_course == SITEID) {
583 fwrite ($bf,full_tag("MESSAGES",3,false,"true"));
584 } else {
585 fwrite ($bf,full_tag("MESSAGES",3,false,"false"));
587 //The blogs in backup
588 if ($preferences->backup_blogs == 1 && $preferences->backup_course == SITEID) {
589 fwrite ($bf,full_tag("BLOGS",3,false,"true"));
590 } else {
591 fwrite ($bf,full_tag("BLOGS",3,false,"false"));
593 //The mode of writing the block data
594 fwrite ($bf,full_tag('BLOCKFORMAT',3,false,'instances'));
595 fwrite ($bf,end_tag("DETAILS",2,true));
597 $status = fwrite ($bf,end_tag("INFO",1,true));
599 ///Roles stuff goes in here
601 fwrite ($bf, start_tag('ROLES', 1, true));
602 $roles = backup_fetch_roles($preferences);
604 $sitecontext = get_context_instance(CONTEXT_SYSTEM);
605 $coursecontext = get_context_instance(CONTEXT_COURSE, $preferences->backup_course);
607 foreach ($roles as $role) {
608 fwrite ($bf,start_tag('ROLE',2,true));
609 fwrite ($bf,full_tag('ID', 3, false, $role->id));
610 fwrite ($bf,full_tag('NAME',3,false,$role->name));
611 fwrite ($bf,full_tag('SHORTNAME',3,false,$role->shortname));
612 /// Calculate $role name in course
613 $nameincourse = role_get_name($role, $coursecontext);
614 if ($nameincourse != $role->name) {
615 fwrite ($bf,full_tag('NAMEINCOURSE', 3, false, $nameincourse));
617 // find and write all default capabilities
618 fwrite ($bf,start_tag('CAPABILITIES',3,true));
619 // pull out all default (site context) capabilities
620 if ($capabilities = role_context_capabilities($role->id, $sitecontext)) {
621 foreach ($capabilities as $capability=>$value) {
622 fwrite ($bf,start_tag('CAPABILITY',4,true));
623 fwrite ($bf,full_tag('NAME', 5, false, $capability));
624 fwrite ($bf,full_tag('PERMISSION', 5, false, $value));
625 // use this to pull out the other info (timemodified and modifierid)
627 $cap = get_record_sql("SELECT *
628 FROM {$CFG->prefix}role_capabilities
629 WHERE capability = '$capability'
630 AND contextid = $sitecontext->id
631 AND roleid = $role->id");
632 fwrite ($bf, full_tag("TIMEMODIFIED", 5, false, $cap->timemodified));
633 fwrite ($bf, full_tag("MODIFIERID", 5, false, $cap->modifierid));
634 fwrite ($bf,end_tag('CAPABILITY',4,true));
637 fwrite ($bf,end_tag('CAPABILITIES',3,true));
638 fwrite ($bf,end_tag('ROLE',2,true));
640 fwrite ($bf,end_tag('ROLES', 1, true));
641 return $status;
644 //Prints course's general info (table course)
645 function backup_course_start ($bf,$preferences) {
647 global $CFG;
649 $status = true;
651 //Course open tag
652 fwrite ($bf,start_tag("COURSE",1,true));
653 //Header open tag
654 fwrite ($bf,start_tag("HEADER",2,true));
656 //Get info from course
657 $course = get_record("course","id",$preferences->backup_course);
658 $context = get_context_instance(CONTEXT_COURSE, $course->id);
659 if ($course) {
660 //Prints course info
661 fwrite ($bf,full_tag("ID",3,false,$course->id));
662 //Obtain the category
663 $category = get_record("course_categories","id","$course->category");
664 if ($category) {
665 //Prints category info
666 fwrite ($bf,start_tag("CATEGORY",3,true));
667 fwrite ($bf,full_tag("ID",4,false,$course->category));
668 fwrite ($bf,full_tag("NAME",4,false,$category->name));
669 fwrite ($bf,end_tag("CATEGORY",3,true));
671 //Continues with the course
672 fwrite ($bf,full_tag("PASSWORD",3,false,$course->password));
673 fwrite ($bf,full_tag("FULLNAME",3,false,$course->fullname));
674 fwrite ($bf,full_tag("SHORTNAME",3,false,$course->shortname));
675 fwrite ($bf,full_tag("IDNUMBER",3,false,$course->idnumber));
676 fwrite ($bf,full_tag("SUMMARY",3,false,$course->summary));
677 fwrite ($bf,full_tag("FORMAT",3,false,$course->format));
678 fwrite ($bf,full_tag("SHOWGRADES",3,false,$course->showgrades));
679 fwrite ($bf,full_tag("NEWSITEMS",3,false,$course->newsitems));
680 fwrite ($bf,full_tag("TEACHER",3,false,$course->teacher));
681 fwrite ($bf,full_tag("TEACHERS",3,false,$course->teachers));
682 fwrite ($bf,full_tag("STUDENT",3,false,$course->student));
683 fwrite ($bf,full_tag("STUDENTS",3,false,$course->students));
684 fwrite ($bf,full_tag("GUEST",3,false,$course->guest));
685 fwrite ($bf,full_tag("STARTDATE",3,false,$course->startdate));
686 fwrite ($bf,full_tag("NUMSECTIONS",3,false,$course->numsections));
687 //fwrite ($bf,full_tag("SHOWRECENT",3,false,$course->showrecent)); INFO: This is out in 1.3
688 fwrite ($bf,full_tag("MAXBYTES",3,false,$course->maxbytes));
689 fwrite ($bf,full_tag("SHOWREPORTS",3,false,$course->showreports));
690 fwrite ($bf,full_tag("GROUPMODE",3,false,$course->groupmode));
691 fwrite ($bf,full_tag("GROUPMODEFORCE",3,false,$course->groupmodeforce));
692 fwrite ($bf,full_tag("DEFAULTGROUPINGID",3,false,$course->defaultgroupingid));
693 fwrite ($bf,full_tag("LANG",3,false,$course->lang));
694 fwrite ($bf,full_tag("THEME",3,false,$course->theme));
695 fwrite ($bf,full_tag("COST",3,false,$course->cost));
696 fwrite ($bf,full_tag("CURRENCY",3,false,$course->currency));
697 fwrite ($bf,full_tag("MARKER",3,false,$course->marker));
698 fwrite ($bf,full_tag("VISIBLE",3,false,$course->visible));
699 fwrite ($bf,full_tag("HIDDENSECTIONS",3,false,$course->hiddensections));
700 fwrite ($bf,full_tag("TIMECREATED",3,false,$course->timecreated));
701 fwrite ($bf,full_tag("TIMEMODIFIED",3,false,$course->timemodified));
702 //If not selected, force metacourse to 0
703 if (!$preferences->backup_metacourse) {
704 $status = fwrite ($bf,full_tag("METACOURSE",3,false,'0'));
705 //else, export the field as is in DB
706 } else {
707 $status = fwrite ($bf,full_tag("METACOURSE",3,false,$course->metacourse));
709 fwrite ($bf,full_tag("EXPIRENOTIFY",3,false,$course->expirynotify));
710 fwrite ($bf,full_tag("NOTIFYSTUDENTS",3,false,$course->notifystudents));
711 fwrite ($bf,full_tag("EXPIRYTHRESHOLD",3,false,$course->expirythreshold));
712 fwrite ($bf,full_tag("ENROLLABLE",3,false,$course->enrollable));
713 fwrite ($bf,full_tag("ENROLSTARTDATE",3,false,$course->enrolstartdate));
714 fwrite ($bf,full_tag("ENROLENDDATE",3,false,$course->enrolenddate));
715 fwrite ($bf,full_tag("ENROLPERIOD",3,false,$course->enrolperiod));
717 /// write local course overrides here?
718 write_role_overrides_xml($bf, $context, 3);
719 /// write role_assign code here
720 write_role_assignments_xml($bf, $preferences, $context, 3);
721 //Print header end
722 fwrite ($bf,end_tag("HEADER",2,true));
723 } else {
724 $status = false;
727 return $status;
730 //Prints course's end tag
731 function backup_course_end ($bf,$preferences) {
733 //Course end tag
734 $status = fwrite ($bf,end_tag("COURSE",1,true));
736 return $status;
740 //Prints course's metacourse info (table course_meta)
741 function backup_course_metacourse ($bf,$preferences) {
743 global $CFG;
745 $status = true;
747 //Get info from meta
748 $parents = get_records_sql ("SELECT m.*, c.idnumber, c.shortname
749 FROM {$CFG->prefix}course_meta m,
750 {$CFG->prefix}course c
751 WHERE m.child_course = '$preferences->backup_course' AND
752 m.parent_course = c.id");
753 $childs = get_records_sql ("SELECT m.*, c.idnumber, c.shortname
754 FROM {$CFG->prefix}course_meta m,
755 {$CFG->prefix}course c
756 WHERE m.parent_course = '$preferences->backup_course' AND
757 m.child_course = c.id");
759 if ($parents || $childs) {
760 //metacourse open tag
761 fwrite ($bf,start_tag("METACOURSE",2,true));
762 if ($parents) {
763 fwrite($bf, start_tag("PARENTS",3,true));
764 //Iterate over every parent
765 foreach ($parents as $parent) {
766 //Begin parent
767 fwrite ($bf,start_tag("PARENT",4,true));
768 fwrite ($bf,full_tag("ID",5,false,$parent->parent_course));
769 fwrite ($bf,full_tag("IDNUMBER",5,false,$parent->idnumber));
770 fwrite ($bf,full_tag("SHORTNAME",5,false,$parent->shortname));
771 //End parent
772 fwrite ($bf,end_tag("PARENT",4,true));
774 fwrite ($bf,end_tag("PARENTS",3,true));
776 if ($childs) {
777 fwrite($bf, start_tag("CHILDS",3,true));
778 //Iterate over every child
779 foreach ($childs as $child) {
780 //Begin parent
781 fwrite ($bf,start_tag("CHILD",4,true));
782 fwrite ($bf,full_tag("ID",5,false,$child->child_course));
783 fwrite ($bf,full_tag("IDNUMBER",5,false,$child->idnumber));
784 fwrite ($bf,full_tag("SHORTNAME",5,false,$child->shortname));
785 //End parent
786 fwrite ($bf,end_tag("CHILD",4,true));
788 fwrite ($bf,end_tag("CHILDS",3,true));
790 //metacourse close tag
791 $status = fwrite ($bf,end_tag("METACOURSE",3,true));
794 return $status;
798 //Prints course's messages info (tables message, message_read and message_contacts)
799 function backup_messages ($bf,$preferences) {
801 global $CFG;
803 $status = true;
805 /// Check we have something to backup
806 $unreads = count_records ('message');
807 $reads = count_records ('message_read');
808 $contacts= count_records ('message_contacts');
810 if ($unreads || $reads || $contacts) {
811 $counter = 0;
812 /// message open tag
813 fwrite ($bf,start_tag("MESSAGES",2,true));
815 if ($unreads) {
816 $rs_unreads = get_recordset('message');
817 /// Iterate over every unread
818 while ($unread = rs_fetch_next_record($rs_unreads)) {
819 /// start message
820 fwrite($bf, start_tag("MESSAGE",3,true));
821 fwrite ($bf,full_tag("ID",4,false,$unread->id));
822 fwrite ($bf,full_tag("STATUS",4,false,"UNREAD"));
823 fwrite ($bf,full_tag("USERIDFROM",4,false,$unread->useridfrom));
824 fwrite ($bf,full_tag("USERIDTO",4,false,$unread->useridto));
825 fwrite ($bf,full_tag("MESSAGE",4,false,$unread->message));
826 fwrite ($bf,full_tag("FORMAT",4,false,$unread->format));
827 fwrite ($bf,full_tag("TIMECREATED",4,false,$unread->timecreated));
828 fwrite ($bf,full_tag("MESSAGETYPE",4,false,$unread->messagetype));
829 /// end message
830 fwrite ($bf,end_tag("MESSAGE",3,true));
832 /// Do some output
833 $counter++;
834 if ($counter % 20 == 0) {
835 echo ".";
836 if ($counter % 400 == 0) {
837 echo "<br />";
839 backup_flush(300);
842 rs_close($rs_unreads);
845 if ($reads) {
846 $rs_reads = get_recordset('message_read');
847 /// Iterate over every unread
848 while ($read = rs_fetch_next_record($rs_reads)) {
849 /// start message
850 fwrite($bf, start_tag("MESSAGE",3,true));
851 fwrite ($bf,full_tag("ID",4,false,$read->id));
852 fwrite ($bf,full_tag("STATUS",4,false,"READ"));
853 fwrite ($bf,full_tag("USERIDFROM",4,false,$read->useridfrom));
854 fwrite ($bf,full_tag("USERIDTO",4,false,$read->useridto));
855 fwrite ($bf,full_tag("MESSAGE",4,false,$read->message));
856 fwrite ($bf,full_tag("FORMAT",4,false,$read->format));
857 fwrite ($bf,full_tag("TIMECREATED",4,false,$read->timecreated));
858 fwrite ($bf,full_tag("MESSAGETYPE",4,false,$read->messagetype));
859 fwrite ($bf,full_tag("TIMEREAD",4,false,$read->timeread));
860 fwrite ($bf,full_tag("MAILED",4,false,$read->mailed));
861 /// end message
862 fwrite ($bf,end_tag("MESSAGE",3,true));
864 /// Do some output
865 $counter++;
866 if ($counter % 20 == 0) {
867 echo ".";
868 if ($counter % 400 == 0) {
869 echo "<br />";
871 backup_flush(300);
874 rs_close($rs_reads);
877 if ($contacts) {
878 fwrite($bf, start_tag("CONTACTS",3,true));
879 $rs_contacts = get_recordset('message_contacts');
880 /// Iterate over every contact
881 while ($contact = rs_fetch_next_record($rs_contacts)) {
882 /// start contact
883 fwrite($bf, start_tag("CONTACT",4,true));
884 fwrite ($bf,full_tag("ID",5,false,$contact->id));
885 fwrite ($bf,full_tag("USERID",5,false,$contact->userid));
886 fwrite ($bf,full_tag("CONTACTID",5,false,$contact->contactid));
887 fwrite ($bf,full_tag("BLOCKED",5,false,$contact->blocked));
888 /// end contact
889 fwrite ($bf,end_tag("CONTACT",4,true));
891 /// Do some output
892 $counter++;
893 if ($counter % 20 == 0) {
894 echo ".";
895 if ($counter % 400 == 0) {
896 echo "<br />";
898 backup_flush(300);
901 rs_close($rs_contacts);
902 fwrite($bf, end_tag("CONTACTS",3,true));
905 /// messages close tag
906 $status = fwrite ($bf,end_tag("MESSAGES",2,true));
909 return $status;
913 //Print blogs info (post table, module=blog, course=0)
914 function backup_blogs($bf, $preferences) {
916 global $CFG;
918 $status = true;
920 /// Check we have something to backup
921 $siteblogs = count_records('post', 'module', 'blog', 'courseid', 0);
923 if ($siteblogs) {
924 $counter = 0;
925 /// blogs open tag
926 fwrite ($bf, start_tag("BLOGS",2,true));
928 if ($siteblogs) {
929 $rs_blogs = get_recordset_sql("SELECT * from {$CFG->prefix}post
930 WHERE module = 'blog'
931 AND courseid = 0");
932 /// Iterate over every blog
933 while ($blog = rs_fetch_next_record($rs_blogs)) {
934 /// start blog
935 fwrite($bf, start_tag("BLOG",3,true));
936 /// blog body
937 fwrite ($bf,full_tag("ID",4,false,$blog->id));
938 fwrite ($bf,full_tag("MODULE",4,false,$blog->module));
939 fwrite ($bf,full_tag("USERID",4,false,$blog->userid));
940 fwrite ($bf,full_tag("COURSEID",4,false,$blog->courseid));
941 fwrite ($bf,full_tag("GROUPID",4,false,$blog->groupid));
942 fwrite ($bf,full_tag("MODULEID",4,false,$blog->moduleid));
943 fwrite ($bf,full_tag("COURSEMODULEID",4,false,$blog->coursemoduleid));
944 fwrite ($bf,full_tag("SUBJECT",4,false,$blog->subject));
945 fwrite ($bf,full_tag("SUMMARY",4,false,$blog->summary));
946 fwrite ($bf,full_tag("CONTENT",4,false,$blog->content));
947 fwrite ($bf,full_tag("UNIQUEHASH",4,false,$blog->uniquehash));
948 fwrite ($bf,full_tag("RATING",4,false,$blog->rating));
949 fwrite ($bf,full_tag("FORMAT",4,false,$blog->format));
950 fwrite ($bf,full_tag("ATTACHMENT",4,false,$blog->attachment));
951 fwrite ($bf,full_tag("PUBLISHSTATE",4,false,$blog->publishstate));
952 fwrite ($bf,full_tag("LASTMODIFIED",4,false,$blog->lastmodified));
953 fwrite ($bf,full_tag("CREATED",4,false,$blog->created));
954 fwrite ($bf,full_tag("USERMODIFIED",4,false,$blog->usermodified));
956 /// Blog tags
957 /// Check if we have blog tags to backup
958 if (!empty($CFG->usetags)) {
959 if ($tags = tag_get_tags('post', $blog->id)) { //This return them ordered by default
960 /// Start BLOG_TAGS tag
961 fwrite ($bf,start_tag("BLOG_TAGS",4,true));
962 /// Write blog tags fields
963 foreach ($tags as $tag) {
964 fwrite ($bf,start_tag("BLOG_TAG",5,true));
965 fwrite ($bf,full_tag("NAME",6,false,$tag->name));
966 fwrite ($bf,full_tag("RAWNAME",6,false,$tag->rawname));
967 fwrite ($bf,end_tag("BLOG_TAG",5,true));
969 /// End BLOG_TAGS tag
970 fwrite ($bf,end_tag("BLOG_TAGS",4,true));
974 /// Blog comments
975 /// TODO: Blog comments go here (2.0)
977 /// end blog
978 fwrite($bf, end_tag("BLOG",3,true));
980 /// Do some output
981 $counter++;
982 if ($counter % 20 == 0) {
983 echo ".";
984 if ($counter % 400 == 0) {
985 echo "<br />";
987 backup_flush(300);
990 rs_close($rs_blogs);
992 /// blogs close tag
993 $status = fwrite($bf, end_tag("BLOGS",2,true));
996 return $status;
999 //Prints course's blocks info (table block_instance)
1000 function backup_course_blocks ($bf,$preferences) {
1002 global $CFG;
1004 $status = true;
1006 // Read all of the block table
1007 $blocks = blocks_get_record();
1009 $pages = array();
1010 $pages[] = page_create_object(PAGE_COURSE_VIEW, $preferences->backup_course);
1012 if (!empty($CFG->showblocksonmodpages)) {
1013 // get course structure
1014 $course = get_record('course', 'id', $preferences->backup_course);
1015 $modinfo =& get_fast_modinfo($course);
1017 foreach($preferences->mods as $module) {
1018 if (!$module->backup) {
1019 continue;
1022 if (empty($modinfo->instances[$module->name])) {
1023 continue;
1026 $pagetypes = page_import_types('mod/'.$module->name.'/');
1027 if (empty($pagetypes)) {
1028 continue;
1031 foreach($pagetypes as $pagetype) {
1032 foreach($modinfo->instances[$module->name] as $cm) {
1033 if (!empty($module->instances[$cm->instance]->backup)) {
1034 $pages[] = page_create_object($pagetype, $cm->instance);
1041 //Blocks open tag
1042 fwrite ($bf,start_tag('BLOCKS',2,true));
1044 foreach($pages as $page) {
1045 if ($instances = blocks_get_by_page($page)) {
1046 //Iterate over every block
1047 foreach ($instances as $position) {
1048 foreach ($position as $instance) {
1050 //If we somehow have a block with an invalid id, skip it
1051 if(empty($blocks[$instance->blockid]->name)) {
1052 continue;
1054 $blockname = $blocks[$instance->blockid]->name;
1056 if (!$blockobj = block_instance($blockname, $instance)) {
1057 // Invalid block
1058 continue;
1061 // encode absolute links in block config
1062 $instance->configdata = $blockobj->get_backup_encoded_config();
1064 //Begin Block
1065 fwrite ($bf,start_tag('BLOCK',3,true));
1066 fwrite ($bf,full_tag('ID', 4, false,$instance->id));
1067 fwrite ($bf,full_tag('NAME',4,false,$blockname));
1068 fwrite ($bf,full_tag('PAGEID',4,false,$instance->pageid));
1069 fwrite ($bf,full_tag('PAGETYPE',4,false,$instance->pagetype));
1070 fwrite ($bf,full_tag('POSITION',4,false,$instance->position));
1071 fwrite ($bf,full_tag('WEIGHT',4,false,$instance->weight));
1072 fwrite ($bf,full_tag('VISIBLE',4,false,$instance->visible));
1073 fwrite ($bf,full_tag('CONFIGDATA',4,false,$instance->configdata));
1074 // Write instance data if needed
1075 if ($blockobj->backuprestore_instancedata_used()) {
1076 fwrite ($bf,start_tag('INSTANCEDATA',4,true));
1077 $status = $blockobj->instance_backup($bf, $preferences);
1078 fwrite ($bf,end_tag('INSTANCEDATA',4,true));
1080 $context = get_context_instance(CONTEXT_BLOCK, $instance->id);
1081 write_role_overrides_xml($bf, $context, 4);
1082 /// write role_assign code here
1083 write_role_assignments_xml($bf, $preferences, $context, 4);
1084 //End Block
1085 fwrite ($bf,end_tag('BLOCK',3,true));
1091 //Blocks close tag
1092 $status = fwrite ($bf,end_tag('BLOCKS',2,true));
1094 return $status;
1098 //Prints course's sections info (table course_sections)
1099 function backup_course_sections ($bf,$preferences) {
1101 global $CFG;
1103 $status = true;
1106 //Get info from sections
1107 $section=false;
1108 if ($sections = get_records("course_sections","course",$preferences->backup_course,"section")) {
1109 //Section open tag
1110 fwrite ($bf,start_tag("SECTIONS",2,true));
1111 //Iterate over every section (ordered by section)
1112 foreach ($sections as $section) {
1113 //Begin Section
1114 fwrite ($bf,start_tag("SECTION",3,true));
1115 fwrite ($bf,full_tag("ID",4,false,$section->id));
1116 fwrite ($bf,full_tag("NUMBER",4,false,$section->section));
1117 fwrite ($bf,full_tag("SUMMARY",4,false,$section->summary));
1118 fwrite ($bf,full_tag("VISIBLE",4,false,$section->visible));
1119 //Now print the mods in section
1120 backup_course_modules ($bf,$preferences,$section);
1121 //End section
1122 fwrite ($bf,end_tag("SECTION",3,true));
1124 //Section close tag
1125 $status = fwrite ($bf,end_tag("SECTIONS",2,true));
1128 return $status;
1132 //Prints course's format data (any data the format might want to save).
1133 function backup_format_data ($bf,$preferences) {
1134 global $CFG;
1136 // Check course format
1137 if(!($format=get_field('course','format','id',$preferences->backup_course))) {
1138 return false;
1140 // Write appropriate tag. Note that we always put this tag there even if
1141 // blank, it makes parsing easier
1142 fwrite ($bf,start_tag("FORMATDATA",2,true));
1144 $file=$CFG->dirroot."/course/format/$format/backuplib.php";
1145 if(file_exists($file)) {
1146 // If the file is there, the function must be or it's an error.
1147 require_once($file);
1148 $function=$format.'_backup_format_data';
1149 if(!function_exists($function)) {
1150 return false;
1152 if(!$function($bf,$preferences)) {
1153 return false;
1157 // This last return just checks the file writing has been ok (ish)
1158 return fwrite ($bf,end_tag("FORMATDATA",2,true));
1161 //Prints course's modules info (table course_modules)
1162 //Only for selected mods in preferences
1163 function backup_course_modules ($bf,$preferences,$section) {
1165 global $CFG;
1167 $status = true;
1169 $first_record = true;
1171 //Now print the mods in section
1172 //Extracts mod id from sequence
1173 $tok = strtok($section->sequence,",");
1174 while ($tok) {
1175 //Get module's type
1176 $moduletype = get_module_type ($preferences->backup_course,$tok);
1177 //Check if we've selected to backup that type
1178 if ($moduletype and $preferences->mods[$moduletype]->backup) {
1179 $selected = true;
1180 } else {
1181 $selected = false;
1184 if ($selected) {
1185 $context = get_context_instance(CONTEXT_MODULE, $tok);
1186 //Gets course_module data from db - verify activity exists and is enabled!
1187 $sql = "SELECT cm.*
1188 FROM {$CFG->prefix}course_modules cm
1189 JOIN {$CFG->prefix}modules m ON m.id = cm.module
1190 JOIN {$CFG->prefix}$moduletype a ON a.id = cm.instance
1191 WHERE m.visible = 1 AND cm.id = $tok";
1192 if (!$course_module = get_record_sql($sql)) {
1193 // cm exists but activity instance missing - probably caused by double clicking
1194 $tok = strtok(",");
1195 continue;
1198 //If it's the first, pring MODS tag
1199 if ($first_record) {
1200 fwrite ($bf,start_tag("MODS",4,true));
1201 $first_record = false;
1203 // if we're doing selected instances, check that too.
1204 if (is_array($preferences->mods[$moduletype]->instances)
1205 && count($preferences->mods[$moduletype]->instances)
1206 && (!array_key_exists($course_module->instance,$preferences->mods[$moduletype]->instances)
1207 || empty($preferences->mods[$moduletype]->instances[$course_module->instance]->backup))) {
1208 $tok = strtok(",");
1209 continue;
1212 // find all role values that has an override in this context
1213 $roles = get_records('role_capabilities', 'contextid', $context->id);
1215 //Print mod info from course_modules
1216 fwrite ($bf,start_tag("MOD",5,true));
1217 //Save neccesary info to backup_ids
1218 fwrite ($bf,full_tag("ID",6,false,$tok));
1219 fwrite ($bf,full_tag("TYPE",6,false,$moduletype));
1220 fwrite ($bf,full_tag("INSTANCE",6,false,$course_module->instance));
1221 fwrite ($bf,full_tag("ADDED",6,false,$course_module->added));
1222 fwrite ($bf,full_tag("SCORE",6,false,$course_module->score));
1223 fwrite ($bf,full_tag("INDENT",6,false,$course_module->indent));
1224 fwrite ($bf,full_tag("VISIBLE",6,false,$course_module->visible));
1225 fwrite ($bf,full_tag("GROUPMODE",6,false,$course_module->groupmode));
1226 fwrite ($bf,full_tag("GROUPINGID",6,false,$course_module->groupingid));
1227 fwrite ($bf,full_tag("GROUPMEMBERSONLY",6,false,$course_module->groupmembersonly));
1228 fwrite ($bf,full_tag("IDNUMBER",6,false,$course_module->idnumber));
1229 // get all the role_capabilities overrides in this mod
1230 write_role_overrides_xml($bf, $context, 6);
1231 /// write role_assign code here
1232 write_role_assignments_xml($bf, $preferences, $context, 6);
1233 /// write role_assign code here
1235 fwrite ($bf,end_tag("MOD",5,true));
1237 //check for next
1238 $tok = strtok(",");
1241 //Si ha habido modulos, final de MODS
1242 if (!$first_record) {
1243 $status =fwrite ($bf,end_tag("MODS",4,true));
1246 return $status;
1249 //Print users to xml
1250 //Only users previously calculated in backup_ids will output
1252 function backup_user_info ($bf,$preferences) {
1254 global $CFG;
1255 require_once ($CFG->dirroot.'/tag/lib.php');
1257 $status = true;
1259 // Use a recordset to for the memory handling on to
1260 // the DB and run faster
1261 // Note the outer join with mnet_host: It shouldn't be neccesary
1262 // but there are some sites having mnet_host records missing
1263 // and that causes backup to fail (no users). Being a bit more
1264 // flexible here (outer joing) we bypass the problem and doesn't
1265 // cause more troubles. Eloy - MDL-16879
1266 $users = get_recordset_sql("SELECT b.old_id, b.table_name, b.info,
1267 u.*, m.wwwroot
1268 FROM {$CFG->prefix}backup_ids b
1269 JOIN {$CFG->prefix}user u ON b.old_id=u.id
1270 LEFT JOIN {$CFG->prefix}mnet_host m ON u.mnethostid=m.id
1271 WHERE b.backup_code = '$preferences->backup_unique_code' AND
1272 b.table_name = 'user'");
1274 //If we have users to backup
1275 if ($users && !rs_EOF($users)) {
1276 //Begin Users tag
1277 fwrite ($bf,start_tag("USERS",2,true));
1278 $counter = 0;
1279 //With every user
1280 while ($user = rs_fetch_next_record($users)) {
1281 //Begin User tag
1282 fwrite ($bf,start_tag("USER",3,true));
1283 //Output all user data
1284 fwrite ($bf,full_tag("ID",4,false,$user->id));
1285 fwrite ($bf,full_tag("AUTH",4,false,$user->auth));
1286 fwrite ($bf,full_tag("CONFIRMED",4,false,$user->confirmed));
1287 fwrite ($bf,full_tag("POLICYAGREED",4,false,$user->policyagreed));
1288 fwrite ($bf,full_tag("DELETED",4,false,$user->deleted));
1289 fwrite ($bf,full_tag("USERNAME",4,false,$user->username));
1290 // Prevent user passwords in backup files unless
1291 // $CFG->includeuserpasswordsinbackup is defined. MDL-20838
1292 if (!empty($CFG->includeuserpasswordsinbackup)) {
1293 fwrite ($bf,full_tag("PASSWORD",4,false,$user->password));
1295 fwrite ($bf,full_tag("IDNUMBER",4,false,$user->idnumber));
1296 fwrite ($bf,full_tag("FIRSTNAME",4,false,$user->firstname));
1297 fwrite ($bf,full_tag("LASTNAME",4,false,$user->lastname));
1298 fwrite ($bf,full_tag("EMAIL",4,false,$user->email));
1299 fwrite ($bf,full_tag("EMAILSTOP",4,false,$user->emailstop));
1300 fwrite ($bf,full_tag("ICQ",4,false,$user->icq));
1301 fwrite ($bf,full_tag("SKYPE",4,false,$user->skype));
1302 fwrite ($bf,full_tag("YAHOO",4,false,$user->yahoo));
1303 fwrite ($bf,full_tag("AIM",4,false,$user->aim));
1304 fwrite ($bf,full_tag("MSN",4,false,$user->msn));
1305 fwrite ($bf,full_tag("PHONE1",4,false,$user->phone1));
1306 fwrite ($bf,full_tag("PHONE2",4,false,$user->phone2));
1307 fwrite ($bf,full_tag("INSTITUTION",4,false,$user->institution));
1308 fwrite ($bf,full_tag("DEPARTMENT",4,false,$user->department));
1309 fwrite ($bf,full_tag("ADDRESS",4,false,$user->address));
1310 fwrite ($bf,full_tag("CITY",4,false,$user->city));
1311 fwrite ($bf,full_tag("COUNTRY",4,false,$user->country));
1312 fwrite ($bf,full_tag("LANG",4,false,$user->lang));
1313 fwrite ($bf,full_tag("THEME",4,false,$user->theme));
1314 fwrite ($bf,full_tag("TIMEZONE",4,false,$user->timezone));
1315 fwrite ($bf,full_tag("FIRSTACCESS",4,false,$user->firstaccess));
1316 fwrite ($bf,full_tag("LASTACCESS",4,false,$user->lastaccess));
1317 fwrite ($bf,full_tag("LASTLOGIN",4,false,$user->lastlogin));
1318 fwrite ($bf,full_tag("CURRENTLOGIN",4,false,$user->currentlogin));
1319 fwrite ($bf,full_tag("LASTIP",4,false,$user->lastip));
1320 fwrite ($bf,full_tag("PICTURE",4,false,$user->picture));
1321 fwrite ($bf,full_tag("URL",4,false,$user->url));
1322 fwrite ($bf,full_tag("DESCRIPTION",4,false,$user->description));
1323 fwrite ($bf,full_tag("MAILFORMAT",4,false,$user->mailformat));
1324 fwrite ($bf,full_tag("MAILDIGEST",4,false,$user->maildigest));
1325 fwrite ($bf,full_tag("MAILDISPLAY",4,false,$user->maildisplay));
1326 fwrite ($bf,full_tag("HTMLEDITOR",4,false,$user->htmleditor));
1327 fwrite ($bf,full_tag("AJAX",4,false,$user->ajax));
1328 fwrite ($bf,full_tag("AUTOSUBSCRIBE",4,false,$user->autosubscribe));
1329 fwrite ($bf,full_tag("TRACKFORUMS",4,false,$user->trackforums));
1330 if ($user->mnethostid != $CFG->mnet_localhost_id && !empty($user->wwwroot)) {
1331 fwrite ($bf,full_tag("MNETHOSTURL",4,false,$user->wwwroot));
1333 fwrite ($bf,full_tag("TIMEMODIFIED",4,false,$user->timemodified));
1335 /// write assign/override code for context_userid
1337 $user->isneeded = strpos($user->info,"needed");
1339 fwrite ($bf,start_tag("ROLES",4,true));
1340 if ($user->info != "needed" && $user->info!="") {
1341 //PRINT ROLE INFO
1342 $roles = explode(",", $user->info);
1343 foreach ($roles as $role) {
1344 if ($role!="" && $role!="needed") {
1345 fwrite ($bf,start_tag("ROLE",5,true));
1346 //Print Role info
1347 fwrite ($bf,full_tag("TYPE",6,false,$role));
1348 //Print ROLE end
1349 fwrite ($bf,end_tag("ROLE",5,true));
1353 //Needed
1354 if ($user->isneeded!==false) {
1355 //Print ROLE start
1356 fwrite ($bf,start_tag("ROLE",5,true));
1357 //Print Role info
1358 fwrite ($bf,full_tag("TYPE",6,false,"needed"));
1359 //Print ROLE end
1360 fwrite ($bf,end_tag("ROLE",5,true));
1363 //End ROLES tag
1364 fwrite ($bf,end_tag("ROLES",4,true));
1366 //Check if we have custom profile fields to backup
1367 if ($cpfields = get_records_sql("SELECT uif.shortname, uif.datatype, uidata.data
1368 FROM {$CFG->prefix}user_info_field uif,
1369 {$CFG->prefix}user_info_data uidata
1370 WHERE uif.id = uidata.fieldid
1371 AND uidata.userid = $user->id")) {
1372 //Start USER_CUSTOM_PROFILE_FIELDS tag
1373 fwrite ($bf,start_tag("USER_CUSTOM_PROFILE_FIELDS",4,true));
1374 //Write custom profile fields
1375 foreach ($cpfields as $cpfield) {
1376 fwrite ($bf,start_tag("USER_CUSTOM_PROFILE_FIELD",5,true));
1377 fwrite ($bf,full_tag("FIELD_NAME",6,false,$cpfield->shortname));
1378 fwrite ($bf,full_tag("FIELD_TYPE",6,false,$cpfield->datatype));
1379 fwrite ($bf,full_tag("FIELD_DATA",6,false,$cpfield->data));
1380 fwrite ($bf,end_tag("USER_CUSTOM_PROFILE_FIELD",5,true));
1382 //End USER_CUSTOM_PROFILE_FIELDS tag
1383 fwrite ($bf,end_tag("USER_CUSTOM_PROFILE_FIELDS",4,true));
1386 //Check if we have user tags to backup
1387 if (!empty($CFG->usetags)) {
1388 if ($tags = tag_get_tags('user', $user->id)) { //This return them ordered by default
1389 //Start USER_TAGS tag
1390 fwrite ($bf,start_tag("USER_TAGS",4,true));
1391 //Write user tags fields
1392 foreach ($tags as $tag) {
1393 fwrite ($bf,start_tag("USER_TAG",5,true));
1394 fwrite ($bf,full_tag("NAME",6,false,$tag->name));
1395 fwrite ($bf,full_tag("RAWNAME",6,false,$tag->rawname));
1396 fwrite ($bf,end_tag("USER_TAG",5,true));
1398 //End USER_TAGS tag
1399 fwrite ($bf,end_tag("USER_TAGS",4,true));
1403 //Check if we have user_preferences to backup
1404 if ($preferences_data = get_records("user_preferences","userid",$user->old_id)) {
1405 //Start USER_PREFERENCES tag
1406 fwrite ($bf,start_tag("USER_PREFERENCES",4,true));
1407 //Write each user_preference
1408 foreach ($preferences_data as $user_preference) {
1409 fwrite ($bf,start_tag("USER_PREFERENCE",5,true));
1410 fwrite ($bf,full_tag("NAME",6,false,$user_preference->name));
1411 fwrite ($bf,full_tag("VALUE",6,false,$user_preference->value));
1412 fwrite ($bf,end_tag("USER_PREFERENCE",5,true));
1414 //End USER_PREFERENCES tag
1415 fwrite ($bf,end_tag("USER_PREFERENCES",4,true));
1418 $context = get_context_instance(CONTEXT_USER, $user->old_id);
1420 write_role_overrides_xml($bf, $context, 4);
1421 /// write role_assign code here
1422 write_role_assignments_xml($bf, $preferences, $context, 4);
1423 //End User tag
1424 fwrite ($bf,end_tag("USER",3,true));
1425 //Do some output
1426 $counter++;
1427 if ($counter % 10 == 0) {
1428 echo ".";
1429 if ($counter % 200 == 0) {
1430 echo "<br />";
1432 backup_flush(300);
1435 //End Users tag
1436 fwrite ($bf,end_tag("USERS",2,true));
1437 } else {
1438 // There aren't any users.
1439 $status = true;
1442 if ($users) {
1443 rs_close($users);
1446 return $status;
1449 //Backup log info (time ordered)
1450 function backup_log_info($bf,$preferences) {
1452 global $CFG;
1454 //Number of records to get in every chunk
1455 $recordset_size = 1000;
1457 $status = true;
1459 //Counter, points to current record
1460 $counter = 0;
1462 //Count records
1463 $count_logs = count_records("log","course",$preferences->backup_course);
1465 //Pring logs header
1466 if ($count_logs > 0 ) {
1467 fwrite ($bf,start_tag("LOGS",2,true));
1469 while ($counter < $count_logs) {
1470 //Get a chunk of records
1471 $logs = get_records ("log","course",$preferences->backup_course,"time","*",$counter,$recordset_size);
1473 //We have logs
1474 if ($logs) {
1475 //Iterate
1476 foreach ($logs as $log) {
1477 //See if it is a valid module to backup
1478 if ($log->module == "course" or
1479 $log->module == "user" or
1480 (array_key_exists($log->module, $preferences->mods) and $preferences->mods[$log->module]->backup == 1)) {
1481 // logs with 'upload' in module field are ignored, there is no restore code anyway
1482 //Begin log tag
1483 fwrite ($bf,start_tag("LOG",3,true));
1485 //Output log tag
1486 fwrite ($bf,full_tag("ID",4,false,$log->id));
1487 fwrite ($bf,full_tag("TIME",4,false,$log->time));
1488 fwrite ($bf,full_tag("USERID",4,false,$log->userid));
1489 fwrite ($bf,full_tag("IP",4,false,$log->ip));
1490 fwrite ($bf,full_tag("MODULE",4,false,$log->module));
1491 fwrite ($bf,full_tag("CMID",4,false,$log->cmid));
1492 fwrite ($bf,full_tag("ACTION",4,false,$log->action));
1493 fwrite ($bf,full_tag("URL",4,false,$log->url));
1494 fwrite ($bf,full_tag("INFO",4,false,$log->info));
1496 //End log tag
1497 fwrite ($bf,end_tag("LOG",3,true));
1499 //Do some output
1500 $counter++;
1501 if ($counter % 20 == 0) {
1502 echo ".";
1503 if ($counter % 400 == 0) {
1504 echo "<br />";
1506 backup_flush(300);
1511 //End logs tag
1512 if ($count_logs > 0 ) {
1513 $status = fwrite ($bf,end_tag("LOGS",2,true));
1515 return $status;
1518 //Backup gradebook info
1519 function backup_gradebook_info($bf, $preferences) {
1520 global $CFG;
1521 require_once($CFG->libdir.'/gradelib.php');
1523 //first make sure items are properly sorted and everything is ok
1524 grade_category::fetch_course_tree($preferences->backup_course, true);
1525 grade_regrade_final_grades($preferences->backup_course);
1527 $status = true;
1529 // see if ALL grade items of type mod of this course are being backed up
1530 // if not, we do not need to backup grade category and associated grade items/grades
1531 $backupall = true;
1533 if ($grade_items = get_records_sql("SELECT *
1534 FROM {$CFG->prefix}grade_items
1535 WHERE courseid = $preferences->backup_course
1536 AND itemtype = 'mod'")) {
1537 foreach ($grade_items as $grade_item) {
1538 // get module information
1539 // if some activities not selected, we do not backup categories at all
1540 if (!backup_mod_selected($preferences,$grade_item->itemmodule,$grade_item->iteminstance)) {
1541 $backupall = false;
1542 break;
1545 unset($grade_items); //free memory
1548 //Gradebook header
1549 fwrite ($bf,start_tag("GRADEBOOK",2,true));
1551 $status = backup_gradebook_outcomes_info($bf, $preferences);
1552 $status = backup_gradebook_grade_letters_info($bf,$preferences);
1554 // Now backup grade_item (inside grade_category)
1555 if ($backupall) {
1556 $status = backup_gradebook_category_info($bf,$preferences);
1559 $status = backup_gradebook_item_info($bf,$preferences, $backupall);
1561 // backup gradebook histories (only if grade history is enabled and selected)
1562 if (empty($CFG->disablegradehistory) && $preferences->backup_gradebook_history) {
1563 $status = backup_gradebook_outcomes_history($bf, $preferences);
1564 $status = backup_gradebook_categories_history_info($bf, $preferences);
1565 $status = backup_gradebook_items_history_info($bf, $preferences);
1566 $status = backup_gradebook_grades_history_info($bf, $preferences);
1569 //Gradebook footer
1570 $status = fwrite ($bf,end_tag("GRADEBOOK",2,true));
1571 return $status;
1574 function backup_gradebook_category_info($bf, $preferences) {
1575 global $CFG;
1576 $status = true;
1578 // get grade categories in proper order - specified in category grade items
1579 $course_item = grade_item::fetch_course_item($preferences->backup_course);
1580 $grade_categories = get_records_sql("SELECT gc.*, gi.sortorder
1581 FROM {$CFG->prefix}grade_categories gc
1582 JOIN {$CFG->prefix}grade_items gi
1583 ON (gi.iteminstance = gc.id)
1584 WHERE gc.courseid = $preferences->backup_course
1585 AND (gi.itemtype='course' OR gi.itemtype='category')
1586 ORDER BY gi.sortorder ASC");
1588 if ($grade_categories) {
1589 //Begin grade_categories tag
1590 fwrite ($bf,start_tag("GRADE_CATEGORIES",3,true));
1591 //Iterate for each category
1592 foreach ($grade_categories as $grade_category) {
1593 //Begin grade_category
1594 fwrite ($bf,start_tag("GRADE_CATEGORY",4,true));
1595 //Output individual fields
1596 fwrite ($bf,full_tag("ID",5,false,$grade_category->id));
1598 // not keeping path and depth because they can be derived
1599 fwrite ($bf,full_tag("PARENT",5,false,$grade_category->parent));
1600 fwrite ($bf,full_tag("FULLNAME",5,false,$grade_category->fullname));
1601 fwrite ($bf,full_tag("AGGREGATION",5,false,$grade_category->aggregation));
1602 fwrite ($bf,full_tag("KEEPHIGH",5,false,$grade_category->keephigh));
1603 fwrite ($bf,full_tag("DROPLOW",5,false,$grade_category->droplow));
1604 fwrite ($bf,full_tag("AGGREGATEONLYGRADED",5,false,$grade_category->aggregateonlygraded));
1605 fwrite ($bf,full_tag("AGGREGATEOUTCOMES",5,false,$grade_category->aggregateoutcomes));
1606 fwrite ($bf,full_tag("AGGREGATESUBCATS",5,false,$grade_category->aggregatesubcats));
1607 fwrite ($bf,full_tag("TIMECREATED",5,false,$grade_category->timecreated));
1608 fwrite ($bf,full_tag("TIMEMODIFIED",5,false,$grade_category->timemodified));
1610 //End grade_category
1611 fwrite ($bf,end_tag("GRADE_CATEGORY",4,true));
1613 //End grade_categories tag
1614 $status = fwrite ($bf,end_tag("GRADE_CATEGORIES",3,true));
1617 return $status;
1620 //Backup gradebook_item (called from backup_gradebook_info
1621 function backup_gradebook_item_info($bf, $preferences, $backupall) {
1622 global $CFG;
1624 $status = true;
1625 // get all the grade_items, ordered by sort order since upon restoring, it is not always
1626 // possible to use the same sort order. We could at least preserve the sortorder by restoring
1627 // grade_items in the original sortorder
1628 if ($grade_items = get_records_sql("SELECT *
1629 FROM {$CFG->prefix}grade_items
1630 WHERE courseid = $preferences->backup_course
1631 ORDER BY sortorder ASC")) {
1633 //Begin grade_items tag
1634 fwrite ($bf,start_tag("GRADE_ITEMS",3,true));
1635 //Iterate over each item
1636 foreach ($grade_items as $item) {
1637 // Instantiate a grade_item object, to access its methods
1638 $grade_item = new grade_item($item, false);
1640 // do not restore if this grade_item is a mod, and
1641 if ($grade_item->itemtype == 'mod') {
1642 //MDL-12463 - exclude grade_items of instances not chosen for backup
1643 if (empty($preferences->mods[$grade_item->itemmodule]->instances[$grade_item->iteminstance]->backup)) {
1644 continue;
1647 } else if ($grade_item->itemtype == 'category') {
1648 // if not all grade items are being backed up
1649 // we ignore this type of grade_item and grades associated
1650 if (!$backupall) {
1651 continue;
1655 //Begin grade_item
1656 fwrite ($bf,start_tag("GRADE_ITEM",4,true));
1657 //Output individual fields
1659 fwrite ($bf,full_tag("ID",5,false,$grade_item->id));
1660 fwrite ($bf,full_tag("CATEGORYID",5,false,$grade_item->categoryid));
1661 fwrite ($bf,full_tag("ITEMNAME",5,false,$grade_item->itemname));
1662 fwrite ($bf,full_tag("ITEMTYPE",5,false,$grade_item->itemtype));
1663 fwrite ($bf,full_tag("ITEMMODULE",5,false,$grade_item->itemmodule));
1664 fwrite ($bf,full_tag("ITEMINSTANCE",5,false,$grade_item->iteminstance));
1665 fwrite ($bf,full_tag("ITEMNUMBER",5,false,$grade_item->itemnumber));
1666 fwrite ($bf,full_tag("ITEMINFO",5,false,$grade_item->iteminfo));
1667 fwrite ($bf,full_tag("IDNUMBER",5,false,$grade_item->idnumber));
1668 // use [idnumber] in calculation instead of [#giXXX#]
1669 fwrite ($bf,full_tag("CALCULATION",5,false,$grade_item->get_calculation()));
1670 fwrite ($bf,full_tag("GRADETYPE",5,false,$grade_item->gradetype));
1671 fwrite ($bf,full_tag("GRADEMAX",5,false,$grade_item->grademax));
1672 fwrite ($bf,full_tag("GRADEMIN",5,false,$grade_item->grademin));
1673 fwrite ($bf,full_tag("SCALEID",5,false,$grade_item->scaleid));
1674 fwrite ($bf,full_tag("OUTCOMEID",5,false,$grade_item->outcomeid));
1675 fwrite ($bf,full_tag("GRADEPASS",5,false,$grade_item->gradepass));
1676 fwrite ($bf,full_tag("MULTFACTOR",5,false,$grade_item->multfactor));
1677 fwrite ($bf,full_tag("PLUSFACTOR",5,false,$grade_item->plusfactor));
1678 fwrite ($bf,full_tag("AGGREGATIONCOEF",5,false,$grade_item->aggregationcoef));
1679 fwrite ($bf,full_tag("DISPLAY",5,false,$grade_item->display));
1680 fwrite ($bf,full_tag("DECIMALS",5,false,$grade_item->decimals));
1681 fwrite ($bf,full_tag("HIDDEN",5,false,$grade_item->hidden));
1682 fwrite ($bf,full_tag("LOCKED",5,false,$grade_item->locked));
1683 fwrite ($bf,full_tag("LOCKTIME",5,false,$grade_item->locktime));
1684 fwrite ($bf,full_tag("NEEDSUPDATE",5,false,$grade_item->needsupdate));
1685 fwrite ($bf,full_tag("TIMECREATED",5,false,$grade_item->timecreated));
1686 fwrite ($bf,full_tag("TIMEMODIFIED",5,false,$grade_item->timemodified));
1688 // back up the other stuff here
1689 // mod grades should only be backed up if selected
1690 if ($grade_item->itemtype == 'mod' && !backup_userdata_selected($preferences,$grade_item->itemmodule,$grade_item->iteminstance)) {
1691 // do not write grades if a mod grade_item is being restored
1692 // but userdata is not selected
1693 } else {
1694 $status = backup_gradebook_grades_info($bf,$preferences,$grade_item->id);
1696 //End grade_item
1697 fwrite ($bf,end_tag("GRADE_ITEM",4,true));
1699 //End grade_items tag
1700 $status = fwrite ($bf,end_tag("GRADE_ITEMS",3,true));
1703 return $status;
1705 //Backup gradebook_item (called from backup_gradebook_info
1707 function backup_gradebook_grade_letters_info($bf, $preferences) {
1708 global $CFG;
1709 $status = true;
1711 $context = get_context_instance(CONTEXT_COURSE, $preferences->backup_course);
1712 $grade_letters = get_records_sql("SELECT *
1713 FROM {$CFG->prefix}grade_letters
1714 WHERE contextid = $context->id");
1715 if ($grade_letters) {
1716 //Begin grade_l tag
1717 fwrite ($bf,start_tag("GRADE_LETTERS",3,true));
1718 //Iterate for each letter
1719 foreach ($grade_letters as $grade_letter) {
1720 //Begin grade_letter
1721 fwrite ($bf,start_tag("GRADE_LETTER",4,true));
1722 //Output individual fields
1723 fwrite ($bf,full_tag("ID",5,false,$grade_letter->id));
1724 fwrite ($bf,full_tag("LOWERBOUNDARY",5,false,$grade_letter->lowerboundary));
1725 fwrite ($bf,full_tag("LETTER",5,false,$grade_letter->letter));
1727 //End grade_letter
1728 fwrite ($bf,end_tag("GRADE_LETTER",4,true));
1730 //End grade_categories tag
1731 $status = fwrite ($bf,end_tag("GRADE_LETTERS",3,true));
1734 return $status;
1737 function backup_gradebook_outcomes_info($bf, $preferences) {
1739 global $CFG;
1740 $status = true;
1741 // only back up courses already in the grade_outcomes_courses table
1742 $grade_outcomes = get_records_sql("SELECT go.*
1743 FROM {$CFG->prefix}grade_outcomes go
1744 JOIN {$CFG->prefix}grade_outcomes_courses goc
1745 ON (goc.outcomeid = go.id)
1746 WHERE goc.courseid = $preferences->backup_course");
1748 if (!empty($grade_outcomes)) {
1749 //Begin grade_outcomes tag
1750 fwrite ($bf,start_tag("GRADE_OUTCOMES",3,true));
1751 //Iterate for each outcome
1752 foreach ($grade_outcomes as $grade_outcome) {
1753 //Begin grade_outcome
1754 fwrite ($bf,start_tag("GRADE_OUTCOME",4,true));
1755 //Output individual fields
1757 fwrite ($bf,full_tag("ID",5,false,$grade_outcome->id));
1758 fwrite ($bf,full_tag("COURSEID",5,false,$grade_outcome->courseid));
1759 fwrite ($bf,full_tag("SHORTNAME",5,false,$grade_outcome->shortname));
1760 fwrite ($bf,full_tag("FULLNAME",5,false,$grade_outcome->fullname));
1761 fwrite ($bf,full_tag("SCALEID",5,false,$grade_outcome->scaleid));
1762 fwrite ($bf,full_tag("DESCRIPTION",5,false,$grade_outcome->description));
1763 fwrite ($bf,full_tag("TIMECREATED",5,false,$grade_outcome->timecreated));
1764 fwrite ($bf,full_tag("TIMEMODIFIED",5,false,$grade_outcome->timemodified));
1765 fwrite ($bf,full_tag("USERMODIFIED",5,false,$grade_outcome->usermodified));
1767 //End grade_outcome
1768 fwrite ($bf,end_tag("GRADE_OUTCOME",4,true));
1770 //End grade_outcomes tag
1771 $status = fwrite ($bf,end_tag("GRADE_OUTCOMES",3,true));
1773 return $status;
1776 function backup_gradebook_grades_info($bf,$preferences, $itemid) {
1778 global $CFG;
1780 $status = true;
1782 // find all grades belonging to this item
1783 if ($grades = get_records('grade_grades', 'itemid', $itemid)) {
1784 fwrite ($bf,start_tag("GRADE_GRADES",5,true));
1785 foreach ($grades as $grade) {
1786 /// Grades are only sent to backup if the user is one target user
1787 if (backup_getid($preferences->backup_unique_code, 'user', $grade->userid)) {
1788 fwrite ($bf,start_tag("GRADE",6,true));
1789 fwrite ($bf,full_tag("ID",7,false,$grade->id));
1790 fwrite ($bf,full_tag("USERID",7,false,$grade->userid));
1791 fwrite ($bf,full_tag("RAWGRADE",7,false,$grade->rawgrade));
1792 fwrite ($bf,full_tag("RAWGRADEMAX",7,false,$grade->rawgrademax));
1793 fwrite ($bf,full_tag("RAWGRADEMIN",7,false,$grade->rawgrademin));
1794 fwrite ($bf,full_tag("RAWSCALEID",7,false,$grade->rawscaleid));
1795 fwrite ($bf,full_tag("USERMODIFIED",7,false,$grade->usermodified));
1796 fwrite ($bf,full_tag("FINALGRADE",7,false,$grade->finalgrade));
1797 fwrite ($bf,full_tag("HIDDEN",7,false,$grade->hidden));
1798 fwrite ($bf,full_tag("LOCKED",7,false,$grade->locked));
1799 fwrite ($bf,full_tag("LOCKTIME",7,false,$grade->locktime));
1800 fwrite ($bf,full_tag("EXPORTED",7,false,$grade->exported));
1801 fwrite ($bf,full_tag("OVERRIDDEN",7,false,$grade->overridden));
1802 fwrite ($bf,full_tag("EXCLUDED",7,false,$grade->excluded));
1803 fwrite ($bf,full_tag("FEEDBACK",7,false,$grade->feedback));
1804 fwrite ($bf,full_tag("FEEDBACKFORMAT",7,false,$grade->feedbackformat));
1805 fwrite ($bf,full_tag("INFORMATION",7,false,$grade->information));
1806 fwrite ($bf,full_tag("INFORMATIONFORMAT",7,false,$grade->informationformat));
1807 fwrite ($bf,full_tag("TIMECREATED",7,false,$grade->timecreated));
1808 fwrite ($bf,full_tag("TIMEMODIFIED",7,false,$grade->timemodified));
1809 fwrite ($bf,end_tag("GRADE",6,true));
1812 $status = fwrite ($bf,end_tag("GRADE_GRADES",5,true));
1814 return $status;
1817 function backup_gradebook_categories_history_info($bf, $preferences) {
1819 global $CFG;
1820 $status = true;
1822 // find all grade categories history
1823 if ($chs = get_records('grade_categories_history', 'courseid', $preferences->backup_course)) {
1824 fwrite ($bf,start_tag("GRADE_CATEGORIES_HISTORIES",3,true));
1825 foreach ($chs as $ch) {
1826 fwrite ($bf,start_tag("GRADE_CATEGORIES_HISTORY",4,true));
1827 fwrite ($bf,full_tag("ID",5,false,$ch->id));
1828 fwrite ($bf,full_tag("ACTION",5,false,$ch->action));
1829 fwrite ($bf,full_tag("OLDID",5,false,$ch->oldid));
1830 fwrite ($bf,full_tag("SOURCE",5,false,$ch->source));
1831 fwrite ($bf,full_tag("TIMEMODIFIED",5,false,$ch->timemodified));
1832 fwrite ($bf,full_tag("LOGGEDUSER",5,false,$ch->loggeduser));
1833 fwrite ($bf,full_tag("PARENT",5,false,$ch->parent));
1834 fwrite ($bf,full_tag("DEPTH",5,false,$ch->depth));
1835 fwrite ($bf,full_tag("PATH",5,false,$ch->path));
1836 fwrite ($bf,full_tag("FULLNAME",5,false,$ch->fullname));
1837 fwrite ($bf,full_tag("AGGRETGATION",5,false,$ch->aggregation));
1838 fwrite ($bf,full_tag("KEEPHIGH",5,false,$ch->keephigh));
1839 fwrite ($bf,full_tag("DROPLOW",5,false,$ch->droplow));
1840 fwrite ($bf,full_tag("AGGREGATEONLYGRADED",5,false,$ch->aggregateonlygraded));
1841 fwrite ($bf,full_tag("AGGREGATEOUTCOMES",5,false,$ch->aggregateoutcomes));
1842 fwrite ($bf,full_tag("AGGREGATESUBCATS",5,false,$ch->aggregatesubcats));
1843 fwrite ($bf,end_tag("GRADE_CATEGORIES_HISTORY",4,true));
1845 $status = fwrite ($bf,end_tag("GRADE_CATEGORIES_HISTORIES",3,true));
1847 return $status;
1850 function backup_gradebook_grades_history_info($bf, $preferences) {
1852 global $CFG;
1853 $status = true;
1855 // find all grade categories history
1856 if ($chs = get_records_sql("SELECT ggh.*
1857 FROM {$CFG->prefix}grade_grades_history ggh
1858 JOIN {$CFG->prefix}grade_items gi
1859 ON gi.id = ggh.itemid
1860 WHERE gi.courseid = $preferences->backup_course")) {
1861 fwrite ($bf,start_tag("GRADE_GRADES_HISTORIES",3,true));
1862 foreach ($chs as $ch) {
1863 /// Grades are only sent to backup if the user is one target user
1864 if (backup_getid($preferences->backup_unique_code, 'user', $ch->userid)) {
1865 fwrite ($bf,start_tag("GRADE_GRADES_HISTORY",4,true));
1866 fwrite ($bf,full_tag("ID",5,false,$ch->id));
1867 fwrite ($bf,full_tag("ACTION",5,false,$ch->action));
1868 fwrite ($bf,full_tag("OLDID",5,false,$ch->oldid));
1869 fwrite ($bf,full_tag("SOURCE",5,false,$ch->source));
1870 fwrite ($bf,full_tag("TIMEMODIFIED",5,false,$ch->timemodified));
1871 fwrite ($bf,full_tag("LOGGEDUSER",5,false,$ch->loggeduser));
1872 fwrite ($bf,full_tag("ITEMID",5,false,$ch->itemid));
1873 fwrite ($bf,full_tag("USERID",5,false,$ch->userid));
1874 fwrite ($bf,full_tag("RAWGRADE",5,false,$ch->rawgrade));
1875 fwrite ($bf,full_tag("RAWGRADEMAX",5,false,$ch->rawgrademax));
1876 fwrite ($bf,full_tag("RAWGRADEMIN",5,false,$ch->rawgrademin));
1877 fwrite ($bf,full_tag("RAWSCALEID",5,false,$ch->rawscaleid));
1878 fwrite ($bf,full_tag("USERMODIFIED",5,false,$ch->usermodified));
1879 fwrite ($bf,full_tag("FINALGRADE",5,false,$ch->finalgrade));
1880 fwrite ($bf,full_tag("HIDDEN",5,false,$ch->hidden));
1881 fwrite ($bf,full_tag("LOCKED",5,false,$ch->locked));
1882 fwrite ($bf,full_tag("LOCKTIME",5,false,$ch->locktime));
1883 fwrite ($bf,full_tag("EXPORTED",5,false,$ch->exported));
1884 fwrite ($bf,full_tag("OVERRIDDEN",5,false,$ch->overridden));
1885 fwrite ($bf,full_tag("EXCLUDED",5,false,$ch->excluded));
1886 fwrite ($bf,full_tag("FEEDBACK",5,false,$ch->feedback));
1887 fwrite ($bf,full_tag("FEEDBACKFORMAT",5,false,$ch->feedbackformat));
1888 fwrite ($bf,full_tag("INFORMATION",5,false,$ch->information));
1889 fwrite ($bf,full_tag("INFORMATIONFORMAT",5,false,$ch->informationformat));
1890 fwrite ($bf,end_tag("GRADE_GRADES_HISTORY",4,true));
1893 $status = fwrite ($bf,end_tag("GRADE_GRADES_HISTORIES",3,true));
1895 return $status;
1898 function backup_gradebook_items_history_info($bf, $preferences) {
1900 global $CFG;
1901 $status = true;
1903 // find all grade categories history
1904 if ($chs = get_records('grade_items_history','courseid', $preferences->backup_course)) {
1905 fwrite ($bf,start_tag("GRADE_ITEM_HISTORIES",3,true));
1906 foreach ($chs as $ch) {
1907 fwrite ($bf,start_tag("GRADE_ITEM_HISTORY",4,true));
1908 fwrite ($bf,full_tag("ID",5,false,$ch->id));
1909 fwrite ($bf,full_tag("ACTION",5,false,$ch->action));
1910 fwrite ($bf,full_tag("OLDID",5,false,$ch->oldid));
1911 fwrite ($bf,full_tag("SOURCE",5,false,$ch->source));
1912 fwrite ($bf,full_tag("TIMEMODIFIED",5,false,$ch->timemodified));
1913 fwrite ($bf,full_tag("LOGGEDUSER",5,false,$ch->loggeduser));
1914 fwrite ($bf,full_tag("CATEGORYID",5,false,$ch->categoryid));
1915 fwrite ($bf,full_tag("ITEMNAME",5,false,$ch->itemname));
1916 fwrite ($bf,full_tag("ITEMTYPE",5,false,$ch->itemtype));
1917 fwrite ($bf,full_tag("ITEMMODULE",5,false,$ch->itemmodule));
1918 fwrite ($bf,full_tag("ITEMINSTANCE",5,false,$ch->iteminstance));
1919 fwrite ($bf,full_tag("ITEMNUMBER",5,false,$ch->itemnumber));
1920 fwrite ($bf,full_tag("ITEMINFO",5,false,$ch->iteminfo));
1921 fwrite ($bf,full_tag("IDNUMBER",5,false,$ch->idnumber));
1922 fwrite ($bf,full_tag("CALCULATION",5,false,$ch->calculation));
1923 fwrite ($bf,full_tag("GRADETYPE",5,false,$ch->gradetype));
1924 fwrite ($bf,full_tag("GRADEMAX",5,false,$ch->grademax));
1925 fwrite ($bf,full_tag("GRADEMIN",5,false,$ch->grademin));
1926 fwrite ($bf,full_tag("SCALEID",5,false,$ch->scaleid));
1927 fwrite ($bf,full_tag("OUTCOMEID",5,false,$ch->outcomeid));
1928 fwrite ($bf,full_tag("GRADEPASS",5,false,$ch->gradepass));
1929 fwrite ($bf,full_tag("MULTFACTOR",5,false,$ch->multfactor));
1930 fwrite ($bf,full_tag("PLUSFACTOR",5,false,$ch->plusfactor));
1931 fwrite ($bf,full_tag("AGGREGATIONCOEF",5,false,$ch->aggregationcoef));
1932 fwrite ($bf,full_tag("SORTORDER",5,false,$ch->sortorder));
1933 //fwrite ($bf,full_tag("DISPLAY",7,false,$ch->display));
1934 //fwrite ($bf,full_tag("DECIMALS",7,false,$ch->decimals));
1935 fwrite ($bf,full_tag("HIDDEN",5,false,$ch->hidden));
1936 fwrite ($bf,full_tag("LOCKED",5,false,$ch->locked));
1937 fwrite ($bf,full_tag("LOCKTIME",5,false,$ch->locktime));
1938 fwrite ($bf,full_tag("NEEDSUPDATE",5,false,$ch->needsupdate));
1939 fwrite ($bf,end_tag("GRADE_ITEM_HISTORY",4,true));
1941 $status = fwrite ($bf,end_tag("GRADE_ITEM_HISTORIES",3,true));
1944 return $status;
1947 function backup_gradebook_outcomes_history($bf, $preferences) {
1948 global $CFG;
1949 $status = true;
1951 // find all grade categories history
1952 if ($chs = get_records('grade_outcomes_history','courseid', $preferences->backup_course)) {
1953 fwrite ($bf,start_tag("GRADE_OUTCOME_HISTORIES",3,true));
1954 foreach ($chs as $ch) {
1955 fwrite ($bf,start_tag("GRADE_OUTCOME_HISTORY",4,true));
1956 fwrite ($bf,full_tag("ID",5,false,$ch->id));
1957 fwrite ($bf,full_tag("OLDID",5,false,$ch->oldid));
1958 fwrite ($bf,full_tag("ACTION",5,false,$ch->action));
1959 fwrite ($bf,full_tag("SOURCE",5,false,$ch->source));
1960 fwrite ($bf,full_tag("TIMEMODIFIED",5,false,$ch->timemodified));
1961 fwrite ($bf,full_tag("LOGGEDUSER",5,false,$ch->loggeduser));
1962 fwrite ($bf,full_tag("SHORTNAME",5,false,$ch->shortname));
1963 fwrite ($bf,full_tag("FULLNAME",5,false,$ch->fullname));
1964 fwrite ($bf,full_tag("SCALEID",5,false,$ch->scaleid));
1965 fwrite ($bf,full_tag("DESCRIPTION",5,false,$ch->description));
1966 fwrite ($bf,end_tag("GRADE_OUTCOME_HISTORY",4,true));
1968 $status = fwrite ($bf,end_tag("GRADE_OUTCOME_HISTORIES",3,true));
1970 return $status;
1973 //Backup scales info (common and course scales)
1974 function backup_scales_info($bf,$preferences) {
1976 global $CFG;
1978 $status = true;
1980 //Counter, points to current record
1981 $counter = 0;
1983 //Get scales (common and course scales)
1984 $scales = get_records_sql("SELECT id, courseid, userid, name, scale, description, timemodified
1985 FROM {$CFG->prefix}scale
1986 WHERE courseid = 0 OR courseid = $preferences->backup_course");
1988 //Copy only used scales to $backupscales. They will be in backup (unused no). See Bug 1223.
1989 $backupscales = array();
1990 if ($scales) {
1991 foreach ($scales as $scale) {
1992 if (course_scale_used($preferences->backup_course, $scale->id)) {
1993 $backupscales[] = $scale;
1998 //Pring scales header
1999 if ($backupscales) {
2000 //Pring scales header
2001 fwrite ($bf,start_tag("SCALES",2,true));
2002 //Iterate
2003 foreach ($backupscales as $scale) {
2004 //Begin scale tag
2005 fwrite ($bf,start_tag("SCALE",3,true));
2006 //Output scale tag
2007 fwrite ($bf,full_tag("ID",4,false,$scale->id));
2008 fwrite ($bf,full_tag("COURSEID",4,false,$scale->courseid));
2009 fwrite ($bf,full_tag("USERID",4,false,$scale->userid));
2010 fwrite ($bf,full_tag("NAME",4,false,$scale->name));
2011 fwrite ($bf,full_tag("SCALETEXT",4,false,$scale->scale));
2012 fwrite ($bf,full_tag("DESCRIPTION",4,false,$scale->description));
2013 fwrite ($bf,full_tag("TIMEMODIFIED",4,false,$scale->timemodified));
2014 //End scale tag
2015 fwrite ($bf,end_tag("SCALE",3,true));
2017 //End scales tag
2018 $status = fwrite ($bf,end_tag("SCALES",2,true));
2020 return $status;
2023 //Backup events info (course events)
2024 function backup_events_info($bf,$preferences) {
2026 global $CFG;
2028 $status = true;
2030 //Counter, points to current record
2031 $counter = 0;
2033 //Get events (course events)
2034 $events = get_records_select("event","courseid='$preferences->backup_course' AND instance='0'","id");
2036 //Pring events header
2037 if ($events) {
2038 //Pring events header
2039 fwrite ($bf,start_tag("EVENTS",2,true));
2040 //Iterate
2041 foreach ($events as $event) {
2042 //Begin event tag
2043 fwrite ($bf,start_tag("EVENT",3,true));
2044 //Output event tag
2045 fwrite ($bf,full_tag("ID",4,false,$event->id));
2046 fwrite ($bf,full_tag("NAME",4,false,$event->name));
2047 fwrite ($bf,full_tag("DESCRIPTION",4,false,$event->description));
2048 fwrite ($bf,full_tag("FORMAT",4,false,$event->format));
2049 fwrite ($bf,full_tag("GROUPID",4,false,$event->groupid));
2050 fwrite ($bf,full_tag("USERID",4,false,$event->userid));
2051 fwrite ($bf,full_tag("REPEATID",4,false,$event->repeatid));
2052 fwrite ($bf,full_tag("EVENTTYPE",4,false,$event->eventtype));
2053 fwrite ($bf,full_tag("MODULENAME",4,false,$event->modulename));
2054 fwrite ($bf,full_tag("TIMESTART",4,false,$event->timestart));
2055 fwrite ($bf,full_tag("TIMEDURATION",4,false,$event->timeduration));
2056 fwrite ($bf,full_tag("VISIBLE",4,false,$event->visible));
2057 fwrite ($bf,full_tag("TIMEMODIFIED",4,false,$event->timemodified));
2058 //End event tag
2059 fwrite ($bf,end_tag("EVENT",3,true));
2061 //End events tag
2062 $status = fwrite ($bf,end_tag("EVENTS",2,true));
2064 return $status;
2067 //Backup groups info
2068 function backup_groups_info($bf,$preferences) {
2070 global $CFG;
2072 $status = true;
2073 $status2 = true;
2075 //Get groups
2076 $groups = get_records("groups","courseid",$preferences->backup_course);
2078 //Pring groups header
2079 if ($groups) {
2080 //Pring groups header
2081 fwrite ($bf,start_tag("GROUPS",2,true));
2082 //Iterate
2083 foreach ($groups as $group) {
2084 //Begin group tag
2085 fwrite ($bf,start_tag("GROUP",3,true));
2086 //Output group contents
2087 fwrite ($bf,full_tag("ID",4,false,$group->id));
2088 //fwrite ($bf,full_tag("COURSEID",4,false,$group->courseid));
2089 fwrite ($bf,full_tag("NAME",4,false,$group->name));
2090 fwrite ($bf,full_tag("DESCRIPTION",4,false,$group->description));
2091 fwrite ($bf,full_tag("ENROLMENTKEY",4,false,$group->enrolmentkey));
2092 fwrite ($bf,full_tag("PICTURE",4,false,$group->picture));
2093 fwrite ($bf,full_tag("HIDEPICTURE",4,false,$group->hidepicture));
2094 fwrite ($bf,full_tag("TIMECREATED",4,false,$group->timecreated));
2095 fwrite ($bf,full_tag("TIMEMODIFIED",4,false,$group->timemodified));
2097 //Now, backup groups_members, only if users are included
2098 if ($preferences->backup_users != 2) {
2099 $status2 = backup_groups_members_info($bf,$preferences,$group->id);
2102 //End group tag
2103 fwrite ($bf,end_tag("GROUP",3,true));
2105 //End groups tag
2106 $status = fwrite ($bf,end_tag("GROUPS",2,true));
2108 //Now save group_files
2109 if ($status && $status2) {
2110 $status2 = backup_copy_group_files($preferences);
2113 return ($status && $status2);
2116 //Backup groups_members info
2117 function backup_groups_members_info($bf,$preferences,$groupid) {
2119 global $CFG;
2121 $status = true;
2123 //Get groups_members that are being included in backup
2124 $groups_members = get_records_sql("SELECT gm.*
2125 FROM {$CFG->prefix}groups_members gm,
2126 {$CFG->prefix}backup_ids bi
2127 WHERE gm.groupid = $groupid
2128 AND bi.backup_code = $preferences->backup_unique_code
2129 AND bi.table_name = 'user'
2130 AND bi.old_id = gm.userid");
2132 //Pring groups_members header
2133 if ($groups_members) {
2134 //Pring groups_members header
2135 fwrite ($bf,start_tag("MEMBERS",4,true));
2136 //Iterate
2137 foreach ($groups_members as $group_member) {
2138 //Begin group_member tag
2139 fwrite ($bf,start_tag("MEMBER",5,true));
2140 //Output group_member contents
2141 fwrite ($bf,full_tag("GROUPID",6,false,$group_member->groupid));
2142 fwrite ($bf,full_tag("USERID",6,false,$group_member->userid));
2143 fwrite ($bf,full_tag("TIMEADDED",6,false,$group_member->timeadded));
2144 //End group_member tag
2145 fwrite ($bf,end_tag("MEMBER",5,true));
2147 //End groups_members tag
2148 $status = fwrite ($bf,end_tag("MEMBERS",4,true));
2150 return $status;
2153 //Backup groupings info
2154 function backup_groupings_info($bf,$preferences) {
2156 global $CFG;
2158 $status = true;
2160 //Get groups
2161 $groupings = get_records("groupings","courseid",$preferences->backup_course);
2163 //Pring groups header
2164 if ($groupings) {
2165 //Pring groups header
2166 fwrite ($bf,start_tag("GROUPINGS",2,true));
2167 //Iterate
2168 foreach ($groupings as $grouping) {
2169 //Begin group tag
2170 fwrite ($bf,start_tag("GROUPING",3,true));
2171 //Output group contents
2172 fwrite ($bf,full_tag("ID",4,false,$grouping->id));
2173 //fwrite ($bf,full_tag("COURSEID",4,false,$grouping->courseid));
2174 fwrite ($bf,full_tag("NAME",4,false,$grouping->name));
2175 fwrite ($bf,full_tag("DESCRIPTION",4,false,$grouping->description));
2176 fwrite ($bf,full_tag("CONFIGDATA",4,false,$grouping->configdata));
2177 fwrite ($bf,full_tag("TIMECREATED",4,false,$grouping->timecreated));
2178 fwrite ($bf,full_tag("TIMEMODIFIED",4,false,$grouping->timemodified));
2180 //End group tag
2181 fwrite ($bf,end_tag("GROUPING",3,true));
2183 //End groups tag
2184 $status = fwrite ($bf,end_tag("GROUPINGS",2,true));
2186 //(Now save grouping_files)
2188 return $status;
2191 //Backup groupings-groups info
2192 function backup_groupings_groups_info($bf,$preferences) {
2194 global $CFG;
2196 $status = true;
2198 //Get grouping_groups
2199 $courseid = $preferences->backup_course;
2200 $sql = "SELECT gg.* FROM {$CFG->prefix}groupings g, {$CFG->prefix}groupings_groups gg
2201 WHERE g.courseid=$courseid AND g.id=gg.groupingid";
2202 $grouping_groups = get_records_sql($sql);
2204 //Pring grouping_groups header
2205 if ($grouping_groups) {
2206 //Pring grouping_groups header
2207 fwrite ($bf,start_tag("GROUPINGSGROUPS",2,true));
2208 //Iterate
2209 foreach ($grouping_groups as $members) {
2210 //Begin grouping_group tag
2211 fwrite ($bf,start_tag("GROUPINGGROUP",3,true));
2212 //Output group_member contents
2213 fwrite ($bf,full_tag("ID",4,false,$members->id));
2214 fwrite ($bf,full_tag("GROUPINGID",4,false,$members->groupingid));
2215 fwrite ($bf,full_tag("GROUPID",4,false,$members->groupid));
2216 fwrite ($bf,full_tag("TIMEADDED",4,false,$members->timeadded));
2217 //End grouping_group tag
2218 fwrite ($bf,end_tag("GROUPINGGROUP",3,true));
2220 //End grouping_groups tag
2221 $status = fwrite ($bf,end_tag("GROUPINGSGROUPS",2,true));
2223 return $status;
2226 //Start the modules tag
2227 function backup_modules_start ($bf,$preferences) {
2229 return fwrite ($bf,start_tag("MODULES",2,true));
2232 //End the modules tag
2233 function backup_modules_end ($bf,$preferences) {
2235 return fwrite ($bf,end_tag("MODULES",2,true));
2238 //This function makes all the necesary calls to every mod
2239 //to export itself and its files !!!
2240 function backup_module($bf,$preferences,$module) {
2242 global $CFG;
2244 $status = true;
2245 $statusm = true;
2247 require_once($CFG->dirroot.'/mod/'.$module.'/backuplib.php');
2249 if (isset($preferences->mods[$module]->instances)
2250 && is_array($preferences->mods[$module]->instances)) {
2251 $onemodbackup = $module.'_backup_one_mod';
2252 if (function_exists($onemodbackup)) {
2253 foreach ($preferences->mods[$module]->instances as $instance => $object) {
2254 if (!empty($object->backup)) {
2255 $statusm = $onemodbackup($bf,$preferences,$instance);
2256 if (!$statusm) {
2257 if (!defined('BACKUP_SILENTLY')) {
2258 notify('backup of '.$module.'-'.$object->name.' failed.');
2260 $status = false;
2264 } else {
2265 $status = false;
2267 } else { // whole module.
2268 //First, re-check if necessary functions exists
2269 $modbackup = $module."_backup_mods";
2270 if (function_exists($modbackup)) {
2271 //Call the function
2272 $status = $modbackup($bf,$preferences);
2273 } else {
2274 //Something was wrong. Function should exist.
2275 $status = false;
2279 return $status;
2283 //This function encode things to make backup multi-site fully functional
2284 //It does this conversions:
2285 // - $CFG->wwwroot/file.php/courseid ------------------> $@FILEPHP@$ (slasharguments links)
2286 // - $CFG->wwwroot/file.php?file=/courseid ------------> $@FILEPHP@$ (non-slasharguments links)
2287 // - Every module/block/course_format xxxx_encode_content_links() is executed too
2289 function backup_encode_absolute_links($content) {
2291 global $CFG,$preferences;
2293 /// MDL-14072: Prevent NULLs, empties and numbers to be processed by the
2294 /// heavy interlinking. Just a few cpu cycles saved.
2295 if ($content === NULL) {
2296 return NULL;
2297 } else if ($content === '') {
2298 return '';
2299 } else if (is_numeric($content)) {
2300 return $content;
2303 //Use one static variable to cache all the require_once calls that,
2304 //under PHP5 seems to increase load too much, and we are requiring
2305 //them here thousands of times (one per content). MDL-8700.
2306 //Once fixed by PHP, we'll delete this hack
2308 static $includedfiles;
2309 if (!isset($includedfiles)) {
2310 $includedfiles = array();
2313 //Check if we support unicode modifiers in regular expressions. Cache it.
2314 static $unicoderegexp;
2315 if (!isset($unicoderegexp)) {
2316 $unicoderegexp = @preg_match('/\pL/u', 'a'); // This will fail silenty, returning false,
2317 } // if regexp libraries don't support unicode
2319 //Check if preferences is ok. If it isn't set, we are
2320 //in a scheduled_backup to we are able to get a copy
2321 //from CFG->backup_preferences
2322 if (!isset($preferences)) {
2323 $mypreferences = $CFG->backup_preferences;
2324 } else {
2325 //We are in manual backups so global preferences must exist!!
2326 $mypreferences = $preferences;
2328 //First, we check for every call to file.php inside the course
2329 $search = array($CFG->wwwroot.'/file.php/'.$mypreferences->backup_course,
2330 $CFG->wwwroot.'/file.php?file=/'.$mypreferences->backup_course,
2331 $CFG->wwwroot.'/file.php?file=%2f'.$mypreferences->backup_course,
2332 $CFG->wwwroot.'/file.php?file=%2F'.$mypreferences->backup_course);
2334 $replace = array('$@FILEPHP@$', '$@FILEPHP@$', '$@FILEPHP@$', '$@FILEPHP@$');
2336 $result = str_replace($search,$replace,$content);
2338 // Now we look for any '$@FILEPHP@$' URLs, replacing:
2339 // - slashes and %2F by $@SLASH@$
2340 // - &forcedownload=1 &amp;forcedownload=1 and ?forcedownload=1 by $@FORCEDOWNLOAD@$
2341 // This way, backup contents will be neutral and independent of slasharguments configuration. MDL-18799
2342 // Based in $unicoderegexp, decide the regular expression to use
2343 if ($unicoderegexp) { //We can use unicode modifiers
2344 $search = '/(\$@FILEPHP@\$)((?:(?:\/|%2f|%2F))(?:(?:\([-;:@#&=\pL0-9\$~_.+!*\',]*?\))|[-;:@#&=\pL0-9\$~_.+!*\',]|%[a-fA-F0-9]{2}|\/)*)?(\?(?:(?:(?:\([-;:@#&=\pL0-9\$~_.+!*\',]*?\))|[-;:@#&=?\pL0-9\$~_.+!*\',]|%[a-fA-F0-9]{2}|\/)*))?(?<![,.;])/u';
2345 } else { //We cannot ue unicode modifiers
2346 $search = '/(\$@FILEPHP@\$)((?:(?:\/|%2f|%2F))(?:(?:\([-;:@#&=a-zA-Z0-9\$~_.+!*\',]*?\))|[-;:@#&=a-zA-Z0-9\$~_.+!*\',]|%[a-fA-F0-9]{2}|\/)*)?(\?(?:(?:(?:\([-;:@#&=a-zA-Z0-9\$~_.+!*\',]*?\))|[-;:@#&=?a-zA-Z0-9\$~_.+!*\',]|%[a-fA-F0-9]{2}|\/)*))?(?<![,.;])/';
2348 $result = preg_replace_callback($search, 'backup_process_filephp_uses', $result);
2350 foreach ($mypreferences->mods as $name => $info) {
2351 /// We only include the corresponding backuplib.php if it hasn't been included before
2352 /// This will save some load under PHP5. MDL-8700.
2353 /// Once fixed by PHP, we'll delete this hack
2354 if (!in_array($name, $includedfiles)) {
2355 include_once("$CFG->dirroot/mod/$name/backuplib.php");
2356 $includedfiles[] = $name;
2358 //Check if the xxxx_encode_content_links exists
2359 $function_name = $name."_encode_content_links";
2360 if (function_exists($function_name)) {
2361 $result = $function_name($result,$mypreferences);
2365 // For the current course format call its encode_content_links method (if it exists)
2366 static $format_function_name;
2367 if (!isset($format_function_name)) {
2368 $format_function_name = false;
2369 if ($format = get_field('course', 'format', 'id', $mypreferences->backup_course)) {
2370 if (file_exists("$CFG->dirroot/course/format/$format/backuplib.php")) {
2371 include_once("$CFG->dirroot/course/format/$format/backuplib.php");
2372 $function_name = $format.'_encode_format_content_links';
2373 if (function_exists($function_name)) {
2374 $format_function_name = $function_name;
2379 // If the above worked - then we have a function to call
2380 if ($format_function_name) {
2381 $result = $format_function_name($result, $mypreferences);
2384 // For each block, call its encode_content_links method.
2385 // This encodes forexample links to blocks/something/viewphp?id=666
2386 // that are stored in other activities.
2387 static $blockobjects = null;
2388 if (!isset($blockobjects)) {
2389 $blockobjects = array();
2390 if ($blocks = get_records('block', 'visible', 1)) {
2391 foreach ($blocks as $block) {
2392 if ($blockobject = block_instance($block->name)) {
2393 $blockobjects[] = $blockobject;
2399 foreach ($blockobjects as $blockobject) {
2400 $result = $blockobject->encode_content_links($result,$mypreferences);
2403 // Finally encode some well-know links to course
2404 $result = backup_course_encode_links($result, $mypreferences);
2406 if ($result != $content) {
2407 debugging('<br /><hr />'.s($content).'<br />changed to<br />'.s($result).'<hr /><br />');
2410 return $result;
2414 * Encode some well-know links to course. Restore will recode them to new course id
2416 function backup_course_encode_links($content, $preferences) {
2417 global $CFG;
2419 $base = preg_quote($CFG->wwwroot,"/");
2421 // Link to the course main page (it also covers "&topic=xx" and "&week=xx"
2422 // because they don't become transformed (section number) in backup/restore
2423 $search = '/(' . $base . '\/course\/view.php\?id\=)([0-9]+)/';
2424 $result = preg_replace($search,'$@COURSEVIEWBYID*$2@$', $content);
2426 return $result;
2430 * Callback preg_replace function used by backup_encode_absolute_links()
2431 * to process $@FILEPHP@$ URLs to get slasharguments independent URLs
2433 function backup_process_filephp_uses($matches) {
2435 // Replace slashes (plain and encoded) and forcedownload=1 parameter
2436 $search = array('/', '%2f', '%2F', '?forcedownload=1', '&forcedownload=1', '&amp;forcedownload=1');
2437 $replace = array('$@SLASH@$', '$@SLASH@$', '$@SLASH@$', '$@FORCEDOWNLOAD@$', '$@FORCEDOWNLOAD@$', '$@FORCEDOWNLOAD@$');
2439 $result = $matches[1] . (isset($matches[2]) ? str_replace($search, $replace, $matches[2]) : '') . (isset($matches[3]) ? str_replace($search, $replace, $matches[3]) : '');
2441 return $result;
2444 //This function copies all the needed files under the "user" directory to the "user_files"
2445 //directory under temp/backup
2446 function backup_copy_user_files ($preferences) {
2448 global $CFG;
2450 $status = true;
2452 //First we check that "user_files" exists and create it if necessary
2453 //in temp/backup/$backup_code dir
2454 $status = check_and_create_user_files_dir($preferences->backup_unique_code);
2455 //now get a list of users that we need for this backup.
2456 $backup_users = get_recordset_select("backup_ids",
2457 "backup_code='$preferences->backup_unique_code' AND table_name='user'", "", "id, old_id");
2458 while ($user = rs_fetch_next_record($backup_users)) {
2459 //If this user's directory exists, copy it
2460 $userdir = make_user_directory($user->old_id, true);
2461 if (check_dir_exists($userdir)) {
2462 //first remove dirroot so we can split out the folders.
2463 $parts = explode('/', str_replace($CFG->dataroot.'/user/', '', $userdir));
2464 $status = true;
2465 if (is_array($parts)) {
2466 $group = $parts[0];
2467 $userid = $parts[1];
2469 // Create group dir first
2470 $status = check_dir_exists("$CFG->dataroot/temp/backup/$preferences->backup_unique_code/user_files/". $group, true);
2473 $status = $status && backup_copy_file($userdir,
2474 "$CFG->dataroot/temp/backup/$preferences->backup_unique_code/user_files/$group/$user->old_id");
2476 //Do some output
2477 backup_flush(30);
2479 rs_close($backup_users);
2481 return $status;
2484 //This function copies all the needed files under the "groups" directory to the "group_files"
2485 //directory under temp/backup
2486 function backup_copy_group_files ($preferences) {
2488 global $CFG;
2490 $status = true;
2492 //First we check if "group_files" exists and create it as necessary
2493 //in temp/backup/$backup_code dir
2494 $status = check_and_create_group_files_dir($preferences->backup_unique_code);
2496 //Now iterate over directories under "groups" to check if that user must be
2497 //copied to backup
2499 $rootdir = $CFG->dataroot.'/groups';
2500 //Check if directory exists
2501 if (is_dir($rootdir)) {
2502 $list = list_directories ($rootdir);
2503 if ($list) {
2504 //Iterate
2505 foreach ($list as $dir) {
2506 //Look for dir like group in groups table
2507 $data = get_record ('groups', 'courseid', $preferences->backup_course,
2508 'id',$dir);
2509 //If exists, copy it
2510 if ($data) {
2511 $status = backup_copy_file($rootdir."/".$dir,
2512 $CFG->dataroot."/temp/backup/".$preferences->backup_unique_code."/group_files/".$dir);
2517 return $status;
2520 //This function copies all the course files under the course directory (except the moddata
2521 //directory to the "course_files" directory under temp/backup
2522 function backup_copy_course_files ($preferences) {
2524 global $CFG;
2526 $status = true;
2528 //First we check to "course_files" exists and create it as necessary
2529 //in temp/backup/$backup_code dir
2530 $status = check_and_create_course_files_dir($preferences->backup_unique_code);
2532 //Now iterate over files and directories except $CFG->moddata and backupdata to be
2533 //copied to backup
2535 $rootdir = $CFG->dataroot."/".$preferences->backup_course;
2537 $name_moddata = $CFG->moddata;
2538 $name_backupdata = "backupdata";
2539 //Check if directory exists
2540 if (is_dir($rootdir)) {
2541 $list = list_directories_and_files ($rootdir);
2542 if ($list) {
2543 //Iterate
2544 foreach ($list as $dir) {
2545 if ($dir !== $name_moddata and $dir !== $name_backupdata) {
2546 $status = backup_copy_file($rootdir."/".$dir,
2547 $CFG->dataroot."/temp/backup/".$preferences->backup_unique_code."/course_files/".$dir);
2552 return $status;
2555 * This function copies all the site files under the site directory (except the moddata and backupdata
2556 * directories to the "site_files" directory under temp/backup
2558 function backup_copy_site_files ($preferences) {
2560 global $CFG;
2562 $status = true;
2564 if ($preferences->backup_course == SITEID){
2565 return $status;
2568 //First we check to "site_files" exists and create it as necessary
2569 //in temp/backup/$backup_code dir
2570 $status = $status && check_and_create_site_files_dir($preferences->backup_unique_code);
2572 $rootdir = $CFG->dataroot."/".SITEID;
2576 $files = get_records_select('backup_files',
2577 "backup_code = '$preferences->backup_unique_code' AND file_type = 'site'");
2578 if ($files) {
2579 //Iterate
2580 foreach ($files as $fileobj) {
2581 //check for dir structure and create recursively
2582 $file = $fileobj->path;
2583 $status = $status && check_dir_exists(dirname($CFG->dataroot."/temp/backup/".$preferences->backup_unique_code."/site_files/".$file), true, true);
2584 $status = $status && backup_copy_file($rootdir."/".$file,
2585 $CFG->dataroot."/temp/backup/".$preferences->backup_unique_code."/site_files/".$file);
2588 return $status;
2590 //This function creates the zip file containing all the backup info
2591 //moodle.xml, moddata, user_files, course_files.
2592 //The zipped file is created in the backup directory and named with
2593 //the "oficial" name of the backup
2594 //It uses "pclzip" if available or system "zip" (unix only)
2595 function backup_zip ($preferences) {
2597 global $CFG;
2599 $status = true;
2601 //Base dir where everything happens
2602 $basedir = cleardoubleslashes($CFG->dataroot."/temp/backup/".$preferences->backup_unique_code);
2603 //Backup zip file name
2604 $name = $preferences->backup_name;
2605 //List of files and directories
2606 $filelist = list_directories_and_files ($basedir);
2608 //Convert them to full paths
2609 $files = array();
2610 foreach ($filelist as $file) {
2611 $files[] = "$basedir/$file";
2614 $status = zip_files($files, "$basedir/$name");
2616 //echo "<br/>Status: ".$status; //Debug
2617 return $status;
2621 //This function copies the final zip to the course dir
2622 function copy_zip_to_course_dir ($preferences) {
2624 global $CFG;
2626 $status = true;
2628 //Define zip location (from)
2629 $from_zip_file = $CFG->dataroot."/temp/backup/".$preferences->backup_unique_code."/".$preferences->backup_name;
2631 //Initialise $to_zip_file
2632 $to_zip_file="";
2634 //If $preferences->backup_destination isn't empty, then copy to custom directory
2635 if (!empty($preferences->backup_destination)) {
2636 $to_zip_file = $preferences->backup_destination."/".$preferences->backup_name;
2637 } else {
2638 //Define zip destination (course dir)
2639 $to_zip_file = $CFG->dataroot."/".$preferences->backup_course;
2641 //echo "<p>From: ".$from_zip_file."<br />"; //Debug
2643 //echo "<p>Checking: ".$to_zip_file."<br />"; //Debug
2645 //Checks course dir exists
2646 $status = check_dir_exists($to_zip_file,true);
2648 //Define zip destination (backup dir)
2649 $to_zip_file = $to_zip_file."/backupdata";
2651 //echo "<p>Checking: ".$to_zip_file."<br />"; //Debug
2653 //Checks backup dir exists
2654 $status = check_dir_exists($to_zip_file,true);
2656 //Define zip destination (zip file)
2657 $to_zip_file = $to_zip_file."/".$preferences->backup_name;
2660 //echo "<p>To: ".$to_zip_file."<br />"; //Debug
2662 //Copy zip file
2663 if ($status) {
2664 $status = backup_copy_file ($from_zip_file,$to_zip_file);
2667 return $status;
2671 * compatibility function
2672 * with new granular backup
2673 * we need to know
2675 function backup_userdata_selected($preferences,$modname,$modid) {
2676 return ((empty($preferences->mods[$modname]->instances)
2677 && !empty($preferences->mods[$modname]->userinfo))
2678 || (is_array($preferences->mods[$modname]->instances)
2679 && array_key_exists($modid,$preferences->mods[$modname]->instances)
2680 && !empty($preferences->mods[$modname]->instances[$modid]->userinfo)));
2684 function backup_mod_selected($preferences,$modname,$modid) {
2685 return ((empty($preferences->mods[$modname]->instances)
2686 && !empty($preferences->mods[$modname]->backup))
2687 || (is_array($preferences->mods[$modname]->instances)
2688 && array_key_exists($modid,$preferences->mods[$modname]->instances)
2689 && !empty($preferences->mods[$modname]->instances[$modid]->backup)));
2693 * Checks for the required files/functions to backup every mod
2694 * And check if there is data about it
2696 function backup_fetch_prefs_from_request(&$preferences,&$count,$course) {
2697 global $CFG,$SESSION;
2699 // check to see if it's in the session already
2700 if (!empty($SESSION->backupprefs) && array_key_exists($course->id,$SESSION->backupprefs) && !empty($SESSION->backupprefs[$course->id])) {
2701 $sprefs = $SESSION->backupprefs[$course->id];
2702 $preferences = $sprefs;
2703 // refetch backup_name just in case.
2704 $bn = optional_param('backup_name','',PARAM_FILE);
2705 if (!empty($bn)) {
2706 $preferences->backup_name = $bn;
2708 $count = 1;
2709 return true;
2712 if ($allmods = get_records("modules") ) {
2713 foreach ($allmods as $mod) {
2714 $modname = $mod->name;
2715 $modfile = "$CFG->dirroot/mod/$modname/backuplib.php";
2716 $modbackup = $modname."_backup_mods";
2717 $modbackupone = $modname."_backup_one_mod";
2718 $modcheckbackup = $modname."_check_backup_mods";
2719 if (!file_exists($modfile)) {
2720 continue;
2722 include_once($modfile);
2723 if (!function_exists($modbackup) || !function_exists($modcheckbackup)) {
2724 continue;
2726 $var = "exists_".$modname;
2727 $preferences->$var = true;
2728 $count++;
2729 // check that there are instances and we can back them up individually
2730 if (!count_records('course_modules','course',$course->id,'module',$mod->id) || !function_exists($modbackupone)) {
2731 continue;
2733 $var = 'exists_one_'.$modname;
2734 $preferences->$var = true;
2735 $varname = $modname.'_instances';
2736 $preferences->$varname = get_all_instances_in_course($modname, $course, NULL, true);
2737 foreach ($preferences->$varname as $instance) {
2738 $preferences->mods[$modname]->instances[$instance->id]->name = $instance->name;
2739 $var = 'backup_'.$modname.'_instance_'.$instance->id;
2740 $$var = optional_param($var,0);
2741 $preferences->$var = $$var;
2742 $preferences->mods[$modname]->instances[$instance->id]->backup = $$var;
2743 $var = 'backup_user_info_'.$modname.'_instance_'.$instance->id;
2744 $$var = optional_param($var,0);
2745 $preferences->$var = $$var;
2746 $preferences->mods[$modname]->instances[$instance->id]->userinfo = $$var;
2747 $var = 'backup_'.$modname.'_instances';
2748 $preferences->$var = 1; // we need this later to determine what to display in modcheckbackup.
2751 //Check data
2752 //Check module info
2753 $preferences->mods[$modname]->name = $modname;
2755 $var = "backup_".$modname;
2756 $$var = optional_param( $var,0);
2757 $preferences->$var = $$var;
2758 $preferences->mods[$modname]->backup = $$var;
2760 //Check include user info
2761 $var = "backup_user_info_".$modname;
2762 $$var = optional_param( $var,0);
2763 $preferences->$var = $$var;
2764 $preferences->mods[$modname]->userinfo = $$var;
2769 //Check other parameters
2770 $preferences->backup_metacourse = optional_param('backup_metacourse',1,PARAM_INT);
2771 $preferences->backup_users = optional_param('backup_users',1,PARAM_INT);
2772 $preferences->backup_logs = optional_param('backup_logs',0,PARAM_INT);
2773 $preferences->backup_user_files = optional_param('backup_user_files',1,PARAM_INT);
2774 $preferences->backup_course_files = optional_param('backup_course_files',1,PARAM_INT);
2775 $preferences->backup_gradebook_history = optional_param('backup_gradebook_history', 1, PARAM_INT);
2776 $preferences->backup_site_files = optional_param('backup_site_files',1,PARAM_INT);
2777 $preferences->backup_messages = optional_param('backup_messages',1,PARAM_INT);
2778 $preferences->backup_blogs = optional_param('backup_blogs',1,PARAM_INT);
2779 $preferences->backup_course = $course->id;
2780 $preferences->backup_name = required_param('backup_name',PARAM_FILE);
2781 $preferences->backup_unique_code = required_param('backup_unique_code');
2783 $roles = get_records('role', '', '', 'sortorder');
2784 $preferences->backuproleassignments = array();
2785 foreach ($roles as $role) {
2786 if (optional_param('backupassignments_' . $role->shortname, 0, PARAM_INT)) {
2787 $preferences->backuproleassignments[$role->id] = $role;
2791 // put it (back) in the session
2792 $SESSION->backupprefs[$course->id] = $preferences;
2795 /* Finds all related roles used in course, mod and blocks context
2796 * @param object $preferences
2797 * @param object $course
2798 * @return array of role objects
2800 function backup_fetch_roles($preferences) {
2802 global $CFG;
2803 $contexts = array();
2804 $roles = array();
2806 /// adding course context
2807 $coursecontext = get_context_instance(CONTEXT_COURSE, $preferences->backup_course);
2808 $contexts[$coursecontext->id] = $coursecontext;
2810 /// adding mod contexts
2811 $mods = $preferences->mods;
2812 foreach ($mods as $modname => $mod) {
2813 $instances = $mod->instances;
2814 foreach ($instances as $id => $instance) {
2815 // if this type of mod is to be backed up
2816 if ($instance->backup) {
2817 $cm = get_coursemodule_from_instance($modname, $id);
2818 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
2819 // put context in array keys
2820 $contexts[$context->id] = $context;
2825 // add all roles assigned at user context
2826 if ($preferences->backup_users) {
2827 if ($users = get_records_sql("SELECT u.old_id, u.table_name,u.info
2828 FROM {$CFG->prefix}backup_ids u
2829 WHERE u.backup_code = '$preferences->backup_unique_code' AND
2830 u.table_name = 'user'")) {
2831 foreach ($users as $user) {
2832 $context = get_context_instance(CONTEXT_USER, $user->old_id);
2833 $contexts[$context->id] = $context;
2839 // add all roles assigned at block context
2840 if ($courseblocks = get_records_sql("SELECT *
2841 FROM {$CFG->prefix}block_instance
2842 WHERE pagetype = '".PAGE_COURSE_VIEW."'
2843 AND pageid = {$preferences->backup_course}")) {
2845 foreach ($courseblocks as $courseblock) {
2847 $context = get_context_instance(CONTEXT_BLOCK, $courseblock->id);
2848 $contexts[$context->id] = $context;
2852 // foreach context, call get_roles_on_exact_context + get_roles_with_override_on_context() and insert into array
2853 foreach ($contexts as $context) {
2854 if ($proles = get_roles_on_exact_context($context)) { // Look for roles assignments
2855 foreach ($proles as $prole) {
2856 $roles[$prole->id] = $prole;
2859 if ($proles = get_roles_with_override_on_context($context)) { // Look for roles overrides
2860 foreach ($proles as $prole) {
2861 $roles[$prole->id] = $prole;
2866 return $roles;
2869 /* function to print xml for overrides */
2870 function write_role_overrides_xml($bf, $context, $startlevel) {
2871 fwrite ($bf, start_tag("ROLES_OVERRIDES", $startlevel, true));
2872 if ($roles = get_roles_with_override_on_context($context)) {
2873 foreach ($roles as $role) {
2874 fwrite ($bf, start_tag("ROLE", $startlevel+1, true));
2875 fwrite ($bf, full_tag("ID", $startlevel+2, false, $role->id));
2876 fwrite ($bf, full_tag("NAME", $startlevel+2, false, $role->name));
2877 fwrite ($bf, full_tag("SHORTNAME", $startlevel+2, false, $role->shortname));
2878 fwrite ($bf, start_tag("CAPABILITIES", $startlevel+2, true));
2879 if ($capabilities = get_capabilities_from_role_on_context($role, $context)) {
2880 foreach ($capabilities as $capability) {
2881 fwrite ($bf, start_tag("CAPABILITY", $startlevel+3, true));
2882 fwrite ($bf, full_tag("NAME", $startlevel+4, false, $capability->capability));
2883 fwrite ($bf, full_tag("PERMISSION", $startlevel+4, false, $capability->permission));
2884 fwrite ($bf, full_tag("TIMEMODIFIED", $startlevel+4, false, $capability->timemodified));
2885 if (!isset($capability->modifierid)) {
2886 $capability->modifierid = 0;
2888 fwrite ($bf, full_tag("MODIFIERID", $startlevel+4, false, $capability->modifierid));
2889 fwrite ($bf, end_tag("CAPABILITY", $startlevel+3, true));
2892 fwrite ($bf, end_tag("CAPABILITIES", $startlevel+2, true));
2893 fwrite ($bf, end_tag("ROLE", $startlevel+1, true));
2896 fwrite ($bf, end_tag("ROLES_OVERRIDES", $startlevel, true));
2899 /* function to print xml for assignment */
2900 function write_role_assignments_xml($bf, $preferences, $context, $startlevel) {
2901 /// write role_assign code here
2902 fwrite ($bf, start_tag("ROLES_ASSIGNMENTS", $startlevel, true));
2904 if ($roles = get_roles_with_assignment_on_context($context)) {
2905 foreach ($roles as $role) {
2906 /// Skip non-selected roles
2907 if (!isset($preferences->backuproleassignments[$role->id])) {
2908 continue;
2910 fwrite ($bf, start_tag("ROLE", $startlevel+1, true));
2911 fwrite ($bf, full_tag("ID", $startlevel+2, false, $role->id));
2912 fwrite ($bf, full_tag("NAME", $startlevel+2, false, $role->name));
2913 fwrite ($bf, full_tag("SHORTNAME", $startlevel+2, false, $role->shortname));
2914 fwrite ($bf, start_tag("ASSIGNMENTS", $startlevel+2, true));
2915 if ($assignments = get_users_from_role_on_context($role, $context)) {
2916 foreach ($assignments as $assignment) {
2917 /// Role assignments are only sent to backup if the user is one target user
2918 if (backup_getid($preferences->backup_unique_code, 'user', $assignment->userid)) {
2919 fwrite ($bf, start_tag("ASSIGNMENT", $startlevel+3, true));
2920 fwrite ($bf, full_tag("USERID", $startlevel+4, false, $assignment->userid));
2921 fwrite ($bf, full_tag("HIDDEN", $startlevel+4, false, $assignment->hidden));
2922 fwrite ($bf, full_tag("TIMESTART", $startlevel+4, false, $assignment->timestart));
2923 fwrite ($bf, full_tag("TIMEEND", $startlevel+4, false, $assignment->timeend));
2924 fwrite ($bf, full_tag("TIMEMODIFIED", $startlevel+4, false, $assignment->timemodified));
2925 if (!isset($assignment->modifierid)) {
2926 $assignment->modifierid = 0;
2928 fwrite ($bf, full_tag("MODIFIERID", $startlevel+4, false, $assignment->modifierid));
2929 fwrite ($bf, full_tag("ENROL", $startlevel+4, false, $assignment->enrol));
2930 fwrite ($bf, full_tag("SORTORDER", $startlevel+4, false, $assignment->sortorder));
2931 fwrite ($bf, end_tag("ASSIGNMENT", $startlevel+3, true));
2935 fwrite ($bf, end_tag("ASSIGNMENTS", $startlevel+2, true));
2936 fwrite ($bf, end_tag("ROLE", $startlevel+1, true));
2939 fwrite ($bf, end_tag("ROLES_ASSIGNMENTS", $startlevel, true));
2943 function backup_execute(&$preferences, &$errorstr) {
2944 global $CFG;
2945 $status = true;
2947 //Check for temp and backup and backup_unique_code directory
2948 //Create them as needed
2949 if (!defined('BACKUP_SILENTLY')) {
2950 echo "<li>".get_string("creatingtemporarystructures").'</li>';
2953 $status = check_and_create_backup_dir($preferences->backup_unique_code);
2954 //Empty dir
2955 if ($status) {
2956 $status = clear_backup_dir($preferences->backup_unique_code);
2959 //Delete old_entries from backup tables
2960 if (!defined('BACKUP_SILENTLY')) {
2961 echo "<li>".get_string("deletingolddata").'</li>';
2963 $status = backup_delete_old_data();
2964 if (!$status) {
2965 if (!defined('BACKUP_SILENTLY')) {
2966 notify ("An error occurred deleting old backup data");
2968 else {
2969 $errorstr = "An error occurred deleting old backup data";
2970 return false;
2974 //Create the moodle.xml file
2975 if ($status) {
2976 if (!defined('BACKUP_SILENTLY')) {
2977 echo "<li>".get_string("creatingxmlfile");
2978 //Begin a new list to xml contents
2979 echo "<ul>";
2980 echo "<li>".get_string("writingheader").'</li>';
2982 //Obtain the xml file (create and open) and print prolog information
2983 $backup_file = backup_open_xml($preferences->backup_unique_code);
2984 if (!defined('BACKUP_SILENTLY')) {
2985 echo "<li>".get_string("writinggeneralinfo").'</li>';
2987 //Prints general info about backup to file
2988 if ($backup_file) {
2989 if (!$status = backup_general_info($backup_file,$preferences)) {
2990 if (!defined('BACKUP_SILENTLY')) {
2991 notify("An error occurred while backing up general info");
2993 else {
2994 $errorstr = "An error occurred while backing up general info";
2995 return false;
2999 if (!defined('BACKUP_SILENTLY')) {
3000 echo "<li>".get_string("writingcoursedata");
3001 //Start new ul (for course)
3002 echo "<ul>";
3003 echo "<li>".get_string("courseinfo").'</li>';
3005 //Prints course start (tag and general info)
3006 if ($status) {
3007 if (!$status = backup_course_start($backup_file,$preferences)) {
3008 if (!defined('BACKUP_SILENTLY')) {
3009 notify("An error occurred while backing up course start");
3011 else {
3012 $errorstr = "An error occurred while backing up course start";
3013 return false;
3017 //Metacourse information
3018 if ($status && $preferences->backup_metacourse) {
3019 if (!defined('BACKUP_SILENTLY')) {
3020 echo "<li>".get_string("metacourse").'</li>';
3022 if (!$status = backup_course_metacourse($backup_file,$preferences)) {
3023 if (!defined('BACKUP_SILENTLY')) {
3024 notify("An error occurred while backing up metacourse info");
3026 else {
3027 $errorstr = "An error occurred while backing up metacourse info";
3028 return false;
3032 if (!defined('BACKUP_SILENTLY')) {
3033 echo "<li>".get_string("blocks").'</li>';
3035 //Blocks information
3036 if ($status) {
3037 if (!$status = backup_course_blocks($backup_file,$preferences)) {
3038 if (!defined('BACKUP_SILENTLY')) {
3039 notify("An error occurred while backing up course blocks");
3041 else {
3042 $errorstr = "An error occurred while backing up course blocks";
3043 return false;
3047 if (!defined('BACKUP_SILENTLY')) {
3048 echo "<li>".get_string("sections").'</li>';
3050 //Section info
3051 if ($status) {
3052 if (!$status = backup_course_sections($backup_file,$preferences)) {
3053 if (!defined('BACKUP_SILENTLY')) {
3054 notify("An error occurred while backing up course sections");
3056 else {
3057 $errorstr = "An error occurred while backing up course sections";
3058 return false;
3063 //End course contents (close ul)
3064 if (!defined('BACKUP_SILENTLY')) {
3065 echo "</ul></li>";
3068 //User info
3069 if ($status) {
3070 if (!defined('BACKUP_SILENTLY')) {
3071 echo "<li>".get_string("writinguserinfo").'</li>';
3073 if (!$status = backup_user_info($backup_file,$preferences)) {
3074 if (!defined('BACKUP_SILENTLY')) {
3075 notify("An error occurred while backing up user info");
3077 else {
3078 $errorstr = "An error occurred while backing up user info";
3079 return false;
3084 //If we have selected to backup messages and we are
3085 //doing a SITE backup, let's do it
3086 if ($status && $preferences->backup_messages && $preferences->backup_course == SITEID) {
3087 if (!defined('BACKUP_SILENTLY')) {
3088 echo "<li>".get_string("writingmessagesinfo").'</li>';
3090 if (!$status = backup_messages($backup_file,$preferences)) {
3091 if (!defined('BACKUP_SILENTLY')) {
3092 notify("An error occurred while backing up messages");
3094 else {
3095 $errorstr = "An error occurred while backing up messages";
3096 return false;
3101 //If we have selected to backup blogs and we are
3102 //doing a SITE backup, let's do it
3103 if ($status && $preferences->backup_blogs && $preferences->backup_course == SITEID) {
3104 if (!defined('BACKUP_SILENTLY')) {
3105 echo "<li>".get_string("writingblogsinfo").'</li>';
3107 if (!$status = backup_blogs($backup_file,$preferences)) {
3108 if (!defined('BACKUP_SILENTLY')) {
3109 notify("An error occurred while backing up blogs");
3111 else {
3112 $errorstr = "An error occurred while backing up blogs";
3113 return false;
3118 //If we have selected to backup quizzes or other modules that use questions
3119 //we've already added ids of categories and questions to backup to backup_ids table
3120 if ($status) {
3121 if (!defined('BACKUP_SILENTLY')) {
3122 echo "<li>".get_string("writingcategoriesandquestions").'</li>';
3124 require_once($CFG->dirroot.'/question/backuplib.php');
3125 if (!$status = backup_question_categories($backup_file, $preferences)) {
3126 if (!defined('BACKUP_SILENTLY')) {
3127 notify("An error occurred while backing up quiz categories");
3129 else {
3130 $errorstr = "An error occurred while backing up quiz categories";
3131 return false;
3136 //Print logs if selected
3137 if ($status) {
3138 if ($preferences->backup_logs) {
3139 if (!defined('BACKUP_SILENTLY')) {
3140 echo "<li>".get_string("writingloginfo").'</li>';
3142 if (!$status = backup_log_info($backup_file,$preferences)) {
3143 if (!defined('BACKUP_SILENTLY')) {
3144 notify("An error occurred while backing up log info");
3146 else {
3147 $errorstr = "An error occurred while backing up log info";
3148 return false;
3154 //Print scales info
3155 if ($status) {
3156 if (!defined('BACKUP_SILENTLY')) {
3157 echo "<li>".get_string("writingscalesinfo").'</li>';
3159 if (!$status = backup_scales_info($backup_file,$preferences)) {
3160 if (!defined('BACKUP_SILENTLY')) {
3161 notify("An error occurred while backing up scales");
3163 else {
3164 $errorstr = "An error occurred while backing up scales";
3165 return false;
3170 //Print groups info
3171 if ($status) {
3172 if (!defined('BACKUP_SILENTLY')) {
3173 echo "<li>".get_string("writinggroupsinfo").'</li>';
3175 if (!$status = backup_groups_info($backup_file,$preferences)) {
3176 if (!defined('BACKUP_SILENTLY')) {
3177 notify("An error occurred while backing up groups");
3179 else {
3180 $errostr = "An error occurred while backing up groups";
3181 return false;
3186 //Print groupings info
3187 if ($status) {
3188 if (!defined('BACKUP_SILENTLY')) {
3189 echo "<li>".get_string("writinggroupingsinfo").'</li>';
3191 if (!$status = backup_groupings_info($backup_file,$preferences)) {
3192 if (!defined('BACKUP_SILENTLY')) {
3193 notify("An error occurred while backing up groupings");
3195 else {
3196 $errorstr = "An error occurred while backing up groupings";
3197 return false;
3202 //Print groupings_groups info
3203 if ($status) {
3204 if (!defined('BACKUP_SILENTLY')) {
3205 echo "<li>".get_string("writinggroupingsgroupsinfo").'</li>';
3207 if (!$status = backup_groupings_groups_info($backup_file,$preferences)) {
3208 if (!defined('BACKUP_SILENTLY')) {
3209 notify("An error occurred while backing up groupings groups");
3211 else {
3212 $errorstr = "An error occurred while backing up groupings groups";
3213 return false;
3218 //Print events info
3219 if ($status) {
3220 if (!defined('BACKUP_SILENTLY')) {
3221 echo "<li>".get_string("writingeventsinfo").'</li>';
3223 if (!$status = backup_events_info($backup_file,$preferences)) {
3224 if (!defined('BACKUP_SILENTLY')) {
3225 notify("An error occurred while backing up events");
3227 else {
3228 $errorstr = "An error occurred while backing up events";
3229 return false;
3234 //Print gradebook info
3235 if ($status) {
3236 if (!defined('BACKUP_SILENTLY')) {
3237 echo "<li>".get_string("writinggradebookinfo").'</li>';
3239 if (!$status = backup_gradebook_info($backup_file,$preferences)) {
3240 if (!defined('BACKUP_SILENTLY')) {
3241 notify("An error occurred while backing up gradebook");
3243 else {
3244 $errorstr = "An error occurred while backing up gradebook";
3245 return false;
3250 //Module info, this unique function makes all the work!!
3251 //db export and module fileis copy
3252 if ($status) {
3253 $mods_to_backup = false;
3254 //Check if we have any mod to backup
3255 foreach ($preferences->mods as $module) {
3256 if ($module->backup) {
3257 $mods_to_backup = true;
3260 //If we have to backup some module
3261 if ($mods_to_backup) {
3262 if (!defined('BACKUP_SILENTLY')) {
3263 echo "<li>".get_string("writingmoduleinfo");
3265 //Start modules tag
3266 if (!$status = backup_modules_start ($backup_file,$preferences)) {
3267 if (!defined('BACKUP_SILENTLY')) {
3268 notify("An error occurred while backing up module info");
3270 else {
3271 $errorstr = "An error occurred while backing up module info";
3272 return false;
3275 //Open ul for module list
3276 if (!defined('BACKUP_SILENTLY')) {
3277 echo "<ul>";
3279 //Iterate over modules and call backup
3280 foreach ($preferences->mods as $module) {
3281 if ($module->backup and $status) {
3282 if (!defined('BACKUP_SILENTLY')) {
3283 echo "<li>".get_string("modulenameplural",$module->name).'</li>';
3285 if (!$status = backup_module($backup_file,$preferences,$module->name)) {
3286 if (!defined('BACKUP_SILENTLY')) {
3287 notify("An error occurred while backing up '$module->name'");
3289 else {
3290 $errorstr = "An error occurred while backing up '$module->name'";
3291 return false;
3296 //Close ul for module list
3297 if (!defined('BACKUP_SILENTLY')) {
3298 echo "</ul></li>";
3300 //Close modules tag
3301 if (!$status = backup_modules_end ($backup_file,$preferences)) {
3302 if (!defined('BACKUP_SILENTLY')) {
3303 notify("An error occurred while finishing the module backups");
3305 else {
3306 $errorstr = "An error occurred while finishing the module backups";
3307 return false;
3313 //Backup course format data, if any.
3314 if (!defined('BACKUP_SILENTLY')) {
3315 echo '<li>'.get_string("courseformatdata").'</li>';
3317 if($status) {
3318 if (!$status = backup_format_data($backup_file,$preferences)) {
3319 if (!defined('BACKUP_SILENTLY')) {
3320 notify("An error occurred while backing up the course format data");
3322 else {
3323 $errorstr = "An error occurred while backing up the course format data";
3324 return false;
3329 //Prints course end
3330 if ($status) {
3331 if (!$status = backup_course_end($backup_file,$preferences)) {
3332 if (!defined('BACKUP_SILENTLY')) {
3333 notify("An error occurred while closing the course backup");
3335 else {
3336 $errorstr = "An error occurred while closing the course backup";
3337 return false;
3341 //Close the xml file and xml data
3342 if ($backup_file) {
3343 backup_close_xml($backup_file);
3346 //End xml contents (close ul)
3347 if (!defined('BACKUP_SILENTLY')) {
3348 echo "</ul></li>";
3352 //Now, if selected, copy user files
3353 if ($status) {
3354 if ($preferences->backup_user_files) {
3355 if (!defined('BACKUP_SILENTLY')) {
3356 echo "<li>".get_string("copyinguserfiles").'</li>';
3358 if (!$status = backup_copy_user_files ($preferences)) {
3359 if (!defined('BACKUP_SILENTLY')) {
3360 notify("An error occurred while copying user files");
3362 else {
3363 $errorstr = "An error occurred while copying user files";
3364 return false;
3370 //Now, if selected, copy course files
3371 if ($status) {
3372 if ($preferences->backup_course_files) {
3373 if (!defined('BACKUP_SILENTLY')) {
3374 echo "<li>".get_string("copyingcoursefiles").'</li>';
3376 if (!$status = backup_copy_course_files ($preferences)) {
3377 if (!defined('BACKUP_SILENTLY')) {
3378 notify("An error occurred while copying course files");
3380 else {
3381 $errorstr = "An error occurred while copying course files";
3382 return false;
3387 //Now, if selected, copy site files
3388 if ($status) {
3389 if ($preferences->backup_site_files) {
3390 if (!defined('BACKUP_SILENTLY')) {
3391 echo "<li>".get_string("copyingsitefiles").'</li>';
3393 if (!$status = backup_copy_site_files ($preferences)) {
3394 if (!defined('BACKUP_SILENTLY')) {
3395 notify("An error occurred while copying site files");
3397 else {
3398 $errorstr = "An error occurred while copying site files";
3399 return false;
3404 //Now, zip all the backup directory contents
3405 if ($status) {
3406 if (!defined('BACKUP_SILENTLY')) {
3407 echo "<li>".get_string("zippingbackup").'</li>';
3409 if (!$status = backup_zip ($preferences)) {
3410 if (!defined('BACKUP_SILENTLY')) {
3411 notify("An error occurred while zipping the backup");
3413 else {
3414 $errorstr = "An error occurred while zipping the backup";
3415 return false;
3420 //Now, copy the zip file to course directory
3421 if ($status) {
3422 if (!defined('BACKUP_SILENTLY')) {
3423 echo "<li>".get_string("copyingzipfile").'</li>';
3425 if (!$status = copy_zip_to_course_dir ($preferences)) {
3426 if (!defined('BACKUP_SILENTLY')) {
3427 notify("An error occurred while copying the zip file to the course directory");
3429 else {
3430 $errorstr = "An error occurred while copying the zip file to the course directory";
3431 return false;
3436 //Now, clean temporary data (db and filesystem)
3437 if ($status) {
3438 if (!defined('BACKUP_SILENTLY')) {
3439 echo "<li>".get_string("cleaningtempdata").'</li>';
3441 if (!$status = clean_temp_data ($preferences)) {
3442 if (!defined('BACKUP_SILENTLY')) {
3443 notify("An error occurred while cleaning up temporary data");
3445 else {
3446 $errorstr = "An error occurred while cleaning up temporary data";
3447 return false;
3452 return $status;
3456 * This function calculates the "backup" part of the file name
3457 * from lang files. Used both in manual and scheduled backups
3459 * @param object $course course object
3460 * @return string "backup" part of the filename
3462 function backup_get_backup_string($course) {
3464 /// Calculate the backup word
3465 /// Take off some characters in the filename !!
3466 $takeoff = array(" ", ":", "/", "\\", "|");
3467 $backup_word = str_replace($takeoff,"_",moodle_strtolower(get_string("backupfilename")));
3468 /// If non-translated, use "backup"
3469 if (substr($backup_word,0,1) == "[") {
3470 $backup_word= "backup";
3473 return $backup_word;
3477 * This function generates the default zipfile name for a backup
3478 * based on the course shortname
3480 * @param object $course course object
3481 * @return string filename (excluding path information)
3483 function backup_get_zipfile_name($course) {
3485 //Calculate the backup word
3486 $backup_word = backup_get_backup_string($course);
3488 //Calculate the date format string
3489 $backup_date_format = str_replace(" ","_",get_string("backupnameformat"));
3490 //If non-translated, use "%Y%m%d-%H%M"
3491 if (substr($backup_date_format,0,1) == "[") {
3492 $backup_date_format = "%%Y%%m%%d-%%H%%M";
3495 //Calculate the shortname
3496 $backup_shortname = clean_filename($course->shortname);
3497 if (empty($backup_shortname) or $backup_shortname == '_' ) {
3498 $backup_shortname = $course->id;
3501 //Calculate the final backup filename
3502 //The backup word
3503 $backup_name = $backup_word."-";
3504 //The shortname
3505 $backup_name .= moodle_strtolower($backup_shortname)."-";
3506 //The date format
3507 $backup_name .= userdate(time(),$backup_date_format,99,false);
3508 //The extension
3509 $backup_name .= ".zip";
3510 //And finally, clean everything
3511 $backup_name = clean_filename($backup_name);
3513 return $backup_name;
3517 * This function generates the common file substring for a course
3518 * used to keep n copies by the scheduled backup
3520 * @param object $course course object
3521 * @return string common part of filename in backups of this course
3523 function backup_get_keep_name($course) {
3525 //Calculate the backup word
3526 $backup_word = backup_get_backup_string($course);
3528 //Calculate the shortname
3529 $backup_shortname = clean_filename($course->shortname);
3530 if (empty($backup_shortname) or $backup_shortname == '_' ) {
3531 $backup_shortname = $course->id;
3534 $keep_name = $backup_word . "-" . moodle_strtolower($backup_shortname)."-";
3535 $keep_name = clean_filename($keep_name);
3537 return $keep_name;
3540 * This function adds on the standard items to the preferences
3541 * Like moodle version and backup version
3543 * @param object $preferences existing preferences object.
3544 * (passed by reference)
3546 function backup_add_static_preferences(&$preferences) {
3547 global $CFG;
3548 $preferences->moodle_version = $CFG->version;
3549 $preferences->moodle_release = $CFG->release;
3550 $preferences->backup_version = $CFG->backup_version;
3551 $preferences->backup_release = $CFG->backup_release;