MDL-22164 backup - clean important parts of old code. Leaving rest for reference
[moodle.git] / backup / restorelib.php
1 <?php
2     //Functions used in restore
4     require_once($CFG->libdir.'/gradelib.php');
6 /**
7  * Group backup/restore constants, 0.
8  */
9 define('RESTORE_GROUPS_NONE', 0);
11 /**
12  * Group backup/restore constants, 1.
13  */
14 define('RESTORE_GROUPS_ONLY', 1);
16 /**
17  * Group backup/restore constants, 2.
18  */
19 define('RESTORE_GROUPINGS_ONLY', 2);
21 /**
22  * Group backup/restore constants, course/all.
23  */
24 define('RESTORE_GROUPS_GROUPINGS', 3);
26     //This function unzips a zip file in the same directory that it is
27     //It automatically uses pclzip or command line unzip
28     function restore_unzip ($file) {
30         return unzip_file($file, '', false);
32     }
34     //This function checks if moodle.xml seems to be a valid xml file
35     //(exists, has an xml header and a course main tag
36     function restore_check_moodle_file ($file) {
38         $status = true;
40         //Check if it exists
41         if ($status = is_file($file)) {
42             //Open it and read the first 200 bytes (chars)
43             $handle = fopen ($file, "r");
44             $first_chars = fread($handle,200);
45             $status = fclose ($handle);
46             //Chek if it has the requires strings
47             if ($status) {
48                 $status = strpos($first_chars,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
49                 if ($status !== false) {
50                     $status = strpos($first_chars,"<MOODLE_BACKUP>");
51                 }
52             }
53         }
55         return $status;
56     }
58     //This function iterates over all modules in backup file, searching for a
59     //MODNAME_refresh_events() to execute. Perhaps it should ve moved to central Moodle...
60     function restore_refresh_events($restore) {
62         global $CFG;
63         $status = true;
65         //Take all modules in backup
66         $modules = $restore->mods;
67         //Iterate
68         foreach($modules as $name => $module) {
69             //Only if the module is being restored
70             if (isset($module->restore) && $module->restore == 1) {
71                 //Include module library
72                 include_once("$CFG->dirroot/mod/$name/lib.php");
73                 //If module_refresh_events exists
74                 $function_name = $name."_refresh_events";
75                 if (function_exists($function_name)) {
76                     $status = $function_name($restore->course_id);
77                 }
78             }
79         }
80         return $status;
81     }
83     //This function makes all the necessary calls to xxxx_decode_content_links_caller()
84     //function in each module/block/course format..., passing them the desired contents to be decoded
85     //from backup format to destination site/course in order to mantain inter-activities
86     //working in the backup/restore process
87     function restore_decode_content_links($restore) {
88         global $CFG, $DB;
90         $status = true;
92         if (!defined('RESTORE_SILENTLY')) {
93             echo "<ul>";
94         }
96         // Recode links in the course summary.
97         if (!defined('RESTORE_SILENTLY')) {
98             echo '<li>' . get_string('from') . ' ' . get_string('course');
99         }
100         $course = $DB->get_record('course', array('id'=>$restore->course_id), 'id,summary');
101         $coursesummary = backup_todb($course->summary); // Exception: Process FILEPHP (not available when restored) MDL-18222
102         $coursesummary = restore_decode_content_links_worker($coursesummary, $restore);
103         if ($coursesummary != $course->summary) {
104             $course->summary = $coursesummary;
105             $DB->update_record('course', $course);
106         }
107         if (!defined('RESTORE_SILENTLY')) {
108             echo '</li>';
109         }
111         // Recode links in section summaries.
112         $sections = $DB->get_records('course_sections', array('course'=>$restore->course_id), 'id', 'id,summary');
113         if ($sections) {
114             if (!defined('RESTORE_SILENTLY')) {
115                 echo '<li>' . get_string('from') . ' ' . get_string('sections');
116             }
117             foreach ($sections as $section) {
118                 $sectionsummary = restore_decode_content_links_worker($section->summary, $restore);
119                 if ($sectionsummary != $section->summary) {
120                     $section->summary = $sectionsummary;
121                     $DB->update_record('course_sections', $section);
122                 }
123             }
124             if (!defined('RESTORE_SILENTLY')) {
125                 echo '</li>';
126             }
127         }
129         // Restore links in modules.
130         foreach ($restore->mods as $name => $info) {
131             //If the module is being restored
132             if (isset($info->restore) && $info->restore == 1) {
133                 //Check if the xxxx_decode_content_links_caller exists
134                 include_once("$CFG->dirroot/mod/$name/restorelib.php");
135                 $function_name = $name."_decode_content_links_caller";
136                 if (function_exists($function_name)) {
137                     if (!defined('RESTORE_SILENTLY')) {
138                         echo "<li>".get_string ("from")." ".get_string("modulenameplural",$name);
139                     }
140                     $status = $function_name($restore) && $status;
141                     if (!defined('RESTORE_SILENTLY')) {
142                         echo '</li>';
143                     }
144                 }
145             }
146         }
148         // For the course format call its decode_content_links method (if it exists)
149         $format = $DB->get_field('course','format', array('id'=>$restore->course_id));
150         if (file_exists("$CFG->dirroot/course/format/$format/restorelib.php")) {
151             include_once("$CFG->dirroot/course/format/$format/restorelib.php");
152             $function_name = $format.'_decode_format_content_links_caller';
154             if (function_exists($function_name)) {
155                 if (!defined('RESTORE_SILENTLY')) {
156                     echo "<li>".get_string ("from")." ".get_string("format").' '.$format;
157                 }
158                 $status = $function_name($restore);
159                 if (!defined('RESTORE_SILENTLY')) {
160                     echo '</li>';
161                 }
162             }
163         }
165         // Process all html text also in blocks too
166         if (!defined('RESTORE_SILENTLY')) {
167             echo '<li>'.get_string ('from').' '.get_string('blocks');
168         }
170         if ($blocks = $DB->get_records('block', array('visible'=>1))) {
171             foreach ($blocks as $block) {
172                 if ($blockobject = block_instance($block->name)) {
173                     $blockobject->decode_content_links_caller($restore);
174                 }
175             }
176         }
178         if (!defined('RESTORE_SILENTLY')) {
179             echo '</li>';
180         }
182         // Restore links in questions.
183         require_once("$CFG->dirroot/question/restorelib.php");
184         if (!defined('RESTORE_SILENTLY')) {
185             echo '<li>' . get_string('from') . ' ' . get_string('questions', 'quiz');
186         }
187         $status = question_decode_content_links_caller($restore) && $status;
188         if (!defined('RESTORE_SILENTLY')) {
189             echo '</li>';
190         }
192         if (!defined('RESTORE_SILENTLY')) {
193             echo "</ul>";
194         }
196         return $status;
197     }
199     //This function is called from all xxxx_decode_content_links_caller(),
200     //its task is to ask all modules (maybe other linkable objects) to restore
201     //links to them.
202     function restore_decode_content_links_worker($content,$restore) {
203         global $CFG, $DB;
205         foreach($restore->mods as $name => $info) {
206             $function_name = $name."_decode_content_links";
207             if (function_exists($function_name)) {
208                 $content = $function_name($content,$restore);
209             }
210         }
212         // For the current format, call decode_format_content_links if it exists
213         static $format_function_name;
214         if (!isset($format_function_name)) {
215             $format_function_name = false;
216             if ($format = $DB->get_field('course','format', array('id'=>$restore->course_id))) {
217                 if (file_exists("$CFG->dirroot/course/format/$format/restorelib.php")) {
218                     include_once("$CFG->dirroot/course/format/$format/restorelib.php");
219                     $function_name = $format.'_decode_format_content_links';
220                     if (function_exists($function_name)) {
221                         $format_function_name = $function_name;
222                     }
223                 }
224             }
225         }
226         // If the above worked - then we have a function to call
227         if ($format_function_name) {
228             $content = $format_function_name($content, $restore);
229         }
231         // For each block, call its encode_content_links method
232         static $blockobjects = null;
233         if (!isset($blockobjects)) {
234             $blockobjects = array();
235             if ($blocks = $DB->get_records('block', array('visible'=>1))) {
236                 foreach ($blocks as $block) {
237                     if ($blockobject = block_instance($block->name)) {
238                         $blockobjects[] = $blockobject;
239                     }
240                 }
241             }
242         }
244         foreach ($blockobjects as $blockobject) {
245             $content = $blockobject->decode_content_links($content,$restore);
246         }
248         return $content;
249     }
252     //This function read the xml file and store it data from the info zone in an object
253     function restore_read_xml_info ($xml_file) {
255         //We call the main read_xml function, with $todo = INFO
256         $info = restore_read_xml ($xml_file,"INFO",false);
258         return $info;
259     }
261     //This function read the xml file and store it data from the course header zone in an object
262     function restore_read_xml_course_header ($xml_file) {
264         //We call the main read_xml function, with $todo = COURSE_HEADER
265         $info = restore_read_xml ($xml_file,"COURSE_HEADER",false);
267         return $info;
268     }
270     //This function read the xml file and store its data from the blocks in a object
271     function restore_read_xml_blocks ($restore, $xml_file) {
273         //We call the main read_xml function, with $todo = BLOCKS
274         $info = restore_read_xml ($xml_file,'BLOCKS',$restore);
276         return $info;
277     }
279     //This function read the xml file and store its data from the sections in a object
280     function restore_read_xml_sections ($xml_file) {
282         //We call the main read_xml function, with $todo = SECTIONS
283         $info = restore_read_xml ($xml_file,"SECTIONS",false);
285         return $info;
286     }
288     //This function read the xml file and store its data from the course format in an object
289     function restore_read_xml_formatdata ($xml_file) {
291         //We call the main read_xml function, with $todo = FORMATDATA
292         $info = restore_read_xml ($xml_file,'FORMATDATA',false);
294         return $info;
295     }
297     //This function read the xml file and store its data from the metacourse in a object
298     function restore_read_xml_metacourse ($xml_file) {
300         //We call the main read_xml function, with $todo = METACOURSE
301         $info = restore_read_xml ($xml_file,"METACOURSE",false);
303         return $info;
304     }
306     //This function read the xml file and store its data from the gradebook in a object
307     function restore_read_xml_gradebook ($restore, $xml_file) {
309         //We call the main read_xml function, with $todo = GRADEBOOK
310         $info = restore_read_xml ($xml_file,"GRADEBOOK",$restore);
312         return $info;
313     }
315     //This function read the xml file and store its data from the users in
316     //backup_ids->info db (and user's id in $info)
317     function restore_read_xml_users ($restore,$xml_file) {
319         //We call the main read_xml function, with $todo = USERS
320         $info = restore_read_xml ($xml_file,"USERS",$restore);
322         return $info;
323     }
325     //This function read the xml file and store its data from the messages in
326     //backup_ids->message backup_ids->message_read and backup_ids->contact and db (and their counters in info)
327     function restore_read_xml_messages ($restore,$xml_file) {
329         //We call the main read_xml function, with $todo = MESSAGES
330         $info = restore_read_xml ($xml_file,"MESSAGES",$restore);
332         return $info;
333     }
335     //This function read the xml file and store its data from the blogs in
336     //backup_ids->blog and backup_ids->blog_tag and db (and their counters in info)
337     function restore_read_xml_blogs ($restore,$xml_file) {
339         //We call the main read_xml function, with $todo = BLOGS
340         $info = restore_read_xml ($xml_file,"BLOGS",$restore);
342         return $info;
343     }
346     //This function read the xml file and store its data from the questions in
347     //backup_ids->info db (and category's id in $info)
348     function restore_read_xml_questions ($restore,$xml_file) {
350         //We call the main read_xml function, with $todo = QUESTIONS
351         $info = restore_read_xml ($xml_file,"QUESTIONS",$restore);
353         return $info;
354     }
356     //This function read the xml file and store its data from the scales in
357     //backup_ids->info db (and scale's id in $info)
358     function restore_read_xml_scales ($restore,$xml_file) {
360         //We call the main read_xml function, with $todo = SCALES
361         $info = restore_read_xml ($xml_file,"SCALES",$restore);
363         return $info;
364     }
366     //This function read the xml file and store its data from the groups in
367     //backup_ids->info db (and group's id in $info)
368     function restore_read_xml_groups ($restore,$xml_file) {
370         //We call the main read_xml function, with $todo = GROUPS
371         $info = restore_read_xml ($xml_file,"GROUPS",$restore);
373         return $info;
374     }
376     //This function read the xml file and store its data from the groupings in
377     //backup_ids->info db (and grouping's id in $info)
378     function restore_read_xml_groupings ($restore,$xml_file) {
380         //We call the main read_xml function, with $todo = GROUPINGS
381         $info = restore_read_xml ($xml_file,"GROUPINGS",$restore);
383         return $info;
384     }
386     //This function read the xml file and store its data from the groupings in
387     //backup_ids->info db (and grouping's id in $info)
388     function restore_read_xml_groupings_groups ($restore,$xml_file) {
390         //We call the main read_xml function, with $todo = GROUPINGS
391         $info = restore_read_xml ($xml_file,"GROUPINGSGROUPS",$restore);
393         return $info;
394     }
396     //This function read the xml file and store its data from the events (course) in
397     //backup_ids->info db (and event's id in $info)
398     function restore_read_xml_events ($restore,$xml_file) {
400         //We call the main read_xml function, with $todo = EVENTS
401         $info = restore_read_xml ($xml_file,"EVENTS",$restore);
403         return $info;
404     }
406     //This function read the xml file and store its data from the modules in
407     //backup_ids->info
408     function restore_read_xml_modules ($restore,$xml_file) {
410         //We call the main read_xml function, with $todo = MODULES
411         $info = restore_read_xml ($xml_file,"MODULES",$restore);
413         return $info;
414     }
416     //This function read the xml file and store its data from the logs in
417     //backup_ids->info
418     function restore_read_xml_logs ($restore,$xml_file) {
420         //We call the main read_xml function, with $todo = LOGS
421         $info = restore_read_xml ($xml_file,"LOGS",$restore);
423         return $info;
424     }
426     function restore_read_xml_roles ($xml_file) {
427         //We call the main read_xml function, with $todo = ROLES
428         $info = restore_read_xml ($xml_file,"ROLES",false);
430         return $info;
431     }
433     //This function prints the contents from the info parammeter passed
434     function restore_print_info ($info) {
436         global $CFG, $OUTPUT;
438         $status = true;
439         if ($info) {
440             $table = new html_table();
441             //This is tha align to every ingo table
442             $table->align = array ("right","left");
443             //This is the nowrap clause
444             $table->wrap = array ("","nowrap");
445             //The width
446             $table->width = "70%";
447             //Put interesting info in table
448             //The backup original name
449             $tab[0][0] = "<b>".get_string("backuporiginalname").":</b>";
450             $tab[0][1] = $info->backup_name;
451             //The moodle version
452             $tab[1][0] = "<b>".get_string("moodleversion").":</b>";
453             $tab[1][1] = $info->backup_moodle_release." (".$info->backup_moodle_version.")";
454             //The backup version
455             $tab[2][0] = "<b>".get_string("backupversion").":</b>";
456             $tab[2][1] = $info->backup_backup_release." (".$info->backup_backup_version.")";
457             //The backup date
458             $tab[3][0] = "<b>".get_string("backupdate").":</b>";
459             $tab[3][1] = userdate($info->backup_date);
460             //Is this the same Moodle install?
461             if (!empty($info->original_siteidentifier)) {
462                 $tab[4][0] = "<b>".get_string("backupfromthissite").":</b>";
463                 if (backup_is_same_site($info)) {
464                     $tab[4][1] = get_string('yes');
465                 } else {
466                     $tab[4][1] = get_string('no');
467                 }
468             }
469             //Print title
470             echo $OUTPUT->heading(get_string("backup").":");
471             $table->data = $tab;
472             //Print backup general info
473             echo html_writer::table($table);
475             if ($info->backup_backup_version <= 2005070500) {
476                  echo $OUTPUT->notification(get_string('backupnonisowarning'));  // Message informing that this backup may not work!
477             }
479             //Now backup contents in another table
480             $tab = array();
481             //First mods info
482             $mods = $info->mods;
483             $elem = 0;
484             foreach ($mods as $key => $mod) {
485                 $tab[$elem][0] = "<b>".get_string("modulenameplural",$key).":</b>";
486                 if ($mod->backup == "false") {
487                     $tab[$elem][1] = get_string("notincluded");
488                 } else {
489                     if ($mod->userinfo == "true") {
490                         $tab[$elem][1] = get_string("included")." ".get_string("withuserdata");
491                     } else {
492                         $tab[$elem][1] = get_string("included")." ".get_string("withoutuserdata");
493                     }
494                     if (isset($mod->instances) && is_array($mod->instances) && count($mod->instances)) {
495                         foreach ($mod->instances as $instance) {
496                             if ($instance->backup) {
497                                 $elem++;
498                                 $tab[$elem][0] = $instance->name;
499                                 if ($instance->userinfo == 'true') {
500                                     $tab[$elem][1] = get_string("included")." ".get_string("withuserdata");
501                                 } else {
502                                     $tab[$elem][1] = get_string("included")." ".get_string("withoutuserdata");
503                                 }
504                             }
505                         }
506                     }
507                 }
508                 $elem++;
509             }
510             //Metacourse info
511             $tab[$elem][0] = "<b>".get_string("metacourse").":</b>";
512             if ($info->backup_metacourse == "true") {
513                 $tab[$elem][1] = get_string("yes");
514             } else {
515                 $tab[$elem][1] = get_string("no");
516             }
517             $elem++;
518             //Users info
519             $tab[$elem][0] = "<b>".get_string("users").":</b>";
520             $tab[$elem][1] = get_string($info->backup_users);
521             $elem++;
522             //Logs info
523             $tab[$elem][0] = "<b>".get_string("logs").":</b>";
524             if ($info->backup_logs == "true") {
525                 $tab[$elem][1] = get_string("yes");
526             } else {
527                 $tab[$elem][1] = get_string("no");
528             }
529             $elem++;
530             //User Files info
531             $tab[$elem][0] = "<b>".get_string("userfiles").":</b>";
532             if ($info->backup_user_files == "true") {
533                 $tab[$elem][1] = get_string("yes");
534             } else {
535                 $tab[$elem][1] = get_string("no");
536             }
537             $elem++;
538             //Course Files info
539             $tab[$elem][0] = "<b>".get_string("coursefiles").":</b>";
540             if ($info->backup_course_files == "true") {
541                 $tab[$elem][1] = get_string("yes");
542             } else {
543                 $tab[$elem][1] = get_string("no");
544             }
545             $elem++;
546             //site Files info
547             $tab[$elem][0] = "<b>".get_string("sitefiles").":</b>";
548             if (isset($info->backup_site_files) && $info->backup_site_files == "true") {
549                 $tab[$elem][1] = get_string("yes");
550             } else {
551                 $tab[$elem][1] = get_string("no");
552             }
553             $elem++;
554             //gradebook history info
555             $tab[$elem][0] = "<b>".get_string('gradebookhistories', 'grades').":</b>";
556             if (isset($info->gradebook_histories) && $info->gradebook_histories == "true") {
557                 $tab[$elem][1] = get_string("yes");
558             } else {
559                 $tab[$elem][1] = get_string("no");
560             }
561             $elem++;
562             //Messages info (only showed if present)
563             if ($info->backup_messages == 'true') {
564                 $tab[$elem][0] = "<b>".get_string('messages','message').":</b>";
565                 $tab[$elem][1] = get_string('yes');
566                 $elem++;
567             } else {
568                 //Do nothing
569             }
570             $elem++;
571             //Blogs info (only showed if present)
572             if (isset($info->backup_blogs) && $info->backup_blogs == 'true') {
573                 $tab[$elem][0] = "<b>".get_string('blogs','blog').":</b>";
574                 $tab[$elem][1] = get_string('yes');
575                 $elem++;
576             } else {
577                 //Do nothing
578             }
579             $table->data = $tab;
580             //Print title
581             echo $OUTPUT->heading(get_string("backupdetails").":");
582             //Print backup general info
583             echo html_writer::table($table);
584         } else {
585             $status = false;
586         }
588         return $status;
589     }
591     //This function prints the contents from the course_header parammeter passed
592     function restore_print_course_header ($course_header) {
593         global $OUTPUT;
594         $status = true;
595         if ($course_header) {
596             $table = new html_table();
597             //This is tha align to every ingo table
598             $table->align = array ("right","left");
599             //The width
600             $table->width = "70%";
601             //Put interesting course header in table
602             //The course name
603             $tab[0][0] = "<b>".get_string("name").":</b>";
604             $tab[0][1] = $course_header->course_fullname." (".$course_header->course_shortname.")";
605             //The course summary
606             $tab[1][0] = "<b>".get_string("summary").":</b>";
607             $tab[1][1] = $course_header->course_summary;
608             $table->data = $tab;
609             //Print title
610             echo $OUTPUT->heading(get_string("course").":");
611             //Print backup course header info
612             echo html_writer::table($table);
613         } else {
614             $status = false;
615         }
616         return $status;
617     }
619    /**
620     * Given one user object (from backup file), perform all the neccesary
621     * checks is order to decide how that user will be handled on restore.
622     *
623     * Note the function requires $user->mnethostid to be already calculated
624     * so it's caller responsibility to set it
625     *
626     * This function is used both by @restore_precheck_users() and
627     * @restore_create_users() to get consistent results in both places
628     *
629     * It returns:
630     *   - one user object (from DB), if match has been found and user will be remapped
631     *   - boolean true if the user needs to be created
632     *   - boolean false if some conflict happened and the user cannot be handled
633     *
634     * Each test is responsible for returning its results and interrupt
635     * execution. At the end, boolean true (user needs to be created) will be
636     * returned if no test has interrupted that.
637     *
638     * Here it's the logic applied, keep it updated:
639     *
640     *  If restoring users from same site backup:
641     *      1A - Normal check: If match by id and username and mnethost  => ok, return target user
642     *      1B - Handle users deleted in DB and "alive" in backup file:
643     *           If match by id and mnethost and user is deleted in DB and
644     *           (match by username LIKE 'backup_email.%' or by non empty email = md5(username)) => ok, return target user
645     *      1C - Handle users deleted in backup file and "alive" in DB:
646     *           If match by id and mnethost and user is deleted in backup file
647     *           and match by email = email_without_time(backup_email) => ok, return target user
648     *      1D - Conflict: If match by username and mnethost and doesn't match by id => conflict, return false
649     *      1E - None of the above, return true => User needs to be created
650     *
651     *  if restoring from another site backup (cannot match by id here, replace it by email/firstaccess combination):
652     *      2A - Normal check: If match by username and mnethost and (email or non-zero firstaccess) => ok, return target user
653     *      2B - Handle users deleted in DB and "alive" in backup file:
654     *           2B1 - If match by mnethost and user is deleted in DB and not empty email = md5(username) and
655     *                 (username LIKE 'backup_email.%' or non-zero firstaccess) => ok, return target user
656     *           2B2 - If match by mnethost and user is deleted in DB and
657     *                 username LIKE 'backup_email.%' and non-zero firstaccess) => ok, return target user
658     *                 (to cover situations were md5(username) wasn't implemented on delete we requiere both)
659     *      2C - Handle users deleted in backup file and "alive" in DB:
660     *           If match mnethost and user is deleted in backup file
661     *           and by email = email_without_time(backup_email) and non-zero firstaccess=> ok, return target user
662     *      2D - Conflict: If match by username and mnethost and not by (email or non-zero firstaccess) => conflict, return false
663     *      2E - None of the above, return true => User needs to be created
664     *
665     * Note: for DB deleted users email is stored in username field, hence we
666     *       are looking there for emails. See delete_user()
667     * Note: for DB deleted users md5(username) is stored *sometimes* in the email field,
668     *       hence we are looking there for usernames if not empty. See delete_user()
669     */
670     function restore_check_user($restore, $user) {
671         global $CFG, $DB;
673         // Verify mnethostid is set, return error if not
674         // it's parent responsibility to define that before
675         // arriving here
676         if (empty($user->mnethostid)) {
677             debugging("restore_check_user() wrong use, mnethostid not set for user $user->username", DEBUG_DEVELOPER);
678             return false;
679         }
681         // Handle checks from same site backups
682         if (backup_is_same_site($restore) && empty($CFG->forcedifferentsitecheckingusersonrestore)) {
684             // 1A - If match by id and username and mnethost => ok, return target user
685             if ($rec = $DB->get_record('user', array('id'=>$user->id, 'username'=>$user->username, 'mnethostid'=>$user->mnethostid))) {
686                 return $rec; // Matching user found, return it
687             }
689             // 1B - Handle users deleted in DB and "alive" in backup file
690             // Note: for DB deleted users email is stored in username field, hence we
691             //       are looking there for emails. See delete_user()
692             // Note: for DB deleted users md5(username) is stored *sometimes* in the email field,
693             //       hence we are looking there for usernames if not empty. See delete_user()
694             // If match by id and mnethost and user is deleted in DB and
695             // match by username LIKE 'backup_email.%' or by non empty email = md5(username) => ok, return target user
696             if ($rec = $DB->get_record_sql("SELECT *
697                                               FROM {user} u
698                                              WHERE id = ?
699                                                AND mnethostid = ?
700                                                AND deleted = 1
701                                                AND (
702                                                        username LIKE ?
703                                                     OR (
704                                                            ".$DB->sql_isnotempty('user', 'email', false, false)."
705                                                        AND email = ?
706                                                        )
707                                                    )",
708                                            array($user->id, $user->mnethostid, $user->email.'.%', md5($user->username)))) {
709                 return $rec; // Matching user, deleted in DB found, return it
710             }
712             // 1C - Handle users deleted in backup file and "alive" in DB
713             // If match by id and mnethost and user is deleted in backup file
714             // and match by email = email_without_time(backup_email) => ok, return target user
715             if ($user->deleted) {
716                 // Note: for DB deleted users email is stored in username field, hence we
717                 //       are looking there for emails. See delete_user()
718                 // Trim time() from email
719                 $trimemail = preg_replace('/(.*?)\.[0-9]+.?$/', '\\1', $user->username);
720                 if ($rec = $DB->get_record_sql("SELECT *
721                                                   FROM {user} u
722                                                  WHERE id = ?
723                                                    AND mnethostid = ?
724                                                    AND email = ?",
725                                                array($user->id, $user->mnethostid, $trimemail))) {
726                     return $rec; // Matching user, deleted in backup file found, return it
727                 }
728             }
730             // 1D - If match by username and mnethost and doesn't match by id => conflict, return false
731             if ($rec = $DB->get_record('user', array('username'=>$user->username, 'mnethostid'=>$user->mnethostid))) {
732                 if ($user->id != $rec->id) {
733                     return false; // Conflict, username already exists and belongs to another id
734                 }
735             }
737         // Handle checks from different site backups
738         } else {
740             // 2A - If match by username and mnethost and
741             //     (email or non-zero firstaccess) => ok, return target user
742             if ($rec = $DB->get_record_sql("SELECT *
743                                               FROM {user} u
744                                              WHERE username = ?
745                                                AND mnethostid = ?
746                                                AND (
747                                                        email = ?
748                                                     OR (
749                                                            firstaccess != 0
750                                                        AND firstaccess = ?
751                                                        )
752                                                    )",
753                                            array($user->username, $user->mnethostid, $user->email, $user->firstaccess))) {
754                 return $rec; // Matching user found, return it
755             }
757             // 2B - Handle users deleted in DB and "alive" in backup file
758             // Note: for DB deleted users email is stored in username field, hence we
759             //       are looking there for emails. See delete_user()
760             // Note: for DB deleted users md5(username) is stored *sometimes* in the email field,
761             //       hence we are looking there for usernames if not empty. See delete_user()
762             // 2B1 - If match by mnethost and user is deleted in DB and not empty email = md5(username) and
763             //       (by username LIKE 'backup_email.%' or non-zero firstaccess) => ok, return target user
764             if ($rec = $DB->get_record_sql("SELECT *
765                                               FROM {user} u
766                                              WHERE mnethostid = ?
767                                                AND deleted = 1
768                                                AND ".$DB->sql_isnotempty('user', 'email', false, false)."
769                                                AND email = ?
770                                                AND (
771                                                        username LIKE ?
772                                                     OR (
773                                                            firstaccess != 0
774                                                        AND firstaccess = ?
775                                                        )
776                                                    )",
777                                            array($user->mnethostid, md5($user->username), $user->email.'.%', $user->firstaccess))) {
778                 return $rec; // Matching user found, return it
779             }
781             // 2B2 - If match by mnethost and user is deleted in DB and
782             //       username LIKE 'backup_email.%' and non-zero firstaccess) => ok, return target user
783             //       (this covers situations where md5(username) wasn't being stored so we require both
784             //        the email & non-zero firstaccess to match)
785             if ($rec = $DB->get_record_sql("SELECT *
786                                               FROM {user} u
787                                              WHERE mnethostid = ?
788                                                AND deleted = 1
789                                                AND username LIKE ?
790                                                AND firstaccess != 0
791                                                AND firstaccess = ?",
792                                            array($user->mnethostid, $user->email.'.%', $user->firstaccess))) {
793                 return $rec; // Matching user found, return it
794             }
796             // 2C - Handle users deleted in backup file and "alive" in DB
797             // If match mnethost and user is deleted in backup file
798             // and match by email = email_without_time(backup_email) and non-zero firstaccess=> ok, return target user
799             if ($user->deleted) {
800                 // Note: for DB deleted users email is stored in username field, hence we
801                 //       are looking there for emails. See delete_user()
802                 // Trim time() from email
803                 $trimemail = preg_replace('/(.*?)\.[0-9]+.?$/', '\\1', $user->username);
804                 if ($rec = $DB->get_record_sql("SELECT *
805                                                   FROM {user} u
806                                                  WHERE mnethostid = ?
807                                                    AND email = ?
808                                                    AND firstaccess != 0
809                                                    AND firstaccess = ?",
810                                                array($user->mnethostid, $trimemail, $user->firstaccess))) {
811                     return $rec; // Matching user, deleted in backup file found, return it
812                 }
813             }
815             // 2D - If match by username and mnethost and not by (email or non-zero firstaccess) => conflict, return false
816             if ($rec = $DB->get_record_sql("SELECT *
817                                               FROM {user} u
818                                              WHERE username = ?
819                                                AND mnethostid = ?
820                                            AND NOT (
821                                                        email = ?
822                                                     OR (
823                                                            firstaccess != 0
824                                                        AND firstaccess = ?
825                                                        )
826                                                    )",
827                                            array($user->username, $user->mnethostid, $user->email, $user->firstaccess))) {
828                 return false; // Conflict, username/mnethostid already exist and belong to another user (by email/firstaccess)
829             }
830         }
832         // Arrived here, return true as the user will need to be created and no
833         // conflicts have been found in the logic above. This covers:
834         // 1E - else => user needs to be created, return true
835         // 2E - else => user needs to be created, return true
836         return true;
837     }
839    /**
840     * For all the users being restored, check if they are going to cause problems
841     * before executing the restore process itself, detecting situations like:
842     *   - conflicts preventing restore to continue - provided by @restore_check_user()
843     *   - prevent creation of users if not allowed - check some global settings/caps
844     */
845     function restore_precheck_users($xml_file, $restore, &$problems) {
846         global $CFG, $DB;
848         $status = true; // Init $status
850         // We aren't restoring users, nothing to check, allow continue
851         if ($restore->users == 2) {
852             return true;
853         }
855         // Get array of users from xml file and load them in backup_ids table
856         if (!$info = restore_read_xml_users($restore,$xml_file)) {
857             return true; // No users, nothing to check, allow continue
858         }
860         // We are going to map mnethostid, so load all the available ones
861         $mnethosts = $DB->get_records('mnet_host', array(), 'wwwroot', 'wwwroot, id');
863         // Calculate the context we are going to use for capability checking
864         if (!empty($restore->course_id)) { // Know the target (existing) course, check capabilities there
865             $context = get_context_instance(CONTEXT_COURSE, $restore->course_id);
866         } else if (!empty($restore->restore_restorecatto)) { // Know the category, check capabilities there
867             $context = get_context_instance(CONTEXT_COURSECAT, $restore->restore_restorecatto);
868         } else { // Last resort, check capabilities at system level
869             $context = get_context_instance(CONTEXT_SYSTEM);
870         }
872         // Calculate if we have perms to create users, by checking:
873         // to 'moodle/restore:createuser' and 'moodle/restore:userinfo'
874         // and also observe $CFG->disableusercreationonrestore
875         $cancreateuser = false;
876         if (has_capability('moodle/restore:createuser', $context) and
877             has_capability('moodle/restore:userinfo', $context) and
878             empty($CFG->disableusercreationonrestore)) { // Can create users
880             $cancreateuser = true;
881         }
883         // Iterate over all users, checking if they are likely to cause problems on restore
884         $counter = 0;
885         foreach ($info->users as $userid) {
886             $rec = backup_getid($restore->backup_unique_code, 'user', $userid);
887             $user = $rec->info;
889             // Find the correct mnethostid for user before performing any further check
890             if (empty($user->mnethosturl) || $user->mnethosturl === $CFG->wwwroot) {
891                 $user->mnethostid = $CFG->mnet_localhost_id;
892             } else {
893                 // fast url-to-id lookups
894                 if (isset($mnethosts[$user->mnethosturl])) {
895                     $user->mnethostid = $mnethosts[$user->mnethosturl]->id;
896                 } else {
897                     $user->mnethostid = $CFG->mnet_localhost_id;
898                 }
899             }
901             // Calculate the best way to handle this user from backup file
902             $usercheck = restore_check_user($restore, $user);
904             if (is_object($usercheck)) { // No problem, we have found one user in DB to be mapped to
905                 // Annotate it, for later process by restore_create_users(). Set new_id to mapping user->id
906                 backup_putid($restore->backup_unique_code, 'user', $userid, $usercheck->id, $user);
908             } else if ($usercheck === false) { // Found conflict, report it as problem
909                 $problems[] = get_string('restoreuserconflict', '', $user->username);
910                 $status = false;
912             } else if ($usercheck === true) { // User needs to be created, check if we are able
913                 if ($cancreateuser) { // Can create user, annotate it, for later process by restore_create_users(). Set new_id to 0
914                     backup_putid($restore->backup_unique_code, 'user', $userid, 0, $user);
916                 } else { // Cannot create user, report it as problem
918                     $problems[] = get_string('restorecannotcreateuser', '', $user->username);
919                     $status = false;
920                 }
922             } else { // Shouldn't arrive here ever, something is for sure wrong in restore_check_user()
923                 if (!defined('RESTORE_SILENTLY')) {
924                     notify('Unexpected error pre-checking user ' . s($user->username) . ' from backup file');
925                     return false;
926                 }
927             }
929             // Do some output
930             $counter++;
931             if ($counter % 10 == 0) {
932                 if (!defined('RESTORE_SILENTLY')) {
933                     echo ".";
934                     if ($counter % 200 == 0) {
935                         echo "<br />";
936                     }
937                 }
938                 backup_flush(300);
939             }
940         }
942         return $status;
943     }
945     //This function create a new course record.
946     //When finished, course_header contains the id of the new course
947     function restore_create_new_course($restore,&$course_header) {
948         global $CFG, $DB;
951         //Create the course_object
952         if ($status) {
953             $course = new object();
954             $course->category = $course_header->category->id;
955             $course->password = $course_header->course_password;
956             $course->fullname = $course_header->course_fullname;
957             $course->shortname = $course_header->course_shortname;
958             $course->idnumber = $course_header->course_idnumber;
959             $course->idnumber = ''; //$course_header->course_idnumber; // we don't want this at all.
960             $course->summary = $course_header->course_summary;
961             $course->format = $course_header->course_format;
962             $course->showgrades = $course_header->course_showgrades;
963             $course->newsitems = $course_header->course_newsitems;
964             $course->guest = $course_header->course_guest;
965             $course->startdate = $course_header->course_startdate;
966             $course->startdate += $restore->course_startdateoffset;
967             $course->numsections = $course_header->course_numsections;
968             //$course->showrecent = $course_header->course_showrecent;   INFO: This is out in 1.3
969             $course->maxbytes = $course_header->course_maxbytes;
970             $course->showreports = $course_header->course_showreports;
971             if (isset($course_header->course_groupmode)) {
972                 $course->groupmode = $course_header->course_groupmode;
973             }
974             if (isset($course_header->course_groupmodeforce)) {
975                 $course->groupmodeforce = $course_header->course_groupmodeforce;
976             }
977             if (isset($course_header->course_defaultgroupingid)) {
978                 //keep the original now - convert after groupings restored
979                 $course->defaultgroupingid = $course_header->course_defaultgroupingid;
980             }
981             $course->lang = $course_header->course_lang;
982             $course->theme = $course_header->course_theme;
983             $course->cost = $course_header->course_cost;
984             $course->currency = isset($course_header->course_currency)?$course_header->course_currency:'';
985             $course->marker = $course_header->course_marker;
986             $course->visible = $course_header->course_visible;
987             $course->hiddensections = $course_header->course_hiddensections;
988             $course->timecreated = $course_header->course_timecreated;
989             $course->timemodified = $course_header->course_timemodified;
990             $course->metacourse = $course_header->course_metacourse;
991             $course->expirynotify = isset($course_header->course_expirynotify) ? $course_header->course_expirynotify:0;
992             $course->notifystudents = isset($course_header->course_notifystudents) ? $course_header->course_notifystudents : 0;
993             $course->expirythreshold = isset($course_header->course_expirythreshold) ? $course_header->course_expirythreshold : 0;
994             $course->enrollable = isset($course_header->course_enrollable) ? $course_header->course_enrollable : 1;
995             $course->enrolstartdate = isset($course_header->course_enrolstartdate) ? $course_header->course_enrolstartdate : 0;
996             if ($course->enrolstartdate)  { //Roll course dates
997                 $course->enrolstartdate += $restore->course_startdateoffset;
998             }
999             $course->enrolenddate = isset($course_header->course_enrolenddate) ? $course_header->course_enrolenddate : 0;
1000             if ($course->enrolenddate) { //Roll course dates
1001                 $course->enrolenddate  += $restore->course_startdateoffset;
1002             }
1003             $course->enrolperiod = $course_header->course_enrolperiod;
1004             $course->enablecompletion = isset($course_header->course_enablecompletion) ? $course_header->course_enablecompletion : 0;
1005             //Put as last course in category
1006             $course->sortorder = $category->sortorder + MAX_COURSES_IN_CATEGORY - 1;
1008             //Now, recode some languages (Moodle 1.5)
1009             if ($course->lang == 'ma_nt') {
1010                 $course->lang = 'mi_nt';
1011             }
1013             //Disable course->metacourse if avoided in restore config
1014             if (!$restore->metacourse) {
1015                 $course->metacourse = 0;
1016             }
1018             //Check if the theme exists in destination server
1019             $themes = get_list_of_themes();
1020             if (!in_array($course->theme, $themes)) {
1021                 $course->theme = '';
1022             }
1024             //Now insert the record
1025             $newid = $DB->insert_record("course",$course);
1026             if ($newid) {
1027                 //save old and new course id
1028                 backup_putid ($restore->backup_unique_code,"course",$course_header->course_id,$newid);
1029                 //Replace old course_id in course_header
1030                 $course_header->course_id = $newid;
1031                 $SESSION->restore->course_id = $newid;
1032                 return $newid;
1033             } else {
1034                 $status = false;
1035             }
1036         }
1038         return $status;
1039     }
1042             // Now that we have IDs for everything, store any completion data
1043             if($status && !empty($info->completiondata) && count($info->completiondata)>0) {
1044                 // Get list of users who can view course (& hence have
1045                 // completion data)
1046                 if(!isset($restore->userswhocanviewcourse)) {
1047                     // Because this is only used here, there is no point requesting
1048                     // anything except id
1049                     $restore->userswhocanviewcourse = get_enrolled_users(get_context_instance(CONTEXT_COURSE, $restore->course_id), '', 0, 'u.id');
1050                 }
1052                 foreach($info->completiondata as $data) {
1053                     // Convert cmid
1054                     $newcmid=backup_getid($restore->backup_unique_code, 'course_modules', $data->coursemoduleid);
1055                     if($newcmid) {
1056                         $data->coursemoduleid=$newcmid->new_id;
1057                     } else {
1058                         if (!defined('RESTORE_SILENTLY')) {
1059                             echo "<p>Can't find new ID for cm $data->coursemoduleid.</p>";
1060                         }
1061                         $status=false;
1062                         continue;
1063                     }
1065                     // Convert userid
1066                     $newuserid=backup_getid($restore->backup_unique_code, 'user', $data->userid);
1067                     if($newuserid) {
1068                         $data->userid=$newuserid->new_id;
1069                     } else {
1070                         // Skip missing users
1071                         debugging("Not restoring completion data for missing user {$data->userid}",DEBUG_DEVELOPER);
1072                         continue;
1073                     }
1075                     // Check user is still able to access new course (they
1076                     // might have had their role assignment excluded, and it
1077                     // creates arguably bogus database rows if we add completion
1078                     // data for them, and displays confusingly in the 'number
1079                     // of people who have already marked this complete' UI)
1080                     if(!array_key_exists($data->userid,$restore->userswhocanviewcourse)) {
1081                         continue;
1082                     }
1084                     // Add record
1085                     $DB->insert_record('course_modules_completion',$data);
1086                 }
1087             }
1089             // Store availability information
1090             if($status && !empty($info->availabilitydata) && count($info->availabilitydata)>0) {
1092                 foreach($info->availabilitydata as $data) {
1093                     // Convert cmid
1094                     $newcmid=backup_getid($restore->backup_unique_code, 'course_modules', $data->coursemoduleid);
1095                     if($newcmid) {
1096                         $data->coursemoduleid=$newcmid->new_id;
1097                     } else {
1098                         if (!defined('RESTORE_SILENTLY')) {
1099                             echo "<p>Can't find new ID for cm $data->coursemoduleid, ignoring availability condition.</p>";
1100                         }
1101                         continue;
1102                     }
1104                     // Convert source cmid
1105                     if($data->sourcecmid) {
1106                         $newcmid=backup_getid($restore->backup_unique_code, 'course_modules', $data->sourcecmid);
1107                         if($newcmid) {
1108                             $data->sourcecmid=$newcmid->new_id;
1109                         } else {
1110                             if (!defined('RESTORE_SILENTLY')) {
1111                                 echo "<p>Can't find new ID for source cm $data->sourcecmid, ignoring availability condition.</p>";
1112                             }
1113                             continue;
1114                         }
1115                     }
1117                     // Grade id is not converted (convert later)
1119                     // Add record
1120                     $DB->insert_record('course_modules_availability',$data);
1121                 }
1122             }
1123         } else {
1124             $status = false;
1125         }
1126         return $status;
1127     }
1129     //Called to set up any course-format specific data that may be in the file
1130     function restore_set_format_data($restore,$xml_file) {
1131         global $CFG, $DB;
1133         $status = true;
1134         //Check it exists
1135         if (!file_exists($xml_file)) {
1136             return false;
1137         }
1138         //Load data from XML to info
1139         if(!($info = restore_read_xml_formatdata($xml_file))) {
1140                 return false;
1141         }
1143         //Process format data if there is any
1144         if (isset($info->format_data)) {
1145                 if(!$format=$DB->get_field('course','format', array('id'=>$restore->course_id))) {
1146                     return false;
1147                 }
1148                 // If there was any data then it must have a restore method
1149                 $file=$CFG->dirroot."/course/format/$format/restorelib.php";
1150                 if(!file_exists($file)) {
1151                     return false;
1152                 }
1153                 require_once($file);
1154                 $function=$format.'_restore_format_data';
1155                 if(!function_exists($function)) {
1156                     return false;
1157                 }
1158                 return $function($restore,$info->format_data);
1159         }
1161         // If we got here then there's no data, but that's cool
1162         return true;
1163     }
1166     /**
1167      * This function creates all the gradebook data from xml
1168      */
1169     function restore_create_gradebook($restore,$xml_file) {
1170         global $CFG, $DB;
1172         $status = true;
1173         //Check it exists
1174         if (!file_exists($xml_file)) {
1175             return false;
1176         }
1178         // Get info from xml
1179         // info will contain the number of record to process
1180         $info = restore_read_xml_gradebook($restore, $xml_file);
1182         // If we have info, then process
1183         if (empty($info)) {
1184             return $status;
1185         }
1187         if (empty($CFG->disablegradehistory) and isset($info->gradebook_histories) and $info->gradebook_histories == "true") {
1188             $restore_histories = true;
1189         } else {
1190             $restore_histories = false;
1191         }
1193         // make sure top course category exists
1194         $course_category = grade_category::fetch_course_category($restore->course_id);
1195         $course_category->load_grade_item();
1197         // we need to know if all grade items that were backed up are being restored
1198         // if that is not the case, we do not restore grade categories nor gradeitems of category type or course type
1199         // i.e. the aggregated grades of that category
1201         $restoreall = true;  // set to false if any grade_item is not selected/restored or already exist
1202         $importing  = !empty($SESSION->restore->importing);
1204         if ($importing) {
1205             $restoreall = false;
1207         } else {
1208             $prev_grade_items = grade_item::fetch_all(array('courseid'=>$restore->course_id));
1209             $prev_grade_cats  = grade_category::fetch_all(array('courseid'=>$restore->course_id));
1211              // if any categories already present, skip restore of categories from backup - course item or category already exist
1212             if (count($prev_grade_items) > 1 or count($prev_grade_cats) > 1) {
1213                 $restoreall = false;
1214             }
1215             unset($prev_grade_items);
1216             unset($prev_grade_cats);
1218             if ($restoreall) {
1219                 if ($recs = $DB->get_records("backup_ids", array('table_name'=>'grade_items', 'backup_code'=>$restore->backup_unique_code), "", "old_id")) {
1220                     foreach ($recs as $rec) {
1221                         if ($data = backup_getid($restore->backup_unique_code,'grade_items',$rec->old_id)) {
1223                             $info = $data->info;
1224                             // do not restore if this grade_item is a mod, and
1225                             $itemtype = backup_todb($info['GRADE_ITEM']['#']['ITEMTYPE']['0']['#']);
1227                             if ($itemtype == 'mod') {
1228                                 $olditeminstance = backup_todb($info['GRADE_ITEM']['#']['ITEMINSTANCE']['0']['#']);
1229                                 $itemmodule      = backup_todb($info['GRADE_ITEM']['#']['ITEMMODULE']['0']['#']);
1231                                 if (empty($restore->mods[$itemmodule]->granular)) {
1232                                     continue;
1233                                 } else if (!empty($restore->mods[$itemmodule]->instances[$olditeminstance]->restore)) {
1234                                     continue;
1235                                 }
1236                                 // at least one activity should not be restored - do not restore categories and manual items at all
1237                                 $restoreall = false;
1238                                 break;
1239                             }
1240                         }
1241                     }
1242                 }
1243             }
1244         }
1246         // Start ul
1247         if (!defined('RESTORE_SILENTLY')) {
1248             echo '<ul>';
1249         }
1251         // array of restored categories - speedup ;-)
1252         $cached_categories = array();
1253         $outcomes          = array();
1255     /// Process letters
1256         $context = get_context_instance(CONTEXT_COURSE, $restore->course_id);
1257         // respect current grade letters if defined
1258         if ($status and $restoreall and !$DB->record_exists('grade_letters', array('contextid'=>$context->id))) {
1259             if (!defined('RESTORE_SILENTLY')) {
1260                 echo '<li>'.get_string('gradeletters','grades').'</li>';
1261             }
1262             // Fetch recordset_size records in each iteration
1263             $recs = $DB->get_records("backup_ids", array('table_name'=>'grade_letters', 'backup_code'=>$restore->backup_unique_code),
1264                                         "",
1265                                         "old_id");
1266             if ($recs) {
1267                 foreach ($recs as $rec) {
1268                     // Get the full record from backup_ids
1269                     $data = backup_getid($restore->backup_unique_code,'grade_letters',$rec->old_id);
1270                     if ($data) {
1271                         $info = $data->info;
1272                         $dbrec = new object();
1273                         $dbrec->contextid     = $context->id;
1274                         $dbrec->lowerboundary = backup_todb($info['GRADE_LETTER']['#']['LOWERBOUNDARY']['0']['#']);
1275                         $dbrec->letter        = backup_todb($info['GRADE_LETTER']['#']['LETTER']['0']['#']);
1276                         $DB->insert_record('grade_letters', $dbrec);
1277                     }
1278                 }
1279             }
1280         }
1282     /// Process grade items and grades
1283         if ($status) {
1284             if (!defined('RESTORE_SILENTLY')) {
1285                 echo '<li>'.get_string('gradeitems','grades').'</li>';
1286             }
1287             $counter = 0;
1289             //Fetch recordset_size records in each iteration
1290             $recs = $DB->get_records("backup_ids", array('table_name'=>'grade_items', 'backup_code'=>$restore->backup_unique_code),
1291                                         "id", // restore in the backup order
1292                                         "old_id");
1294             if ($recs) {
1295                 foreach ($recs as $rec) {
1296                     //Get the full record from backup_ids
1297                     $data = backup_getid($restore->backup_unique_code,'grade_items',$rec->old_id);
1298                     if ($data) {
1299                         $info = $data->info;
1301                         // first find out if category or normal item
1302                         $itemtype =  backup_todb($info['GRADE_ITEM']['#']['ITEMTYPE']['0']['#'], false);
1303                         if ($itemtype == 'course' or $itemtype == 'category') {
1304                             if (!$restoreall or $importing) {
1305                                 continue;
1306                             }
1308                             $oldcat = backup_todb($info['GRADE_ITEM']['#']['ITEMINSTANCE']['0']['#'], false);
1309                             if (!$cdata = backup_getid($restore->backup_unique_code,'grade_categories',$oldcat)) {
1310                                 continue;
1311                             }
1312                             $cinfo = $cdata->info;
1313                             unset($cdata);
1314                             if ($itemtype == 'course') {
1316                                 $course_category->fullname            = backup_todb($cinfo['GRADE_CATEGORY']['#']['FULLNAME']['0']['#'], false);
1317                                 $course_category->aggregation         = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATION']['0']['#'], false);
1318                                 $course_category->keephigh            = backup_todb($cinfo['GRADE_CATEGORY']['#']['KEEPHIGH']['0']['#'], false);
1319                                 $course_category->droplow             = backup_todb($cinfo['GRADE_CATEGORY']['#']['DROPLOW']['0']['#'], false);
1320                                 $course_category->aggregateonlygraded = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATEONLYGRADED']['0']['#'], false);
1321                                 $course_category->aggregateoutcomes   = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATEOUTCOMES']['0']['#'], false);
1322                                 $course_category->aggregatesubcats    = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATESUBCATS']['0']['#'], false);
1323                                 $course_category->timecreated         = backup_todb($cinfo['GRADE_CATEGORY']['#']['TIMECREATED']['0']['#'], false);
1324                                 $course_category->update('restore');
1326                                 $status = backup_putid($restore->backup_unique_code,'grade_categories',$oldcat,$course_category->id) && $status;
1327                                 $cached_categories[$oldcat] = $course_category;
1328                                 $grade_item = $course_category->get_grade_item();
1330                             } else {
1331                                 $oldparent = backup_todb($cinfo['GRADE_CATEGORY']['#']['PARENT']['0']['#'], false);
1332                                 if (empty($cached_categories[$oldparent])) {
1333                                     debugging('parent not found '.$oldparent);
1334                                     continue; // parent not found, sorry
1335                                 }
1336                                 $grade_category = new grade_category();
1337                                 $grade_category->courseid            = $restore->course_id;
1338                                 $grade_category->parent              = $cached_categories[$oldparent]->id;
1339                                 $grade_category->fullname            = backup_todb($cinfo['GRADE_CATEGORY']['#']['FULLNAME']['0']['#'], false);
1340                                 $grade_category->aggregation         = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATION']['0']['#'], false);
1341                                 $grade_category->keephigh            = backup_todb($cinfo['GRADE_CATEGORY']['#']['KEEPHIGH']['0']['#'], false);
1342                                 $grade_category->droplow             = backup_todb($cinfo['GRADE_CATEGORY']['#']['DROPLOW']['0']['#'], false);
1343                                 $grade_category->aggregateonlygraded = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATEONLYGRADED']['0']['#'], false);
1344                                 $grade_category->aggregateoutcomes   = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATEOUTCOMES']['0']['#'], false);
1345                                 $grade_category->aggregatesubcats    = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATESUBCATS']['0']['#'], false);
1346                                 $grade_category->timecreated         = backup_todb($cinfo['GRADE_CATEGORY']['#']['TIMECREATED']['0']['#'], false);
1347                                 $grade_category->insert('restore');
1349                                 $status = backup_putid($restore->backup_unique_code,'grade_categories',$oldcat,$grade_category->id) && $status;
1350                                 $cached_categories[$oldcat] = $grade_category;
1351                                 $grade_item = $grade_category->get_grade_item(); // creates grade_item too
1352                             }
1353                             unset($cinfo);
1355                             $idnumber = backup_todb($info['GRADE_ITEM']['#']['IDNUMBER']['0']['#'], false);
1356                             if (grade_verify_idnumber($idnumber, $restore->course_id)) {
1357                                 $grade_item->idnumber    = $idnumber;
1358                             }
1360                             $grade_item->itemname        = backup_todb($info['GRADE_ITEM']['#']['ITEMNAME']['0']['#'], false);
1361                             $grade_item->iteminfo        = backup_todb($info['GRADE_ITEM']['#']['ITEMINFO']['0']['#'], false);
1362                             $grade_item->gradetype       = backup_todb($info['GRADE_ITEM']['#']['GRADETYPE']['0']['#'], false);
1363                             $grade_item->calculation     = backup_todb($info['GRADE_ITEM']['#']['CALCULATION']['0']['#'], false);
1364                             $grade_item->grademax        = backup_todb($info['GRADE_ITEM']['#']['GRADEMAX']['0']['#'], false);
1365                             $grade_item->grademin        = backup_todb($info['GRADE_ITEM']['#']['GRADEMIN']['0']['#'], false);
1366                             $grade_item->gradepass       = backup_todb($info['GRADE_ITEM']['#']['GRADEPASS']['0']['#'], false);
1367                             $grade_item->multfactor      = backup_todb($info['GRADE_ITEM']['#']['MULTFACTOR']['0']['#'], false);
1368                             $grade_item->plusfactor      = backup_todb($info['GRADE_ITEM']['#']['PLUSFACTOR']['0']['#'], false);
1369                             $grade_item->aggregationcoef = backup_todb($info['GRADE_ITEM']['#']['AGGREGATIONCOEF']['0']['#'], false);
1370                             $grade_item->display         = backup_todb($info['GRADE_ITEM']['#']['DISPLAY']['0']['#'], false);
1371                             $grade_item->decimals        = backup_todb($info['GRADE_ITEM']['#']['DECIMALS']['0']['#'], false);
1372                             $grade_item->hidden          = backup_todb($info['GRADE_ITEM']['#']['HIDDEN']['0']['#'], false);
1373                             $grade_item->locked          = backup_todb($info['GRADE_ITEM']['#']['LOCKED']['0']['#'], false);
1374                             $grade_item->locktime        = backup_todb($info['GRADE_ITEM']['#']['LOCKTIME']['0']['#'], false);
1375                             $grade_item->timecreated     = backup_todb($info['GRADE_ITEM']['#']['TIMECREATED']['0']['#'], false);
1377                             if (backup_todb($info['GRADE_ITEM']['#']['SCALEID']['0']['#'], false)) {
1378                                 $scale = backup_getid($restore->backup_unique_code,"scale",backup_todb($info['GRADE_ITEM']['#']['SCALEID']['0']['#'], false));
1379                                 $grade_item->scaleid     = $scale->new_id;
1380                             }
1382                             if  (backup_todb($info['GRADE_ITEM']['#']['OUTCOMEID']['0']['#'], false)) {
1383                                 $outcome = backup_getid($restore->backup_unique_code,"grade_outcomes",backup_todb($info['GRADE_ITEM']['#']['OUTCOMEID']['0']['#'], false));
1384                                 $grade_item->outcomeid   = $outcome->new_id;
1385                             }
1387                             $grade_item->update('restore');
1388                             $status = backup_putid($restore->backup_unique_code,"grade_items", $rec->old_id, $grade_item->id) && $status;
1390                         } else {
1391                             if ($itemtype != 'mod' and (!$restoreall or $importing)) {
1392                                 // not extra gradebook stuff if restoring individual activities or something already there
1393                                 continue;
1394                             }
1396                             $dbrec = new object();
1398                             $dbrec->courseid      = $restore->course_id;
1399                             $dbrec->itemtype      = backup_todb($info['GRADE_ITEM']['#']['ITEMTYPE']['0']['#'], false);
1400                             $dbrec->itemmodule    = backup_todb($info['GRADE_ITEM']['#']['ITEMMODULE']['0']['#'], false);
1402                             if ($itemtype == 'mod') {
1403                                 // iteminstance should point to new mod
1404                                 $olditeminstance = backup_todb($info['GRADE_ITEM']['#']['ITEMINSTANCE']['0']['#'], false);
1405                                 $mod = backup_getid($restore->backup_unique_code,$dbrec->itemmodule, $olditeminstance);
1406                                 $dbrec->iteminstance = $mod->new_id;
1407                                 if (!$cm = get_coursemodule_from_instance($dbrec->itemmodule, $mod->new_id)) {
1408                                     // item not restored - no item
1409                                     continue;
1410                                 }
1411                                 // keep in sync with activity idnumber
1412                                 $dbrec->idnumber = $cm->idnumber;
1414                             } else {
1415                                 $idnumber = backup_todb($info['GRADE_ITEM']['#']['IDNUMBER']['0']['#'], false);
1417                                 if (grade_verify_idnumber($idnumber, $restore->course_id)) {
1418                                     //make sure the new idnumber is unique
1419                                     $dbrec->idnumber  = $idnumber;
1420                                 }
1421                             }
1423                             $dbrec->itemname        = backup_todb($info['GRADE_ITEM']['#']['ITEMNAME']['0']['#'], false);
1424                             $dbrec->itemtype        = backup_todb($info['GRADE_ITEM']['#']['ITEMTYPE']['0']['#'], false);
1425                             $dbrec->itemmodule      = backup_todb($info['GRADE_ITEM']['#']['ITEMMODULE']['0']['#'], false);
1426                             $dbrec->itemnumber      = backup_todb($info['GRADE_ITEM']['#']['ITEMNUMBER']['0']['#'], false);
1427                             $dbrec->iteminfo        = backup_todb($info['GRADE_ITEM']['#']['ITEMINFO']['0']['#'], false);
1428                             $dbrec->gradetype       = backup_todb($info['GRADE_ITEM']['#']['GRADETYPE']['0']['#'], false);
1429                             $dbrec->calculation     = backup_todb($info['GRADE_ITEM']['#']['CALCULATION']['0']['#'], false);
1430                             $dbrec->grademax        = backup_todb($info['GRADE_ITEM']['#']['GRADEMAX']['0']['#'], false);
1431                             $dbrec->grademin        = backup_todb($info['GRADE_ITEM']['#']['GRADEMIN']['0']['#'], false);
1432                             $dbrec->gradepass       = backup_todb($info['GRADE_ITEM']['#']['GRADEPASS']['0']['#'], false);
1433                             $dbrec->multfactor      = backup_todb($info['GRADE_ITEM']['#']['MULTFACTOR']['0']['#'], false);
1434                             $dbrec->plusfactor      = backup_todb($info['GRADE_ITEM']['#']['PLUSFACTOR']['0']['#'], false);
1435                             $dbrec->aggregationcoef = backup_todb($info['GRADE_ITEM']['#']['AGGREGATIONCOEF']['0']['#'], false);
1436                             $dbrec->display         = backup_todb($info['GRADE_ITEM']['#']['DISPLAY']['0']['#'], false);
1437                             $dbrec->decimals        = backup_todb($info['GRADE_ITEM']['#']['DECIMALS']['0']['#'], false);
1438                             $dbrec->hidden          = backup_todb($info['GRADE_ITEM']['#']['HIDDEN']['0']['#'], false);
1439                             $dbrec->locked          = backup_todb($info['GRADE_ITEM']['#']['LOCKED']['0']['#'], false);
1440                             $dbrec->locktime        = backup_todb($info['GRADE_ITEM']['#']['LOCKTIME']['0']['#'], false);
1441                             $dbrec->timecreated     = backup_todb($info['GRADE_ITEM']['#']['TIMECREATED']['0']['#'], false);
1443                             if (backup_todb($info['GRADE_ITEM']['#']['SCALEID']['0']['#'], false)) {
1444                                 $scale = backup_getid($restore->backup_unique_code,"scale",backup_todb($info['GRADE_ITEM']['#']['SCALEID']['0']['#'], false));
1445                                 $dbrec->scaleid = $scale->new_id;
1446                             }
1448                             if  (backup_todb($info['GRADE_ITEM']['#']['OUTCOMEID']['0']['#'])) {
1449                                 $oldoutcome = backup_todb($info['GRADE_ITEM']['#']['OUTCOMEID']['0']['#']);
1450                                 if (empty($outcomes[$oldoutcome])) {
1451                                     continue; // error!
1452                                 }
1453                                 if (empty($outcomes[$oldoutcome]->id)) {
1454                                     $outcomes[$oldoutcome]->insert('restore');
1455                                     $outcomes[$oldoutcome]->use_in($restore->course_id);
1456                                     backup_putid($restore->backup_unique_code, "grade_outcomes", $oldoutcome, $outcomes[$oldoutcome]->id);
1457                                 }
1458                                 $dbrec->outcomeid = $outcomes[$oldoutcome]->id;
1459                             }
1461                             $grade_item = new grade_item($dbrec, false);
1462                             $grade_item->insert('restore');
1463                             if ($restoreall) {
1464                                 // set original parent if restored
1465                                 $oldcat = $info['GRADE_ITEM']['#']['CATEGORYID']['0']['#'];
1466                                 if (!empty($cached_categories[$oldcat])) {
1467                                     $grade_item->set_parent($cached_categories[$oldcat]->id);
1468                                 }
1469                             }
1470                             $status = backup_putid($restore->backup_unique_code,"grade_items", $rec->old_id, $grade_item->id) && $status;
1471                         }
1473                         // no need to restore grades if user data is not selected or importing activities
1474                         if ($importing
1475                           or ($grade_item->itemtype == 'mod' and !restore_userdata_selected($restore,  $grade_item->itemmodule, $olditeminstance))) {
1476                             // module instance not selected when restored using granular
1477                             // skip this item
1478                             continue;
1479                         }
1481                         /// now, restore grade_grades
1482                         if (!empty($info['GRADE_ITEM']['#']['GRADE_GRADES']['0']['#']['GRADE'])) {
1483                             //Iterate over items
1484                             foreach ($info['GRADE_ITEM']['#']['GRADE_GRADES']['0']['#']['GRADE'] as $g_info) {
1486                                 $grade = new grade_grade();
1487                                 $grade->itemid         = $grade_item->id;
1489                                 $olduser = backup_todb($g_info['#']['USERID']['0']['#'], false);
1490                                 $user = backup_getid($restore->backup_unique_code,"user",$olduser);
1491                                 $grade->userid         = $user->new_id;
1493                                 $grade->rawgrade       = backup_todb($g_info['#']['RAWGRADE']['0']['#'], false);
1494                                 $grade->rawgrademax    = backup_todb($g_info['#']['RAWGRADEMAX']['0']['#'], false);
1495                                 $grade->rawgrademin    = backup_todb($g_info['#']['RAWGRADEMIN']['0']['#'], false);
1496                                 // need to find scaleid
1497                                 if (backup_todb($g_info['#']['RAWSCALEID']['0']['#'])) {
1498                                     $scale = backup_getid($restore->backup_unique_code,"scale",backup_todb($g_info['#']['RAWSCALEID']['0']['#'], false));
1499                                     $grade->rawscaleid = $scale->new_id;
1500                                 }
1502                                 if (backup_todb($g_info['#']['USERMODIFIED']['0']['#'])) {
1503                                     if ($modifier = backup_getid($restore->backup_unique_code,"user", backup_todb($g_info['#']['USERMODIFIED']['0']['#'], false))) {
1504                                         $grade->usermodified = $modifier->new_id;
1505                                     }
1506                                 }
1508                                 $grade->finalgrade        = backup_todb($g_info['#']['FINALGRADE']['0']['#'], false);
1509                                 $grade->hidden            = backup_todb($g_info['#']['HIDDEN']['0']['#'], false);
1510                                 $grade->locked            = backup_todb($g_info['#']['LOCKED']['0']['#'], false);
1511                                 $grade->locktime          = backup_todb($g_info['#']['LOCKTIME']['0']['#'], false);
1512                                 $grade->exported          = backup_todb($g_info['#']['EXPORTED']['0']['#'], false);
1513                                 $grade->overridden        = backup_todb($g_info['#']['OVERRIDDEN']['0']['#'], false);
1514                                 $grade->excluded          = backup_todb($g_info['#']['EXCLUDED']['0']['#'], false);
1515                                 $grade->feedback          = backup_todb($g_info['#']['FEEDBACK']['0']['#'], false);
1516                                 $grade->feedbackformat    = backup_todb($g_info['#']['FEEDBACKFORMAT']['0']['#'], false);
1517                                 $grade->information       = backup_todb($g_info['#']['INFORMATION']['0']['#'], false);
1518                                 $grade->informationformat = backup_todb($g_info['#']['INFORMATIONFORMAT']['0']['#'], false);
1519                                 $grade->timecreated       = backup_todb($g_info['#']['TIMECREATED']['0']['#'], false);
1520                                 $grade->timemodified      = backup_todb($g_info['#']['TIMEMODIFIED']['0']['#'], false);
1522                                 $grade->insert('restore');
1523                                 backup_putid($restore->backup_unique_code,"grade_grades", backup_todb($g_info['#']['ID']['0']['#']), $grade->id);
1525                                 $counter++;
1526                                 if ($counter % 20 == 0) {
1527                                     if (!defined('RESTORE_SILENTLY')) {
1528                                         echo ".";
1529                                         if ($counter % 400 == 0) {
1530                                             echo "<br />";
1531                                         }
1532                                     }
1533                                     backup_flush(300);
1534                                 }
1535                             }
1536                         }
1537                     }
1538                 }
1539             }
1540         }
1542     /// add outcomes that are not used when doing full restore
1543         if ($status and $restoreall) {
1544             foreach ($outcomes as $oldoutcome=>$grade_outcome) {
1545                 if (empty($grade_outcome->id)) {
1546                     $grade_outcome->insert('restore');
1547                     $grade_outcome->use_in($restore->course_id);
1548                     backup_putid($restore->backup_unique_code, "grade_outcomes", $oldoutcome, $grade_outcome->id);
1549                 }
1550             }
1551         }
1554         if ($status and !$importing and $restore_histories) {
1555             /// following code is very inefficient
1557             $gchcount = $DB->count_records('backup_ids', array('backup_code'=>$restore->backup_unique_code, 'table_name'=>'grade_categories_history'));
1558             $gghcount = $DB->count_records('backup_ids', array('backup_code'=>$restore->backup_unique_code, 'table_name'=>'grade_grades_history'));
1559             $gihcount = $DB->count_records('backup_ids', array('backup_code'=>$restore->backup_unique_code, 'table_name'=>'grade_items_history'));
1560             $gohcount = $DB->count_records('backup_ids', array('backup_code'=>$restore->backup_unique_code, 'table_name'=>'grade_outcomes_history'));
1562             // Number of records to get in every chunk
1563             $recordset_size = 2;
1565             // process histories
1566             if ($gchcount && $status) {
1567                 if (!defined('RESTORE_SILENTLY')) {
1568                     echo '<li>'.get_string('gradecategoryhistory','grades').'</li>';
1569                 }
1570                 $counter = 0;
1571                 while ($counter < $gchcount) {
1572                     //Fetch recordset_size records in each iteration
1573                     $recs = $DB->get_records("backup_ids",array('table_name'=>'grade_categories_history', 'backup_code'=>$restore->backup_unique_code),
1574                                                 "old_id",
1575                                                 "old_id",
1576                                                 $counter,
1577                                                 $recordset_size);
1578                     if ($recs) {
1579                         foreach ($recs as $rec) {
1580                             //Get the full record from backup_ids
1581                             $data = backup_getid($restore->backup_unique_code,'grade_categories_history',$rec->old_id);
1582                             if ($data) {
1583                                 //Now get completed xmlized object
1584                                 $info = $data->info;
1585                                 //traverse_xmlize($info);                            //Debug
1586                                 //print_object ($GLOBALS['traverse_array']);         //Debug
1587                                 //$GLOBALS['traverse_array']="";                     //Debug
1589                                 $oldobj = backup_getid($restore->backup_unique_code,"grade_categories", backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['OLDID']['0']['#']));
1590                                 if (empty($oldobj->new_id)) {
1591                                     // if the old object is not being restored, can't restoring its history
1592                                     $counter++;
1593                                     continue;
1594                                 }
1595                                 $dbrec->oldid = $oldobj->new_id;
1596                                 $dbrec->action = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['ACTION']['0']['#']);
1597                                 $dbrec->source = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['SOURCE']['0']['#']);
1598                                 $dbrec->timemodified = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['TIMEMODIFIED']['0']['#']);
1600                                 // loggeduser might not be restored, e.g. admin
1601                                 if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['LOGGEDUSER']['0']['#']))) {
1602                                     $dbrec->loggeduser = $oldobj->new_id;
1603                                 }
1605                                 // this item might not have a parent at all, do not skip it if no parent is specified
1606                                 if (backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['PARENT']['0']['#'])) {
1607                                     $oldobj = backup_getid($restore->backup_unique_code,"grade_categories", backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['PARENT']['0']['#']));
1608                                     if (empty($oldobj->new_id)) {
1609                                         // if the parent category not restored
1610                                         $counter++;
1611                                         continue;
1612                                     }
1613                                 }
1614                                 $dbrec->parent = $oldobj->new_id;
1615                                 $dbrec->depth = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['DEPTH']['0']['#']);
1616                                 // path needs to be rebuilt
1617                                 if ($path = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['PATH']['0']['#'])) {
1618                                 // to preserve the path and make it work, we need to replace the categories one by one
1619                                 // we first get the list of categories in current path
1620                                     if ($paths = explode("/", $path)) {
1621                                         $newpath = '';
1622                                         foreach ($paths as $catid) {
1623                                             if ($catid) {
1624                                                 // find the new corresponding path
1625                                                 $oldpath = backup_getid($restore->backup_unique_code,"grade_categories", $catid);
1626                                                 $newpath .= "/$oldpath->new_id";
1627                                             }
1628                                         }
1629                                         $dbrec->path = $newpath;
1630                                     }
1631                                 }
1632                                 $dbrec->fullname = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['FULLNAME']['0']['#']);
1633                                 $dbrec->aggregation = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['AGGRETGATION']['0']['#']);
1634                                 $dbrec->keephigh = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['KEEPHIGH']['0']['#']);
1635                                 $dbrec->droplow = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['DROPLOW']['0']['#']);
1637                                 $dbrec->aggregateonlygraded = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['AGGREGATEONLYGRADED']['0']['#']);
1638                                 $dbrec->aggregateoutcomes = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['AGGREGATEOUTCOMES']['0']['#']);
1639                                 $dbrec->aggregatesubcats = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['AGGREGATESUBCATS']['0']['#']);
1641                                 $dbrec->courseid = $restore->course_id;
1642                                 $DB->insert_record('grade_categories_history', $dbrec);
1643                                 unset($dbrec);
1645                             }
1646                             //Increment counters
1647                             $counter++;
1648                             //Do some output
1649                             if ($counter % 1 == 0) {
1650                                 if (!defined('RESTORE_SILENTLY')) {
1651                                     echo ".";
1652                                     if ($counter % 20 == 0) {
1653                                         echo "<br />";
1654                                     }
1655                                 }
1656                                 backup_flush(300);
1657                             }
1658                         }
1659                     }
1660                 }
1661             }
1663             // process histories
1664             if ($gghcount && $status) {
1665                 if (!defined('RESTORE_SILENTLY')) {
1666                     echo '<li>'.get_string('gradegradeshistory','grades').'</li>';
1667                 }
1668                 $counter = 0;
1669                 while ($counter < $gghcount) {
1670                     //Fetch recordset_size records in each iteration
1671                     $recs = $DB->get_records("backup_ids", array('table_name'=>'grade_grades_history', 'backup_code'=>$restore->backup_unique_code),
1672                                                 "old_id",
1673                                                 "old_id",
1674                                                 $counter,
1675                                                 $recordset_size);
1676                     if ($recs) {
1677                         foreach ($recs as $rec) {
1678                             //Get the full record from backup_ids
1679                             $data = backup_getid($restore->backup_unique_code,'grade_grades_history',$rec->old_id);
1680                             if ($data) {
1681                                 //Now get completed xmlized object
1682                                 $info = $data->info;
1683                                 //traverse_xmlize($info);                            //Debug
1684                                 //print_object ($GLOBALS['traverse_array']);         //Debug
1685                                 //$GLOBALS['traverse_array']="";                     //Debug
1687                                 $oldobj = backup_getid($restore->backup_unique_code,"grade_grades", backup_todb($info['GRADE_GRADES_HISTORY']['#']['OLDID']['0']['#']));
1688                                 if (empty($oldobj->new_id)) {
1689                                     // if the old object is not being restored, can't restoring its history
1690                                     $counter++;
1691                                     continue;
1692                                 }
1693                                 $dbrec->oldid = $oldobj->new_id;
1694                                 $dbrec->action = backup_todb($info['GRADE_GRADES_HISTORY']['#']['ACTION']['0']['#']);
1695                                 $dbrec->source = backup_todb($info['GRADE_GRADES_HISTORY']['#']['SOURCE']['0']['#']);
1696                                 $dbrec->timemodified = backup_todb($info['GRADE_GRADES_HISTORY']['#']['TIMEMODIFIED']['0']['#']);
1697                                 if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_GRADES_HISTORY']['#']['LOGGEDUSER']['0']['#']))) {
1698                                     $dbrec->loggeduser = $oldobj->new_id;
1699                                 }
1701                                 $oldobj = backup_getid($restore->backup_unique_code,"grade_items", backup_todb($info['GRADE_GRADES_HISTORY']['#']['ITEMID']['0']['#']));
1702                                 $dbrec->itemid = $oldobj->new_id;
1703                                 if (empty($dbrec->itemid)) {
1704                                     $counter++;
1705                                     continue; // grade item not being restored
1706                                 }
1707                                 $oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_GRADES_HISTORY']['#']['USERID']['0']['#']));
1708                                 $dbrec->userid = $oldobj->new_id;
1709                                 $dbrec->rawgrade = backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWGRADE']['0']['#']);
1710                                 $dbrec->rawgrademax = backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWGRADEMAX']['0']['#']);
1711                                 $dbrec->rawgrademin = backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWGRADEMIN']['0']['#']);
1712                                 if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_GRADES_HISTORY']['#']['USERMODIFIED']['0']['#']))) {
1713                                     $dbrec->usermodified = $oldobj->new_id;
1714                                 }
1716                                 if (backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWSCALEID']['0']['#'])) {
1717                                     $scale = backup_getid($restore->backup_unique_code,"scale",backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWSCALEID']['0']['#']));
1718                                     $dbrec->rawscaleid = $scale->new_id;
1719                                 }
1721                                 $dbrec->finalgrade = backup_todb($info['GRADE_GRADES_HISTORY']['#']['FINALGRADE']['0']['#']);
1722                                 $dbrec->hidden = backup_todb($info['GRADE_GRADES_HISTORY']['#']['HIDDEN']['0']['#']);
1723                                 $dbrec->locked = backup_todb($info['GRADE_GRADES_HISTORY']['#']['LOCKED']['0']['#']);
1724                                 $dbrec->locktime = backup_todb($info['GRADE_GRADES_HISTORY']['#']['LOCKTIME']['0']['#']);
1725                                 $dbrec->exported = backup_todb($info['GRADE_GRADES_HISTORY']['#']['EXPORTED']['0']['#']);
1726                                 $dbrec->overridden = backup_todb($info['GRADE_GRADES_HISTORY']['#']['OVERRIDDEN']['0']['#']);
1727                                 $dbrec->excluded = backup_todb($info['GRADE_GRADES_HISTORY']['#']['EXCLUDED']['0']['#']);
1728                                 $dbrec->feedback = backup_todb($info['GRADE_TEXT_HISTORY']['#']['FEEDBACK']['0']['#']);
1729                                 $dbrec->feedbackformat = backup_todb($info['GRADE_TEXT_HISTORY']['#']['FEEDBACKFORMAT']['0']['#']);
1730                                 $dbrec->information = backup_todb($info['GRADE_TEXT_HISTORY']['#']['INFORMATION']['0']['#']);
1731                                 $dbrec->informationformat = backup_todb($info['GRADE_TEXT_HISTORY']['#']['INFORMATIONFORMAT']['0']['#']);
1733                                 $DB->insert_record('grade_grades_history', $dbrec);
1734                                 unset($dbrec);
1736                             }
1737                             //Increment counters
1738                             $counter++;
1739                             //Do some output
1740                             if ($counter % 1 == 0) {
1741                                 if (!defined('RESTORE_SILENTLY')) {
1742                                     echo ".";
1743                                     if ($counter % 20 == 0) {
1744                                         echo "<br />";
1745                                     }
1746                                 }
1747                                 backup_flush(300);
1748                             }
1749                         }
1750                     }
1751                 }
1752             }
1754             // process histories
1756             if ($gihcount && $status) {
1757                 if (!defined('RESTORE_SILENTLY')) {
1758                     echo '<li>'.get_string('gradeitemshistory','grades').'</li>';
1759                 }
1760                 $counter = 0;
1761                 while ($counter < $gihcount) {
1762                     //Fetch recordset_size records in each iteration
1763                     $recs = $DB->get_records("backup_ids", array('table_name'=>'grade_items_history', 'backup_code'=>$restore->backup_unique_code),
1764                                                 "old_id",
1765                                                 "old_id",
1766                                                 $counter,
1767                                                 $recordset_size);
1768                     if ($recs) {
1769                         foreach ($recs as $rec) {
1770                             //Get the full record from backup_ids
1771                             $data = backup_getid($restore->backup_unique_code,'grade_items_history',$rec->old_id);
1772                             if ($data) {
1773                                 //Now get completed xmlized object
1774                                 $info = $data->info;
1775                                 //traverse_xmlize($info);                            //Debug
1776                                 //print_object ($GLOBALS['traverse_array']);         //Debug
1777                                 //$GLOBALS['traverse_array']="";                     //Debug
1780                                 $oldobj = backup_getid($restore->backup_unique_code,"grade_items", backup_todb($info['GRADE_ITEM_HISTORY']['#']['OLDID']['0']['#']));
1781                                 if (empty($oldobj->new_id)) {
1782                                     // if the old object is not being restored, can't restoring its history
1783                                     $counter++;
1784                                     continue;
1785                                 }
1786                                 $dbrec->oldid = $oldobj->new_id;
1787                                 $dbrec->action = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ACTION']['0']['#']);
1788                                 $dbrec->source = backup_todb($info['GRADE_ITEM_HISTORY']['#']['SOURCE']['0']['#']);
1789                                 $dbrec->timemodified = backup_todb($info['GRADE_ITEM_HISTORY']['#']['TIMEMODIFIED']['0']['#']);
1790                                 if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_ITEM_HISTORY']['#']['LOGGEDUSER']['0']['#']))) {
1791                                     $dbrec->loggeduser = $oldobj->new_id;
1792                                 }
1793                                 $dbrec->courseid = $restore->course_id;
1794                                 $oldobj = backup_getid($restore->backup_unique_code,'grade_categories',backup_todb($info['GRADE_ITEM_HISTORY']['#']['CATEGORYID']['0']['#']));
1795                                 $oldobj->categoryid = $category->new_id;
1796                                 if (empty($oldobj->categoryid)) {
1797                                     $counter++;
1798                                     continue; // category not restored
1799                                 }
1801                                 $dbrec->itemname= backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMNAME']['0']['#']);
1802                                 $dbrec->itemtype = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMTYPE']['0']['#']);
1803                                 $dbrec->itemmodule = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMMODULE']['0']['#']);
1805                                 // code from grade_items restore
1806                                 $iteminstance = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMINSTANCE']['0']['#']);
1807                                 // do not restore if this grade_item is a mod, and
1808                                 if ($dbrec->itemtype == 'mod') {
1810                                     if (!restore_userdata_selected($restore,  $dbrec->itemmodule, $iteminstance)) {
1811                                         // module instance not selected when restored using granular
1812                                         // skip this item
1813                                         $counter++;
1814                                         continue;
1815                                     }
1817                                     // iteminstance should point to new mod
1819                                     $mod = backup_getid($restore->backup_unique_code,$dbrec->itemmodule, $iteminstance);
1820                                     $dbrec->iteminstance = $mod->new_id;
1822                                 } else if ($dbrec->itemtype == 'category') {
1823                                     // the item instance should point to the new grade category
1825                                     // only proceed if we are restoring all grade items
1826                                     if ($restoreall) {
1827                                         $category = backup_getid($restore->backup_unique_code,'grade_categories', $iteminstance);
1828                                         $dbrec->iteminstance = $category->new_id;
1829                                     } else {
1830                                         // otherwise we can safely ignore this grade item and subsequent
1831                                         // grade_raws, grade_finals etc
1832                                         continue;
1833                                     }
1834                                 } elseif ($dbrec->itemtype == 'course') { // We don't restore course type to avoid duplicate course items
1835                                     if ($restoreall) {
1836                                         // TODO any special code needed here to restore course item without duplicating it?
1837                                         // find the course category with depth 1, and course id = current course id
1838                                         // this would have been already restored
1840                                         $cat = $DB->get_record('grade_categories', array('depth'=>1, 'courseid'=>$restore->course_id));
1841                                         $dbrec->iteminstance = $cat->id;
1843                                     } else {
1844                                         $counter++;
1845                                         continue;
1846                                     }
1847                                 }
1849                                 $dbrec->itemnumber = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMNUMBER']['0']['#']);
1850                                 $dbrec->iteminfo = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMINFO']['0']['#']);
1851                                 $dbrec->idnumber = backup_todb($info['GRADE_ITEM_HISTORY']['#']['IDNUMBER']['0']['#']);
1852                                 $dbrec->calculation = backup_todb($info['GRADE_ITEM_HISTORY']['#']['CALCULATION']['0']['#']);
1853                                 $dbrec->gradetype = backup_todb($info['GRADE_ITEM_HISTORY']['#']['GRADETYPE']['0']['#']);
1854                                 $dbrec->grademax = backup_todb($info['GRADE_ITEM_HISTORY']['#']['GRADEMAX']['0']['#']);
1855                                 $dbrec->grademin = backup_todb($info['GRADE_ITEM_HISTORY']['#']['GRADEMIN']['0']['#']);
1856                                 if ($oldobj = backup_getid($restore->backup_unique_code,"scale", backup_todb($info['GRADE_ITEM_HISTORY']['#']['SCALEID']['0']['#']))) {
1857                                     // scaleid is optional
1858                                     $dbrec->scaleid = $oldobj->new_id;
1859                                 }
1860                                 if ($oldobj = backup_getid($restore->backup_unique_code,"grade_outcomes", backup_todb($info['GRADE_ITEM_HISTORY']['#']['OUTCOMEID']['0']['#']))) {
1861                                     // outcome is optional
1862                                     $dbrec->outcomeid = $oldobj->new_id;
1863                                 }
1864                                 $dbrec->gradepass = backup_todb($info['GRADE_ITEM_HISTORY']['#']['GRADEPASS']['0']['#']);
1865                                 $dbrec->multfactor = backup_todb($info['GRADE_ITEM_HISTORY']['#']['MULTFACTOR']['0']['#']);
1866                                 $dbrec->plusfactor = backup_todb($info['GRADE_ITEM_HISTORY']['#']['PLUSFACTOR']['0']['#']);
1867                                 $dbrec->aggregationcoef = backup_todb($info['GRADE_ITEM_HISTORY']['#']['AGGREGATIONCOEF']['0']['#']);
1868                                 $dbrec->sortorder = backup_todb($info['GRADE_ITEM_HISTORY']['#']['SORTORDER']['0']['#']);
1869                                 $dbrec->display = backup_todb($info['GRADE_ITEM_HISTORY']['#']['DISPLAY']['0']['#']);
1870                                 $dbrec->decimals = backup_todb($info['GRADE_ITEM_HISTORY']['#']['DECIMALS']['0']['#']);
1871                                 $dbrec->hidden = backup_todb($info['GRADE_ITEM_HISTORY']['#']['HIDDEN']['0']['#']);
1872                                 $dbrec->locked = backup_todb($info['GRADE_ITEM_HISTORY']['#']['LOCKED']['0']['#']);
1873                                 $dbrec->locktime = backup_todb($info['GRADE_ITEM_HISTORY']['#']['LOCKTIME']['0']['#']);
1874                                 $dbrec->needsupdate = backup_todb($info['GRADE_ITEM_HISTORY']['#']['NEEDSUPDATE']['0']['#']);
1876                                 $DB->insert_record('grade_items_history', $dbrec);
1877                                 unset($dbrec);
1879                             }
1880                             //Increment counters
1881                             $counter++;
1882                             //Do some output
1883                             if ($counter % 1 == 0) {
1884                                 if (!defined('RESTORE_SILENTLY')) {
1885                                     echo ".";
1886                                     if ($counter % 20 == 0) {
1887                                         echo "<br />";
1888                                     }
1889                                 }
1890                                 backup_flush(300);
1891                             }
1892                         }
1893                     }
1894                 }
1895             }
1897             // process histories
1898             if ($gohcount && $status) {
1899                 if (!defined('RESTORE_SILENTLY')) {
1900                     echo '<li>'.get_string('gradeoutcomeshistory','grades').'</li>';
1901                 }
1902                 $counter = 0;
1903                 while ($counter < $gohcount) {
1904                     //Fetch recordset_size records in each iteration
1905                     $recs = $DB->get_records("backup_ids", array('table_name'=>'grade_outcomes_history', 'backup_code'=>$restore->backup_unique_code),
1906                                                 "old_id",
1907                                                 "old_id",
1908                                                 $counter,
1909                                                 $recordset_size);
1910                     if ($recs) {
1911                         foreach ($recs as $rec) {
1912                             //Get the full record from backup_ids
1913                             $data = backup_getid($restore->backup_unique_code,'grade_outcomes_history',$rec->old_id);
1914                             if ($data) {
1915                                 //Now get completed xmlized object
1916                                 $info = $data->info;
1917                                 //traverse_xmlize($info);                            //Debug
1918                                 //print_object ($GLOBALS['traverse_array']);         //Debug
1919                                 //$GLOBALS['traverse_array']="";                     //Debug
1921                                 $oldobj = backup_getid($restore->backup_unique_code,"grade_outcomes", backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['OLDID']['0']['#']));
1922                                 if (empty($oldobj->new_id)) {
1923                                     // if the old object is not being restored, can't restoring its history
1924                                     $counter++;
1925                                     continue;
1926                                 }
1927                                 $dbrec->oldid = $oldobj->new_id;
1928                                 $dbrec->action = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['ACTION']['0']['#']);
1929                                 $dbrec->source = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['SOURCE']['0']['#']);
1930                                 $dbrec->timemodified = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['TIMEMODIFIED']['0']['#']);
1931                                 if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['LOGGEDUSER']['0']['#']))) {
1932                                     $dbrec->loggeduser = $oldobj->new_id;
1933                                 }
1934                                 $dbrec->courseid = $restore->course_id;
1935                                 $dbrec->shortname = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['SHORTNAME']['0']['#']);
1936                                 $dbrec->fullname= backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['FULLNAME']['0']['#']);
1937                                 $oldobj = backup_getid($restore->backup_unique_code,"scale", backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['SCALEID']['0']['#']));
1938                                 $dbrec->scaleid = $oldobj->new_id;
1939                                 $dbrec->description = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['DESCRIPTION']['0']['#']);
1941                                 $DB->insert_record('grade_outcomes_history', $dbrec);
1942                                 unset($dbrec);
1944                             }
1945                             //Increment counters
1946                             $counter++;
1947                             //Do some output
1948                             if ($counter % 1 == 0) {
1949                                 if (!defined('RESTORE_SILENTLY')) {
1950                                     echo ".";
1951                                     if ($counter % 20 == 0) {
1952                                         echo "<br />";
1953                                     }
1954                                 }
1955                                 backup_flush(300);
1956                             }
1957                         }
1958                     }
1959                 }
1960             }
1961         }
1963         if (!defined('RESTORE_SILENTLY')) {
1964         //End ul
1965             echo '</ul>';
1966         }
1967         return $status;
1968     }
1970     //This function creates all the structures messages and contacts
1971     function restore_create_messages($restore,$xml_file) {
1972         global $CFG, $DB;
1974         $status = true;
1975         //Check it exists
1976         if (!file_exists($xml_file)) {
1977             $status = false;
1978         }
1979         //Get info from xml
1980         if ($status) {
1981             //info will contain the id and name of every table
1982             //(message, message_read and message_contacts)
1983             //in backup_ids->info will be the real info (serialized)
1984             $info = restore_read_xml_messages($restore,$xml_file);
1986             //If we have info, then process messages & contacts
1987             if ($info > 0) {
1988                 //Count how many we have
1989                 $unreadcount  = $DB->count_records ('backup_ids', array('backup_code'=>$restore->backup_unique_code, 'table_name'=>'message'));
1990                 $readcount    = $DB->count_records ('backup_ids', array('backup_code'=>$restore->backup_unique_code, 'table_name'=>'message_read'));
1991                 $contactcount = $DB->count_records ('backup_ids', array('backup_code'=>$restore->backup_unique_code, 'table_name'=>'message_contacts'));
1992                 if ($unreadcount || $readcount || $contactcount) {
1993                     //Start ul
1994                     if (!defined('RESTORE_SILENTLY')) {
1995                         echo '<ul>';
1996                     }
1997                     //Number of records to get in every chunk
1998                     $recordset_size = 4;
2000                     //Process unread
2001                     if ($unreadcount) {
2002                         if (!defined('RESTORE_SILENTLY')) {
2003                             echo '<li>'.get_string('unreadmessages','message').'</li>';
2004                         }
2005                         $counter = 0;
2006                         while ($counter < $unreadcount) {
2007                             //Fetch recordset_size records in each iteration
2008                             $recs = $DB->get_records("backup_ids", array('table_name'=>'message', 'backup_code'=>$restore->backup_unique_code),"old_id","old_id",$counter,$recordset_size);
2009                             if ($recs) {
2010                                 foreach ($recs as $rec) {
2011                                     //Get the full record from backup_ids
2012                                     $data = backup_getid($restore->backup_unique_code,"message",$rec->old_id);
2013                                     if ($data) {
2014                                         //Now get completed xmlized object
2015                                         $info = $data->info;
2016                                         //traverse_xmlize($info);                            //Debug
2017                                         //print_object ($GLOBALS['traverse_array']);         //Debug
2018                                         //$GLOBALS['traverse_array']="";                     //Debug
2019                                         //Now build the MESSAGE record structure
2020                                         $dbrec = new object();
2021                                         $dbrec->useridfrom = backup_todb($info['MESSAGE']['#']['USERIDFROM']['0']['#']);
2022                                         $dbrec->useridto = backup_todb($info['MESSAGE']['#']['USERIDTO']['0']['#']);
2023                                         $dbrec->message = backup_todb($info['MESSAGE']['#']['MESSAGE']['0']['#']);
2024                                         $dbrec->format = backup_todb($info['MESSAGE']['#']['FORMAT']['0']['#']);
2025                                         $dbrec->timecreated = backup_todb($info['MESSAGE']['#']['TIMECREATED']['0']['#']);
2026                                         $dbrec->messagetype = backup_todb($info['MESSAGE']['#']['MESSAGETYPE']['0']['#']);
2027                                         //We have to recode the useridfrom field
2028                                         $user = backup_getid($restore->backup_unique_code,"user",$dbrec->useridfrom);
2029                                         if ($user) {
2030                                             //echo "User ".$dbrec->useridfrom." to user ".$user->new_id."<br />";   //Debug
2031                                             $dbrec->useridfrom = $user->new_id;
2032                                         }
2033                                         //We have to recode the useridto field
2034                                         $user = backup_getid($restore->backup_unique_code,"user",$dbrec->useridto);
2035                                         if ($user) {
2036                                             //echo "User ".$dbrec->useridto." to user ".$user->new_id."<br />";   //Debug
2037                                             $dbrec->useridto = $user->new_id;
2038                                         }
2039                                         //Check if the record doesn't exist in DB!
2040                                         $exist = $DB->get_record('message', array('useridfrom'=>$dbrec->useridfrom,
2041                                                                                   'useridto'=>$dbrec->useridto,
2042                                                                                   'timecreated'=>$dbrec->timecreated));
2043                                         if (!$exist) {
2044                                             //Not exist. Insert
2045                                             $status = $DB->insert_record('message',$dbrec);
2046                                         } else {
2047                                             //Duplicate. Do nothing
2048                                         }
2049                                     }
2050                                     //Do some output
2051                                     $counter++;
2052                                     if ($counter % 10 == 0) {
2053                                         if (!defined('RESTORE_SILENTLY')) {
2054                                             echo ".";
2055                                             if ($counter % 200 == 0) {
2056                                                 echo "<br />";
2057                                             }
2058                                         }
2059                                         backup_flush(300);
2060                                     }
2061                                 }
2062                             }
2063                         }
2064                     }
2066                     //Process read
2067                     if ($readcount) {
2068                         if (!defined('RESTORE_SILENTLY')) {
2069                             echo '<li>'.get_string('readmessages','message').'</li>';
2070                         }
2071                         $counter = 0;
2072                         while ($counter < $readcount) {
2073                             //Fetch recordset_size records in each iteration
2074                             $recs = $DB->get_records("backup_ids", array('table_name'=>'message_read', 'backup_code'=>$restore->backup_unique_code),"old_id","old_id",$counter,$recordset_size);
2075                             if ($recs) {
2076                                 foreach ($recs as $rec) {
2077                                     //Get the full record from backup_ids
2078                                     $data = backup_getid($restore->backup_unique_code,"message_read",$rec->old_id);
2079                                     if ($data) {
2080                                         //Now get completed xmlized object
2081                                         $info = $data->info;
2082                                         //traverse_xmlize($info);                            //Debug
2083                                         //print_object ($GLOBALS['traverse_array']);         //Debug
2084                                         //$GLOBALS['traverse_array']="";                     //Debug
2085                                         //Now build the MESSAGE_READ record structure
2086                                         $dbrec->useridfrom = backup_todb($info['MESSAGE']['#']['USERIDFROM']['0']['#']);
2087                                         $dbrec->useridto = backup_todb($info['MESSAGE']['#']['USERIDTO']['0']['#']);
2088                                         $dbrec->message = backup_todb($info['MESSAGE']['#']['MESSAGE']['0']['#']);
2089                                         $dbrec->format = backup_todb($info['MESSAGE']['#']['FORMAT']['0']['#']);
2090                                         $dbrec->timecreated = backup_todb($info['MESSAGE']['#']['TIMECREATED']['0']['#']);
2091                                         $dbrec->messagetype = backup_todb($info['MESSAGE']['#']['MESSAGETYPE']['0']['#']);
2092                                         $dbrec->timeread = backup_todb($info['MESSAGE']['#']['TIMEREAD']['0']['#']);
2093                                         $dbrec->mailed = backup_todb($info['MESSAGE']['#']['MAILED']['0']['#']);
2094                                         //We have to recode the useridfrom field
2095                                         $user = backup_getid($restore->backup_unique_code,"user",$dbrec->useridfrom);
2096                                         if ($user) {
2097                                             //echo "User ".$dbrec->useridfrom." to user ".$user->new_id."<br />";   //Debug
2098                                             $dbrec->useridfrom = $user->new_id;
2099                                         }
2100                                         //We have to recode the useridto field
2101                                         $user = backup_getid($restore->backup_unique_code,"user",$dbrec->useridto);
2102                                         if ($user) {
2103                                             //echo "User ".$dbrec->useridto." to user ".$user->new_id."<br />";   //Debug
2104                                             $dbrec->useridto = $user->new_id;
2105                                         }
2106                                         //Check if the record doesn't exist in DB!
2107                                         $exist = $DB->get_record('message_read', array('useridfrom'=>$dbrec->useridfrom,
2108                                                                                        'useridto'=>$dbrec->useridto,
2109                                                                                        'timecreated'=>$dbrec->timecreated));
2110                                         if (!$exist) {
2111                                             //Not exist. Insert
2112                                             $status = $DB->insert_record('message_read',$dbrec);
2113                                         } else {
2114                                             //Duplicate. Do nothing
2115                                         }
2116                                     }
2117                                     //Do some output
2118                                     $counter++;
2119                                     if ($counter % 10 == 0) {
2120                                         if (!defined('RESTORE_SILENTLY')) {
2121                                             echo ".";
2122                                             if ($counter % 200 == 0) {
2123                                                 echo "<br />";
2124                                             }
2125                                         }
2126                                         backup_flush(300);
2127                                     }
2128                                 }
2129                             }
2130                         }
2131                     }
2133                     //Process contacts
2134                     if ($contactcount) {
2135                         if (!defined('RESTORE_SILENTLY')) {
2136                             echo '<li>'.moodle_strtolower(get_string('contacts','message')).'</li>';
2137                         }
2138                         $counter = 0;
2139                         while ($counter < $contactcount) {
2140                             //Fetch recordset_size records in each iteration
2141                             $recs = $DB->get_records("backup_ids", array('table_name'=>'message_contacts', 'backup_code'=>$restore->backup_unique_code),"old_id","old_id",$counter,$recordset_size);
2142                             if ($recs) {
2143                                 foreach ($recs as $rec) {
2144                                     //Get the full record from backup_ids
2145                                     $data = backup_getid($restore->backup_unique_code,"message_contacts",$rec->old_id);
2146                                     if ($data) {
2147                                         //Now get completed xmlized object
2148                                         $info = $data->info;
2149                                         //traverse_xmlize($info);                            //Debug
2150                                         //print_object ($GLOBALS['traverse_array']);         //Debug
2151                                         //$GLOBALS['traverse_array']="";                     //Debug
2152                                         //Now build the MESSAGE_CONTACTS record structure
2153                                         $dbrec->userid = backup_todb($info['CONTACT']['#']['USERID']['0']['#']);
2154                                         $dbrec->contactid = backup_todb($info['CONTACT']['#']['CONTACTID']['0']['#']);
2155                                         $dbrec->blocked = backup_todb($info['CONTACT']['#']['BLOCKED']['0']['#']);
2156                                         //We have to recode the userid field
2157                                         $user = backup_getid($restore->backup_unique_code,"user",$dbrec->userid);
2158                                         if ($user) {
2159                                             //echo "User ".$dbrec->userid." to user ".$user->new_id."<br />";   //Debug
2160                                             $dbrec->userid = $user->new_id;
2161                                         }
2162                                         //We have to recode the contactid field
2163                                         $user = backup_getid($restore->backup_unique_code,"user",$dbrec->contactid);
2164                                         if ($user) {
2165                                             //echo "User ".$dbrec->contactid." to user ".$user->new_id."<br />";   //Debug
2166                                             $dbrec->contactid = $user->new_id;
2167                                         }
2168                                         //Check if the record doesn't exist in DB!
2169                                         $exist = $DB->get_record('message_contacts', array('userid'=>$dbrec->userid,
2170                                                                                            'contactid'=>$dbrec->contactid));
2171                                         if (!$exist) {
2172                                             //Not exist. Insert
2173                                             $status = $DB->insert_record('message_contacts',$dbrec);
2174                                         } else {
2175                                             //Duplicate. Do nothing
2176                                         }
2177                                     }
2178                                     //Do some output
2179                                     $counter++;
2180                                     if ($counter % 10 == 0) {
2181                                         if (!defined('RESTORE_SILENTLY')) {
2182                                             echo ".";
2183                                             if ($counter % 200 == 0) {
2184                                                 echo "<br />";
2185                                             }
2186                                         }
2187                                         backup_flush(300);
2188                                     }
2189                                 }
2190                             }
2191                         }
2192                     }
2193                     if (!defined('RESTORE_SILENTLY')) {
2194                         //End ul
2195                         echo '</ul>';
2196                     }
2197                 }
2198             }
2199         }
2201        return $status;
2202     }
2204     //This function creates all the structures for blogs and blog tags
2205     function restore_create_blogs($restore,$xml_file) {
2206         global $CFG, $DB;
2208         $status = true;
2209         //Check it exists
2210         if (!file_exists($xml_file)) {
2211             $status = false;
2212         }
2213         //Get info from xml
2214         if ($status) {
2215             //info will contain the number of blogs in the backup file
2216             //in backup_ids->info will be the real info (serialized)
2217             $info = restore_read_xml_blogs($restore,$xml_file);
2219             //If we have info, then process blogs & blog_tags
2220             if ($info > 0) {
2221                 //Count how many we have
2222                 $blogcount = $DB->count_records('backup_ids', array('backup_code'=>$restore->backup_unique_code, 'table_name'=>'blog'));
2223                 if ($blogcount) {
2224                     //Number of records to get in every chunk
2225                     $recordset_size = 4;
2227                     //Process blog
2228                     if ($blogcount) {
2229                         $counter = 0;
2230                         while ($counter < $blogcount) {
2231                             //Fetch recordset_size records in each iteration
2232                             $recs = $DB->get_records("backup_ids", array("table_name"=>'blog', 'backup_code'=>$restore->backup_unique_code),"old_id","old_id",$counter,$recordset_size);
2233                             if ($recs) {
2234                                 foreach ($recs as $rec) {
2235                                     //Get the full record from backup_ids
2236                                     $data = backup_getid($restore->backup_unique_code,"blog",$rec->old_id);
2237                                     if ($data) {
2238                                         //Now get completed xmlized object
2239                                         $info = $data->info;
2240                                         //traverse_xmlize($info);                            //Debug
2241                                         //print_object ($GLOBALS['traverse_array']);         //Debug
2242                                         //$GLOBALS['traverse_array']="";                     //Debug
2243                                         //Now build the BLOG record structure
2244                                         $dbrec = new object();
2245                                         $dbrec->module = backup_todb($info['BLOG']['#']['MODULE']['0']['#']);
2246                                         $dbrec->userid = backup_todb($info['BLOG']['#']['USERID']['0']['#']);
2247                                         $dbrec->courseid = backup_todb($info['BLOG']['#']['COURSEID']['0']['#']);
2248                                         $dbrec->groupid = backup_todb($info['BLOG']['#']['GROUPID']['0']['#']);
2249                                         $dbrec->moduleid = backup_todb($info['BLOG']['#']['MODULEID']['0']['#']);
2250                                         $dbrec->coursemoduleid = backup_todb($info['BLOG']['#']['COURSEMODULEID']['0']['#']);
2251                                         $dbrec->subject = backup_todb($info['BLOG']['#']['SUBJECT']['0']['#']);
2252                                         $dbrec->summary = backup_todb($info['BLOG']['#']['SUMMARY']['0']['#']);
2253                                         $dbrec->content = backup_todb($info['BLOG']['#']['CONTENT']['0']['#']);
2254                                         $dbrec->uniquehash = backup_todb($info['BLOG']['#']['UNIQUEHASH']['0']['#']);
2255                                         $dbrec->rating = backup_todb($info['BLOG']['#']['RATING']['0']['#']);
2256                                         $dbrec->format = backup_todb($info['BLOG']['#']['FORMAT']['0']['#']);
2257                                         $dbrec->attachment = backup_todb($info['BLOG']['#']['ATTACHMENT']['0']['#']);
2258                                         $dbrec->publishstate = backup_todb($info['BLOG']['#']['PUBLISHSTATE']['0']['#']);
2259                                         $dbrec->lastmodified = backup_todb($info['BLOG']['#']['LASTMODIFIED']['0']['#']);
2260                                         $dbrec->created = backup_todb($info['BLOG']['#']['CREATED']['0']['#']);
2261                                         $dbrec->usermodified = backup_todb($info['BLOG']['#']['USERMODIFIED']['0']['#']);
2263                                         //We have to recode the userid field
2264                                         $user = backup_getid($restore->backup_unique_code,"user",$dbrec->userid);
2265                                         if ($user) {
2266                                             //echo "User ".$dbrec->userid." to user ".$user->new_id."<br />";   //Debug
2267                                             $dbrec->userid = $user->new_id;
2268                                         }
2270                                         //Check if the record doesn't exist in DB!
2271                                         $exist = $DB->get_record('post', array('userid'=>$dbrec->userid,
2272                                                                                'subject'=>$dbrec->subject,
2273                                                                                'created'=>$dbrec->created));
2274                                         $newblogid = 0;
2275                                         if (!$exist) {
2276                                             //Not exist. Insert
2277                                             $newblogid = $DB->insert_record('post',$dbrec);
2278                                         }
2280                                         //Going to restore related tags. Check they are enabled and we have inserted a blog
2281                                         if ($CFG->usetags && $newblogid) {
2282                                             //Look for tags in this blog
2283                                             if (isset($info['BLOG']['#']['BLOG_TAGS']['0']['#']['BLOG_TAG'])) {
2284                                                 $tagsarr = $info['BLOG']['#']['BLOG_TAGS']['0']['#']['BLOG_TAG'];
2285                                                 //Iterate over tags
2286                                                 $tags = array();
2287                                                 for($i = 0; $i < sizeof($tagsarr); $i++) {
2288                                                     $tag_info = $tagsarr[$i];
2289                                                     ///traverse_xmlize($tag_info);                        //Debug
2290                                                     ///print_object ($GLOBALS['traverse_array']);         //Debug
2291                                                     ///$GLOBALS['traverse_array']="";                     //Debug
2293                                                     $name = backup_todb($tag_info['#']['NAME']['0']['#']);
2294                                                     $rawname = backup_todb($tag_info['#']['RAWNAME']['0']['#']);
2296                                                     $tags[] = $rawname;  //Rawname is all we need
2297                                                 }
2298                                                 tag_set('post', $newblogid, $tags); //Add all the tags in one API call
2299                                             }
2300                                         }
2301                                     }
2302                                     //Do some output
2303                                     $counter++;
2304                                     if ($counter % 10 == 0) {
2305                                         if (!defined('RESTORE_SILENTLY')) {
2306                                             echo ".";
2307                                             if ($counter % 200 == 0) {
2308                                                 echo "<br />";
2309                                             }
2310                                         }
2311                                         backup_flush(300);
2312                                     }
2313                                 }
2314                             }
2315                         }
2316                     }
2317                 }
2318             }
2319         }
2321         return $status;
2322     }
2324     //This function creates all the categories and questions
2325     //from xml
2326     function restore_create_questions($restore,$xml_file) {
2327         global $CFG;
2329         $status = true;
2330         //Check it exists
2331         if (!file_exists($xml_file)) {
2332             $status = false;
2333         }
2334         //Get info from xml
2335         if ($status) {
2336             //info will contain the old_id of every category
2337             //in backup_ids->info will be the real info (serialized)
2338             $info = restore_read_xml_questions($restore,$xml_file);
2339         }
2340         //Now, if we have anything in info, we have to restore that
2341         //categories/questions
2342         if ($info) {
2343             if ($info !== true) {
2344                 $status = $status &&  restore_question_categories($info, $restore);
2345             }
2346         } else {
2347             $status = false;
2348         }
2349         return $status;
2350     }
2352     //This function creates all the course events
2353     function restore_create_events($restore,$xml_file) {
2354         global $DB;
2356         global $CFG, $SESSION;
2358         $status = true;
2359         //Check it exists
2360         if (!file_exists($xml_file)) {
2361             $status = false;
2362         }
2363         //Get info from xml
2364         if ($status) {
2365             //events will contain the old_id of every event
2366             //in backup_ids->info will be the real info (serialized)
2367             $events = restore_read_xml_events($restore,$xml_file);
2368         }
2370         //Get admin->id for later use
2371         $admin = get_admin();
2372         $adminid = $admin->id;
2374         //Now, if we have anything in events, we have to restore that
2375         //events
2376         if ($events) {
2377             if ($events !== true) {
2378                 //Iterate over each event
2379                 foreach ($events as $event) {
2380                     //Get record from backup_ids
2381                     $data = backup_getid($restore->backup_unique_code,"event",$event->id);
2382                     //Init variables
2383                     $create_event = false;
2385                     if ($data) {
2386                         //Now get completed xmlized object
2387                         $info = $data->info;
2388                         //traverse_xmlize($info);                                                                     //Debug
2389                         //print_object ($GLOBALS['traverse_array']);                                                  //Debug
2390                         //$GLOBALS['traverse_array']="";                                                              //Debug
2392                         //if necessary, write to restorelog and adjust date/time fields
2393                         if ($restore->course_startdateoffset) {
2394                             restore_log_date_changes('Events', $restore, $info['EVENT']['#'], array('TIMESTART'));
2395                         }
2397                         //Now build the EVENT record structure
2398                         $eve->name = backup_todb($info['EVENT']['#']['NAME']['0']['#']);
2399                         $eve->description = backup_todb($info['EVENT']['#']['DESCRIPTION']['0']['#']);
2400                         $eve->format = backup_todb($info['EVENT']['#']['FORMAT']['0']['#']);
2401                         $eve->courseid = $restore->course_id;
2402                         $eve->groupid = backup_todb($info['EVENT']['#']['GROUPID']['0']['#']);
2403                         $eve->userid = backup_todb($info['EVENT']['#']['USERID']['0']['#']);
2404                         $eve->repeatid = backup_todb($info['EVENT']['#']['REPEATID']['0']['#']);
2405                         $eve->modulename = "";
2406                         if (!empty($info['EVENT']['#']['MODULENAME'])) {
2407                             $eve->modulename = backup_todb($info['EVENT']['#']['MODULENAME']['0']['#']);
2408                         }
2409                         $eve->instance = 0;
2410                         $eve->eventtype = backup_todb($info['EVENT']['#']['EVENTTYPE']['0']['#']);
2411                         $eve->timestart = backup_todb($info['EVENT']['#']['TIMESTART']['0']['#']);
2412                         $eve->timeduration = backup_todb($info['EVENT']['#']['TIMEDURATION']['0']['#']);
2413                         $eve->visible = backup_todb($info['EVENT']['#']['VISIBLE']['0']['#']);
2414                         $eve->timemodified = backup_todb($info['EVENT']['#']['TIMEMODIFIED']['0']['#']);
2416                         //Now search if that event exists (by name, description, timestart fields) in
2417                         //restore->course_id course
2418                         //Going to compare LOB columns so, use the cross-db sql_compare_text() in both sides.
2419                         $compare_description_clause = $DB->sql_compare_text('description')  . "=" .  $DB->sql_compare_text("'" . $eve->description . "'");
2420                         $eve_db = $DB->get_record_select('event',
2421                             "courseid = ? AND name = ? AND $compare_description_clause AND timestart = ?",
2422                             array($eve->courseid, $eve->name, $eve->timestart));
2423                         //If it doesn't exist, create
2424                         if (!$eve_db) {
2425                             $create_event = true;
2426                         }
2427                         //If we must create the event
2428                         if ($create_event) {
2430                             //We must recode the userid
2431                             $user = backup_getid($restore->backup_unique_code,"user",$eve->userid);
2432                             if ($user) {
2433                                 $eve->userid = $user->new_id;
2434                             } else {
2435                                 //Assign it to admin
2436                                 $eve->userid = $adminid;
2437                             }
2439                             //We have to recode the groupid field
2440                             $group = backup_getid($restore->backup_unique_code,"groups",$eve->groupid);
2441                             if ($group) {
2442                                 $eve->groupid = $group->new_id;
2443                             } else {
2444                                 //Assign it to group 0
2445                                 $eve->groupid = 0;
2446                             }
2448                             //The structure is equal to the db, so insert the event
2449                             $newid = $DB->insert_record ("event",$eve);
2451                             //We must recode the repeatid if the event has it
2452                             //The repeatid now refers to the id of the original event. (see Bug#5956)
2453                             if ($newid && !empty($eve->repeatid)) {
2454                                 $repeat_rec = backup_getid($restore->backup_unique_code,"event_repeatid",$eve->repeatid);
2455                                 if ($repeat_rec) {    //Exists, so use it...
2456                                     $eve->repeatid = $repeat_rec->new_id;
2457                                 } else {              //Doesn't exists, calculate the next and save it
2458                                     $oldrepeatid = $eve->repeatid;
2459                                     $eve->repeatid = $newid;
2460                                     backup_putid($restore->backup_unique_code,"event_repeatid", $oldrepeatid, $eve->repeatid);
2461                                 }
2462                                 $eve->id = $newid;
2463                                 // update the record to contain the correct repeatid
2464                                 $DB->update_record('event',$eve);
2465                             }
2466                         } else {
2467                             //get current event id
2468                             $newid = $eve_db->id;
2469                         }
2470                         if ($newid) {
2471                             //We have the newid, update backup_ids
2472                             backup_putid($restore->backup_unique_code,"event",
2473                                          $event->id, $newid);
2474                         }
2475                     }
2476                 }
2477             }
2478         } else {
2479             $status = false;
2480         }
2481         return $status;
2482     }
2484     //This function decode things to make restore multi-site fully functional
2485     //It does this conversions:
2486     //    - $@FILEPHP@$ ---|------------> $CFG->wwwroot/file.php/courseid (slasharguments on)
2487     //                     |------------> $CFG->wwwroot/file.php?file=/courseid (slasharguments off)
2488     //
2489     //    - $@SLASH@$ --|---------------> / (slasharguments on)
2490     //                  |---------------> %2F (slasharguments off)
2491     //
2492     //    - $@FORCEDOWNLOAD@$ --|-------> ?forcedownload=1 (slasharguments on)
2493     //                          |-------> &amp;forcedownload=1(slasharguments off)
2494     //Note: Inter-activities linking is being implemented as a final
2495     //step in the restore execution, because we need to have it
2496     //finished to know all the oldid, newid equivaleces
2497     function restore_decode_absolute_links($content) {
2498         global $CFG, $restore;
2499         require_once($CFG->libdir.'/filelib.php');
2501     /// MDL-14072: Prevent NULLs, empties and numbers to be processed by the
2502     /// heavy interlinking. Just a few cpu cycles saved.
2503         if ($content === NULL) {
2504             return NULL;
2505         } else if ($content === '') {
2506             return '';
2507         } else if (is_numeric($content)) {
2508             return $content;
2509         }
2511         //Now decode wwwroot and file.php calls
2512         $search = array ("$@FILEPHP@$");
2513         $replace = array(get_file_url($restore->course_id));
2514         $result = str_replace($search,$replace,$content);
2516         //Now $@SLASH@$ and $@FORCEDOWNLOAD@$ MDL-18799
2517         $search = array('$@SLASH@$', '$@FORCEDOWNLOAD@$');
2518         if ($CFG->slasharguments) {
2519             $replace = array('/', '?forcedownload=1');
2520         } else {
2521             $replace = array('%2F', '&amp;forcedownload=1');
2522         }
2523         $result = str_replace($search, $replace, $result);
2525         if ($result != $content && debugging()) {                                  //Debug
2526             if (!defined('RESTORE_SILENTLY')) {
2527                 echo '<br /><hr />'.s($content).'<br />changed to<br />'.s($result).'<hr /><br />';        //Debug
2528             }
2529         }                                                                            //Debug
2531         return $result;
2532     }
2534     //This function restores the userfiles from the temp (user_files) directory to the
2535     //dataroot/users directory
2536     function restore_user_files($restore) {
2538         global $CFG;
2540         $status = true;
2542         $counter = 0;
2544         // 'users' is the old users folder, 'user' is the new one, with a new hierarchy. Detect which one is here and treat accordingly
2545         //in CFG->dataroot
2546         $dest_dir = $CFG->dataroot."/user";
2547         $status = check_dir_exists($dest_dir,true);
2549         //Now, we iterate over "user_files" records to check if that user dir must be
2550         //copied (and renamed) to the "users" dir.
2551         $rootdir = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/user_files";
2553         //Check if directory exists
2554         $userlist = array();
2556         if (is_dir($rootdir) && ($list = list_directories ($rootdir))) {
2557             $counter = 0;
2558             foreach ($list as $dir) {
2559                 // If there are directories in this folder, we are in the new user hierarchy
2560                 if ($newlist = list_directories("$rootdir/$dir")) {
2561                     foreach ($newlist as $olduserid) {
2562                         $userlist[$olduserid] = "$rootdir/$dir/$olduserid";
2563                     }
2564                 } else {
2565                     $userlist[$dir] = "$rootdir/$dir";
2566                 }
2567             }
2569             foreach ($userlist as $olduserid => $backup_location) {
2570                 //Look for dir like username in backup_ids
2571                 //If that user exists in backup_ids
2572                 if ($user = backup_getid($restore->backup_unique_code,"user",$olduserid)) {
2573                     //Only if user has been created now or if it existed previously, but he hasn't got an image (see bug 1123)
2574                     $newuserdir = make_user_directory($user->new_id, true); // Doesn't create the folder, just returns the location
2576                     // restore images if new user or image does not exist yet
2577                     if (!empty($user->new) or !check_dir_exists($newuserdir)) {
2578                         if (make_user_directory($user->new_id)) { // Creates the folder
2579                             $status = backup_copy_file($backup_location, $newuserdir, true);
2580                             $counter ++;
2581                         }
2582                         //Do some output
2583                         if ($counter % 2 == 0) {
2584                             if (!defined('RESTORE_SILENTLY')) {
2585                                 echo ".";
2586                                 if ($counter % 40 == 0) {
2587                                     echo "<br />";
2588                                 }
2589                             }
2590                             backup_flush(300);
2591                         }
2592                     }
2593                 }
2594             }
2595         }
2596         //If status is ok and whe have dirs created, returns counter to inform
2597         if ($status and $counter) {
2598             return $counter;
2599         } else {
2600             return $status;
2601         }
2602     }
2604     //This function restores the groupfiles from the temp (group_files) directory to the
2605     //dataroot/groups directory
2606     function restore_group_files($restore) {
2607         global $CFG, $DB;
2609         $status = true;
2611         $counter = 0;
2613         //First, we check to "groups" exists and create is as necessary
2614         //in CFG->dataroot
2615         $dest_dir = $CFG->dataroot.'/groups';
2616         $status = check_dir_exists($dest_dir,true);
2618         //Now, we iterate over "group_files" records to check if that user dir must be
2619         //copied (and renamed) to the "groups" dir.
2620         $rootdir = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/group_files";
2621         //Check if directory exists
2622         if (is_dir($rootdir)) {
2623             $list = list_directories ($rootdir);
2624             if ($list) {
2625                 //Iterate
2626                 $counter = 0;
2627                 foreach ($list as $dir) {
2628                     //Look for dir like groupid in backup_ids
2629                     $data = $DB->get_record ("backup_ids", array("backup_code"=>$restore->backup_unique_code,
2630                                                      "table_name"=>"groups",
2631                                                      "old_id"=>$dir));
2632                     //If that group exists in backup_ids
2633                     if ($data) {
2634                         if (!file_exists($dest_dir."/".$data->new_id)) {
2635                             $status = backup_copy_file($rootdir."/".$dir, $dest_dir."/".$data->new_id,true);
2636                             $counter ++;
2637                         }
2638                         //Do some output
2639                         if ($counter % 2 == 0) {
2640                             if (!defined('RESTORE_SILENTLY')) {
2641                                 echo ".";
2642                                 if ($counter % 40 == 0) {
2643                                     echo "<br />";
2644                                 }
2645                             }
2646                             backup_flush(300);
2647                         }
2648                     }
2649                 }
2650             }
2651         }
2652         //If status is ok and whe have dirs created, returns counter to inform
2653         if ($status and $counter) {
2654             return $counter;
2655         } else {
2656             return $status;
2657         }
2658     }
2660     //This function restores the course files from the temp (course_files) directory to the
2661     //dataroot/course_id directory
2662     function restore_course_files($restore) {
2663         global $CFG;
2665         $status = true;
2667         $counter = 0;
2669         //First, we check to "course_id" exists and create is as necessary
2670         //in CFG->dataroot
2671         $dest_dir = $CFG->dataroot."/".$restore->course_id;
2672         $status = check_dir_exists($dest_dir,true);
2674         //Now, we iterate over "course_files" records to check if that file/dir must be
2675         //copied to the "dest_dir" dir.
2676         $rootdir = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/course_files";
2677         //Check if directory exists
2678         if (is_dir($rootdir)) {
2679             $list = list_directories_and_files ($rootdir);
2680             if ($list) {
2681                 //Iterate
2682                 $counter = 0;
2683                 foreach ($list as $dir) {
2684                     //Copy the dir to its new location
2685                     //Only if destination file/dir doesn exists
2686                     if (!file_exists($dest_dir."/".$dir)) {
2687                         $status = backup_copy_file($rootdir."/".$dir,
2688                                       $dest_dir."/".$dir,true);
2689                         $counter ++;
2690                     }
2691                     //Do some output
2692                     if ($counter % 2 == 0) {
2693                         if (!defined('RESTORE_SILENTLY')) {
2694                             echo ".";
2695                             if ($counter % 40 == 0) {
2696                                 echo "<br />";
2697                             }
2698                         }
2699                         backup_flush(300);
2700                     }
2701                 }
2702             }
2703         }
2704         //If status is ok and whe have dirs created, returns counter to inform
2705         if ($status and $counter) {
2706             return $counter;
2707         } else {
2708             return $status;
2709         }
2710     }
2712     //This function restores the site files from the temp (site_files) directory to the
2713     //dataroot/SITEID directory
2714     function restore_site_files($restore) {
2715         global $CFG;
2717         $status = true;
2719         $counter = 0;
2721         //First, we check to "course_id" exists and create is as necessary
2722         //in CFG->dataroot
2723         $dest_dir = $CFG->dataroot."/".SITEID;
2724         $status = check_dir_exists($dest_dir,true);
2726         //Now, we iterate over "site_files" files to check if that file/dir must be
2727         //copied to the "dest_dir" dir.
2728         $rootdir = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/site_files";
2729         //Check if directory exists
2730         if (is_dir($rootdir)) {
2731             $list = list_directories_and_files ($rootdir);
2732             if ($list) {
2733                 //Iterate
2734                 $counter = 0;
2735                 foreach ($list as $dir) {
2736                     //no need to deal with 'maintenance.html' here anymore - MDL-18594
2737                     //Copy the dir to its new location
2738                     //Only if destination file/dir doesn exists
2739                     if (!file_exists($dest_dir."/".$dir)) {
2740                         $status = backup_copy_file($rootdir."/".$dir,
2741                                       $dest_dir."/".$dir,true);
2742                         $counter ++;
2743             &