f9696c485f1e4f8ddc7afa295f7ebf7a961d1ad9
[moodle.git] / backup / restorelib.php
1 <?php //$Id$
2     //Functions used in restore
3    
4     //This function unzips a zip file in the same directory that it is
5     //It automatically uses pclzip or command line unzip
6     function restore_unzip ($file) {
7         
8         return unzip_file($file, '', false);
10     }
12     //This function checks if moodle.xml seems to be a valid xml file
13     //(exists, has an xml header and a course main tag
14     function restore_check_moodle_file ($file) {
15     
16         $status = true;
18         //Check if it exists
19         if ($status = is_file($file)) {
20             //Open it and read the first 200 bytes (chars)
21             $handle = fopen ($file, "r");
22             $first_chars = fread($handle,200);
23             $status = fclose ($handle);
24             //Chek if it has the requires strings
25             if ($status) {
26                 $status = strpos($first_chars,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
27                 if ($status !== false) {
28                     $status = strpos($first_chars,"<MOODLE_BACKUP>");
29                 }
30             }
31         }   
33         return $status;  
34     }   
36     //This function iterates over all modules in backup file, searching for a
37     //MODNAME_refresh_events() to execute. Perhaps it should ve moved to central Moodle...
38     function restore_refresh_events($restore) {
39    
40         global $CFG;
41         $status = true;
42         
43         //Take all modules in backup
44         $modules = $restore->mods;
45         //Iterate
46         foreach($modules as $name => $module) {
47             //Only if the module is being restored
48             if ($module->restore == 1) {
49                 //Include module library
50                 include_once("$CFG->dirroot/mod/$name/lib.php");
51                 //If module_refresh_events exists
52                 $function_name = $name."_refresh_events";
53                 if (function_exists($function_name)) {
54                     $status = $function_name($restore->course_id);
55                 }
56             }
57         }
58         return $status;
59     }
61     //This function makes all the necessary calls to xxxx_decode_content_links_caller()
62     //function in each module, passing them the desired contents to be decoded
63     //from backup format to destination site/course in order to mantain inter-activities
64     //working in the backup/restore process
65     function restore_decode_content_links($restore) {
66         global $CFG;
68         $status = true;
70         if (!defined('RESTORE_SILENTLY')) {
71             echo "<ul>";
72         }
73         foreach ($restore->mods as $name => $info) {
74             //If the module is being restored
75             if ($info->restore == 1) {
76                 //Check if the xxxx_decode_content_links_caller exists
77                     include_once("$CFG->dirroot/mod/$name/restorelib.php");
78                 $function_name = $name."_decode_content_links_caller";
79                 if (function_exists($function_name)) {
80                     if (!defined('RESTORE_SILENTLY')) {
81                         echo "<li>".get_string ("from")." ".get_string("modulenameplural",$name);
82                         echo '</li>';
83                     }
84                     $status = $function_name($restore);
85                 }
86             }
87         }
88         if (!defined('RESTORE_SILENTLY')) {
89             echo "</ul>";
90         }
91         
92         // TODO: process all html text also in blocks too
93         
94         return $status;
95     }
96     
97     //This function is called from all xxxx_decode_content_links_caller(),
98     //its task is to ask all modules (maybe other linkable objects) to restore
99     //links to them.
100     function restore_decode_content_links_worker($content,$restore) {
101         foreach($restore->mods as $name => $info) {
102             $function_name = $name."_decode_content_links";
103             if (function_exists($function_name)) {
104                 $content = $function_name($content,$restore);
105             }
106         }
107         return $content;
108     }
110     //This function converts all the wiki texts in the restored course
111     //to the Markdown format. Used only for backup files prior 2005041100.
112     //It calls every module xxxx_convert_wiki2markdown function
113     function restore_convert_wiki2markdown($restore) {
115         $status = true;
117         if (!defined('RESTORE_SILENTLY')) {
118             echo "<ul>";
119         }
120         foreach ($restore->mods as $name => $info) {
121             //If the module is being restored
122             if ($info->restore == 1) {
123                 //Check if the xxxx_restore_wiki2markdown exists
124                 $function_name = $name."_restore_wiki2markdown";
125                 if (function_exists($function_name)) {
126                     $status = $function_name($restore);
127                     if (!defined('RESTORE_SILENTLY')) {
128                         echo "<li>".get_string("modulenameplural",$name);
129                         echo '</li>';
130                     }
131                 }
132             }
133         }
134         if (!defined('RESTORE_SILENTLY')) {
135             echo "</ul>";
136         }
137         return $status;
138     }
140     //This function receives a wiki text in the restore process and
141     //return it with every link to modules " modulename:moduleid"
142     //converted if possible. See the space before modulename!!
143     function restore_decode_wiki_content($content,$restore) {
145         global $CFG;
146         
147         $result = $content;
148         
149         $searchstring='/ ([a-zA-Z]+):([0-9]+)\(([^)]+)\)/';
150         //We look for it
151         preg_match_all($searchstring,$content,$foundset);
152         //If found, then we are going to look for its new id (in backup tables)
153         if ($foundset[0]) { 
154             //print_object($foundset);                                     //Debug
155             //Iterate over foundset[2]. They are the old_ids               
156             foreach($foundset[2] as $old_id) {
157                 //We get the needed variables here (course id)
158                 $rec = backup_getid($restore->backup_unique_code,"course_modules",$old_id);
159                 //Personalize the searchstring
160                 $searchstring='/ ([a-zA-Z]+):'.$old_id.'\(([^)]+)\)/';
161                 //If it is a link to this course, update the link to its new location
162                 if($rec->new_id) {
163                     //Now replace it
164                     $result= preg_replace($searchstring,' $1:'.$rec->new_id.'($2)',$result);
165                 } else {
166                     //It's a foreign link so redirect it to its original URL
167                     $result= preg_replace($searchstring,$restore->original_wwwroot.'/mod/$1/view.php?id='.$old_id.'($2)',$result);
168                 }
169             }
170         }
171         return $result;
172     }
175     //This function read the xml file and store it data from the info zone in an object
176     function restore_read_xml_info ($xml_file) {
178         //We call the main read_xml function, with todo = INFO
179         $info = restore_read_xml ($xml_file,"INFO",false);
181         return $info;
182     }
184     //This function read the xml file and store it data from the course header zone in an object  
185     function restore_read_xml_course_header ($xml_file) {
187         //We call the main read_xml function, with todo = COURSE_HEADER
188         $info = restore_read_xml ($xml_file,"COURSE_HEADER",false);
190         return $info;
191     }
193     //This function read the xml file and store its data from the blocks in a object
194     function restore_read_xml_blocks ($xml_file) {
196         //We call the main read_xml function, with todo = BLOCKS
197         $info = restore_read_xml ($xml_file,'BLOCKS',false);
199         return $info;
200     }
202     //This function read the xml file and store its data from the sections in a object
203     function restore_read_xml_sections ($xml_file) {
205         //We call the main read_xml function, with todo = SECTIONS
206         $info = restore_read_xml ($xml_file,"SECTIONS",false);
208         return $info;
209     }
210     
211     //This function read the xml file and store its data from the metacourse in a object
212     function restore_read_xml_metacourse ($xml_file) {
214         //We call the main read_xml function, with todo = METACOURSE
215         $info = restore_read_xml ($xml_file,"METACOURSE",false);
217         return $info;
218     }
220     //This function read the xml file and store its data from the gradebook in a object
221     function restore_read_xml_gradebook ($restore, $xml_file) {
223         //We call the main read_xml function, with todo = GRADEBOOK
224         $info = restore_read_xml ($xml_file,"GRADEBOOK",$restore);
225     
226         return $info;
227     }
229     //This function read the xml file and store its data from the users in 
230     //backup_ids->info db (and user's id in $info)
231     function restore_read_xml_users ($restore,$xml_file) {
233         //We call the main read_xml function, with todo = USERS
234         $info = restore_read_xml ($xml_file,"USERS",$restore);
236         return $info;
237     }
239     //This function read the xml file and store its data from the messages in
240     //backup_ids->message backup_ids->message_read and backup_ids->contact and db (and their counters in info)
241     function restore_read_xml_messages ($restore,$xml_file) {
243         //We call the main read_xml function, with todo = MESSAGES
244         $info = restore_read_xml ($xml_file,"MESSAGES",$restore);
246         return $info;
247     }
250     //This function read the xml file and store its data from the questions in
251     //backup_ids->info db (and category's id in $info)
252     function restore_read_xml_questions ($restore,$xml_file) {
254         //We call the main read_xml function, with todo = QUESTIONS
255         $info = restore_read_xml ($xml_file,"QUESTIONS",$restore);
257         return $info;
258     }
260     //This function read the xml file and store its data from the scales in
261     //backup_ids->info db (and scale's id in $info)
262     function restore_read_xml_scales ($restore,$xml_file) {
264         //We call the main read_xml function, with todo = SCALES
265         $info = restore_read_xml ($xml_file,"SCALES",$restore);
267         return $info;
268     }
270     //This function read the xml file and store its data from the groups in
271     //backup_ids->info db (and group's id in $info)
272     function restore_read_xml_groups ($restore,$xml_file) {
274         //We call the main read_xml function, with todo = GROUPS
275         $info = restore_read_xml ($xml_file,"GROUPS",$restore);
277         return $info;
278     }
280     //This function read the xml file and store its data from the events (course) in
281     //backup_ids->info db (and event's id in $info)
282     function restore_read_xml_events ($restore,$xml_file) {
284         //We call the main read_xml function, with todo = EVENTS
285         $info = restore_read_xml ($xml_file,"EVENTS",$restore);
287         return $info;
288     }
290     //This function read the xml file and store its data from the modules in
291     //backup_ids->info
292     function restore_read_xml_modules ($restore,$xml_file) {
294         //We call the main read_xml function, with todo = MODULES
295         $info = restore_read_xml ($xml_file,"MODULES",$restore);
297         return $info;
298     }
300     //This function read the xml file and store its data from the logs in
301     //backup_ids->info
302     function restore_read_xml_logs ($restore,$xml_file) {
304         //We call the main read_xml function, with todo = LOGS
305         $info = restore_read_xml ($xml_file,"LOGS",$restore);
307         return $info;
308     }
310     //This function prints the contents from the info parammeter passed
311     function restore_print_info ($info) {
313         global $CFG;
315         $status = true;
316         if ($info) {
317             //This is tha align to every ingo table      
318             $table->align = array ("right","left");
319             //This is the nowrap clause 
320             $table->wrap = array ("","nowrap");
321             //The width
322             $table->width = "70%";
323             //Put interesting info in table
324             //The backup original name
325             $tab[0][0] = "<b>".get_string("backuporiginalname").":</b>";
326             $tab[0][1] = $info->backup_name;
327             //The moodle version
328             $tab[1][0] = "<b>".get_string("moodleversion").":</b>";
329             $tab[1][1] = $info->backup_moodle_release." (".$info->backup_moodle_version.")";
330             //The backup version
331             $tab[2][0] = "<b>".get_string("backupversion").":</b>";
332             $tab[2][1] = $info->backup_backup_release." (".$info->backup_backup_version.")";
333             //The backup date
334             $tab[3][0] = "<b>".get_string("backupdate").":</b>";
335             $tab[3][1] = userdate($info->backup_date);
336             //Print title
337             print_heading(get_string("backup").":");
338             $table->data = $tab;
339             //Print backup general info
340             print_table($table);
342             if ($info->backup_backup_version <= 2005070500 && !empty($CFG->unicodedb)) {
343                  notify(get_string('backupnonisowarning'));  // Message informing that this backup may not work!
344             }
346             //Now backup contents in another table
347             $tab = array();
348             //First mods info
349             $mods = $info->mods;
350             $elem = 0;
351             foreach ($mods as $key => $mod) {
352                 $tab[$elem][0] = "<b>".get_string("modulenameplural",$key).":</b>";
353                 if ($mod->backup == "false") {
354                     $tab[$elem][1] = get_string("notincluded");
355                 } else {
356                     if ($mod->userinfo == "true") {
357                         $tab[$elem][1] = get_string("included")." ".get_string("withuserdata");
358                     } else {
359                         $tab[$elem][1] = get_string("included")." ".get_string("withoutuserdata");
360                     }
361                     if (is_array($mod->instances) && count($mod->instances)) {
362                         foreach ($mod->instances as $instance) {
363                             if ($instance->backup) {
364                                 $elem++;
365                                 $tab[$elem][0] = $instance->name;
366                                 if ($instance->userinfo == 'true') {
367                                     $tab[$elem][1] = get_string("included")." ".get_string("withuserdata");
368                                 } else {
369                                     $tab[$elem][1] = get_string("included")." ".get_string("withoutuserdata");
370                                 }
371                             }
372                         }
373                     }
374                 }
375                 $elem++;
376             }
377             //Metacourse info
378             $tab[$elem][0] = "<b>".get_string("metacourse").":</b>";
379             if ($info->backup_metacourse == "true") {
380                 $tab[$elem][1] = get_string("yes");
381             } else {
382                 $tab[$elem][1] = get_string("no");
383             }
384             $elem++;
385             //Users info
386             $tab[$elem][0] = "<b>".get_string("users").":</b>";
387             $tab[$elem][1] = get_string($info->backup_users);
388             $elem++;
389             //Logs info
390             $tab[$elem][0] = "<b>".get_string("logs").":</b>";
391             if ($info->backup_logs == "true") {
392                 $tab[$elem][1] = get_string("yes");
393             } else {
394                 $tab[$elem][1] = get_string("no");
395             }
396             $elem++;
397             //User Files info
398             $tab[$elem][0] = "<b>".get_string("userfiles").":</b>";
399             if ($info->backup_user_files == "true") {
400                 $tab[$elem][1] = get_string("yes");
401             } else {
402                 $tab[$elem][1] = get_string("no");
403             }
404             $elem++;
405             //Course Files info
406             $tab[$elem][0] = "<b>".get_string("coursefiles").":</b>";
407             if ($info->backup_course_files == "true") {
408                 $tab[$elem][1] = get_string("yes");
409             } else {
410                 $tab[$elem][1] = get_string("no");
411             }
412             $elem++;
413             //Messages info (only showed if present)
414             if ($info->backup_messages == 'true') {
415                 $tab[$elem][0] = "<b>".get_string('messages','message').":</b>";
416                 $tab[$elem][1] = get_string('yes');
417                 $elem++;
418             } else {
419                 //Do nothing
420             }
421             $table->data = $tab;
422             //Print title
423             print_heading(get_string("backupdetails").":");
424             //Print backup general info
425             print_table($table);
426         } else {
427             $status = false;
428         }
430         return $status;
431     }
433     //This function prints the contents from the course_header parammeter passed
434     function restore_print_course_header ($course_header) {
436         $status = true;
437         if ($course_header) {
438             //This is tha align to every ingo table
439             $table->align = array ("right","left");
440             //The width
441             $table->width = "70%";
442             //Put interesting course header in table
443             //The course name
444             $tab[0][0] = "<b>".get_string("name").":</b>";
445             $tab[0][1] = $course_header->course_fullname." (".$course_header->course_shortname.")";
446             //The course summary
447             $tab[1][0] = "<b>".get_string("summary").":</b>";
448             $tab[1][1] = $course_header->course_summary;
449             $table->data = $tab;
450             //Print title
451             print_heading(get_string("course").":");
452             //Print backup course header info
453             print_table($table);
454         } else {
455             $status = false; 
456         }
457         return $status;
458     }
460     //This function create a new course record.
461     //When finished, course_header contains the id of the new course
462     function restore_create_new_course($restore,&$course_header) {
464         global $CFG;
465  
466         $status = true;
468         $fullname = $course_header->course_fullname;
469         $shortname = $course_header->course_shortname;
470         $currentfullname = "";
471         $currentshortname = "";
472         $counter = 0;
473         //Iteratere while the name exists
474         do {
475             if ($counter) {
476                 $suffixfull = " ".get_string("copyasnoun")." ".$counter;
477                 $suffixshort = "_".$counter;
478             } else {
479                 $suffixfull = "";
480                 $suffixshort = "";
481             }
482             $currentfullname = $fullname.$suffixfull;
483             // Limit the size of shortname - database column accepts <= 15 chars
484             $currentshortname = substr($shortname, 0, 15 - strlen($suffixshort)).$suffixshort;
485             $coursefull  = get_record("course","fullname",addslashes($currentfullname));
486             $courseshort = get_record("course","shortname",addslashes($currentshortname));
487             $counter++;
488         } while ($coursefull || $courseshort);
490         //New name = currentname
491         $course_header->course_fullname = $currentfullname;
492         $course_header->course_shortname = $currentshortname;
493         
494         //Now calculate the category
495         $category = get_record("course_categories","id",$course_header->category->id,
496                                                    "name",addslashes($course_header->category->name));
497         //If no exists, try by name only
498         if (!$category) {
499             $category = get_record("course_categories","name",addslashes($course_header->category->name));
500         }
501         //If no exists, get category id 1
502         if (!$category) {
503             $category = get_record("course_categories","id","1");
504         }
505         //If category 1 doesn'exists, lets create the course category (get it from backup file)
506         if (!$category) {
507             $ins_category->name = addslashes($course_header->category->name);
508             $ins_category->parent = 0;
509             $ins_category->sortorder = 0;
510             $ins_category->coursecount = 0;
511             $ins_category->visible = 0;            //To avoid interferences with the rest of the site
512             $ins_category->timemodified = time();
513             $newid = insert_record("course_categories",$ins_category);
514             $category->id = $newid;
515             $category->name = $course_header->category->name;
516         }
517         //If exists, put new category id
518         if ($category) {
519             $course_header->category->id = $category->id;
520             $course_header->category->name = $category->name;
521         //Error, cannot locate category
522         } else {
523             $course_header->category->id = 0;
524             $course_header->category->name = get_string("unknowncategory");
525             $status = false;
526         }
528         //Create the course_object
529         if ($status) {
530             $course->category = addslashes($course_header->category->id);
531             $course->password = addslashes($course_header->course_password);
532             $course->fullname = addslashes($course_header->course_fullname);
533             $course->shortname = addslashes($course_header->course_shortname);
534             $course->idnumber = addslashes($course_header->course_idnumber);
535             $course->idnumber = ''; //addslashes($course_header->course_idnumber); // we don't want this at all.
536             $course->summary = restore_decode_absolute_links(addslashes($course_header->course_summary));
537             $course->format = addslashes($course_header->course_format);
538             $course->showgrades = addslashes($course_header->course_showgrades);
539             $course->newsitems = addslashes($course_header->course_newsitems);
540             $course->teacher = addslashes($course_header->course_teacher);
541             $course->teachers = addslashes($course_header->course_teachers);
542             $course->student = addslashes($course_header->course_student);
543             $course->students = addslashes($course_header->course_students);
544             $course->guest = addslashes($course_header->course_guest);
545             $course->startdate = addslashes($course_header->course_startdate);
546             $course->enrolperiod = addslashes($course_header->course_enrolperiod);
547             $course->numsections = addslashes($course_header->course_numsections);
548             //$course->showrecent = addslashes($course_header->course_showrecent);   INFO: This is out in 1.3
549             $course->maxbytes = addslashes($course_header->course_maxbytes);
550             $course->showreports = addslashes($course_header->course_showreports);
551             if (isset($course_header->course_groupmode)) {
552                 $course->groupmode = addslashes($course_header->course_groupmode);
553             }
554             if (isset($course_header->course_groupmodeforce)) {
555                 $course->groupmodeforce = addslashes($course_header->course_groupmodeforce);
556             }
557             $course->lang = addslashes($course_header->course_lang);
558             $course->theme = addslashes($course_header->course_theme);
559             $course->cost = addslashes($course_header->course_cost);
560             $course->currency = addslashes($course_header->course_currency);
561             $course->marker = addslashes($course_header->course_marker);
562             $course->visible = addslashes($course_header->course_visible);
563             $course->hiddensections = addslashes($course_header->course_hiddensections);
564             $course->timecreated = addslashes($course_header->course_timecreated);
565             $course->timemodified = addslashes($course_header->course_timemodified);
566             $course->metacourse = addslashes($course_header->course_metacourse);
567             //Calculate sortorder field
568             $sortmax = get_record_sql('SELECT MAX(sortorder) AS max
569                                        FROM ' . $CFG->prefix . 'course
570                                        WHERE category=' . $course->category);
571             if (!empty($sortmax->max)) {
572                 $course->sortorder = $sortmax->max + 1;
573                 unset($sortmax);
574             } else {
575                 $course->sortorder = 100;
576             }
578             //Now, recode some languages (Moodle 1.5)
579             if ($course->lang == 'ma_nt') {
580                 $course->lang = 'mi_nt';
581             }
583             //Disable course->metacourse if avoided in restore config
584             if (!$restore->metacourse) {
585                 $course->metacourse = 0;
586             }
588             //Check if the theme exists in destination server
589             $themes = get_list_of_themes();
590             if (!in_array($course->theme, $themes)) {
591                 $course->theme = '';
592             } 
594             //Now insert the record
595             $newid = insert_record("course",$course);
596             if ($newid) {
597                 //save old and new course id
598                 backup_putid ($restore->backup_unique_code,"course",$course_header->course_id,$newid);
599                 //Replace old course_id in course_header
600                 $course_header->course_id = $newid;
601             } else {
602                 $status = false;
603             }
604         }
606         return $status;
607     }
609    /**
610     * Returns the best question category (id) found to restore one
611     * question category from a backup file. Works by stamp (since Moodle 1.1)
612     * or by name (for older versions).
613     *
614     * @param object  $cat      the question_categories record to be searched
615     * @param integer $courseid the course where we are restoring
616     * @return integer the id of a existing question_category or 0 (not found)
617     */
618     function restore_get_best_question_category($cat, $courseid) {
619         
620         $found = 0;
622         //Decide how to work (by stamp or name)
623         if ($cat->stamp) {
624             $searchfield = 'stamp';
625             $searchvalue = $cat->stamp;
626         } else {
627             $searchfield = 'name';
628             $searchvalue = $cat->name;
629         }
630         
631         //First shot. Try to get the category from the course being restored
632         if ($fcat = get_record('question_categories','course',$courseid,$searchfield,$searchvalue)) {
633             $found = $fcat->id;
634         //Second shot. Try to obtain any concordant category and check its publish status and editing rights
635         } else if ($fcats = get_records('question_categories', $searchfield, $searchvalue, 'id', 'id, publish, course')) {
636             foreach ($fcats as $fcat) {
637                 if ($fcat->publish == 1 && isteacheredit($fcat->course)) {
638                     $found = $fcat->id;
639                     break;
640                 }
641             }
642         }
644         return $found;
645     }
647     //This function creates all the block stuff when restoring courses
648     //It calls selectively to  restore_create_block_instances() for 1.5 
649     //and above backups. Upwards compatible with old blocks.
650     function restore_create_blocks($restore, $backup_block_format, $blockinfo, $xml_file) {
652         $status = true;
654         delete_records('block_instance', 'pageid', $restore->course_id, 'pagetype', PAGE_COURSE_VIEW);
655         if (empty($backup_block_format)) {     // This is a backup from Moodle < 1.5
656             if (empty($blockinfo)) {
657                 // Looks like it's from Moodle < 1.3. Let's give the course default blocks...
658                 $newpage = page_create_object(PAGE_COURSE_VIEW, $restore->course_id);
659                 blocks_repopulate_page($newpage);
660             } else {
661                 // We just have a blockinfo field, this is a legacy 1.4 or 1.3 backup
662                 $blockrecords = get_records_select('block', '', '', 'name, id');
663                 $temp_blocks_l = array();
664                 $temp_blocks_r = array();
665                 @list($temp_blocks_l, $temp_blocks_r) = explode(':', $blockinfo);
666                 $temp_blocks = array(BLOCK_POS_LEFT => explode(',', $temp_blocks_l), BLOCK_POS_RIGHT => explode(',', $temp_blocks_r));
667                 foreach($temp_blocks as $blockposition => $blocks) {
668                     $blockweight = 0;
669                     foreach($blocks as $blockname) { 
670                         if(!isset($blockrecords[$blockname])) {
671                             // We don't know anything about this block!
672                             continue;
673                         }
674                         $blockinstance = new stdClass;
675                         // Remove any - prefix before doing the name-to-id mapping
676                         if(substr($blockname, 0, 1) == '-') {
677                             $blockname = substr($blockname, 1);
678                             $blockinstance->visible = 0;
679                         } else {
680                             $blockinstance->visible = 1;
681                         }
682                         $blockinstance->blockid  = $blockrecords[$blockname]->id;
683                         $blockinstance->pageid   = $restore->course_id;
684                         $blockinstance->pagetype = PAGE_COURSE_VIEW;
685                         $blockinstance->position = $blockposition;
686                         $blockinstance->weight   = $blockweight;
687                         if(!$status = insert_record('block_instance', $blockinstance)) {
688                             $status = false;
689                         }
690                         ++$blockweight;
691                     }
692                 }
693             }
694         } else if($backup_block_format == 'instances') {
695             $status = restore_create_block_instances($restore,$xml_file);
696         }
698         return $status;
700     } 
702     //This function creates all the block_instances from xml when restoring in a
703     //new course
704     function restore_create_block_instances($restore,$xml_file) {
706         $status = true;
707         //Check it exists
708         if (!file_exists($xml_file)) {
709             $status = false;
710         }
711         //Get info from xml
712         if ($status) {
713             $info = restore_read_xml_blocks($xml_file);
714         }
716         if(empty($info->instances)) {
717             return $status;
718         }
720         // First of all, iterate over the blocks to see which distinct pages we have
721         // in our hands and arrange the blocks accordingly.
722         $pageinstances = array();
723         foreach($info->instances as $instance) {
725             //pagetype and pageid black magic, we have to handle the case of blocks for the
726             //course, blocks from other pages in that course etc etc etc.
728             if($instance->pagetype == PAGE_COURSE_VIEW) {
729                 // This one's easy...
730                 $instance->pageid  = $restore->course_id;
731             }
732             else {
733                 $parts = explode('-', $instance->pagetype);
734                 if($parts[0] == 'mod') {
735                     if(!$restore->mods[$parts[1]]->restore) {
736                         continue;
737                     }
738                     $getid = backup_getid($restore->backup_unique_code, $parts[1], $instance->pageid);
739                     $instance->pageid = $getid->new_id;
740                 }
741                 else {
742                     // Not invented here ;-)
743                     continue;
744                 }
745             }
747             if(!isset($pageinstances[$instance->pagetype])) {
748                 $pageinstances[$instance->pagetype] = array();
749             }
750             if(!isset($pageinstances[$instance->pagetype][$instance->pageid])) {
751                 $pageinstances[$instance->pagetype][$instance->pageid] = array();
752             }
754             $pageinstances[$instance->pagetype][$instance->pageid][] = $instance;
755         }
757         $blocks = get_records_select('block', '', '', 'name, id, multiple');
759         // For each type of page we have restored
760         foreach($pageinstances as $thistypeinstances) {
762             // For each page id of that type
763             foreach($thistypeinstances as $thisidinstances) {
765                 $addedblocks = array();
766                 $maxweights  = array();
768                 // For each block instance in that page
769                 foreach($thisidinstances as $instance) {
771                     if(!isset($blocks[$instance->name])) {
772                         //We are trying to restore a block we don't have...
773                         continue;
774                     }
775     
776                     //If we have already added this block once and multiples aren't allowed, disregard it
777                     if(!$blocks[$instance->name]->multiple && isset($addedblocks[$instance->name])) {
778                         continue;
779                     }
781                     //If its the first block we add to a new position, start weight counter equal to 0.
782                     if(empty($maxweights[$instance->position])) {
783                         $maxweights[$instance->position] = 0;
784                     }
785     
786                     //If the instance weight is greater than the weight counter (we skipped some earlier
787                     //blocks most probably), bring it back in line.
788                     if($instance->weight > $maxweights[$instance->position]) {
789                         $instance->weight = $maxweights[$instance->position];
790                     }
792                     //Add this instance
793                     $instance->blockid = $blocks[$instance->name]->id;
794                     
795                     if(!insert_record('block_instance', $instance)) {
796                         $status = false;
797                         break;
798                     }
799     
800                     //Now we can increment the weight counter
801                     ++$maxweights[$instance->position];
802     
803                     //Keep track of block types we have already added
804                     $addedblocks[$instance->name] = true;
806                 }
807             }
808         }
810         return $status;
811     }
813     //This function creates all the course_sections and course_modules from xml
814     //when restoring in a new course or simply checks sections and create records
815     //in backup_ids when restoring in a existing course
816     function restore_create_sections(&$restore, $xml_file) {
818         global $CFG,$db;
820         $status = true;
821         //Check it exists
822         if (!file_exists($xml_file)) {
823             $status = false;
824         }
825         //Get info from xml
826         if ($status) {
827             $info = restore_read_xml_sections($xml_file);
828         }
829         //Put the info in the DB, recoding ids and saving the in backup tables
831         $sequence = "";
833         if ($info) {
834             //For each, section, save it to db
835             foreach ($info->sections as $key => $sect) {
836                 $sequence = "";
837                 $section->course = $restore->course_id;
838                 $section->section = $sect->number;
839                 $section->summary = restore_decode_absolute_links(addslashes($sect->summary));
840                 $section->visible = $sect->visible;
841                 $section->sequence = "";
842                 //Now calculate the section's newid
843                 $newid = 0;
844                 if ($restore->restoreto == 2) {
845                     //Save it to db (only if restoring to new course)
846                     $newid = insert_record("course_sections",$section);
847                 } else {
848                     //Get section id when restoring in existing course
849                     $rec = get_record("course_sections","course",$restore->course_id,
850                                                         "section",$section->section);
851                     //If that section doesn't exist, get section 0 (every mod will be
852                     //asigned there
853                     if(!$rec) {
854                         $rec = get_record("course_sections","course",$restore->course_id,
855                                                             "section","0");
856                     }
857                     //New check. If section 0 doesn't exist, insert it here !!
858                     //Teorically this never should happen but, in practice, some users
859                     //have reported this issue.
860                     if(!$rec) {
861                         $zero_sec->course = $restore->course_id;
862                         $zero_sec->section = 0;
863                         $zero_sec->summary = "";
864                         $zero_sec->sequence = "";
865                         $newid = insert_record("course_sections",$zero_sec);
866                         $rec->id = $newid;
867                         $rec->sequence = "";
868                     }
869                     $newid = $rec->id;
870                     $sequence = $rec->sequence;
871                 }
872                 if ($newid) {
873                     //save old and new section id
874                     backup_putid ($restore->backup_unique_code,"course_sections",$key,$newid);
875                 } else {
876                     $status = false;
877                 }
878                 //If all is OK, go with associated mods
879                 if ($status) {
880                     //If we have mods in the section
881                     if (!empty($sect->mods)) {
882                         //For each mod inside section
883                         foreach ($sect->mods as $keym => $mod) {
884                             //Check if we've to restore this module (and instance) 
885                             if ($restore->mods[$mod->type]->restore) {
886                                 if (!is_array($restore->mods[$mod->type]->instances)  // we don't care about per instance
887                                     || (array_key_exists($mod->instance,$restore->mods[$mod->type]->instances) 
888                                         && !empty($restore->mods[$mod->type]->instances[$mod->instance]->restore))) {
889                                     
890                                     //Get the module id from modules
891                                     $module = get_record("modules","name",$mod->type);
892                                     if ($module) {
893                                         $course_module->course = $restore->course_id;
894                                         $course_module->module = $module->id;
895                                         $course_module->section = $newid;
896                                         $course_module->added = $mod->added;
897                                         $course_module->score = $mod->score;
898                                         $course_module->indent = $mod->indent;
899                                         $course_module->visible = $mod->visible;
900                                         if (isset($mod->groupmode)) {
901                                             $course_module->groupmode = $mod->groupmode;
902                                         }
903                                         $course_module->instance = 0;
904                                         //NOTE: The instance (new) is calculated and updated in db in the
905                                         //      final step of the restore. We don't know it yet.
906                                         //print_object($course_module);                                 //Debug
907                                         //Save it to db
908                                         $newidmod = insert_record("course_modules",$course_module); 
909                                         if ($newidmod) {
910                                             //save old and new module id
911                                             //In the info field, we save the original instance of the module
912                                             //to use it later
913                                             backup_putid ($restore->backup_unique_code,"course_modules",
914                                                           $keym,$newidmod,$mod->instance);
915                                             
916                                             $restore->mods[$mod->type]->instances[$mod->instance]->restored_as_course_module = $newidmod;
917                                         } else {
918                                             $status = false;
919                                         }
920                                         //Now, calculate the sequence field
921                                         if ($status) {
922                                             if ($sequence) {
923                                                 $sequence .= ",".$newidmod;
924                                             } else {
925                                                 $sequence = $newidmod;
926                                             }
927                                         }
928                                     } else {
929                                         $status = false;
930                                     }
931                                 }
932                             }
933                         }
934                     }
935                 }
936                 //If all is OK, update sequence field in course_sections
937                 if ($status) {
938                     if (isset($sequence)) {
939                         $update_rec->id = $newid;
940                         $update_rec->sequence = $sequence;
941                         $status = update_record("course_sections",$update_rec);
942                     }
943                 }
944             }
945         } else {
946             $status = false;
947         }
948         return $status;
949     }
951     //This function creates all the metacourse data from xml, notifying 
952     //about each incidence
953     function restore_create_metacourse($restore,$xml_file) {
955         global $CFG,$db;
957         $status = true;
958         //Check it exists
959         if (!file_exists($xml_file)) {
960             $status = false;
961         }
962         //Get info from xml
963         if ($status) {
964             //Load data from XML to info
965             $info = restore_read_xml_metacourse($xml_file);
966         }
968         //Process info about metacourse
969         if ($status and $info) {
970             //Process child records
971             if (!empty($info->childs)) {
972                 foreach ($info->childs as $child) {
973                     $dbcourse = false;
974                     $dbmetacourse = false;
975                     //Check if child course exists in destination server
976                     //(by id in the same server or by idnumber and shortname in other server)
977                     if ($restore->original_wwwroot == $CFG->wwwroot) {
978                         //Same server, lets see by id
979                         $dbcourse = get_record('course','id',$child->id);
980                     } else {
981                         //Different server, lets see by idnumber and shortname, and only ONE record
982                         $dbcount = count_records('course','idnumber',$child->idnumber,'shortname',$child->shortname);
983                         if ($dbcount == 1) {
984                             $dbcourse = get_record('course','idnumber',$child->idnumber,'shortname',$child->shortname);
985                         }
986                     }
987                     //If child course has been found, insert data
988                     if ($dbcourse) {
989                         $dbmetacourse->child_course = $dbcourse->id;
990                         $dbmetacourse->parent_course = $restore->course_id;
991                         $status = insert_record ('course_meta',$dbmetacourse);
992                     } else {
993                         //Child course not found, notice!
994                         if (!defined('RESTORE_SILENTLY')) {
995                             echo '<ul><li>'.get_string ('childcoursenotfound').' ('.$child->id.'/'.$child->idnumber.'/'.$child->shortname.')</li></ul>';
996                         }
997                     }
998                 }
999                 //Now, recreate student enrolments...
1000                 sync_metacourse($restore->course_id);
1001             }
1002             //Process parent records
1003             if (!empty($info->parents)) {
1004                 foreach ($info->parents as $parent) {
1005                     $dbcourse = false;
1006                     $dbmetacourse = false;
1007                     //Check if parent course exists in destination server
1008                     //(by id in the same server or by idnumber and shortname in other server)
1009                     if ($restore->original_wwwroot == $CFG->wwwroot) {
1010                         //Same server, lets see by id
1011                         $dbcourse = get_record('course','id',$parent->id);
1012                     } else {
1013                         //Different server, lets see by idnumber and shortname, and only ONE record
1014                         $dbcount = count_records('course','idnumber',$parent->idnumber,'shortname',$parent->shortname);
1015                         if ($dbcount == 1) {
1016                             $dbcourse = get_record('course','idnumber',$parent->idnumber,'shortname',$parent->shortname);
1017                         }
1018                     }
1019                     //If parent course has been found, insert data if it is a metacourse
1020                     if ($dbcourse) {
1021                         if ($dbcourse->metacourse) {
1022                             $dbmetacourse->parent_course = $dbcourse->id;
1023                             $dbmetacourse->child_course = $restore->course_id;
1024                             $status = insert_record ('course_meta',$dbmetacourse);
1025                             //Now, recreate student enrolments in parent course
1026                             sync_metacourse($dbcourse->id);
1027                         } else {
1028                             //Parent course isn't metacourse, notice!
1029                             if (!defined('RESTORE_SILENTLY')) {
1030                                 echo '<ul><li>'.get_string ('parentcoursenotmetacourse').' ('.$parent->id.'/'.$parent->idnumber.'/'.$parent->shortname.')</li></ul>';
1031                             }
1032                         }
1033                     } else {
1034                         //Parent course not found, notice!
1035                         if (!defined('RESTORE_SILENTLY')) {
1036                             echo '<ul><li>'.get_string ('parentcoursenotfound').' ('.$parent->id.'/'.$parent->idnumber.'/'.$parent->shortname.')</li></ul>';
1037                         }
1038                     }
1039                 }
1040             }
1042         }
1043         return $status;
1044     }
1045     
1046     //This function creates all the gradebook data from xml, notifying 
1047     //about each incidence
1048     function restore_create_gradebook($restore,$xml_file) {
1050         global $CFG,$db;
1052         $status = true;
1053         //Check it exists
1054         if (!file_exists($xml_file)) {
1055             $status = false;
1056         }
1057         //Get info from xml
1058         if ($status) {
1059             //info will contain the number of record to process
1060             $info = restore_read_xml_gradebook($restore, $xml_file);
1062         //If we have info, then process preferences, letters & categories
1063             if ($info > 0) {
1064                 //Count how many we have
1065                 $preferencescount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'grade_preferences');
1066                 $letterscount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'grade_letter');
1067                 $categoriescount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'grade_category');
1069                 if ($preferencescount || $letterscount || $categoriescount) {
1070                     //Start ul
1071                     if (!defined('RESTORE_SILENTLY')) {
1072                         echo '<ul>';
1073                     }
1074                     //Number of records to get in every chunk
1075                     $recordset_size = 2;
1076                     //Flag to mark if we must continue
1077                     $continue = true;
1079                     //If there aren't preferences, stop
1080                     if (!$preferencescount) {
1081                         $continue = false;
1082                         if (!defined('RESTORE_SILENTLY')) {
1083                             echo '<li>'.get_string('backupwithoutgradebook','grade').'</li>';
1084                         }
1085                     }
1087                     //If we are restoring to an existing course and it has advanced disabled, stop
1088                     if ($restore->restoreto != 2) {
1089                         //Fetch the 'use_advanced' preferences (id = 0)
1090                         if ($pref_rec = get_record('grade_preferences','courseid',$restore->course_id,'preference',0)) {
1091                             if ($pref_rec->value == 0) {
1092                                 $continue = false;
1093                                 if (!defined('RESTORE_SILENTLY')) {
1094                                     echo '<li>'.get_string('respectingcurrentdata','grade').'</li>';
1095                                 }
1096                             }
1097                         }
1098                     }
1100                     //Process preferences
1101                     if ($preferencescount && $continue) {
1102                         if (!defined('RESTORE_SILENTLY')) {
1103                             echo '<li>'.get_string('preferences','grades').'</li>';
1104                         }
1105                         $counter = 0;
1106                         while ($counter < $preferencescount) {
1107                             //Fetch recordset_size records in each iteration
1108                             $recs = get_records_select("backup_ids","table_name = 'grade_preferences' AND backup_code = '$restore->backup_unique_code'",
1109                                                        "old_id",
1110                                                        "old_id, old_id",
1111                                                        $counter,
1112                                                        $recordset_size);
1113                             if ($recs) {
1114                                 foreach ($recs as $rec) {
1115                                     //Get the full record from backup_ids
1116                                     $data = backup_getid($restore->backup_unique_code,'grade_preferences',$rec->old_id);
1117                                     if ($data) {
1118                                         //Now get completed xmlized object
1119                                         $info = $data->info;
1120                                         //traverse_xmlize($info);                            //Debug
1121                                         //print_object ($GLOBALS['traverse_array']);         //Debug
1122                                         //$GLOBALS['traverse_array']="";                     //Debug
1123                                         //Now build the GRADE_PREFERENCES record structure
1124                                         $dbrec->courseid   = $restore->course_id;
1125                                         $dbrec->preference = backup_todb($info['GRADE_PREFERENCE']['#']['PREFERENCE']['0']['#']);
1126                                         $dbrec->value      = backup_todb($info['GRADE_PREFERENCE']['#']['VALUE']['0']['#']);
1127    
1128                                         //Structure is equal to db, insert record
1129                                         //if the preference doesn't exist
1130                                         if (!$prerec = get_record('grade_preferences','courseid',$dbrec->courseid,'preference',$dbrec->preference)) {
1131                                             $status = insert_record('grade_preferences',$dbrec);
1132                                         }
1133                                     }
1134                                     //Increment counters
1135                                     $counter++;
1136                                     //Do some output
1137                                     if ($counter % 1 == 0) {
1138                                         if (!defined('RESTORE_SILENTLY')) {
1139                                             echo ".";
1140                                             if ($counter % 20 == 0) {
1141                                                 echo "<br />";
1142                                             }
1143                                         }
1144                                         backup_flush(300);
1145                                     }
1146                                 }
1147                             }
1148                         }
1149                     }
1151                     //Process letters
1152                     //If destination course has letters, skip restoring letters
1153                     $hasletters = get_records('grade_letter', 'courseid', $restore->course_id);
1155                     if ($letterscount && $continue && !$hasletters) {
1156                         if (!defined('RESTORE_SILENTLY')) {
1157                             echo '<li>'.get_string('letters','grades').'</li>';
1158                         }
1159                         $counter = 0;
1160                         while ($counter < $letterscount) {
1161                             //Fetch recordset_size records in each iteration
1162                             $recs = get_records_select("backup_ids","table_name = 'grade_letter' AND backup_code = '$restore->backup_unique_code'",
1163                                                        "old_id",
1164                                                        "old_id, old_id",
1165                                                        $counter,
1166                                                        $recordset_size);
1167                             if ($recs) {
1168                                 foreach ($recs as $rec) {
1169                                     //Get the full record from backup_ids
1170                                     $data = backup_getid($restore->backup_unique_code,'grade_letter',$rec->old_id);
1171                                     if ($data) {
1172                                         //Now get completed xmlized object
1173                                         $info = $data->info;
1174                                         //traverse_xmlize($info);                            //Debug
1175                                         //print_object ($GLOBALS['traverse_array']);         //Debug
1176                                         //$GLOBALS['traverse_array']="";                     //Debug
1177                                         //Now build the GRADE_LETTER record structure
1178                                         $dbrec->courseid   = $restore->course_id;
1179                                         $dbrec->letter     = backup_todb($info['GRADE_LETTER']['#']['LETTER']['0']['#']);
1180                                         $dbrec->grade_high = backup_todb($info['GRADE_LETTER']['#']['GRADE_HIGH']['0']['#']);
1181                                         $dbrec->grade_low  = backup_todb($info['GRADE_LETTER']['#']['GRADE_LOW']['0']['#']);
1183                                         //Structure is equal to db, insert record
1184                                         $status = insert_record('grade_letter',$dbrec);
1185                                     }
1186                                     //Increment counters
1187                                     $counter++;
1188                                     //Do some output
1189                                     if ($counter % 1 == 0) {
1190                                         if (!defined('RESTORE_SILENTLY')) {
1191                                             echo ".";
1192                                             if ($counter % 20 == 0) {
1193                                                 echo "<br />";
1194                                             }
1195                                         }
1196                                         backup_flush(300);
1197                                     }
1198                                 }
1199                             }
1200                         }
1201                     }
1203                     //Process categories
1204                     if ($categoriescount && $continue) {
1205                         if (!defined('RESTORE_SILENTLY')) {
1206                             echo '<li>'.get_string('categories','grades').'</li>';
1207                         }
1208                         $counter = 0;
1209                         $countercat = 0;
1210                         while ($countercat < $categoriescount) {
1211                             //Fetch recordset_size records in each iteration
1212                             $recs = get_records_select("backup_ids","table_name = 'grade_category' AND backup_code = '$restore->backup_unique_code'",
1213                                                        "old_id",
1214                                                        "old_id, old_id",
1215                                                        $countercat,
1216                                                        $recordset_size);
1217                             if ($recs) {
1218                                 foreach ($recs as $rec) {
1219                                     //Get the full record from backup_ids
1220                                     $data = backup_getid($restore->backup_unique_code,'grade_category',$rec->old_id);
1221                                     if ($data) {
1222                                         //Now get completed xmlized object
1223                                         $info = $data->info;
1224                                         //traverse_xmlize($info);                            //Debug
1225                                         //print_object ($GLOBALS['traverse_array']);         //Debug
1226                                         //$GLOBALS['traverse_array']="";                     //Debug
1227                                         //Now build the GRADE_CATEGORY record structure
1228                                         $dbrec->courseid     = $restore->course_id;
1229                                         $dbrec->name         = backup_todb($info['GRADE_CATEGORY']['#']['NAME']['0']['#']);
1230                                         $dbrec->drop_x_lowest= backup_todb($info['GRADE_CATEGORY']['#']['DROP_X_LOWEST']['0']['#']);
1231                                         $dbrec->bonus_points = backup_todb($info['GRADE_CATEGORY']['#']['BONUS_POINTS']['0']['#']);
1232                                         $dbrec->hidden       = backup_todb($info['GRADE_CATEGORY']['#']['HIDDEN']['0']['#']);
1233                                         $dbrec->weight       = backup_todb($info['GRADE_CATEGORY']['#']['WEIGHT']['0']['#']);
1235                                         //If the grade_category exists in the course (by name), don't insert anything
1236                                         $catex = get_record('grade_category','courseid',$dbrec->courseid,'name',$dbrec->name);
1238                                         if (!$catex) {
1239                                             //Structure is equal to db, insert record
1240                                             $categoryid = insert_record('grade_category',$dbrec);
1241                                         } else {
1242                                             //Simply remap category
1243                                             $categoryid = $catex->id;
1244                                         }
1246                                         //Now, restore grade_item
1247                                         $items = $info['GRADE_CATEGORY']['#']['GRADE_ITEMS']['0']['#']['GRADE_ITEM'];
1249                                         //Iterate over items
1250                                         for($i = 0; $i < sizeof($items); $i++) {
1251                                             $ite_info = $items[$i];
1252                                             //traverse_xmlize($ite_info);                                                                 //Debug
1253                                             //print_object ($GLOBALS['traverse_array']);                                                  //Debug
1254                                             //$GLOBALS['traverse_array']="";                                                              //Debug
1256                                             //Now build the GRADE_ITEM record structure
1257                                             $item->courseid     = $restore->course_id;
1258                                             $item->category     = $categoryid;
1259                                             $item->module_name  = backup_todb($ite_info['#']['MODULE_NAME']['0']['#']);
1260                                             $item->cminstance   = backup_todb($ite_info['#']['CMINSTANCE']['0']['#']);
1261                                             $item->scale_grade  = backup_todb($ite_info['#']['SCALE_GRADE']['0']['#']);
1262                                             $item->extra_credit = backup_todb($ite_info['#']['EXTRA_CREDIT']['0']['#']);
1263                                             $item->sort_order   = backup_todb($ite_info['#']['SORT_ORDER']['0']['#']);
1265                                             //Check that the module has been included in the restore
1266                                             if ($restore->mods[$item->module_name]->restore) {
1267                                                 //Get the id of the moduletype
1268                                                 if ($module = get_record('modules','name',$item->module_name)) {
1269                                                     $item->modid = $module->id;
1270                                                     //Get the instance id
1271                                                     if ($instance = backup_getid($restore->backup_unique_code,$item->module_name,$item->cminstance)) {
1272                                                         $item->cminstance = $instance->new_id;
1273                                                         //Structure is equal to db, insert record
1274                                                         $itemid = insert_record('grade_item',$item);
1276                                                         //Now process grade_exceptions
1277                                                         if (!empty($ite_info['#']['GRADE_EXCEPTIONS'])) {
1278                                                             $exceptions = $ite_info['#']['GRADE_EXCEPTIONS']['0']['#']['GRADE_EXCEPTION'];
1279                                                         } else {
1280                                                             $exceptions = array();
1281                                                         }
1283                                                         //Iterate over exceptions
1284                                                         for($j = 0; $j < sizeof($exceptions); $j++) {
1285                                                             $exc_info = $exceptions[$j];
1286                                                             //traverse_xmlize($exc_info);                                                                 //Debug
1287                                                             //print_object ($GLOBALS['traverse_array']);                                                  //Debug
1288                                                             //$GLOBALS['traverse_array']="";                                                              //Debug
1290                                                             //Now build the GRADE_EXCEPTIONS record structure
1291                                                             $exception->courseid     = $restore->course_id;
1292                                                             $exception->grade_itemid = $itemid;
1293                                                             $exception->userid       = backup_todb($exc_info['#']['USERID']['0']['#']);
1295                                                             //We have to recode the useridto field
1296                                                             $user = backup_getid($restore->backup_unique_code,"user",$exception->userid);
1297                                                             if ($user) {
1298                                                                 $exception->userid = $user->new_id;
1299                                                                 //Structure is equal to db, insert record
1300                                                                 $exceptionid = insert_record('grade_exceptions',$exception);
1301                                                                 //Do some output
1302                                                                 $counter++;
1303                                                                 if ($counter % 20 == 0) {
1304                                                                     if (!defined('RESTORE_SILENTLY')) {
1305                                                                         echo ".";
1306                                                                         if ($counter % 400 == 0) {
1307                                                                             echo "<br />";
1308                                                                         }
1309                                                                     }
1310                                                                     backup_flush(300);
1311                                                                 }
1312                                                             }
1313                                                         }
1314                                                     }
1315                                                 }
1316                                             }
1317                                         }
1319                                         //Re-sort all the grade_items because we can have duplicates
1320                                         if ($grade_items = get_records ('grade_item','courseid',$restore->course_id,'sort_order','id,sort_order')) {
1321                                             $order = 1;
1322                                             foreach ($grade_items as $grade_item) {
1323                                                 $grade_item->sort_order = $order;
1324                                                 set_field ('grade_item','sort_order',$grade_item->sort_order,'id',$grade_item->id);
1325                                                 $order++;
1326                                             }
1327                                         }
1328                                     }
1329                                     //Increment counters
1330                                     $countercat++;
1331                                     //Do some output
1332                                     if ($countercat % 1 == 0) {
1333                                         if (!defined('RESTORE_SILENTLY')) {
1334                                             echo ".";
1335                                             if ($countercat % 20 == 0) {
1336                                                 echo "<br />";
1337                                             }
1338                                         }
1339                                         backup_flush(300);
1340                                     }
1341                                 }
1342                             }
1343                         }
1344                     }
1345                     if (!defined('RESTORE_SILENTLY')) {
1346                     //End ul
1347                         echo '</ul>';
1348                     }
1349                 }
1350             }
1351         }                
1352      
1353         return $status;
1354     }
1356     //This function creates all the user, user_students, user_teachers
1357     //user_course_creators and user_admins from xml
1358     function restore_create_users($restore,$xml_file) {
1360         global $CFG, $db;
1362         $status = true;
1363         //Check it exists
1364         if (!file_exists($xml_file)) {
1365             $status = false;
1366         }
1367         //Get info from xml
1368         if ($status) {
1369             //info will contain the old_id of every user
1370             //in backup_ids->info will be the real info (serialized)
1371             $info = restore_read_xml_users($restore,$xml_file);
1372         }
1374         //Now, get evey user_id from $info and user data from $backup_ids
1375         //and create the necessary records (users, user_students, user_teachers
1376         //user_course_creators and user_admins
1377         if (!empty($info->users)) {
1378             //For each user, take its info from backup_ids
1379             foreach ($info->users as $userid) {
1380                 $rec = backup_getid($restore->backup_unique_code,"user",$userid); 
1381                 $user = $rec->info;
1383                 //Now, recode some languages (Moodle 1.5)
1384                 if ($user->lang == 'ma_nt') {
1385                     $user->lang = 'mi_nt';
1386                 }
1388                 //Check if it's admin and coursecreator
1389                 $is_admin =         !empty($user->roles['admin']);
1390                 $is_coursecreator = !empty($user->roles['coursecreator']);
1392                 //Check if it's teacher and student
1393                 $is_teacher = !empty($user->roles['teacher']);
1394                 $is_student = !empty($user->roles['student']);
1396                 //Check if it's needed
1397                 $is_needed = !empty($user->roles['needed']);
1399                 //Calculate if it is a course user
1400                 //Has role teacher or student or needed
1401                 $is_course_user = ($is_teacher or $is_student or $is_needed);
1403                 //To store new ids created
1404                 $newid=null;
1405                 //check if it exists (by username) and get its id
1406                 $user_exists = true;
1407                 $user_data = get_record("user","username",addslashes($user->username));
1408                 if (!$user_data) {
1409                     $user_exists = false;
1410                 } else {
1411                     $newid = $user_data->id;
1412                 }
1413                 //Flags to see if we have to create the user, roles and preferences
1414                 $create_user = true;
1415                 $create_roles = true;
1416                 $create_preferences = true;
1418                 //If we are restoring course users and it isn't a course user
1419                 if ($restore->users == 1 and !$is_course_user) {
1420                     //If only restoring course_users and user isn't a course_user, inform to $backup_ids
1421                     $status = backup_putid($restore->backup_unique_code,"user",$userid,null,'notincourse');
1422                     $create_user = false;
1423                     $create_roles = false;
1424                     $create_preferences = false;
1425                 }
1427                 if ($user_exists and $create_user) {
1428                     //If user exists mark its newid in backup_ids (the same than old)
1429                     $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,'exists');
1430                     $create_user = false;
1431                 }
1433                 //Here, if create_user, do it
1434                 if ($create_user) {
1435                     //Unset the id because it's going to be inserted with a new one
1436                     unset ($user->id);
1437                     //We addslashes to necessary fields
1438                     $user->username = addslashes($user->username);
1439                     $user->firstname = addslashes($user->firstname);
1440                     $user->lastname = addslashes($user->lastname);
1441                     $user->email = addslashes($user->email);
1442                     $user->institution = addslashes($user->institution);
1443                     $user->department = addslashes($user->department);
1444                     $user->address = addslashes($user->address);
1445                     $user->city = addslashes($user->city);
1446                     $user->url = addslashes($user->url);
1447                     $user->description = restore_decode_absolute_links(addslashes($user->description));
1449                     //We need to analyse the AUTH field to recode it:
1450                     //   - if the field isn't set, we are in a pre 1.4 backup and we'll 
1451                     //     use $CFG->auth
1452                     //   - if the destination site has any kind of INTERNAL authentication, 
1453                     //     then apply it to the new user.
1454                     //   - if the destination site has any kind of EXTERNAL authentication, 
1455                     //     then leave the original authentication of the user.
1457                     if ((! isset($user->auth)) || is_internal_auth($CFG->auth)) {
1458                         $user->auth = $CFG->auth;
1459                     }
1461                     //We need to process the POLICYAGREED field to recalculate it:
1462                     //    - if the destination site is different (by wwwroot) reset it.
1463                     //    - if the destination site is the same (by wwwroot), leave it unmodified
1465                     if ($restore->original_wwwroot != $CFG->wwwroot) {
1466                         $user->policyagreed = 0;
1467                     } else {
1468                         //Nothing to do, we are in the same server
1469                     }
1471                     //Check if the theme exists in destination server
1472                     $themes = get_list_of_themes();
1473                     if (!in_array($user->theme, $themes)) {
1474                         $user->theme = '';
1475                     }
1477                     //We are going to create the user
1478                     //The structure is exactly as we need
1479                     $newid = insert_record ("user",$user);
1480                     //Put the new id
1481                     $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,"new");
1482                 }
1484                 //Here, if create_roles, do it as necessary
1485                 if ($create_roles) {
1486                     //Get the newid and current info from backup_ids
1487                     $data = backup_getid($restore->backup_unique_code,"user",$userid);
1488                     $newid = $data->new_id;
1489                     $currinfo = $data->info.",";
1491                     //Now, depending of the role, create records in user_studentes and user_teacher 
1492                     //and/or mark it in backup_ids
1493                     
1494                     if ($is_admin) {
1495                         //If the record (user_admins) doesn't exists
1496                         if (!record_exists("user_admins","userid",$newid)) {
1497                             //Only put status in backup_ids
1498                             $currinfo = $currinfo."admin,";
1499                             $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
1500                         }
1501                     } 
1502                     if ($is_coursecreator) {
1503                         //If the record (user_coursecreators) doesn't exists
1504                         if (!record_exists("user_coursecreators","userid",$newid)) {
1505                             //Only put status in backup_ids
1506                             $currinfo = $currinfo."coursecreator,";
1507                             $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
1508                         }
1509                     } 
1510                     if ($is_needed) {
1511                         //Only put status in backup_ids
1512                         $currinfo = $currinfo."needed,";
1513                         $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
1514                     }
1515                     if ($is_teacher) {
1516                         //If the record (teacher) doesn't exists
1517                         if (!record_exists("user_teachers","userid",$newid,"course", $restore->course_id)) {
1518                             //Put status in backup_ids 
1519                             $currinfo = $currinfo."teacher,";
1520                             $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
1521                             //Set course and user
1522                             $user->roles['teacher']->course = $restore->course_id;
1523                             $user->roles['teacher']->userid = $newid;
1525                             //Need to analyse the enrol field
1526                             //    - if it isn't set, set it to $CFG->enrol
1527                             //    - if we are in a different server (by wwwroot), set it to $CFG->enrol
1528                             //    - if we are in the same server (by wwwroot), maintain it unmodified.
1529                             if (empty($user->roles['teacher']->enrol)) {
1530                                 $user->roles['teacher']->enrol = $CFG->enrol;
1531                             } else if ($restore->original_wwwroot != $CFG->wwwroot) {
1532                                 $user->roles['teacher']->enrol = $CFG->enrol;
1533                             } else {
1534                                 //Nothing to do. Leave it unmodified
1535                             }    
1537                             //Insert data in user_teachers
1538                             //The structure is exactly as we need
1539                             $status = insert_record("user_teachers",$user->roles['teacher']);
1540                         }
1541                     } 
1542                     if ($is_student) {
1543                         //If the record (student) doesn't exists
1544                         if (!record_exists("user_students","userid",$newid,"course", $restore->course_id)) {
1545                             //Put status in backup_ids
1546                             $currinfo = $currinfo."student,";
1547                             $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
1548                             //Set course and user
1549                             $user->roles['student']->course = $restore->course_id;
1550                             $user->roles['student']->userid = $newid;
1552                             //Need to analyse the enrol field
1553                             //    - if it isn't set, set it to $CFG->enrol
1554                             //    - if we are in a different server (by wwwroot), set it to $CFG->enrol
1555                             //    - if we are in the same server (by wwwroot), maintain it unmodified.
1556                             if (empty($user->roles['student']->enrol)) {
1557                                 $user->roles['student']->enrol = $CFG->enrol;
1558                             } else if ($restore->original_wwwroot != $CFG->wwwroot) {
1559                                 $user->roles['student']->enrol = $CFG->enrol;
1560                             } else {
1561                                 //Nothing to do. Leave it unmodified
1562                             }    
1564                             //Insert data in user_students
1565                             //The structure is exactly as we need
1566                             $status = insert_record("user_students",$user->roles['student']);
1567                         }
1568                     }
1569                     if (!$is_course_user) {
1570                         //If the record (user) doesn't exists
1571                         if (!record_exists("user","id",$newid)) {
1572                             //Put status in backup_ids
1573                             $currinfo = $currinfo."user,";
1574                             $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
1575                         }
1576                     }
1577                 }
1579                 //Here, if create_preferences, do it as necessary
1580                 if ($create_preferences) {
1581                     //echo "Checking for preferences of user ".$user->username."<br />";         //Debug
1582                     //Get user new id from backup_ids
1583                     $data = backup_getid($restore->backup_unique_code,"user",$userid);
1584                     $newid = $data->new_id;
1585                     if (isset($user->user_preferences)) {
1586                         //echo "Preferences exist in backup file<br />";                         //Debug
1587                         foreach($user->user_preferences as $user_preference) {
1588                             //echo $user_preference->name." = ".$user_preference->value."<br />";    //Debug
1589                             //We check if that user_preference exists in DB
1590                             if (!record_exists("user_preferences","userid",$newid,"name",$user_preference->name)) {
1591                                 //echo "Creating it<br />";                                              //Debug
1592                                 //Prepare the record and insert it
1593                                 $user_preference->userid = $newid;
1594                                 $status = insert_record("user_preferences",$user_preference);
1595                             }
1596                         }
1597                     }
1598                 }
1599             }
1600         }
1602         return $status;
1603     }
1605     //This function creates all the structures messages and contacts
1606     function restore_create_messages($restore,$xml_file) {
1608         global $CFG;
1610         $status = true;
1611         //Check it exists
1612         if (!file_exists($xml_file)) {
1613             $status = false;
1614         }
1615         //Get info from xml
1616         if ($status) {
1617             //info will contain the id and name of every table
1618             //(message, message_read and message_contacts)
1619             //in backup_ids->info will be the real info (serialized)
1620             $info = restore_read_xml_messages($restore,$xml_file);
1622             //If we have info, then process messages & contacts
1623             if ($info > 0) {
1624                 //Count how many we have
1625                 $unreadcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'message');
1626                 $readcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'message_read');
1627                 $contactcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'message_contacts');
1628                 if ($unreadcount || $readcount || $contactcount) {
1629                     //Start ul
1630                     if (!defined('RESTORE_SILENTLY')) {
1631                         echo '<ul>';
1632                     }
1633                     //Number of records to get in every chunk
1634                     $recordset_size = 4;
1636                     //Process unread
1637                     if ($unreadcount) {
1638                         if (!defined('RESTORE_SILENTLY')) {
1639                             echo '<li>'.get_string('unreadmessages','message').'</li>';
1640                         }
1641                         $counter = 0;
1642                         while ($counter < $unreadcount) {
1643                             //Fetch recordset_size records in each iteration
1644                             $recs = get_records_select("backup_ids","table_name = 'message' AND backup_code = '$restore->backup_unique_code'","old_id","old_id, old_id",$counter,$recordset_size);
1645                             if ($recs) {
1646                                 foreach ($recs as $rec) {
1647                                     //Get the full record from backup_ids
1648                                     $data = backup_getid($restore->backup_unique_code,"message",$rec->old_id);
1649                                     if ($data) {
1650                                         //Now get completed xmlized object
1651                                         $info = $data->info;
1652                                         //traverse_xmlize($info);                            //Debug
1653                                         //print_object ($GLOBALS['traverse_array']);         //Debug
1654                                         //$GLOBALS['traverse_array']="";                     //Debug
1655                                         //Now build the MESSAGE record structure
1656                                         $dbrec->useridfrom = backup_todb($info['MESSAGE']['#']['USERIDFROM']['0']['#']);
1657                                         $dbrec->useridto = backup_todb($info['MESSAGE']['#']['USERIDTO']['0']['#']);
1658                                         $dbrec->message = backup_todb($info['MESSAGE']['#']['MESSAGE']['0']['#']);
1659                                         $dbrec->format = backup_todb($info['MESSAGE']['#']['FORMAT']['0']['#']);
1660                                         $dbrec->timecreated = backup_todb($info['MESSAGE']['#']['TIMECREATED']['0']['#']);
1661                                         $dbrec->messagetype = backup_todb($info['MESSAGE']['#']['MESSAGETYPE']['0']['#']);
1662                                         //We have to recode the useridfrom field
1663                                         $user = backup_getid($restore->backup_unique_code,"user",$dbrec->useridfrom);
1664                                         if ($user) {
1665                                             //echo "User ".$dbrec->useridfrom." to user ".$user->new_id."<br />";   //Debug
1666                                             $dbrec->useridfrom = $user->new_id;
1667                                         }
1668                                         //We have to recode the useridto field
1669                                         $user = backup_getid($restore->backup_unique_code,"user",$dbrec->useridto);
1670                                         if ($user) {
1671                                             //echo "User ".$dbrec->useridto." to user ".$user->new_id."<br />";   //Debug
1672                                             $dbrec->useridto = $user->new_id;
1673                                         }
1674                                         //Check if the record doesn't exist in DB!
1675                                         $exist = get_record('message','useridfrom',$dbrec->useridfrom,
1676                                                                       'useridto',  $dbrec->useridto,
1677                                                                       'timecreated',$dbrec->timecreated);
1678                                         if (!$exist) {
1679                                             //Not exist. Insert
1680                                             $status = insert_record('message',$dbrec);
1681                                         } else {
1682                                             //Duplicate. Do nothing
1683                                         }
1684                                     }
1685                                     //Do some output
1686                                     $counter++;
1687                                     if ($counter % 10 == 0) {
1688                                         if (!defined('RESTORE_SILENTLY')) {
1689                                             echo ".";
1690                                             if ($counter % 200 == 0) {
1691                                                 echo "<br />";
1692                                             }
1693                                         }
1694                                         backup_flush(300);
1695                                     }
1696                                 }
1697                             }
1698                         }
1699                     }
1701                     //Process read
1702                     if ($readcount) {
1703                         if (!defined('RESTORE_SILENTLY')) {
1704                             echo '<li>'.get_string('readmessages','message').'</li>';
1705                         }
1706                         $counter = 0;
1707                         while ($counter < $readcount) {
1708                             //Fetch recordset_size records in each iteration
1709                             $recs = get_records_select("backup_ids","table_name = 'message_read' AND backup_code = '$restore->backup_unique_code'","old_id","old_id, old_id",$counter,$recordset_size);
1710                             if ($recs) {
1711                                 foreach ($recs as $rec) {
1712                                     //Get the full record from backup_ids
1713                                     $data = backup_getid($restore->backup_unique_code,"message_read",$rec->old_id);
1714                                     if ($data) {
1715                                         //Now get completed xmlized object
1716                                         $info = $data->info;
1717                                         //traverse_xmlize($info);                            //Debug
1718                                         //print_object ($GLOBALS['traverse_array']);         //Debug
1719                                         //$GLOBALS['traverse_array']="";                     //Debug
1720                                         //Now build the MESSAGE_READ record structure
1721                                         $dbrec->useridfrom = backup_todb($info['MESSAGE']['#']['USERIDFROM']['0']['#']);
1722                                         $dbrec->useridto = backup_todb($info['MESSAGE']['#']['USERIDTO']['0']['#']);
1723                                         $dbrec->message = backup_todb($info['MESSAGE']['#']['MESSAGE']['0']['#']);
1724                                         $dbrec->format = backup_todb($info['MESSAGE']['#']['FORMAT']['0']['#']);
1725                                         $dbrec->timecreated = backup_todb($info['MESSAGE']['#']['TIMECREATED']['0']['#']);
1726                                         $dbrec->messagetype = backup_todb($info['MESSAGE']['#']['MESSAGETYPE']['0']['#']);
1727                                         $dbrec->timeread = backup_todb($info['MESSAGE']['#']['TIMEREAD']['0']['#']);
1728                                         $dbrec->mailed = backup_todb($info['MESSAGE']['#']['MAILED']['0']['#']);
1729                                         //We have to recode the useridfrom field
1730                                         $user = backup_getid($restore->backup_unique_code,"user",$dbrec->useridfrom);
1731                                         if ($user) {
1732                                             //echo "User ".$dbrec->useridfrom." to user ".$user->new_id."<br />";   //Debug
1733                                             $dbrec->useridfrom = $user->new_id;
1734                                         }
1735                                         //We have to recode the useridto field
1736                                         $user = backup_getid($restore->backup_unique_code,"user",$dbrec->useridto);
1737                                         if ($user) {
1738                                             //echo "User ".$dbrec->useridto." to user ".$user->new_id."<br />";   //Debug
1739                                             $dbrec->useridto = $user->new_id;
1740                                         }
1741                                         //Check if the record doesn't exist in DB!
1742                                         $exist = get_record('message_read','useridfrom',$dbrec->useridfrom,
1743                                                                            'useridto',  $dbrec->useridto,
1744                                                                            'timecreated',$dbrec->timecreated);
1745                                         if (!$exist) {
1746                                             //Not exist. Insert
1747                                             $status = insert_record('message_read',$dbrec);
1748                                         } else {
1749                                             //Duplicate. Do nothing
1750                                         }
1751                                     }
1752                                     //Do some output
1753                                     $counter++;
1754                                     if ($counter % 10 == 0) {
1755                                         if (!defined('RESTORE_SILENTLY')) {
1756                                             echo ".";
1757                                             if ($counter % 200 == 0) {
1758                                                 echo "<br />";
1759                                             }
1760                                         }
1761                                         backup_flush(300);
1762                                     }
1763                                 }
1764                             }
1765                         }
1766                     }
1768                     //Process contacts
1769                     if ($contactcount) {
1770                         if (!defined('RESTORE_SILENTLY')) {
1771                             echo '<li>'.strtolower(get_string('contacts','message')).'</li>';
1772                         }
1773                         $counter = 0;
1774                         while ($counter < $contactcount) {
1775                             //Fetch recordset_size records in each iteration
1776                             $recs = get_records_select("backup_ids","table_name = 'message_contacts' AND backup_code = '$restore->backup_unique_code'","old_id","old_id, old_id",$counter,$recordset_size);
1777                             if ($recs) {
1778                                 foreach ($recs as $rec) {
1779                                     //Get the full record from backup_ids
1780                                     $data = backup_getid($restore->backup_unique_code,"message_contacts",$rec->old_id);
1781                                     if ($data) {
1782                                         //Now get completed xmlized object
1783                                         $info = $data->info;
1784                                         //traverse_xmlize($info);                            //Debug
1785                                         //print_object ($GLOBALS['traverse_array']);         //Debug
1786                                         //$GLOBALS['traverse_array']="";                     //Debug
1787                                         //Now build the MESSAGE_CONTACTS record structure
1788                                         $dbrec->userid = backup_todb($info['CONTACT']['#']['USERID']['0']['#']);
1789                                         $dbrec->contactid = backup_todb($info['CONTACT']['#']['CONTACTID']['0']['#']);
1790                                         $dbrec->blocked = backup_todb($info['CONTACT']['#']['BLOCKED']['0']['#']);
1791                                         //We have to recode the userid field
1792                                         $user = backup_getid($restore->backup_unique_code,"user",$dbrec->userid);
1793                                         if ($user) {
1794                                             //echo "User ".$dbrec->userid." to user ".$user->new_id."<br />";   //Debug
1795                                             $dbrec->userid = $user->new_id;
1796                                         }
1797                                         //We have to recode the contactid field
1798                                         $user = backup_getid($restore->backup_unique_code,"user",$dbrec->contactid);
1799                                         if ($user) {
1800                                             //echo "User ".$dbrec->contactid." to user ".$user->new_id."<br />";   //Debug
1801                                             $dbrec->contactid = $user->new_id;
1802                                         }
1803                                         //Check if the record doesn't exist in DB!
1804                                         $exist = get_record('message_contacts','userid',$dbrec->userid,
1805                                                                                'contactid',  $dbrec->contactid);
1806                                         if (!$exist) {
1807                                             //Not exist. Insert
1808                                             $status = insert_record('message_contacts',$dbrec);
1809                                         } else {
1810                                             //Duplicate. Do nothing
1811                                         }
1812                                     }
1813                                     //Do some output
1814                                     $counter++;
1815                                     if ($counter % 10 == 0) {
1816                                         if (!defined('RESTORE_SILENTLY')) {
1817                                             echo ".";
1818                                             if ($counter % 200 == 0) {
1819                                                 echo "<br />";
1820                                             }
1821                                         }
1822                                         backup_flush(300);
1823                                     }
1824                                 }
1825                             }
1826                         }
1827                     }
1828                     if (!defined('RESTORE_SILENTLY')) {
1829                         //End ul
1830                         echo '</ul>';
1831                     }
1832                 }
1833             }
1834         }
1836        return $status;
1837     }
1839     //This function creates all the categories and questions
1840     //from xml 
1841     function restore_create_questions($restore,$xml_file) {
1843         global $CFG, $db;
1845         $status = true;
1846         //Check it exists
1847         if (!file_exists($xml_file)) {
1848             $status = false;
1849         }
1850         //Get info from xml
1851         if ($status) {
1852             //info will contain the old_id of every category
1853             //in backup_ids->info will be the real info (serialized)
1854             $info = restore_read_xml_questions($restore,$xml_file);
1855         }
1856         //Now, if we have anything in info, we have to restore that
1857         //categories/questions
1858         if ($info) {
1859             if ($info !== true) {
1860                 //Iterate over each category
1861                 foreach ($info as $category) {
1862                     //Skip empty categories (some backups can contain them)
1863                     if (!empty($category->id)) {
1864                         $catrestore = "restore_question_categories";
1865                         if (function_exists($catrestore)) {
1866                             //print_object ($category);                                                //Debug
1867                             $status = $catrestore($category,$restore);
1868                         } else {
1869                             //Something was wrong. Function should exist.
1870                             $status = false;
1871                         }
1872                     }
1873                 }
1875                 //Now we have to recode the parent field of each restored category
1876                 $categories = get_records_sql("SELECT old_id, new_id 
1877                                                FROM {$CFG->prefix}backup_ids
1878                                                WHERE backup_code = $restore->backup_unique_code AND
1879                                                      table_name = 'question_categories'");
1880                 if ($categories) {
1881                     foreach ($categories as $category) {
1882                         $restoredcategory = get_record('question_categories','id',$category->new_id);
1883                         if ($restoredcategory->parent != 0) {
1884                             //echo 'Parent '.$restoredcategory->parent.' is ';           //Debug
1885                             $idcat = backup_getid($restore->backup_unique_code,'question_categories',$restoredcategory->parent);
1886                             if ($idcat->new_id) {
1887                                 $restoredcategory->parent = $idcat->new_id;
1888                             } else {
1889                                 $restoredcategory->parent = 0;
1890                             }
1891                             //echo $restoredcategory->parent.' now<br />';  //Debug
1892                             update_record('question_categories', $restoredcategory);
1893                         }
1894                     }
1895                 }
1896             }
1897         } else {
1898             $status = false;
1899         }   
1900         return $status;
1901     }
1903     //This function creates all the scales
1904     function restore_create_scales($restore,$xml_file) {
1906         global $CFG, $db;
1908         $status = true;
1909         //Check it exists
1910         if (!file_exists($xml_file)) {
1911             $status = false;
1912         }
1913         //Get info from xml
1914         if ($status) {
1915             //scales will contain the old_id of every scale
1916             //in backup_ids->info will be the real info (serialized)
1917             $scales = restore_read_xml_scales($restore,$xml_file);
1918         }
1919         //Now, if we have anything in scales, we have to restore that
1920         //scales
1921         if ($scales) {
1922             //Get admin->id for later use
1923             $admin = get_admin();
1924             $adminid = $admin->id;
1925             if ($scales !== true) {
1926                 //Iterate over each scale
1927                 foreach ($scales as $scale) {
1928                     //Get record from backup_ids
1929                     $data = backup_getid($restore->backup_unique_code,"scale",$scale->id);
1930                     //Init variables
1931                     $create_scale = false;
1933                     if ($data) {
1934                         //Now get completed xmlized object
1935                         $info = $data->info;
1936                         //traverse_xmlize($info);                                                                     //Debug
1937                         //print_object ($GLOBALS['traverse_array']);                                                  //Debug
1938                         //$GLOBALS['traverse_array']="";                                                              //Debug
1940                         //Now build the SCALE record structure
1941                         $sca->courseid = backup_todb($info['SCALE']['#']['COURSEID']['0']['#']);
1942                         $sca->userid = backup_todb($info['SCALE']['#']['USERID']['0']['#']);
1943                         $sca->name = backup_todb($info['SCALE']['#']['NAME']['0']['#']);
1944                         $sca->scale = backup_todb($info['SCALE']['#']['SCALETEXT']['0']['#']);
1945                         $sca->description = backup_todb($info['SCALE']['#']['DESCRIPTION']['0']['#']);
1946                         $sca->timemodified = backup_todb($info['SCALE']['#']['TIMEMODIFIED']['0']['#']);
1948                         //Now search if that scale exists (by scale field) in course 0 (Standar scale)
1949                         //or in restore->course_id course (Personal scale)
1950                         if ($sca->courseid == 0) {
1951                             $course_to_search = 0;
1952                         } else {
1953                             $course_to_search = $restore->course_id;
1954                         }
1955                         $sca_db = get_record("scale","scale",$sca->scale,"courseid",$course_to_search);
1956                         //If it doesn't exist, create
1957                         if (!$sca_db) {
1958                             $create_scale = true;
1959                         } 
1960                         //If we must create the scale
1961                         if ($create_scale) {
1962                             //Me must recode the courseid if it's <> 0 (common scale)
1963                             if ($sca->courseid != 0) {
1964                                 $sca->courseid = $restore->course_id;
1965                             }
1966                             //We must recode the userid
1967                             $user = backup_getid($restore->backup_unique_code,"user",$sca->userid);
1968                             if ($user) {
1969                                 $sca->userid = $user->new_id;
1970                             } else {
1971                                 //Assign it to admin
1972                                 $sca->userid = $adminid;
1973                             }
1974                             //The structure is equal to the db, so insert the scale
1975                             $newid = insert_record ("scale",$sca);
1976                         } else {
1977                             //get current scale id
1978                             $newid = $sca_db->id;
1979                         }
1980                         if ($newid) {
1981                             //We have the newid, update backup_ids
1982                             backup_putid($restore->backup_unique_code,"scale",
1983                                          $scale->id, $newid);
1984                         }
1985                     }
1986                 }
1987             }
1988         } else {
1989             $status = false;
1990         }  
1991         return $status;
1992     }
1994     //This function creates all the groups
1995     function restore_create_groups($restore,$xml_file) {
1997         global $CFG, $db;
1999         $status = true;
2000         $status2 = true;
2001         //Check it exists
2002         if (!file_exists($xml_file)) {
2003             $status = false;
2004         }
2005         //Get info from xml
2006         if ($status) {
2007             //groups will contain the old_id of every group
2008             //in backup_ids->info will be the real info (serialized)
2009             $groups = restore_read_xml_groups($restore,$xml_file);
2010         }
2011         //Now, if we have anything in groups, we have to restore that
2012         //groups
2013         if ($groups) {
2014             if ($groups !== true) {
2015                 //Iterate over each group
2016                 foreach ($groups as $group) {
2017                     //Get record from backup_ids
2018                     $data = backup_getid($restore->backup_unique_code,"groups",$group->id);
2019                     //Init variables
2020                     $create_group = false;
2022                     if ($data) {
2023                         //Now get completed xmlized object
2024                         $info = $data->info;
2025                         //traverse_xmlize($info);                                                                     //Debug
2026                         //print_object ($GLOBALS['traverse_array']);                                                  //Debug
2027                         //$GLOBALS['traverse_array']="";                                                              //Debug
2028                         //Now build the GROUP record structure
2029                         $gro->courseid = backup_todb($info['GROUP']['#']['COURSEID']['0']['#']);
2030                         $gro->name = backup_todb($info['GROUP']['#']['NAME']['0']['#']);
2031                         $gro->description = backup_todb($info['GROUP']['#']['DESCRIPTION']['0']['#']);
2032                         $gro->password = backup_todb($info['GROUP']['#']['PASSWORD']['0']['#']);
2033                         $gro->lang = backup_todb($info['GROUP']['#']['LANG']['0']['#']);
2034                         $gro->theme = backup_todb($info['GROUP']['#']['THEME']['0']['#']);
2035                         $gro->picture = backup_todb($info['GROUP']['#']['PICTURE']['0']['#']);
2036                         $gro->hidepicture = backup_todb($info['GROUP']['#']['HIDEPICTURE']['0']['#']);
2037                         $gro->timecreated = backup_todb($info['GROUP']['#']['TIMECREATED']['0']['#']);
2038                         $gro->timemodified = backup_todb($info['GROUP']['#']['TIMEMODIFIED']['0']['#']);
2039                 
2040                         //Now search if that group exists (by name and description field) in 
2041                         //restore->course_id course 
2042                         $gro_db = get_record("groups","courseid",$restore->course_id,"name",$gro->name,"description",$gro->description);
2043                         //If it doesn't exist, create
2044                         if (!$gro_db) {
2045                             $create_group = true;
2046                         }
2047                         //If we must create the group
2048                         if ($create_group) {
2049                             //Me must recode the courseid to the restore->course_id 
2050                             $gro->courseid = $restore->course_id;
2052                             //Check if the theme exists in destination server
2053                             $themes = get_list_of_themes();
2054                             if (!in_array($gro->theme, $themes)) {
2055                                 $gro->theme = '';
2056                             }
2058                             //The structure is equal to the db, so insert the group
2059                             $newid = insert_record ("groups",$gro);
2060                         } else { 
2061                             //get current group id
2062                             $newid = $gro_db->id;
2063                         }
2064                         if ($newid) {
2065                             //We have the newid, update backup_ids
2066                             backup_putid($restore->backup_unique_code,"groups",
2067                                          $group->id, $newid);
2068                         }
2069                         //Now restore members in the groups_members, only if
2070                         //users are included
2071                         if ($restore->users != 2) {
2072                             $status2 = restore_create_groups_members($newid,$info,$restore);
2073                         }
2074                     }   
2075                 }
2076                 //Now, restore group_files
2077                 if ($status && $status2) {
2078                     $status2 = restore_group_files($restore); 
2079                 }
2080             }
2081         } else {
2082             $status = false;
2083         } 
2084         return ($status && $status2);
2085     }
2087     //This function restores the groups_members
2088     function restore_create_groups_members($group_id,$info,$restore) {
2090         global $CFG;
2092         $status = true;
2094         //Get the members array
2095         $members = $info['GROUP']['#']['MEMBERS']['0']['#']['MEMBER'];
2097         //Iterate over members
2098         for($i = 0; $i < sizeof($members); $i++) {
2099             $mem_info = $members[$i];
2100             //traverse_xmlize($mem_info);                                                                 //Debug
2101             //print_object ($GLOBALS['traverse_array']);                                                  //Debug
2102             //$GLOBALS['traverse_array']="";                                                              //Debug
2104             //Now, build the GROUPS_MEMBERS record structure
2105             $group_member->groupid = $group_id;
2106             $group_member->userid = backup_todb($mem_info['#']['USERID']['0']['#']);
2107             $group_member->timeadded = backup_todb($mem_info['#']['TIMEADDED']['0']['#']);
2109             //We have to recode the userid field
2110             $user = backup_getid($restore->backup_unique_code,"user",$group_member->userid);
2111             if ($user) {
2112                 $group_member->userid = $user->new_id;
2113             }
2115             //The structure is equal to the db, so insert the groups_members
2116             $newid = insert_record ("groups_members",$group_member);
2117             //Do some output
2118             if (($i+1) % 50 == 0) {
2119                 if (!defined('RESTORE_SILENTLY')) {
2120                     echo ".";
2121                     if (($i+1) % 1000 == 0) {
2122                         echo "<br />";
2123                     }
2124                 }
2125                 backup_flush(300);
2126             }
2127             
2128             if (!$newid) {
2129                 $status = false;
2130             }
2131         }
2133         return $status;
2134     }
2136     //This function creates all the course events
2137     function restore_create_events($restore,$xml_file) {
2139         global $CFG, $db;
2141         $status = true;
2142         //Check it exists
2143         if (!file_exists($xml_file)) {
2144             $status = false;
2145         }
2146         //Get info from xml
2147         if ($status) {
2148             //events will contain the old_id of every event
2149             //in backup_ids->info will be the real info (serialized)
2150             $events = restore_read_xml_events($restore,$xml_file);
2151         }
2153         //Get admin->id for later use
2154         $admin = get_admin();
2155         $adminid = $admin->id;
2157         //Now, if we have anything in events, we have to restore that
2158         //events
2159         if ($events) {
2160             if ($events !== true) {
2161                 //Iterate over each event
2162                 foreach ($events as $event) {
2163                     //Get record from backup_ids
2164                     $data = backup_getid($restore->backup_unique_code,"event",$event->id);
2165                     //Init variables
2166                     $create_event = false;
2168                     if ($data) {
2169                         //Now get completed xmlized object
2170                         $info = $data->info;
2171                         //traverse_xmlize($info);                                                                     //Debug
2172                         //print_object ($GLOBALS['traverse_array']);                                                  //Debug
2173                         //$GLOBALS['traverse_array']="";                                                              //Debug
2175                         //Now build the EVENT record structure
2176                         $eve->name = backup_todb($info['EVENT']['#']['NAME']['0']['#']);
2177                         $eve->description = backup_todb($info['EVENT']['#']['DESCRIPTION']['0']['#']);
2178                         $eve->format = backup_todb($info['EVENT']['#']['FORMAT']['0']['#']);
2179                         $eve->courseid = $restore->course_id;
2180                         $eve->groupid = backup_todb($info['EVENT']['#']['GROUPID']['0']['#']);
2181                         $eve->userid = backup_todb($info['EVENT']['#']['USERID']['0']['#']);
2182                         $eve->repeatid = backup_todb($info['EVENT']['#']['REPEATID']['0']['#']);
2183                         $eve->modulename = "";
2184                         $eve->instance = 0;
2185                         $eve->eventtype = backup_todb($info['EVENT']['#']['EVENTTYPE']['0']['#']);
2186                         $eve->timestart = backup_todb($info['EVENT']['#']['TIMESTART']['0']['#']);
2187                         $eve->timeduration = backup_todb($info['EVENT']['#']['TIMEDURATION']['0']['#']);
2188                         $eve->visible = backup_todb($info['EVENT']['#']['VISIBLE']['0']['#']);
2189                         $eve->timemodified = backup_todb($info['EVENT']['#']['TIMEMODIFIED']['0']['#']);
2191                         //Now search if that event exists (by description and timestart field) in
2192                         //restore->course_id course 
2193                         $eve_db = get_record("event","courseid",$eve->courseid,"description",$eve->description,"timestart",$eve->timestart);
2194                         //If it doesn't exist, create
2195                         if (!$eve_db) {
2196                             $create_event = true;
2197                         }
2198                         //If we must create the event
2199                         if ($create_event) {
2201                             //We must recode the userid
2202                             $user = backup_getid($restore->backup_unique_code,"user",$eve->userid);
2203                             if ($user) {
2204                                 $eve->userid = $user->new_id;
2205                             } else {
2206                                 //Assign it to admin
2207                                 $eve->userid = $adminid;
2208                             }
2210                             //We must recode the repeatid if the event has it
2211                             if (!empty($eve->repeatid)) {
2212                                 $repeat_rec = backup_getid($restore->backup_unique_code,"event_repeatid",$eve->repeatid);
2213                                 if ($repeat_rec) {    //Exists, so use it...
2214                                     $eve->repeatid = $repeat_rec->new_id;
2215                                 } else {              //Doesn't exists, calculate the next and save it
2216                                     $oldrepeatid = $eve->repeatid;
2217                                     $max_rec = get_record_sql('SELECT 1, MAX(repeatid) AS repeatid FROM '.$CFG->prefix.'event');
2218                                     $eve->repeatid = empty($max_rec) ? 1 : $max_rec->repeatid + 1;
2219                                     backup_putid($restore->backup_unique_code,"event_repeatid", $oldrepeatid, $eve->repeatid);
2220                                 }
2221                             }
2222  
2223                             //We have to recode the groupid field
2224                             $group = backup_getid($restore->backup_unique_code,"groups",$eve->groupid);
2225                             if ($group) {
2226                                 $eve->groupid = $group->new_id;
2227                             } else {
2228                                 //Assign it to group 0
2229                                 $eve->groupid = 0;
2230                             }
2232                             //The structure is equal to the db, so insert the event
2233                             $newid = insert_record ("event",$eve);
2234                         } else {
2235                             //get current event id
2236                             $newid = $eve_db->id;
2237                         }
2238                         if ($newid) {
2239                             //We have the newid, update backup_ids
2240                             backup_putid($restore->backup_unique_code,"event",
2241                                          $event->id, $newid);
2242                         }
2243                     }
2244                 }
2245             }
2246         } else {
2247             $status = false;
2248         } 
2249         return $status;
2250     }
2252     //This function decode things to make restore multi-site fully functional
2253     //It does this conversions:
2254     //    - $@FILEPHP@$ ---|------------> $CFG->wwwroot/file.php/courseid (slasharguments on)
2255     //                     |------------> $CFG->wwwroot/file.php?file=/courseid (slasharguments off)
2256     //
2257     //Note: Inter-activities linking is being implemented as a final
2258     //step in the restore execution, because we need to have it 
2259     //finished to know all the oldid, newid equivaleces
2260     function restore_decode_absolute_links($content) {
2261                                      
2262         global $CFG,$restore;    
2264         //Now decode wwwroot and file.php calls
2265         $search = array ("$@FILEPHP@$");
2267         //Check for the status of the slasharguments config variable
2268         $slash = $CFG->slasharguments;
2269         
2270         //Build the replace string as needed
2271         if ($slash == 1) {
2272             $replace = array ($CFG->wwwroot."/file.php/".$restore->course_id);
2273         } else {
2274             $replace = array ($CFG->wwwroot."/file.php?file=/".$restore->course_id);
2275         }
2276     
2277         $result = str_replace($search,$replace,$content);
2279         if ($result != $content && $CFG->debug>7) {                                  //Debug
2280             if (!defined('RESTORE_SILENTLY')) {
2281                 echo '<br /><hr />'.s($content).'<br />changed to<br />'.s($result).'<hr /><br />';        //Debug
2282             }
2283         }                                                                            //Debug
2285         return $result;
2286     }
2288     //This function restores the userfiles from the temp (user_files) directory to the
2289     //dataroot/users directory
2290     function restore_user_files($restore) {
2292         global $CFG;
2294         $status = true;
2296         $counter = 0;
2298         //First, we check to "users" exists and create is as necessary
2299         //in CFG->dataroot
2300         $dest_dir = $CFG->dataroot."/users";
2301         $status = check_dir_exists($dest_dir,true);
2303         //Now, we iterate over "user_files" records to check if that user dir must be
2304         //copied (and renamed) to the "users" dir.
2305         $rootdir = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/user_files";
2306         //Check if directory exists
2307         if (is_dir($rootdir)) {
2308             $list = list_directories ($rootdir);
2309             if ($list) {
2310                 //Iterate
2311                 $counter = 0;
2312                 foreach ($list as $dir) {
2313                     //Look for dir like username in backup_ids
2314                     $data = get_record ("backup_ids","backup_code",$restore->backup_unique_code,
2315                                                      "table_name","user",
2316                                                      "old_id",$dir);
2317                     //If thar user exists in backup_ids
2318                     if ($data) {
2319                         //Only it user has been created now
2320                         //or if it existed previously, but he hasn't image (see bug 1123)
2321                         if ((strpos($data->info,"new") !== false) or 
2322                             (!check_dir_exists($dest_dir."/".$data->new_id,false))) {
2323                             //Copy the old_dir to its new location (and name) !!
2324                             //Only if destination doesn't exists
2325                             if (!file_exists($dest_dir."/".$data->new_id)) {
2326                                 $status = backup_copy_file($rootdir."/".$dir,
2327                                               $dest_dir."/".$data->new_id,true);
2328                                 $counter ++;
2329                             }
2330                             //Do some output
2331                             if ($counter % 2 == 0) {
2332                                 if (!defined('RESTORE_SILENTLY')) {
2333                                     echo ".";
2334                                     if ($counter % 40 == 0) {
2335                                         echo "<br />";
2336                                     }
2337                                 }
2338                                 backup_flush(300);
2339                             }
2340                         }
2341                     }
2342                 }
2343             }
2344         }
2345         //If status is ok and whe have dirs created, returns counter to inform
2346         if ($status and $counter) {
2347             return $counter;
2348         } else {
2349             return $status;
2350         }
2351     }
2353     //This function restores the groupfiles from the temp (group_files) directory to the
2354     //dataroot/groups directory
2355     function restore_group_files($restore) {
2357         global $CFG;
2359         $status = true;
2361         $counter = 0;
2363         //First, we check to "groups" exists and create is as necessary
2364         //in CFG->dataroot
2365         $dest_dir = $CFG->dataroot.'/groups';
2366         $status = check_dir_exists($dest_dir,true);
2368         //Now, we iterate over "group_files" records to check if that user dir must be
2369         //copied (and renamed) to the "groups" dir.
2370         $rootdir = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/group_files";
2371         //Check if directory exists
2372         if (is_dir($rootdir)) {
2373             $list = list_directories ($rootdir);
2374             if ($list) {
2375                 //Iterate
2376                 $counter = 0;
2377                 foreach ($list as $dir) {
2378                     //Look for dir like groupid in backup_ids
2379                     $data = get_record ("backup_ids","backup_code",$restore->backup_unique_code,
2380                                                      "table_name","groups",
2381                                                      "old_id",$dir);
2382                     //If that group exists in backup_ids
2383                     if ($data) {
2384                         if (!file_exists($dest_dir."/".$data->new_id)) {
2385                             $status = backup_copy_file($rootdir."/".$dir, $dest_dir."/".$data->new_id,true);
2386                             $counter ++;
2387                         }
2388                         //Do some output
2389                         if ($counter % 2 == 0) {
2390                             if (!defined('RESTORE_SILENTLY')) {
2391                                 echo ".";
2392                                 if ($counter % 40 == 0) {
2393                                     echo "<br />";
2394                                 }
2395                             }
2396                             backup_flush(300);
2397                         } 
2398                     }
2399                 }
2400             }
2401         }
2402         //If status is ok and whe have dirs created, returns counter to inform
2403         if ($status and $counter) {
2404             return $counter;
2405         } else {
2406             return $status;
2407         }
2408     }
2410     //This function restores the course files from the temp (course_files) directory to the
2411     //dataroot/course_id directory
2412     function restore_course_files($restore) {
2414         global $CFG;
2416         $status = true;
2417  
2418         $counter = 0;
2420         //First, we check to "course_id" exists and create is as necessary
2421         //in CFG->dataroot
2422         $dest_dir = $CFG->dataroot."/".$restore->course_id;
2423         $status = check_dir_exists($dest_dir,true);
2425         //Now, we iterate over "course_files" records to check if that file/dir must be
2426         //copied to the "dest_dir" dir.
2427         $rootdir = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/course_files";
2428         //Check if directory exists
2429         if (is_dir($rootdir)) {
2430             $list = list_directories_and_files ($rootdir);
2431             if ($list) {
2432                 //Iterate
2433                 $counter = 0;
2434                 foreach ($list as $dir) {
2435                     //Copy the dir to its new location 
2436                     //Only if destination file/dir doesn exists
2437                     if (!file_exists($dest_dir."/".$dir)) {
2438                         $status = backup_copy_file($rootdir."/".$dir,
2439                                       $dest_dir."/".$dir,true);
2440                         $counter ++;
2441                     }
2442                     //Do some output
2443                     if ($counter % 2 == 0) {       
2444                         if (!defined('RESTORE_SILENTLY')) {
2445                             echo ".";
2446                             if ($counter % 40 == 0) {       
2447                                 echo "<br />";
2448                             }
2449                         }
2450                         backup_flush(300);
2451                     }
2452                 }
2453             }
2454         }
2455         //If status is ok and whe have dirs created, returns counter to inform
2456         if ($status and $counter) {
2457             return $counter;
2458         } else {
2459             return $status;
2460         }
2461     }
2462    
2464     //This function creates all the structures for every module in backup file
2465     //Depending what has been selected.
2466     function restore_create_modules($restore,$xml_file) {
2468         global $CFG;
2469         $status = true;
2470         //Check it exists
2471         if (!file_exists($xml_file)) {
2472             $status = false;
2473         }
2474         //Get info from xml
2475         if ($status) {
2476             //info will contain the id and modtype of every module
2477             //in backup_ids->info will be the real info (serialized)
2478             $info = restore_read_xml_modules($restore,$xml_file);
2479         }
2480         //Now, if we have anything in info, we have to restore that mods
2481         //from backup_ids (calling every mod restore function)
2482         if ($info) {
2483             if ($info !== true) {
2484                 if (!defined('RESTORE_SILENTLY')) {
2485                     echo '<ul>';
2486                 }
2487                 //Iterate over each module
2488                 foreach ($info as $mod) {
2489                     if (!is_array($restore->mods[$mod->modtype]->instances)  // we don't care about per instance
2490                         || (array_key_exists($mod->id,$restore->mods[$mod->modtype]->instances) 
2491                             && !empty($restore->mods[$mod->modtype]->instances[$mod->id]->restore))) {
2492                         $modrestore = $mod->modtype."_restore_mods";
2493                         if (function_exists($modrestore)) {
2494                             //print_object ($mod);                                                //Debug
2495                             $status = $status and $modrestore($mod,$restore); //bit operator & not reliable here!
2496                         } else {
2497                             //Something was wrong. Function should exist.
2498                             $status = false;
2499                         }
2500                     }
2501                 }
2502                 if (!defined('RESTORE_SILENTLY')) {
2503                     echo '</ul>';
2504                 }
2505             }
2506         } else {
2507             $status = false;
2508         }
2509        return $status;
2510     }
2512     //This function creates all the structures for every log in backup file
2513     //Depending what has been selected.
2514     function restore_create_logs($restore,$xml_file) {
2515             
2516         global $CFG,$db;
2518         //Number of records to get in every chunk
2519         $recordset_size = 4;
2520         //Counter, points to current record
2521         $counter = 0;
2522         //To count all the recods to restore
2523         $count_logs = 0;
2524         
2525         $status = true;
2526         //Check it exists 
2527         if (!file_exists($xml_file)) { 
2528             $status = false;
2529         }
2530         //Get info from xml
2531         if ($status) {
2532             //count_logs will contain the number of logs entries to process
2533             //in backup_ids->info will be the real info (serialized)
2534             $count_logs = restore_read_xml_logs($restore,$xml_file);
2535         }
2536  
2537         //Now, if we have records in count_logs, we have to restore that logs
2538         //from backup_ids. This piece of code makes calls to:
2539         // - restore_log_course() if it's a course log
2540         // - restore_log_user() if it's a user log
2541         // - restore_log_module() if it's a module log.
2542         //And all is segmented in chunks to allow large recordsets to be restored !!
2543         if ($count_logs > 0) {
2544             while ($counter < $count_logs) {
2545                 //Get a chunk of records
2546                 //Take old_id twice to avoid adodb limitation
2547                 $logs = get_records_select("backup_ids","table_name = 'log' AND backup_code = '$restore->backup_unique_code'","old_id","old_id,old_id",$counter,$recordset_size);
2548                 //We have logs
2549                 if ($logs) {
2550                     //Iterate
2551                     foreach ($logs as $log) {
2552                         //Get the full record from backup_ids
2553                         $data = backup_getid($restore->backup_unique_code,"log",$log->old_id);
2554                         if ($data) {
2555                             //Now get completed xmlized object
2556                             $info = $data->info;
2557                             //traverse_xmlize($info);                                                                     //Debug
2558                             //print_object ($GLOBALS['traverse_array']);                                                  //Debug
2559                             //$GLOBALS['traverse_array']="";                                                              //Debug
2560                             //Now build the LOG record structure
2561                             $dblog->time = backup_todb($info['LOG']['#']['TIME']['0']['#']);
2562                             $dblog->userid = backup_todb($info['LOG']['#']['USERID']['0']['#']);
2563                             $dblog->ip = backup_todb($info['LOG']['#']['IP']['0']['#']);
2564                             $dblog->course = $restore->course_id;
2565                             $dblog->module = backup_todb($info['LOG']['#']['MODULE']['0']['#']);
2566                             $dblog->cmid = backup_todb($info['LOG']['#']['CMID']['0']['#']);
2567                             $dblog->action = backup_todb($info['LOG']['#']['ACTION']['0']['#']);
2568                             $dblog->url = backup_todb($info['LOG']['#']['URL']['0']['#']);
2569                             $dblog->info = backup_todb($info['LOG']['#']['INFO']['0']['#']);
2570                             //We have to recode the userid field
2571                             $user = backup_getid($restore->backup_unique_code,"user",$dblog->userid);
2572                             if ($user) {
2573                                 //echo "User ".$dblog->userid." to user ".$user->new_id."<br />";                             //Debug
2574                                 $dblog->userid = $user->new_id;
2575                             }
2576                             //We have to recode the cmid field (if module isn't "course" or "user")
2577                             if ($dblog->module != "course" and $dblog->module != "user") {
2578                                 $cm = backup_getid($restore->backup_unique_code,"course_modules",$dblog->cmid);
2579                                 if ($cm) {
2580                                     //echo "Module ".$dblog->cmid." to module ".$cm->new_id."<br />";                         //Debug
2581                                     $dblog->cmid = $cm->new_id;
2582                                 } else {
2583                                     $dblog->cmid = 0;
2584                                 }
2585                             }
2586                             //print_object ($dblog);                                                                        //Debug
2587                             //Now, we redirect to the needed function to make all the work
2588                             if ($dblog->module == "course") {
2589                                 //It's a course log,
2590                                 $stat = restore_log_course($restore,$dblog);
2591                             } elseif ($dblog->module == "user") {
2592                                 //It's a user log,
2593                                 $stat = restore_log_user($restore,$dblog);
2594                             } else {
2595                                 //It's a module log,
2596                                 $stat = restore_log_module($restore,$dblog);
2597                             }
2598                         }
2600                         //Do some output
2601                         $counter++;
2602                         if ($counter % 10 == 0) {
2603                             if (!defined('RESTORE_SILENTLY')) {
2604                                 echo ".";
2605                                 if ($counter % 200 == 0) {
2606                                     echo "<br />";
2607                                 }
2608                             }
2609                             backup_flush(300);
2610                         }
2611                     }
2612                 } else {
2613                     //We never should arrive here
2614                     $counter = $count_logs;
2615                     $status = false;
2616                 }
2617             }
2618         }
2620         return $status;
2621     }
2623     //This function inserts a course log record, calculating the URL field as necessary
2624     function restore_log_course($restore,$log) {
2626         $status = true;
2627         $toinsert = false;
2629         //echo "<hr />Before transformations<br />";                                        //Debug
2630         //print_object($log);                                                           //Debug
2631         //Depending of the action, we recode different things
2632         switch ($log->action) {
2633         case "view":
2634             $log->url = "view.php?id=".$log->course;
2635             $log->info = $log->course;
2636             $toinsert = true;
2637             break;
2638         case "guest":
2639             $log->url = "view.php?id=".$log->course;
2640             $toinsert = true;
2641             break;
2642         case "user report":
2643             //recode the info field (it's the user id)
2644             $user = backup_getid($restore->backup_unique_code,"user",$log->info);
2645             if ($user) {
2646                 $log->info = $user->new_id;
2647                 //Now, extract the mode from the url field
2648                 $mode = substr(strrchr($log->url,"="),1);
2649                 $log->url = "user.php?id=".$log->course."&user=".$log->info."&mode=".$mode;
2650                 $toinsert = true;
2651             }
2652             break;
2653         case "add mod":
2654             //Extract the course_module from the url field
2655             $cmid = substr(strrchr($log->url,"="),1);
2656             //recode the course_module to see it it has been restored
2657             $cm = backup_getid($restore->backup_unique_code,"course_modules",$cmid);
2658             if ($cm) {
2659                 $cmid = $cm->new_id;
2660                 //Extract the module name and the module id from the info field
2661                 $modname = strtok($log->info," ");
2662                 $modid = strtok(" ");
2663                 //recode the module id to see if it has been restored
2664                 $mod = backup_getid($restore->backup_unique_code,$modname,$modid);
2665                 if ($mod) {
2666                     $modid = $mod->new_id;
2667                     //Now I have everything so reconstruct url and info
2668                     $log->info = $modname." ".$modid;
2669                     $log->url = "../mod/".$modname."/view.php?id=".$cmid;
2670                     $toinsert = true;
2671                 }
2672             }
2673             break;
2674         case "update mod":
2675             //Extract the course_module from the url field
2676             $cmid = substr(strrchr($log->url,"="),1);
2677             //recode the course_module to see it it has been restored
2678             $cm = backup_getid($restore->backup_unique_code,"course_modules",$cmid);
2679             if ($cm) {
2680                 $cmid = $cm->new_id;
2681                 //Extract the module name and the module id from the info field
2682                 $modname = strtok($log->info," ");
2683                 $modid = strtok(" ");
2684                 //recode the module id to see if it has been restored
2685                 $mod = backup_getid($restore->backup_unique_code,$modname,$modid);
2686                 if ($mod) {
2687                     $modid = $mod->new_id;
2688                     //Now I have everything so reconstruct url and info
2689                     $log->info = $modname." ".$modid;
2690                     $log->url = "../mod/".$modname."/view.php?id=".$cmid;
2691                     $toinsert = true;
2692                 }
2693             }
2694             break;
2695         case "delete mod":
2696             $log->url = "view.php?id=".$log->course;
2697             $toinsert = true;
2698             break;
2699         case "update":
2700             $log->url = "edit.php?id=".$log->course;
2701             $log->info = "";
2702             $toinsert = true;
2703             break;
2704         case "unenrol":
2705             //recode the info field (it's the user id)
2706             $user = backup_getid($restore->backup_unique_code,"user",$log->info);
2707             if ($user) {
2708                 $log->info = $user->new_id;
2709                 $log->url = "view.php?id=".$log->course;
2710                 $toinsert = true;
2711             }
2712             break;
2713         case "enrol":
2714             //recode the info field (it's the user id)
2715             $user = backup_getid($restore->backup_unique_code,"user",$log->info);
2716             if ($user) {
2717                 $log->info = $user->new_id;
2718                 $log->url = "view.php?id=".$log->course;
2719                 $toinsert = true;
2720             }
2721             break;
2722         case "editsection":
2723             //Extract the course_section from the url field
2724             $secid = substr(strrchr($log->url,"="),1);
2725             //recode the course_section to see if it has been restored
2726             $sec = backup_getid($restore->backup_unique_code,"course_sections",$secid);
2727             if ($sec) {
2728                 $secid = $sec->new_id;
2729                 //Now I have everything so reconstruct url and info
2730                 $log->url = "editsection.php?id=".$secid;
2731                 $toinsert = true;
2732             }
2733             break;
2734         case "new":
2735             $log->url = "view.php?id=".$log->course;
2736             $log->info = "";
2737             $toinsert = true;
2738             break;
2739         case "recent":
2740             $log->url = "recent.php?id=".$log->course;
2741             $log->info = "";
2742             $toinsert = true;
2743             break;
2744         case "report log":
2745             $log->url = "report/log/index.php?id=".$log->course;
2746             $log->info = $log->course;
2747             $toinsert = true;
2748             break;
2749         case "report live":
2750             $log->url = "report/log/live.php?id=".$log->course;
2751             $log->info = $log->course;
2752             $toinsert = true;
2753             break;
2754         case "report outline":
2755             $log->url = "report/outline/index.php?id=".$log->course;
2756             $log->info = $log->course;
2757             $toinsert = true;
2758             break;
2759         case "report participation":
2760             $log->url = "report/participation/index.php?id=".$log->course;
2761             $log->info = $log->course;
2762             $toinsert = true;
2763             break;
2764         case "report stats":
2765             $log->url = "report/stats/index.php?id=".$log->course;
2766             $log->info = $log->course;
2767             $toinsert = true;
2768             break;
2769         default:
2770             echo "action (".$log->module."-".$log->action.") unknown. Not restored<br />";                 //Debug
2771             break;
2772         }
2774         //echo "After transformations<br />";                                             //Debug
2775         //print_object($log);                                                           //Debug
2777         //Now if $toinsert is set, insert the record
2778         if ($toinsert) {
2779             //echo "Inserting record<br />";                                              //Debug
2780             $status = insert_record("log",$log);
2781         }
2782         return $status;
2783     }
2785     //This function inserts a user log record, calculating the URL field as necessary
2786     function restore_log_user($restore,$log) {
2788         $status = true;
2789         $toinsert = false;
2790         
2791         //echo "<hr />Before transformations<br />";                                        //Debug
2792         //print_object($log);                                                           //Debug
2793         //Depending of the action, we recode different things                           
2794         switch ($log->action) {
2795         case "view":
2796             //recode the info field (it's the user id)
2797             $user = backup_getid($restore->backup_unique_code,"user",$log->info);
2798             if ($user) {
2799                 $log->info = $user->new_id;
2800                 $log->url = "view.php?id=".$log->info."&course=".$log->course;
2801                 $toinsert = true;
2802             }
2803             break;
2804         case "change password":
2805             //recode the info field (it's the user id)
2806             $user = backup_getid($restore->backup_unique_code,"user",$log->info);
2807             if ($user) {
2808                 $log->info = $user->new_id;
2809                 $log->url = "view.php?id=".$log->info."&course=".$log->course;
2810                 $toinsert = true;
2811             }
2812             break;
2813         case "login":
2814             //recode the info field (it's the user id)
2815             $user = backup_getid($restore->backup_unique_code,"user",$log->info);
2816             if ($user) {
2817                 $log->info = $user->new_id;
2818                 $log->url = "view.php?id=".$log->info."&course=".$log->course;
2819                 $toinsert = true;
2820             }
2821             break;
2822         case "logout":
2823             //recode the info field (it's the user id)
2824             $user = backup_getid($restore->backup_unique_code,"user",$log->info);
2825             if ($user) {
2826                 $log->info = $user->new_id;
2827                 $log->url = "view.php?id=".$log->info."&course=".$log->course;
2828                 $toinsert = true;
2829             }
2830             break;
2831         case "view all":
2832             $log->url = "view.php?id=".$log->course;
2833             $log->info = "";
2834             $toinsert = true;
2835         case "update":
2836             //We split the url by ampersand char 
2837             $first_part = strtok($log->url,"&");
2838             //Get data after the = char. It's the user being updated
2839             $userid = substr(strrchr($first_part,"="),1);
2840             //Recode the user
2841             $user = backup_getid($restore->backup_unique_code,"user",$userid);
2842             if ($user) {
2843                 $log->info = "";
2844                 $log->url = "view.php?id=".$user->new_id."&course=".$log->course;
2845                 $toinsert = true;
2846             }
2847             break;
2848         default:
2849             echo "action (".$log->module."-".$log->action.") unknown. Not restored<br />";                 //Debug
2850             break;
2851         }
2853         //echo "After transformations<br />";                                             //Debug
2854         //print_object($log);                                                           //Debug
2856         //Now if $toinsert is set, insert the record
2857         if ($toinsert) {
2858             //echo "Inserting record<br />";                                              //Debug
2859             $status = insert_record("log",$log);
2860         }
2861         return $status;
2862     }
2864     //This function inserts a module log record, calculating the URL field as necessary
2865     function restore_log_module($restore,$log) {
2867         $status = true;
2868         $toinsert = false;
2870         //echo "<hr />Before transformations<br />";                                        //Debug
2871         //print_object($log);                                                           //Debug
2873         //Now we see if the required function in the module exists
2874         $function = $log->module."_restore_logs";
2875         if (function_exists($function)) {
2876             //Call the function
2877             $log = $function($restore,$log);
2878             //If everything is ok, mark the insert flag
2879             if ($log) {
2880                 $toinsert = true;
2881             }
2882         }
2884         //echo "After transformations<br />";                                             //Debug
2885         //print_object($log);                                                           //Debug
2887         //Now if $toinsert is set, insert the record
2888         if ($toinsert) {
2889             //echo "Inserting record<br />";                                              //Debug
2890             $status = insert_record("log",$log);
2891         }
2892         return $status;
2893     }
2895     //This function adjusts the instance field into course_modules. It's executed after
2896     //modules restore. There, we KNOW the new instance id !!
2897     function restore_check_instances($restore) {
2899         global $CFG;
2901         $status = true;
2903         //We are going to iterate over each course_module saved in backup_ids
2904         $course_modules = get_records_sql("SELECT old_id,new_id
2905                                            FROM {$CFG->prefix}backup_ids
2906                                            WHERE backup_code = '$restore->backup_unique_code' AND
2907                                                  table_name = 'course_modules'");
2908         if ($course_modules) {
2909             foreach($course_modules as $cm) {
2910                 //Get full record, using backup_getids
2911                 $cm_module = backup_getid($restore->backup_unique_code,"course_modules",$cm->old_id);
2912                 //Now we are going to the REAL course_modules to get its type (field module)
2913                 $module = get_record("course_modules","id",$cm_module->new_id);
2914                 if ($module) {
2915                     //We know the module type id. Get the name from modules
2916                     $type = get_record("modules","id",$module->module);
2917                     if ($type) {
2918                         //We know the type name and the old_id. Get its new_id
2919                         //from backup_ids. It's the instance !!!
2920                         $instance =  backup_getid($restore->backup_unique_code,$type->name,$cm_module->info);
2921                         if ($instance) {
2922                             //We have the new instance, so update the record in course_modules
2923                             $module->instance = $instance->new_id;
2924                             //print_object ($module);                                                   //Debug
2925                             $status = update_record("course_modules",$module);
2926                         } else {
2927                             $status = false;
2928                         }
2929                     } else {
2930                         $status = false;
2931                     }
2932                 } else {
2933                     $status = false;
2934                }
2935             }
2936         }
2939         return $status;
2940     }
2942     //=====================================================================================
2943     //==                                                                                 ==
2944     //==                         XML Functions (SAX)                                     ==
2945     //==                                                                                 ==
2946     //=====================================================================================
2948     //This is the class used to do all the xml parse
2949     class MoodleParser {
2951         var $level = 0;        //Level we are
2952         var $counter = 0;      //Counter
2953         var $tree = array();   //Array of levels we are
2954         var $content = "";     //Content under current level
2955         var $todo = "";        //What we hav to do when parsing
2956         var $info = "";        //Information collected. Temp storage. Used to return data after parsing.
2957         var $temp = "";        //Temp storage.
2958         var $preferences = ""; //Preferences about what to load !!
2959         var $finished = false; //Flag to say xml_parse to stop
2961         //This function is used to get the current contents property value
2962         //They are trimed (and converted from utf8 if needed)
2963         function getContents() {
2964             global $CFG;
2966             if (empty($CFG->unicodedb)) {
2967                 return trim(utf8_decode($this->content));
2968             } else {
2969                 return trim($this->content);
2970             }
2971         }
2972  
2973         //This is the startTag handler we use where we are reading the info zone (todo="INFO")
2974         function startElementInfo($parser, $tagName, $attrs) {
2975             //Refresh properties
2976             $this->level++;
2977             $this->tree[$this->level] = $tagName;
2979             //Output something to avoid browser timeouts...
2980             backup_flush();
2982             //Check if we are into INFO zone
2983             //if ($this->tree[2] == "INFO")                                                             //Debug
2984             //    echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n";   //Debug
2985         }
2987         //This is the startTag handler we use where we are reading the course header zone (todo="COURSE_HEADER")
2988         function startElementCourseHeader($parser, $tagName, $attrs) {
2989             //Refresh properties
2990             $this->level++;
2991             $this->tree[$this->level] = $tagName;
2993             //Output something to avoid browser timeouts...
2994             backup_flush();
2996             //Check if we are into COURSE_HEADER zone
2997             //if ($this->tree[3] == "HEADER")                                                           //Debug
2998             //    echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n";   //Debug
2999         }
3001         //This is the startTag handler we use where we are reading the blocks zone (todo="BLOCKS")
3002         function startElementBlocks($parser, $tagName, $attrs) {
3003             //Refresh properties     
3004             $this->level++;
3005             $this->tree[$this->level] = $tagName;   
3006             
3007             //Output something to avoid browser timeouts...
3008             backup_flush();
3010             //Check if we are into BLOCKS zone
3011             //if ($this->tree[3] == "BLOCKS")                                                         //Debug
3012             //    echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n";   //Debug
3013         }
3015         //This is the startTag handler we use where we are reading the sections zone (todo="SECTIONS")
3016         function startElementSections($parser, $tagName, $attrs) {
3017             //Refresh properties     
3018             $this->level++;
3019             $this->tree[$this->level] = $tagName;   
3021             //Output something to avoid browser timeouts...
3022             backup_flush();
3024             //Check if we are into SECTIONS zone
3025             //if ($this->tree[3] == "SECTIONS")                                                         //Debug
3026             //    echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n";   //Debug
3027         }
3029         //This is the startTag handler we use where we are reading the metacourse zone (todo="METACOURSE")
3030         function startElementMetacourse($parser, $tagName, $attrs) {
3032             //Refresh properties     
3033             $this->level++;
3034             $this->tree[$this->level] = $tagName;   
3035             
3036             //Output something to avoid browser timeouts...
3037             backup_flush();
3039             //Check if we are into METACOURSE zone
3040             //if ($this->tree[3] == "METACOURSE")                                                         //Debug
3041             //    echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n";   //Debug
3042         }
3044         //This is the startTag handler we use where we are reading the gradebook zone (todo="GRADEBOOK")
3045         function startElementGradebook($parser, $tagName, $attrs) {
3047             //Refresh properties
3048             $this->level++;
3049             $this->tree[$this->level] = $tagName;
3051             //Output something to avoid browser timeouts...
3052             backup_flush();
3054             //Check if we are into GRADEBOOK zone
3055             //if ($this->tree[3] == "GRADEBOOK")                                                         //Debug
3056             //    echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n";  //Debug
3058             //If we are under a GRADE_PREFERENCE, GRADE_LETTER or GRADE_CATEGORY tag under a GRADEBOOK zone, accumule it
3059             if (isset($this->tree[5]) and isset($this->tree[3])) {
3060                 if (($this->tree[5] == "GRADE_PREFERENCE" || $this->tree[5] == "GRADE_LETTER" || $this->tree[5] == "GRADE_CATEGORY" ) && ($this->tree[3] == "GRADEBOOK")) {
3061                     if (!isset($this->temp)) {
3062                         $this->temp = "";
3063                     }
3064                     $this->temp .= "<".$tagName.">";
3065                 }
3066             }
3067         }
3068         
3069         
3070         //This is the startTag handler we use where we are reading the user zone (todo="USERS")
3071         function startElementUsers($parser, $tagName, $attrs) {
3072             //Refresh properties     
3073             $this->level++;
3074             $this->tree[$this->level] = $tagName;   
3076             //Check if we are into USERS zone  
3077             //if ($this->tree[3] == "USERS")                                                            //Debug
3078             //    echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n";   //Debug
3079         }
3081         //This is the startTag handler we use where we are reading the messages zone (todo="MESSAGES")
3082         function startElementMessages($parser, $tagName, $attrs) {
3083             //Refresh properties
3084             $this->level++;
3085             $this->tree[$this->level] = $tagName;
3087             //Output something to avoid browser timeouts...
3088             backup_flush();
3090             //Check if we are into MESSAGES zone
3091             //if ($this->tree[3] == "MESSAGES")                                                          //Debug
3092             //    echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n";  //Debug
3094             //If we are under a MESSAGE tag under a MESSAGES zone, accumule it
3095             if (isset($this->tree[4]) and isset($this->tree[3])) {
3096                 if (($this->tree[4] == "MESSAGE" || $this->tree[5] == "CONTACT" ) and ($this->tree[3] == "MESSAGES")) {
3097                     if (!isset($this->temp)) {
3098                         $this->temp = "";
3099                     }
3100                     $this->temp .= "<".$tagName.">";
3101                 }
3102             }
3103         }
3104         //This is the startTag handler we use where we are reading the questions zone (todo="QUESTIONS")
3105         function startElementQuestions($parser, $tagName, $attrs) {
3106             //Refresh properties
3107             $this->level++;
3108             $this->tree[$this->level] = $tagName;
3110             //if ($tagName == "QUESTION_CATEGORY" && $this->tree[3] == "QUESTION_CATEGORIES") {        //Debug
3111             //    echo "<P>QUESTION_CATEGORY: ".strftime ("%X",time()),"-";                            //Debug
3112             //}                                                                                        //Debug
3114             //Output something to avoid browser timeouts...
3115             backup_flush();
3117             //Check if we are into QUESTION_CATEGORIES zone
3118             //if ($this->tree[3] == "QUESTION_CATEGORIES")                                              //Debug
3119             //    echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n";   //Debug
3121             //If we are under a QUESTION_CATEGORY tag under a QUESTION_CATEGORIES zone, accumule it
3122             if (isset($this->tree[4]) and isset($this->tree[3])) {
3123                 if (($this->tree[4] == "QUESTION_CATEGORY") and ($this->tree[3] == "QUESTION_CATEGORIES")) {
3124                     if (!isset($this->temp)) {
3125                         $this->temp = "";
3126                     }
3127                     $this->temp .= "<".$tagName.">";
3128                 }
3129             }
3130         }
3132         //This is the startTag handler we use where we are reading the scales zone (todo="SCALES")
3133         function startElementScales($parser, $tagName, $attrs) {
3134             //Refresh properties          
3135             $this->level++;
3136             $this->tree[$this->level] = $tagName;
3138             //if ($tagName == "SCALE" && $this->tree[3] == "SCALES") {                                 //Debug
3139             //    echo "<P>SCALE: ".strftime ("%X",time()),"-";                                        //Debug
3140             //}                                                                                        //Debug
3142             //Output something to avoid browser timeouts...
3143             backup_flush();
3145             //Check if we are into SCALES zone
3146             //if ($this->tree[3] == "SCALES")                                                           //Debug
3147             //    echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n";   //Debug
3149             //If we are under a SCALE tag under a SCALES zone, accumule it
3150             if (isset($this->tree[4]) and isset($this->tree[3])) {
3151                 if (($this->tree[4] == "SCALE") and ($this->tree[3] == "SCALES")) {
3152                     if (!isset($this->temp)) {
3153                         $this->temp = "";
3154                     }
3155                     $this->temp .= "<".$tagName.">";
3156                 }
3157             }
3158         }
3160         function startElementGroups($parser, $tagName, $attrs) {
3161             //Refresh properties
3162             $this->level++;
3163             $this->tree[$this->level] = $tagName;
3165             //if ($tagName == "GROUP" && $this->tree[3] == "GROUPS") {                                 //Debug
3166             //    echo "<P>GROUP: ".strftime ("%X",time()),"-";                                        //Debug
3167             //}                                                                                        //Debug
3169             //Output something to avoid browser timeouts...
3170             backup_flush();
3172             //Check if we are into GROUPS zone
3173             //if ($this->tree[3] == "GROUPS")                                                           //Debug
3174             //    echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n";   //Debug
3176             //If we are under a GROUP tag under a GROUPS zone, accumule it
3177             if (isset($this->tree[4]) and isset($this->tree[3])) {
3178                 if (($this->tree[4] == "GROUP") and ($this->tree[3] == "GROUPS")) {
3179                     if (!isset($this->temp)) {
3180                         $this->temp = "";
3181                     }
3182                     $this->temp .= "<".$tagName.">";
3183                 }
3184             }
3185         }
3187         //This is the startTag handler we use where we are reading the events zone (todo="EVENTS")
3188         function startElementEvents($parser, $tagName, $attrs) {
3189             //Refresh properties
3190             $this->level++;
3191             $this->tree[$this->level] = $tagName;
3193             //if ($tagName == "EVENT" && $this->tree[3] == "EVENTS") {                                 //Debug
3194             //    echo "<P>EVENT: ".strftime ("%X",time()),"-";                                        //Debug
3195             //}                                                                                        //Debug
3197             //Output something to avoid browser timeouts...
3198             backup_flush();
3200             //Check if we are into EVENTS zone
3201             //if ($this->tree[3] == "EVENTS")