| [ Index ] |
PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008] |
[Summary view] [Print] [Text view]
1 <?php //$Id: restorelib.php,v 1.283.2.53 2008/08/21 11:26:32 mudrd8mz Exp $ 2 //Functions used in restore 3 4 require_once($CFG->libdir.'/gradelib.php'); 5 6 /** 7 * Group backup/restore constants, 0. 8 */ 9 define('RESTORE_GROUPS_NONE', 0); 10 11 /** 12 * Group backup/restore constants, 1. 13 */ 14 define('RESTORE_GROUPS_ONLY', 1); 15 16 /** 17 * Group backup/restore constants, 2. 18 */ 19 define('RESTORE_GROUPINGS_ONLY', 2); 20 21 /** 22 * Group backup/restore constants, course/all. 23 */ 24 define('RESTORE_GROUPS_GROUPINGS', 3); 25 26 //This function unzips a zip file in the same directory that it is 27 //It automatically uses pclzip or command line unzip 28 function restore_unzip ($file) { 29 30 return unzip_file($file, '', false); 31 32 } 33 34 //This function checks if moodle.xml seems to be a valid xml file 35 //(exists, has an xml header and a course main tag 36 function restore_check_moodle_file ($file) { 37 38 $status = true; 39 40 //Check if it exists 41 if ($status = is_file($file)) { 42 //Open it and read the first 200 bytes (chars) 43 $handle = fopen ($file, "r"); 44 $first_chars = fread($handle,200); 45 $status = fclose ($handle); 46 //Chek if it has the requires strings 47 if ($status) { 48 $status = strpos($first_chars,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); 49 if ($status !== false) { 50 $status = strpos($first_chars,"<MOODLE_BACKUP>"); 51 } 52 } 53 } 54 55 return $status; 56 } 57 58 //This function iterates over all modules in backup file, searching for a 59 //MODNAME_refresh_events() to execute. Perhaps it should ve moved to central Moodle... 60 function restore_refresh_events($restore) { 61 62 global $CFG; 63 $status = true; 64 65 //Take all modules in backup 66 $modules = $restore->mods; 67 //Iterate 68 foreach($modules as $name => $module) { 69 //Only if the module is being restored 70 if (isset($module->restore) && $module->restore == 1) { 71 //Include module library 72 include_once("$CFG->dirroot/mod/$name/lib.php"); 73 //If module_refresh_events exists 74 $function_name = $name."_refresh_events"; 75 if (function_exists($function_name)) { 76 $status = $function_name($restore->course_id); 77 } 78 } 79 } 80 return $status; 81 } 82 83 //This function makes all the necessary calls to xxxx_decode_content_links_caller() 84 //function in each module, passing them the desired contents to be decoded 85 //from backup format to destination site/course in order to mantain inter-activities 86 //working in the backup/restore process 87 function restore_decode_content_links($restore) { 88 global $CFG; 89 90 $status = true; 91 92 if (!defined('RESTORE_SILENTLY')) { 93 echo "<ul>"; 94 } 95 96 // Recode links in the course summary. 97 if (!defined('RESTORE_SILENTLY')) { 98 echo '<li>' . get_string('from') . ' ' . get_string('course'); 99 } 100 $course = get_record('course', 'id', $restore->course_id, '', '', '', '', 'id,summary'); 101 $coursesummary = restore_decode_content_links_worker($course->summary, $restore); 102 if ($coursesummary != $course->summary) { 103 $course->summary = addslashes($coursesummary); 104 if (!update_record('course', $course)) { 105 $status = false; 106 } 107 } 108 if (!defined('RESTORE_SILENTLY')) { 109 echo '</li>'; 110 } 111 112 // Recode links in section summaries. 113 $sections = get_records('course_sections', 'course', $restore->course_id, 'id', 'id,summary'); 114 if ($sections) { 115 if (!defined('RESTORE_SILENTLY')) { 116 echo '<li>' . get_string('from') . ' ' . get_string('sections'); 117 } 118 foreach ($sections as $section) { 119 $sectionsummary = restore_decode_content_links_worker($section->summary, $restore); 120 if ($sectionsummary != $section->summary) { 121 $section->summary = addslashes($sectionsummary); 122 if (!update_record('course_sections', $section)) { 123 $status = false; 124 } 125 } 126 } 127 if (!defined('RESTORE_SILENTLY')) { 128 echo '</li>'; 129 } 130 } 131 132 // Restore links in modules. 133 foreach ($restore->mods as $name => $info) { 134 //If the module is being restored 135 if (isset($info->restore) && $info->restore == 1) { 136 //Check if the xxxx_decode_content_links_caller exists 137 include_once("$CFG->dirroot/mod/$name/restorelib.php"); 138 $function_name = $name."_decode_content_links_caller"; 139 if (function_exists($function_name)) { 140 if (!defined('RESTORE_SILENTLY')) { 141 echo "<li>".get_string ("from")." ".get_string("modulenameplural",$name); 142 } 143 $status = $function_name($restore) && $status; 144 if (!defined('RESTORE_SILENTLY')) { 145 echo '</li>'; 146 } 147 } 148 } 149 } 150 151 // Process all html text also in blocks too 152 if (!defined('RESTORE_SILENTLY')) { 153 echo '<li>'.get_string ('from').' '.get_string('blocks'); 154 } 155 156 if ($blocks = get_records('block', 'visible', 1)) { 157 foreach ($blocks as $block) { 158 if ($blockobject = block_instance($block->name)) { 159 $blockobject->decode_content_links_caller($restore); 160 } 161 } 162 } 163 164 if (!defined('RESTORE_SILENTLY')) { 165 echo '</li>'; 166 } 167 168 // Restore links in questions. 169 require_once("$CFG->dirroot/question/restorelib.php"); 170 if (!defined('RESTORE_SILENTLY')) { 171 echo '<li>' . get_string('from') . ' ' . get_string('questions', 'quiz'); 172 } 173 $status = question_decode_content_links_caller($restore) && $status; 174 if (!defined('RESTORE_SILENTLY')) { 175 echo '</li>'; 176 } 177 178 if (!defined('RESTORE_SILENTLY')) { 179 echo "</ul>"; 180 } 181 182 return $status; 183 } 184 185 //This function is called from all xxxx_decode_content_links_caller(), 186 //its task is to ask all modules (maybe other linkable objects) to restore 187 //links to them. 188 function restore_decode_content_links_worker($content,$restore) { 189 foreach($restore->mods as $name => $info) { 190 $function_name = $name."_decode_content_links"; 191 if (function_exists($function_name)) { 192 $content = $function_name($content,$restore); 193 } 194 } 195 196 // For each block, call its encode_content_links method 197 static $blockobjects = null; 198 if (!isset($blockobjects)) { 199 $blockobjects = array(); 200 if ($blocks = get_records('block', 'visible', 1)) { 201 foreach ($blocks as $block) { 202 if ($blockobject = block_instance($block->name)) { 203 $blockobjects[] = $blockobject; 204 } 205 } 206 } 207 } 208 209 foreach ($blockobjects as $blockobject) { 210 $content = $blockobject->decode_content_links($content,$restore); 211 } 212 213 return $content; 214 } 215 216 //This function converts all the wiki texts in the restored course 217 //to the Markdown format. Used only for backup files prior 2005041100. 218 //It calls every module xxxx_convert_wiki2markdown function 219 function restore_convert_wiki2markdown($restore) { 220 221 $status = true; 222 223 if (!defined('RESTORE_SILENTLY')) { 224 echo "<ul>"; 225 } 226 foreach ($restore->mods as $name => $info) { 227 //If the module is being restored 228 if ($info->restore == 1) { 229 //Check if the xxxx_restore_wiki2markdown exists 230 $function_name = $name."_restore_wiki2markdown"; 231 if (function_exists($function_name)) { 232 $status = $function_name($restore); 233 if (!defined('RESTORE_SILENTLY')) { 234 echo "<li>".get_string("modulenameplural",$name); 235 echo '</li>'; 236 } 237 } 238 } 239 } 240 if (!defined('RESTORE_SILENTLY')) { 241 echo "</ul>"; 242 } 243 return $status; 244 } 245 246 //This function receives a wiki text in the restore process and 247 //return it with every link to modules " modulename:moduleid" 248 //converted if possible. See the space before modulename!! 249 function restore_decode_wiki_content($content,$restore) { 250 251 global $CFG; 252 253 $result = $content; 254 255 $searchstring='/ ([a-zA-Z]+):([0-9]+)\(([^)]+)\)/'; 256 //We look for it 257 preg_match_all($searchstring,$content,$foundset); 258 //If found, then we are going to look for its new id (in backup tables) 259 if ($foundset[0]) { 260 //print_object($foundset); //Debug 261 //Iterate over foundset[2]. They are the old_ids 262 foreach($foundset[2] as $old_id) { 263 //We get the needed variables here (course id) 264 $rec = backup_getid($restore->backup_unique_code,"course_modules",$old_id); 265 //Personalize the searchstring 266 $searchstring='/ ([a-zA-Z]+):'.$old_id.'\(([^)]+)\)/'; 267 //If it is a link to this course, update the link to its new location 268 if($rec->new_id) { 269 //Now replace it 270 $result= preg_replace($searchstring,' $1:'.$rec->new_id.'($2)',$result); 271 } else { 272 //It's a foreign link so redirect it to its original URL 273 $result= preg_replace($searchstring,$restore->original_wwwroot.'/mod/$1/view.php?id='.$old_id.'($2)',$result); 274 } 275 } 276 } 277 return $result; 278 } 279 280 281 //This function read the xml file and store it data from the info zone in an object 282 function restore_read_xml_info ($xml_file) { 283 284 //We call the main read_xml function, with todo = INFO 285 $info = restore_read_xml ($xml_file,"INFO",false); 286 287 return $info; 288 } 289 290 //This function read the xml file and store it data from the course header zone in an object 291 function restore_read_xml_course_header ($xml_file) { 292 293 //We call the main read_xml function, with todo = COURSE_HEADER 294 $info = restore_read_xml ($xml_file,"COURSE_HEADER",false); 295 296 return $info; 297 } 298 299 //This function read the xml file and store its data from the blocks in a object 300 function restore_read_xml_blocks ($restore, $xml_file) { 301 302 //We call the main read_xml function, with todo = BLOCKS 303 $info = restore_read_xml ($xml_file,'BLOCKS',$restore); 304 305 return $info; 306 } 307 308 //This function read the xml file and store its data from the sections in a object 309 function restore_read_xml_sections ($xml_file) { 310 311 //We call the main read_xml function, with todo = SECTIONS 312 $info = restore_read_xml ($xml_file,"SECTIONS",false); 313 314 return $info; 315 } 316 317 //This function read the xml file and store its data from the course format in an object 318 function restore_read_xml_formatdata ($xml_file) { 319 320 //We call the main read_xml function, with todo = FORMATDATA 321 $info = restore_read_xml ($xml_file,'FORMATDATA',false); 322 323 return $info; 324 } 325 326 //This function read the xml file and store its data from the metacourse in a object 327 function restore_read_xml_metacourse ($xml_file) { 328 329 //We call the main read_xml function, with todo = METACOURSE 330 $info = restore_read_xml ($xml_file,"METACOURSE",false); 331 332 return $info; 333 } 334 335 //This function read the xml file and store its data from the gradebook in a object 336 function restore_read_xml_gradebook ($restore, $xml_file) { 337 338 //We call the main read_xml function, with todo = GRADEBOOK 339 $info = restore_read_xml ($xml_file,"GRADEBOOK",$restore); 340 341 return $info; 342 } 343 344 //This function read the xml file and store its data from the users in 345 //backup_ids->info db (and user's id in $info) 346 function restore_read_xml_users ($restore,$xml_file) { 347 348 //We call the main read_xml function, with todo = USERS 349 $info = restore_read_xml ($xml_file,"USERS",$restore); 350 351 return $info; 352 } 353 354 //This function read the xml file and store its data from the messages in 355 //backup_ids->message backup_ids->message_read and backup_ids->contact and db (and their counters in info) 356 function restore_read_xml_messages ($restore,$xml_file) { 357 358 //We call the main read_xml function, with todo = MESSAGES 359 $info = restore_read_xml ($xml_file,"MESSAGES",$restore); 360 361 return $info; 362 } 363 364 //This function read the xml file and store its data from the blogs in 365 //backup_ids->blog and backup_ids->blog_tag and db (and their counters in info) 366 function restore_read_xml_blogs ($restore,$xml_file) { 367 368 //We call the main read_xml function, with todo = BLOGS 369 $info = restore_read_xml ($xml_file,"BLOGS",$restore); 370 371 return $info; 372 } 373 374 375 //This function read the xml file and store its data from the questions in 376 //backup_ids->info db (and category's id in $info) 377 function restore_read_xml_questions ($restore,$xml_file) { 378 379 //We call the main read_xml function, with todo = QUESTIONS 380 $info = restore_read_xml ($xml_file,"QUESTIONS",$restore); 381 382 return $info; 383 } 384 385 //This function read the xml file and store its data from the scales in 386 //backup_ids->info db (and scale's id in $info) 387 function restore_read_xml_scales ($restore,$xml_file) { 388 389 //We call the main read_xml function, with todo = SCALES 390 $info = restore_read_xml ($xml_file,"SCALES",$restore); 391 392 return $info; 393 } 394 395 //This function read the xml file and store its data from the groups in 396 //backup_ids->info db (and group's id in $info) 397 function restore_read_xml_groups ($restore,$xml_file) { 398 399 //We call the main read_xml function, with todo = GROUPS 400 $info = restore_read_xml ($xml_file,"GROUPS",$restore); 401 402 return $info; 403 } 404 405 //This function read the xml file and store its data from the groupings in 406 //backup_ids->info db (and grouping's id in $info) 407 function restore_read_xml_groupings ($restore,$xml_file) { 408 409 //We call the main read_xml function, with todo = GROUPINGS 410 $info = restore_read_xml ($xml_file,"GROUPINGS",$restore); 411 412 return $info; 413 } 414 415 //This function read the xml file and store its data from the groupings in 416 //backup_ids->info db (and grouping's id in $info) 417 function restore_read_xml_groupings_groups ($restore,$xml_file) { 418 419 //We call the main read_xml function, with todo = GROUPINGS 420 $info = restore_read_xml ($xml_file,"GROUPINGSGROUPS",$restore); 421 422 return $info; 423 } 424 425 //This function read the xml file and store its data from the events (course) in 426 //backup_ids->info db (and event's id in $info) 427 function restore_read_xml_events ($restore,$xml_file) { 428 429 //We call the main read_xml function, with todo = EVENTS 430 $info = restore_read_xml ($xml_file,"EVENTS",$restore); 431 432 return $info; 433 } 434 435 //This function read the xml file and store its data from the modules in 436 //backup_ids->info 437 function restore_read_xml_modules ($restore,$xml_file) { 438 439 //We call the main read_xml function, with todo = MODULES 440 $info = restore_read_xml ($xml_file,"MODULES",$restore); 441 442 return $info; 443 } 444 445 //This function read the xml file and store its data from the logs in 446 //backup_ids->info 447 function restore_read_xml_logs ($restore,$xml_file) { 448 449 //We call the main read_xml function, with todo = LOGS 450 $info = restore_read_xml ($xml_file,"LOGS",$restore); 451 452 return $info; 453 } 454 455 function restore_read_xml_roles ($xml_file) { 456 //We call the main read_xml function, with todo = ROLES 457 $info = restore_read_xml ($xml_file,"ROLES",false); 458 459 return $info; 460 } 461 462 //This function prints the contents from the info parammeter passed 463 function restore_print_info ($info) { 464 465 global $CFG; 466 467 $status = true; 468 if ($info) { 469 $table = new object(); 470 //This is tha align to every ingo table 471 $table->align = array ("right","left"); 472 //This is the nowrap clause 473 $table->wrap = array ("","nowrap"); 474 //The width 475 $table->width = "70%"; 476 //Put interesting info in table 477 //The backup original name 478 $tab[0][0] = "<b>".get_string("backuporiginalname").":</b>"; 479 $tab[0][1] = $info->backup_name; 480 //The moodle version 481 $tab[1][0] = "<b>".get_string("moodleversion").":</b>"; 482 $tab[1][1] = $info->backup_moodle_release." (".$info->backup_moodle_version.")"; 483 //The backup version 484 $tab[2][0] = "<b>".get_string("backupversion").":</b>"; 485 $tab[2][1] = $info->backup_backup_release." (".$info->backup_backup_version.")"; 486 //The backup date 487 $tab[3][0] = "<b>".get_string("backupdate").":</b>"; 488 $tab[3][1] = userdate($info->backup_date); 489 //Print title 490 print_heading(get_string("backup").":"); 491 $table->data = $tab; 492 //Print backup general info 493 print_table($table); 494 495 if ($info->backup_backup_version <= 2005070500) { 496 notify(get_string('backupnonisowarning')); // Message informing that this backup may not work! 497 } 498 499 //Now backup contents in another table 500 $tab = array(); 501 //First mods info 502 $mods = $info->mods; 503 $elem = 0; 504 foreach ($mods as $key => $mod) { 505 $tab[$elem][0] = "<b>".get_string("modulenameplural",$key).":</b>"; 506 if ($mod->backup == "false") { 507 $tab[$elem][1] = get_string("notincluded"); 508 } else { 509 if ($mod->userinfo == "true") { 510 $tab[$elem][1] = get_string("included")." ".get_string("withuserdata"); 511 } else { 512 $tab[$elem][1] = get_string("included")." ".get_string("withoutuserdata"); 513 } 514 if (isset($mod->instances) && is_array($mod->instances) && count($mod->instances)) { 515 foreach ($mod->instances as $instance) { 516 if ($instance->backup) { 517 $elem++; 518 $tab[$elem][0] = $instance->name; 519 if ($instance->userinfo == 'true') { 520 $tab[$elem][1] = get_string("included")." ".get_string("withuserdata"); 521 } else { 522 $tab[$elem][1] = get_string("included")." ".get_string("withoutuserdata"); 523 } 524 } 525 } 526 } 527 } 528 $elem++; 529 } 530 //Metacourse info 531 $tab[$elem][0] = "<b>".get_string("metacourse").":</b>"; 532 if ($info->backup_metacourse == "true") { 533 $tab[$elem][1] = get_string("yes"); 534 } else { 535 $tab[$elem][1] = get_string("no"); 536 } 537 $elem++; 538 //Users info 539 $tab[$elem][0] = "<b>".get_string("users").":</b>"; 540 $tab[$elem][1] = get_string($info->backup_users); 541 $elem++; 542 //Logs info 543 $tab[$elem][0] = "<b>".get_string("logs").":</b>"; 544 if ($info->backup_logs == "true") { 545 $tab[$elem][1] = get_string("yes"); 546 } else { 547 $tab[$elem][1] = get_string("no"); 548 } 549 $elem++; 550 //User Files info 551 $tab[$elem][0] = "<b>".get_string("userfiles").":</b>"; 552 if ($info->backup_user_files == "true") { 553 $tab[$elem][1] = get_string("yes"); 554 } else { 555 $tab[$elem][1] = get_string("no"); 556 } 557 $elem++; 558 //Course Files info 559 $tab[$elem][0] = "<b>".get_string("coursefiles").":</b>"; 560 if ($info->backup_course_files == "true") { 561 $tab[$elem][1] = get_string("yes"); 562 } else { 563 $tab[$elem][1] = get_string("no"); 564 } 565 $elem++; 566 //site Files info 567 $tab[$elem][0] = "<b>".get_string("sitefiles").":</b>"; 568 if (isset($info->backup_site_files) && $info->backup_site_files == "true") { 569 $tab[$elem][1] = get_string("yes"); 570 } else { 571 $tab[$elem][1] = get_string("no"); 572 } 573 $elem++; 574 //gradebook history info 575 $tab[$elem][0] = "<b>".get_string('gradebookhistories', 'grades').":</b>"; 576 if (isset($info->gradebook_histories) && $info->gradebook_histories == "true") { 577 $tab[$elem][1] = get_string("yes"); 578 } else { 579 $tab[$elem][1] = get_string("no"); 580 } 581 $elem++; 582 //Messages info (only showed if present) 583 if ($info->backup_messages == 'true') { 584 $tab[$elem][0] = "<b>".get_string('messages','message').":</b>"; 585 $tab[$elem][1] = get_string('yes'); 586 $elem++; 587 } else { 588 //Do nothing 589 } 590 $elem++; 591 //Blogs info (only showed if present) 592 if (isset($info->backup_blogs) && $info->backup_blogs == 'true') { 593 $tab[$elem][0] = "<b>".get_string('blogs','blog').":</b>"; 594 $tab[$elem][1] = get_string('yes'); 595 $elem++; 596 } else { 597 //Do nothing 598 } 599 $table->data = $tab; 600 //Print title 601 print_heading(get_string("backupdetails").":"); 602 //Print backup general info 603 print_table($table); 604 } else { 605 $status = false; 606 } 607 608 return $status; 609 } 610 611 //This function prints the contents from the course_header parammeter passed 612 function restore_print_course_header ($course_header) { 613 614 $status = true; 615 if ($course_header) { 616 $table = new object(); 617 //This is tha align to every ingo table 618 $table->align = array ("right","left"); 619 //The width 620 $table->width = "70%"; 621 //Put interesting course header in table 622 //The course name 623 $tab[0][0] = "<b>".get_string("name").":</b>"; 624 $tab[0][1] = $course_header->course_fullname." (".$course_header->course_shortname.")"; 625 //The course summary 626 $tab[1][0] = "<b>".get_string("summary").":</b>"; 627 $tab[1][1] = $course_header->course_summary; 628 $table->data = $tab; 629 //Print title 630 print_heading(get_string("course").":"); 631 //Print backup course header info 632 print_table($table); 633 } else { 634 $status = false; 635 } 636 return $status; 637 } 638 639 //This function create a new course record. 640 //When finished, course_header contains the id of the new course 641 function restore_create_new_course($restore,&$course_header) { 642 643 global $CFG; 644 645 $status = true; 646 647 $fullname = $course_header->course_fullname; 648 $shortname = $course_header->course_shortname; 649 $currentfullname = ""; 650 $currentshortname = ""; 651 $counter = 0; 652 //Iteratere while the name exists 653 do { 654 if ($counter) { 655 $suffixfull = " ".get_string("copyasnoun")." ".$counter; 656 $suffixshort = "_".$counter; 657 } else { 658 $suffixfull = ""; 659 $suffixshort = ""; 660 } 661 $currentfullname = $fullname.$suffixfull; 662 // Limit the size of shortname - database column accepts <= 100 chars 663 $currentshortname = substr($shortname, 0, 100 - strlen($suffixshort)).$suffixshort; 664 $coursefull = get_record("course","fullname",addslashes($currentfullname)); 665 $courseshort = get_record("course","shortname",addslashes($currentshortname)); 666 $counter++; 667 } while ($coursefull || $courseshort); 668 669 //New name = currentname 670 $course_header->course_fullname = $currentfullname; 671 $course_header->course_shortname = $currentshortname; 672 673 // first try to get it from restore 674 if ($restore->restore_restorecatto) { 675 $category = get_record('course_categories', 'id', $restore->restore_restorecatto); 676 } 677 678 // else we try to get it from the xml file 679 //Now calculate the category 680 if (empty($category)) { 681 $category = get_record("course_categories","id",$course_header->category->id, 682 "name",addslashes($course_header->category->name)); 683 } 684 685 //If no exists, try by name only 686 if (!$category) { 687 $category = get_record("course_categories","name",addslashes($course_header->category->name)); 688 } 689 690 //If no exists, get category id 1 691 if (!$category) { 692 $category = get_record("course_categories","id","1"); 693 } 694 695 //If category 1 doesn'exists, lets create the course category (get it from backup file) 696 if (!$category) { 697 $ins_category = new object(); 698 $ins_category->name = addslashes($course_header->category->name); 699 $ins_category->parent = 0; 700 $ins_category->sortorder = 0; 701 $ins_category->coursecount = 0; 702 $ins_category->visible = 0; //To avoid interferences with the rest of the site 703 $ins_category->timemodified = time(); 704 $newid = insert_record("course_categories",$ins_category); 705 $category->id = $newid; 706 $category->name = $course_header->category->name; 707 } 708 //If exists, put new category id 709 if ($category) { 710 $course_header->category->id = $category->id; 711 $course_header->category->name = $category->name; 712 //Error, cannot locate category 713 } else { 714 $course_header->category->id = 0; 715 $course_header->category->name = get_string("unknowncategory"); 716 $status = false; 717 } 718 719 //Create the course_object 720 if ($status) { 721 $course = new object(); 722 $course->category = addslashes($course_header->category->id); 723 $course->password = addslashes($course_header->course_password); 724 $course->fullname = addslashes($course_header->course_fullname); 725 $course->shortname = addslashes($course_header->course_shortname); 726 $course->idnumber = addslashes($course_header->course_idnumber); 727 $course->idnumber = ''; //addslashes($course_header->course_idnumber); // we don't want this at all. 728 $course->summary = backup_todb($course_header->course_summary); 729 $course->format = addslashes($course_header->course_format); 730 $course->showgrades = addslashes($course_header->course_showgrades); 731 $course->newsitems = addslashes($course_header->course_newsitems); 732 $course->teacher = addslashes($course_header->course_teacher); 733 $course->teachers = addslashes($course_header->course_teachers); 734 $course->student = addslashes($course_header->course_student); 735 $course->students = addslashes($course_header->course_students); 736 $course->guest = addslashes($course_header->course_guest); 737 $course->startdate = addslashes($course_header->course_startdate); 738 $course->startdate += $restore->course_startdateoffset; 739 $course->numsections = addslashes($course_header->course_numsections); 740 //$course->showrecent = addslashes($course_header->course_showrecent); INFO: This is out in 1.3 741 $course->maxbytes = addslashes($course_header->course_maxbytes); 742 $course->showreports = addslashes($course_header->course_showreports); 743 if (isset($course_header->course_groupmode)) { 744 $course->groupmode = addslashes($course_header->course_groupmode); 745 } 746 if (isset($course_header->course_groupmodeforce)) { 747 $course->groupmodeforce = addslashes($course_header->course_groupmodeforce); 748 } 749 if (isset($course_header->course_defaultgroupingid)) { 750 //keep the original now - convert after groupings restored 751 $course->defaultgroupingid = addslashes($course_header->course_defaultgroupingid); 752 } 753 $course->lang = addslashes($course_header->course_lang); 754 $course->theme = addslashes($course_header->course_theme); 755 $course->cost = addslashes($course_header->course_cost); 756 $course->currency = isset($course_header->course_currency)?addslashes($course_header->course_currency):''; 757 $course->marker = addslashes($course_header->course_marker); 758 $course->visible = addslashes($course_header->course_visible); 759 $course->hiddensections = addslashes($course_header->course_hiddensections); 760 $course->timecreated = addslashes($course_header->course_timecreated); 761 $course->timemodified = addslashes($course_header->course_timemodified); 762 $course->metacourse = addslashes($course_header->course_metacourse); 763 $course->expirynotify = isset($course_header->course_expirynotify) ? addslashes($course_header->course_expirynotify):0; 764 $course->notifystudents = isset($course_header->course_notifystudents) ? addslashes($course_header->course_notifystudents) : 0; 765 $course->expirythreshold = isset($course_header->course_expirythreshold) ? addslashes($course_header->course_expirythreshold) : 0; 766 $course->enrollable = isset($course_header->course_enrollable) ? addslashes($course_header->course_enrollable) : 1; 767 $course->enrolstartdate = isset($course_header->course_enrolstartdate) ? addslashes($course_header->course_enrolstartdate) : 0; 768 if ($course->enrolstartdate) { //Roll course dates 769 $course->enrolstartdate += $restore->course_startdateoffset; 770 } 771 $course->enrolenddate = isset($course_header->course_enrolenddate) ? addslashes($course_header->course_enrolenddate) : 0; 772 if ($course->enrolenddate) { //Roll course dates 773 $course->enrolenddate += $restore->course_startdateoffset; 774 } 775 $course->enrolperiod = addslashes($course_header->course_enrolperiod); 776 //Calculate sortorder field 777 $sortmax = get_record_sql('SELECT MAX(sortorder) AS max 778 FROM ' . $CFG->prefix . 'course 779 WHERE category=' . $course->category); 780 if (!empty($sortmax->max)) { 781 $course->sortorder = $sortmax->max + 1; 782 unset($sortmax); 783 } else { 784 $course->sortorder = 100; 785 } 786 787 //Now, recode some languages (Moodle 1.5) 788 if ($course->lang == 'ma_nt') { 789 $course->lang = 'mi_nt'; 790 } 791 792 //Disable course->metacourse if avoided in restore config 793 if (!$restore->metacourse) { 794 $course->metacourse = 0; 795 } 796 797 //Check if the theme exists in destination server 798 $themes = get_list_of_themes(); 799 if (!in_array($course->theme, $themes)) { 800 $course->theme = ''; 801 } 802 803 //Now insert the record 804 $newid = insert_record("course",$course); 805 if ($newid) { 806 //save old and new course id 807 backup_putid ($restore->backup_unique_code,"course",$course_header->course_id,$newid); 808 //Replace old course_id in course_header 809 $course_header->course_id = $newid; 810 } else { 811 $status = false; 812 } 813 } 814 815 return $status; 816 } 817 818 819 820 //This function creates all the block stuff when restoring courses 821 //It calls selectively to restore_create_block_instances() for 1.5 822 //and above backups. Upwards compatible with old blocks. 823 function restore_create_blocks($restore, $backup_block_format, $blockinfo, $xml_file) { 824 global $CFG; 825 $status = true; 826 827 delete_records('block_instance', 'pageid', $restore->course_id, 'pagetype', PAGE_COURSE_VIEW); 828 if (empty($backup_block_format)) { // This is a backup from Moodle < 1.5 829 if (empty($blockinfo)) { 830 // Looks like it's from Moodle < 1.3. Let's give the course default blocks... 831 $newpage = page_create_object(PAGE_COURSE_VIEW, $restore->course_id); 832 blocks_repopulate_page($newpage); 833 } else { 834 // We just have a blockinfo field, this is a legacy 1.4 or 1.3 backup 835 $blockrecords = get_records_select('block', '', '', 'name, id'); 836 $temp_blocks_l = array(); 837 $temp_blocks_r = array(); 838 @list($temp_blocks_l, $temp_blocks_r) = explode(':', $blockinfo); 839 $temp_blocks = array(BLOCK_POS_LEFT => explode(',', $temp_blocks_l), BLOCK_POS_RIGHT => explode(',', $temp_blocks_r)); 840 foreach($temp_blocks as $blockposition => $blocks) { 841 $blockweight = 0; 842 foreach($blocks as $blockname) { 843 if(!isset($blockrecords[$blockname])) { 844 // We don't know anything about this block! 845 continue; 846 } 847 $blockinstance = new stdClass; 848 // Remove any - prefix before doing the name-to-id mapping 849 if(substr($blockname, 0, 1) == '-') { 850 $blockname = substr($blockname, 1); 851 $blockinstance->visible = 0; 852 } else { 853 $blockinstance->visible = 1; 854 } 855 $blockinstance->blockid = $blockrecords[$blockname]->id; 856 $blockinstance->pageid = $restore->course_id; 857 $blockinstance->pagetype = PAGE_COURSE_VIEW; 858 $blockinstance->position = $blockposition; 859 $blockinstance->weight = $blockweight; 860 if(!$status = insert_record('block_instance', $blockinstance)) { 861 $status = false; 862 } 863 ++$blockweight; 864 } 865 } 866 } 867 } else if($backup_block_format == 'instances') { 868 $status = restore_create_block_instances($restore,$xml_file); 869 } 870 871 return $status; 872 873 } 874 875 //This function creates all the block_instances from xml when restoring in a 876 //new course 877 function restore_create_block_instances($restore,$xml_file) { 878 global $CFG; 879 $status = true; 880 881 //Check it exists 882 if (!file_exists($xml_file)) { 883 $status = false; 884 } 885 //Get info from xml 886 if ($status) { 887 $info = restore_read_xml_blocks($restore,$xml_file); 888 } 889 890 if(empty($info->instances)) { 891 return $status; 892 } 893 894 // First of all, iterate over the blocks to see which distinct pages we have 895 // in our hands and arrange the blocks accordingly. 896 $pageinstances = array(); 897 foreach($info->instances as $instance) { 898 899 //pagetype and pageid black magic, we have to handle the case of blocks for the 900 //course, blocks from other pages in that course etc etc etc. 901 902 if($instance->pagetype == PAGE_COURSE_VIEW) { 903 // This one's easy... 904 $instance->pageid = $restore->course_id; 905 906 } else if (!empty($CFG->showblocksonmodpages)) { 907 $parts = explode('-', $instance->pagetype); 908 if($parts[0] == 'mod') { 909 if(!$restore->mods[$parts[1]]->restore) { 910 continue; 911 } 912 $getid = backup_getid($restore->backup_unique_code, $parts[1], $instance->pageid); 913 914 if (empty($getid->new_id)) { 915 // Failed, perhaps the module was not included in the restore MDL-13554 916 continue; 917 } 918 $instance->pageid = $getid->new_id; 919 } 920 else { 921 // Not invented here ;-) 922 continue; 923 } 924 925 } else { 926 // do not restore activity blocks if disabled 927 continue; 928 } 929 930 if(!isset($pageinstances[$instance->pagetype])) { 931 $pageinstances[$instance->pagetype] = array(); 932 } 933 if(!isset($pageinstances[$instance->pagetype][$instance->pageid])) { 934 $pageinstances[$instance->pagetype][$instance->pageid] = array(); 935 } 936 937 $pageinstances[$instance->pagetype][$instance->pageid][] = $instance; 938 } 939 940 $blocks = get_records_select('block', 'visible = 1', '', 'name, id, multiple'); 941 942 // For each type of page we have restored 943 foreach($pageinstances as $thistypeinstances) { 944 945 // For each page id of that type 946 foreach($thistypeinstances as $thisidinstances) { 947 948 $addedblocks = array(); 949 $maxweights = array(); 950 951 // For each block instance in that page 952 foreach($thisidinstances as $instance) { 953 954 if(!isset($blocks[$instance->name])) { 955 //We are trying to restore a block we don't have... 956 continue; 957 } 958 959 //If we have already added this block once and multiples aren't allowed, disregard it 960 if(!$blocks[$instance->name]->multiple && isset($addedblocks[$instance->name])) { 961 continue; 962 } 963 964 //If its the first block we add to a new position, start weight counter equal to 0. 965 if(empty($maxweights[$instance->position])) { 966 $maxweights[$instance->position] = 0; 967 } 968 969 //If the instance weight is greater than the weight counter (we skipped some earlier 970 //blocks most probably), bring it back in line. 971 if($instance->weight > $maxweights[$instance->position]) { 972 $instance->weight = $maxweights[$instance->position]; 973 } 974 975 //Add this instance 976 $instance->blockid = $blocks[$instance->name]->id; 977 978 // This will only be set if we come from 1.7 and above backups 979 // Also, must do this before insert (insert_record unsets id) 980 if (!empty($instance->id)) { 981 $oldid = $instance->id; 982 } else { 983 $oldid = 0; 984 } 985 986 if ($instance->id = insert_record('block_instance', $instance)) { 987 // Create block instance 988 if (!$blockobj = block_instance($instance->name, $instance)) { 989 $status = false; 990 break; 991 } 992 // Run the block restore if needed 993 if ($blockobj->backuprestore_instancedata_used()) { 994 // Get restore information 995 $data = backup_getid($restore->backup_unique_code,'block_instance',$oldid); 996 $data->new_id = $instance->id; // For completeness 997 if (!$blockobj->instance_restore($restore, $data)) { 998 $status = false; 999 break; 1000 } 1001 } 1002 // Save oldid after block restore process because info will be over-written with blank string 1003 if ($oldid) { 1004 backup_putid ($restore->backup_unique_code,"block_instance",$oldid,$instance->id); 1005 } 1006 1007 } else { 1008 $status = false; 1009 break; 1010 } 1011 1012 //Get an object for the block and tell it it's been restored so it can update dates 1013 //etc. if necessary 1014 if ($blockobj = block_instance($instance->name,$instance)) { 1015 $blockobj->after_restore($restore); 1016 } 1017 1018 //Now we can increment the weight counter 1019 ++$maxweights[$instance->position]; 1020 1021 //Keep track of block types we have already added 1022 $addedblocks[$instance->name] = true; 1023 1024 } 1025 } 1026 } 1027 1028 return $status; 1029 } 1030 1031 //This function creates all the course_sections and course_modules from xml 1032 //when restoring in a new course or simply checks sections and create records 1033 //in backup_ids when restoring in a existing course 1034 function restore_create_sections(&$restore, $xml_file) { 1035 1036 global $CFG,$db; 1037 1038 $status = true; 1039 //Check it exists 1040 if (!file_exists($xml_file)) { 1041 $status = false; 1042 } 1043 //Get info from xml 1044 if ($status) { 1045 $info = restore_read_xml_sections($xml_file); 1046 } 1047 //Put the info in the DB, recoding ids and saving the in backup tables 1048 1049 $sequence = ""; 1050 1051 if ($info) { 1052 //For each, section, save it to db 1053 foreach ($info->sections as $key => $sect) { 1054 $sequence = ""; 1055 $section = new object(); 1056 $section->course = $restore->course_id; 1057 $section->section = $sect->number; 1058 $section->summary = backup_todb($sect->summary); 1059 $section->visible = $sect->visible; 1060 $section->sequence = ""; 1061 //Now calculate the section's newid 1062 $newid = 0; 1063 if ($restore->restoreto == 2) { 1064 //Save it to db (only if restoring to new course) 1065 $newid = insert_record("course_sections",$section); 1066 } else { 1067 //Get section id when restoring in existing course 1068 $rec = get_record("course_sections","course",$restore->course_id, 1069 "section",$section->section); 1070 //If that section doesn't exist, get section 0 (every mod will be 1071 //asigned there 1072 if(!$rec) { 1073 $rec = get_record("course_sections","course",$restore->course_id, 1074 "section","0"); 1075 } 1076 //New check. If section 0 doesn't exist, insert it here !! 1077 //Teorically this never should happen but, in practice, some users 1078 //have reported this issue. 1079 if(!$rec) { 1080 $zero_sec = new object(); 1081 $zero_sec->course = $restore->course_id; 1082 $zero_sec->section = 0; 1083 $zero_sec->summary = ""; 1084 $zero_sec->sequence = ""; 1085 $newid = insert_record("course_sections",$zero_sec); 1086 $rec->id = $newid; 1087 $rec->sequence = ""; 1088 } 1089 $newid = $rec->id; 1090 $sequence = $rec->sequence; 1091 } 1092 if ($newid) { 1093 //save old and new section id 1094 backup_putid ($restore->backup_unique_code,"course_sections",$key,$newid); 1095 } else { 1096 $status = false; 1097 } 1098 //If all is OK, go with associated mods 1099 if ($status) { 1100 //If we have mods in the section 1101 if (!empty($sect->mods)) { 1102 //For each mod inside section 1103 foreach ($sect->mods as $keym => $mod) { 1104 // Yu: This part is called repeatedly for every instance, 1105 // so it is necessary to set the granular flag and check isset() 1106 // when the first instance of this type of mod is processed. 1107 1108 //if (!isset($restore->mods[$mod->type]->granular) && isset($restore->mods[$mod->type]->instances) && is_array($restore->mods[$mod->type]->instances)) { 1109 1110 if (!isset($restore->mods[$mod->type]->granular)) { 1111 if (isset($restore->mods[$mod->type]->instances) && is_array($restore->mods[$mod->type]->instances)) { 1112 // This defines whether we want to restore specific 1113 // instances of the modules (granular restore), or 1114 // whether we don't care and just want to restore 1115 // all module instances (non-granular). 1116 $restore->mods[$mod->type]->granular = true; 1117 } else { 1118 $restore->mods[$mod->type]->granular = false; 1119 } 1120 } 1121 1122 //Check if we've to restore this module (and instance) 1123 if (!empty($restore->mods[$mod->type]->restore)) { 1124 if (empty($restore->mods[$mod->type]->granular) // we don't care about per instance 1125 || (array_key_exists($mod->instance,$restore->mods[$mod->type]->instances) 1126 && !empty($restore->mods[$mod->type]->instances[$mod->instance]->restore))) { 1127 1128 //Get the module id from modules 1129 $module = get_record("modules","name",$mod->type); 1130 if ($module) { 1131 $course_module = new object(); 1132 $course_module->course = $restore->course_id; 1133 $course_module->module = $module->id; 1134 $course_module->section = $newid; 1135 $course_module->added = $mod->added; 1136 $course_module->score = $mod->score; 1137 $course_module->indent = $mod->indent; 1138 $course_module->visible = $mod->visible; 1139 $course_module->groupmode = $mod->groupmode; 1140 if ($mod->groupingid and $grouping = restore_grouping_getid($restore, $mod->groupingid)) { 1141 $course_module->groupingid = $grouping->new_id; 1142 } else { 1143 $course_module->groupingid = 0; 1144 } 1145 $course_module->groupmembersonly = $mod->groupmembersonly; 1146 $course_module->instance = 0; 1147 //NOTE: The instance (new) is calculated and updated in db in the 1148 // final step of the restore. We don't know it yet. 1149 //print_object($course_module); //Debug 1150 //Save it to db 1151 if ($mod->idnumber) { 1152 if (grade_verify_idnumber($mod->idnumber, $restore->course_id)) { 1153 $course_module->idnumber = $mod->idnumber; 1154 } 1155 } 1156 1157 $newidmod = insert_record("course_modules", addslashes_recursive($course_module)); 1158 if ($newidmod) { 1159 //save old and new module id 1160 //In the info field, we save the original instance of the module 1161 //to use it later 1162 backup_putid ($restore->backup_unique_code,"course_modules", 1163 $keym,$newidmod,$mod->instance); 1164 1165 $restore->mods[$mod->type]->instances[$mod->instance]->restored_as_course_module = $newidmod; 1166 } else { 1167 $status = false; 1168 } 1169 //Now, calculate the sequence field 1170 if ($status) { 1171 if ($sequence) { 1172 $sequence .= ",".$newidmod; 1173 } else { 1174 $sequence = $newidmod; 1175 } 1176 } 1177 } else { 1178 $status = false; 1179 } 1180 } 1181 } 1182 } 1183 } 1184 } 1185 //If all is OK, update sequence field in course_sections 1186 if ($status) { 1187 if (isset($sequence)) { 1188 $update_rec = new object(); 1189 $update_rec->id = $newid; 1190 $update_rec->sequence = $sequence; 1191 $status = update_record("course_sections",$update_rec); 1192 } 1193 } 1194 } 1195 } else { 1196 $status = false; 1197 } 1198 return $status; 1199 } 1200 1201 //Called to set up any course-format specific data that may be in the file 1202 function restore_set_format_data($restore,$xml_file) { 1203 global $CFG,$db; 1204 1205 $status = true; 1206 //Check it exists 1207 if (!file_exists($xml_file)) { 1208 return false; 1209 } 1210 //Load data from XML to info 1211 if(!($info = restore_read_xml_formatdata($xml_file))) { 1212 return false; 1213 } 1214 1215 //Process format data if there is any 1216 if (isset($info->format_data)) { 1217 if(!$format=get_field('course','format','id',$restore->course_id)) { 1218 return false; 1219 } 1220 // If there was any data then it must have a restore method 1221 $file=$CFG->dirroot."/course/format/$format/restorelib.php"; 1222 if(!file_exists($file)) { 1223 return false; 1224 } 1225 require_once($file); 1226 $function=$format.'_restore_format_data'; 1227 if(!function_exists($function)) { 1228 return false; 1229 } 1230 return $function($restore,$info->format_data); 1231 } 1232 1233 // If we got here then there's no data, but that's cool 1234 return true; 1235 } 1236 1237 //This function creates all the metacourse data from xml, notifying 1238 //about each incidence 1239 function restore_create_metacourse($restore,$xml_file) { 1240 1241 global $CFG,$db; 1242 1243 $status = true; 1244 //Check it exists 1245 if (!file_exists($xml_file)) { 1246 $status = false; 1247 } 1248 //Get info from xml 1249 if ($status) { 1250 //Load data from XML to info 1251 $info = restore_read_xml_metacourse($xml_file); 1252 } 1253 1254 //Process info about metacourse 1255 if ($status and $info) { 1256 //Process child records 1257 if (!empty($info->childs)) { 1258 foreach ($info->childs as $child) { 1259 $dbcourse = false; 1260 $dbmetacourse = false; 1261 //Check if child course exists in destination server 1262 //(by id in the same server or by idnumber and shortname in other server) 1263 if ($restore->original_wwwroot == $CFG->wwwroot) { 1264 //Same server, lets see by id 1265 $dbcourse = get_record('course','id',$child->id); 1266 } else { 1267 //Different server, lets see by idnumber and shortname, and only ONE record 1268 $dbcount = count_records('course','idnumber',$child->idnumber,'shortname',$child->shortname); 1269 if ($dbcount == 1) { 1270 $dbcourse = get_record('course','idnumber',$child->idnumber,'shortname',$child->shortname); 1271 } 1272 } 1273 //If child course has been found, insert data 1274 if ($dbcourse) { 1275 $dbmetacourse->child_course = $dbcourse->id; 1276 $dbmetacourse->parent_course = $restore->course_id; 1277 $status = insert_record ('course_meta',$dbmetacourse); 1278 } else { 1279 //Child course not found, notice! 1280 if (!defined('RESTORE_SILENTLY')) { 1281 echo '<ul><li>'.get_string ('childcoursenotfound').' ('.$child->id.'/'.$child->idnumber.'/'.$child->shortname.')</li></ul>'; 1282 } 1283 } 1284 } 1285 //Now, recreate student enrolments... 1286 sync_metacourse($restore->course_id); 1287 } 1288 //Process parent records 1289 if (!empty($info->parents)) { 1290 foreach ($info->parents as $parent) { 1291 $dbcourse = false; 1292 $dbmetacourse = false; 1293 //Check if parent course exists in destination server 1294 //(by id in the same server or by idnumber and shortname in other server) 1295 if ($restore->original_wwwroot == $CFG->wwwroot) { 1296 //Same server, lets see by id 1297 $dbcourse = get_record('course','id',$parent->id); 1298 } else { 1299 //Different server, lets see by idnumber and shortname, and only ONE record 1300 $dbcount = count_records('course','idnumber',$parent->idnumber,'shortname',$parent->shortname); 1301 if ($dbcount == 1) { 1302 $dbcourse = get_record('course','idnumber',$parent->idnumber,'shortname',$parent->shortname); 1303 } 1304 } 1305 //If parent course has been found, insert data if it is a metacourse 1306 if ($dbcourse) { 1307 if ($dbcourse->metacourse) { 1308 $dbmetacourse->parent_course = $dbcourse->id; 1309 $dbmetacourse->child_course = $restore->course_id; 1310 $status = insert_record ('course_meta',$dbmetacourse); 1311 //Now, recreate student enrolments in parent course 1312 sync_metacourse($dbcourse->id); 1313 } else { 1314 //Parent course isn't metacourse, notice! 1315 if (!defined('RESTORE_SILENTLY')) { 1316 echo '<ul><li>'.get_string ('parentcoursenotmetacourse').' ('.$parent->id.'/'.$parent->idnumber.'/'.$parent->shortname.')</li></ul>'; 1317 } 1318 } 1319 } else { 1320 //Parent course not found, notice! 1321 if (!defined('RESTORE_SILENTLY')) { 1322 echo '<ul><li>'.get_string ('parentcoursenotfound').' ('.$parent->id.'/'.$parent->idnumber.'/'.$parent->shortname.')</li></ul>'; 1323 } 1324 } 1325 } 1326 } 1327 1328 } 1329 return $status; 1330 } 1331 1332 /** 1333 * This function migrades all the pre 1.9 gradebook data from xml 1334 */ 1335 function restore_migrate_old_gradebook($restore,$xml_file) { 1336 global $CFG; 1337 1338 $status = true; 1339 //Check it exists 1340 if (!file_exists($xml_file)) { 1341 return false; 1342 } 1343 1344 // Get info from xml 1345 // info will contain the number of record to process 1346 $info = restore_read_xml_gradebook($restore, $xml_file); 1347 1348 // If we have info, then process 1349 if (empty($info)) { 1350 return $status; 1351 } 1352 1353 // make sure top course category exists 1354 $course_category = grade_category::fetch_course_category($restore->course_id); 1355 $course_category->load_grade_item(); 1356 1357 // we need to know if all grade items that were backed up are being restored 1358 // if that is not the case, we do not restore grade categories nor gradeitems of category type or course type 1359 // i.e. the aggregated grades of that category 1360 1361 $restoreall = true; // set to false if any grade_item is not selected/restored 1362 $importing = !empty($SESSION->restore->importing); // there should not be a way to import old backups, but anyway ;-) 1363 1364 if ($importing) { 1365 $restoreall = false; 1366 1367 } else { 1368 $prev_grade_items = grade_item::fetch_all(array('courseid'=>$restore->course_id)); 1369 $prev_grade_cats = grade_category::fetch_all(array('courseid'=>$restore->course_id)); 1370 1371 // if any categories already present, skip restore of categories from backup 1372 if (count($prev_grade_items) > 1 or count($prev_grade_cats) > 1) { 1373 $restoreall = false; 1374 } 1375 unset($prev_grade_items); 1376 unset($prev_grade_cats); 1377 } 1378 1379 // force creation of all grade_items - the course_modules already exist 1380 grade_force_full_regrading($restore->course_id); 1381 grade_grab_course_grades($restore->course_id); 1382 1383 // Start ul 1384 if (!defined('RESTORE_SILENTLY')) { 1385 echo '<ul>'; 1386 } 1387 1388 /// Process letters 1389 $context = get_context_instance(CONTEXT_COURSE, $restore->course_id); 1390 // respect current grade letters if defined 1391 if ($status and $restoreall and !record_exists('grade_letters', 'contextid', $context->id)) { 1392 if (!defined('RESTORE_SILENTLY')) { 1393 echo '<li>'.get_string('gradeletters','grades').'</li>'; 1394 } 1395 // Fetch recordset_size records in each iteration 1396 $recs = get_records_select("backup_ids","table_name = 'grade_letter' AND backup_code = $restore->backup_unique_code", 1397 "", 1398 "old_id"); 1399 if ($recs) { 1400 foreach ($recs as $rec) { 1401 // Get the full record from backup_ids 1402 $data = backup_getid($restore->backup_unique_code,'grade_letter',$rec->old_id); 1403 if ($data) { 1404 $info = $data->info; 1405 $dbrec = new object(); 1406 $dbrec->contextid = $context->id; 1407 $dbrec->lowerboundary = backup_todb($info['GRADE_LETTER']['#']['GRADE_LOW']['0']['#']); 1408 $dbrec->letter = backup_todb($info['GRADE_LETTER']['#']['LETTER']['0']['#']); 1409 insert_record('grade_letters', $dbrec); 1410 } 1411 } 1412 } 1413 } 1414 1415 if (!defined('RESTORE_SILENTLY')) { 1416 echo '<li>'.get_string('categories','grades').'</li>'; 1417 } 1418 //Fetch recordset_size records in each iteration 1419 $recs = get_records_select("backup_ids","table_name = 'grade_category' AND backup_code = $restore->backup_unique_code", 1420 "old_id", 1421 "old_id"); 1422 $cat_count = count($recs); 1423 if ($recs) { 1424 foreach ($recs as $rec) { 1425 //Get the full record from backup_ids 1426 $data = backup_getid($restore->backup_unique_code,'grade_category',$rec->old_id); 1427 if ($data) { 1428 //Now get completed xmlized object 1429 $info = $data->info; 1430 1431 if ($restoreall) { 1432 if ($cat_count == 1) { 1433 $course_category->fullname = backup_todb($info['GRADE_CATEGORY']['#']['NAME']['0']['#'], false); 1434 $course_category->droplow = backup_todb($info['GRADE_CATEGORY']['#']['DROP_X_LOWEST']['0']['#'], false); 1435 $course_category->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN2; 1436 $course_category->aggregateonlygraded = 0; 1437 $course_category->update('restore'); 1438 $grade_category = $course_category; 1439 1440 } else { 1441 $grade_category = new grade_category(); 1442 $grade_category->courseid = $restore->course_id; 1443 $grade_category->fullname = backup_todb($info['GRADE_CATEGORY']['#']['NAME']['0']['#'], false); 1444 $grade_category->droplow = backup_todb($info['GRADE_CATEGORY']['#']['DROP_X_LOWEST']['0']['#'], false); 1445 $grade_category->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN2; 1446 $grade_category->aggregateonlygraded = 0; 1447 $grade_category->insert('restore'); 1448 $grade_category->load_grade_item(); // force cretion of grade_item 1449 } 1450 1451 } else { 1452 $grade_category = null; 1453 } 1454 1455 /// now, restore grade_items 1456 $items = array(); 1457 if (!empty($info['GRADE_CATEGORY']['#']['GRADE_ITEMS']['0']['#']['GRADE_ITEM'])) { 1458 //Iterate over items 1459 foreach ($info['GRADE_CATEGORY']['#']['GRADE_ITEMS']['0']['#']['GRADE_ITEM'] as $ite_info) { 1460 $modname = backup_todb($ite_info['#']['MODULE_NAME']['0']['#'], false); 1461 $olditeminstance = backup_todb($ite_info['#']['CMINSTANCE']['0']['#'], false); 1462 if (!$mod = backup_getid($restore->backup_unique_code,$modname, $olditeminstance)) { 1463 continue; // not restored 1464 } 1465 $iteminstance = $mod->new_id; 1466 if (!$cm = get_coursemodule_from_instance($modname, $iteminstance, $restore->course_id)) { 1467 continue; // does not exist 1468 } 1469 1470 if (!$grade_item = grade_item::fetch(array('itemtype'=>'mod', 'itemmodule'=>$cm->modname, 'iteminstance'=>$cm->instance, 'courseid'=>$cm->course, 'itemnumber'=>0))) { 1471 continue; // no item yet?? 1472 } 1473 1474 if ($grade_category) { 1475 $grade_item->sortorder = backup_todb($ite_info['#']['SORT_ORDER']['0']['#'], false); 1476 $grade_item->set_parent($grade_category->id); 1477 } 1478 1479 if ($importing 1480 or ($grade_item->itemtype == 'mod' and !restore_userdata_selected($restore, $grade_item->itemmodule, $olditeminstance))) { 1481 // module instance not selected when restored using granular 1482 // skip this item 1483 continue; 1484 } 1485 1486 //Now process grade excludes 1487 if (empty($ite_info['#']['GRADE_EXCEPTIONS'])) { 1488 continue; 1489 } 1490 1491 foreach($ite_info['#']['GRADE_EXCEPTIONS']['0']['#']['GRADE_EXCEPTION'] as $exc_info) { 1492 if ($u = backup_getid($restore->backup_unique_code,"user",backup_todb($exc_info['#']['USERID']['0']['#']))) { 1493 $userid = $u->new_id; 1494 $grade_grade = new grade_grade(array('itemid'=>$grade_item->id, 'userid'=>$userid)); 1495 $grade_grade->excluded = 1; 1496 if ($grade_grade->id) { 1497 $grade_grade->update('restore'); 1498 } else { 1499 $grade_grade->insert('restore'); 1500 } 1501 } 1502 } 1503 } 1504 } 1505 } 1506 } 1507 } 1508 1509 if (!defined('RESTORE_SILENTLY')) { 1510 //End ul 1511 echo '</ul>'; 1512 } 1513 1514 return $status; 1515 } 1516 1517 /** 1518 * This function creates all the gradebook data from xml 1519 */ 1520 function restore_create_gradebook($restore,$xml_file) { 1521 global $CFG; 1522 1523 $status = true; 1524 //Check it exists 1525 if (!file_exists($xml_file)) { 1526 return false; 1527 } 1528 1529 // Get info from xml 1530 // info will contain the number of record to process 1531 $info = restore_read_xml_gradebook($restore, $xml_file); 1532 1533 // If we have info, then process 1534 if (empty($info)) { 1535 return $status; 1536 } 1537 1538 if (empty($CFG->disablegradehistory) and isset($info->gradebook_histories) and $info->gradebook_histories == "true") { 1539 $restore_histories = true; 1540 } else { 1541 $restore_histories = false; 1542 } 1543 1544 // make sure top course category exists 1545 $course_category = grade_category::fetch_course_category($restore->course_id); 1546 $course_category->load_grade_item(); 1547 1548 // we need to know if all grade items that were backed up are being restored 1549 // if that is not the case, we do not restore grade categories nor gradeitems of category type or course type 1550 // i.e. the aggregated grades of that category 1551 1552 $restoreall = true; // set to false if any grade_item is not selected/restored or already exist 1553 $importing = !empty($SESSION->restore->importing); 1554 1555 if ($importing) { 1556 $restoreall = false; 1557 1558 } else { 1559 $prev_grade_items = grade_item::fetch_all(array('courseid'=>$restore->course_id)); 1560 $prev_grade_cats = grade_category::fetch_all(array('courseid'=>$restore->course_id)); 1561 1562 // if any categories already present, skip restore of categories from backup - course item or category already exist 1563 if (count($prev_grade_items) > 1 or count($prev_grade_cats) > 1) { 1564 $restoreall = false; 1565 } 1566 unset($prev_grade_items); 1567 unset($prev_grade_cats); 1568 1569 if ($restoreall) { 1570 if ($recs = get_records_select("backup_ids","table_name = 'grade_items' AND backup_code = $restore->backup_unique_code", "", "old_id")) { 1571 foreach ($recs as $rec) { 1572 if ($data = backup_getid($restore->backup_unique_code,'grade_items',$rec->old_id)) { 1573 1574 $info = $data->info; 1575 // do not restore if this grade_item is a mod, and 1576 $itemtype = backup_todb($info['GRADE_ITEM']['#']['ITEMTYPE']['0']['#']); 1577 1578 if ($itemtype == 'mod') { 1579 $olditeminstance = backup_todb($info['GRADE_ITEM']['#']['ITEMINSTANCE']['0']['#']); 1580 $itemmodule = backup_todb($info['GRADE_ITEM']['#']['ITEMMODULE']['0']['#']); 1581 1582 if (empty($restore->mods[$itemmodule]->granular)) { 1583 continue; 1584 } else if (!empty($restore->mods[$itemmodule]->instances[$olditeminstance]->restore)) { 1585 continue; 1586 } 1587 // at least one activity should not be restored - do not restore categories and manual items at all 1588 $restoreall = false; 1589 break; 1590 } 1591 } 1592 } 1593 } 1594 } 1595 } 1596 1597 // Start ul 1598 if (!defined('RESTORE_SILENTLY')) { 1599 echo '<ul>'; 1600 } 1601 1602 // array of restored categories - speedup ;-) 1603 $cached_categories = array(); 1604 $outcomes = array(); 1605 1606 /// Process letters 1607 $context = get_context_instance(CONTEXT_COURSE, $restore->course_id); 1608 // respect current grade letters if defined 1609 if ($status and $restoreall and !record_exists('grade_letters', 'contextid', $context->id)) { 1610 if (!defined('RESTORE_SILENTLY')) { 1611 echo '<li>'.get_string('gradeletters','grades').'</li>'; 1612 } 1613 // Fetch recordset_size records in each iteration 1614 $recs = get_records_select("backup_ids","table_name = 'grade_letters' AND backup_code = $restore->backup_unique_code", 1615 "", 1616 "old_id"); 1617 if ($recs) { 1618 foreach ($recs as $rec) { 1619 // Get the full record from backup_ids 1620 $data = backup_getid($restore->backup_unique_code,'grade_letters',$rec->old_id); 1621 if ($data) { 1622 $info = $data->info; 1623 $dbrec = new object(); 1624 $dbrec->contextid = $context->id; 1625 $dbrec->lowerboundary = backup_todb($info['GRADE_LETTER']['#']['LOWERBOUNDARY']['0']['#']); 1626 $dbrec->letter = backup_todb($info['GRADE_LETTER']['#']['LETTER']['0']['#']); 1627 insert_record('grade_letters', $dbrec); 1628 } 1629 } 1630 } 1631 } 1632 1633 /// Preprocess outcomes - do not store them yet! 1634 if ($status and !$importing and $restoreall) { 1635 if (!defined('RESTORE_SILENTLY')) { 1636 echo '<li>'.get_string('gradeoutcomes','grades').'</li>'; 1637 } 1638 $recs = get_records_select("backup_ids","table_name = 'grade_outcomes' AND backup_code = '$restore->backup_unique_code'", 1639 "", 1640 "old_id"); 1641 if ($recs) { 1642 foreach ($recs as $rec) { 1643 //Get the full record from backup_ids 1644 $data = backup_getid($restore->backup_unique_code,'grade_outcomes',$rec->old_id); 1645 if ($data) { 1646 $info = $data->info; 1647 1648 //first find out if outcome already exists 1649 $shortname = backup_todb($info['GRADE_OUTCOME']['#']['SHORTNAME']['0']['#']); 1650 1651 if ($candidates = get_records_sql("SELECT * 1652 FROM {$CFG->prefix}grade_outcomes 1653 WHERE (courseid IS NULL OR courseid = $restore->course_id) 1654 AND shortname = '$shortname' 1655 ORDER BY courseid ASC, id ASC")) { 1656 $grade_outcome = reset($candidates); 1657 $outcomes[$rec->old_id] = $grade_outcome; 1658 continue; 1659 } 1660 1661 $dbrec = new object(); 1662 1663 if (has_capability('moodle/grade:manageoutcomes', get_context_instance(CONTEXT_SYSTEM))) { 1664 $oldoutcome = backup_todb($info['GRADE_OUTCOME']['#']['COURSEID']['0']['#']); 1665 if (empty($oldoutcome)) { 1666 //site wide 1667 $dbrec->courseid = null; 1668 } else { 1669 //course only 1670 $dbrec->courseid = $restore->course_id; 1671 } 1672 } else { 1673 // no permission to add site outcomes 1674 $dbrec->courseid = $restore->course_id; 1675 } 1676 1677 //Get the fields 1678 $dbrec->shortname = backup_todb($info['GRADE_OUTCOME']['#']['SHORTNAME']['0']['#'], false); 1679 $dbrec->fullname = backup_todb($info['GRADE_OUTCOME']['#']['FULLNAME']['0']['#'], false); 1680 $dbrec->scaleid = backup_todb($info['GRADE_OUTCOME']['#']['SCALEID']['0']['#'], false); 1681 $dbrec->description = backup_todb($info['GRADE_OUTCOME']['#']['DESCRIPTION']['0']['#'], false); 1682 $dbrec->timecreated = backup_todb($info['GRADE_OUTCOME']['#']['TIMECREATED']['0']['#'], false); 1683 $dbrec->timemodified = backup_todb($info['GRADE_OUTCOME']['#']['TIMEMODIFIED']['0']['#'], false); 1684 $dbrec->usermodified = backup_todb($info['GRADE_OUTCOME']['#']['USERMODIFIED']['0']['#'], false); 1685 1686 //Need to recode the scaleid 1687 if ($scale = backup_getid($restore->backup_unique_code, 'scale', $dbrec->scaleid)) { 1688 $dbrec->scaleid = $scale->new_id; 1689 } 1690 1691 //Need to recode the usermodified 1692 if ($modifier = backup_getid($restore->backup_unique_code, 'user', $dbrec->usermodified)) { 1693 $dbrec->usermodified = $modifier->new_id; 1694 } 1695 1696 $grade_outcome = new grade_outcome($dbrec, false); 1697 $outcomes[$rec->old_id] = $grade_outcome; 1698 } 1699 } 1700 } 1701 } 1702 1703 /// Process grade items and grades 1704 if ($status) { 1705 if (!defined('RESTORE_SILENTLY')) { 1706 echo '<li>'.get_string('gradeitems','grades').'</li>'; 1707 } 1708 $counter = 0; 1709 1710 //Fetch recordset_size records in each iteration 1711 $recs = get_records_select("backup_ids","table_name = 'grade_items' AND backup_code = '$restore->backup_unique_code'", 1712 "id", // restore in the backup order 1713 "old_id"); 1714 1715 if ($recs) { 1716 foreach ($recs as $rec) { 1717 //Get the full record from backup_ids 1718 $data = backup_getid($restore->backup_unique_code,'grade_items',$rec->old_id); 1719 if ($data) { 1720 $info = $data->info; 1721 1722 // first find out if category or normal item 1723 $itemtype = backup_todb($info['GRADE_ITEM']['#']['ITEMTYPE']['0']['#'], false); 1724 if ($itemtype == 'course' or $itemtype == 'category') { 1725 if (!$restoreall or $importing) { 1726 continue; 1727 } 1728 1729 $oldcat = backup_todb($info['GRADE_ITEM']['#']['ITEMINSTANCE']['0']['#'], false); 1730 if (!$cdata = backup_getid($restore->backup_unique_code,'grade_categories',$oldcat)) { 1731 continue; 1732 } 1733 $cinfo = $cdata->info; 1734 unset($cdata); 1735 if ($itemtype == 'course') { 1736 1737 $course_category->fullname = backup_todb($cinfo['GRADE_CATEGORY']['#']['FULLNAME']['0']['#'], false); 1738 $course_category->aggregation = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATION']['0']['#'], false); 1739 $course_category->keephigh = backup_todb($cinfo['GRADE_CATEGORY']['#']['KEEPHIGH']['0']['#'], false); 1740 $course_category->droplow = backup_todb($cinfo['GRADE_CATEGORY']['#']['DROPLOW']['0']['#'], false); 1741 $course_category->aggregateonlygraded = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATEONLYGRADED']['0']['#'], false); 1742 $course_category->aggregateoutcomes = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATEOUTCOMES']['0']['#'], false); 1743 $course_category->aggregatesubcats = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATESUBCATS']['0']['#'], false); 1744