Merge branch 'MDL-32903' of git://github.com/netspotau/moodle-mod_assign
[moodle.git] / backup / restorelib.php
blob911df714a71bfbe14c5e91bf70e2521e4a7efb49
1 <?php
2 //This function iterates over all modules in backup file, searching for a
3 //MODNAME_refresh_events() to execute. Perhaps it should ve moved to central Moodle...
4 function restore_refresh_events($restore) {
6 global $CFG;
7 $status = true;
9 //Take all modules in backup
10 $modules = $restore->mods;
11 //Iterate
12 foreach($modules as $name => $module) {
13 //Only if the module is being restored
14 if (isset($module->restore) && $module->restore == 1) {
15 //Include module library
16 include_once("$CFG->dirroot/mod/$name/lib.php");
17 //If module_refresh_events exists
18 $function_name = $name."_refresh_events";
19 if (function_exists($function_name)) {
20 $status = $function_name($restore->course_id);
24 return $status;
27 //Called to set up any course-format specific data that may be in the file
28 function restore_set_format_data($restore,$xml_file) {
29 global $CFG, $DB;
31 $status = true;
32 //Check it exists
33 if (!file_exists($xml_file)) {
34 return false;
36 //Load data from XML to info
37 if(!($info = restore_read_xml_formatdata($xml_file))) {
38 return false;
41 //Process format data if there is any
42 if (isset($info->format_data)) {
43 if(!$format=$DB->get_field('course','format', array('id'=>$restore->course_id))) {
44 return false;
46 // If there was any data then it must have a restore method
47 $file=$CFG->dirroot."/course/format/$format/restorelib.php";
48 if(!file_exists($file)) {
49 return false;
51 require_once($file);
52 $function=$format.'_restore_format_data';
53 if(!function_exists($function)) {
54 return false;
56 return $function($restore,$info->format_data);
59 // If we got here then there's no data, but that's cool
60 return true;
63 //This function creates all the structures messages and contacts
64 function restore_create_messages($restore,$xml_file) {
65 global $CFG, $DB;
67 $status = true;
68 //Check it exists
69 if (!file_exists($xml_file)) {
70 $status = false;
72 //Get info from xml
73 if ($status) {
74 //info will contain the id and name of every table
75 //(message, message_read and message_contacts)
76 //in backup_ids->info will be the real info (serialized)
77 $info = restore_read_xml_messages($restore,$xml_file);
79 //If we have info, then process messages & contacts
80 if ($info > 0) {
81 //Count how many we have
82 $unreadcount = $DB->count_records ('backup_ids', array('backup_code'=>$restore->backup_unique_code, 'table_name'=>'message'));
83 $readcount = $DB->count_records ('backup_ids', array('backup_code'=>$restore->backup_unique_code, 'table_name'=>'message_read'));
84 $contactcount = $DB->count_records ('backup_ids', array('backup_code'=>$restore->backup_unique_code, 'table_name'=>'message_contacts'));
85 if ($unreadcount || $readcount || $contactcount) {
86 //Start ul
87 if (!defined('RESTORE_SILENTLY')) {
88 echo '<ul>';
90 //Number of records to get in every chunk
91 $recordset_size = 4;
93 //Process unread
94 if ($unreadcount) {
95 if (!defined('RESTORE_SILENTLY')) {
96 echo '<li>'.get_string('unreadmessages','message').'</li>';
98 $counter = 0;
99 while ($counter < $unreadcount) {
100 //Fetch recordset_size records in each iteration
101 $recs = $DB->get_records("backup_ids", array('table_name'=>'message', 'backup_code'=>$restore->backup_unique_code),"old_id","old_id",$counter,$recordset_size);
102 if ($recs) {
103 foreach ($recs as $rec) {
104 //Get the full record from backup_ids
105 $data = backup_getid($restore->backup_unique_code,"message",$rec->old_id);
106 if ($data) {
107 //Now get completed xmlized object
108 $info = $data->info;
109 //traverse_xmlize($info); //Debug
110 //print_object ($GLOBALS['traverse_array']); //Debug
111 //$GLOBALS['traverse_array']=""; //Debug
112 //Now build the MESSAGE record structure
113 $dbrec = new stdClass();
114 $dbrec->useridfrom = backup_todb($info['MESSAGE']['#']['USERIDFROM']['0']['#']);
115 $dbrec->useridto = backup_todb($info['MESSAGE']['#']['USERIDTO']['0']['#']);
116 $dbrec->message = backup_todb($info['MESSAGE']['#']['MESSAGE']['0']['#']);
117 $dbrec->format = backup_todb($info['MESSAGE']['#']['FORMAT']['0']['#']);
118 $dbrec->timecreated = backup_todb($info['MESSAGE']['#']['TIMECREATED']['0']['#']);
119 $dbrec->messagetype = backup_todb($info['MESSAGE']['#']['MESSAGETYPE']['0']['#']);
120 //We have to recode the useridfrom field
121 $user = backup_getid($restore->backup_unique_code,"user",$dbrec->useridfrom);
122 if ($user) {
123 //echo "User ".$dbrec->useridfrom." to user ".$user->new_id."<br />"; //Debug
124 $dbrec->useridfrom = $user->new_id;
126 //We have to recode the useridto field
127 $user = backup_getid($restore->backup_unique_code,"user",$dbrec->useridto);
128 if ($user) {
129 //echo "User ".$dbrec->useridto." to user ".$user->new_id."<br />"; //Debug
130 $dbrec->useridto = $user->new_id;
132 //Check if the record doesn't exist in DB!
133 $exist = $DB->get_record('message', array('useridfrom'=>$dbrec->useridfrom,
134 'useridto'=>$dbrec->useridto,
135 'timecreated'=>$dbrec->timecreated));
136 if (!$exist) {
137 //Not exist. Insert
138 $status = $DB->insert_record('message',$dbrec);
139 } else {
140 //Duplicate. Do nothing
143 //Do some output
144 $counter++;
145 if ($counter % 10 == 0) {
146 if (!defined('RESTORE_SILENTLY')) {
147 echo ".";
148 if ($counter % 200 == 0) {
149 echo "<br />";
152 backup_flush(300);
159 //Process read
160 if ($readcount) {
161 if (!defined('RESTORE_SILENTLY')) {
162 echo '<li>'.get_string('readmessages','message').'</li>';
164 $counter = 0;
165 while ($counter < $readcount) {
166 //Fetch recordset_size records in each iteration
167 $recs = $DB->get_records("backup_ids", array('table_name'=>'message_read', 'backup_code'=>$restore->backup_unique_code),"old_id","old_id",$counter,$recordset_size);
168 if ($recs) {
169 foreach ($recs as $rec) {
170 //Get the full record from backup_ids
171 $data = backup_getid($restore->backup_unique_code,"message_read",$rec->old_id);
172 if ($data) {
173 //Now get completed xmlized object
174 $info = $data->info;
175 //traverse_xmlize($info); //Debug
176 //print_object ($GLOBALS['traverse_array']); //Debug
177 //$GLOBALS['traverse_array']=""; //Debug
178 //Now build the MESSAGE_READ record structure
179 $dbrec->useridfrom = backup_todb($info['MESSAGE']['#']['USERIDFROM']['0']['#']);
180 $dbrec->useridto = backup_todb($info['MESSAGE']['#']['USERIDTO']['0']['#']);
181 $dbrec->message = backup_todb($info['MESSAGE']['#']['MESSAGE']['0']['#']);
182 $dbrec->format = backup_todb($info['MESSAGE']['#']['FORMAT']['0']['#']);
183 $dbrec->timecreated = backup_todb($info['MESSAGE']['#']['TIMECREATED']['0']['#']);
184 $dbrec->messagetype = backup_todb($info['MESSAGE']['#']['MESSAGETYPE']['0']['#']);
185 $dbrec->timeread = backup_todb($info['MESSAGE']['#']['TIMEREAD']['0']['#']);
186 $dbrec->mailed = backup_todb($info['MESSAGE']['#']['MAILED']['0']['#']);
187 //We have to recode the useridfrom field
188 $user = backup_getid($restore->backup_unique_code,"user",$dbrec->useridfrom);
189 if ($user) {
190 //echo "User ".$dbrec->useridfrom." to user ".$user->new_id."<br />"; //Debug
191 $dbrec->useridfrom = $user->new_id;
193 //We have to recode the useridto field
194 $user = backup_getid($restore->backup_unique_code,"user",$dbrec->useridto);
195 if ($user) {
196 //echo "User ".$dbrec->useridto." to user ".$user->new_id."<br />"; //Debug
197 $dbrec->useridto = $user->new_id;
199 //Check if the record doesn't exist in DB!
200 $exist = $DB->get_record('message_read', array('useridfrom'=>$dbrec->useridfrom,
201 'useridto'=>$dbrec->useridto,
202 'timecreated'=>$dbrec->timecreated));
203 if (!$exist) {
204 //Not exist. Insert
205 $status = $DB->insert_record('message_read',$dbrec);
206 } else {
207 //Duplicate. Do nothing
210 //Do some output
211 $counter++;
212 if ($counter % 10 == 0) {
213 if (!defined('RESTORE_SILENTLY')) {
214 echo ".";
215 if ($counter % 200 == 0) {
216 echo "<br />";
219 backup_flush(300);
226 //Process contacts
227 if ($contactcount) {
228 if (!defined('RESTORE_SILENTLY')) {
229 echo '<li>'.textlib::strtolower(get_string('contacts','message')).'</li>';
231 $counter = 0;
232 while ($counter < $contactcount) {
233 //Fetch recordset_size records in each iteration
234 $recs = $DB->get_records("backup_ids", array('table_name'=>'message_contacts', 'backup_code'=>$restore->backup_unique_code),"old_id","old_id",$counter,$recordset_size);
235 if ($recs) {
236 foreach ($recs as $rec) {
237 //Get the full record from backup_ids
238 $data = backup_getid($restore->backup_unique_code,"message_contacts",$rec->old_id);
239 if ($data) {
240 //Now get completed xmlized object
241 $info = $data->info;
242 //traverse_xmlize($info); //Debug
243 //print_object ($GLOBALS['traverse_array']); //Debug
244 //$GLOBALS['traverse_array']=""; //Debug
245 //Now build the MESSAGE_CONTACTS record structure
246 $dbrec->userid = backup_todb($info['CONTACT']['#']['USERID']['0']['#']);
247 $dbrec->contactid = backup_todb($info['CONTACT']['#']['CONTACTID']['0']['#']);
248 $dbrec->blocked = backup_todb($info['CONTACT']['#']['BLOCKED']['0']['#']);
249 //We have to recode the userid field
250 $user = backup_getid($restore->backup_unique_code,"user",$dbrec->userid);
251 if ($user) {
252 //echo "User ".$dbrec->userid." to user ".$user->new_id."<br />"; //Debug
253 $dbrec->userid = $user->new_id;
255 //We have to recode the contactid field
256 $user = backup_getid($restore->backup_unique_code,"user",$dbrec->contactid);
257 if ($user) {
258 //echo "User ".$dbrec->contactid." to user ".$user->new_id."<br />"; //Debug
259 $dbrec->contactid = $user->new_id;
261 //Check if the record doesn't exist in DB!
262 $exist = $DB->get_record('message_contacts', array('userid'=>$dbrec->userid,
263 'contactid'=>$dbrec->contactid));
264 if (!$exist) {
265 //Not exist. Insert
266 $status = $DB->insert_record('message_contacts',$dbrec);
267 } else {
268 //Duplicate. Do nothing
271 //Do some output
272 $counter++;
273 if ($counter % 10 == 0) {
274 if (!defined('RESTORE_SILENTLY')) {
275 echo ".";
276 if ($counter % 200 == 0) {
277 echo "<br />";
280 backup_flush(300);
286 if (!defined('RESTORE_SILENTLY')) {
287 //End ul
288 echo '</ul>';
294 return $status;
297 //This function creates all the structures for blogs and blog tags
298 function restore_create_blogs($restore,$xml_file) {
299 global $CFG, $DB;
301 $status = true;
302 //Check it exists
303 if (!file_exists($xml_file)) {
304 $status = false;
306 //Get info from xml
307 if ($status) {
308 //info will contain the number of blogs in the backup file
309 //in backup_ids->info will be the real info (serialized)
310 $info = restore_read_xml_blogs($restore,$xml_file);
312 //If we have info, then process blogs & blog_tags
313 if ($info > 0) {
314 //Count how many we have
315 $blogcount = $DB->count_records('backup_ids', array('backup_code'=>$restore->backup_unique_code, 'table_name'=>'blog'));
316 if ($blogcount) {
317 //Number of records to get in every chunk
318 $recordset_size = 4;
320 //Process blog
321 if ($blogcount) {
322 $counter = 0;
323 while ($counter < $blogcount) {
324 //Fetch recordset_size records in each iteration
325 $recs = $DB->get_records("backup_ids", array("table_name"=>'blog', 'backup_code'=>$restore->backup_unique_code),"old_id","old_id",$counter,$recordset_size);
326 if ($recs) {
327 foreach ($recs as $rec) {
328 //Get the full record from backup_ids
329 $data = backup_getid($restore->backup_unique_code,"blog",$rec->old_id);
330 if ($data) {
331 //Now get completed xmlized object
332 $info = $data->info;
333 //traverse_xmlize($info); //Debug
334 //print_object ($GLOBALS['traverse_array']); //Debug
335 //$GLOBALS['traverse_array']=""; //Debug
336 //Now build the BLOG record structure
337 $dbrec = new stdClass();
338 $dbrec->module = backup_todb($info['BLOG']['#']['MODULE']['0']['#']);
339 $dbrec->userid = backup_todb($info['BLOG']['#']['USERID']['0']['#']);
340 $dbrec->courseid = backup_todb($info['BLOG']['#']['COURSEID']['0']['#']);
341 $dbrec->groupid = backup_todb($info['BLOG']['#']['GROUPID']['0']['#']);
342 $dbrec->moduleid = backup_todb($info['BLOG']['#']['MODULEID']['0']['#']);
343 $dbrec->coursemoduleid = backup_todb($info['BLOG']['#']['COURSEMODULEID']['0']['#']);
344 $dbrec->subject = backup_todb($info['BLOG']['#']['SUBJECT']['0']['#']);
345 $dbrec->summary = backup_todb($info['BLOG']['#']['SUMMARY']['0']['#']);
346 $dbrec->content = backup_todb($info['BLOG']['#']['CONTENT']['0']['#']);
347 $dbrec->uniquehash = backup_todb($info['BLOG']['#']['UNIQUEHASH']['0']['#']);
348 $dbrec->rating = backup_todb($info['BLOG']['#']['RATING']['0']['#']);
349 $dbrec->format = backup_todb($info['BLOG']['#']['FORMAT']['0']['#']);
350 $dbrec->attachment = backup_todb($info['BLOG']['#']['ATTACHMENT']['0']['#']);
351 $dbrec->publishstate = backup_todb($info['BLOG']['#']['PUBLISHSTATE']['0']['#']);
352 $dbrec->lastmodified = backup_todb($info['BLOG']['#']['LASTMODIFIED']['0']['#']);
353 $dbrec->created = backup_todb($info['BLOG']['#']['CREATED']['0']['#']);
354 $dbrec->usermodified = backup_todb($info['BLOG']['#']['USERMODIFIED']['0']['#']);
356 //We have to recode the userid field
357 $user = backup_getid($restore->backup_unique_code,"user",$dbrec->userid);
358 if ($user) {
359 //echo "User ".$dbrec->userid." to user ".$user->new_id."<br />"; //Debug
360 $dbrec->userid = $user->new_id;
363 //Check if the record doesn't exist in DB!
364 $exist = $DB->get_record('post', array('userid'=>$dbrec->userid,
365 'subject'=>$dbrec->subject,
366 'created'=>$dbrec->created));
367 $newblogid = 0;
368 if (!$exist) {
369 //Not exist. Insert
370 $newblogid = $DB->insert_record('post',$dbrec);
373 //Going to restore related tags. Check they are enabled and we have inserted a blog
374 if ($CFG->usetags && $newblogid) {
375 //Look for tags in this blog
376 if (isset($info['BLOG']['#']['BLOG_TAGS']['0']['#']['BLOG_TAG'])) {
377 $tagsarr = $info['BLOG']['#']['BLOG_TAGS']['0']['#']['BLOG_TAG'];
378 //Iterate over tags
379 $tags = array();
380 $sizetagsarr = sizeof($tagsarr);
381 for ($i = 0; $i < $sizetagsarr; $i++) {
382 $tag_info = $tagsarr[$i];
383 ///traverse_xmlize($tag_info); //Debug
384 ///print_object ($GLOBALS['traverse_array']); //Debug
385 ///$GLOBALS['traverse_array']=""; //Debug
387 $name = backup_todb($tag_info['#']['NAME']['0']['#']);
388 $rawname = backup_todb($tag_info['#']['RAWNAME']['0']['#']);
390 $tags[] = $rawname; //Rawname is all we need
392 tag_set('post', $newblogid, $tags); //Add all the tags in one API call
396 //Do some output
397 $counter++;
398 if ($counter % 10 == 0) {
399 if (!defined('RESTORE_SILENTLY')) {
400 echo ".";
401 if ($counter % 200 == 0) {
402 echo "<br />";
405 backup_flush(300);
415 return $status;
418 //This function creates all the course events
419 function restore_create_events($restore,$xml_file) {
420 global $DB;
422 global $CFG, $SESSION;
424 $status = true;
425 //Check it exists
426 if (!file_exists($xml_file)) {
427 $status = false;
429 //Get info from xml
430 if ($status) {
431 //events will contain the old_id of every event
432 //in backup_ids->info will be the real info (serialized)
433 $events = restore_read_xml_events($restore,$xml_file);
436 //Get admin->id for later use
437 $admin = get_admin();
438 $adminid = $admin->id;
440 //Now, if we have anything in events, we have to restore that
441 //events
442 if ($events) {
443 if ($events !== true) {
444 //Iterate over each event
445 foreach ($events as $event) {
446 //Get record from backup_ids
447 $data = backup_getid($restore->backup_unique_code,"event",$event->id);
448 //Init variables
449 $create_event = false;
451 if ($data) {
452 //Now get completed xmlized object
453 $info = $data->info;
454 //traverse_xmlize($info); //Debug
455 //print_object ($GLOBALS['traverse_array']); //Debug
456 //$GLOBALS['traverse_array']=""; //Debug
458 //if necessary, write to restorelog and adjust date/time fields
459 if ($restore->course_startdateoffset) {
460 restore_log_date_changes('Events', $restore, $info['EVENT']['#'], array('TIMESTART'));
463 //Now build the EVENT record structure
464 $eve = new stdClass();
465 $eve->name = backup_todb($info['EVENT']['#']['NAME']['0']['#']);
466 $eve->description = backup_todb($info['EVENT']['#']['DESCRIPTION']['0']['#']);
467 $eve->format = backup_todb($info['EVENT']['#']['FORMAT']['0']['#']);
468 $eve->courseid = $restore->course_id;
469 $eve->groupid = backup_todb($info['EVENT']['#']['GROUPID']['0']['#']);
470 $eve->userid = backup_todb($info['EVENT']['#']['USERID']['0']['#']);
471 $eve->repeatid = backup_todb($info['EVENT']['#']['REPEATID']['0']['#']);
472 $eve->modulename = "";
473 if (!empty($info['EVENT']['#']['MODULENAME'])) {
474 $eve->modulename = backup_todb($info['EVENT']['#']['MODULENAME']['0']['#']);
476 $eve->instance = 0;
477 $eve->eventtype = backup_todb($info['EVENT']['#']['EVENTTYPE']['0']['#']);
478 $eve->timestart = backup_todb($info['EVENT']['#']['TIMESTART']['0']['#']);
479 $eve->timeduration = backup_todb($info['EVENT']['#']['TIMEDURATION']['0']['#']);
480 $eve->visible = backup_todb($info['EVENT']['#']['VISIBLE']['0']['#']);
481 $eve->timemodified = backup_todb($info['EVENT']['#']['TIMEMODIFIED']['0']['#']);
483 //Now search if that event exists (by name, description, timestart fields) in
484 //restore->course_id course
485 //Going to compare LOB columns so, use the cross-db sql_compare_text() in both sides.
486 $compare_description_clause = $DB->sql_compare_text('description') . "=" . $DB->sql_compare_text("'" . $eve->description . "'");
487 $eve_db = $DB->get_record_select('event',
488 "courseid = ? AND name = ? AND $compare_description_clause AND timestart = ?",
489 array($eve->courseid, $eve->name, $eve->timestart));
490 //If it doesn't exist, create
491 if (!$eve_db) {
492 $create_event = true;
494 //If we must create the event
495 if ($create_event) {
497 //We must recode the userid
498 $user = backup_getid($restore->backup_unique_code,"user",$eve->userid);
499 if ($user) {
500 $eve->userid = $user->new_id;
501 } else {
502 //Assign it to admin
503 $eve->userid = $adminid;
506 //We have to recode the groupid field
507 $group = backup_getid($restore->backup_unique_code,"groups",$eve->groupid);
508 if ($group) {
509 $eve->groupid = $group->new_id;
510 } else {
511 //Assign it to group 0
512 $eve->groupid = 0;
515 //The structure is equal to the db, so insert the event
516 $newid = $DB->insert_record ("event",$eve);
518 //We must recode the repeatid if the event has it
519 //The repeatid now refers to the id of the original event. (see Bug#5956)
520 if ($newid && !empty($eve->repeatid)) {
521 $repeat_rec = backup_getid($restore->backup_unique_code,"event_repeatid",$eve->repeatid);
522 if ($repeat_rec) { //Exists, so use it...
523 $eve->repeatid = $repeat_rec->new_id;
524 } else { //Doesn't exists, calculate the next and save it
525 $oldrepeatid = $eve->repeatid;
526 $eve->repeatid = $newid;
527 backup_putid($restore->backup_unique_code,"event_repeatid", $oldrepeatid, $eve->repeatid);
529 $eve->id = $newid;
530 // update the record to contain the correct repeatid
531 $DB->update_record('event',$eve);
533 } else {
534 //get current event id
535 $newid = $eve_db->id;
537 if ($newid) {
538 //We have the newid, update backup_ids
539 backup_putid($restore->backup_unique_code,"event",
540 $event->id, $newid);
545 } else {
546 $status = false;
548 return $status;
551 function restore_execute(&$restore,$info,$course_header,&$errorstr) {
552 global $CFG, $USER, $DB, $OUTPUT;
554 $status = true;
556 //Now create events as needed
557 if ($status) {
558 if (!defined('RESTORE_SILENTLY')) {
559 echo "<li>".get_string("creatingevents");
561 if (!$status = restore_create_events($restore,$xml_file)) {
562 if (!defined('RESTORE_SILENTLY')) {
563 echo $OUTPUT->notification("Could not restore course events!");
564 } else {
565 $errorstr = "Could not restore course events!";
566 return false;
569 if (!defined('RESTORE_SILENTLY')) {
570 echo '</li>';
574 if ($status) {
575 //If we are deleting and bringing into a course or making a new course, same situation
576 if ($restore->restoreto == RESTORETO_CURRENT_DELETING ||
577 $restore->restoreto == RESTORETO_EXISTING_DELETING ||
578 $restore->restoreto == RESTORETO_NEW_COURSE) {
579 if (!defined('RESTORE_SILENTLY')) {
580 echo '<li>'.get_string('courseformatdata');
582 if (!$status = restore_set_format_data($restore, $xml_file)) {
583 $error = "Error while setting the course format data";
584 if (!defined('RESTORE_SILENTLY')) {
585 echo $OUTPUT->notification($error);
586 } else {
587 $errorstr=$error;
588 return false;
591 if (!defined('RESTORE_SILENTLY')) {
592 echo '</li>';
597 //Now, if all is OK, adjust activity events
598 if ($status) {
599 if (!defined('RESTORE_SILENTLY')) {
600 echo "<li>".get_string("refreshingevents");
602 if (!$status = restore_refresh_events($restore)) {
603 if (!defined('RESTORE_SILENTLY')) {
604 echo $OUTPUT->notification("Could not refresh events for activities!");
605 } else {
606 $errorstr = "Could not refresh events for activities!";
607 return false;
610 if (!defined('RESTORE_SILENTLY')) {
611 echo '</li>';