4f5ea37205106a90ef860a28c23eedb50c194044
[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         global $CFG;
10         $status = true;
12         if (empty($CFG->unzip)) {    // Use built-in php-based unzip function
13             include_once("$CFG->dirroot/lib/pclzip/pclzip.lib.php");
14             //include_once("$CFG->dirroot/lib/pclzip/pclerror.lib.php");    //Debug
15             //include_once("$CFG->dirroot/lib/pclzip/pcltrace.lib.php");    //Debug
16             //PclTraceOn(2);                                          //Debug
17             $archive = new PclZip($file);
18             if (!$list = $archive->extract(dirname($file))) {
19                 $status = false;
20             }
21             //PclTraceDisplay();                                       //Debug
22             //PclTraceOff();                                           //Debug
23         } else {                     // Use external unzip program
24             $command = "cd ".dirname($file)."; $CFG->unzip -o ".basename($file);
25             Exec($command);
26         }
28         return $status;
29     }
31     //This function checks if moodle.xml seems to be a valid xml file
32     //(exists, has an xml header and a course main tag
33     function restore_check_moodle_file ($file) {
34     
35         $status = true;
37         //Check if it exists
38         if ($status = is_file($file)) {
39             //Open it and read the first 200 bytes (chars)
40             $handle = fopen ($file, "r");
41             $first_chars = fread($handle,200);
42             $status = fclose ($handle);
43             //Chek if it has the requires strings
44             if ($status) {
45                 $status = strpos($first_chars,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
46                 if ($status !== false) {
47                     $status = strpos($first_chars,"<MOODLE_BACKUP>");
48                 }
49             }
50         }   
52         return $status;  
53     }   
55     //This function iterates over all modules in backup file, searching for a
56     //MODNAME_refresh_events() to execute. Perhaps it should ve moved to central Moodle...
57     function restore_refresh_events($restore) {
58    
59         global $CFG;
60         $status = true;
61         
62         //Take all modules in backup
63         $modules = $restore->mods;
64         //Iterate
65         foreach($modules as $name => $module) {
66             //Only if the module is being restored
67             if ($module->restore == 1) {
68                 //Include module library
69                 include_once("$CFG->dirroot/mod/$name/lib.php");
70                 //If module_refresh_events exists
71                 $function_name = $name."_refresh_events";
72                 if (function_exists($function_name)) {
73                     $status = $function_name($restore->course_id);
74                 }
75             }
76         }
77         return $status;
78     }
80     //This function makes all the necessary calls to xxxx_decode_content_links_caller()
81     //function in each module, passing them the desired contents to be decoded
82     //from backup format to destination site/course in order to mantain inter-activities
83     //working in the backup/restore process
84     function restore_decode_content_links($restore) {
86         global $CFG;
88         $status = true;
90         echo "<ul>";
91         foreach ($restore->mods as $name => $info) {
92             //If the module is being restored
93             if ($info->restore == 1) {
94                 //Check if the xxxx_decode_content_links_caller exists
95                 $function_name = $name."_decode_content_links_caller";
96                 if (function_exists($function_name)) {
97                     echo "<li>".get_string ("to")." ".get_string("modulenameplural",$name);
98                     $status = $function_name($restore);
99                 }
100             }
101         }
103         //Now I'm going to decode to their new location all the links in wiki texts
104         //having the syntax " modulename:moduleid".
105         echo "<li>wiki";
106         $status = restore_decode_wiki_texts($restore);
108         echo "</ul>";
110         return $status;
111     }
113     //This function search for some wiki texts in differenct parts of Moodle to
114     //decode them to their new ids.
115     function restore_decode_wiki_texts($restore) {
117         global $CFG;
119         $status = true;
121         echo "<ul>";
123         if (file_exists("$CFG->dirroot/mod/resource/lib.php")) {
124             include_once("$CFG->dirroot/mod/resource/lib.php");
125         }
127         $formatwiki = FORMAT_WIKI;
128         $typewiki = WIKITEXT;
129  
130         //FORUM: Decode every POST (message) in the course
131         //Check we are restoring forums
132         if ($restore->mods['forum']->restore == 1) {
133             echo "<li>".get_string("from")." ".get_string("modulenameplural","forum");
134             //Get all course posts
135             if ($posts = get_records_sql ("SELECT p.id, p.message
136                                        FROM {$CFG->prefix}forum_posts p,
137                                             {$CFG->prefix}forum_discussions d
138                                        WHERE d.course = $restore->course_id AND
139                                              p.discussion = d.id AND
140                                              p.format = $formatwiki")) {
141                 //Iterate over each post->message
142                 $i = 0;   //Counter to send some output to the browser to avoid timeouts
143                 foreach ($posts as $post) {
144                     //Increment counter
145                     $i++;
146                     $content = $post->message;
147                     //Decode it 
148                     $result = restore_decode_wiki_content($content,$restore);
150                     if ($result != $content) {
151                         //Update record
152                         $post->message = addslashes($result);
153                         $status = update_record("forum_posts",$post);
154                         if ($CFG->debug>7) {
155                             echo "<br><hr>".$content."<br>changed to</br>".$result."<hr><br>";
156                         }
157                     }
158                     //Do some output
159                     if (($i+1) % 5 == 0) {
160                         echo ".";
161                         if (($i+1) % 100 == 0) {
162                             echo "<br>";
163                         }
164                         backup_flush(300);
165                     }
166                 }
167             }
168         }
170         //RESOURCE: Decode every RESOURCE (alltext) in the coure
172         //Check we are restoring resources
173         if ($restore->mods['resource']->restore == 1) {
174             echo "<li>".get_string("from")." ".get_string("modulenameplural","resource");
175             //Get all course resources of type=8 WIKITEXT
176             if ($resources = get_records_sql ("SELECT r.id, r.alltext
177                                        FROM {$CFG->prefix}resource r
178                                        WHERE r.course = $restore->course_id AND
179                                              r.type = $typewiki")) {
180                 //Iterate over each resource->alltext
181                 $i = 0;   //Counter to send some output to the browser to avoid timeouts
182                 foreach ($resources as $resource) {
183                     //Increment counter
184                     $i++;
185                     $content = $resource->alltext;
186                     //Decode it
187                     $result = restore_decode_wiki_content($content,$restore);
188                     if ($result != $content) {
189                         //Update record
190                         $resource->alltext = addslashes($result);
191                         $status = update_record("resource",$resource);
192                         if ($CFG->debug>7) {
193                             echo "<br><hr>".$content."<br>changed to</br>".$result."<hr><br>";
194                         }
195                     }
196                     //Do some output
197                     if (($i+1) % 5 == 0) {
198                         echo ".";
199                         if (($i+1) % 100 == 0) {
200                             echo "<br>";
201                         }
202                         backup_flush(300);
203                     }
204                 }
205             }
206         }
207         echo "</ul>";
209         return $status;
211     }
213     //This function receives a wiki text in the restore process and
214     //return it with every link to modules " modulename:moduleid"
215     //converted if possible. See the space before modulename!!
216     function restore_decode_wiki_content($content,$restore) {
218         global $CFG;
219         
220         $result = $content;
221         
222         $searchstring='/ ([a-zA-Z]+):([0-9]+)\(([^)]+)\)/';
223         //We look for it
224         preg_match_all($searchstring,$content,$foundset);
225         //If found, then we are going to look for its new id (in backup tables)
226         if ($foundset[0]) { 
227             //print_object($foundset);                                     //Debug
228             //Iterate over foundset[2]. They are the old_ids               
229             foreach($foundset[2] as $old_id) {
230                 //We get the needed variables here (course id)
231                 $rec = backup_getid($restore->backup_unique_code,"course_modules",$old_id);
232                 //Personalize the searchstring
233                 $searchstring='/ ([a-zA-Z]+):'.$old_id.'\(([^)]+)\)/';
234                 //If it is a link to this course, update the link to its new location
235                 if($rec->new_id) {
236                     //Now replace it
237                     $result= preg_replace($searchstring,' $1:'.$rec->new_id.'($2)',$result);
238                 } else {
239                     //It's a foreign link so redirect it to its original URL
240                     $result= preg_replace($searchstring,$restore->original_wwwroot.'/mod/$1/view.php?id='.$old_id.'($2)',$result);
241                 }
242             }
243         }
244         return $result;
245     }
248     //This function read the xml file and store it data from the info zone in an object
249     function restore_read_xml_info ($xml_file) {
251         //We call the main read_xml function, with todo = INFO
252         $info = restore_read_xml ($xml_file,"INFO",false);
254         return $info;
255     }
257     //This function read the xml file and store it data from the course header zone in an object  
258     function restore_read_xml_course_header ($xml_file) {
260         //We call the main read_xml function, with todo = COURSE_HEADER
261         $info = restore_read_xml ($xml_file,"COURSE_HEADER",false);
263         return $info;
264     }
266     //This function read the xml file and store its data from the sections in a object
267     function restore_read_xml_sections ($xml_file) {
269         //We call the main read_xml function, with todo = SECTIONS
270         $info = restore_read_xml ($xml_file,"SECTIONS",false);
272         return $info;
273     }
274     
275     //This function read the xml file and store its data from the users in 
276     //backup_ids->info db (and user's id in $info)
277     function restore_read_xml_users ($restore,$xml_file) {
279         //We call the main read_xml function, with todo = USERS
280         $info = restore_read_xml ($xml_file,"USERS",$restore);
282         return $info;
283     }
285     //This function read the xml file and store its data from the questions in
286     //backup_ids->info db (and category's id in $info)
287     function restore_read_xml_questions ($restore,$xml_file) {
289         //We call the main read_xml function, with todo = QUESTIONS
290         $info = restore_read_xml ($xml_file,"QUESTIONS",$restore);
292         return $info;
293     }
295     //This function read the xml file and store its data from the scales in
296     //backup_ids->info db (and scale's id in $info)
297     function restore_read_xml_scales ($restore,$xml_file) {
299         //We call the main read_xml function, with todo = SCALES
300         $info = restore_read_xml ($xml_file,"SCALES",$restore);
302         return $info;
303     }
305     //This function read the xml file and store its data from the groups in
306     //backup_ids->info db (and group's id in $info)
307     function restore_read_xml_groups ($restore,$xml_file) {
309         //We call the main read_xml function, with todo = GROUPS
310         $info = restore_read_xml ($xml_file,"GROUPS",$restore);
312         return $info;
313     }
315     //This function read the xml file and store its data from the events (course) in
316     //backup_ids->info db (and event's id in $info)
317     function restore_read_xml_events ($restore,$xml_file) {
319         //We call the main read_xml function, with todo = EVENTS
320         $info = restore_read_xml ($xml_file,"EVENTS",$restore);
322         return $info;
323     }
325     //This function read the xml file and store its data from the modules in
326     //backup_ids->info
327     function restore_read_xml_modules ($restore,$xml_file) {
329         //We call the main read_xml function, with todo = MODULES
330         $info = restore_read_xml ($xml_file,"MODULES",$restore);
332         return $info;
333     }
335     //This function read the xml file and store its data from the logs in
336     //backup_ids->info
337     function restore_read_xml_logs ($restore,$xml_file) {
339         //We call the main read_xml function, with todo = LOGS
340         $info = restore_read_xml ($xml_file,"LOGS",$restore);
342         return $info;
343     }
345     //This function prints the contents from the info parammeter passed
346     function restore_print_info ($info) {
348         $status = true;
349         if ($info) {
350             //This is tha align to every ingo table      
351             $table->align = array ("RIGHT","LEFT");
352             //This is the nowrap clause 
353             $table->wrap = array ("","NOWRAP");
354             //The width
355             $table->width = "70%";
356             //Put interesting info in table
357             //The backup original name
358             $tab[0][0] = "<b>".get_string("backuporiginalname").":</b>";
359             $tab[0][1] = $info->backup_name;
360             //The moodle version
361             $tab[1][0] = "<b>".get_string("moodleversion").":</b>";
362             $tab[1][1] = $info->backup_moodle_release." (".$info->backup_moodle_version.")";
363             //The backup version
364             $tab[2][0] = "<b>".get_string("backupversion").":</b>";
365             $tab[2][1] = $info->backup_backup_release." (".$info->backup_backup_version.")";
366             //The backup date
367             $tab[3][0] = "<b>".get_string("backupdate").":</b>";
368             $tab[3][1] = userdate($info->backup_date);
369             //Print title
370             print_heading(get_string("backup").":");
371             $table->data = $tab;
372             //Print backup general info
373             print_table($table);
374             //Now backup contents in another table
375             $tab = array();
376             //First mods info
377             $mods = $info->mods;
378             $elem = 0;
379             foreach ($mods as $key => $mod) {
380                 $tab[$elem][0] = "<b>".get_string("modulenameplural",$key).":</b>";
381                 if ($mod->backup == "false") {
382                     $tab[$elem][1] = get_string("notincluded");
383                 } else {
384                     if ($mod->userinfo == "true") {
385                         $tab[$elem][1] = get_string("included")." ".get_string("withuserdata");
386                     } else {
387                         $tab[$elem][1] = get_string("included")." ".get_string("withoutuserdata");
388                     }
389                 }
390                 $elem++;
391             }
392             //Users info
393             $tab[$elem][0] = "<b>".get_string("users").":</b>";
394             $tab[$elem][1] = get_string($info->backup_users);
395             $elem++;
396             //Logs info
397             $tab[$elem][0] = "<b>".get_string("logs").":</b>";
398             if ($info->backup_logs == "true") {
399                 $tab[$elem][1] = get_string("yes");
400             } else {
401                 $tab[$elem][1] = get_string("no");
402             }
403             $elem++;
404             //User Files info
405             $tab[$elem][0] = "<b>".get_string("userfiles").":</b>";
406             if ($info->backup_user_files == "true") {
407                 $tab[$elem][1] = get_string("yes");
408             } else {
409                 $tab[$elem][1] = get_string("no");
410             }
411             $elem++;
412             //Course Files info
413             $tab[$elem][0] = "<b>".get_string("coursefiles").":</b>";
414             if ($info->backup_course_files == "true") {
415                 $tab[$elem][1] = get_string("yes");
416             } else {
417                 $tab[$elem][1] = get_string("no");
418             }
419             $elem++;
420             $table->data = $tab;
421             //Print title
422             print_heading(get_string("backupdetails").":");
423             //Print backup general info
424             print_table($table);
425         } else {
426             $status = false;
427         }
429         return $status;
430     }
432     //This function prints the contents from the course_header parammeter passed
433     function restore_print_course_header ($course_header) {
435         $status = true;
436         if ($course_header) {
437             //This is tha align to every ingo table
438             $table->align = array ("RIGHT","LEFT");
439             //The width
440             $table->width = "70%";
441             //Put interesting course header in table
442             //The course name
443             $tab[0][0] = "<b>".get_string("name").":</b>";
444             $tab[0][1] = $course_header->course_fullname." (".$course_header->course_shortname.")";
445             //The course summary
446             $tab[1][0] = "<b>".get_string("summary").":</b>";
447             $tab[1][1] = $course_header->course_summary;
448             $table->data = $tab;
449             //Print title
450             print_heading(get_string("course").":");
451             //Print backup course header info
452             print_table($table);
453         } else {
454             $status = false; 
455         }
456         return $status;
457     }
459     //This function create a new course record.
460     //When finished, course_header contains the id of the new course
461     function restore_create_new_course($restore,&$course_header) {
463         global $CFG;
464  
465         $status = true;
467         $fullname = $course_header->course_fullname;
468         $shortname = $course_header->course_shortname;
469         $currentfullname = "";
470         $currentshortname = "";
471         $counter = 0;
472         //Iteratere while the name exists
473         do {
474             if ($counter) {
475                 $suffixfull = " ".get_string("copy")." ".$counter;
476                 $suffixshort = "_".$counter;
477             } else {
478                 $suffixfull = "";
479                 $suffixshort = "";
480             }
481             $currentfullname = $fullname.$suffixfull;
482             $currentshortname = $shortname.$suffixshort;
483             $course = get_record("course","fullname",addslashes($currentfullname));
484             $counter++;
485         } while ($course);
487         //New name = currentname
488         $course_header->course_fullname = $currentfullname;
489         $course_header->course_shortname = $currentshortname;
490         
491         //Now calculate the category
492         $category = get_record("course_categories","id",$course_header->category->id,
493                                                    "name",addslashes($course_header->category->name));
494         //If no exists, try by name only
495         if (!$category) {
496             $category = get_record("course_categories","name",addslashes($course_header->category->name));
497         }
498         //If no exists, get category id 1
499         if (!$category) {
500             $category = get_record("course_categories","id","1");
501         }
502         //If category 1 doesn'exists, lets create the course category (get it from backup file)
503         if (!$category) {
504             $ins_category->name = addslashes($course_header->category->name);
505             $ins_category->parent = 0;
506             $ins_category->sortorder = 0;
507             $ins_category->coursecount = 0;
508             $ins_category->visible = 0;            //To avoid interferences with the rest of the site
509             $ins_category->timemodified = time();
510             $newid = insert_record("course_categories",$ins_category);
511             $category->id = $newid;
512             $category->name = $course_header->category->name;
513         }
514         //If exists, put new category id
515         if ($category) {
516             $course_header->category->id = $category->id;
517             $course_header->category->name = $category->name;
518         //Error, cannot locate category
519         } else {
520             $course_header->category->id = 0;
521             $course_header->category->name = get_string("unknowncategory");
522             $status = false;
523         }
525         //Create the course_object
526         if ($status) {
527             $course->category = addslashes($course_header->category->id);
528             $course->password = addslashes($course_header->course_password);
529             $course->fullname = addslashes($course_header->course_fullname);
530             $course->shortname = addslashes($course_header->course_shortname);
531             $course->summary = addslashes($course_header->course_summary);
532             $course->format = addslashes($course_header->course_format);
533             $course->showgrades = addslashes($course_header->course_showgrades);
534             $course->blockinfo = addslashes($course_header->blockinfo);
535             $course->newsitems = addslashes($course_header->course_newsitems);
536             $course->teacher = addslashes($course_header->course_teacher);
537             $course->teachers = addslashes($course_header->course_teachers);
538             $course->student = addslashes($course_header->course_student);
539             $course->students = addslashes($course_header->course_students);
540             $course->guest = addslashes($course_header->course_guest);
541             $course->startdate = addslashes($course_header->course_startdate);
542             $course->numsections = addslashes($course_header->course_numsections);
543             //$course->showrecent = addslashes($course_header->course_showrecent);   INFO: This is out in 1.3
544             $course->maxbytes = addslashes($course_header->course_maxbytes);
545             $course->showreports = addslashes($course_header->course_showreports);
546             $course->groupmode = addslashes($course_header->course_groupmode);
547             $course->groupmodeforce = addslashes($course_header->course_groupmodeforce);
548             $course->lang = addslashes($course_header->course_lang);
549             $course->marker = addslashes($course_header->course_marker);
550             $course->visible = addslashes($course_header->course_visible);
551             $course->hiddensections = addslashes($course_header->course_hiddensections);
552             $course->timecreated = addslashes($course_header->course_timecreated);
553             $course->timemodified = addslashes($course_header->course_timemodified);
554             //Adjust blockinfo field.
555             //If the info doesn't exist in backup, we create defaults, else we recode it 
556             //to current site blocks.
557             if (!$course->blockinfo) {
558                 //Create blockinfo default content
559                 if ($course->format == "social") {
560                     $course->blockinfo = blocks_get_default_blocks (NULL,"participants,search_forums,calendar_month,calendar_upcoming,social_activities,recent_activity,admin,course_list");
561                 } else {
562                     //For topics and weeks formats (default built in the function)
563                     $course->blockinfo = blocks_get_default_blocks();
564                 }
565             } else {
566                 $course->blockinfo = blocks_get_block_ids($course->blockinfo);
567             }
568             //Now insert the record
569             $newid = insert_record("course",$course);
570             if ($newid) {
571                 //save old and new course id
572                 backup_putid ($restore->backup_unique_code,"course",$course_header->course_id,$newid);
573                 //Replace old course_id in course_header
574                 $course_header->course_id = $newid;
575             } else {
576                 $status = false;
577             }
578         }
580         return $status;
581     }
583     //This function creates all the course_sections and course_modules from xml
584     //when restoring in a new course or simply checks sections and create records
585     //in backup_ids when restoring in a existing course
586     function restore_create_sections($restore,$xml_file) {
588         global $CFG,$db;
590         $status = true;
591         //Check it exists
592         if (!file_exists($xml_file)) {
593             $status = false;
594         }
595         //Get info from xml
596         if ($status) {
597             $info = restore_read_xml_sections($xml_file);
598         }
599         //Put the info in the DB, recoding ids and saving the in backup tables
601         $sequence = "";
603         if ($info) {
604             //For each, section, save it to db
605             foreach ($info->sections as $key => $sect) {
606                 $sequence = "";
607                 $section->course = $restore->course_id;
608                 $section->section = $sect->number;
609                 $section->summary = addslashes($sect->summary);
610                 $section->visible = $sect->visible;
611                 $section->sequence = "";
612                 //Now calculate the section's newid
613                 $newid = 0;
614                 if ($restore->restoreto == 2) {
615                 //Save it to db (only if restoring to new course)
616                     $newid = insert_record("course_sections",$section);
617                 } else {
618                     //Get section id when restoring in existing course
619                     $rec = get_record("course_sections","course",$restore->course_id,
620                                                         "section",$section->section);
621                     //If that section doesn't exist, get section 0 (every mod will be
622                     //asigned there
623                     if(!$rec) {
624                         $rec = get_record("course_sections","course",$restore->course_id,
625                                                             "section","0");
626                     }
627                     //New check. If section 0 doesn't exist, insert it here !!
628                     //Teorically this never should happen but, in practice, some users
629                     //have reported this issue. 
630                     if(!$rec) {
631                         $zero_sec->course = $restore->course_id;
632                         $zero_sec->section = 0;
633                         $zero_sec->summary = "";
634                         $zero_sec->sequence = "";
635                         $newid = insert_record("course_sections",$zero_sec);
636                         $rec->id = $newid;
637                         $rec->sequence = "";
638                     }
639                     $newid = $rec->id;
640                     $sequence = $rec->sequence;
641                 }
642                 if ($newid) {
643                     //save old and new section id
644                     backup_putid ($restore->backup_unique_code,"course_sections",$key,$newid);
645                 } else {
646                     $status = false;
647                 }
648                 //If all is OK, go with associated mods
649                 if ($status) {
650                     //If we have mods in the section
651                     if (!empty($sect->mods)) {
652                         //For each mod inside section
653                         foreach ($sect->mods as $keym => $mod) {
654                             //Check if we've to restore this module
655                             if ($restore->mods[$mod->type]->restore) {
656                                 //Get the module id from modules
657                                 $module = get_record("modules","name",$mod->type);
658                                 if ($module) {
659                                     $course_module->course = $restore->course_id;
660                                     $course_module->module = $module->id;
661                                     $course_module->section = $newid;
662                                     $course_module->added = $mod->added;
663                                     $course_module->deleted = $mod->deleted;
664                                     $course_module->score = $mod->score;
665                                     $course_module->indent = $mod->indent;
666                                     $course_module->visible = $mod->visible;
667                                     $course_module->groupmode = $mod->groupmode;
668                                     $course_module->instance = null;
669                                     //NOTE: The instance (new) is calculated and updated in db in the
670                                     //      final step of the restore. We don't know it yet.
671                                     //print_object($course_module);                                     //Debug
672                                     //Save it to db
673                                     $newidmod = insert_record("course_modules",$course_module); 
674                                     if ($newidmod) {
675                                         //save old and new module id
676                                         //In the info field, we save the original instance of the module
677                                         //to use it later
678                                         backup_putid ($restore->backup_unique_code,"course_modules",
679                                                                 $keym,$newidmod,$mod->instance);
680                                     } else {
681                                         $status = false;
682                                     }
683                                     //Now, calculate the sequence field
684                                     if ($status) {
685                                         if ($sequence) {
686                                             $sequence .= ",".$newidmod;
687                                         } else {
688                                             $sequence = $newidmod;
689                                         }
690                                     }
691                                 } else {
692                                     $status = false;
693                                 }
694                             }
695                         }
696                     }
697                 }
698                 //If all is OK, update sequence field in course_sections
699                 if ($status) {
700                     if (isset($sequence)) {
701                         $update_rec->id = $newid;
702                         $update_rec->sequence = $sequence;
703                         $status = update_record("course_sections",$update_rec);
704                     }
705                 }
706             }
707         } else {
708             $status = false;
709         }
710         return $status;
711     }
712     
713     //This function creates all the user, user_students, user_teachers
714     //user_course_creators and user_admins from xml
715     function restore_create_users($restore,$xml_file) {
717         global $CFG, $db;
719         $status = true;
720         //Check it exists
721         if (!file_exists($xml_file)) {
722             $status = false;
723         }
724         //Get info from xml
725         if ($status) {
726             //info will contain the old_id of every user
727             //in backup_ids->info will be the real info (serialized)
728             $info = restore_read_xml_users($restore,$xml_file);
729         }
731         //Now, get evey user_id from $info and user data from $backup_ids
732         //and create the necessary records (users, user_students, user_teachers
733         //user_course_creators and user_admins
734         if (!empty($info->users)) {
735             //For each user, take its info from backup_ids
736             foreach ($info->users as $userid) {
737                 $rec = backup_getid($restore->backup_unique_code,"user",$userid); 
738                 $user = $rec->info;
740                 //Check if it's admin and coursecreator
741                 $is_admin =         !empty($user->roles['admin']);
742                 $is_coursecreator = !empty($user->roles['coursecreator']);
744                 //Check if it's teacher and student
745                 $is_teacher = !empty($user->roles['teacher']);
746                 $is_student = !empty($user->roles['student']);
748                 //Check if it's needed
749                 $is_needed = !empty($user->roles['needed']);
751                 //Calculate if it is a course user
752                 //Has role teacher or student or needed
753                 $is_course_user = ($is_teacher or $is_student or $is_needed);
755                 //To store new ids created
756                 $newid=null;
757                 //check if it exists (by username) and get its id
758                 $user_exists = true;
759                 $user_data = get_record("user","username",addslashes($user->username));
760                 if (!$user_data) {
761                     $user_exists = false;
762                 } else {
763                     $newid = $user_data->id;
764                 }
765                 //Flags to see if we have to create the user, roles and preferences
766                 $create_user = true;
767                 $create_roles = true;
768                 $create_preferences = true;
770                 //If we are restoring course users and it isn't a course user
771                 if ($restore->users == 1 and !$is_course_user) {
772                     //If only restoring course_users and user isn't a course_user, inform to $backup_ids
773                     $status = backup_putid($restore->backup_unique_code,"user",$userid,null,'notincourse');
774                     $create_user = false;
775                     $create_roles = false;
776                     $create_preferences = false;
777                 }
779                 if ($user_exists and $create_user) {
780                     //If user exists mark its newid in backup_ids (the same than old)
781                     $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,'exists');
782                     $create_user = false;
783                 }
785                 //Here, if create_user, do it
786                 if ($create_user) {
787                     //Unset the id because it's going to be inserted with a new one
788                     unset ($user->id);
789                     //We addslashes to necessary fields
790                     $user->username = addslashes($user->username);
791                     $user->firstname = addslashes($user->firstname);
792                     $user->lastname = addslashes($user->lastname);
793                     $user->email = addslashes($user->email);
794                     $user->institution = addslashes($user->institution);
795                     $user->department = addslashes($user->department);
796                     $user->address = addslashes($user->address);
797                     $user->city = addslashes($user->city);
798                     $user->url = addslashes($user->url);
799                     $user->description = addslashes($user->description);
800                     //We are going to create the user
801                     //The structure is exactly as we need
802                     $newid = insert_record ("user",$user);
803                     //Put the new id
804                     $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,"new");
805                 }
807                 //Here, if create_roles, do it as necessary
808                 if ($create_roles) {
809                     //Get the newid and current info from backup_ids
810                     $data = backup_getid($restore->backup_unique_code,"user",$userid);
811                     $newid = $data->new_id;
812                     $currinfo = $data->info.",";
814                     //Now, depending of the role, create records in user_studentes and user_teacher 
815                     //and/or mark it in backup_ids
816                     
817                     if ($is_admin) {
818                         //If the record (user_admins) doesn't exists
819                         if (!record_exists("user_admins","userid",$newid)) {
820                             //Only put status in backup_ids
821                             $currinfo = $currinfo."admin,";
822                             $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
823                         }
824                     } 
825                     if ($is_coursecreator) {
826                         //If the record (user_coursecreators) doesn't exists
827                         if (!record_exists("user_coursecreators","userid",$newid)) {
828                             //Only put status in backup_ids
829                             $currinfo = $currinfo."coursecreator,";
830                             $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
831                         }
832                     } 
833                     if ($is_needed) {
834                         //Only put status in backup_ids
835                         $currinfo = $currinfo."needed,";
836                         $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
837                     }
838                     if ($is_teacher) {
839                         //If the record (teacher) doesn't exists
840                         if (!record_exists("user_teachers","userid",$newid,"course", $restore->course_id)) {
841                             //Put status in backup_ids 
842                             $currinfo = $currinfo."teacher,";
843                             $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
844                             //Set course and user
845                             $user->roles['teacher']->course = $restore->course_id;
846                             $user->roles['teacher']->userid = $newid;
847                             //Insert data in user_teachers
848                             //The structure is exactly as we need
849                             $status = insert_record("user_teachers",$user->roles['teacher']);
850                         }
851                     } 
852                     if ($is_student) {
853                         //If the record (student) doesn't exists
854                         if (!record_exists("user_students","userid",$newid,"course", $restore->course_id)) {
855                             //Put status in backup_ids
856                             $currinfo = $currinfo."student,";
857                             $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
858                             //Set course and user
859                             $user->roles['student']->course = $restore->course_id;
860                             $user->roles['student']->userid = $newid;
861                             //Insert data in user_students
862                             //The structure is exactly as we need
863                             $status = insert_record("user_students",$user->roles['student']);
864                         }
865                     }
866                     if (!$is_course_user) {
867                         //If the record (user) doesn't exists
868                         if (!record_exists("user","id",$newid)) {
869                             //Put status in backup_ids
870                             $currinfo = $currinfo."user,";
871                             $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
872                         }
873                     }
874                 }
876                 //Here, if create_preferences, do it as necessary
877                 if ($create_preferences) {
878                     //echo "Checking for preferences of user ".$user->username."<br>";         //Debug
879                     //Get user new id from backup_ids
880                     $data = backup_getid($restore->backup_unique_code,"user",$userid);
881                     $newid = $data->new_id;
882                     if (isset($user->user_preferences)) {
883                         //echo "Preferences exist in backup file<br>";                         //Debug
884                         foreach($user->user_preferences as $user_preference) {
885                             //echo $user_preference->name." = ".$user_preference->value."<br>";    //Debug
886                             //We check if that user_preference exists in DB
887                             if (!record_exists("user_preferences","userid",$newid,"name",$user_preference->name)) {
888                                 //echo "Creating it<br>";                                              //Debug
889                                 //Prepare the record and insert it
890                                 $user_preference->userid = $newid;
891                                 $status = insert_record("user_preferences",$user_preference);
892                             }
893                         }
894                     }
895                 }
896             }
897         }
899         return $status;
900     }
902     //This function creates all the categories and questions
903     //from xml (STEP1 of quiz restore)
904     function restore_create_questions($restore,$xml_file) {
906         global $CFG, $db;
908         $status = true;
909         //Check it exists
910         if (!file_exists($xml_file)) {
911             $status = false;
912         }
913         //Get info from xml
914         if ($status) {
915             //info will contain the old_id of every category
916             //in backup_ids->info will be the real info (serialized)
917             $info = restore_read_xml_questions($restore,$xml_file);
918         }
919         //Now, if we have anything in info, we have to restore that
920         //categories/questions
921         if ($info) {
922             if ($info !== true) {
923                 //Iterate over each category
924                 foreach ($info as $category) {
925                     $catrestore = "quiz_restore_question_categories";
926                     if (function_exists($catrestore)) {
927                         //print_object ($category);                                                //Debug
928                         $status = $catrestore($category,$restore);
929                     } else {
930                         //Something was wrong. Function should exist.
931                         $status = false;
932                     }
933                 }
934             }
935         } else {
936             $status = false;
937         }   
938         return $status;
939     }
941     //This function creates all the scales
942     function restore_create_scales($restore,$xml_file) {
944         global $CFG, $db;
946         $status = true;
947         //Check it exists
948         if (!file_exists($xml_file)) {
949             $status = false;
950         }
951         //Get info from xml
952         if ($status) {
953             //scales will contain the old_id of every scale
954             //in backup_ids->info will be the real info (serialized)
955             $scales = restore_read_xml_scales($restore,$xml_file);
956         }
957         //Now, if we have anything in scales, we have to restore that
958         //scales
959         if ($scales) {
960             if ($scales !== true) {
961                 //Iterate over each scale
962                 foreach ($scales as $scale) {
963                     //Get record from backup_ids
964                     $data = backup_getid($restore->backup_unique_code,"scale",$scale->id);
965                     //Init variables
966                     $create_scale = false;
968                     if ($data) {
969                         //Now get completed xmlized object
970                         $info = $data->info;
971                         //traverse_xmlize($info);                                                                     //Debug
972                         //print_object ($GLOBALS['traverse_array']);                                                  //Debug
973                         //$GLOBALS['traverse_array']="";                                                              //Debug
975                         //Now build the SCALE record structure
976                         $sca->courseid = backup_todb($info['SCALE']['#']['COURSEID']['0']['#']);
977                         $sca->userid = backup_todb($info['SCALE']['#']['USERID']['0']['#']);
978                         $sca->name = backup_todb($info['SCALE']['#']['NAME']['0']['#']);
979                         $sca->scale = backup_todb($info['SCALE']['#']['SCALETEXT']['0']['#']);
980                         $sca->description = backup_todb($info['SCALE']['#']['DESCRIPTION']['0']['#']);
981                         $sca->timemodified = backup_todb($info['SCALE']['#']['TIMEMODIFIED']['0']['#']);
983                         //Now search if that scale exists (by scale field) in course 0 (Standar scale)
984                         //or in restore->course_id course (Personal scale)
985                         if ($sca->courseid == 0) {
986                             $course_to_search = 0;
987                         } else {
988                             $course_to_search = $restore->course_id;
989                         }
990                         $sca_db = get_record("scale","scale",$sca->scale,"courseid",$course_to_search);
991                         //If it doesn't exist, create
992                         if (!$sca_db) {
993                             $create_scale = true;
994                         } 
995                         //If we must create the scale
996                         if ($create_scale) {
997                             //Me must recode the courseid if it's <> 0 (common scale)
998                             if ($sca->courseid != 0) {
999                                 $sca->courseid = $restore->course_id;
1000                             }
1001                             //We must recode the userid
1002                             $user = backup_getid($restore->backup_unique_code,"user",$sca->userid);
1003                             if ($user) {
1004                                 $sca->userid = $user->new_id;
1005                             } else {
1006                                 //Assign it to admin
1007                                 $sca->userid = 1;
1008                             }
1009                             //The structure is equal to the db, so insert the scale
1010                             $newid = insert_record ("scale",$sca);
1011                         } else {
1012                             //get current scale id
1013                             $newid = $sca_db->id;
1014                         }
1015                         if ($newid) {
1016                             //We have the newid, update backup_ids
1017                             backup_putid($restore->backup_unique_code,"scale",
1018                                          $scale->id, $newid);
1019                         }
1020                     }
1021                 }
1022             }
1023         } else {
1024             $status = false;
1025         }  
1026         return $status;
1027     }
1029     //This function creates all the groups
1030     function restore_create_groups($restore,$xml_file) {
1032         global $CFG, $db;
1034         $status = true;
1035         $status2 = true;
1036         //Check it exists
1037         if (!file_exists($xml_file)) {
1038             $status = false;
1039         }
1040         //Get info from xml
1041         if ($status) {
1042             //groups will contain the old_id of every group
1043             //in backup_ids->info will be the real info (serialized)
1044             $groups = restore_read_xml_groups($restore,$xml_file);
1045         }
1046         //Now, if we have anything in groups, we have to restore that
1047         //groups
1048         if ($groups) {
1049             if ($groups !== true) {
1050                 //Iterate over each group
1051                 foreach ($groups as $group) {
1052                     //Get record from backup_ids
1053                     $data = backup_getid($restore->backup_unique_code,"group",$group->id);
1054                     //Init variables
1055                     $create_group = false;
1057                     if ($data) {
1058                         //Now get completed xmlized object
1059                         $info = $data->info;
1060                         //traverse_xmlize($info);                                                                     //Debug
1061                         //print_object ($GLOBALS['traverse_array']);                                                  //Debug
1062                         //$GLOBALS['traverse_array']="";                                                              //Debug
1063                         //Now build the GROUP record structure
1064                         $gro->courseid = backup_todb($info['GROUP']['#']['COURSEID']['0']['#']);
1065                         $gro->name = backup_todb($info['GROUP']['#']['NAME']['0']['#']);
1066                         $gro->description = backup_todb($info['GROUP']['#']['DESCRIPTION']['0']['#']);
1067                         $gro->lang = backup_todb($info['GROUP']['#']['LANG']['0']['#']);
1068                         $gro->picture = backup_todb($info['GROUP']['#']['PICTURE']['0']['#']);
1069                         $gro->hidepicture = backup_todb($info['GROUP']['#']['HIDEPICTURE']['0']['#']);
1070                         $gro->timecreated = backup_todb($info['GROUP']['#']['TIMECREATED']['0']['#']);
1071                         $gro->timemodified = backup_todb($info['GROUP']['#']['TIMEMODIFIED']['0']['#']);
1072                 
1073                         //Now search if that group exists (by name and description field) in 
1074                         //restore->course_id course 
1075                         $gro_db = get_record("groups","courseid",$restore->course_id,"name",$gro->name,"description",$gro->description);
1076                         //If it doesn't exist, create
1077                         if (!$gro_db) {
1078                             $create_group = true;
1079                         }
1080                         //If we must create the group
1081                         if ($create_group) {
1082                             //Me must recode the courseid to the restore->course_id 
1083                             $gro->courseid = $restore->course_id;
1084                             //The structure is equal to the db, so insert the group
1085                             $newid = insert_record ("groups",$gro);
1086                         } else { 
1087                             //get current group id
1088                             $newid = $gro_db->id;
1089                         }
1090                         if ($newid) {
1091                             //We have the newid, update backup_ids
1092                             backup_putid($restore->backup_unique_code,"group",
1093                                          $group->id, $newid);
1094                         }
1095                         //Now restore members in the groups_members
1096                         $status2 = restore_create_groups_members($newid,$info,$restore);
1097                     }   
1098                 }
1099             }
1100         } else {
1101             $status = false;
1102         } 
1103         return ($status && $status2);
1104     }
1106     //This function restores the groups_members
1107     function restore_create_groups_members($group_id,$info,$restore) {
1109         global $CFG;
1111         $status = true;
1113         //Get the members array
1114         $members = $info['GROUP']['#']['MEMBERS']['0']['#']['MEMBER'];
1116         //Iterate over members
1117         for($i = 0; $i < sizeof($members); $i++) {
1118             $mem_info = $members[$i];
1119             //traverse_xmlize($mem_info);                                                                 //Debug
1120             //print_object ($GLOBALS['traverse_array']);                                                  //Debug
1121             //$GLOBALS['traverse_array']="";                                                              //Debug
1123             //Now, build the GROUPS_MEMBERS record structure
1124             $group_member->groupid = $group_id;
1125             $group_member->userid = backup_todb($mem_info['#']['USERID']['0']['#']);
1126             $group_member->timeadded = backup_todb($mem_info['#']['TIMEADDED']['0']['#']);
1128             //We have to recode the userid field
1129             $user = backup_getid($restore->backup_unique_code,"user",$group_member->userid);
1130             if ($user) {
1131                 $group_member->userid = $user->new_id;
1132             }
1134             //The structure is equal to the db, so insert the groups_members
1135             $newid = insert_record ("groups_members",$group_member);
1137             //Do some output
1138             if (($i+1) % 50 == 0) {
1139                 echo ".";
1140                 if (($i+1) % 1000 == 0) {
1141                     echo "<br>";
1142                 }
1143                 backup_flush(300);
1144             }
1145             
1146             if (!$newid) {
1147                 $status = false;
1148             }
1149         }
1151         return $status;
1152     }
1154     //This function creates all the course events
1155     function restore_create_events($restore,$xml_file) {
1157         global $CFG, $db;
1159         $status = true;
1160         //Check it exists
1161         if (!file_exists($xml_file)) {
1162             $status = false;
1163         }
1164         //Get info from xml
1165         if ($status) {
1166             //events will contain the old_id of every event
1167             //in backup_ids->info will be the real info (serialized)
1168             $events = restore_read_xml_events($restore,$xml_file);
1169         }
1170         //Now, if we have anything in events, we have to restore that
1171         //events
1172         if ($events) {
1173             if ($events !== true) {
1174                 //Iterate over each event
1175                 foreach ($events as $event) {
1176                     //Get record from backup_ids
1177                     $data = backup_getid($restore->backup_unique_code,"event",$event->id);
1178                     //Init variables
1179                     $create_event = false;
1181                     if ($data) {
1182                         //Now get completed xmlized object
1183                         $info = $data->info;
1184                         //traverse_xmlize($info);                                                                     //Debug
1185                         //print_object ($GLOBALS['traverse_array']);                                                  //Debug
1186                         //$GLOBALS['traverse_array']="";                                                              //Debug
1188                         //Now build the EVENT record structure
1189                         $eve->name = backup_todb($info['EVENT']['#']['NAME']['0']['#']);
1190                         $eve->description = backup_todb($info['EVENT']['#']['DESCRIPTION']['0']['#']);
1191                         $eve->format = backup_todb($info['EVENT']['#']['FORMAT']['0']['#']);
1192                         $eve->courseid = $restore->course_id;
1193                         $eve->groupid = backup_todb($info['EVENT']['#']['GROUPID']['0']['#']);
1194                         $eve->userid = backup_todb($info['EVENT']['#']['USERID']['0']['#']);
1195                         $eve->modulename = "";
1196                         $eve->instance = 0;
1197                         $eve->eventtype = backup_todb($info['EVENT']['#']['EVENTTYPE']['0']['#']);
1198                         $eve->timestart = backup_todb($info['EVENT']['#']['TIMESTART']['0']['#']);
1199                         $eve->timeduration = backup_todb($info['EVENT']['#']['TIMEDURATION']['0']['#']);
1200                         $eve->visible = backup_todb($info['EVENT']['#']['VISIBLE']['0']['#']);
1201                         $eve->timemodified = backup_todb($info['EVENT']['#']['TIMEMODIFIED']['0']['#']);
1203                         //Now search if that event exists (by description and timestart field) in
1204                         //restore->course_id course 
1205                         $eve_db = get_record("event","courseid",$eve->courseid,"description",$eve->description,"timestart",$eve->timestart);
1206                         //If it doesn't exist, create
1207                         if (!$eve_db) {
1208                             $create_event = true;
1209                         }
1210                         //If we must create the event
1211                         if ($create_event) {
1213                             //We must recode the userid
1214                             $user = backup_getid($restore->backup_unique_code,"user",$eve->userid);
1215                             if ($user) {
1216                                 $eve->userid = $user->new_id;
1217                             } else {
1218                                 //Assign it to admin
1219                                 $eve->userid = 1;
1220                             }
1221                             //We have to recode the groupid field
1222                             $group = backup_getid($restore->backup_unique_code,"group",$eve->groupid);
1223                             if ($group) {
1224                                 $eve->groupid = $group->new_id;
1225                             } else {
1226                                 //Assign it to group 0
1227                                 $eve->groupid = 0;
1228                             }
1230                             //The structure is equal to the db, so insert the event
1231                             $newid = insert_record ("event",$eve);
1232                         } else {
1233                             //get current event id
1234                             $newid = $eve_db->id;
1235                         }
1236                         if ($newid) {
1237                             //We have the newid, update backup_ids
1238                             backup_putid($restore->backup_unique_code,"event",
1239                                          $event->id, $newid);
1240                         }
1241                     }
1242                 }
1243             }
1244         } else {
1245             $status = false;
1246         } 
1247         return $status;
1248     }
1250     //This function decode things to make restore multi-site fully functional
1251     //It does this conversions:
1252     //    - $@FILEPHP@$ -------------------------------> $CFG->wwwroot/file.php/courseid
1253     //
1254     //Note: Inter-activities linking is being implemented as a final
1255     //step in the restore execution, because we need to have it 
1256     //finished to know all the oldid, newid equivaleces
1257     function restore_decode_absolute_links($content) {
1258                                      
1259         global $CFG,$restore;    
1261         //Now decode wwwroot and file.php calls
1262         $search = array ("$@FILEPHP@$");
1263         
1264         $replace = array ($CFG->wwwroot."/file.php/".$restore->course_id);
1265     
1266         $result = str_replace($search,$replace,$content);
1268         if ($result != $content && $CFG->debug>7) {                                  //Debug
1269             echo "<br><hr>".$content."<br>changed to<br>".$result."<hr><br>";        //Debug
1270         }                                                                            //Debug
1272         return $result;
1273     }
1275     //This function restores the userfiles from the temp (user_files) directory to the
1276     //dataroot/users directory
1277     function restore_user_files($restore) {
1279         global $CFG;
1281         $status = true;
1283         $counter = 0;
1285         //First, we check to "users" exists and create is as necessary
1286         //in CFG->dataroot
1287         $dest_dir = $CFG->dataroot."/users";
1288         $status = check_dir_exists($dest_dir,true);
1290         //Now, we iterate over "user_files" records to check if that user dir must be
1291         //copied (and renamed) to the "users" dir.
1292         $rootdir = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/user_files";
1293         //Check if directory exists
1294         if (is_dir($rootdir)) {
1295             $list = list_directories ($rootdir);
1296             if ($list) {
1297                 //Iterate
1298                 $counter = 0;
1299                 foreach ($list as $dir) {
1300                     //Look for dir like username in backup_ids
1301                     $data = get_record ("backup_ids","backup_code",$restore->backup_unique_code,
1302                                                      "table_name","user",
1303                                                      "old_id",$dir);
1304                     //If thar user exists in backup_ids
1305                     if ($data) {
1306                         //Only it user has been created now
1307                         //or if it existed previously, but he hasn't image (see bug 1123)
1308                         if ((strpos($data->info,"new") !== false) or 
1309                             (!check_dir_exists($dest_dir."/".$data->new_id,false))) {
1310                             //Copy the old_dir to its new location (and name) !!
1311                             //Only if destination doesn't exists
1312                             if (!file_exists($dest_dir."/".$data->new_id)) {
1313                                 $status = backup_copy_file($rootdir."/".$dir,
1314                                               $dest_dir."/".$data->new_id);
1315                                 $counter ++;
1316                             }
1317                             //Do some output
1318                             if ($counter % 2 == 0) {
1319                                 echo ".";
1320                                 if ($counter % 40 == 0) {
1321                                 echo "<br>";
1322                                 }
1323                                 backup_flush(300);
1324                             }
1325                         }
1326                     }
1327                 }
1328             }
1329         }
1330         //If status is ok and whe have dirs created, returns counter to inform
1331         if ($status and $counter) {
1332             return $counter;
1333         } else {
1334             return $status;
1335         }
1336     }
1338     //This function restores the course files from the temp (course_files) directory to the
1339     //dataroot/course_id directory
1340     function restore_course_files($restore) {
1342         global $CFG;
1344         $status = true;
1345  
1346         $counter = 0;
1348         //First, we check to "course_id" exists and create is as necessary
1349         //in CFG->dataroot
1350         $dest_dir = $CFG->dataroot."/".$restore->course_id;
1351         $status = check_dir_exists($dest_dir,true);
1353         //Now, we iterate over "course_files" records to check if that file/dir must be
1354         //copied to the "dest_dir" dir.
1355         $rootdir = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/course_files";
1356         //Check if directory exists
1357         if (is_dir($rootdir)) {
1358             $list = list_directories_and_files ($rootdir);
1359             if ($list) {
1360                 //Iterate
1361                 $counter = 0;
1362                 foreach ($list as $dir) {
1363                     //Copy the dir to its new location 
1364                     //Only if destination file/dir doesn exists
1365                     if (!file_exists($dest_dir."/".$dir)) {
1366                         $status = backup_copy_file($rootdir."/".$dir,
1367                                       $dest_dir."/".$dir);
1368                         $counter ++;
1369                     }
1370                     //Do some output
1371                     if ($counter % 2 == 0) {       
1372                         echo ".";
1373                         if ($counter % 40 == 0) {       
1374                         echo "<br>";
1375                         }
1376                         backup_flush(300);
1377                     }
1378                 }
1379             }
1380         }
1381         //If status is ok and whe have dirs created, returns counter to inform
1382         if ($status and $counter) {
1383             return $counter;
1384         } else {
1385             return $status;
1386         }
1387     }
1388    
1390     //This function creates all the structures for every module in backup file
1391     //Depending what has been selected.
1392     function restore_create_modules($restore,$xml_file) {
1394         global $CFG;
1396         $status = true;
1397         //Check it exists
1398         if (!file_exists($xml_file)) {
1399             $status = false;
1400         }
1401         //Get info from xml
1402         if ($status) {
1403             //info will contain the id and modtype of every module
1404             //in backup_ids->info will be the real info (serialized)
1405             $info = restore_read_xml_modules($restore,$xml_file);
1406         }
1408         //Now, if we have anything in info, we have to restore that mods
1409         //from backup_ids (calling every mod restore function)
1410         if ($info) {
1411             if ($info !== true) {
1412                 //Iterate over each module
1413                 foreach ($info as $mod) {
1414                     $modrestore = $mod->modtype."_restore_mods";
1415                     if (function_exists($modrestore)) {
1416                         //print_object ($mod);                                                //Debug
1417                         $status = $modrestore($mod,$restore);
1418                     } else {
1419                         //Something was wrong. Function should exist.
1420                         $status = false;
1421                     }
1422                 }
1423             }
1424         } else {
1425             $status = false;
1426         }
1427        return $status;
1428     }
1430     //This function creates all the structures for every log in backup file
1431     //Depending what has been selected.
1432     function restore_create_logs($restore,$xml_file) {
1433             
1434         global $CFG,$db;
1436         //Number of records to get in every chunk
1437         $recordset_size = 4;
1438         //Counter, points to current record
1439         $counter = 0;
1440         //To count all the recods to restore
1441         $count_logs = 0;
1442         
1443         $status = true;
1444         //Check it exists 
1445         if (!file_exists($xml_file)) { 
1446             $status = false;
1447         }
1448         //Get info from xml
1449         if ($status) {
1450             //count_logs will contain the number of logs entries to process
1451             //in backup_ids->info will be the real info (serialized)
1452             $count_logs = restore_read_xml_logs($restore,$xml_file);
1453         }
1454  
1455         //Now, if we have records in count_logs, we have to restore that logs
1456         //from backup_ids. This piece of code makes calls to:
1457         // - restore_log_course() if it's a course log
1458         // - restore_log_user() if it's a user log
1459         // - restore_log_module() if it's a module log.
1460         //And all is segmented in chunks to allow large recordsets to be restored !!
1461         if ($count_logs > 0) {
1462             while ($counter < $count_logs) {
1463                 //Get a chunk of records
1464                 //Take old_id twice to avoid adodb limitation
1465                 $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);
1466                 //We have logs
1467                 if ($logs) {
1468                     //Iterate
1469                     foreach ($logs as $log) {
1470                         //Get the full record from backup_ids
1471                         $data = backup_getid($restore->backup_unique_code,"log",$log->old_id);
1472                         if ($data) {
1473                             //Now get completed xmlized object
1474                             $info = $data->info;
1475                             //traverse_xmlize($info);                                                                     //Debug
1476                             //print_object ($GLOBALS['traverse_array']);                                                  //Debug
1477                             //$GLOBALS['traverse_array']="";                                                              //Debug
1478                             //Now build the LOG record structure
1479                             $dblog->time = backup_todb($info['LOG']['#']['TIME']['0']['#']);
1480                             $dblog->userid = backup_todb($info['LOG']['#']['USERID']['0']['#']);
1481                             $dblog->ip = backup_todb($info['LOG']['#']['IP']['0']['#']);
1482                             $dblog->course = $restore->course_id;
1483                             $dblog->module = backup_todb($info['LOG']['#']['MODULE']['0']['#']);
1484                             $dblog->cmid = backup_todb($info['LOG']['#']['CMID']['0']['#']);
1485                             $dblog->action = backup_todb($info['LOG']['#']['ACTION']['0']['#']);
1486                             $dblog->url = backup_todb($info['LOG']['#']['URL']['0']['#']);
1487                             $dblog->info = backup_todb($info['LOG']['#']['INFO']['0']['#']);
1488                             //We have to recode the userid field
1489                             $user = backup_getid($restore->backup_unique_code,"user",$dblog->userid);
1490                             if ($user) {
1491                                 //echo "User ".$dblog->userid." to user ".$user->new_id."<br>";                             //Debug
1492                                 $dblog->userid = $user->new_id;
1493                             }
1494                             //We have to recode the cmid field (if module isn't "course" or "user")
1495                             if ($dblog->module != "course" and $dblog->module != "user") {
1496                                 $cm = backup_getid($restore->backup_unique_code,"course_modules",$dblog->cmid);
1497                                 if ($cm) {
1498                                     //echo "Module ".$dblog->cmid." to module ".$cm->new_id."<br>";                         //Debug
1499                                     $dblog->cmid = $cm->new_id;
1500                                 } else {
1501                                     $dblog->cmid = 0;
1502                                 }
1503                             }
1504                             //print_object ($dblog);                                                                        //Debug
1505                             //Now, we redirect to the needed function to make all the work
1506                             if ($dblog->module == "course") {
1507                                 //It's a course log,
1508                                 $stat = restore_log_course($restore,$dblog);
1509                             } elseif ($dblog->module == "user") {
1510                                 //It's a user log,
1511                                 $stat = restore_log_user($restore,$dblog);
1512                             } else {
1513                                 //It's a module log,
1514                                 $stat = restore_log_module($restore,$dblog);
1515                             }
1516                         }
1518                         //Do some output
1519                         $counter++;
1520                         if ($counter % 10 == 0) {
1521                             echo ".";
1522                             if ($counter % 200 == 0) {
1523                                 echo "<br>";
1524                             }
1525                             backup_flush(300);
1526                         }
1527                     }
1528                 } else {
1529                     //We never should arrive here
1530                     $counter = $count_logs;
1531                     $status = false;
1532                 }
1533             }
1534         }
1536         return $status;
1537     }
1539     //This function inserts a course log record, calculating the URL field as necessary
1540     function restore_log_course($restore,$log) {
1542         $status = true;
1543         $toinsert = false;
1545         //echo "<hr>Before transformations<br>";                                        //Debug
1546         //print_object($log);                                                           //Debug
1547         //Depending of the action, we recode different things
1548         switch ($log->action) {
1549         case "view":
1550             $log->url = "view.php?id=".$log->course;
1551             $log->info = $log->course;
1552             $toinsert = true;
1553             break;
1554         case "user report":
1555             //recode the info field (it's the user id)
1556             $user = backup_getid($restore->backup_unique_code,"user",$log->info);
1557             if ($user) {
1558                 $log->info = $user->new_id;
1559                 //Now, extract the mode from the url field
1560                 $mode = substr(strrchr($log->url,"="),1);
1561                 $log->url = "user.php?id=".$log->course."&user=".$log->info."&mode=".$mode;
1562                 $toinsert = true;
1563             }
1564             break;
1565         case "add mod":
1566             //Extract the course_module from the url field
1567             $cmid = substr(strrchr($log->url,"="),1);
1568             //recode the course_module to see it it has been restored
1569             $cm = backup_getid($restore->backup_unique_code,"course_modules",$cmid);
1570             if ($cm) {
1571                 $cmid = $cm->new_id;
1572                 //Extract the module name and the module id from the info field
1573                 $modname = strtok($log->info," ");
1574                 $modid = strtok(" ");
1575                 //recode the module id to see if it has been restored
1576                 $mod = backup_getid($restore->backup_unique_code,$modname,$modid);
1577                 if ($mod) {
1578                     $modid = $mod->new_id;
1579                     //Now I have everything so reconstruct url and info
1580                     $log->info = $modname." ".$modid;
1581                     $log->url = "../mod/".$modname."/view.php?id=".$cmid;
1582                     $toinsert = true;
1583                 }
1584             }
1585             break;
1586         case "update mod":
1587             //Extract the course_module from the url field
1588             $cmid = substr(strrchr($log->url,"="),1);
1589             //recode the course_module to see it it has been restored
1590             $cm = backup_getid($restore->backup_unique_code,"course_modules",$cmid);
1591             if ($cm) {
1592                 $cmid = $cm->new_id;
1593                 //Extract the module name and the module id from the info field
1594                 $modname = strtok($log->info," ");
1595                 $modid = strtok(" ");
1596                 //recode the module id to see if it has been restored
1597                 $mod = backup_getid($restore->backup_unique_code,$modname,$modid);
1598                 if ($mod) {
1599                     $modid = $mod->new_id;
1600                     //Now I have everything so reconstruct url and info
1601                     $log->info = $modname." ".$modid;
1602                     $log->url = "../mod/".$modname."/view.php?id=".$cmid;
1603                     $toinsert = true;
1604                 }
1605             }
1606             break;
1607         case "delete mod":
1608             $log->url = "view.php?id=".$log->course;
1609             $toinsert = true;
1610             break;
1611         case "update":
1612             $log->url = "edit.php?id=".$log->course;
1613             $log->info = "";
1614             $toinsert = true;
1615             break;
1616         case "unenrol":
1617             //recode the info field (it's the user id)
1618             $user = backup_getid($restore->backup_unique_code,"user",$log->info);
1619             if ($user) {
1620                 $log->info = $user->new_id;
1621                 $log->url = "view.php?id=".$log->course;
1622                 $toinsert = true;
1623             }
1624             break;
1625         case "enrol":
1626             //recode the info field (it's the user id)
1627             $user = backup_getid($restore->backup_unique_code,"user",$log->info);
1628             if ($user) {
1629                 $log->info = $user->new_id;
1630                 $log->url = "view.php?id=".$log->course;
1631                 $toinsert = true;
1632             }
1633             break;
1634         case "editsection":
1635             //Extract the course_section from the url field
1636             $secid = substr(strrchr($log->url,"="),1);
1637             //recode the course_section to see if it has been restored
1638             $sec = backup_getid($restore->backup_unique_code,"course_sections",$secid);
1639             if ($sec) {
1640                 $secid = $sec->new_id;
1641                 //Now I have everything so reconstruct url and info
1642                 $log->url = "editsection.php?id=".$secid;
1643                 $toinsert = true;
1644             }
1645             break;
1646         case "new":
1647             $log->url = "view.php?id=".$log->course;
1648             $log->info = "";
1649             $toinsert = true;
1650             break;
1651         default:
1652             echo "action (".$log->module."-".$log->action.") unknow. Not restored<br>";                 //Debug
1653             break;
1654         }
1656         //echo "After transformations<br>";                                             //Debug
1657         //print_object($log);                                                           //Debug
1659         //Now if $toinsert is set, insert the record
1660         if ($toinsert) {
1661             //echo "Inserting record<br>";                                              //Debug
1662             $status = insert_record("log",$log);
1663         }
1664         return $status;
1665     }
1667     //This function inserts a user log record, calculating the URL field as necessary
1668     function restore_log_user($restore,$log) {
1670         $status = true;
1671         $toinsert = false;
1672         
1673         //echo "<hr>Before transformations<br>";                                        //Debug
1674         //print_object($log);                                                           //Debug
1675         //Depending of the action, we recode different things                           
1676         switch ($log->action) {
1677         case "view":
1678             //recode the info field (it's the user id)
1679             $user = backup_getid($restore->backup_unique_code,"user",$log->info);
1680             if ($user) {
1681                 $log->info = $user->new_id;
1682                 $log->url = "view.php?id=".$log->info."&course=".$log->course;
1683                 $toinsert = true;
1684             }
1685             break;
1686         case "change password":
1687             //recode the info field (it's the user id)
1688             $user = backup_getid($restore->backup_unique_code,"user",$log->info);
1689             if ($user) {
1690                 $log->info = $user->new_id;
1691                 $log->url = "view.php?id=".$log->info."&course=".$log->course;
1692                 $toinsert = true;
1693             }
1694             break;
1695         case "view all":
1696             $log->url = "view.php?id=".$log->course;
1697             $log->info = "";
1698             $toinsert = true;
1699         case "update":
1700             //We split the url by ampersand char 
1701             $first_part = strtok($log->url,"&");
1702             //Get data after the = char. It's the user being updated
1703             $userid = substr(strrchr($first_part,"="),1);
1704             //Recode the user
1705             $user = backup_getid($restore->backup_unique_code,"user",$userid);
1706             if ($user) {
1707                 $log->info = "";
1708                 $log->url = "view.php?id=".$user->new_id."&course=".$log->course;
1709                 $toinsert = true;
1710             }
1711             break;
1712         default:
1713             echo "action (".$log->module."-".$log->action.") unknow. Not restored<br>";                 //Debug
1714             break;
1715         }
1717         //echo "After transformations<br>";                                             //Debug
1718         //print_object($log);                                                           //Debug
1720         //Now if $toinsert is set, insert the record
1721         if ($toinsert) {
1722             //echo "Inserting record<br>";                                              //Debug
1723             $status = insert_record("log",$log);
1724         }
1725         return $status;
1726     }
1728     //This function inserts a module log record, calculating the URL field as necessary
1729     function restore_log_module($restore,$log) {
1731         $status = true;
1732         $toinsert = false;
1734         //echo "<hr>Before transformations<br>";                                        //Debug
1735         //print_object($log);                                                           //Debug
1737         //Now we see if the required function in the module exists
1738         $function = $log->module."_restore_logs";
1739         if (function_exists($function)) {
1740             //Call the function
1741             $log = $function($restore,$log);
1742             //If everything is ok, mark the insert flag
1743             if ($log) {
1744                 $toinsert = true;
1745             }
1746         }
1748         //echo "After transformations<br>";                                             //Debug
1749         //print_object($log);                                                           //Debug
1751         //Now if $toinsert is set, insert the record
1752         if ($toinsert) {
1753             //echo "Inserting record<br>";                                              //Debug
1754             $status = insert_record("log",$log);
1755         }
1756         return $status;
1757     }
1759     //This function adjusts the instance field into course_modules. It's executed after
1760     //modules restore. There, we KNOW the new instance id !!
1761     function restore_check_instances($restore) {
1763         global $CFG;
1765         $status = true;
1767         //We are going to iterate over each course_module saved in backup_ids
1768         $course_modules = get_records_sql("SELECT old_id,new_id
1769                                            FROM {$CFG->prefix}backup_ids
1770                                            WHERE backup_code = '$restore->backup_unique_code' AND
1771                                                  table_name = 'course_modules'");
1772         if ($course_modules) {
1773             foreach($course_modules as $cm) {
1774                 //Get full record, using backup_getids
1775                 $cm_module = backup_getid($restore->backup_unique_code,"course_modules",$cm->old_id);
1776                 //Now we are going to the REAL course_modules to get its type (field module)
1777                 $module = get_record("course_modules","id",$cm_module->new_id);
1778                 if ($module) {
1779                     //We know the module type id. Get the name from modules
1780                     $type = get_record("modules","id",$module->module);
1781                     if ($type) {
1782                         //We know the type name and the old_id. Get its new_id
1783                         //from backup_ids. It's the instance !!!
1784                         $instance =  backup_getid($restore->backup_unique_code,$type->name,$cm_module->info);
1785                         if ($instance) {
1786                             //We have the new instance, so update the record in course_modules
1787                             $module->instance = $instance->new_id;
1788                             //print_object ($module);                                                   //Debug
1789                             $status = update_record("course_modules",$module);
1790                         } else {
1791                             $status = false;
1792                         }
1793                     } else {
1794                         $status = false;
1795                     }
1796                 } else {
1797                     $status = false;
1798                }
1799             }
1800         }
1803         return $status;
1804     }
1806     //=====================================================================================
1807     //==                                                                                 ==
1808     //==                         XML Functions (SAX)                                     ==
1809     //==                                                                                 ==
1810     //=====================================================================================
1812     //This is the class used to do all the xml parse
1813     class MoodleParser {
1815         var $level = 0;        //Level we are
1816         var $counter = 0;      //Counter
1817         var $tree = array();   //Array of levels we are
1818         var $content = "";     //Content under current level
1819         var $todo = "";        //What we hav to do when parsing
1820         var $info = "";        //Information collected. Temp storage. Used to return data after parsing.
1821         var $temp = "";        //Temp storage.
1822         var $preferences = ""; //Preferences about what to load !!
1823         var $finished = false; //Flag to say xml_parse to stop
1825         //This function is used to get the current contents property value
1826         //They are trimed and converted from utf8
1827         function getContents() {
1828             return trim(utf8_decode($this->content));
1829         }
1830  
1831         //This is the startTag handler we use where we are reading the info zone (todo="INFO")
1832         function startElementInfo($parser, $tagName, $attrs) {
1833             //Refresh properties
1834             $this->level++;
1835             $this->tree[$this->level] = $tagName;
1837             //Output something to avoid browser timeouts...
1838             backup_flush();
1840             //Check if we are into INFO zone
1841             //if ($this->tree[2] == "INFO")                                                             //Debug
1842             //    echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br>\n";   //Debug
1843         }
1845         //This is the startTag handler we use where we are reading the course header zone (todo="COURSE_HEADER")
1846         function startElementCourseHeader($parser, $tagName, $attrs) {
1847             //Refresh properties
1848             $this->level++;
1849             $this->tree[$this->level] = $tagName;
1851             //Output something to avoid browser timeouts...
1852             backup_flush();
1854             //Check if we are into COURSE_HEADER zone
1855             //if ($this->tree[3] == "HEADER")                                                           //Debug
1856             //    echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br>\n";   //Debug
1857         }
1859         //This is the startTag handler we use where we are reading the sections zone (todo="SECTIONS")
1860         function startElementSections($parser, $tagName, $attrs) {
1861             //Refresh properties     
1862             $this->level++;
1863             $this->tree[$this->level] = $tagName;   
1865             //Output something to avoid browser timeouts...
1866             backup_flush();
1868             //Check if we are into SECTIONS zone
1869             //if ($this->tree[3] == "SECTIONS")                                                         //Debug
1870             //    echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br>\n";   //Debug
1871         }
1872         
1873         //This is the startTag handler we use where we are reading the user zone (todo="USERS")
1874         function startElementUsers($parser, $tagName, $attrs) {
1875             //Refresh properties     
1876             $this->level++;
1877             $this->tree[$this->level] = $tagName;   
1879             //Check if we are into USERS zone  
1880             //if ($this->tree[3] == "USERS")                                                            //Debug
1881             //    echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br>\n";   //Debug
1882         }
1884         //This is the startTag handler we use where we are reading the questions zone (todo="QUESTIONS")
1885         function startElementQuestions($parser, $tagName, $attrs) {
1886             //Refresh properties
1887             $this->level++;
1888             $this->tree[$this->level] = $tagName;
1890             //if ($tagName == "QUESTION_CATEGORY" && $this->tree[3] == "QUESTION_CATEGORIES") {        //Debug
1891             //    echo "<P>QUESTION_CATEGORY: ".strftime ("%X",time()),"-";                            //Debug
1892             //}                                                                                        //Debug
1894             //Output something to avoid browser timeouts...
1895             backup_flush();
1897             //Check if we are into QUESTION_CATEGORIES zone
1898             //if ($this->tree[3] == "QUESTION_CATEGORIES")                                              //Debug
1899             //    echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br>\n";   //Debug
1901             //If we are under a QUESTION_CATEGORY tag under a QUESTION_CATEGORIES zone, accumule it
1902             if (isset($this->tree[4]) and isset($this->tree[3])) {
1903                 if (($this->tree[4] == "QUESTION_CATEGORY") and ($this->tree[3] == "QUESTION_CATEGORIES")) {
1904                     if (!isset($this->temp)) {
1905                         $this->temp = "";
1906                     }
1907                     $this->temp .= "<".$tagName.">";
1908                 }
1909             }
1910         }
1912         //This is the startTag handler we use where we are reading the scales zone (todo="SCALES")
1913         function startElementScales($parser, $tagName, $attrs) {
1914             //Refresh properties          
1915             $this->level++;
1916             $this->tree[$this->level] = $tagName;
1918             //if ($tagName == "SCALE" && $this->tree[3] == "SCALES") {                                 //Debug
1919             //    echo "<P>SCALE: ".strftime ("%X",time()),"-";                                        //Debug
1920             //}                                                                                        //Debug
1922             //Output something to avoid browser timeouts...
1923             backup_flush();
1925             //Check if we are into SCALES zone
1926             //if ($this->tree[3] == "SCALES")                                                           //Debug
1927             //    echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br>\n";   //Debug
1929             //If we are under a SCALE tag under a SCALES zone, accumule it
1930             if (isset($this->tree[4]) and isset($this->tree[3])) {
1931                 if (($this->tree[4] == "SCALE") and ($this->tree[3] == "SCALES")) {
1932                     if (!isset($this->temp)) {
1933                         $this->temp = "";
1934                     }
1935                     $this->temp .= "<".$tagName.">";
1936                 }
1937             }
1938         }
1940         function startElementGroups($parser, $tagName, $attrs) {
1941             //Refresh properties
1942             $this->level++;
1943             $this->tree[$this->level] = $tagName;
1945             //if ($tagName == "GROUP" && $this->tree[3] == "GROUPS") {                                 //Debug
1946             //    echo "<P>GROUP: ".strftime ("%X",time()),"-";                                        //Debug
1947             //}                                                                                        //Debug
1949             //Output something to avoid browser timeouts...
1950             backup_flush();
1952             //Check if we are into GROUPS zone
1953             //if ($this->tree[3] == "GROUPS")                                                           //Debug
1954             //    echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br>\n";   //Debug
1956             //If we are under a GROUP tag under a GROUPS zone, accumule it
1957             if (isset($this->tree[4]) and isset($this->tree[3])) {
1958                 if (($this->tree[4] == "GROUP") and ($this->tree[3] == "GROUPS")) {
1959                     if (!isset($this->temp)) {
1960                         $this->temp = "";
1961                     }
1962                     $this->temp .= "<".$tagName.">";
1963                 }
1964             }
1965         }
1967         //This is the startTag handler we use where we are reading the events zone (todo="EVENTS")
1968         function startElementEvents($parser, $tagName, $attrs) {
1969             //Refresh properties
1970             $this->level++;
1971             $this->tree[$this->level] = $tagName;
1973             //if ($tagName == "EVENT" && $this->tree[3] == "EVENTS") {                                 //Debug
1974             //    echo "<P>EVENT: ".strftime ("%X",time()),"-";                                        //Debug
1975             //}                                                                                        //Debug
1977             //Output something to avoid browser timeouts...
1978             backup_flush();
1980             //Check if we are into EVENTS zone
1981             //if ($this->tree[3] == "EVENTS")                                                           //Debug
1982             //    echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br>\n";   //Debug
1984             //If we are under a EVENT tag under a EVENTS zone, accumule it
1985             if (isset($this->tree[4]) and isset($this->tree[3])) {
1986                 if (($this->tree[4] == "EVENT") and ($this->tree[3] == "EVENTS")) {
1987                     if (!isset($this->temp)) {
1988                         $this->temp = "";
1989                     }
1990                     $this->temp .= "<".$tagName.">";
1991                 }
1992             }
1993         }
1995         //This is the startTag handler we use where we are reading the modules zone (todo="MODULES")
1996         function startElementModules($parser, $tagName, $attrs) {
1997             //Refresh properties
1998             $this->level++;
1999             $this->tree[$this->level] = $tagName;
2001             //if ($tagName == "MOD" && $this->tree[3] == "MODULES") {                                     //Debug
2002             //    echo "<P>MOD: ".strftime ("%X",time()),"-";                                             //Debug
2003             //}                                                                                           //Debug
2005             //Output something to avoid browser timeouts...
2006             backup_flush();
2008             //Check if we are into MODULES zone
2009             //if ($this->tree[3] == "MODULES")                                                          //Debug
2010             //    echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br>\n";   //Debug
2012             //If we are under a MOD tag under a MODULES zone, accumule it
2013             if (isset($this->tree[4]) and isset($this->tree[3])) {
2014                 if (($this->tree[4] == "MOD") and ($this->tree[3] == "MODULES")) {
2015                     if (!isset($this->temp)) {
2016                         $this->temp = "";
2017                     }
2018                     $this->temp .= "<".$tagName.">";
2019                 }
2020             }
2021         }
2023         //This is the startTag handler we use where we are reading the logs zone (todo="LOGS")
2024         function startElementLogs($parser, $tagName, $attrs) {
2025             //Refresh properties
2026             $this->level++;
2027             $this->tree[$this->level] = $tagName;
2029             //if ($tagName == "LOG" && $this->tree[3] == "LOGS") {                                        //Debug
2030             //    echo "<P>LOG: ".strftime ("%X",time()),"-";                                             //Debug
2031             //}                                                                                           //Debug
2033             //Output something to avoid browser timeouts...
2034             backup_flush();
2036             //Check if we are into LOGS zone
2037             //if ($this->tree[3] == "LOGS")                                                             //Debug
2038             //    echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br>\n";   //Debug
2040             //If we are under a LOG tag under a LOGS zone, accumule it
2041             if (isset($this->tree[4]) and isset($this->tree[3])) {
2042                 if (($this->tree[4] == "LOG") and ($this->tree[3] == "LOGS")) {
2043                     if (!isset($this->temp)) {
2044                         $this->temp = "";
2045                     }
2046                     $this->temp .= "<".$tagName.">";
2047                 }
2048             }
2049         }
2051         //This is the startTag default handler we use when todo is undefined
2052         function startElement($parser, $tagName, $attrs) {
2053             $this->level++;
2054             $this->tree[$this->level] = $tagName;
2056             //Output something to avoid browser timeouts...
2057             backup_flush();
2059             echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br>\n";   //Debug
2060         }
2061  
2062         //This is the endTag handler we use where we are reading the info zone (todo="INFO")
2063         function endElementInfo($parser, $tagName) {
2064             //Check if we are into INFO zone
2065             if ($this->tree[2] == "INFO") {
2066                 //if (trim($this->content))                                                                     //Debug
2067                 //    echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br>\n";           //Debug
2068                 //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br>\n";          //Debug
2069                 //Dependig of different combinations, do different things
2070                 if ($this->level == 3) {
2071                     switch ($tagName) {
2072                         case "NAME":
2073                             $this->info->backup_name = $this->getContents();
2074                             break;
2075                         case "MOODLE_VERSION":
2076                             $this->info->backup_moodle_version = $this->getContents();
2077                             break;
2078                         case "MOODLE_RELEASE":
2079                             $this->info->backup_moodle_release = $this->getContents();
2080                             break;
2081                         case "BACKUP_VERSION":
2082                             $this->info->backup_backup_version = $this->getContents();
2083                             break;
2084                         case "BACKUP_RELEASE":
2085                             $this->info->backup_backup_release = $this->getContents();
2086                             break;
2087                         case "DATE":
2088                             $this->info->backup_date = $this->getContents();
2089                             break;
2090                         case "ORIGINAL_WWWROOT":
2091                             $this->info->original_wwwroot = $this->getContents();
2092                             break;
2093                     }
2094                 }
2095                 if ($this->tree[3] == "DETAILS") {
2096                     if ($this->level == 4) {
2097                         switch ($tagName) {
2098                             case "USERS":
2099                                 $this->info->backup_users = $this->getContents();
2100                                 break;
2101                             case "LOGS":
2102                                 $this->info->backup_logs = $this->getContents();
2103                                 break;
2104                             case "USERFILES":
2105                                 $this->info->backup_user_files = $this->getContents();
2106                                 break;
2107                             case "COURSEFILES":
2108                                 $this->info->backup_course_files = $this->getContents();
2109                                 break;
2110                         }
2111                     }
2112                     if ($this->level == 5) {
2113                         switch ($tagName) {
2114                             case "NAME":
2115                                 $this->info->tempName = $this->getContents();
2116                                 break;
2117                             case "INCLUDED":
2118                                 $this->info->mods[$this->info->tempName]->backup = $this->getContents();
2119                                 break;
2120                             case "USERINFO":
2121                                 $this->info->mods[$this->info->tempName]->userinfo = $this->getContents();
2122                                 break;
2123                         }
2124                     }
2125                 }
2126             }
2129             //Clear things
2130             $this->tree[$this->level] = "";
2131             $this->level--;
2132             $this->content = "";
2134             //Stop parsing if todo = INFO and tagName = INFO (en of the tag, of course)
2135             //Speed up a lot (avoid parse all)
2136             if ($tagName == "INFO") {
2137                 $this->finished = true;
2138             }
2139         }
2141         //This is the endTag handler we use where we are reading the course_header zone (todo="COURSE_HEADER")
2142         function endElementCourseHeader($parser, $tagName) {
2143             //Check if we are into COURSE_HEADER zone
2144             if ($this->tree[3] == "HEADER") {
2145                 //if (trim($this->content))                                                                     //Debug
2146                 //    echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br>\n";           //Debug
2147                 //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br>\n";          //Debug
2148                 //Dependig of different combinations, do different things
2149                 if ($this->level == 4) {
2150                     switch ($tagName) {
2151                         case "ID":
2152                             $this->info->course_id = $this->getContents();
2153                             break;
2154                         case "PASSWORD":
2155                             $this->info->course_password = $this->getContents();
2156                             break;
2157                         case "FULLNAME":
2158                             $this->info->course_fullname = $this->getContents();
2159                             break;
2160                         case "SHORTNAME":
2161                             $this->info->course_shortname = $this->getContents();
2162                             break;
2163                         case "SUMMARY":
2164                             $this->info->course_summary = $this->getContents();
2165                             break;
2166                         case "FORMAT":
2167                             $this->info->course_format = $this->getContents();
2168                             break;
2169                         case "SHOWGRADES":
2170                             $this->info->course_showgrades = $this->getContents();
2171                             break;
2172                         case "BLOCKINFO":
2173                             $this->info->blockinfo = $this->getContents();
2174                             break;
2175                         case "NEWSITEMS":
2176                             $this->info->course_newsitems = $this->getContents();
2177                             break;
2178                         case "TEACHER":
2179                             $this->info->course_teacher = $this->getContents();
2180                             break;
2181                         case "TEACHERS":
2182                             $this->info->course_teachers = $this->getContents();
2183                             break;
2184                         case "STUDENT":
2185                             $this->info->course_student = $this->getContents();
2186                             break;
2187                         case "STUDENTS":
2188                             $this->info->course_students = $this->getContents();
2189                             break;
2190                         case "GUEST":
2191                             $this->info->course_guest = $this->getContents();
2192                             break;
2193                         case "STARTDATE":
2194                             $this->info->course_startdate = $this->getContents();
2195                             break;
2196                         case "NUMSECTIONS":
2197                             $this->info->course_numsections = $this->getContents();
2198                             break;
2199                         //case "SHOWRECENT":                                          INFO: This is out in 1.3
2200                         //    $this->info->course_showrecent = $this->getContents();
2201                         //    break;
2202                         case "MAXBYTES":
2203                             $this->info->course_maxbytes = $this->getContents();
2204                             break;
2205                         case "SHOWREPORTS":
2206                             $this->info->course_showreports = $this->getContents();
2207                             break;
2208                         case "GROUPMODE":
2209                             $this->info->course_groupmode = $this->getContents();
2210                             break;
2211                         case "GROUPMODEFORCE":
2212                             $this->info->course_groupmodeforce = $this->getContents();
2213                             break;
2214                         case "LANG":
2215                             $this->info->course_lang = $this->getContents();
2216                             break;
2217                         case "MARKER":
2218                             $this->info->course_marker = $this->getContents();
2219                             break;
2220                         case "VISIBLE":
2221                             $this->info->course_visible = $this->getContents();
2222                             break;
2223                         case "HIDDENSECTIONS":
2224                             $this->info->course_hiddensections = $this->getContents();
2225                             break;
2226                         case "TIMECREATED":
2227                             $this->info->course_timecreated = $this->getContents();
2228                             break;
2229                         case "TIMEMODIFIED":
2230                             $this->info->course_timemodified = $this->getContents();
2231                             break;
2232                     }
2233                 }
2234                 if ($this->tree[4] == "CATEGORY") {
2235                     if ($this->level == 5) {
2236                         switch ($tagName) {
2237                             case "ID":
2238                                 $this->info->category->id = $this->getContents();
2239                                 break;
2240                             case "NAME":
2241                                 $this->info->category->name = $this->getContents();
2242                                 break;
2243                         }
2244                     }
2245                 }
2247             }
2248             //Clear things
2249             $this->tree[$this->level] = "";
2250             $this->level--;
2251             $this->content = "";
2253             //Stop parsing if todo = COURSE_HEADER and tagName = HEADER (en of the tag, of course)
2254             //Speed up a lot (avoid parse all)
2255             if ($tagName == "HEADER") {
2256                 $this->finished = true;
2257             }
2258         }
2260         //This is the endTag handler we use where we are reading the sections zone (todo="SECTIONS")
2261         function endElementSections($parser, $tagName) {
2262             //Check if we are into SECTIONS zone
2263             if ($this->tree[3] == "SECTIONS") {
2264                 //if (trim($this->content))                                                                     //Debug
2265                 //    echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br>\n";           //Debug
2266                 //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br>\n";          //Debug
2267                 //Dependig of different combinations, do different things
2268                 if ($this->level == 4) {
2269                     switch ($tagName) {
2270                         case "SECTION":
2271                             //We've finalized a section, get it
2272                             $this->info->sections[$this->info->tempsection->id] = $this->info->tempsection;
2273                             unset($this->info->tempsection);
2274                     }
2275                 }
2276                 if ($this->level == 5) {
2277                     switch ($tagName) {
2278                         case "ID":
2279                             $this->info->tempsection->id = $this->getContents();
2280                             break;
2281                         case "NUMBER":
2282                             $this->info->tempsection->number = $this->getContents();
2283                             break;
2284                         case "SUMMARY":
2285                             $this->info->tempsection->summary = $this->getContents();
2286                             break;
2287                         case "VISIBLE":
2288                             $this->info->tempsection->visible = $this->getContents();
2289                             break;
2290                     }
2291                 }
2292                 if ($this->level == 6) {
2293                     switch ($tagName) {
2294                         case "MOD":
2295                             //We've finalized a mod, get it
2296                             $this->info->tempsection->mods[$this->info->tempmod->id]->type = 
2297                                 $this->info->tempmod->type;
2298                             $this->info->tempsection->mods[$this->info->tempmod->id]->instance = 
2299                                 $this->info->tempmod->instance;
2300                             $this->info->tempsection->mods[$this->info->tempmod->id]->added = 
2301                                 $this->info->tempmod->added;
2302                             $this->info->tempsection->mods[$this->info->tempmod->id]->deleted = 
2303                                 $this->info->tempmod->deleted;
2304                             $this->info->tempsection->mods[$this->info->tempmod->id]->score = 
2305                                 $this->info->tempmod->score;
2306                             $this->info->tempsection->mods[$this->info->tempmod->id]->indent = 
2307                                 $this->info->tempmod->indent;
2308                             $this->info->tempsection->mods[$this->info->tempmod->id]->visible = 
2309                                 $this->info->tempmod->visible;
2310                             $this->info->tempsection->mods[$this->info->tempmod->id]->groupmode = 
2311                                 $this->info->tempmod->groupmode;
2312                             unset($this->info->tempmod);
2313                     }
2314                 }
2315                 if ($this->level == 7) {
2316                     switch ($tagName) {
2317                         case "ID":
2318                             $this->info->tempmod->id = $this->getContents();
2319                             break;
2320                         case "TYPE":
2321                             $this->info->tempmod->type = $this->getContents();
2322                             break;
2323                         case "INSTANCE":
2324                             $this->info->tempmod->instance = $this->getContents();
2325                             break;
2326                         case "ADDED":
2327                             $this->info->tempmod->added = $this->getContents();
2328                             break;
2329                         case "DELETED":
2330                             $this->info->tempmod->deleted = $this->getContents();
2331                             break;
2332                         case "SCORE":
2333                             $this->info->tempmod->score = $this->getContents();
2334                             break;
2335                         case "INDENT":
2336                             $this->info->tempmod->indent = $this->getContents();
2337                             break;
2338                         case "VISIBLE":
2339                             $this->info->tempmod->visible = $this->getContents();
2340                             break;
2341                         case "GROUPMODE":
2342                             $this->info->tempmod->groupmode = $this->getContents();
2343                             break;
2344                     }
2345                 }
2346             }
2347             //Clear things
2348             $this->tree[$this->level] = "";
2349             $this->level--;
2350             $this->content = "";
2352             //Stop parsing if todo = SECTIONS and tagName = SECTIONS (en of the tag, of course)
2353             //Speed up a lot (avoid parse all)
2354             if ($tagName == "SECTIONS") {
2355                 $this->finished = true;
2356             }
2357         }
2358         
2359         //This is the endTag handler we use where we are reading the users zone (todo="USERS")
2360         function endElementUsers($parser, $tagName) {
2361             //Check if we are into USERS zone
2362             if ($this->tree[3] == "USERS") {
2363                 //if (trim($this->content))                                                                     //Debug
2364                 //    echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br>\n";           //Debug
2365                 //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br>\n";          //Debug
2366                 //Dependig of different combinations, do different things
2367                 if ($this->level == 4) {
2368                     switch ($tagName) {
2369                         case "USER":
2370                             //Increment counter
2371                             $this->counter++;
2372                             //Save to db
2373                             backup_putid($this->preferences->backup_unique_code,"user",$this->info->tempuser->id,
2374                                           null,$this->info->tempuser);
2376                             //Do some output   
2377                             if ($this->counter % 10 == 0) {
2378                                 echo ".";
2379                                 if ($this->counter % 200 == 0) {
2380                                 echo "<br>";
2381                                 }
2382                                 backup_flush(300);
2383                             }
2385                             //Delete temp obejct
2386                             unset($this->info->tempuser);
2387                             break;
2388                     }
2389                 }
2390                 if ($this->level == 5) {
2391                     switch ($tagName) {
2392                         case "ID": 
2393                             $this->info->users[$this->getContents()] = $this->getContents();
2394                             $this->info->tempuser->id = $this->getContents();
2395                             break;
2396                         case "CONFIRMED": 
2397                             $this->info->tempuser->confirmed = $this->getContents();
2398                             break;
2399                         case "DELETED": 
2400                             $this->info->tempuser->deleted = $this->getContents();
2401                             break;
2402                         case "USERNAME": 
2403                             $this->info->tempuser->username = $this->getContents();
2404                             break;
2405                         case "PASSWORD": 
2406                             $this->info->tempuser->password = $this->getContents();
2407                             break;
2408                         case "IDNUMBER": 
2409                             $this->info->tempuser->idnumber = $this->getContents();
2410                             break;
2411                         case "FIRSTNAME": 
2412                             $this->info->tempuser->firstname = $this->getContents();
2413                             break;
2414                         case "LASTNAME": 
2415                             $this->info->tempuser->lastname = $this->getContents();
2416                             break;
2417                         case "EMAIL": 
2418                             $this->info->tempuser->email = $this->getContents();
2419                             break;
2420                         case "EMAILSTOP": 
2421                             $this->info->tempuser->emailstop = $this->getContents();
2422                             break;
2423                         case "ICQ": 
2424                             $this->info->tempuser->icq = $this->getContents();
2425                             break;
2426                         case "PHONE1": 
2427                             $this->info->tempuser->phone1 = $this->getContents();
2428                             break;
2429                         case "PHONE2": 
2430                             $this->info->tempuser->phone2 = $this->getContents();
2431                             break;
2432                         case "INSTITUTION": 
2433                             $this->info->tempuser->institution = $this->getContents();
2434                             break;
2435                         case "DEPARTMENT": 
2436                             $this->info->tempuser->department = $this->getContents();
2437                             break;
2438                         case "ADDRESS": 
2439                             $this->info->tempuser->address = $this->getContents();
2440                             break;
2441                         case "CITY": 
2442                             $this->info->tempuser->city = $this->getContents();
2443                             break;
2444                         case "COUNTRY": 
2445                             $this->info->tempuser->country = $this->getContents();
2446                             break;
2447                         case "LANG": 
2448                             $this->info->tempuser->lang = $this->getContents();
2449                             break;
2450                         case "TIMEZONE": 
2451                             $this->info->tempuser->timezone = $this->getContents();
2452                             break;
2453                         case "FIRSTACCESS": 
2454                             $this->info->tempuser->firstaccess = $this->getContents();
2455                             break;
2456                         case "LASTACCESS": 
2457                             $this->info->tempuser->lastaccess = $this->getContents();
2458                             break;
2459                         case "LASTLOGIN": 
2460                             $this->info->tempuser->lastlogin = $this->getContents();
2461                             break;
2462                         case "CURRENTLOGIN": 
2463                             $this->info->tempuser->currentlogin = $this->getContents();
2464                             break;
2465                         case "LASTIP": 
2466                             $this->info->tempuser->lastip = $this->getContents();
2467                             break;
2468                         case "SECRET": 
2469                             $this->info->tempuser->secret = $this->getContents();
2470                             break;
2471                         case "PICTURE": 
2472                             $this->info->tempuser->picture = $this->getContents();
2473                             break;
2474                         case "URL": 
2475                             $this->info->tempuser->url = $this->getContents();
2476                             break;
2477                         case "DESCRIPTION": 
2478                             $this->info->tempuser->description = $this->getContents();
2479                             break;
2480                         case "MAILFORMAT": 
2481                             $this->info->tempuser->mailformat = $this->getContents();
2482                             break;
2483                         case "MAILDISPLAY": 
2484                             $this->info->tempuser->maildisplay = $this->getContents();
2485                             break;
2486                         case "HTMLEDITOR": 
2487                             $this->info->tempuser->htmleditor = $this->getContents();
2488                             break;
2489                         case "AUTOSUBSCRIBE": 
2490                             $this->info->tempuser->autosubscribe = $this->getContents();
2491                             break;
2492                         case "TIMEMODIFIED": 
2493                             $this->info->tempuser->timemodified = $this->getContents();
2494                             break;
2495                     }
2496                 }
2497                 if ($this->level == 6) {
2498                     switch ($tagName) {
2499                         case "ROLE":
2500                             //We've finalized a role, get it
2501                             $this->info->tempuser->roles[$this->info->temprole->type] = $this->info->temprole;
2502                             unset($this->info->temprole);
2503                             break;
2504                         case "USER_PREFERENCE":
2505                             //We've finalized a user_preference, get it
2506                             $this->info->tempuser->user_preferences[$this->info->tempuserpreference->name] = $this->info->tempuserpreference;
2507                             unset($this->info->tempuserpreference);
2508                             break;
2509                     }
2510                 }
2511                 if ($this->level == 7) {
2512                     switch ($tagName) {
2513                         case "TYPE":
2514                             $this->info->temprole->type = $this->getContents();
2515                             break;
2516                         case "AUTHORITY":
2517                             $this->info->temprole->authority = $this->getContents();
2518                             break;
2519                         case "TEA_ROLE":
2520                             $this->info->temprole->tea_role = $this->getContents();
2521                             break;
2522                         case "EDITALL":
2523                             $this->info->temprole->editall = $this->getContents();
2524                             break;
2525                         case "TIMEMODIFIED":
2526                             $this->info->temprole->timemodified = $this->getContents();
2527                             break;
2528                         case "TIMESTART":
2529                             $this->info->temprole->timestart = $this->getContents();
2530                             break;
2531                         case "TIMEEND":
2532                             $this->info->temprole->timeend = $this->getContents();
2533                             break;
2534                         case "TIME":
2535                             $this->info->temprole->time = $this->getContents();
2536                             break;
2537                         case "TIMEACCESS":
2538                             $this->info->temprole->timeaccess = $this->getContents();
2539                             break;
2540                         case "NAME":
2541                             $this->info->tempuserpreference->name = $this->getContents();
2542                             break;
2543                         case "VALUE":
2544                             $this->info->tempuserpreference->value = $this->getContents();
2545                             break;
2546                     }
2547                 }
2548             }
2550             //Stop parsing if todo = USERS and tagName = USERS (en of the tag, of course)
2551             //Speed up a lot (avoid parse all)
2552             if ($tagName == "USERS" and $this->level == 3) {
2553                 $this->finished = true;
2554                 $this->counter = 0;
2555             }
2557             //Clear things
2558             $this->tree[$this->level] = "";
2559             $this->level--;
2560             $this->content = "";
2561         }
2563         //This is the endTag handler we use where we are reading the questions zone (todo="QUESTIONS")  
2564         function endElementQuestions($parser, $tagName) {
2565             //Check if we are into QUESTION_CATEGORIES zone
2566             if ($this->tree[3] == "QUESTION_CATEGORIES") {
2567                 //if (trim($this->content))                                                                     //Debug
2568                 //    echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br>\n";           //Debug
2569                 //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br>\n";          //Debug
2570                 //Acumulate data to info (content + close tag)
2571                 //Reconvert: strip htmlchars again and trim to generate xml data
2572                 if (!isset($this->temp)) {
2573                     $this->temp = "";
2574                 }
2575                 $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
2576                 //If we've finished a mod, xmlize it an save to db
2577                 if (($this->level == 4) and ($tagName == "QUESTION_CATEGORY")) {
2578                     //Prepend XML standard header to info gathered
2579                     $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
2580                     //Call to xmlize for this portion of xml data (one QUESTION_CATEGORY)
2581                     //echo "-XMLIZE: ".strftime ("%X",time()),"-";                                                //Debug
2582                     $data = xmlize($xml_data,0);
2583                     //echo strftime ("%X",time())."<p>";                                                          //Debug
2584                     //traverse_xmlize($data);                                                                     //Debug
2585                     //print_object ($GLOBALS['traverse_array']);                                                  //Debug
2586                     //$GLOBALS['traverse_array']="";                                                              //Debug
2587                     //Now, save data to db. We'll use it later
2588                     //Get id from data
2589                     $category_id = $data["QUESTION_CATEGORY"]["#"]["ID"]["0"]["#"];
2590                     //Save to db
2591                     $status = backup_putid($this->preferences->backup_unique_code,"quiz_categories",$category_id,
2592                                      null,$data);
2593                     //Create returning info
2594                     $ret_info->id = $category_id;
2595                     $this->info[] = $ret_info;
2596                     //Reset temp
2597                     unset($this->temp);
2598                 }
2599             }
2601             //Stop parsing if todo = QUESTION_CATEGORIES and tagName = QUESTION_CATEGORY (en of the tag, of course)
2602             //Speed up a lot (avoid parse all)
2603             if ($tagName == "QUESTION_CATEGORIES" and $this->level == 3) {
2604                 $this->finished = true;
2605             }
2607             //Clear things
2608             $this->tree[$this->level] = "";
2609             $this->level--;
2610             $this->content = "";
2611         }
2613         //This is the endTag handler we use where we are reading the scales zone (todo="SCALES")
2614         function endElementScales($parser, $tagName) {
2615             //Check if we are into SCALES zone
2616             if ($this->tree[3] == "SCALES") {
2617                 //if (trim($this->content))                                                                     //Debug
2618                 //    echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br>\n";           //Debug
2619                 //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br>\n";          //Debug
2620                 //Acumulate data to info (content + close tag)
2621                 //Reconvert: strip htmlchars again and trim to generate xml data
2622                 if (!isset($this->temp)) {
2623                     $this->temp = "";
2624                 }
2625                 $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
2626                 //If we've finished a scale, xmlize it an save to db
2627                 if (($this->level == 4) and ($tagName == "SCALE")) {
2628                     //Prepend XML standard header to info gathered
2629                     $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
2630                     //Call to xmlize for this portion of xml data (one SCALE)
2631                     //echo "-XMLIZE: ".strftime ("%X",time()),"-";                                                //Debug
2632                     $data = xmlize($xml_data,0);
2633                     //echo strftime ("%X",time())."<p>";                                                          //Debug
2634                     //traverse_xmlize($data);                                                                     //Debug
2635                     //print_object ($GLOBALS['traverse_array']);                                                  //Debug
2636                     //$GLOBALS['traverse_array']="";                                                              //Debug
2637                     //Now, save data to db. We'll use it later
2638                     //Get id and from data
2639                     $scale_id = $data["SCALE"]["#"]["ID"]["0"]["#"];
2640                     //Save to db
2641                     $status = backup_putid($this->preferences->backup_unique_code,"scale",$scale_id,
2642                                      null,$data);
2643                     //Create returning info
2644                     $ret_info->id = $scale_id;
2645                     $this->info[] = $ret_info;
2646                     //Reset temp
2647                     unset($this->temp);
2648                 }
2649             }
2651             //Stop parsing if todo = SCALES and tagName = SCALE (en of the tag, of course)
2652             //Speed up a lot (avoid parse all)
2653             if ($tagName == "SCALES" and $this->level == 3) {
2654                 $this->finished = true;
2655             }
2657             //Clear things
2658             $this->tree[$this->level] = "";
2659             $this->level--;
2660             $this->content = "";
2661         }
2663         //This is the endTag handler we use where we are reading the groups zone (todo="GROUPS")
2664         function endElementGroups($parser, $tagName) {
2665             //Check if we are into GROUPS zone
2666             if ($this->tree[3] == "GROUPS") {
2667                 //if (trim($this->content))                                                                     //Debug
2668                 //    echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br>\n";           //Debug
2669                 //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br>\n";          //Debug
2670                 //Acumulate data to info (content + close tag)
2671                 //Reconvert: strip htmlchars again and trim to generate xml data
2672                 if (!isset($this->temp)) {
2673                     $this->temp = "";
2674                 }
2675                 $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
2676                 //If we've finished a group, xmlize it an save to db
2677                 if (($this->level == 4) and ($tagName == "GROUP")) {
2678                     //Prepend XML standard header to info gathered
2679                     $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
2680                     //Call to xmlize for this portion of xml data (one GROUP)
2681                     //echo "-XMLIZE: ".strftime ("%X",time()),"-";                                                //Debug
2682                     $data = xmlize($xml_data,0);
2683                     //echo strftime ("%X",time())."<p>";                                                          //Debug
2684                     //traverse_xmlize($data);                                                                     //Debug
2685                     //print_object ($GLOBALS['traverse_array']);                                                  //Debug
2686                     //$GLOBALS['traverse_array']="";                                                              //Debug
2687                     //Now, save data to db. We'll use it later
2688                     //Get id and from data
2689                     $group_id = $data["GROUP"]["#"]["ID"]["0"]["#"];
2690                     //Save to db
2691                     $status = backup_putid($this->preferences->backup_unique_code,"group",$group_id,
2692                                      null,$data);
2693                     //Create returning info
2694                     $ret_info->id = $group_id;
2695                     $this->info[] = $ret_info;
2696                     //Reset temp
2697                     unset($this->temp);
2698                 }
2699             }
2701             //Stop parsing if todo = GROUPS and tagName = GROUP (en of the tag, of course)
2702             //Speed up a lot (avoid parse all)
2703             if ($tagName == "GROUPS" and $this->level == 3) {
2704                 $this->finished = true;
2705             }
2707             //Clear things
2708             $this->tree[$this->level] = "";
2709             $this->level--;
2710             $this->content = "";
2711         }
2713         //This is the endTag handler we use where we are reading the events zone (todo="EVENTS")
2714         function endElementEvents($parser, $tagName) {
2715             //Check if we are into EVENTS zone
2716             if ($this->tree[3] == "EVENTS") {
2717                 //if (trim($this->content))                                                                     //Debug
2718                 //    echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br>\n";           //Debug
2719                 //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br>\n";          //Debug
2720                 //Acumulate data to info (content + close tag)
2721                 //Reconvert: strip htmlchars again and trim to generate xml data
2722                 if (!isset($this->temp)) {
2723                     $this->temp = "";
2724                 }
2725                 $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
2726                 //If we've finished a event, xmlize it an save to db
2727                 if (($this->level == 4) and ($tagName == "EVENT")) {
2728                     //Prepend XML standard header to info gathered
2729                     $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
2730                     //Call to xmlize for this portion of xml data (one EVENT)
2731                     //echo "-XMLIZE: ".strftime ("%X",time()),"-";                                                //Debug
2732                     $data = xmlize($xml_data,0);
2733                     //echo strftime ("%X",time())."<p>";                                                          //Debug
2734                     //traverse_xmlize($data);                                                                     //Debug
2735                     //print_object ($GLOBALS['traverse_array']);                                                  //Debug
2736                     //$GLOBALS['traverse_array']="";                                                              //Debug
2737                     //Now, save data to db. We'll use it later
2738                     //Get id and from data
2739                     $event_id = $data["EVENT"]["#"]["ID"]["0"]["#"];
2740                     //Save to db
2741                     $status = backup_putid($this->preferences->backup_unique_code,"event",$event_id,
2742                                      null,$data);
2743                     //Create returning info
2744                     $ret_info->id = $event_id;
2745                     $this->info[] = $ret_info;
2746                     //Reset temp
2747                     unset($this->temp);
2748                 }
2749             }
2751             //Stop parsing if todo = EVENTS and tagName = EVENT (en of the tag, of course)
2752             //Speed up a lot (avoid parse all)
2753             if ($tagName == "EVENTS" and $this->level == 3) {
2754                 $this->finished = true;
2755             }
2757             //Clear things
2758             $this->tree[$this->level] = "";
2759             $this->level--;
2760             $this->content = "";
2761         }
2763         //This is the endTag handler we use where we are reading the modules zone (todo="MODULES")
2764         function endElementModules($parser, $tagName) {
2765             //Check if we are into MODULES zone
2766             if ($this->tree[3] == "MODULES") {
2767                 //if (trim($this->content))                                                                     //Debug
2768                 //    echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br>\n";           //Debug
2769                 //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br>\n";          //Debug
2770                 //Acumulate data to info (content + close tag)
2771                 //Reconvert: strip htmlchars again and trim to generate xml data
2772                 if (!isset($this->temp)) {
2773                     $this->temp = "";
2774                 }
2775                 $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
2776                 //If we've finished a mod, xmlize it an save to db
2777                 if (($this->level == 4) and ($tagName == "MOD")) {
2778                     //Prepend XML standard header to info gathered
2779                     $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
2780                     //Call to xmlize for this portion of xml data (one MOD)
2781                     //echo "-XMLIZE: ".strftime ("%X",time()),"-";                                                  //Debug
2782                     $data = xmlize($xml_data,0);         
2783                     //echo strftime ("%X",time())."<p>";                                                            //Debug
2784                     //traverse_xmlize($data);                                                                     //Debug
2785                     //print_object ($GLOBALS['traverse_array']);                                                  //Debug
2786                     //$GLOBALS['traverse_array']="";                                                              //Debug
2787                     //Now, save data to db. We'll use it later
2788                     //Get id and modtype from data
2789                     $mod_id = $data["MOD"]["#"]["ID"]["0"]["#"];
2790                     $mod_type = $data["MOD"]["#"]["MODTYPE"]["0"]["#"];
2791                     //Only if we've selected to restore it
2792                     if  ($this->preferences->mods[$mod_type]->restore) {
2793                         //Save to db
2794                         $status = backup_putid($this->preferences->backup_unique_code,$mod_type,$mod_id,
2795                                      null,$data);
2796                         //echo "<p>id: ".$mod_id."-".$mod_type." len.: ".strlen($sla_mod_temp)." to_db: ".$status."<p>";   //Debug
2797                         //Create returning info
2798                         $ret_info->id = $mod_id;
2799                         $ret_info->modtype = $mod_type;
2800                         $this->info[] = $ret_info;
2801                     }
2802                     //Reset temp
2803                     unset($this->temp);
2804                 }
2805             }
2807             //Stop parsing if todo = MODULES and tagName = MODULES (en of the tag, of course)
2808             //Speed up a lot (avoid parse all)
2809             if ($tagName == "MODULES" and $this->level == 3) {
2810                 $this->finished = true;
2811             }
2813             //Clear things
2814             $this->tree[$this->level] = "";
2815             $this->level--;
2816             $this->content = "";
2817         }
2819         //This is the endTag handler we use where we are reading the logs zone (todo="LOGS")
2820         function endElementLogs($parser, $tagName) {
2821             //Check if we are into LOGS zone
2822             if ($this->tree[3] == "LOGS") {
2823                 //if (trim($this->content))                                                                     //Debug
2824                 //    echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br>\n";           //Debug
2825                 //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br>\n";          //Debug
2826                 //Acumulate data to info (content + close tag)
2827                 //Reconvert: strip htmlchars again and trim to generate xml data
2828                 if (!isset($this->temp)) {
2829                     $this->temp = "";
2830                 }
2831                 $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
2832                 //If we've finished a log, xmlize it an save to db
2833                 if (($this->level == 4) and ($tagName == "LOG")) {
2834                     //Prepend XML standard header to info gathered
2835                     $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
2836                     //Call to xmlize for this portion of xml data (one LOG)
2837                     //echo "-XMLIZE: ".strftime ("%X",time()),"-";                                                //Debug
2838                     $data = xmlize($xml_data,0);
2839                     //echo strftime ("%X",time())."<p>";                                                          //Debug
2840                     //traverse_xmlize($data);                                                                     //Debug
2841                     //print_object ($GLOBALS['traverse_array']);                                                  //Debug
2842                     //$GLOBALS['traverse_array']="";                                                              //Debug
2843                     //Now, save data to db. We'll use it later
2844                     //Get id and modtype from data
2845                     $log_id = $data["LOG"]["#"]["ID"]["0"]["#"];
2846                     $log_module = $data["LOG"]["#"]["MODULE"]["0"]["#"];
2847                     //We only save log entries from backup file if they are:
2848                     // - Course logs
2849                     // - User logs
2850                     // - Module logs about one restored module
2851                     if  ($log_module == "course" or
2852                          $log_module == "user" or
2853                         $this->preferences->mods[$log_module]->restore) {
2854                         //Increment counter
2855                         $this->counter++;
2856                         //Save to db
2857                         $status = backup_putid($this->preferences->backup_unique_code,"log",$log_id,
2858                                      null,$data);
2859                         //echo "<p>id: ".$mod_id."-".$mod_type." len.: ".strlen($sla_mod_temp)." to_db: ".$status."<p>";   //Debug
2860                         //Create returning info
2861                         $this->info = $this->counter;
2862                     }
2863                     //Reset temp
2864                     unset($this->temp);
2865                 }
2866             }
2868             //Stop parsing if todo = LOGS and tagName = LOGS (en of the tag, of course)
2869             //Speed up a lot (avoid parse all)
2870             if ($tagName == "LOGS" and $this->level == 3) {
2871                 $this->finished = true;
2872                 $this->counter = 0;
2874             }
2876             //Clear things
2877             $this->tree[$this->level] = "";
2878             $this->level--;
2879             $this->content = "";
2880         }
2882         //This is the endTag default handler we use when todo is undefined
2883         function endElement($parser, $tagName) {
2884             if (trim($this->content))                                                                     //Debug
2885                 echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br>\n";           //Debug
2886             echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br>\n";          //Debug
2888             //Clear things
2889             $this->tree[$this->level] = "";
2890             $this->level--;
2891             $this->content = "";
2892         }
2894         //This is the handler to read data contents (simple accumule it)
2895         function characterData($parser, $data) {
2896             $this->content .= $data;
2897         }
2898     }
2899     
2900     //This function executes the MoodleParser
2901     function restore_read_xml ($xml_file,$todo,$preferences) {
2902         
2903         $status = true;
2905         $xml_parser = xml_parser_create();
2906         $moodle_parser = new MoodleParser();
2907         $moodle_parser->todo = $todo;
2908         $moodle_parser->preferences = $preferences;
2909         xml_set_object($xml_parser,$moodle_parser);
2910         //Depending of the todo we use some element_handler or another
2911         if ($todo == "INFO") {
2912             //Define handlers to that zone
2913             xml_set_element_handler($xml_parser, "startElementInfo", "endElementInfo");
2914         } else if ($todo == "COURSE_HEADER") {
2915             //Define handlers to that zone
2916             xml_set_element_handler($xml_parser, "startElementCourseHeader", "endElementCourseHeader");
2917         } else if ($todo == "SECTIONS") {
2918             //Define handlers to that zone
2919             xml_set_element_handler($xml_parser, "startElementSections", "endElementSections");
2920         } else if ($todo == "USERS") {
2921             //Define handlers to that zone
2922             xml_set_element_handler($xml_parser, "startElementUsers", "endElementUsers");
2923         } else if ($todo == "QUESTIONS") {
2924             //Define handlers to that zone
2925             xml_set_element_handler($xml_parser, "startElementQuestions", "endElementQuestions");
2926         } else if ($todo == "SCALES") {
2927             //Define handlers to that zone
2928             xml_set_element_handler($xml_parser, "startElementScales", "endElementScales");
2929         } else if ($todo == "GROUPS") {
2930             //Define handlers to that zone
2931             xml_set_element_handler($xml_parser, "startElementGroups", "endElementGroups");
2932         } else if ($todo == "EVENTS") {
2933             //Define handlers to that zone
2934             xml_set_element_handler($xml_parser, "startElementEvents", "endElementEvents");
2935         } else if ($todo == "MODULES") {
2936             //Define handlers to that zone
2937             xml_set_element_handler($xml_parser, "startElementModules", "endElementModules");
2938         } else if ($todo == "LOGS") {
2939             //Define handlers to that zone
2940             xml_set_element_handler($xml_parser, "startElementLogs", "endElementLogs");
2941         } else {
2942             //Define default handlers (must no be invoked when everything become finished)
2943             xml_set_element_handler($xml_parser, "startElementInfo", "endElementInfo");
2944         }
2945         xml_set_character_data_handler($xml_parser, "characterData");
2946         $fp = fopen($xml_file,"r")
2947             or $status = false;
2948         if ($status) {
2949             while ($data = fread($fp, 4096) and !$moodle_parser->finished)
2950                     xml_parse($xml_parser, $data, feof($fp))
2951                             or die(sprintf("XML error: %s at line %d",
2952                             xml_error_string(xml_get_error_code($xml_parser)),
2953                                     xml_get_current_line_number($xml_parser)));
2954             fclose($fp);
2955         }
2956         //Get info from parser
2957         $info = $moodle_parser->info;
2958         
2959         //Clear parser mem
2960         xml_parser_free($xml_parser);
2962         if ($status && $info) {
2963             return $info;
2964         } else {
2965             return $status;
2966         }
2967     }
2968 ?>