New translation added.
[moodle.git] / backup / restorelib.php
blob32eaf8311ff2421f494614e647b3dbdc8ade35be
1 <?PHP //$Id$
2 //Functions used in restore
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,$moodle_home) {
8 global $CFG;
10 $status = true;
12 if (empty($CFG->unzip)) { // Use built-in php-based unzip function
13 include_once($moodle_home."/lib/pclzip/pclzip.lib.php");
14 $archive = new PclZip($file);
15 if (!$list = $archive->extract(dirname($file))) {
16 $status = false;
18 } else { // Use external unzip program
19 $command = "cd ".dirname($file)."; $CFG->unzip -o ".basename($file);
20 Exec($command);
23 return $status;
26 //This function checks if moodle.xml seems to be a valid xml file
27 //(exists, has an xml header and a course main tag
28 function restore_check_moodle_file ($file) {
30 $status = true;
32 //Check if it exists
33 if ($status = is_file($file)) {
34 //Open it and read the first 200 bytes (chars)
35 $handle = fopen ($file, "r");
36 $first_chars = fread($handle,200);
37 $status = fclose ($handle);
38 //Chek if it has the requires strings
39 if ($status) {
40 $status = strpos($first_chars,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
41 if ($status !== false) {
42 $status = strpos($first_chars,"<MOODLE_BACKUP>");
47 return $status;
50 //This function read the xml file and store it data from the info zone in an object
51 function restore_read_xml_info ($xml_file) {
53 //We call the main read_xml function, with todo = INFO
54 $info = restore_read_xml ($xml_file,"INFO",false);
56 return $info;
59 //This function read the xml file and store it data from the course header zone in an object
60 function restore_read_xml_course_header ($xml_file) {
62 //We call the main read_xml function, with todo = COURSE_HEADER
63 $info = restore_read_xml ($xml_file,"COURSE_HEADER",false);
65 return $info;
68 //This function read the xml file and store its data from the sections in a object
69 function restore_read_xml_sections ($xml_file) {
71 //We call the main read_xml function, with todo = SECTIONS
72 $info = restore_read_xml ($xml_file,"SECTIONS",false);
74 return $info;
77 //This function read the xml file and store its data from the users in
78 //backup_ids->info db (and user's id in $info)
79 function restore_read_xml_users ($restore,$xml_file) {
81 //We call the main read_xml function, with todo = USERS
82 $info = restore_read_xml ($xml_file,"USERS",$restore);
84 return $info;
87 //This function read the xml file and store its data from the questions in
88 //backup_ids->info db (and category's id in $info)
89 function restore_read_xml_questions ($restore,$xml_file) {
91 //We call the main read_xml function, with todo = QUESTIONS
92 $info = restore_read_xml ($xml_file,"QUESTIONS",$restore);
94 return $info;
97 //This function read the xml file and store its data from the modules in
98 //backup_ids->info
99 function restore_read_xml_modules ($restore,$xml_file) {
101 //We call the main read_xml function, with todo = MODULES
102 $info = restore_read_xml ($xml_file,"MODULES",$restore);
104 return $info;
107 //This function prints the contents from the info parammeter passed
108 function restore_print_info ($info) {
110 $status = true;
111 if ($info) {
112 //This is tha align to every ingo table
113 $table->align = array ("RIGHT","LEFT");
114 //This is the nowrap clause
115 $table->wrap = array ("","NOWRAP");
116 //The width
117 $table->width = "70%";
118 //Put interesting info in table
119 //The backup original name
120 $tab[0][0] = "<b>".get_string("backuporiginalname").":</b>";
121 $tab[0][1] = $info->backup_name;
122 //The moodle version
123 $tab[1][0] = "<b>".get_string("moodleversion").":</b>";
124 $tab[1][1] = $info->backup_moodle_release." (".$info->backup_moodle_version.")";
125 //The backup version
126 $tab[2][0] = "<b>".get_string("backupversion").":</b>";
127 $tab[2][1] = $info->backup_backup_release." (".$info->backup_backup_version.")";
128 //The backup date
129 $tab[3][0] = "<b>".get_string("backupdate").":</b>";
130 $tab[3][1] = userdate($info->backup_date);
131 //Print title
132 print_heading(get_string("backup").":");
133 $table->data = $tab;
134 //Print backup general info
135 print_table($table);
136 //Now backup contents in another table
137 $tab = array();
138 //First mods info
139 $mods = $info->mods;
140 $elem = 0;
141 foreach ($mods as $key => $mod) {
142 $tab[$elem][0] = "<b>".get_string("modulenameplural",$key).":</b>";
143 if ($mod->backup == "false") {
144 $tab[$elem][1] = get_string("notincluded");
145 } else {
146 if ($mod->userinfo == "true") {
147 $tab[$elem][1] = get_string("included")." ".get_string("withuserdata");
148 } else {
149 $tab[$elem][1] = get_string("included")." ".get_string("withoutuserdata");
152 $elem++;
154 //Users info
155 $tab[$elem][0] = "<b>".get_string("users").":</b>";
156 $tab[$elem][1] = get_string($info->backup_users);
157 $elem++;
158 //Logs info
159 $tab[$elem][0] = "<b>".get_string("logs").":</b>";
160 if ($info->backup_logs == "true") {
161 $tab[$elem][1] = get_string("yes");
162 } else {
163 $tab[$elem][1] = get_string("no");
165 $elem++;
166 //User Files info
167 $tab[$elem][0] = "<b>".get_string("userfiles").":</b>";
168 if ($info->backup_user_files == "true") {
169 $tab[$elem][1] = get_string("yes");
170 } else {
171 $tab[$elem][1] = get_string("no");
173 $elem++;
174 //Course Files info
175 $tab[$elem][0] = "<b>".get_string("coursefiles").":</b>";
176 if ($info->backup_course_files == "true") {
177 $tab[$elem][1] = get_string("yes");
178 } else {
179 $tab[$elem][1] = get_string("no");
181 $elem++;
182 $table->data = $tab;
183 //Print title
184 print_heading(get_string("backupdetails").":");
185 //Print backup general info
186 print_table($table);
187 } else {
188 $status = false;
191 return $status;
194 //This function prints the contents from the course_header parammeter passed
195 function restore_print_course_header ($course_header) {
197 $status = true;
198 if ($course_header) {
199 //This is tha align to every ingo table
200 $table->align = array ("RIGHT","LEFT");
201 //The width
202 $table->width = "70%";
203 //Put interesting course header in table
204 //The course name
205 $tab[0][0] = "<b>".get_string("name").":</b>";
206 $tab[0][1] = $course_header->course_fullname." (".$course_header->course_shortname.")";
207 //The course summary
208 $tab[1][0] = "<b>".get_string("summary").":</b>";
209 $tab[1][1] = $course_header->course_summary;
210 $table->data = $tab;
211 //Print title
212 print_heading(get_string("course").":");
213 //Print backup course header info
214 print_table($table);
215 } else {
216 $status = false;
218 return $status;
221 //This function create a new course record.
222 //When finished, course_header contains the id of the new course
223 function restore_create_new_course($restore,&$course_header) {
225 global $CFG;
227 $status = true;
229 $fullname = $course_header->course_fullname;
230 $shortname = $course_header->course_shortname;
231 $currentfullname = "";
232 $currentshortname = "";
233 $counter = 0;
234 //Iteratere while the name exists
235 do {
236 if ($counter) {
237 $suffixfull = " ".get_string("copy")." ".$counter;
238 $suffixshort = "-".$counter;
239 } else {
240 $suffixfull = "";
241 $suffixshort = "";
243 $currentfullname = $fullname.$suffixfull;
244 $currentshortname = $shortname.$suffixshort;
245 $course = get_record("course","fullname",addslashes($currentfullname));
246 $counter++;
247 } while ($course);
249 //New name = currentname
250 $course_header->course_fullname = $currentfullname;
251 $course_header->course_shortname = $currentshortname;
253 //Now calculate the category
254 $category = get_record("course_categories","id",$course_header->category->id,
255 "name",addslashes($course_header->category->name));
256 //If no exists, try by name only
257 if (!$category) {
258 $category = get_record("course_categories","name",addslashes($course_header->category->name));
260 //If no exists, get category id 1
261 if (!$category) {
262 $category = get_record("course_categories","id","1");
264 //If exists, put new category id
265 if ($category) {
266 $course_header->category->id = $category->id;
267 $course_header->category->name = $category->name;
268 //Error, cannot locate category
269 } else {
270 $course_header->category->id = 0;
271 $course_header->category->name = getstring("unknowcategory");
272 $status = false;
275 //Create the course_object
276 if ($status) {
277 $course->category = addslashes($course_header->category->id);
278 $course->password = addslashes($course_header->course_password);
279 $course->fullname = addslashes($course_header->course_fullname);
280 $course->shortname = addslashes($course_header->course_shortname);
281 $course->summary = addslashes($course_header->course_summary);
282 $course->format = addslashes($course_header->course_format);
283 $course->newsitems = addslashes($course_header->course_newsitems);
284 $course->teacher = addslashes($course_header->course_teacher);
285 $course->teachers = addslashes($course_header->course_teachers);
286 $course->student = addslashes($course_header->course_student);
287 $course->students = addslashes($course_header->course_students);
288 $course->guest = addslashes($course_header->course_guest);
289 $course->startdate = addslashes($course_header->course_startdate);
290 $course->numsections = addslashes($course_header->course_numsections);
291 $course->showrecent = addslashes($course_header->course_showrecent);
292 $course->marker = addslashes($course_header->course_marker);
293 $course->visible = addslashes($course_header->course_visible);
294 $course->timecreated = addslashes($course_header->course_timecreated);
295 $course->timemodified = addslashes($course_header->course_timemodified);
296 //Now insert the record
297 $newid = insert_record("course",$course);
298 if ($newid) {
299 //save old and new course id
300 backup_putid ($restore->backup_unique_code,"course",$course_header->course_id,$newid);
301 //Replace old course_id in course_header
302 $course_header->course_id = $newid;
303 } else {
304 $status = false;
308 return $status;
311 //This function creates all the course_sections and course_modules from xml
312 //when restoring in a new course or simply checks sections and create records
313 //in backup_ids when restoring in a existing course
314 function restore_create_sections($restore,$xml_file) {
316 global $CFG,$db;
318 $status = true;
319 //Check it exists
320 if (!file_exists($xml_file)) {
321 $status = false;
323 //Get info from xml
324 if ($status) {
325 $info = restore_read_xml_sections($xml_file);
327 //Put the info in the DB, recoding ids and saving the in backup tables
329 $sequence = "";
331 if ($info) {
332 //For each, section, save it to db
333 foreach ($info->sections as $key => $sect) {
334 $sequence = "";
335 $section->course = $restore->course_id;
336 $section->section = $sect->number;
337 $section->summary = addslashes($sect->summary);
338 $section->visible = $sect->visible;
339 $section->sequence = "";
340 //Now calculate the section's newid
341 $newid = 0;
342 if ($restore->restoreto == 1) {
343 //Save it to db (only if restoring to new course)
344 $newid = insert_record("course_sections",$section);
345 } else {
346 //Get section id when restoring in existing course
347 $rec = get_record("course_sections","course",$restore->course_id,
348 "section",$section->section);
349 //If that section doesn't exist, get section 0 (every mod will be
350 //asigned there
351 if(!$rec) {
352 $rec = get_record("course_sections","course",$restore->course_id,
353 "section","0");
355 $newid = $rec->id;
356 $sequence = $rec->sequence;
358 if ($newid) {
359 //save old and new section id
360 backup_putid ($restore->backup_unique_code,"course_sections",$key,$newid);
361 } else {
362 $status = false;
364 //If all is OK, go with associated mods
365 if ($status) {
366 //If we have mods in the section
367 if ($sect->mods) {
368 //For each mod inside section
369 foreach ($sect->mods as $keym => $mod) {
370 //Check if we've to restore this module
371 if ($restore->mods[$mod->type]->restore) {
372 //Get the module id from modules
373 $module = get_record("modules","name",$mod->type);
374 if ($module) {
375 $course_module->course = $restore->course_id;
376 $course_module->module = $module->id;
377 $course_module->section = $newid;
378 $course_module->added = $mod->added;
379 $course_module->deleted = $mod->deleted;
380 $course_module->score = $mod->score;
381 $course_module->visible = $mod->visible;
382 $course_module->instance = null;
383 //NOTE: The instance (new) is calculated and updated in db in the
384 // final step of the restore. We don't know it yet.
385 //print_object($course_module); //Debug
386 //Save it to db
387 $newidmod = insert_record("course_modules",$course_module);
388 if ($newidmod) {
389 //save old and new module id
390 //In the info field, we save the original instance of the module
391 //to use it later
392 backup_putid ($restore->backup_unique_code,"course_modules",
393 $keym,$newidmod,$mod->instance);
394 } else {
395 $status = false;
397 //Now, calculate the sequence field
398 if ($status) {
399 if ($sequence) {
400 $sequence .= ",".$newidmod;
401 } else {
402 $sequence = $newidmod;
405 } else {
406 $status = false;
412 //If all is OK, update sequence field in course_sections
413 if ($status) {
414 $rec->id = $newid;
415 $rec->sequence = $sequence;
416 //Unset other fields before update (we don't want them)
417 //Only need id and sequence !! Previously, existing bug
418 //because update without addslashes in summary
419 unset($rec->course);
420 unset($rec->section);
421 unset($rec->summary);
422 unset($rec->visible);
423 $status = update_record("course_sections",$rec);
426 } else {
427 $status = false;
429 return $status;
432 //This function creates all the user, user_students, user_teachers
433 //user_course_creators and user_admins from xml
434 function restore_create_users($restore,$xml_file) {
436 global $CFG, $db;
438 $status = true;
439 //Check it exists
440 if (!file_exists($xml_file)) {
441 $status = false;
443 //Get info from xml
444 if ($status) {
445 //info will contain the old_id of every user
446 //in backup_ids->info will be the real info (serialized)
447 $info = restore_read_xml_users($restore,$xml_file);
450 //Now, get evey user_id from $info and user data from $backup_ids
451 //and create the necessary records (users, user_students, user_teachers
452 //user_course_creators and user_admins
453 if ($info) {
454 //For each, user, take its info from backup_ids
455 foreach ($info->users as $userid) {
456 $rec = backup_getid($restore->backup_unique_code,"user",$userid);
457 $user = $rec->info;
458 //Calculate if it is a course user
459 //Has role teacher or student or admin or coursecreator
460 $is_course_user = ($user->roles[teacher] or $user->roles[student] or
461 $user->roles[admin] or $user->roles[coursecreator]);
462 //Check if it's admin and coursecreator
463 $is_admin = ($user->roles[admin]);
464 $is_coursecreator = ($user->roles[coursecreator]);
465 //Check if it's teacher and student
466 $is_teacher = ($user->roles[teacher]);
467 $is_student = ($user->roles[student]);
468 //To store new ids created
469 $newid=null;
470 //check if it exists (by username) and get its id
471 $user_exists = true;
472 $user_data = get_record("user","username",$user->username);
473 if (!$user_data) {
474 $user_exists = false;
475 } else {
476 $newid = $user_data->id;
478 //Flags to see if we have to create the user and roles
479 $create_user = true;
480 $create_roles = true;
482 //If we are restoring course users and it isn't a course user
483 if ($restore->users == 1 and !$is_course_user) {
484 //If only restoring course_users and user isn't a course_user, inform to $backup_ids
485 $status = backup_putid($restore->backup_unique_code,"user",$userid,null,'notincourse');
486 $create_user = false;
487 $create_roles = false;
490 if ($user_exists and $create_user) {
491 //If user exists mark its newid in backup_ids (the same than old)
492 $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,'exists');
493 $create_user = false;
496 //Here, if create_user, do it
497 if ($create_user) {
498 //We addslashes to necessary fields
499 $user->username = addslashes($user->username);
500 $user->firstname = addslashes($user->firstname);
501 $user->lastname = addslashes($user->lastname);
502 $user->email = addslashes($user->email);
503 $user->institution = addslashes($user->institution);
504 $user->department = addslashes($user->department);
505 $user->address = addslashes($user->address);
506 $user->city = addslashes($user->city);
507 $user->url = addslashes($user->url);
508 $user->description = addslashes($user->description);
509 //We are going to create the user
510 //The structure is exactly as we need
511 $newid = insert_record ("user",$user);
512 //Put the new id
513 $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,"new");
516 //Here, if create_roles, do it as necessary
517 if ($create_roles) {
518 //Get the newid and currecnt info from backup_ids
519 $data = backup_getid($restore->backup_unique_code,"user",$userid);
520 $newid = $data->new_id;
521 $currinfo = $data->info.",";
522 //Now, depending of the role, create records in user_studentes and user_teacher
523 //and/or mark it in backup_ids
524 if ($is_admin) {
525 //If the record (user_admins) doesn't exists
526 if (!record_exists("user_admins","userid",$newid)) {
527 //Only put status in backup_ids
528 $currinfo = $currinfo."admin,";
529 $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
532 if ($is_coursecreator) {
533 //If the record (user_coursecreators) doesn't exists
534 if (!record_exists("user_coursecreators","userid",$newid)) {
535 //Only put status in backup_ids
536 $currinfo = $currinfo."coursecreator,";
537 $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
540 if ($is_teacher) {
541 //If the record (teacher) doesn't exists
542 if (!record_exists("user_teachers","userid",$newid,"course", $restore->course_id)) {
543 //Put status in backup_ids
544 $currinfo = $currinfo."teacher,";
545 $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
546 //Set course and user
547 $user->roles[teacher]->course = $restore->course_id;
548 $user->roles[teacher]->userid = $newid;
549 //Insert data in user_teachers
550 //The structure is exactly as we need
551 $status = insert_record("user_teachers",$user->roles[teacher]);
554 if ($is_student) {
555 //If the record (student) doesn't exists
556 if (!record_exists("user_students","userid",$newid,"course", $restore->course_id)) {
557 //Put status in backup_ids
558 $currinfo = $currinfo."student,";
559 $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
560 //Set course and user
561 $user->roles[student]->course = $restore->course_id;
562 $user->roles[student]->userid = $newid;
563 //Insert data in user_students
564 //The structure is exactly as we need
565 $status = insert_record("user_students",$user->roles[student]);
568 if (!$is_course_user) {
569 //If the record (user) doesn't exists
570 if (!record_exists("user","id",$newid)) {
571 //Put status in backup_ids
572 $currinfo = $currinfo."user,";
573 $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
578 } else {
579 $status = false;
582 return $status;
585 //This function creates all the categories and questions
586 //from xml (STEP1 of quiz restore)
587 function restore_create_questions($restore,$xml_file) {
589 global $CFG, $db;
591 $status = true;
592 //Check it exists
593 if (!file_exists($xml_file)) {
594 $status = false;
596 //Get info from xml
597 if ($status) {
598 //info will contain the old_id of every category
599 //in backup_ids->info will be the real info (serialized)
600 $info = restore_read_xml_questions($restore,$xml_file);
602 //Now, if we have anything in info, we have to restore that
603 //categories/questions
604 if ($info) {
605 if ($info !== true) {
606 //Iterate over each category
607 foreach ($info as $category) {
608 $catrestore = "quiz_restore_question_categories";
609 if (function_exists($catrestore)) {
610 //print_object ($category); //Debug
611 $status = $catrestore($category,$restore);
612 } else {
613 //Something was wrong. Function should exist.
614 $status = false;
618 } else {
619 $status = false;
621 return $status;
624 //This function restores the userfiles from the temp (user_files) directory to the
625 //dataroot/users directory
626 function restore_user_files($restore) {
628 global $CFG;
630 $status = true;
632 //First, we check to "users" exists and create is as necessary
633 //in CFG->dataroot
634 $dest_dir = $CFG->dataroot."/users";
635 $status = check_dir_exists($dest_dir,true);
637 //Now, we iterate over "user_files" records to check if that user dir must be
638 //copied (and renamed) to the "users" dir.
639 $rootdir = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/user_files";
640 //Check if directory exists
641 if (is_dir($rootdir)) {
642 $list = list_directories ($rootdir);
643 if ($list) {
644 //Iterate
645 $counter = 0;
646 foreach ($list as $dir) {
647 //Look for dir like username in backup_ids
648 $data = get_record ("backup_ids","backup_code",$restore->backup_unique_code,
649 "table_name","user",
650 "old_id",$dir);
651 //If thar user exists in backup_ids
652 if ($data) {
653 //Only it user has been created now
654 if (strpos($data->info,"new") !== false) {
655 //Copy the old_dir to its new location (and name) !!
656 //Only if destination doesn't exists
657 if (!file_exists($dest_dir."/".$data->new_id)) {
658 $status = backup_copy_file($rootdir."/".$dir,
659 $dest_dir."/".$data->new_id);
660 $counter ++;
662 //Do some output
663 if ($counter % 2 == 0) {
664 echo ".";
665 if ($counter % 40 == 0) {
666 echo "<br>";
668 backup_flush(300);
675 //If status is ok and whe have dirs created, returns counter to inform
676 if ($status and $counter) {
677 return $counter;
678 } else {
679 return $status;
683 //This function restores the course files from the temp (course_files) directory to the
684 //dataroot/course_id directory
685 function restore_course_files($restore) {
687 global $CFG;
689 $status = true;
691 //First, we check to "course_id" exists and create is as necessary
692 //in CFG->dataroot
693 $dest_dir = $CFG->dataroot."/".$restore->course_id;
694 $status = check_dir_exists($dest_dir,true);
696 //Now, we iterate over "course_files" records to check if that file/dir must be
697 //copied to the "dest_dir" dir.
698 $rootdir = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/course_files";
699 //Check if directory exists
700 if (is_dir($rootdir)) {
701 $list = list_directories_and_files ($rootdir);
702 if ($list) {
703 //Iterate
704 $counter = 0;
705 foreach ($list as $dir) {
706 //Copy the dir to its new location
707 //Only if destination file/dir doesn exists
708 if (!file_exists($dest_dir."/".$dir)) {
709 $status = backup_copy_file($rootdir."/".$dir,
710 $dest_dir."/".$dir);
711 $counter ++;
713 //Do some output
714 if ($counter % 2 == 0) {
715 echo ".";
716 if ($counter % 40 == 0) {
717 echo "<br>";
719 backup_flush(300);
724 //If status is ok and whe have dirs created, returns counter to inform
725 if ($status and $counter) {
726 return $counter;
727 } else {
728 return $status;
733 //This function creates all the structures for every module in backup file
734 //Depending what has been selected.
735 function restore_create_modules($restore,$xml_file) {
737 global $CFG;
739 $status = true;
740 //Check it exists
741 if (!file_exists($xml_file)) {
742 $status = false;
744 //Get info from xml
745 if ($status) {
746 //info will contain the id and modtype of every module
747 //in backup_ids->info will be the real info (serialized)
748 $info = restore_read_xml_modules($restore,$xml_file);
751 //Now, if we have anything in info, we have to restore that mods
752 //from backup_ids (calling every mod restore function)
753 if ($info) {
754 if ($info !== true) {
755 //Iterate over each module
756 foreach ($info as $mod) {
757 $modrestore = $mod->modtype."_restore_mods";
758 if (function_exists($modrestore)) {
759 //print_object ($mod); //Debug
760 $status = $modrestore($mod,$restore);
761 } else {
762 //Something was wrong. Function should exist.
763 $status = false;
767 } else {
768 $status = false;
770 return $status;
773 //This function adjusts the instance field into course_modules. It's executed after
774 //modules restore. There, we KNOW the new instance id !!
775 function restore_check_instances($restore) {
777 global $CFG;
779 $status = true;
781 //We are going to iterate over each course_module saved in backup_ids
782 $course_modules = get_records_sql("SELECT old_id,new_id
783 FROM {$CFG->prefix}backup_ids
784 WHERE backup_code = '$restore->backup_unique_code' AND
785 table_name = 'course_modules'");
786 if ($course_modules) {
787 foreach($course_modules as $cm) {
788 //Get full record, using backup_getids
789 $cm_module = backup_getid($restore->backup_unique_code,"course_modules",$cm->old_id);
790 //Now we are going to the REAL course_modules to get its type (field module)
791 $module = get_record("course_modules","id",$cm_module->new_id);
792 if ($module) {
793 //We know the module type id. Get the name from modules
794 $type = get_record("modules","id",$module->module);
795 if ($type) {
796 //We know the type name and the old_id. Get its new_id
797 //from backup_ids. It's the instance !!!
798 $instance = backup_getid($restore->backup_unique_code,$type->name,$cm_module->info);
799 if ($instance) {
800 //We have the new instance, so update the record in course_modules
801 $module->instance = $instance->new_id;
802 //print_object ($module); //Debug
803 $status = update_record("course_modules",$module);
804 } else {
805 $status = false;
807 } else {
808 $status = false;
810 } else {
811 $status = false;
817 return $status;
820 //=====================================================================================
821 //== ==
822 //== XML Functions (SAX) ==
823 //== ==
824 //=====================================================================================
826 //This is the class used to do all the xml parse
827 class MoodleParser {
829 var $level = 0; //Level we are
830 var $counter = 0; //Counter
831 var $tree = array(); //Array of levels we are
832 var $content = ""; //Content under current level
833 var $todo = ""; //What we hav to do when parsing
834 var $info = ""; //Information collected. Temp storage. Used to return data after parsing.
835 var $temp = ""; //Temp storage.
836 var $preferences = ""; //Preferences about what to load !!
837 var $finished = false; //Flag to say xml_parse to stop
839 //This function is used to get the current contents property value
840 //They are trimed and converted from utf8
841 function getContents() {
842 return trim(utf8_decode($this->content));
845 //This is the startTag handler we use where we are reading the info zone (todo="INFO")
846 function startElementInfo($parser, $tagName, $attrs) {
847 //Refresh properties
848 $this->level++;
849 $this->tree[$this->level] = $tagName;
851 //Output something to avoid browser timeouts...
852 backup_flush();
854 //Check if we are into INFO zone
855 //if ($this->tree[2] == "INFO") //Debug
856 // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br>\n"; //Debug
859 //This is the startTag handler we use where we are reading the course header zone (todo="COURSE_HEADER")
860 function startElementCourseHeader($parser, $tagName, $attrs) {
861 //Refresh properties
862 $this->level++;
863 $this->tree[$this->level] = $tagName;
865 //Output something to avoid browser timeouts...
866 backup_flush();
868 //Check if we are into COURSE_HEADER zone
869 //if ($this->tree[3] == "HEADER") //Debug
870 // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br>\n"; //Debug
873 //This is the startTag handler we use where we are reading the sections zone (todo="SECTIONS")
874 function startElementSections($parser, $tagName, $attrs) {
875 //Refresh properties
876 $this->level++;
877 $this->tree[$this->level] = $tagName;
879 //Output something to avoid browser timeouts...
880 backup_flush();
882 //Check if we are into SECTIONS zone
883 //if ($this->tree[3] == "SECTIONS") //Debug
884 // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br>\n"; //Debug
887 //This is the startTag handler we use where we are reading the user zone (todo="USERS")
888 function startElementUsers($parser, $tagName, $attrs) {
889 //Refresh properties
890 $this->level++;
891 $this->tree[$this->level] = $tagName;
893 //Check if we are into USERS zone
894 //if ($this->tree[3] == "USERS") //Debug
895 // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br>\n"; //Debug
898 //This is the startTag handler we use where we are reading the questions zone (todo="QUESTIONS")
899 function startElementQuestions($parser, $tagName, $attrs) {
900 //Refresh properties
901 $this->level++;
902 $this->tree[$this->level] = $tagName;
904 //if ($tagName == "QUESTION_CATEGORY" && $this->tree[3] == "QUESTION_CATEGORIES") { //Debug
905 // echo "<P>QUESTION_CATEGORY: ".strftime ("%X",time()),"-"; //Debug
906 //} //Debug
908 //Output something to avoid browser timeouts...
909 backup_flush();
911 //Check if we are into QUESTION_CATEGORIES zone
912 //if ($this->tree[3] == "QUESTION_CATEGORIES") //Debug
913 // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br>\n"; //Debug
915 //If we are under a QUESTION_CATEGORY tag under a QUESTION_CATEGORIES zone, accumule it
916 if (($this->tree[4] == "QUESTION_CATEGORY") and ($this->tree[3] == "QUESTION_CATEGORIES")) {
917 $this->temp .= "<".$tagName.">";
921 //This is the startTag handler we use where we are reading the modules zone (todo="MODULES")
922 function startElementModules($parser, $tagName, $attrs) {
923 //Refresh properties
924 $this->level++;
925 $this->tree[$this->level] = $tagName;
927 //if ($tagName == "MOD" && $this->tree[3] == "MODULES") { //Debug
928 // echo "<P>MOD: ".strftime ("%X",time()),"-"; //Debug
929 //} //Debug
931 //Output something to avoid browser timeouts...
932 backup_flush();
934 //Check if we are into MODULES zone
935 //if ($this->tree[3] == "MODULES") //Debug
936 // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br>\n"; //Debug
938 //If we are under a MOD tag under a MODULES zone, accumule it
939 if (($this->tree[4] == "MOD") and ($this->tree[3] == "MODULES")) {
940 $this->temp .= "<".$tagName.">";
944 //This is the startTag default handler we use when todo is undefined
945 function startElement($parser, $tagName, $attrs) {
946 $this->level++;
947 $this->tree[$this->level] = $tagName;
949 //Output something to avoid browser timeouts...
950 backup_flush();
952 echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br>\n"; //Debug
955 //This is the endTag handler we use where we are reading the info zone (todo="INFO")
956 function endElementInfo($parser, $tagName) {
957 //Check if we are into INFO zone
958 if ($this->tree[2] == "INFO") {
959 //if (trim($this->content)) //Debug
960 // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br>\n"; //Debug
961 //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br>\n"; //Debug
962 //Dependig of different combinations, do different things
963 if ($this->level == 3) {
964 switch ($tagName) {
965 case "NAME":
966 $this->info->backup_name = $this->getContents();
967 break;
968 case "MOODLE_VERSION":
969 $this->info->backup_moodle_version = $this->getContents();
970 break;
971 case "MOODLE_RELEASE":
972 $this->info->backup_moodle_release = $this->getContents();
973 break;
974 case "BACKUP_VERSION":
975 $this->info->backup_backup_version = $this->getContents();
976 break;
977 case "BACKUP_RELEASE":
978 $this->info->backup_backup_release = $this->getContents();
979 break;
980 case "DATE":
981 $this->info->backup_date = $this->getContents();
982 break;
985 if ($this->tree[3] == "DETAILS") {
986 if ($this->level == 4) {
987 switch ($tagName) {
988 case "USERS":
989 $this->info->backup_users = $this->getContents();
990 break;
991 case "LOGS":
992 $this->info->backup_logs = $this->getContents();
993 break;
994 case "USERFILES":
995 $this->info->backup_user_files = $this->getContents();
996 break;
997 case "COURSEFILES":
998 $this->info->backup_course_files = $this->getContents();
999 break;
1002 if ($this->level == 5) {
1003 switch ($tagName) {
1004 case "NAME":
1005 $this->info->tempName = $this->getContents();
1006 break;
1007 case "INCLUDED":
1008 $this->info->mods[$this->info->tempName]->backup = $this->getContents();
1009 break;
1010 case "USERINFO":
1011 $this->info->mods[$this->info->tempName]->userinfo = $this->getContents();
1012 break;
1019 //Clear things
1020 $this->tree[$this->level] = "";
1021 $this->level--;
1022 $this->content = "";
1024 //Stop parsing if todo = INFO and tagName = INFO (en of the tag, of course)
1025 //Speed up a lot (avoid parse all)
1026 if ($tagName == "INFO") {
1027 $this->finished = true;
1031 //This is the endTag handler we use where we are reading the course_header zone (todo="COURSE_HEADER")
1032 function endElementCourseHeader($parser, $tagName) {
1033 //Check if we are into COURSE_HEADER zone
1034 if ($this->tree[3] == "HEADER") {
1035 //if (trim($this->content)) //Debug
1036 // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br>\n"; //Debug
1037 //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br>\n"; //Debug
1038 //Dependig of different combinations, do different things
1039 if ($this->level == 4) {
1040 switch ($tagName) {
1041 case "ID":
1042 $this->info->course_id = $this->getContents();
1043 break;
1044 case "PASSWORD":
1045 $this->info->course_password = $this->getContents();
1046 break;
1047 case "FULLNAME":
1048 $this->info->course_fullname = $this->getContents();
1049 break;
1050 case "SHORTNAME":
1051 $this->info->course_shortname = $this->getContents();
1052 break;
1053 case "SUMMARY":
1054 $this->info->course_summary = $this->getContents();
1055 break;
1056 case "FORMAT":
1057 $this->info->course_format = $this->getContents();
1058 break;
1059 case "NEWSITEMS":
1060 $this->info->course_newsitems = $this->getContents();
1061 break;
1062 case "TEACHER":
1063 $this->info->course_teacher = $this->getContents();
1064 break;
1065 case "TEACHERS":
1066 $this->info->course_teachers = $this->getContents();
1067 break;
1068 case "STUDENT":
1069 $this->info->course_student = $this->getContents();
1070 break;
1071 case "STUDENTS":
1072 $this->info->course_students = $this->getContents();
1073 break;
1074 case "GUEST":
1075 $this->info->course_guest = $this->getContents();
1076 break;
1077 case "STARDATE":
1078 $this->info->course_stardate = $this->getContents();
1079 break;
1080 case "NUMSECTIONS":
1081 $this->info->course_numsections = $this->getContents();
1082 break;
1083 case "SHOWRECENT":
1084 $this->info->course_showrecent = $this->getContents();
1085 break;
1086 case "MARKER":
1087 $this->info->course_marker = $this->getContents();
1088 break;
1089 case "VISIBLE":
1090 $this->info->course_visible = $this->getContents();
1091 break;
1092 case "TIMECREATED":
1093 $this->info->course_timecreated = $this->getContents();
1094 break;
1095 case "TIMEMODIFIED":
1096 $this->info->course_timemodified = $this->getContents();
1097 break;
1100 if ($this->tree[4] == "CATEGORY") {
1101 if ($this->level == 5) {
1102 switch ($tagName) {
1103 case "ID":
1104 $this->info->category->id = $this->getContents();
1105 break;
1106 case "NAME":
1107 $this->info->category->name = $this->getContents();
1108 break;
1114 //Clear things
1115 $this->tree[$this->level] = "";
1116 $this->level--;
1117 $this->content = "";
1119 //Stop parsing if todo = COURSE_HEADER and tagName = HEADER (en of the tag, of course)
1120 //Speed up a lot (avoid parse all)
1121 if ($tagName == "HEADER") {
1122 $this->finished = true;
1126 //This is the endTag handler we use where we are reading the sections zone (todo="SECTIONS")
1127 function endElementSections($parser, $tagName) {
1128 //Check if we are into SECTIONS zone
1129 if ($this->tree[3] == "SECTIONS") {
1130 //if (trim($this->content)) //Debug
1131 // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br>\n"; //Debug
1132 //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br>\n"; //Debug
1133 //Dependig of different combinations, do different things
1134 if ($this->level == 4) {
1135 switch ($tagName) {
1136 case "SECTION":
1137 //We've finalized a section, get it
1138 $this->info->sections[$this->info->tempsection->id]->number = $this->info->tempsection->number;
1139 $this->info->sections[$this->info->tempsection->id]->summary = $this->info->tempsection->summary;
1140 $this->info->sections[$this->info->tempsection->id]->visible = $this->info->tempsection->visible;
1141 $this->info->sections[$this->info->tempsection->id]->mods = $this->info->tempsection->mods;
1142 unset($this->info->tempsection);
1145 if ($this->level == 5) {
1146 switch ($tagName) {
1147 case "ID":
1148 $this->info->tempsection->id = $this->getContents();
1149 break;
1150 case "NUMBER":
1151 $this->info->tempsection->number = $this->getContents();
1152 break;
1153 case "SUMMARY":
1154 $this->info->tempsection->summary = $this->getContents();
1155 break;
1156 case "VISIBLE":
1157 $this->info->tempsection->visible = $this->getContents();
1158 break;
1161 if ($this->level == 6) {
1162 switch ($tagName) {
1163 case "MOD":
1164 //We've finalized a mod, get it
1165 $this->info->tempsection->mods[$this->info->tempmod->id]->type =
1166 $this->info->tempmod->type;
1167 $this->info->tempsection->mods[$this->info->tempmod->id]->instance =
1168 $this->info->tempmod->instance;
1169 $this->info->tempsection->mods[$this->info->tempmod->id]->added =
1170 $this->info->tempmod->added;
1171 $this->info->tempsection->mods[$this->info->tempmod->id]->deleted =
1172 $this->info->tempmod->deleted;
1173 $this->info->tempsection->mods[$this->info->tempmod->id]->score =
1174 $this->info->tempmod->score;
1175 $this->info->tempsection->mods[$this->info->tempmod->id]->visible =
1176 $this->info->tempmod->visible;
1177 unset($this->info->tempmod);
1180 if ($this->level == 7) {
1181 switch ($tagName) {
1182 case "ID":
1183 $this->info->tempmod->id = $this->getContents();
1184 break;
1185 case "TYPE":
1186 $this->info->tempmod->type = $this->getContents();
1187 break;
1188 case "INSTANCE":
1189 $this->info->tempmod->instance = $this->getContents();
1190 break;
1191 case "ADDED":
1192 $this->info->tempmod->added = $this->getContents();
1193 break;
1194 case "DELETED":
1195 $this->info->tempmod->deleted = $this->getContents();
1196 break;
1197 case "SCORE":
1198 $this->info->tempmod->score = $this->getContents();
1199 break;
1200 case "VISIBLE":
1201 $this->info->tempmod->visible = $this->getContents();
1202 break;
1206 //Clear things
1207 $this->tree[$this->level] = "";
1208 $this->level--;
1209 $this->content = "";
1211 //Stop parsing if todo = SECTIONS and tagName = SECTIONS (en of the tag, of course)
1212 //Speed up a lot (avoid parse all)
1213 if ($tagName == "SECTIONS") {
1214 $this->finished = true;
1218 //This is the endTag handler we use where we are reading the users zone (todo="USERS")
1219 function endElementUsers($parser, $tagName) {
1220 //Check if we are into USERS zone
1221 if ($this->tree[3] == "USERS") {
1222 //if (trim($this->content)) //Debug
1223 // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br>\n"; //Debug
1224 //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br>\n"; //Debug
1225 //Dependig of different combinations, do different things
1226 if ($this->level == 4) {
1227 switch ($tagName) {
1228 case "USER":
1229 //Increment counter
1230 $this->counter++;
1231 //Save to db
1232 backup_putid($this->preferences->backup_unique_code,"user",$this->info->tempuser->id,
1233 null,$this->info->tempuser);
1235 //Do some output
1236 if ($this->counter % 10 == 0) {
1237 echo ".";
1238 if ($this->counter % 200 == 0) {
1239 echo "<br>";
1241 backup_flush(300);
1244 //Delete temp obejct
1245 unset($this->info->tempuser);
1246 break;
1249 if ($this->level == 5) {
1250 switch ($tagName) {
1251 case "ID":
1252 $this->info->users[$this->getContents()] = $this->getContents();
1253 $this->info->tempuser->id = $this->getContents();
1254 break;
1255 case "CONFIRMED":
1256 $this->info->tempuser->confirmed = $this->getContents();
1257 break;
1258 case "DELETED":
1259 $this->info->tempuser->deleted = $this->getContents();
1260 break;
1261 case "USERNAME":
1262 $this->info->tempuser->username = $this->getContents();
1263 break;
1264 case "PASSWORD":
1265 $this->info->tempuser->password = $this->getContents();
1266 break;
1267 case "IDNUMBER":
1268 $this->info->tempuser->idnumber = $this->getContents();
1269 break;
1270 case "FIRSTNAME":
1271 $this->info->tempuser->firstname = $this->getContents();
1272 break;
1273 case "LASTNAME":
1274 $this->info->tempuser->lastname = $this->getContents();
1275 break;
1276 case "EMAIL":
1277 $this->info->tempuser->email = $this->getContents();
1278 break;
1279 case "ICQ":
1280 $this->info->tempuser->icq = $this->getContents();
1281 break;
1282 case "PHONE1":
1283 $this->info->tempuser->phone1 = $this->getContents();
1284 break;
1285 case "PHONE2":
1286 $this->info->tempuser->phone2 = $this->getContents();
1287 break;
1288 case "INSTITUTION":
1289 $this->info->tempuser->institution = $this->getContents();
1290 break;
1291 case "DEPARTMENT":
1292 $this->info->tempuser->department = $this->getContents();
1293 break;
1294 case "ADDRESS":
1295 $this->info->tempuser->address = $this->getContents();
1296 break;
1297 case "CITY":
1298 $this->info->tempuser->city = $this->getContents();
1299 break;
1300 case "COUNTRY":
1301 $this->info->tempuser->country = $this->getContents();
1302 break;
1303 case "LANG":
1304 $this->info->tempuser->lang = $this->getContents();
1305 break;
1306 case "TIMEZONE":
1307 $this->info->tempuser->timezone = $this->getContents();
1308 break;
1309 case "FIRSTACCESS":
1310 $this->info->tempuser->firstaccess = $this->getContents();
1311 break;
1312 case "LASTACCESS":
1313 $this->info->tempuser->lastaccess = $this->getContents();
1314 break;
1315 case "LASTLOGIN":
1316 $this->info->tempuser->lastlogin = $this->getContents();
1317 break;
1318 case "CURRENTLOGIN":
1319 $this->info->tempuser->currentlogin = $this->getContents();
1320 break;
1321 case "LASTIP":
1322 $this->info->tempuser->lastip = $this->getContents();
1323 break;
1324 case "SECRET":
1325 $this->info->tempuser->secret = $this->getContents();
1326 break;
1327 case "PICTURE":
1328 $this->info->tempuser->picture = $this->getContents();
1329 break;
1330 case "URL":
1331 $this->info->tempuser->url = $this->getContents();
1332 break;
1333 case "DESCRIPTION":
1334 $this->info->tempuser->description = $this->getContents();
1335 break;
1336 case "MAILFORMAT":
1337 $this->info->tempuser->mailformat = $this->getContents();
1338 break;
1339 case "MAILDISPLAY":
1340 $this->info->tempuser->maildisplay = $this->getContents();
1341 break;
1342 case "HTMLEDITOR":
1343 $this->info->tempuser->htmleditor = $this->getContents();
1344 break;
1345 case "AUTOSUBSCRIBE":
1346 $this->info->tempuser->autosubscribe = $this->getContents();
1347 break;
1348 case "TIMEMODIFIED":
1349 $this->info->tempuser->timemodified = $this->getContents();
1350 break;
1353 if ($this->level == 6) {
1354 switch ($tagName) {
1355 case "ROLE":
1356 //We've finalized a role, get it
1357 $this->info->tempuser->roles[$this->info->temprole->type]->authority =
1358 $this->info->temprole->authority;
1359 $this->info->tempuser->roles[$this->info->temprole->type]->tea_role =
1360 $this->info->temprole->tea_role;
1361 $this->info->tempuser->roles[$this->info->temprole->type]->timestart =
1362 $this->info->temprole->timestart;
1363 $this->info->tempuser->roles[$this->info->temprole->type]->timeend =
1364 $this->info->temprole->timeend;
1365 $this->info->tempuser->roles[$this->info->temprole->type]->time =
1366 $this->info->temprole->time;
1367 unset($this->info->temprole);
1368 break;
1371 if ($this->level == 7) {
1372 switch ($tagName) {
1373 case "TYPE":
1374 $this->info->temprole->type = $this->getContents();
1375 break;
1376 case "AUTHORITY":
1377 $this->info->temprole->authority = $this->getContents();
1378 break;
1379 case "TEA_ROLE":
1380 $this->info->temprole->tea_role = $this->getContents();
1381 break;
1382 case "TIMESTART":
1383 $this->info->temprole->timestart = $this->getContents();
1384 break;
1385 case "TIMEEND":
1386 $this->info->temprole->timeend = $this->getContents();
1387 break;
1388 case "TIME":
1389 $this->info->temprole->time = $this->getContents();
1390 break;
1395 //Stop parsing if todo = USERS and tagName = USERS (en of the tag, of course)
1396 //Speed up a lot (avoid parse all)
1397 if ($tagName == "USERS" and $this->level == 3) {
1398 $this->finished = true;
1399 $this->counter = 0;
1402 //Clear things
1403 $this->tree[$this->level] = "";
1404 $this->level--;
1405 $this->content = "";
1408 //This is the endTag handler we use where we are reading the modules zone (todo="QUESTIONS")
1409 function endElementQuestions($parser, $tagName) {
1410 //Check if we are into QUESTION_CATEGORIES zone
1411 if ($this->tree[3] == "QUESTION_CATEGORIES") {
1412 //if (trim($this->content)) //Debug
1413 // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br>\n"; //Debug
1414 //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br>\n"; //Debug
1415 //Acumulate data to info (content + close tag)
1416 //Reconvert: strip htmlchars again and trim to generate xml data
1417 $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
1418 //If we've finished a mod, xmlize it an save to db
1419 if (($this->level == 4) and ($tagName == "QUESTION_CATEGORY")) {
1420 //Prepend XML standard header to info gathered
1421 $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
1422 //Call to xmlize for this portion of xml data (one MOD)
1423 //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
1424 $data = xmlize($xml_data,0);
1425 //echo strftime ("%X",time())."<p>"; //Debug
1426 //traverse_xmlize($data); //Debug
1427 //print_object ($GLOBALS['traverse_array']); //Debug
1428 //$GLOBALS['traverse_array']=""; //Debug
1429 //Now, save data to db. We'll use it later
1430 //Get id and modtype from data
1431 $category_id = $data["QUESTION_CATEGORY"]["#"]["ID"]["0"]["#"];
1432 //Save to db
1433 $status = backup_putid($this->preferences->backup_unique_code,"quiz_categories",$category_id,
1434 null,$data);
1435 //Create returning info
1436 $ret_info->id = $category_id;
1437 $this->info[] = $ret_info;
1438 //Reset temp
1439 unset($this->temp);
1443 //Stop parsing if todo = QUESTION_CATEGORIES and tagName = QUESTION_CATEGORY (en of the tag, of course)
1444 //Speed up a lot (avoid parse all)
1445 if ($tagName == "QUESTION_CATEGORIES" and $this->level == 3) {
1446 $this->finished = true;
1449 //Clear things
1450 $this->tree[$this->level] = "";
1451 $this->level--;
1452 $this->content = "";
1455 //This is the endTag handler we use where we are reading the modules zone (todo="MODULES")
1456 function endElementModules($parser, $tagName) {
1457 //Check if we are into MODULES zone
1458 if ($this->tree[3] == "MODULES") {
1459 //if (trim($this->content)) //Debug
1460 // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br>\n"; //Debug
1461 //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br>\n"; //Debug
1462 //Acumulate data to info (content + close tag)
1463 //Reconvert: strip htmlchars again and trim to generate xml data
1464 $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
1465 //If we've finished a mod, xmlize it an save to db
1466 if (($this->level == 4) and ($tagName == "MOD")) {
1467 //Prepend XML standard header to info gathered
1468 $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
1469 //Call to xmlize for this portion of xml data (one MOD)
1470 //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
1471 $data = xmlize($xml_data,0);
1472 //echo strftime ("%X",time())."<p>"; //Debug
1473 //traverse_xmlize($data); //Debug
1474 //print_object ($GLOBALS['traverse_array']); //Debug
1475 //$GLOBALS['traverse_array']=""; //Debug
1476 //Now, save data to db. We'll use it later
1477 //Get id and modtype from data
1478 $mod_id = $data["MOD"]["#"]["ID"]["0"]["#"];
1479 $mod_type = $data["MOD"]["#"]["MODTYPE"]["0"]["#"];
1480 //Only if we've selected to restore it
1481 if ($this->preferences->mods[$mod_type]->restore) {
1482 //Save to db
1483 $status = backup_putid($this->preferences->backup_unique_code,$mod_type,$mod_id,
1484 null,$data);
1485 //echo "<p>id: ".$mod_id."-".$mod_type." len.: ".strlen($sla_mod_temp)." to_db: ".$status."<p>"; //Debug
1486 //Create returning info
1487 $ret_info->id = $mod_id;
1488 $ret_info->modtype = $mod_type;
1489 $this->info[] = $ret_info;
1491 //Reset temp
1492 unset($this->temp);
1496 //Stop parsing if todo = MODULES and tagName = MODULES (en of the tag, of course)
1497 //Speed up a lot (avoid parse all)
1498 if ($tagName == "MODULES" and $this->level == 3) {
1499 $this->finished = true;
1502 //Clear things
1503 $this->tree[$this->level] = "";
1504 $this->level--;
1505 $this->content = "";
1508 //This is the endTag default handler we use when todo is undefined
1509 function endElement($parser, $tagName) {
1510 if (trim($this->content)) //Debug
1511 echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br>\n"; //Debug
1512 echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br>\n"; //Debug
1514 //Clear things
1515 $this->tree[$this->level] = "";
1516 $this->level--;
1517 $this->content = "";
1520 //This is the handler to read data contents (simple accumule it)
1521 function characterData($parser, $data) {
1522 $this->content .= $data;
1526 //This function executes the MoodleParser
1527 function restore_read_xml ($xml_file,$todo,$preferences) {
1529 $status = true;
1531 $xml_parser = xml_parser_create();
1532 $moodle_parser = new MoodleParser();
1533 $moodle_parser->todo = $todo;
1534 $moodle_parser->preferences = $preferences;
1535 xml_set_object($xml_parser,&$moodle_parser);
1536 //Depending of the todo we use some element_handler or another
1537 if ($todo == "INFO") {
1538 //Define handlers to that zone
1539 xml_set_element_handler($xml_parser, "startElementInfo", "endElementInfo");
1540 } else if ($todo == "COURSE_HEADER") {
1541 //Define handlers to that zone
1542 xml_set_element_handler($xml_parser, "startElementCourseHeader", "endElementCourseHeader");
1543 } else if ($todo == "SECTIONS") {
1544 //Define handlers to that zone
1545 xml_set_element_handler($xml_parser, "startElementSections", "endElementSections");
1546 } else if ($todo == "USERS") {
1547 //Define handlers to that zone
1548 xml_set_element_handler($xml_parser, "startElementUsers", "endElementUsers");
1549 } else if ($todo == "QUESTIONS") {
1550 //Define handlers to that zone
1551 xml_set_element_handler($xml_parser, "startElementQuestions", "endElementQuestions");
1552 } else if ($todo == "MODULES") {
1553 //Define handlers to that zone
1554 xml_set_element_handler($xml_parser, "startElementModules", "endElementModules");
1555 } else {
1556 //Define default handlers (must no be invoked when everything become finished)
1557 xml_set_element_handler($xml_parser, "startElementInfo", "endElementInfo");
1559 xml_set_character_data_handler($xml_parser, "characterData");
1560 $fp = fopen($xml_file,"r")
1561 or $status = false;
1562 if ($status) {
1563 while ($data = fread($fp, 4096) and !$moodle_parser->finished)
1564 xml_parse($xml_parser, $data, feof($fp))
1565 or die(sprintf("XML error: %s at line %d",
1566 xml_error_string(xml_get_error_code($xml_parser)),
1567 xml_get_current_line_number($xml_parser)));
1568 fclose($fp);
1570 //Get info from parser
1571 $info = $moodle_parser->info;
1573 //Clear parser mem
1574 xml_parser_free($xml_parser);
1576 if ($status && $info) {
1577 return $info;
1578 } else {
1579 return $status;