PageRenderTime 123ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 2ms

/trunk/MoodleWebRole/backup/restorelib.php

#
PHP | 9497 lines | 6535 code | 988 blank | 1974 comment | 1799 complexity | e80ab7b2c91d48cd729e48a68e816ee5 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause, LGPL-2.0, GPL-2.0
  1. <?php //$Id: restorelib.php,v 1.283.2.97 2010/05/28 09:18:03 stronk7 Exp $
  2. //Functions used in restore
  3. require_once($CFG->libdir.'/gradelib.php');
  4. /**
  5. * Group backup/restore constants, 0.
  6. */
  7. define('RESTORE_GROUPS_NONE', 0);
  8. /**
  9. * Group backup/restore constants, 1.
  10. */
  11. define('RESTORE_GROUPS_ONLY', 1);
  12. /**
  13. * Group backup/restore constants, 2.
  14. */
  15. define('RESTORE_GROUPINGS_ONLY', 2);
  16. /**
  17. * Group backup/restore constants, course/all.
  18. */
  19. define('RESTORE_GROUPS_GROUPINGS', 3);
  20. //This function unzips a zip file in the same directory that it is
  21. //It automatically uses pclzip or command line unzip
  22. function restore_unzip ($file) {
  23. return unzip_file($file, '', false);
  24. }
  25. //This function checks if moodle.xml seems to be a valid xml file
  26. //(exists, has an xml header and a course main tag
  27. function restore_check_moodle_file ($file) {
  28. $status = true;
  29. //Check if it exists
  30. if ($status = is_file($file)) {
  31. //Open it and read the first 200 bytes (chars)
  32. $handle = fopen ($file, "r");
  33. $first_chars = fread($handle,200);
  34. $status = fclose ($handle);
  35. //Chek if it has the requires strings
  36. if ($status) {
  37. $status = strpos($first_chars,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
  38. if ($status !== false) {
  39. $status = strpos($first_chars,"<MOODLE_BACKUP>");
  40. }
  41. }
  42. }
  43. return $status;
  44. }
  45. //This function iterates over all modules in backup file, searching for a
  46. //MODNAME_refresh_events() to execute. Perhaps it should ve moved to central Moodle...
  47. function restore_refresh_events($restore) {
  48. global $CFG;
  49. $status = true;
  50. //Take all modules in backup
  51. $modules = $restore->mods;
  52. //Iterate
  53. foreach($modules as $name => $module) {
  54. //Only if the module is being restored
  55. if (isset($module->restore) && $module->restore == 1) {
  56. //Include module library
  57. include_once("$CFG->dirroot/mod/$name/lib.php");
  58. //If module_refresh_events exists
  59. $function_name = $name."_refresh_events";
  60. if (function_exists($function_name)) {
  61. $status = $function_name($restore->course_id);
  62. }
  63. }
  64. }
  65. return $status;
  66. }
  67. //This function makes all the necessary calls to xxxx_decode_content_links_caller()
  68. //function in each module/block/course format..., passing them the desired contents to be decoded
  69. //from backup format to destination site/course in order to mantain inter-activities
  70. //working in the backup/restore process
  71. function restore_decode_content_links($restore) {
  72. global $CFG;
  73. $status = true;
  74. if (!defined('RESTORE_SILENTLY')) {
  75. echo "<ul>";
  76. }
  77. // Recode links in the course summary.
  78. if (!defined('RESTORE_SILENTLY')) {
  79. echo '<li>' . get_string('from') . ' ' . get_string('course');
  80. }
  81. $course = get_record('course', 'id', $restore->course_id, '', '', '', '', 'id,summary');
  82. $coursesummary = backup_todb($course->summary,false); // Exception: Process FILEPHP (not available when restored) MDL-18222
  83. $coursesummary = restore_decode_content_links_worker($coursesummary, $restore);
  84. if ($coursesummary != $course->summary) {
  85. $course->summary = addslashes($coursesummary);
  86. if (!update_record('course', $course)) {
  87. $status = false;
  88. }
  89. }
  90. if (!defined('RESTORE_SILENTLY')) {
  91. echo '</li>';
  92. }
  93. // Recode links in section summaries.
  94. $sections = get_records('course_sections', 'course', $restore->course_id, 'id', 'id,summary');
  95. if ($sections) {
  96. if (!defined('RESTORE_SILENTLY')) {
  97. echo '<li>' . get_string('from') . ' ' . get_string('sections');
  98. }
  99. foreach ($sections as $section) {
  100. $sectionsummary = restore_decode_content_links_worker($section->summary, $restore);
  101. if ($sectionsummary != $section->summary) {
  102. $section->summary = addslashes($sectionsummary);
  103. if (!update_record('course_sections', $section)) {
  104. $status = false;
  105. }
  106. }
  107. }
  108. if (!defined('RESTORE_SILENTLY')) {
  109. echo '</li>';
  110. }
  111. }
  112. // Restore links in modules.
  113. foreach ($restore->mods as $name => $info) {
  114. //If the module is being restored
  115. if (isset($info->restore) && $info->restore == 1) {
  116. //Check if the xxxx_decode_content_links_caller exists
  117. include_once("$CFG->dirroot/mod/$name/restorelib.php");
  118. $function_name = $name."_decode_content_links_caller";
  119. if (function_exists($function_name)) {
  120. if (!defined('RESTORE_SILENTLY')) {
  121. echo "<li>".get_string ("from")." ".get_string("modulenameplural",$name);
  122. }
  123. $status = $function_name($restore) && $status;
  124. if (!defined('RESTORE_SILENTLY')) {
  125. echo '</li>';
  126. }
  127. }
  128. }
  129. }
  130. // For the course format call its decode_content_links method (if it exists)
  131. $format = get_field('course', 'format', 'id', $restore->course_id);
  132. if (file_exists("$CFG->dirroot/course/format/$format/restorelib.php")) {
  133. include_once("$CFG->dirroot/course/format/$format/restorelib.php");
  134. $function_name = $format.'_decode_format_content_links_caller';
  135. if (function_exists($function_name)) {
  136. if (!defined('RESTORE_SILENTLY')) {
  137. echo "<li>".get_string ("from")." ".get_string("format").' '.$format;
  138. }
  139. $status = $function_name($restore);
  140. if (!defined('RESTORE_SILENTLY')) {
  141. echo '</li>';
  142. }
  143. }
  144. }
  145. // Process all html text also in blocks too
  146. if (!defined('RESTORE_SILENTLY')) {
  147. echo '<li>'.get_string ('from').' '.get_string('blocks');
  148. }
  149. if ($blocks = get_records('block', 'visible', 1)) {
  150. foreach ($blocks as $block) {
  151. if ($blockobject = block_instance($block->name)) {
  152. $blockobject->decode_content_links_caller($restore);
  153. }
  154. }
  155. }
  156. if (!defined('RESTORE_SILENTLY')) {
  157. echo '</li>';
  158. }
  159. // Restore links in questions.
  160. require_once("$CFG->dirroot/question/restorelib.php");
  161. if (!defined('RESTORE_SILENTLY')) {
  162. echo '<li>' . get_string('from') . ' ' . get_string('questions', 'quiz');
  163. }
  164. $status = question_decode_content_links_caller($restore) && $status;
  165. if (!defined('RESTORE_SILENTLY')) {
  166. echo '</li>';
  167. }
  168. if (!defined('RESTORE_SILENTLY')) {
  169. echo "</ul>";
  170. }
  171. return $status;
  172. }
  173. /**
  174. * This function decodes some well-know links to course
  175. */
  176. function course_decode_content_links($content, $restore) {
  177. global $CFG;
  178. // Links to course
  179. $searchstring = '/\$@(COURSEVIEWBYID)\*([0-9]+)@\$/';
  180. $replacestring= $CFG->wwwroot . '/course/view.php?id=' . $restore->course_id;
  181. $result = preg_replace($searchstring, $replacestring, $content);
  182. return $result;
  183. }
  184. //This function is called from all xxxx_decode_content_links_caller(),
  185. //its task is to ask all modules (maybe other linkable objects) to restore
  186. //links to them.
  187. function restore_decode_content_links_worker($content,$restore) {
  188. global $CFG;
  189. // Course links decoder
  190. $content = course_decode_content_links($content, $restore);
  191. // Module links decoders
  192. foreach($restore->mods as $name => $info) {
  193. $function_name = $name."_decode_content_links";
  194. if (function_exists($function_name)) {
  195. $content = $function_name($content,$restore);
  196. }
  197. }
  198. // For the current format, call decode_format_content_links if it exists
  199. static $format_function_name;
  200. if (!isset($format_function_name)) {
  201. $format_function_name = false;
  202. if ($format = get_field('course', 'format', 'id', $restore->course_id)) {
  203. if (file_exists("$CFG->dirroot/course/format/$format/restorelib.php")) {
  204. include_once("$CFG->dirroot/course/format/$format/restorelib.php");
  205. $function_name = $format.'_decode_format_content_links';
  206. if (function_exists($function_name)) {
  207. $format_function_name = $function_name;
  208. }
  209. }
  210. }
  211. }
  212. // If the above worked - then we have a function to call
  213. if ($format_function_name) {
  214. $content = $format_function_name($content, $restore);
  215. }
  216. // For each block, call its encode_content_links method
  217. static $blockobjects = null;
  218. if (!isset($blockobjects)) {
  219. $blockobjects = array();
  220. if ($blocks = get_records('block', 'visible', 1)) {
  221. foreach ($blocks as $block) {
  222. if ($blockobject = block_instance($block->name)) {
  223. $blockobjects[] = $blockobject;
  224. }
  225. }
  226. }
  227. }
  228. foreach ($blockobjects as $blockobject) {
  229. $content = $blockobject->decode_content_links($content,$restore);
  230. }
  231. return $content;
  232. }
  233. //This function converts all the wiki texts in the restored course
  234. //to the Markdown format. Used only for backup files prior 2005041100.
  235. //It calls every module xxxx_convert_wiki2markdown function
  236. function restore_convert_wiki2markdown($restore) {
  237. $status = true;
  238. if (!defined('RESTORE_SILENTLY')) {
  239. echo "<ul>";
  240. }
  241. foreach ($restore->mods as $name => $info) {
  242. //If the module is being restored
  243. if ($info->restore == 1) {
  244. //Check if the xxxx_restore_wiki2markdown exists
  245. $function_name = $name."_restore_wiki2markdown";
  246. if (function_exists($function_name)) {
  247. $status = $function_name($restore);
  248. if (!defined('RESTORE_SILENTLY')) {
  249. echo "<li>".get_string("modulenameplural",$name);
  250. echo '</li>';
  251. }
  252. }
  253. }
  254. }
  255. if (!defined('RESTORE_SILENTLY')) {
  256. echo "</ul>";
  257. }
  258. return $status;
  259. }
  260. //This function receives a wiki text in the restore process and
  261. //return it with every link to modules " modulename:moduleid"
  262. //converted if possible. See the space before modulename!!
  263. function restore_decode_wiki_content($content,$restore) {
  264. global $CFG;
  265. $result = $content;
  266. $searchstring='/ ([a-zA-Z]+):([0-9]+)\(([^)]+)\)/';
  267. //We look for it
  268. preg_match_all($searchstring,$content,$foundset);
  269. //If found, then we are going to look for its new id (in backup tables)
  270. if ($foundset[0]) {
  271. //print_object($foundset); //Debug
  272. //Iterate over foundset[2]. They are the old_ids
  273. foreach($foundset[2] as $old_id) {
  274. //We get the needed variables here (course id)
  275. $rec = backup_getid($restore->backup_unique_code,"course_modules",$old_id);
  276. //Personalize the searchstring
  277. $searchstring='/ ([a-zA-Z]+):'.$old_id.'\(([^)]+)\)/';
  278. //If it is a link to this course, update the link to its new location
  279. if($rec->new_id) {
  280. //Now replace it
  281. $result= preg_replace($searchstring,' $1:'.$rec->new_id.'($2)',$result);
  282. } else {
  283. //It's a foreign link so redirect it to its original URL
  284. $result= preg_replace($searchstring,$restore->original_wwwroot.'/mod/$1/view.php?id='.$old_id.'($2)',$result);
  285. }
  286. }
  287. }
  288. return $result;
  289. }
  290. //This function read the xml file and store it data from the info zone in an object
  291. function restore_read_xml_info ($xml_file) {
  292. //We call the main read_xml function, with todo = INFO
  293. $info = restore_read_xml ($xml_file,"INFO",false);
  294. return $info;
  295. }
  296. //This function read the xml file and store it data from the course header zone in an object
  297. function restore_read_xml_course_header ($xml_file) {
  298. //We call the main read_xml function, with todo = COURSE_HEADER
  299. $info = restore_read_xml ($xml_file,"COURSE_HEADER",false);
  300. return $info;
  301. }
  302. //This function read the xml file and store its data from the blocks in a object
  303. function restore_read_xml_blocks ($restore, $xml_file) {
  304. //We call the main read_xml function, with todo = BLOCKS
  305. $info = restore_read_xml ($xml_file,'BLOCKS',$restore);
  306. return $info;
  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. //We call the main read_xml function, with todo = SECTIONS
  311. $info = restore_read_xml ($xml_file,"SECTIONS",false);
  312. return $info;
  313. }
  314. //This function read the xml file and store its data from the course format in an object
  315. function restore_read_xml_formatdata ($xml_file) {
  316. //We call the main read_xml function, with todo = FORMATDATA
  317. $info = restore_read_xml ($xml_file,'FORMATDATA',false);
  318. return $info;
  319. }
  320. //This function read the xml file and store its data from the metacourse in a object
  321. function restore_read_xml_metacourse ($xml_file) {
  322. //We call the main read_xml function, with todo = METACOURSE
  323. $info = restore_read_xml ($xml_file,"METACOURSE",false);
  324. return $info;
  325. }
  326. //This function read the xml file and store its data from the gradebook in a object
  327. function restore_read_xml_gradebook ($restore, $xml_file) {
  328. //We call the main read_xml function, with todo = GRADEBOOK
  329. $info = restore_read_xml ($xml_file,"GRADEBOOK",$restore);
  330. return $info;
  331. }
  332. //This function read the xml file and store its data from the users in
  333. //backup_ids->info db (and user's id in $info)
  334. function restore_read_xml_users ($restore,$xml_file) {
  335. //We call the main read_xml function, with todo = USERS
  336. $info = restore_read_xml ($xml_file,"USERS",$restore);
  337. return $info;
  338. }
  339. //This function read the xml file and store its data from the messages in
  340. //backup_ids->message backup_ids->message_read and backup_ids->contact and db (and their counters in info)
  341. function restore_read_xml_messages ($restore,$xml_file) {
  342. //We call the main read_xml function, with todo = MESSAGES
  343. $info = restore_read_xml ($xml_file,"MESSAGES",$restore);
  344. return $info;
  345. }
  346. //This function read the xml file and store its data from the blogs in
  347. //backup_ids->blog and backup_ids->blog_tag and db (and their counters in info)
  348. function restore_read_xml_blogs ($restore,$xml_file) {
  349. //We call the main read_xml function, with todo = BLOGS
  350. $info = restore_read_xml ($xml_file,"BLOGS",$restore);
  351. return $info;
  352. }
  353. //This function read the xml file and store its data from the questions in
  354. //backup_ids->info db (and category's id in $info)
  355. function restore_read_xml_questions ($restore,$xml_file) {
  356. //We call the main read_xml function, with todo = QUESTIONS
  357. $info = restore_read_xml ($xml_file,"QUESTIONS",$restore);
  358. return $info;
  359. }
  360. //This function read the xml file and store its data from the scales in
  361. //backup_ids->info db (and scale's id in $info)
  362. function restore_read_xml_scales ($restore,$xml_file) {
  363. //We call the main read_xml function, with todo = SCALES
  364. $info = restore_read_xml ($xml_file,"SCALES",$restore);
  365. return $info;
  366. }
  367. //This function read the xml file and store its data from the groups in
  368. //backup_ids->info db (and group's id in $info)
  369. function restore_read_xml_groups ($restore,$xml_file) {
  370. //We call the main read_xml function, with todo = GROUPS
  371. $info = restore_read_xml ($xml_file,"GROUPS",$restore);
  372. return $info;
  373. }
  374. //This function read the xml file and store its data from the groupings in
  375. //backup_ids->info db (and grouping's id in $info)
  376. function restore_read_xml_groupings ($restore,$xml_file) {
  377. //We call the main read_xml function, with todo = GROUPINGS
  378. $info = restore_read_xml ($xml_file,"GROUPINGS",$restore);
  379. return $info;
  380. }
  381. //This function read the xml file and store its data from the groupings in
  382. //backup_ids->info db (and grouping's id in $info)
  383. function restore_read_xml_groupings_groups ($restore,$xml_file) {
  384. //We call the main read_xml function, with todo = GROUPINGS
  385. $info = restore_read_xml ($xml_file,"GROUPINGSGROUPS",$restore);
  386. return $info;
  387. }
  388. //This function read the xml file and store its data from the events (course) in
  389. //backup_ids->info db (and event's id in $info)
  390. function restore_read_xml_events ($restore,$xml_file) {
  391. //We call the main read_xml function, with todo = EVENTS
  392. $info = restore_read_xml ($xml_file,"EVENTS",$restore);
  393. return $info;
  394. }
  395. //This function read the xml file and store its data from the modules in
  396. //backup_ids->info
  397. function restore_read_xml_modules ($restore,$xml_file) {
  398. //We call the main read_xml function, with todo = MODULES
  399. $info = restore_read_xml ($xml_file,"MODULES",$restore);
  400. return $info;
  401. }
  402. //This function read the xml file and store its data from the logs in
  403. //backup_ids->info
  404. function restore_read_xml_logs ($restore,$xml_file) {
  405. //We call the main read_xml function, with todo = LOGS
  406. $info = restore_read_xml ($xml_file,"LOGS",$restore);
  407. return $info;
  408. }
  409. function restore_read_xml_roles ($xml_file) {
  410. //We call the main read_xml function, with todo = ROLES
  411. $info = restore_read_xml ($xml_file,"ROLES",false);
  412. return $info;
  413. }
  414. //This function prints the contents from the info parammeter passed
  415. function restore_print_info ($info) {
  416. global $CFG;
  417. $status = true;
  418. if ($info) {
  419. $table = new object();
  420. //This is tha align to every ingo table
  421. $table->align = array ("right","left");
  422. //This is the nowrap clause
  423. $table->wrap = array ("","nowrap");
  424. //The width
  425. $table->width = "70%";
  426. //Put interesting info in table
  427. //The backup original name
  428. $tab[0][0] = "<b>".get_string("backuporiginalname").":</b>";
  429. $tab[0][1] = $info->backup_name;
  430. //The moodle version
  431. $tab[1][0] = "<b>".get_string("moodleversion").":</b>";
  432. $tab[1][1] = $info->backup_moodle_release." (".$info->backup_moodle_version.")";
  433. //The backup version
  434. $tab[2][0] = "<b>".get_string("backupversion").":</b>";
  435. $tab[2][1] = $info->backup_backup_release." (".$info->backup_backup_version.")";
  436. //The backup date
  437. $tab[3][0] = "<b>".get_string("backupdate").":</b>";
  438. $tab[3][1] = userdate($info->backup_date);
  439. //Is this the same Moodle install?
  440. if (!empty($info->original_siteidentifier)) {
  441. $tab[4][0] = "<b>".get_string("backupfromthissite").":</b>";
  442. if (backup_is_same_site($info)) {
  443. $tab[4][1] = get_string('yes');
  444. } else {
  445. $tab[4][1] = get_string('no');
  446. }
  447. }
  448. //Print title
  449. print_heading(get_string("backup").":");
  450. $table->data = $tab;
  451. //Print backup general info
  452. print_table($table);
  453. if ($info->backup_backup_version <= 2005070500) {
  454. notify(get_string('backupnonisowarning')); // Message informing that this backup may not work!
  455. }
  456. //Now backup contents in another table
  457. $tab = array();
  458. //First mods info
  459. $mods = $info->mods;
  460. $elem = 0;
  461. foreach ($mods as $key => $mod) {
  462. $tab[$elem][0] = "<b>".get_string("modulenameplural",$key).":</b>";
  463. if ($mod->backup == "false") {
  464. $tab[$elem][1] = get_string("notincluded");
  465. } else {
  466. if ($mod->userinfo == "true") {
  467. $tab[$elem][1] = get_string("included")." ".get_string("withuserdata");
  468. } else {
  469. $tab[$elem][1] = get_string("included")." ".get_string("withoutuserdata");
  470. }
  471. if (isset($mod->instances) && is_array($mod->instances) && count($mod->instances)) {
  472. foreach ($mod->instances as $instance) {
  473. if ($instance->backup) {
  474. $elem++;
  475. $tab[$elem][0] = $instance->name;
  476. if ($instance->userinfo == 'true') {
  477. $tab[$elem][1] = get_string("included")." ".get_string("withuserdata");
  478. } else {
  479. $tab[$elem][1] = get_string("included")." ".get_string("withoutuserdata");
  480. }
  481. }
  482. }
  483. }
  484. }
  485. $elem++;
  486. }
  487. //Metacourse info
  488. $tab[$elem][0] = "<b>".get_string("metacourse").":</b>";
  489. if ($info->backup_metacourse == "true") {
  490. $tab[$elem][1] = get_string("yes");
  491. } else {
  492. $tab[$elem][1] = get_string("no");
  493. }
  494. $elem++;
  495. //Users info
  496. $tab[$elem][0] = "<b>".get_string("users").":</b>";
  497. $tab[$elem][1] = get_string($info->backup_users);
  498. $elem++;
  499. //Logs info
  500. $tab[$elem][0] = "<b>".get_string("logs").":</b>";
  501. if ($info->backup_logs == "true") {
  502. $tab[$elem][1] = get_string("yes");
  503. } else {
  504. $tab[$elem][1] = get_string("no");
  505. }
  506. $elem++;
  507. //User Files info
  508. $tab[$elem][0] = "<b>".get_string("userfiles").":</b>";
  509. if ($info->backup_user_files == "true") {
  510. $tab[$elem][1] = get_string("yes");
  511. } else {
  512. $tab[$elem][1] = get_string("no");
  513. }
  514. $elem++;
  515. //Course Files info
  516. $tab[$elem][0] = "<b>".get_string("coursefiles").":</b>";
  517. if ($info->backup_course_files == "true") {
  518. $tab[$elem][1] = get_string("yes");
  519. } else {
  520. $tab[$elem][1] = get_string("no");
  521. }
  522. $elem++;
  523. //site Files info
  524. $tab[$elem][0] = "<b>".get_string("sitefiles").":</b>";
  525. if (isset($info->backup_site_files) && $info->backup_site_files == "true") {
  526. $tab[$elem][1] = get_string("yes");
  527. } else {
  528. $tab[$elem][1] = get_string("no");
  529. }
  530. $elem++;
  531. //gradebook history info
  532. $tab[$elem][0] = "<b>".get_string('gradebookhistories', 'grades').":</b>";
  533. if (isset($info->gradebook_histories) && $info->gradebook_histories == "true") {
  534. $tab[$elem][1] = get_string("yes");
  535. } else {
  536. $tab[$elem][1] = get_string("no");
  537. }
  538. $elem++;
  539. //Messages info (only showed if present)
  540. if ($info->backup_messages == 'true') {
  541. $tab[$elem][0] = "<b>".get_string('messages','message').":</b>";
  542. $tab[$elem][1] = get_string('yes');
  543. $elem++;
  544. } else {
  545. //Do nothing
  546. }
  547. $elem++;
  548. //Blogs info (only showed if present)
  549. if (isset($info->backup_blogs) && $info->backup_blogs == 'true') {
  550. $tab[$elem][0] = "<b>".get_string('blogs','blog').":</b>";
  551. $tab[$elem][1] = get_string('yes');
  552. $elem++;
  553. } else {
  554. //Do nothing
  555. }
  556. $table->data = $tab;
  557. //Print title
  558. print_heading(get_string("backupdetails").":");
  559. //Print backup general info
  560. print_table($table);
  561. } else {
  562. $status = false;
  563. }
  564. return $status;
  565. }
  566. //This function prints the contents from the course_header parammeter passed
  567. function restore_print_course_header ($course_header) {
  568. $status = true;
  569. if ($course_header) {
  570. $table = new object();
  571. //This is tha align to every ingo table
  572. $table->align = array ("right","left");
  573. //The width
  574. $table->width = "70%";
  575. //Put interesting course header in table
  576. //The course name
  577. $tab[0][0] = "<b>".get_string("name").":</b>";
  578. $tab[0][1] = $course_header->course_fullname." (".$course_header->course_shortname.")";
  579. //The course summary
  580. $tab[1][0] = "<b>".get_string("summary").":</b>";
  581. $tab[1][1] = $course_header->course_summary;
  582. $table->data = $tab;
  583. //Print title
  584. print_heading(get_string("course").":");
  585. //Print backup course header info
  586. print_table($table);
  587. } else {
  588. $status = false;
  589. }
  590. return $status;
  591. }
  592. /**
  593. * Given one user object (from backup file), perform all the neccesary
  594. * checks is order to decide how that user will be handled on restore.
  595. *
  596. * Note the function requires $user->mnethostid to be already calculated
  597. * so it's caller responsibility to set it
  598. *
  599. * This function is used both by @restore_precheck_users() and
  600. * @restore_create_users() to get consistent results in both places
  601. *
  602. * It returns:
  603. * - one user object (from DB), if match has been found and user will be remapped
  604. * - boolean true if the user needs to be created
  605. * - boolean false if some conflict happened and the user cannot be handled
  606. *
  607. * Each test is responsible for returning its results and interrupt
  608. * execution. At the end, boolean true (user needs to be created) will be
  609. * returned if no test has interrupted that.
  610. *
  611. * Here it's the logic applied, keep it updated:
  612. *
  613. * If restoring users from same site backup:
  614. * 1A - Normal check: If match by id and username and mnethost => ok, return target user
  615. * 1B - Handle users deleted in DB and "alive" in backup file:
  616. * If match by id and mnethost and user is deleted in DB and
  617. * (match by username LIKE 'backup_email.%' or by non empty email = md5(username)) => ok, return target user
  618. * 1C - Handle users deleted in backup file and "alive" in DB:
  619. * If match by id and mnethost and user is deleted in backup file
  620. * and match by email = email_without_time(backup_email) => ok, return target user
  621. * 1D - Conflict: If match by username and mnethost and doesn't match by id => conflict, return false
  622. * 1E - None of the above, return true => User needs to be created
  623. *
  624. * if restoring from another site backup (cannot match by id here, replace it by email/firstaccess combination):
  625. * 2A - Normal check: If match by username and mnethost and (email or non-zero firstaccess) => ok, return target user
  626. * 2B - Handle users deleted in DB and "alive" in backup file:
  627. * 2B1 - If match by mnethost and user is deleted in DB and not empty email = md5(username) and
  628. * (username LIKE 'backup_email.%' or non-zero firstaccess) => ok, return target user
  629. * 2B2 - If match by mnethost and user is deleted in DB and
  630. * username LIKE 'backup_email.%' and non-zero firstaccess) => ok, return target user
  631. * (to cover situations were md5(username) wasn't implemented on delete we requiere both)
  632. * 2C - Handle users deleted in backup file and "alive" in DB:
  633. * If match mnethost and user is deleted in backup file
  634. * and by email = email_without_time(backup_email) and non-zero firstaccess=> ok, return target user
  635. * 2D - Conflict: If match by username and mnethost and not by (email or non-zero firstaccess) => conflict, return false
  636. * 2E - None of the above, return true => User needs to be created
  637. *
  638. * Note: for DB deleted users email is stored in username field, hence we
  639. * are looking there for emails. See delete_user()
  640. * Note: for DB deleted users md5(username) is stored *sometimes* in the email field,
  641. * hence we are looking there for usernames if not empty. See delete_user()
  642. */
  643. function restore_check_user($restore, $user) {
  644. global $CFG;
  645. // Verify mnethostid is set, return error if not
  646. // it's parent responsibility to define that before
  647. // arriving here
  648. if (empty($user->mnethostid)) {
  649. debugging("restore_check_user() wrong use, mnethostid not set for user $user->username", DEBUG_DEVELOPER);
  650. return false;
  651. }
  652. // Handle checks from same site backups
  653. if (backup_is_same_site($restore) && empty($CFG->forcedifferentsitecheckingusersonrestore)) {
  654. // 1A - If match by id and username and mnethost => ok, return target user
  655. if ($rec = get_record('user', 'id', $user->id, 'username', addslashes($user->username), 'mnethostid', $user->mnethostid)) {
  656. return $rec; // Matching user found, return it
  657. }
  658. // 1B - Handle users deleted in DB and "alive" in backup file
  659. // Note: for DB deleted users email is stored in username field, hence we
  660. // are looking there for emails. See delete_user()
  661. // Note: for DB deleted users md5(username) is stored *sometimes* in the email field,
  662. // hence we are looking there for usernames if not empty. See delete_user()
  663. // If match by id and mnethost and user is deleted in DB and
  664. // match by username LIKE 'backup_email.%' or by non empty email = md5(username) => ok, return target user
  665. if ($rec = get_record_sql("SELECT *
  666. FROM {$CFG->prefix}user u
  667. WHERE id = $user->id
  668. AND mnethostid = $user->mnethostid
  669. AND deleted = 1
  670. AND (
  671. username LIKE '".addslashes($user->email).".%'
  672. OR (
  673. ".sql_isnotempty('user', 'email', false, false)."
  674. AND email = '".md5($user->username)."'
  675. )
  676. )")) {
  677. return $rec; // Matching user, deleted in DB found, return it
  678. }
  679. // 1C - Handle users deleted in backup file and "alive" in DB
  680. // If match by id and mnethost and user is deleted in backup file
  681. // and match by email = email_without_time(backup_email) => ok, return target user
  682. if ($user->deleted) {
  683. // Note: for DB deleted users email is stored in username field, hence we
  684. // are looking there for emails. See delete_user()
  685. // Trim time() from email
  686. $trimemail = preg_replace('/(.*?)\.[0-9]+.?$/', '\\1', $user->username);
  687. if ($rec = get_record_sql("SELECT *
  688. FROM {$CFG->prefix}user u
  689. WHERE id = $user->id
  690. AND mnethostid = $user->mnethostid
  691. AND email = '".addslashes($trimemail)."'")) {
  692. return $rec; // Matching user, deleted in backup file found, return it
  693. }
  694. }
  695. // 1D - If match by username and mnethost and doesn't match by id => conflict, return false
  696. if ($rec = get_record('user', 'username', addslashes($user->username), 'mnethostid', $user->mnethostid)) {
  697. if ($user->id != $rec->id) {
  698. return false; // Conflict, username already exists and belongs to another id
  699. }
  700. }
  701. // Handle checks from different site backups
  702. } else {
  703. // 2A - If match by username and mnethost and
  704. // (email or non-zero firstaccess) => ok, return target user
  705. if ($rec = get_record_sql("SELECT *
  706. FROM {$CFG->prefix}user u
  707. WHERE username = '".addslashes($user->username)."'
  708. AND mnethostid = $user->mnethostid
  709. AND (
  710. email = '".addslashes($user->email)."'
  711. OR (
  712. firstaccess != 0
  713. AND firstaccess = $user->firstaccess
  714. )
  715. )")) {
  716. return $rec; // Matching user found, return it
  717. }
  718. // 2B - Handle users deleted in DB and "alive" in backup file
  719. // Note: for DB deleted users email is stored in username field, hence we
  720. // are looking there for emails. See delete_user()
  721. // Note: for DB deleted users md5(username) is stored *sometimes* in the email field,
  722. // hence we are looking there for usernames if not empty. See delete_user()
  723. // 2B1 - If match by mnethost and user is deleted in DB and not empty email = md5(username) and
  724. // (by username LIKE 'backup_email.%' or non-zero firstaccess) => ok, return target user
  725. if ($rec = get_record_sql("SELECT *
  726. FROM {$CFG->prefix}user u
  727. WHERE mnethostid = $user->mnethostid
  728. AND deleted = 1
  729. AND ".sql_isnotempty('user', 'email', false, false)."
  730. AND email = '".md5($user->username)."'
  731. AND (
  732. username LIKE '".addslashes($user->email).".%'
  733. OR (
  734. firstaccess != 0
  735. AND firstaccess = $user->firstaccess
  736. )
  737. )")) {
  738. return $rec; // Matching user found, return it
  739. }
  740. // 2B2 - If match by mnethost and user is deleted in DB and
  741. // username LIKE 'backup_email.%' and non-zero firstaccess) => ok, return target user
  742. // (this covers situations where md5(username) wasn't being stored so we require both
  743. // the email & non-zero firstaccess to match)
  744. if ($rec = get_record_sql("SELECT *
  745. FROM {$CFG->prefix}user u
  746. WHERE mnethostid = $user->mnethostid
  747. AND deleted = 1
  748. AND username LIKE '".addslashes($user->email).".%'
  749. AND firstaccess != 0
  750. AND firstaccess = $user->firstaccess")) {
  751. return $rec; // Matching user found, return it
  752. }
  753. // 2C - Handle users deleted in backup file and "alive" in DB
  754. // If match mnethost and user is deleted in backup file
  755. // and match by email = email_without_time(backup_email) and non-zero firstaccess=> ok, return target user
  756. if ($user->deleted) {
  757. // Note: for DB deleted users email is stored in username field, hence we
  758. // are looking there for emails. See delete_user()
  759. // Trim time() from email
  760. $trimemail = preg_replace('/(.*?)\.[0-9]+.?$/', '\\1', $user->username);
  761. if ($rec = get_record_sql("SELECT *
  762. FROM {$CFG->prefix}user u
  763. WHERE mnethostid = $user->mnethostid
  764. AND email = '".addslashes($trimemail)."'
  765. AND firstaccess != 0
  766. AND firstaccess = $user->firstaccess")) {
  767. return $rec; // Matching user, deleted in backup file found, return it
  768. }
  769. }
  770. // 2D - If match by username and mnethost and not by (email or non-zero firstaccess) => conflict, return false
  771. if ($rec = get_record_sql("SELECT *
  772. FROM {$CFG->prefix}user u
  773. WHERE username = '".addslashes($user->username)."'
  774. AND mnethostid = $user->mnethostid
  775. AND NOT (
  776. email = '".addslashes($user->email)."'
  777. OR (
  778. firstaccess != 0
  779. AND firstaccess = $user->firstaccess
  780. )
  781. )")) {
  782. return false; // Conflict, username/mnethostid already exist and belong to another user (by email/firstaccess)
  783. }
  784. }
  785. // Arrived here, return true as the user will need to be created and no
  786. // conflicts have been found in the logic above. This covers:
  787. // 1E - else => user needs to be created, return true
  788. // 2E - else => user needs to be created, return true
  789. return true;
  790. }
  791. /**
  792. * For all the users being restored, check if they are going to cause problems
  793. * before executing the restore process itself, detecting situations like:
  794. * - conflicts preventing restore to continue - provided by @restore_check_user()
  795. * - prevent creation of users if not allowed - check some global settings/caps
  796. */
  797. function restore_precheck_users($xml_file, $restore, &$problems) {
  798. global $CFG;
  799. $status = true; // Init $status
  800. // We aren't restoring users, nothing to check, allow continue
  801. if ($restore->users == 2) {
  802. return true;
  803. }
  804. // Get array of users from xml file and load them in backup_ids table
  805. if (!$info = restore_read_xml_users($restore,$xml_file)) {
  806. return true; // No users, nothing to check, allow continue
  807. }
  808. // We are going to map mnethostid, so load all the available ones
  809. $mnethosts = get_records('mnet_host', '', '', 'wwwroot', 'wwwroot, id');
  810. // Calculate the context we are going to use for capability checking
  811. if (!empty($restore->course_id)) { // Know the target (existing) course, check capabilities there
  812. $context = get_context_instance(CONTEXT_COURSE, $restore->course_id);
  813. } else if (!empty($restore->restore_restorecatto)) { // Know the category, check capabilities there
  814. $context = get_context_instance(CONTEXT_COURSECAT, $restore->restore_restorecatto);
  815. } else { // Last resort, check capabilities at system level
  816. $context = get_context_instance(CONTEXT_SYSTEM);
  817. }
  818. // Calculate if we have perms to create users, by checking:
  819. // to 'moodle/restore:createuser' and 'moodle/restore:userinfo'
  820. // and also observe $CFG->disableusercreationonrestore
  821. $cancreateuser = false;
  822. if (has_capability('moodle/restore:createuser', $context) and
  823. has_capability('moodle/restore:userinfo', $context) and
  824. empty($CFG->disableusercreationonrestore)) { // Can create users
  825. $cancreateuser = true;
  826. }
  827. // Iterate over all users, checking if they are likely to cause problems on restore
  828. $counter = 0;
  829. foreach ($info->users as $userid) {
  830. $rec = backup_getid($restore->backup_unique_code, 'user', $userid);
  831. $user = $rec->info;
  832. // Find the correct mnethostid for user before performing any further check
  833. if (empty($user->mnethosturl) || $user->mnethosturl === $CFG->wwwroot) {
  834. $user->mnethostid = $CFG->mnet_localhost_id;
  835. } else {
  836. // fast url-to-id lookups
  837. if (isset($mnethosts[$user->mnethosturl])) {
  838. $user->mnethostid = $mnethosts[$user->mnethosturl]->id;
  839. } else {
  840. $user->mnethostid = $CFG->mnet_localhost_id;
  841. }
  842. }
  843. // Calculate the best way to handle this user from backup file
  844. $usercheck = restore_check_user($restore, $user);
  845. if (is_object($usercheck)) { // No problem, we have found one user in DB to be mapped to
  846. // Annotate it, for later process by restore_create_users(). Set new_id to mapping user->id
  847. backup_putid($restore->backup_unique_code, 'user', $userid, $usercheck->id, $user);
  848. } else if ($usercheck === false) { // Found conflict, report it as problem
  849. $problems[] = get_string('restoreuserconflict', '', $user->username);
  850. $status = false;
  851. } else if ($usercheck === true) { // User needs to be created, check if we are able
  852. if ($cancreateuser) { // Can create user, annotate it, for later process by restore_create_users(). Set new_id to 0
  853. backup_putid($restore->backup_unique_code, 'user', $userid, 0, $user);
  854. } else { // Cannot create user, report it as problem
  855. $problems[] = get_string('restorecannotcreateuser', '', $user->username);
  856. $status = false;
  857. }
  858. } else { // Shouldn't arrive here ever, something is for sure wrong in restore_check_user()
  859. if (!defined('RESTORE_SILENTLY')) {
  860. notify('Unexpected error pre-checking user ' . s($user->username) . ' from backup file');
  861. return false;
  862. }
  863. }
  864. // Do some output
  865. $counter++;
  866. if ($counter % 10 == 0) {
  867. if (!defined('RESTORE_SILENTLY')) {
  868. echo ".";
  869. if ($counter % 200 == 0) {
  870. echo "<br />";
  871. }
  872. }
  873. backup_flush(300);
  874. }
  875. }
  876. return $status;
  877. }
  878. //This function create a new course record.
  879. //When finished, course_header contains the id of the new course
  880. function restore_create_new_course($restore,&$course_header) {
  881. global $CFG, $SESSION;
  882. $status = true;
  883. $fullname = $course_header->course_fullname;
  884. $shortname = $course_header->course_shortname;
  885. $currentfullname = "";
  886. $currentshortname = "";
  887. $counter = 0;
  888. //Iteratere while the name exists
  889. do {
  890. if ($counter) {
  891. $suffixfull = " ".get_string("copyasnoun")." ".$counter;
  892. $suffixshort = "_".$counter;
  893. } else {
  894. $suffixfull = "";
  895. $suffixshort = "";
  896. }
  897. $currentfullname = $fullname.$suffixfull;
  898. // Limit the size of shortname - database column accepts <= 100 chars
  899. $currentshortname = substr($shortname, 0, 100 - strlen($suffixshort)).$suffixshort;
  900. $coursefull = get_record("course","fullname",addslashes($currentfullname));
  901. $courseshort = get_record("course","shortname",addslashes($currentshortname));
  902. $counter++;
  903. } while ($coursefull || $courseshort);
  904. //New name = currentname
  905. $course_header->course_fullname = $currentfullname;
  906. $course_header->course_shortname = $currentshortname;
  907. // first try to get it from restore
  908. if ($restore->restore_restorecatto) {
  909. $category = get_record('course_categories', 'id', $restore->restore_restorecatto);
  910. }
  911. // else we try to get it from the xml file
  912. //Now calculate the category
  913. if (empty($category)) {
  914. $category = get_record("course_categories","id",$course_header->category->id,
  915. "name",addslashes($course_header->category->name));
  916. }
  917. //If no exists, try by name only
  918. if (!$category) {
  919. $category = get_record("course_categories","name",addslashes($course_header->category->name));
  920. }
  921. //If no exists, get category id 1
  922. if (!$category) {
  923. $category = get_record("course_categories","id","1");
  924. }
  925. //If category 1 doesn'exists, lets create the course category (get it from backup file)
  926. if (!$category) {
  927. $ins_category = new object();
  928. $ins_category->name = addslashes($course_header->category->name);
  929. $ins_category->parent = 0;
  930. $ins_category->sortorder = 0;
  931. $ins_category->coursecount = 0;
  932. $ins_category->visible = 0; //To avoid interferences with the rest of the site
  933. $ins_category->timemodified = time();
  934. $newid = insert_record("course_categories",$ins_category);
  935. $category->id = $newid;
  936. $category->name = $course_header->category->name;
  937. }
  938. //If exists, put new category id
  939. if ($category) {
  940. $course_header->category->id = $category->id;
  941. $course_header->category->name = $category->name;
  942. //Error, cannot locate category
  943. } else {
  944. $course_header->category->id = 0;
  945. $course_header->category->name = get_string("unknowncategory");
  946. $status = false;
  947. }
  948. //Create the course_object
  949. if ($status) {
  950. $course = new object();
  951. $course->category = addslashes($course_header->category->id);
  952. $course->password = addslashes($course_header->course_password);
  953. $course->fullname = addslashes($course_header->course_fullname);
  954. $course->shortname = addslashes($course_header->course_shortname);
  955. $course->idnumber = addslashes($course_header->course_idnumber);
  956. $course->idnumber = ''; //addslashes($course_header->course_idnumber); // we don't want this at all.
  957. $course->summary = addslashes($course_header->course_summary);
  958. $course->format = addslashes($course_header->course_format);
  959. $course->showgrades = addslashes($course_header->course_showgrades);
  960. $course->newsitems = addslashes($course_header->course_newsitems);
  961. $course->teacher = addslashes($course_header->course_teacher);
  962. $course->teachers = addslashes($course_header->course_teachers);
  963. $course->student = addslashes($course_header->course_student);
  964. $course->students = addslashes($course_header->course_students);
  965. $course->guest = addslashes($course_header->course_guest);
  966. $course->startdate = addslashes($course_header->course_startdate);
  967. $course->startdate += $restore->course_startdateoffset;
  968. $course->numsections = addslashes($course_header->course_numsections);
  969. //$course->showrecent = addslashes($course_header->course_showrecent); INFO: This is out in 1.3
  970. $course->maxbytes = addslashes($course_header->course_maxbytes);
  971. $course->showreports = addslashes($course_header->course_showreports);
  972. if (isset($course_header->course_groupmode)) {
  973. $course->groupmode = addslashes($course_header->course_groupmode);
  974. }
  975. if (isset($course_header->course_groupmodeforce)) {
  976. $course->groupmodeforce = addslashes($course_header->course_groupmodeforce);
  977. }
  978. if (isset($course_header->course_defaultgroupingid)) {
  979. //keep the original now - convert after groupings restored
  980. $course->defaultgroupingid = addslashes($course_header->course_defaultgroupingid);
  981. }
  982. $course->lang = addslashes($course_header->course_lang);
  983. $course->theme = addslashes($course_header->course_theme);
  984. $course->cost = addslashes($course_header->course_cost);
  985. $course->currency = isset($course_header->course_currency)?addslashes($course_header->course_currency):'';
  986. $course->marker = addslashes($course_header->course_marker);
  987. $course->visible = addslashes($course_header->course_visible);
  988. $course->hiddensections = addslashes($course_header->course_hiddensections);
  989. $course->timecreated = addslashes($course_header->course_timecreated);
  990. $course->timemodified = addslashes($course_header->course_timemodified);
  991. $course->metacourse = addslashes($course_header->course_metacourse);
  992. $course->expirynotify = isset($course_header->course_expirynotify) ? addslashes($course_header->course_expirynotify):0;
  993. $course->notifystudents = isset($course_header->course_notifystudents) ? addslashes($course_header->course_notifystudents) : 0;
  994. $course->expirythreshold = isset($course_header->course_expirythreshold) ? addslashes($course_header->course_expirythreshold) : 0;
  995. $course->enrollable = isset($course_header->course_enrollable) ? addslashes($course_header->course_enrollable) : 1;
  996. $course->enrolstartdate = isset($course_header->course_enrolstartdate) ? addslashes($course_header->course_enrolstartdate) : 0;
  997. if ($course->enrolstartdate) { //Roll course dates
  998. $course->enrolstartdate += $restore->course_startdateoffset;
  999. }
  1000. $course->enrolenddate = isset($course_header->course_enrolenddate) ? addslashes($course_header->course_enrolenddate) : 0;
  1001. if ($course->enrolenddate) { //Roll course dates
  1002. $course->enrolenddate += $restore->course_startdateoffset;
  1003. }
  1004. $course->enrolperiod = addslashes($course_header->course_enrolperiod);
  1005. //Calculate sortorder field
  1006. $sortmax = get_record_sql('SELECT MAX(sortorder) AS max
  1007. FROM ' . $CFG->prefix . 'course
  1008. WHERE category=' . $course->category);
  1009. if (!empty($sortmax->max)) {
  1010. $course->sortorder = $sortmax->max + 1;
  1011. unset($sortmax);
  1012. } else {
  1013. $course->sortorder = 100;
  1014. }
  1015. //Now, recode some languages (Moodle 1.5)
  1016. if ($course->lang == 'ma_nt') {
  1017. $course->lang = 'mi_nt';
  1018. }
  1019. //Disable course->metacourse if avoided in restore config
  1020. if (!$restore->metacourse) {
  1021. $course->metacourse = 0;
  1022. }
  1023. //Check if the theme exists in destination server
  1024. $themes = get_list_of_themes();
  1025. if (!in_array($course->theme, $themes)) {
  1026. $course->theme = '';
  1027. }
  1028. //Now insert the record
  1029. $newid = insert_record("course",$course);
  1030. if ($newid) {
  1031. //save old and new course id
  1032. backup_putid ($restore->backup_unique_code,"course",$course_header->course_id,$newid);
  1033. //Replace old course_id in course_header
  1034. $course_header->course_id = $newid;
  1035. $SESSION->restore->course_id = $newid;
  1036. return $newid;
  1037. } else {
  1038. $status = false;
  1039. }
  1040. }
  1041. return $status;
  1042. }
  1043. //This function creates all the block stuff when restoring courses
  1044. //It calls selectively to restore_create_block_instances() for 1.5
  1045. //and above backups. Upwards compatible with old blocks.
  1046. function restore_create_blocks($restore, $backup_block_format, $blockinfo, $xml_file) {
  1047. global $CFG;
  1048. $status = true;
  1049. blocks_delete_all_on_page(PAGE_COURSE_VIEW, $restore->course_id);
  1050. if (empty($backup_block_format)) { // This is a backup from Moodle < 1.5
  1051. if (empty($blockinfo)) {
  1052. // Looks like it's from Moodle < 1.3. Let's give the course default blocks...
  1053. $newpage = page_create_object(PAGE_COURSE_VIEW, $restore->course_id);
  1054. blocks_repopulate_page($newpage);
  1055. } else {
  1056. // We just have a blockinfo field, this is a legacy 1.4 or 1.3 backup
  1057. $blockrecords = get_records_select('block', '', '', 'name, id');
  1058. $temp_blocks_l = array();
  1059. $temp_blocks_r = array();
  1060. @list($temp_blocks_l, $temp_blocks_r) = explode(':', $blockinfo);
  1061. $temp_blocks = array(BLOCK_POS_LEFT => explode(',', $temp_blocks_l), BLOCK_POS_RIGHT => explode(',', $temp_blocks_r));
  1062. foreach($temp_blocks as $blockposition => $blocks) {
  1063. $blockweight = 0;
  1064. foreach($blocks as $blockname) {
  1065. if(!isset($blockrecords[$blockname])) {
  1066. // We don't know anything about this block!
  1067. continue;
  1068. }
  1069. $blockinstance = new stdClass;
  1070. // Remove any - prefix before doing the name-to-id mapping
  1071. if(substr($blockname, 0, 1) == '-') {
  1072. $blockname = substr($blockname, 1);
  1073. $blockinstance->visible = 0;
  1074. } else {
  1075. $blockinstance->visible = 1;
  1076. }
  1077. $blockinstance->blockid = $blockrecords[$blockname]->id;
  1078. $blockinstance->pageid = $restore->course_id;
  1079. $blockinstance->pagetype = PAGE_COURSE_VIEW;
  1080. $blockinstance->position = $blockposition;
  1081. $blockinstance->weight = $blockweight;
  1082. if(!$status = insert_record('block_instance', $blockinstance)) {
  1083. $status = false;
  1084. }
  1085. ++$blockweight;
  1086. }
  1087. }
  1088. }
  1089. } else if($backup_block_format == 'instances') {
  1090. $status = restore_create_block_instances($restore,$xml_file);
  1091. }
  1092. return $status;
  1093. }
  1094. //This function creates all the block_instances from xml when restoring in a
  1095. //new course
  1096. function restore_create_block_instances($restore,$xml_file) {
  1097. global $CFG;
  1098. $status = true;
  1099. //Check it exists
  1100. if (!file_exists($xml_file)) {
  1101. $status = false;
  1102. }
  1103. //Get info from xml
  1104. if ($status) {
  1105. $info = restore_read_xml_blocks($restore,$xml_file);
  1106. }
  1107. if(empty($info->instances)) {
  1108. return $status;
  1109. }
  1110. // First of all, iterate over the blocks to see which distinct pages we have
  1111. // in our hands and arrange the blocks accordingly.
  1112. $pageinstances = array();
  1113. foreach($info->instances as $instance) {
  1114. //pagetype and pageid black magic, we have to handle the case of blocks for the
  1115. //course, blocks from other pages in that course etc etc etc.
  1116. if($instance->pagetype == PAGE_COURSE_VIEW) {
  1117. // This one's easy...
  1118. $instance->pageid = $restore->course_id;
  1119. } else if (!empty($CFG->showblocksonmodpages)) {
  1120. $parts = explode('-', $instance->pagetype);
  1121. if($parts[0] == 'mod') {
  1122. if(!$restore->mods[$parts[1]]->restore) {
  1123. continue;
  1124. }
  1125. $getid = backup_getid($restore->backup_unique_code, $parts[1], $instance->pageid);
  1126. if (empty($getid->new_id)) {
  1127. // Failed, perhaps the module was not included in the restore MDL-13554
  1128. continue;
  1129. }
  1130. $instance->pageid = $getid->new_id;
  1131. }
  1132. else {
  1133. // Not invented here ;-)
  1134. continue;
  1135. }
  1136. } else {
  1137. // do not restore activity blocks if disabled
  1138. continue;
  1139. }
  1140. if(!isset($pageinstances[$instance->pagetype])) {
  1141. $pageinstances[$instance->pagetype] = array();
  1142. }
  1143. if(!isset($pageinstances[$instance->pagetype][$instance->pageid])) {
  1144. $pageinstances[$instance->pagetype][$instance->pageid] = array();
  1145. }
  1146. $pageinstances[$instance->pagetype][$instance->pageid][] = $instance;
  1147. }
  1148. $blocks = get_records_select('block', 'visible = 1', '', 'name, id, multiple');
  1149. // For each type of page we have restored
  1150. foreach($pageinstances as $thistypeinstances) {
  1151. // For each page id of that type
  1152. foreach($thistypeinstances as $thisidinstances) {
  1153. $addedblocks = array();
  1154. $maxweights = array();
  1155. // For each block instance in that page
  1156. foreach($thisidinstances as $instance) {
  1157. if(!isset($blocks[$instance->name])) {
  1158. //We are trying to restore a block we don't have...
  1159. continue;
  1160. }
  1161. //If we have already added this block once and multiples aren't allowed, disregard it
  1162. if(!$blocks[$instance->name]->multiple && isset($addedblocks[$instance->name])) {
  1163. continue;
  1164. }
  1165. //If its the first block we add to a new position, start weight counter equal to 0.
  1166. if(empty($maxweights[$instance->position])) {
  1167. $maxweights[$instance->position] = 0;
  1168. }
  1169. //If the instance weight is greater than the weight counter (we skipped some earlier
  1170. //blocks most probably), bring it back in line.
  1171. if($instance->weight > $maxweights[$instance->position]) {
  1172. $instance->weight = $maxweights[$instance->position];
  1173. }
  1174. //Add this instance
  1175. $instance->blockid = $blocks[$instance->name]->id;
  1176. // This will only be set if we come from 1.7 and above backups
  1177. // Also, must do this before insert (insert_record unsets id)
  1178. if (!empty($instance->id)) {
  1179. $oldid = $instance->id;
  1180. } else {
  1181. $oldid = 0;
  1182. }
  1183. if ($instance->id = insert_record('block_instance', $instance)) {
  1184. // Create block instance
  1185. if (!$blockobj = block_instance($instance->name, $instance)) {
  1186. $status = false;
  1187. break;
  1188. }
  1189. // Run the block restore if needed
  1190. if ($blockobj->backuprestore_instancedata_used()) {
  1191. // Get restore information
  1192. $data = backup_getid($restore->backup_unique_code,'block_instance',$oldid);
  1193. $data->new_id = $instance->id; // For completeness
  1194. if (!$blockobj->instance_restore($restore, $data)) {
  1195. $status = false;
  1196. break;
  1197. }
  1198. }
  1199. // Save oldid after block restore process because info will be over-written with blank string
  1200. if ($oldid) {
  1201. backup_putid ($restore->backup_unique_code,"block_instance",$oldid,$instance->id);
  1202. }
  1203. } else {
  1204. $status = false;
  1205. break;
  1206. }
  1207. //Get an object for the block and tell it it's been restored so it can update dates
  1208. //etc. if necessary
  1209. if ($blockobj = block_instance($instance->name,$instance)) {
  1210. $blockobj->after_restore($restore);
  1211. }
  1212. //Now we can increment the weight counter
  1213. ++$maxweights[$instance->position];
  1214. //Keep track of block types we have already added
  1215. $addedblocks[$instance->name] = true;
  1216. }
  1217. }
  1218. }
  1219. return $status;
  1220. }
  1221. //This function creates all the course_sections and course_modules from xml
  1222. //when restoring in a new course or simply checks sections and create records
  1223. //in backup_ids when restoring in a existing course
  1224. function restore_create_sections(&$restore, $xml_file) {
  1225. global $CFG,$db;
  1226. $status = true;
  1227. //Check it exists
  1228. if (!file_exists($xml_file)) {
  1229. $status = false;
  1230. }
  1231. //Get info from xml
  1232. if ($status) {
  1233. $info = restore_read_xml_sections($xml_file);
  1234. }
  1235. //Put the info in the DB, recoding ids and saving the in backup tables
  1236. $sequence = "";
  1237. if ($info) {
  1238. //For each, section, save it to db
  1239. foreach ($info->sections as $key => $sect) {
  1240. $sequence = "";
  1241. $section = new object();
  1242. $section->course = $restore->course_id;
  1243. $section->section = $sect->number;
  1244. $section->summary = backup_todb($sect->summary);
  1245. $section->visible = $sect->visible;
  1246. $section->sequence = "";
  1247. //Now calculate the section's newid
  1248. $newid = 0;
  1249. if ($restore->restoreto == RESTORETO_NEW_COURSE) {
  1250. //Save it to db (only if restoring to new course)
  1251. $newid = insert_record("course_sections",$section);
  1252. } else {
  1253. //Get section id when restoring in existing course
  1254. $rec = get_record("course_sections","course",$restore->course_id,
  1255. "section",$section->section);
  1256. //If section exists, has empty summary and backup has some summary, use it. MDL-8848
  1257. if ($rec && empty($rec->summary) && !empty($section->summary)) {
  1258. $rec->summary = $section->summary;
  1259. update_record("course_sections", $rec);
  1260. }
  1261. //If that section doesn't exist, get section 0 (every mod will be
  1262. //asigned there
  1263. if(!$rec) {
  1264. $rec = get_record("course_sections","course",$restore->course_id,
  1265. "section","0");
  1266. }
  1267. //New check. If section 0 doesn't exist, insert it here !!
  1268. //Teorically this never should happen but, in practice, some users
  1269. //have reported this issue.
  1270. if(!$rec) {
  1271. $zero_sec = new object();
  1272. $zero_sec->course = $restore->course_id;
  1273. $zero_sec->section = 0;
  1274. $zero_sec->summary = "";
  1275. $zero_sec->sequence = "";
  1276. $newid = insert_record("course_sections",$zero_sec);
  1277. $rec->id = $newid;
  1278. $rec->sequence = "";
  1279. }
  1280. $newid = $rec->id;
  1281. $sequence = $rec->sequence;
  1282. }
  1283. if ($newid) {
  1284. //save old and new section id
  1285. backup_putid ($restore->backup_unique_code,"course_sections",$key,$newid);
  1286. } else {
  1287. $status = false;
  1288. }
  1289. //If all is OK, go with associated mods
  1290. if ($status) {
  1291. //If we have mods in the section
  1292. if (!empty($sect->mods)) {
  1293. //For each mod inside section
  1294. foreach ($sect->mods as $keym => $mod) {
  1295. // Yu: This part is called repeatedly for every instance,
  1296. // so it is necessary to set the granular flag and check isset()
  1297. // when the first instance of this type of mod is processed.
  1298. //if (!isset($restore->mods[$mod->type]->granular) && isset($restore->mods[$mod->type]->instances) && is_array($restore->mods[$mod->type]->instances)) {
  1299. if (!isset($restore->mods[$mod->type]->granular)) {
  1300. if (isset($restore->mods[$mod->type]->instances) && is_array($restore->mods[$mod->type]->instances)) {
  1301. // This defines whether we want to restore specific
  1302. // instances of the modules (granular restore), or
  1303. // whether we don't care and just want to restore
  1304. // all module instances (non-granular).
  1305. $restore->mods[$mod->type]->granular = true;
  1306. } else {
  1307. $restore->mods[$mod->type]->granular = false;
  1308. }
  1309. }
  1310. //Check if we've to restore this module (and instance)
  1311. if (!empty($restore->mods[$mod->type]->restore)) {
  1312. if (empty($restore->mods[$mod->type]->granular) // we don't care about per instance
  1313. || (array_key_exists($mod->instance,$restore->mods[$mod->type]->instances)
  1314. && !empty($restore->mods[$mod->type]->instances[$mod->instance]->restore))) {
  1315. //Get the module id from modules
  1316. $module = get_record("modules","name",$mod->type);
  1317. if ($module) {
  1318. $course_module = new object();
  1319. $course_module->course = $restore->course_id;
  1320. $course_module->module = $module->id;
  1321. $course_module->section = $newid;
  1322. $course_module->added = $mod->added;
  1323. $course_module->score = $mod->score;
  1324. $course_module->indent = $mod->indent;
  1325. $course_module->visible = $mod->visible;
  1326. $course_module->groupmode = $mod->groupmode;
  1327. if ($mod->groupingid and $grouping = restore_grouping_getid($restore, $mod->groupingid)) {
  1328. $course_module->groupingid = $grouping->new_id;
  1329. } else {
  1330. $course_module->groupingid = 0;
  1331. }
  1332. $course_module->groupmembersonly = $mod->groupmembersonly;
  1333. $course_module->instance = 0;
  1334. //NOTE: The instance (new) is calculated and updated in db in the
  1335. // final step of the restore. We don't know it yet.
  1336. //print_object($course_module); //Debug
  1337. //Save it to db
  1338. if ($mod->idnumber) {
  1339. if (grade_verify_idnumber($mod->idnumber, $restore->course_id)) {
  1340. $course_module->idnumber = $mod->idnumber;
  1341. }
  1342. }
  1343. $newidmod = insert_record("course_modules", addslashes_recursive($course_module));
  1344. if ($newidmod) {
  1345. //save old and new module id
  1346. //In the info field, we save the original instance of the module
  1347. //to use it later
  1348. backup_putid ($restore->backup_unique_code,"course_modules",
  1349. $keym,$newidmod,$mod->instance);
  1350. $restore->mods[$mod->type]->instances[$mod->instance]->restored_as_course_module = $newidmod;
  1351. } else {
  1352. $status = false;
  1353. }
  1354. //Now, calculate the sequence field
  1355. if ($status) {
  1356. if ($sequence) {
  1357. $sequence .= ",".$newidmod;
  1358. } else {
  1359. $sequence = $newidmod;
  1360. }
  1361. }
  1362. } else {
  1363. $status = false;
  1364. }
  1365. }
  1366. }
  1367. }
  1368. }
  1369. }
  1370. //If all is OK, update sequence field in course_sections
  1371. if ($status) {
  1372. if (isset($sequence)) {
  1373. $update_rec = new object();
  1374. $update_rec->id = $newid;
  1375. $update_rec->sequence = $sequence;
  1376. $status = update_record("course_sections",$update_rec);
  1377. }
  1378. }
  1379. }
  1380. } else {
  1381. $status = false;
  1382. }
  1383. return $status;
  1384. }
  1385. //Called to set up any course-format specific data that may be in the file
  1386. function restore_set_format_data($restore,$xml_file) {
  1387. global $CFG,$db;
  1388. $status = true;
  1389. //Check it exists
  1390. if (!file_exists($xml_file)) {
  1391. return false;
  1392. }
  1393. //Load data from XML to info
  1394. if(!($info = restore_read_xml_formatdata($xml_file))) {
  1395. return false;
  1396. }
  1397. //Process format data if there is any
  1398. if (isset($info->format_data)) {
  1399. if(!$format=get_field('course','format','id',$restore->course_id)) {
  1400. return false;
  1401. }
  1402. // If there was any data then it must have a restore method
  1403. $file=$CFG->dirroot."/course/format/$format/restorelib.php";
  1404. if(!file_exists($file)) {
  1405. return false;
  1406. }
  1407. require_once($file);
  1408. $function=$format.'_restore_format_data';
  1409. if(!function_exists($function)) {
  1410. return false;
  1411. }
  1412. return $function($restore,$info->format_data);
  1413. }
  1414. // If we got here then there's no data, but that's cool
  1415. return true;
  1416. }
  1417. //This function creates all the metacourse data from xml, notifying
  1418. //about each incidence
  1419. function restore_create_metacourse($restore,$xml_file) {
  1420. global $CFG,$db;
  1421. $status = true;
  1422. //Check it exists
  1423. if (!file_exists($xml_file)) {
  1424. $status = false;
  1425. }
  1426. //Get info from xml
  1427. if ($status) {
  1428. //Load data from XML to info
  1429. $info = restore_read_xml_metacourse($xml_file);
  1430. }
  1431. //Process info about metacourse
  1432. if ($status and $info) {
  1433. //Process child records
  1434. if (!empty($info->childs)) {
  1435. foreach ($info->childs as $child) {
  1436. $dbcourse = false;
  1437. $dbmetacourse = false;
  1438. //Check if child course exists in destination server
  1439. //(by id in the same server or by idnumber and shortname in other server)
  1440. if (backup_is_same_site($restore)) {
  1441. //Same server, lets see by id
  1442. $dbcourse = get_record('course','id',$child->id);
  1443. } else {
  1444. //Different server, lets see by idnumber and shortname, and only ONE record
  1445. $dbcount = count_records('course','idnumber',$child->idnumber,'shortname',$child->shortname);
  1446. if ($dbcount == 1) {
  1447. $dbcourse = get_record('course','idnumber',$child->idnumber,'shortname',$child->shortname);
  1448. }
  1449. }
  1450. //If child course has been found, insert data
  1451. if ($dbcourse) {
  1452. $dbmetacourse->child_course = $dbcourse->id;
  1453. $dbmetacourse->parent_course = $restore->course_id;
  1454. $status = insert_record ('course_meta',$dbmetacourse);
  1455. } else {
  1456. //Child course not found, notice!
  1457. if (!defined('RESTORE_SILENTLY')) {
  1458. echo '<ul><li>'.get_string ('childcoursenotfound').' ('.$child->id.'/'.$child->idnumber.'/'.$child->shortname.')</li></ul>';
  1459. }
  1460. }
  1461. }
  1462. //Now, recreate student enrolments...
  1463. sync_metacourse($restore->course_id);
  1464. }
  1465. //Process parent records
  1466. if (!empty($info->parents)) {
  1467. foreach ($info->parents as $parent) {
  1468. $dbcourse = false;
  1469. $dbmetacourse = false;
  1470. //Check if parent course exists in destination server
  1471. //(by id in the same server or by idnumber and shortname in other server)
  1472. if (backup_is_same_site($restore)) {
  1473. //Same server, lets see by id
  1474. $dbcourse = get_record('course','id',$parent->id);
  1475. } else {
  1476. //Different server, lets see by idnumber and shortname, and only ONE record
  1477. $dbcount = count_records('course','idnumber',$parent->idnumber,'shortname',$parent->shortname);
  1478. if ($dbcount == 1) {
  1479. $dbcourse = get_record('course','idnumber',$parent->idnumber,'shortname',$parent->shortname);
  1480. }
  1481. }
  1482. //If parent course has been found, insert data if it is a metacourse
  1483. if ($dbcourse) {
  1484. if ($dbcourse->metacourse) {
  1485. $dbmetacourse->parent_course = $dbcourse->id;
  1486. $dbmetacourse->child_course = $restore->course_id;
  1487. $status = insert_record ('course_meta',$dbmetacourse);
  1488. //Now, recreate student enrolments in parent course
  1489. sync_metacourse($dbcourse->id);
  1490. } else {
  1491. //Parent course isn't metacourse, notice!
  1492. if (!defined('RESTORE_SILENTLY')) {
  1493. echo '<ul><li>'.get_string ('parentcoursenotmetacourse').' ('.$parent->id.'/'.$parent->idnumber.'/'.$parent->shortname.')</li></ul>';
  1494. }
  1495. }
  1496. } else {
  1497. //Parent course not found, notice!
  1498. if (!defined('RESTORE_SILENTLY')) {
  1499. echo '<ul><li>'.get_string ('parentcoursenotfound').' ('.$parent->id.'/'.$parent->idnumber.'/'.$parent->shortname.')</li></ul>';
  1500. }
  1501. }
  1502. }
  1503. }
  1504. }
  1505. return $status;
  1506. }
  1507. /**
  1508. * This function migrades all the pre 1.9 gradebook data from xml
  1509. */
  1510. function restore_migrate_old_gradebook($restore,$xml_file) {
  1511. global $CFG;
  1512. $status = true;
  1513. //Check it exists
  1514. if (!file_exists($xml_file)) {
  1515. return false;
  1516. }
  1517. // Get info from xml
  1518. // info will contain the number of record to process
  1519. $info = restore_read_xml_gradebook($restore, $xml_file);
  1520. // If we have info, then process
  1521. if (empty($info)) {
  1522. return $status;
  1523. }
  1524. // make sure top course category exists
  1525. $course_category = grade_category::fetch_course_category($restore->course_id);
  1526. $course_category->load_grade_item();
  1527. // we need to know if all grade items that were backed up are being restored
  1528. // if that is not the case, we do not restore grade categories nor gradeitems of category type or course type
  1529. // i.e. the aggregated grades of that category
  1530. $restoreall = true; // set to false if any grade_item is not selected/restored
  1531. $importing = !empty($SESSION->restore->importing); // there should not be a way to import old backups, but anyway ;-)
  1532. if ($importing) {
  1533. $restoreall = false;
  1534. } else {
  1535. $prev_grade_items = grade_item::fetch_all(array('courseid'=>$restore->course_id));
  1536. $prev_grade_cats = grade_category::fetch_all(array('courseid'=>$restore->course_id));
  1537. // if any categories already present, skip restore of categories from backup
  1538. if (count($prev_grade_items) > 1 or count($prev_grade_cats) > 1) {
  1539. $restoreall = false;
  1540. }
  1541. unset($prev_grade_items);
  1542. unset($prev_grade_cats);
  1543. }
  1544. // force creation of all grade_items - the course_modules already exist
  1545. grade_force_full_regrading($restore->course_id);
  1546. grade_grab_course_grades($restore->course_id);
  1547. // Start ul
  1548. if (!defined('RESTORE_SILENTLY')) {
  1549. echo '<ul>';
  1550. }
  1551. /// Process letters
  1552. $context = get_context_instance(CONTEXT_COURSE, $restore->course_id);
  1553. // respect current grade letters if defined
  1554. if ($status and $restoreall and !record_exists('grade_letters', 'contextid', $context->id)) {
  1555. if (!defined('RESTORE_SILENTLY')) {
  1556. echo '<li>'.get_string('gradeletters','grades').'</li>';
  1557. }
  1558. // Fetch recordset_size records in each iteration
  1559. $recs = get_records_select("backup_ids","table_name = 'grade_letter' AND backup_code = $restore->backup_unique_code",
  1560. "",
  1561. "old_id");
  1562. if ($recs) {
  1563. foreach ($recs as $rec) {
  1564. // Get the full record from backup_ids
  1565. $data = backup_getid($restore->backup_unique_code,'grade_letter',$rec->old_id);
  1566. if ($data) {
  1567. $info = $data->info;
  1568. $dbrec = new object();
  1569. $dbrec->contextid = $context->id;
  1570. $dbrec->lowerboundary = backup_todb($info['GRADE_LETTER']['#']['GRADE_LOW']['0']['#']);
  1571. $dbrec->letter = backup_todb($info['GRADE_LETTER']['#']['LETTER']['0']['#']);
  1572. insert_record('grade_letters', $dbrec);
  1573. }
  1574. }
  1575. }
  1576. }
  1577. if (!defined('RESTORE_SILENTLY')) {
  1578. echo '<li>'.get_string('categories','grades').'</li>';
  1579. }
  1580. //Fetch recordset_size records in each iteration
  1581. $recs = get_records_select("backup_ids","table_name = 'grade_category' AND backup_code = $restore->backup_unique_code",
  1582. "old_id",
  1583. "old_id");
  1584. $cat_count = count($recs);
  1585. if ($recs) {
  1586. foreach ($recs as $rec) {
  1587. //Get the full record from backup_ids
  1588. $data = backup_getid($restore->backup_unique_code,'grade_category',$rec->old_id);
  1589. if ($data) {
  1590. //Now get completed xmlized object
  1591. $info = $data->info;
  1592. if ($restoreall) {
  1593. if ($cat_count == 1) {
  1594. $course_category->fullname = backup_todb($info['GRADE_CATEGORY']['#']['NAME']['0']['#'], false);
  1595. $course_category->droplow = backup_todb($info['GRADE_CATEGORY']['#']['DROP_X_LOWEST']['0']['#'], false);
  1596. $course_category->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN2;
  1597. $course_category->aggregateonlygraded = 0;
  1598. $course_category->update('restore');
  1599. $grade_category = $course_category;
  1600. } else {
  1601. $grade_category = new grade_category();
  1602. $grade_category->courseid = $restore->course_id;
  1603. $grade_category->fullname = backup_todb($info['GRADE_CATEGORY']['#']['NAME']['0']['#'], false);
  1604. $grade_category->droplow = backup_todb($info['GRADE_CATEGORY']['#']['DROP_X_LOWEST']['0']['#'], false);
  1605. $grade_category->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN2;
  1606. $grade_category->aggregateonlygraded = 0;
  1607. $grade_category->insert('restore');
  1608. $grade_category->load_grade_item(); // force cretion of grade_item
  1609. }
  1610. } else {
  1611. $grade_category = null;
  1612. }
  1613. /// now, restore grade_items
  1614. $items = array();
  1615. if (!empty($info['GRADE_CATEGORY']['#']['GRADE_ITEMS']['0']['#']['GRADE_ITEM'])) {
  1616. //Iterate over items
  1617. foreach ($info['GRADE_CATEGORY']['#']['GRADE_ITEMS']['0']['#']['GRADE_ITEM'] as $ite_info) {
  1618. $modname = backup_todb($ite_info['#']['MODULE_NAME']['0']['#'], false);
  1619. $olditeminstance = backup_todb($ite_info['#']['CMINSTANCE']['0']['#'], false);
  1620. if (!$mod = backup_getid($restore->backup_unique_code,$modname, $olditeminstance)) {
  1621. continue; // not restored
  1622. }
  1623. $iteminstance = $mod->new_id;
  1624. if (!$cm = get_coursemodule_from_instance($modname, $iteminstance, $restore->course_id)) {
  1625. continue; // does not exist
  1626. }
  1627. if (!$grade_item = grade_item::fetch(array('itemtype'=>'mod', 'itemmodule'=>$cm->modname, 'iteminstance'=>$cm->instance, 'courseid'=>$cm->course, 'itemnumber'=>0))) {
  1628. continue; // no item yet??
  1629. }
  1630. if ($grade_category) {
  1631. $grade_item->sortorder = backup_todb($ite_info['#']['SORT_ORDER']['0']['#'], false);
  1632. $grade_item->set_parent($grade_category->id);
  1633. }
  1634. if ($importing
  1635. or ($grade_item->itemtype == 'mod' and !restore_userdata_selected($restore, $grade_item->itemmodule, $olditeminstance))) {
  1636. // module instance not selected when restored using granular
  1637. // skip this item
  1638. continue;
  1639. }
  1640. //Now process grade excludes
  1641. if (empty($ite_info['#']['GRADE_EXCEPTIONS'])) {
  1642. continue;
  1643. }
  1644. foreach($ite_info['#']['GRADE_EXCEPTIONS']['0']['#']['GRADE_EXCEPTION'] as $exc_info) {
  1645. if ($u = backup_getid($restore->backup_unique_code,"user",backup_todb($exc_info['#']['USERID']['0']['#']))) {
  1646. $userid = $u->new_id;
  1647. $grade_grade = new grade_grade(array('itemid'=>$grade_item->id, 'userid'=>$userid));
  1648. $grade_grade->excluded = 1;
  1649. if ($grade_grade->id) {
  1650. $grade_grade->update('restore');
  1651. } else {
  1652. $grade_grade->insert('restore');
  1653. }
  1654. }
  1655. }
  1656. }
  1657. }
  1658. }
  1659. }
  1660. }
  1661. if (!defined('RESTORE_SILENTLY')) {
  1662. //End ul
  1663. echo '</ul>';
  1664. }
  1665. return $status;
  1666. }
  1667. /**
  1668. * This function creates all the gradebook data from xml
  1669. */
  1670. function restore_create_gradebook($restore,$xml_file) {
  1671. global $CFG;
  1672. $status = true;
  1673. //Check it exists
  1674. if (!file_exists($xml_file)) {
  1675. return false;
  1676. }
  1677. // Get info from xml
  1678. // info will contain the number of record to process
  1679. $info = restore_read_xml_gradebook($restore, $xml_file);
  1680. // If we have info, then process
  1681. if (empty($info)) {
  1682. return $status;
  1683. }
  1684. if (empty($CFG->disablegradehistory) and isset($info->gradebook_histories) and $info->gradebook_histories == "true") {
  1685. $restore_histories = true;
  1686. } else {
  1687. $restore_histories = false;
  1688. }
  1689. // make sure top course category exists
  1690. $course_category = grade_category::fetch_course_category($restore->course_id);
  1691. $course_category->load_grade_item();
  1692. // we need to know if all grade items that were backed up are being restored
  1693. // if that is not the case, we do not restore grade categories nor gradeitems of category type or course type
  1694. // i.e. the aggregated grades of that category
  1695. $restoreall = true; // set to false if any grade_item is not selected/restored or already exist
  1696. $importing = !empty($SESSION->restore->importing);
  1697. if ($importing) {
  1698. $restoreall = false;
  1699. } else {
  1700. $prev_grade_items = grade_item::fetch_all(array('courseid'=>$restore->course_id));
  1701. $prev_grade_cats = grade_category::fetch_all(array('courseid'=>$restore->course_id));
  1702. // if any categories already present, skip restore of categories from backup - course item or category already exist
  1703. if (count($prev_grade_items) > 1 or count($prev_grade_cats) > 1) {
  1704. $restoreall = false;
  1705. }
  1706. unset($prev_grade_items);
  1707. unset($prev_grade_cats);
  1708. if ($restoreall) {
  1709. if ($recs = get_records_select("backup_ids","table_name = 'grade_items' AND backup_code = $restore->backup_unique_code", "", "old_id")) {
  1710. foreach ($recs as $rec) {
  1711. if ($data = backup_getid($restore->backup_unique_code,'grade_items',$rec->old_id)) {
  1712. $info = $data->info;
  1713. // do not restore if this grade_item is a mod, and
  1714. $itemtype = backup_todb($info['GRADE_ITEM']['#']['ITEMTYPE']['0']['#']);
  1715. if ($itemtype == 'mod') {
  1716. $olditeminstance = backup_todb($info['GRADE_ITEM']['#']['ITEMINSTANCE']['0']['#']);
  1717. $itemmodule = backup_todb($info['GRADE_ITEM']['#']['ITEMMODULE']['0']['#']);
  1718. if (empty($restore->mods[$itemmodule]->granular)) {
  1719. continue;
  1720. } else if (!empty($restore->mods[$itemmodule]->instances[$olditeminstance]->restore)) {
  1721. continue;
  1722. }
  1723. // at least one activity should not be restored - do not restore categories and manual items at all
  1724. $restoreall = false;
  1725. break;
  1726. }
  1727. }
  1728. }
  1729. }
  1730. }
  1731. }
  1732. // Start ul
  1733. if (!defined('RESTORE_SILENTLY')) {
  1734. echo '<ul>';
  1735. }
  1736. // array of restored categories - speedup ;-)
  1737. $cached_categories = array();
  1738. $outcomes = array();
  1739. /// Process letters
  1740. $context = get_context_instance(CONTEXT_COURSE, $restore->course_id);
  1741. // respect current grade letters if defined
  1742. if ($status and $restoreall and !record_exists('grade_letters', 'contextid', $context->id)) {
  1743. if (!defined('RESTORE_SILENTLY')) {
  1744. echo '<li>'.get_string('gradeletters','grades').'</li>';
  1745. }
  1746. // Fetch recordset_size records in each iteration
  1747. $recs = get_records_select("backup_ids","table_name = 'grade_letters' AND backup_code = $restore->backup_unique_code",
  1748. "",
  1749. "old_id");
  1750. if ($recs) {
  1751. foreach ($recs as $rec) {
  1752. // Get the full record from backup_ids
  1753. $data = backup_getid($restore->backup_unique_code,'grade_letters',$rec->old_id);
  1754. if ($data) {
  1755. $info = $data->info;
  1756. $dbrec = new object();
  1757. $dbrec->contextid = $context->id;
  1758. $dbrec->lowerboundary = backup_todb($info['GRADE_LETTER']['#']['LOWERBOUNDARY']['0']['#']);
  1759. $dbrec->letter = backup_todb($info['GRADE_LETTER']['#']['LETTER']['0']['#']);
  1760. insert_record('grade_letters', $dbrec);
  1761. }
  1762. }
  1763. }
  1764. }
  1765. /// Preprocess outcomes - do not store them yet!
  1766. if ($status and !$importing and $restoreall) {
  1767. if (!defined('RESTORE_SILENTLY')) {
  1768. echo '<li>'.get_string('gradeoutcomes','grades').'</li>';
  1769. }
  1770. $recs = get_records_select("backup_ids","table_name = 'grade_outcomes' AND backup_code = '$restore->backup_unique_code'",
  1771. "",
  1772. "old_id");
  1773. if ($recs) {
  1774. foreach ($recs as $rec) {
  1775. //Get the full record from backup_ids
  1776. $data = backup_getid($restore->backup_unique_code,'grade_outcomes',$rec->old_id);
  1777. if ($data) {
  1778. $info = $data->info;
  1779. //first find out if outcome already exists
  1780. $shortname = backup_todb($info['GRADE_OUTCOME']['#']['SHORTNAME']['0']['#']);
  1781. if ($candidates = get_records_sql("SELECT *
  1782. FROM {$CFG->prefix}grade_outcomes
  1783. WHERE (courseid IS NULL OR courseid = $restore->course_id)
  1784. AND shortname = '$shortname'
  1785. ORDER BY courseid ASC, id ASC")) {
  1786. $grade_outcome = reset($candidates);
  1787. $outcomes[$rec->old_id] = $grade_outcome;
  1788. continue;
  1789. }
  1790. $dbrec = new object();
  1791. if (has_capability('moodle/grade:manageoutcomes', get_context_instance(CONTEXT_SYSTEM))) {
  1792. $oldoutcome = backup_todb($info['GRADE_OUTCOME']['#']['COURSEID']['0']['#']);
  1793. if (empty($oldoutcome)) {
  1794. //site wide
  1795. $dbrec->courseid = null;
  1796. } else {
  1797. //course only
  1798. $dbrec->courseid = $restore->course_id;
  1799. }
  1800. } else {
  1801. // no permission to add site outcomes
  1802. $dbrec->courseid = $restore->course_id;
  1803. }
  1804. //Get the fields
  1805. $dbrec->shortname = backup_todb($info['GRADE_OUTCOME']['#']['SHORTNAME']['0']['#'], false);
  1806. $dbrec->fullname = backup_todb($info['GRADE_OUTCOME']['#']['FULLNAME']['0']['#'], false);
  1807. $dbrec->scaleid = backup_todb($info['GRADE_OUTCOME']['#']['SCALEID']['0']['#'], false);
  1808. $dbrec->description = backup_todb($info['GRADE_OUTCOME']['#']['DESCRIPTION']['0']['#'], false);
  1809. $dbrec->timecreated = backup_todb($info['GRADE_OUTCOME']['#']['TIMECREATED']['0']['#'], false);
  1810. $dbrec->timemodified = backup_todb($info['GRADE_OUTCOME']['#']['TIMEMODIFIED']['0']['#'], false);
  1811. $dbrec->usermodified = backup_todb($info['GRADE_OUTCOME']['#']['USERMODIFIED']['0']['#'], false);
  1812. //Need to recode the scaleid
  1813. if ($scale = backup_getid($restore->backup_unique_code, 'scale', $dbrec->scaleid)) {
  1814. $dbrec->scaleid = $scale->new_id;
  1815. }
  1816. //Need to recode the usermodified
  1817. if ($modifier = backup_getid($restore->backup_unique_code, 'user', $dbrec->usermodified)) {
  1818. $dbrec->usermodified = $modifier->new_id;
  1819. }
  1820. $grade_outcome = new grade_outcome($dbrec, false);
  1821. $outcomes[$rec->old_id] = $grade_outcome;
  1822. }
  1823. }
  1824. }
  1825. }
  1826. /// Process grade items and grades
  1827. if ($status) {
  1828. if (!defined('RESTORE_SILENTLY')) {
  1829. echo '<li>'.get_string('gradeitems','grades').'</li>';
  1830. }
  1831. $counter = 0;
  1832. //Fetch recordset_size records in each iteration
  1833. $recs = get_records_select("backup_ids","table_name = 'grade_items' AND backup_code = '$restore->backup_unique_code'",
  1834. "id", // restore in the backup order
  1835. "old_id");
  1836. if ($recs) {
  1837. foreach ($recs as $rec) {
  1838. //Get the full record from backup_ids
  1839. $data = backup_getid($restore->backup_unique_code,'grade_items',$rec->old_id);
  1840. if ($data) {
  1841. $info = $data->info;
  1842. // first find out if category or normal item
  1843. $itemtype = backup_todb($info['GRADE_ITEM']['#']['ITEMTYPE']['0']['#'], false);
  1844. if ($itemtype == 'course' or $itemtype == 'category') {
  1845. if (!$restoreall or $importing) {
  1846. continue;
  1847. }
  1848. $oldcat = backup_todb($info['GRADE_ITEM']['#']['ITEMINSTANCE']['0']['#'], false);
  1849. if (!$cdata = backup_getid($restore->backup_unique_code,'grade_categories',$oldcat)) {
  1850. continue;
  1851. }
  1852. $cinfo = $cdata->info;
  1853. unset($cdata);
  1854. if ($itemtype == 'course') {
  1855. $course_category->fullname = backup_todb($cinfo['GRADE_CATEGORY']['#']['FULLNAME']['0']['#'], false);
  1856. $course_category->aggregation = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATION']['0']['#'], false);
  1857. $course_category->keephigh = backup_todb($cinfo['GRADE_CATEGORY']['#']['KEEPHIGH']['0']['#'], false);
  1858. $course_category->droplow = backup_todb($cinfo['GRADE_CATEGORY']['#']['DROPLOW']['0']['#'], false);
  1859. $course_category->aggregateonlygraded = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATEONLYGRADED']['0']['#'], false);
  1860. $course_category->aggregateoutcomes = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATEOUTCOMES']['0']['#'], false);
  1861. $course_category->aggregatesubcats = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATESUBCATS']['0']['#'], false);
  1862. $course_category->timecreated = backup_todb($cinfo['GRADE_CATEGORY']['#']['TIMECREATED']['0']['#'], false);
  1863. $course_category->update('restore');
  1864. $status = backup_putid($restore->backup_unique_code,'grade_categories',$oldcat,$course_category->id) && $status;
  1865. $cached_categories[$oldcat] = $course_category;
  1866. $grade_item = $course_category->get_grade_item();
  1867. } else {
  1868. $oldparent = backup_todb($cinfo['GRADE_CATEGORY']['#']['PARENT']['0']['#'], false);
  1869. if (empty($cached_categories[$oldparent])) {
  1870. debugging('parent not found '.$oldparent);
  1871. continue; // parent not found, sorry
  1872. }
  1873. $grade_category = new grade_category();
  1874. $grade_category->courseid = $restore->course_id;
  1875. $grade_category->parent = $cached_categories[$oldparent]->id;
  1876. $grade_category->fullname = backup_todb($cinfo['GRADE_CATEGORY']['#']['FULLNAME']['0']['#'], false);
  1877. $grade_category->aggregation = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATION']['0']['#'], false);
  1878. $grade_category->keephigh = backup_todb($cinfo['GRADE_CATEGORY']['#']['KEEPHIGH']['0']['#'], false);
  1879. $grade_category->droplow = backup_todb($cinfo['GRADE_CATEGORY']['#']['DROPLOW']['0']['#'], false);
  1880. $grade_category->aggregateonlygraded = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATEONLYGRADED']['0']['#'], false);
  1881. $grade_category->aggregateoutcomes = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATEOUTCOMES']['0']['#'], false);
  1882. $grade_category->aggregatesubcats = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATESUBCATS']['0']['#'], false);
  1883. $grade_category->timecreated = backup_todb($cinfo['GRADE_CATEGORY']['#']['TIMECREATED']['0']['#'], false);
  1884. $grade_category->insert('restore');
  1885. $status = backup_putid($restore->backup_unique_code,'grade_categories',$oldcat,$grade_category->id) && $status;
  1886. $cached_categories[$oldcat] = $grade_category;
  1887. $grade_item = $grade_category->get_grade_item(); // creates grade_item too
  1888. }
  1889. unset($cinfo);
  1890. $idnumber = backup_todb($info['GRADE_ITEM']['#']['IDNUMBER']['0']['#'], false);
  1891. if (grade_verify_idnumber($idnumber, $restore->course_id)) {
  1892. $grade_item->idnumber = $idnumber;
  1893. }
  1894. $grade_item->itemname = backup_todb($info['GRADE_ITEM']['#']['ITEMNAME']['0']['#'], false);
  1895. $grade_item->iteminfo = backup_todb($info['GRADE_ITEM']['#']['ITEMINFO']['0']['#'], false);
  1896. $grade_item->gradetype = backup_todb($info['GRADE_ITEM']['#']['GRADETYPE']['0']['#'], false);
  1897. $grade_item->calculation = backup_todb($info['GRADE_ITEM']['#']['CALCULATION']['0']['#'], false);
  1898. $grade_item->grademax = backup_todb($info['GRADE_ITEM']['#']['GRADEMAX']['0']['#'], false);
  1899. $grade_item->grademin = backup_todb($info['GRADE_ITEM']['#']['GRADEMIN']['0']['#'], false);
  1900. $grade_item->gradepass = backup_todb($info['GRADE_ITEM']['#']['GRADEPASS']['0']['#'], false);
  1901. $grade_item->multfactor = backup_todb($info['GRADE_ITEM']['#']['MULTFACTOR']['0']['#'], false);
  1902. $grade_item->plusfactor = backup_todb($info['GRADE_ITEM']['#']['PLUSFACTOR']['0']['#'], false);
  1903. $grade_item->aggregationcoef = backup_todb($info['GRADE_ITEM']['#']['AGGREGATIONCOEF']['0']['#'], false);
  1904. $grade_item->display = backup_todb($info['GRADE_ITEM']['#']['DISPLAY']['0']['#'], false);
  1905. $grade_item->decimals = backup_todb($info['GRADE_ITEM']['#']['DECIMALS']['0']['#'], false);
  1906. $grade_item->hidden = backup_todb($info['GRADE_ITEM']['#']['HIDDEN']['0']['#'], false);
  1907. $grade_item->locked = backup_todb($info['GRADE_ITEM']['#']['LOCKED']['0']['#'], false);
  1908. $grade_item->locktime = backup_todb($info['GRADE_ITEM']['#']['LOCKTIME']['0']['#'], false);
  1909. $grade_item->timecreated = backup_todb($info['GRADE_ITEM']['#']['TIMECREATED']['0']['#'], false);
  1910. if (backup_todb($info['GRADE_ITEM']['#']['SCALEID']['0']['#'], false)) {
  1911. $scale = backup_getid($restore->backup_unique_code,"scale",backup_todb($info['GRADE_ITEM']['#']['SCALEID']['0']['#'], false));
  1912. $grade_item->scaleid = $scale->new_id;
  1913. }
  1914. if (backup_todb($info['GRADE_ITEM']['#']['OUTCOMEID']['0']['#'], false)) {
  1915. $outcome = backup_getid($restore->backup_unique_code,"grade_outcomes",backup_todb($info['GRADE_ITEM']['#']['OUTCOMEID']['0']['#'], false));
  1916. $grade_item->outcomeid = $outcome->new_id;
  1917. }
  1918. $grade_item->update('restore');
  1919. $status = backup_putid($restore->backup_unique_code,"grade_items", $rec->old_id, $grade_item->id) && $status;
  1920. } else {
  1921. if ($itemtype != 'mod' and (!$restoreall or $importing)) {
  1922. // not extra gradebook stuff if restoring individual activities or something already there
  1923. continue;
  1924. }
  1925. $dbrec = new object();
  1926. $dbrec->courseid = $restore->course_id;
  1927. $dbrec->itemtype = backup_todb($info['GRADE_ITEM']['#']['ITEMTYPE']['0']['#'], false);
  1928. $dbrec->itemmodule = backup_todb($info['GRADE_ITEM']['#']['ITEMMODULE']['0']['#'], false);
  1929. if ($itemtype == 'mod') {
  1930. // iteminstance should point to new mod
  1931. $olditeminstance = backup_todb($info['GRADE_ITEM']['#']['ITEMINSTANCE']['0']['#'], false);
  1932. $mod = backup_getid($restore->backup_unique_code,$dbrec->itemmodule, $olditeminstance);
  1933. $dbrec->iteminstance = $mod->new_id;
  1934. if (!$cm = get_coursemodule_from_instance($dbrec->itemmodule, $mod->new_id)) {
  1935. // item not restored - no item
  1936. continue;
  1937. }
  1938. // keep in sync with activity idnumber
  1939. $dbrec->idnumber = $cm->idnumber;
  1940. } else {
  1941. $idnumber = backup_todb($info['GRADE_ITEM']['#']['IDNUMBER']['0']['#'], false);
  1942. if (grade_verify_idnumber($idnumber, $restore->course_id)) {
  1943. //make sure the new idnumber is unique
  1944. $dbrec->idnumber = $idnumber;
  1945. }
  1946. }
  1947. $dbrec->itemname = backup_todb($info['GRADE_ITEM']['#']['ITEMNAME']['0']['#'], false);
  1948. $dbrec->itemtype = backup_todb($info['GRADE_ITEM']['#']['ITEMTYPE']['0']['#'], false);
  1949. $dbrec->itemmodule = backup_todb($info['GRADE_ITEM']['#']['ITEMMODULE']['0']['#'], false);
  1950. $dbrec->itemnumber = backup_todb($info['GRADE_ITEM']['#']['ITEMNUMBER']['0']['#'], false);
  1951. $dbrec->iteminfo = backup_todb($info['GRADE_ITEM']['#']['ITEMINFO']['0']['#'], false);
  1952. $dbrec->gradetype = backup_todb($info['GRADE_ITEM']['#']['GRADETYPE']['0']['#'], false);
  1953. $dbrec->calculation = backup_todb($info['GRADE_ITEM']['#']['CALCULATION']['0']['#'], false);
  1954. $dbrec->grademax = backup_todb($info['GRADE_ITEM']['#']['GRADEMAX']['0']['#'], false);
  1955. $dbrec->grademin = backup_todb($info['GRADE_ITEM']['#']['GRADEMIN']['0']['#'], false);
  1956. $dbrec->gradepass = backup_todb($info['GRADE_ITEM']['#']['GRADEPASS']['0']['#'], false);
  1957. $dbrec->multfactor = backup_todb($info['GRADE_ITEM']['#']['MULTFACTOR']['0']['#'], false);
  1958. $dbrec->plusfactor = backup_todb($info['GRADE_ITEM']['#']['PLUSFACTOR']['0']['#'], false);
  1959. $dbrec->aggregationcoef = backup_todb($info['GRADE_ITEM']['#']['AGGREGATIONCOEF']['0']['#'], false);
  1960. $dbrec->display = backup_todb($info['GRADE_ITEM']['#']['DISPLAY']['0']['#'], false);
  1961. $dbrec->decimals = backup_todb($info['GRADE_ITEM']['#']['DECIMALS']['0']['#'], false);
  1962. $dbrec->hidden = backup_todb($info['GRADE_ITEM']['#']['HIDDEN']['0']['#'], false);
  1963. $dbrec->locked = backup_todb($info['GRADE_ITEM']['#']['LOCKED']['0']['#'], false);
  1964. $dbrec->locktime = backup_todb($info['GRADE_ITEM']['#']['LOCKTIME']['0']['#'], false);
  1965. $dbrec->timecreated = backup_todb($info['GRADE_ITEM']['#']['TIMECREATED']['0']['#'], false);
  1966. if (backup_todb($info['GRADE_ITEM']['#']['SCALEID']['0']['#'], false)) {
  1967. $scale = backup_getid($restore->backup_unique_code,"scale",backup_todb($info['GRADE_ITEM']['#']['SCALEID']['0']['#'], false));
  1968. $dbrec->scaleid = $scale->new_id;
  1969. }
  1970. if (backup_todb($info['GRADE_ITEM']['#']['OUTCOMEID']['0']['#'])) {
  1971. $oldoutcome = backup_todb($info['GRADE_ITEM']['#']['OUTCOMEID']['0']['#']);
  1972. if (empty($outcomes[$oldoutcome])) {
  1973. continue; // error!
  1974. }
  1975. if (empty($outcomes[$oldoutcome]->id)) {
  1976. $outcomes[$oldoutcome]->insert('restore');
  1977. $outcomes[$oldoutcome]->use_in($restore->course_id);
  1978. backup_putid($restore->backup_unique_code, "grade_outcomes", $oldoutcome, $outcomes[$oldoutcome]->id);
  1979. }
  1980. $dbrec->outcomeid = $outcomes[$oldoutcome]->id;
  1981. }
  1982. $grade_item = new grade_item($dbrec, false);
  1983. $grade_item->insert('restore');
  1984. if ($restoreall) {
  1985. // set original parent if restored
  1986. $oldcat = $info['GRADE_ITEM']['#']['CATEGORYID']['0']['#'];
  1987. if (!empty($cached_categories[$oldcat])) {
  1988. $grade_item->set_parent($cached_categories[$oldcat]->id);
  1989. }
  1990. }
  1991. $status = backup_putid($restore->backup_unique_code,"grade_items", $rec->old_id, $grade_item->id) && $status;
  1992. }
  1993. // no need to restore grades if user data is not selected or importing activities
  1994. if ($importing
  1995. or ($grade_item->itemtype == 'mod' and !restore_userdata_selected($restore, $grade_item->itemmodule, $olditeminstance))) {
  1996. // module instance not selected when restored using granular
  1997. // skip this item
  1998. continue;
  1999. }
  2000. /// now, restore grade_grades
  2001. if (!empty($info['GRADE_ITEM']['#']['GRADE_GRADES']['0']['#']['GRADE'])) {
  2002. //Iterate over items
  2003. foreach ($info['GRADE_ITEM']['#']['GRADE_GRADES']['0']['#']['GRADE'] as $g_info) {
  2004. $grade = new grade_grade();
  2005. $grade->itemid = $grade_item->id;
  2006. $olduser = backup_todb($g_info['#']['USERID']['0']['#'], false);
  2007. $user = backup_getid($restore->backup_unique_code,"user",$olduser);
  2008. $grade->userid = $user->new_id;
  2009. $grade->rawgrade = backup_todb($g_info['#']['RAWGRADE']['0']['#'], false);
  2010. $grade->rawgrademax = backup_todb($g_info['#']['RAWGRADEMAX']['0']['#'], false);
  2011. $grade->rawgrademin = backup_todb($g_info['#']['RAWGRADEMIN']['0']['#'], false);
  2012. // need to find scaleid
  2013. if (backup_todb($g_info['#']['RAWSCALEID']['0']['#'])) {
  2014. $scale = backup_getid($restore->backup_unique_code,"scale",backup_todb($g_info['#']['RAWSCALEID']['0']['#'], false));
  2015. $grade->rawscaleid = $scale->new_id;
  2016. }
  2017. if (backup_todb($g_info['#']['USERMODIFIED']['0']['#'])) {
  2018. if ($modifier = backup_getid($restore->backup_unique_code,"user", backup_todb($g_info['#']['USERMODIFIED']['0']['#'], false))) {
  2019. $grade->usermodified = $modifier->new_id;
  2020. }
  2021. }
  2022. $grade->finalgrade = backup_todb($g_info['#']['FINALGRADE']['0']['#'], false);
  2023. $grade->hidden = backup_todb($g_info['#']['HIDDEN']['0']['#'], false);
  2024. $grade->locked = backup_todb($g_info['#']['LOCKED']['0']['#'], false);
  2025. $grade->locktime = backup_todb($g_info['#']['LOCKTIME']['0']['#'], false);
  2026. $grade->exported = backup_todb($g_info['#']['EXPORTED']['0']['#'], false);
  2027. $grade->overridden = backup_todb($g_info['#']['OVERRIDDEN']['0']['#'], false);
  2028. $grade->excluded = backup_todb($g_info['#']['EXCLUDED']['0']['#'], false);
  2029. $grade->feedback = backup_todb($g_info['#']['FEEDBACK']['0']['#'], false);
  2030. $grade->feedbackformat = backup_todb($g_info['#']['FEEDBACKFORMAT']['0']['#'], false);
  2031. $grade->information = backup_todb($g_info['#']['INFORMATION']['0']['#'], false);
  2032. $grade->informationformat = backup_todb($g_info['#']['INFORMATIONFORMAT']['0']['#'], false);
  2033. $grade->timecreated = backup_todb($g_info['#']['TIMECREATED']['0']['#'], false);
  2034. $grade->timemodified = backup_todb($g_info['#']['TIMEMODIFIED']['0']['#'], false);
  2035. $grade->insert('restore');
  2036. backup_putid($restore->backup_unique_code,"grade_grades", backup_todb($g_info['#']['ID']['0']['#']), $grade->id);
  2037. $counter++;
  2038. if ($counter % 20 == 0) {
  2039. if (!defined('RESTORE_SILENTLY')) {
  2040. echo ".";
  2041. if ($counter % 400 == 0) {
  2042. echo "<br />";
  2043. }
  2044. }
  2045. backup_flush(300);
  2046. }
  2047. }
  2048. }
  2049. }
  2050. }
  2051. }
  2052. }
  2053. /// add outcomes that are not used when doing full restore
  2054. if ($status and $restoreall) {
  2055. foreach ($outcomes as $oldoutcome=>$grade_outcome) {
  2056. if (empty($grade_outcome->id)) {
  2057. $grade_outcome->insert('restore');
  2058. $grade_outcome->use_in($restore->course_id);
  2059. backup_putid($restore->backup_unique_code, "grade_outcomes", $oldoutcome, $grade_outcome->id);
  2060. }
  2061. }
  2062. }
  2063. if ($status and !$importing and $restore_histories) {
  2064. /// following code is very inefficient
  2065. $gchcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'grade_categories_history');
  2066. $gghcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'grade_grades_history');
  2067. $gihcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'grade_items_history');
  2068. $gohcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'grade_outcomes_history');
  2069. // Number of records to get in every chunk
  2070. $recordset_size = 2;
  2071. // process histories
  2072. if ($gchcount && $status) {
  2073. if (!defined('RESTORE_SILENTLY')) {
  2074. echo '<li>'.get_string('gradecategoryhistory','grades').'</li>';
  2075. }
  2076. $counter = 0;
  2077. while ($counter < $gchcount) {
  2078. //Fetch recordset_size records in each iteration
  2079. $recs = get_records_select("backup_ids","table_name = 'grade_categories_history' AND backup_code = '$restore->backup_unique_code'",
  2080. "old_id",
  2081. "old_id",
  2082. $counter,
  2083. $recordset_size);
  2084. if ($recs) {
  2085. foreach ($recs as $rec) {
  2086. //Get the full record from backup_ids
  2087. $data = backup_getid($restore->backup_unique_code,'grade_categories_history',$rec->old_id);
  2088. if ($data) {
  2089. //Now get completed xmlized object
  2090. $info = $data->info;
  2091. //traverse_xmlize($info); //Debug
  2092. //print_object ($GLOBALS['traverse_array']); //Debug
  2093. //$GLOBALS['traverse_array']=""; //Debug
  2094. $oldobj = backup_getid($restore->backup_unique_code,"grade_categories", backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['OLDID']['0']['#']));
  2095. if (empty($oldobj->new_id)) {
  2096. // if the old object is not being restored, can't restoring its history
  2097. $counter++;
  2098. continue;
  2099. }
  2100. $dbrec->oldid = $oldobj->new_id;
  2101. $dbrec->action = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['ACTION']['0']['#']);
  2102. $dbrec->source = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['SOURCE']['0']['#']);
  2103. $dbrec->timemodified = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['TIMEMODIFIED']['0']['#']);
  2104. // loggeduser might not be restored, e.g. admin
  2105. if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['LOGGEDUSER']['0']['#']))) {
  2106. $dbrec->loggeduser = $oldobj->new_id;
  2107. }
  2108. // this item might not have a parent at all, do not skip it if no parent is specified
  2109. if (backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['PARENT']['0']['#'])) {
  2110. $oldobj = backup_getid($restore->backup_unique_code,"grade_categories", backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['PARENT']['0']['#']));
  2111. if (empty($oldobj->new_id)) {
  2112. // if the parent category not restored
  2113. $counter++;
  2114. continue;
  2115. }
  2116. }
  2117. $dbrec->parent = $oldobj->new_id;
  2118. $dbrec->depth = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['DEPTH']['0']['#']);
  2119. // path needs to be rebuilt
  2120. if ($path = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['PATH']['0']['#'])) {
  2121. // to preserve the path and make it work, we need to replace the categories one by one
  2122. // we first get the list of categories in current path
  2123. if ($paths = explode("/", $path)) {
  2124. $newpath = '';
  2125. foreach ($paths as $catid) {
  2126. if ($catid) {
  2127. // find the new corresponding path
  2128. $oldpath = backup_getid($restore->backup_unique_code,"grade_categories", $catid);
  2129. $newpath .= "/$oldpath->new_id";
  2130. }
  2131. }
  2132. $dbrec->path = $newpath;
  2133. }
  2134. }
  2135. $dbrec->fullname = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['FULLNAME']['0']['#']);
  2136. $dbrec->aggregation = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['AGGRETGATION']['0']['#']);
  2137. $dbrec->keephigh = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['KEEPHIGH']['0']['#']);
  2138. $dbrec->droplow = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['DROPLOW']['0']['#']);
  2139. $dbrec->aggregateonlygraded = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['AGGREGATEONLYGRADED']['0']['#']);
  2140. $dbrec->aggregateoutcomes = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['AGGREGATEOUTCOMES']['0']['#']);
  2141. $dbrec->aggregatesubcats = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['AGGREGATESUBCATS']['0']['#']);
  2142. $dbrec->courseid = $restore->course_id;
  2143. insert_record('grade_categories_history', $dbrec);
  2144. unset($dbrec);
  2145. }
  2146. //Increment counters
  2147. $counter++;
  2148. //Do some output
  2149. if ($counter % 1 == 0) {
  2150. if (!defined('RESTORE_SILENTLY')) {
  2151. echo ".";
  2152. if ($counter % 20 == 0) {
  2153. echo "<br />";
  2154. }
  2155. }
  2156. backup_flush(300);
  2157. }
  2158. }
  2159. }
  2160. }
  2161. }
  2162. // process histories
  2163. if ($gghcount && $status) {
  2164. if (!defined('RESTORE_SILENTLY')) {
  2165. echo '<li>'.get_string('gradegradeshistory','grades').'</li>';
  2166. }
  2167. $counter = 0;
  2168. while ($counter < $gghcount) {
  2169. //Fetch recordset_size records in each iteration
  2170. $recs = get_records_select("backup_ids","table_name = 'grade_grades_history' AND backup_code = '$restore->backup_unique_code'",
  2171. "old_id",
  2172. "old_id",
  2173. $counter,
  2174. $recordset_size);
  2175. if ($recs) {
  2176. foreach ($recs as $rec) {
  2177. //Get the full record from backup_ids
  2178. $data = backup_getid($restore->backup_unique_code,'grade_grades_history',$rec->old_id);
  2179. if ($data) {
  2180. //Now get completed xmlized object
  2181. $info = $data->info;
  2182. //traverse_xmlize($info); //Debug
  2183. //print_object ($GLOBALS['traverse_array']); //Debug
  2184. //$GLOBALS['traverse_array']=""; //Debug
  2185. $oldobj = backup_getid($restore->backup_unique_code,"grade_grades", backup_todb($info['GRADE_GRADES_HISTORY']['#']['OLDID']['0']['#']));
  2186. if (empty($oldobj->new_id)) {
  2187. // if the old object is not being restored, can't restoring its history
  2188. $counter++;
  2189. continue;
  2190. }
  2191. $dbrec->oldid = $oldobj->new_id;
  2192. $dbrec->action = backup_todb($info['GRADE_GRADES_HISTORY']['#']['ACTION']['0']['#']);
  2193. $dbrec->source = backup_todb($info['GRADE_GRADES_HISTORY']['#']['SOURCE']['0']['#']);
  2194. $dbrec->timemodified = backup_todb($info['GRADE_GRADES_HISTORY']['#']['TIMEMODIFIED']['0']['#']);
  2195. if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_GRADES_HISTORY']['#']['LOGGEDUSER']['0']['#']))) {
  2196. $dbrec->loggeduser = $oldobj->new_id;
  2197. }
  2198. $oldobj = backup_getid($restore->backup_unique_code,"grade_items", backup_todb($info['GRADE_GRADES_HISTORY']['#']['ITEMID']['0']['#']));
  2199. $dbrec->itemid = $oldobj->new_id;
  2200. if (empty($dbrec->itemid)) {
  2201. $counter++;
  2202. continue; // grade item not being restored
  2203. }
  2204. $oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_GRADES_HISTORY']['#']['USERID']['0']['#']));
  2205. $dbrec->userid = $oldobj->new_id;
  2206. $dbrec->rawgrade = backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWGRADE']['0']['#']);
  2207. $dbrec->rawgrademax = backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWGRADEMAX']['0']['#']);
  2208. $dbrec->rawgrademin = backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWGRADEMIN']['0']['#']);
  2209. if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_GRADES_HISTORY']['#']['USERMODIFIED']['0']['#']))) {
  2210. $dbrec->usermodified = $oldobj->new_id;
  2211. }
  2212. if (backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWSCALEID']['0']['#'])) {
  2213. $scale = backup_getid($restore->backup_unique_code,"scale",backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWSCALEID']['0']['#']));
  2214. $dbrec->rawscaleid = $scale->new_id;
  2215. }
  2216. $dbrec->finalgrade = backup_todb($info['GRADE_GRADES_HISTORY']['#']['FINALGRADE']['0']['#']);
  2217. $dbrec->hidden = backup_todb($info['GRADE_GRADES_HISTORY']['#']['HIDDEN']['0']['#']);
  2218. $dbrec->locked = backup_todb($info['GRADE_GRADES_HISTORY']['#']['LOCKED']['0']['#']);
  2219. $dbrec->locktime = backup_todb($info['GRADE_GRADES_HISTORY']['#']['LOCKTIME']['0']['#']);
  2220. $dbrec->exported = backup_todb($info['GRADE_GRADES_HISTORY']['#']['EXPORTED']['0']['#']);
  2221. $dbrec->overridden = backup_todb($info['GRADE_GRADES_HISTORY']['#']['OVERRIDDEN']['0']['#']);
  2222. $dbrec->excluded = backup_todb($info['GRADE_GRADES_HISTORY']['#']['EXCLUDED']['0']['#']);
  2223. $dbrec->feedback = backup_todb($info['GRADE_TEXT_HISTORY']['#']['FEEDBACK']['0']['#']);
  2224. $dbrec->feedbackformat = backup_todb($info['GRADE_TEXT_HISTORY']['#']['FEEDBACKFORMAT']['0']['#']);
  2225. $dbrec->information = backup_todb($info['GRADE_TEXT_HISTORY']['#']['INFORMATION']['0']['#']);
  2226. $dbrec->informationformat = backup_todb($info['GRADE_TEXT_HISTORY']['#']['INFORMATIONFORMAT']['0']['#']);
  2227. insert_record('grade_grades_history', $dbrec);
  2228. unset($dbrec);
  2229. }
  2230. //Increment counters
  2231. $counter++;
  2232. //Do some output
  2233. if ($counter % 1 == 0) {
  2234. if (!defined('RESTORE_SILENTLY')) {
  2235. echo ".";
  2236. if ($counter % 20 == 0) {
  2237. echo "<br />";
  2238. }
  2239. }
  2240. backup_flush(300);
  2241. }
  2242. }
  2243. }
  2244. }
  2245. }
  2246. // process histories
  2247. if ($gihcount && $status) {
  2248. if (!defined('RESTORE_SILENTLY')) {
  2249. echo '<li>'.get_string('gradeitemshistory','grades').'</li>';
  2250. }
  2251. $counter = 0;
  2252. while ($counter < $gihcount) {
  2253. //Fetch recordset_size records in each iteration
  2254. $recs = get_records_select("backup_ids","table_name = 'grade_items_history' AND backup_code = '$restore->backup_unique_code'",
  2255. "old_id",
  2256. "old_id",
  2257. $counter,
  2258. $recordset_size);
  2259. if ($recs) {
  2260. foreach ($recs as $rec) {
  2261. //Get the full record from backup_ids
  2262. $data = backup_getid($restore->backup_unique_code,'grade_items_history',$rec->old_id);
  2263. if ($data) {
  2264. //Now get completed xmlized object
  2265. $info = $data->info;
  2266. //traverse_xmlize($info); //Debug
  2267. //print_object ($GLOBALS['traverse_array']); //Debug
  2268. //$GLOBALS['traverse_array']=""; //Debug
  2269. $oldobj = backup_getid($restore->backup_unique_code,"grade_items", backup_todb($info['GRADE_ITEM_HISTORY']['#']['OLDID']['0']['#']));
  2270. if (empty($oldobj->new_id)) {
  2271. // if the old object is not being restored, can't restoring its history
  2272. $counter++;
  2273. continue;
  2274. }
  2275. $dbrec->oldid = $oldobj->new_id;
  2276. $dbrec->action = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ACTION']['0']['#']);
  2277. $dbrec->source = backup_todb($info['GRADE_ITEM_HISTORY']['#']['SOURCE']['0']['#']);
  2278. $dbrec->timemodified = backup_todb($info['GRADE_ITEM_HISTORY']['#']['TIMEMODIFIED']['0']['#']);
  2279. if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_ITEM_HISTORY']['#']['LOGGEDUSER']['0']['#']))) {
  2280. $dbrec->loggeduser = $oldobj->new_id;
  2281. }
  2282. $dbrec->courseid = $restore->course_id;
  2283. $oldobj = backup_getid($restore->backup_unique_code,'grade_categories',backup_todb($info['GRADE_ITEM_HISTORY']['#']['CATEGORYID']['0']['#']));
  2284. $oldobj->categoryid = $category->new_id;
  2285. if (empty($oldobj->categoryid)) {
  2286. $counter++;
  2287. continue; // category not restored
  2288. }
  2289. $dbrec->itemname= backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMNAME']['0']['#']);
  2290. $dbrec->itemtype = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMTYPE']['0']['#']);
  2291. $dbrec->itemmodule = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMMODULE']['0']['#']);
  2292. // code from grade_items restore
  2293. $iteminstance = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMINSTANCE']['0']['#']);
  2294. // do not restore if this grade_item is a mod, and
  2295. if ($dbrec->itemtype == 'mod') {
  2296. if (!restore_userdata_selected($restore, $dbrec->itemmodule, $iteminstance)) {
  2297. // module instance not selected when restored using granular
  2298. // skip this item
  2299. $counter++;
  2300. continue;
  2301. }
  2302. // iteminstance should point to new mod
  2303. $mod = backup_getid($restore->backup_unique_code,$dbrec->itemmodule, $iteminstance);
  2304. $dbrec->iteminstance = $mod->new_id;
  2305. } else if ($dbrec->itemtype == 'category') {
  2306. // the item instance should point to the new grade category
  2307. // only proceed if we are restoring all grade items
  2308. if ($restoreall) {
  2309. $category = backup_getid($restore->backup_unique_code,'grade_categories', $iteminstance);
  2310. $dbrec->iteminstance = $category->new_id;
  2311. } else {
  2312. // otherwise we can safely ignore this grade item and subsequent
  2313. // grade_raws, grade_finals etc
  2314. continue;
  2315. }
  2316. } elseif ($dbrec->itemtype == 'course') { // We don't restore course type to avoid duplicate course items
  2317. if ($restoreall) {
  2318. // TODO any special code needed here to restore course item without duplicating it?
  2319. // find the course category with depth 1, and course id = current course id
  2320. // this would have been already restored
  2321. $cat = get_record('grade_categories', 'depth', 1, 'courseid', $restore->course_id);
  2322. $dbrec->iteminstance = $cat->id;
  2323. } else {
  2324. $counter++;
  2325. continue;
  2326. }
  2327. }
  2328. $dbrec->itemnumber = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMNUMBER']['0']['#']);
  2329. $dbrec->iteminfo = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMINFO']['0']['#']);
  2330. $dbrec->idnumber = backup_todb($info['GRADE_ITEM_HISTORY']['#']['IDNUMBER']['0']['#']);
  2331. $dbrec->calculation = backup_todb($info['GRADE_ITEM_HISTORY']['#']['CALCULATION']['0']['#']);
  2332. $dbrec->gradetype = backup_todb($info['GRADE_ITEM_HISTORY']['#']['GRADETYPE']['0']['#']);
  2333. $dbrec->grademax = backup_todb($info['GRADE_ITEM_HISTORY']['#']['GRADEMAX']['0']['#']);
  2334. $dbrec->grademin = backup_todb($info['GRADE_ITEM_HISTORY']['#']['GRADEMIN']['0']['#']);
  2335. if ($oldobj = backup_getid($restore->backup_unique_code,"scale", backup_todb($info['GRADE_ITEM_HISTORY']['#']['SCALEID']['0']['#']))) {
  2336. // scaleid is optional
  2337. $dbrec->scaleid = $oldobj->new_id;
  2338. }
  2339. if ($oldobj = backup_getid($restore->backup_unique_code,"grade_outcomes", backup_todb($info['GRADE_ITEM_HISTORY']['#']['OUTCOMEID']['0']['#']))) {
  2340. // outcome is optional
  2341. $dbrec->outcomeid = $oldobj->new_id;
  2342. }
  2343. $dbrec->gradepass = backup_todb($info['GRADE_ITEM_HISTORY']['#']['GRADEPASS']['0']['#']);
  2344. $dbrec->multfactor = backup_todb($info['GRADE_ITEM_HISTORY']['#']['MULTFACTOR']['0']['#']);
  2345. $dbrec->plusfactor = backup_todb($info['GRADE_ITEM_HISTORY']['#']['PLUSFACTOR']['0']['#']);
  2346. $dbrec->aggregationcoef = backup_todb($info['GRADE_ITEM_HISTORY']['#']['AGGREGATIONCOEF']['0']['#']);
  2347. $dbrec->sortorder = backup_todb($info['GRADE_ITEM_HISTORY']['#']['SORTORDER']['0']['#']);
  2348. $dbrec->display = backup_todb($info['GRADE_ITEM_HISTORY']['#']['DISPLAY']['0']['#']);
  2349. $dbrec->decimals = backup_todb($info['GRADE_ITEM_HISTORY']['#']['DECIMALS']['0']['#']);
  2350. $dbrec->hidden = backup_todb($info['GRADE_ITEM_HISTORY']['#']['HIDDEN']['0']['#']);
  2351. $dbrec->locked = backup_todb($info['GRADE_ITEM_HISTORY']['#']['LOCKED']['0']['#']);
  2352. $dbrec->locktime = backup_todb($info['GRADE_ITEM_HISTORY']['#']['LOCKTIME']['0']['#']);
  2353. $dbrec->needsupdate = backup_todb($info['GRADE_ITEM_HISTORY']['#']['NEEDSUPDATE']['0']['#']);
  2354. insert_record('grade_items_history', $dbrec);
  2355. unset($dbrec);
  2356. }
  2357. //Increment counters
  2358. $counter++;
  2359. //Do some output
  2360. if ($counter % 1 == 0) {
  2361. if (!defined('RESTORE_SILENTLY')) {
  2362. echo ".";
  2363. if ($counter % 20 == 0) {
  2364. echo "<br />";
  2365. }
  2366. }
  2367. backup_flush(300);
  2368. }
  2369. }
  2370. }
  2371. }
  2372. }
  2373. // process histories
  2374. if ($gohcount && $status) {
  2375. if (!defined('RESTORE_SILENTLY')) {
  2376. echo '<li>'.get_string('gradeoutcomeshistory','grades').'</li>';
  2377. }
  2378. $counter = 0;
  2379. while ($counter < $gohcount) {
  2380. //Fetch recordset_size records in each iteration
  2381. $recs = get_records_select("backup_ids","table_name = 'grade_outcomes_history' AND backup_code = '$restore->backup_unique_code'",
  2382. "old_id",
  2383. "old_id",
  2384. $counter,
  2385. $recordset_size);
  2386. if ($recs) {
  2387. foreach ($recs as $rec) {
  2388. //Get the full record from backup_ids
  2389. $data = backup_getid($restore->backup_unique_code,'grade_outcomes_history',$rec->old_id);
  2390. if ($data) {
  2391. //Now get completed xmlized object
  2392. $info = $data->info;
  2393. //traverse_xmlize($info); //Debug
  2394. //print_object ($GLOBALS['traverse_array']); //Debug
  2395. //$GLOBALS['traverse_array']=""; //Debug
  2396. $oldobj = backup_getid($restore->backup_unique_code,"grade_outcomes", backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['OLDID']['0']['#']));
  2397. if (empty($oldobj->new_id)) {
  2398. // if the old object is not being restored, can't restoring its history
  2399. $counter++;
  2400. continue;
  2401. }
  2402. $dbrec->oldid = $oldobj->new_id;
  2403. $dbrec->action = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['ACTION']['0']['#']);
  2404. $dbrec->source = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['SOURCE']['0']['#']);
  2405. $dbrec->timemodified = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['TIMEMODIFIED']['0']['#']);
  2406. if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['LOGGEDUSER']['0']['#']))) {
  2407. $dbrec->loggeduser = $oldobj->new_id;
  2408. }
  2409. $dbrec->courseid = $restore->course_id;
  2410. $dbrec->shortname = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['SHORTNAME']['0']['#']);
  2411. $dbrec->fullname= backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['FULLNAME']['0']['#']);
  2412. $oldobj = backup_getid($restore->backup_unique_code,"scale", backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['SCALEID']['0']['#']));
  2413. $dbrec->scaleid = $oldobj->new_id;
  2414. $dbrec->description = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['DESCRIPTION']['0']['#']);
  2415. insert_record('grade_outcomes_history', $dbrec);
  2416. unset($dbrec);
  2417. }
  2418. //Increment counters
  2419. $counter++;
  2420. //Do some output
  2421. if ($counter % 1 == 0) {
  2422. if (!defined('RESTORE_SILENTLY')) {
  2423. echo ".";
  2424. if ($counter % 20 == 0) {
  2425. echo "<br />";
  2426. }
  2427. }
  2428. backup_flush(300);
  2429. }
  2430. }
  2431. }
  2432. }
  2433. }
  2434. }
  2435. if (!defined('RESTORE_SILENTLY')) {
  2436. //End ul
  2437. echo '</ul>';
  2438. }
  2439. return $status;
  2440. }
  2441. //This function creates all the user, user_students, user_teachers
  2442. //user_course_creators and user_admins from xml
  2443. function restore_create_users($restore,$xml_file) {
  2444. global $CFG, $db;
  2445. require_once ($CFG->dirroot.'/tag/lib.php');
  2446. $authcache = array(); // Cache to get some bits from authentication plugins
  2447. $status = true;
  2448. // Users have already been checked by restore_precheck_users() so they are loaded
  2449. // in backup_ids table. They don't need to be loaded (parsed) from XML again. Also, note
  2450. // the same function has performed the needed modifications in the $user->mnethostid field
  2451. // so we don't need to do it again here at all. Just some checks.
  2452. // Get users ids from backup_ids table
  2453. $userids = get_fieldset_select('backup_ids', 'old_id', "backup_code = $restore->backup_unique_code AND table_name = 'user'");
  2454. // Have users to process, proceed with them
  2455. if (!empty($userids)) {
  2456. /// Get languages for quick search later
  2457. $languages = get_list_of_languages();
  2458. /// Iterate over all users loaded from xml
  2459. $counter = 0;
  2460. /// Init trailing messages
  2461. $messages = array();
  2462. foreach ($userids as $userid) {
  2463. // Defaults
  2464. $user_exists = false; // By default user does not exist
  2465. $newid = null; // By default, there is not newid
  2466. // Get record from backup_ids
  2467. $useridsdbrec = backup_getid($restore->backup_unique_code, 'user', $userid);
  2468. // Based in restore_precheck_users() calculations, if the user exists
  2469. // new_id must contain the id of the matching user
  2470. if (!empty($useridsdbrec->new_id)) {
  2471. $user_exists = true;
  2472. $newid = $useridsdbrec->new_id;
  2473. }
  2474. $user = $useridsdbrec->info;
  2475. foreach (array_keys(get_object_vars($user)) as $field) {
  2476. if (!is_array($user->$field)) {
  2477. $user->$field = backup_todb($user->$field, false);
  2478. if (is_null($user->$field)) {
  2479. $user->$field = '';
  2480. }
  2481. }
  2482. }
  2483. //Now, recode some languages (Moodle 1.5)
  2484. if ($user->lang == 'ma_nt') {
  2485. $user->lang = 'mi_nt';
  2486. }
  2487. //Country list updates - MDL-13060
  2488. //Any user whose country code has been deleted or modified needs to be assigned a valid one.
  2489. $country_update_map = array(
  2490. 'ZR' => 'CD',
  2491. 'TP' => 'TL',
  2492. 'FX' => 'FR',
  2493. 'KO' => 'RS',
  2494. 'CS' => 'RS',
  2495. 'WA' => 'GB');
  2496. if (array_key_exists($user->country, $country_update_map)) {
  2497. $user->country = $country_update_map[$user->country];
  2498. }
  2499. //If language does not exist here - use site default
  2500. if (!array_key_exists($user->lang, $languages)) {
  2501. $user->lang = $CFG->lang;
  2502. }
  2503. //Check if it's admin and coursecreator
  2504. $is_admin = !empty($user->roles['admin']);
  2505. $is_coursecreator = !empty($user->roles['coursecreator']);
  2506. //Check if it's teacher and student
  2507. $is_teacher = !empty($user->roles['teacher']);
  2508. $is_student = !empty($user->roles['student']);
  2509. //Check if it's needed
  2510. $is_needed = !empty($user->roles['needed']);
  2511. //Calculate if it is a course user
  2512. //Has role teacher or student or needed
  2513. $is_course_user = ($is_teacher or $is_student or $is_needed);
  2514. // Only try to perform mnethost/auth modifications if restoring to another server
  2515. // or if, while restoring to same server, the user doesn't exists yet (rebuilt site)
  2516. //
  2517. // So existing user data in same server *won't be modified by restore anymore*,
  2518. // under any circumpstance. If somehting is wrong with existing data, it's server fault.
  2519. if (!backup_is_same_site($restore) || (backup_is_same_site($restore) && !$user_exists)) {
  2520. //Arriving here, any user with mnet auth and using $CFG->mnet_localhost_id is wrong
  2521. //as own server cannot be accesed over mnet. Change auth to manual and inform about the switch
  2522. if ($user->auth == 'mnet' && $user->mnethostid == $CFG->mnet_localhost_id) {
  2523. // Respect registerauth
  2524. if ($CFG->registerauth == 'email') {
  2525. $user->auth = 'email';
  2526. } else {
  2527. $user->auth = 'manual';
  2528. }
  2529. // inform about the automatic switch of authentication/host
  2530. if(empty($user->mnethosturl)) {
  2531. $user->mnethosturl = '----';
  2532. }
  2533. $messages[] = get_string('mnetrestore_extusers_switchuserauth', 'admin', $user);
  2534. }
  2535. }
  2536. unset($user->mnethosturl);
  2537. //Flags to see what parts are we going to restore
  2538. $create_user = true;
  2539. $create_roles = true;
  2540. $create_custom_profile_fields = true;
  2541. $create_tags = true;
  2542. $create_preferences = true;
  2543. //If we are restoring course users and it isn't a course user
  2544. if ($restore->users == 1 and !$is_course_user) {
  2545. //If only restoring course_users and user isn't a course_user, inform to $backup_ids
  2546. $status = backup_putid($restore->backup_unique_code,"user",$userid,null,'notincourse');
  2547. $create_user = false;
  2548. $create_roles = false;
  2549. $create_custom_profile_fields = false;
  2550. $create_tags = false;
  2551. $create_preferences = false;
  2552. }
  2553. if ($user_exists and $create_user) {
  2554. //If user exists mark its newid in backup_ids (the same than old)
  2555. $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,'exists');
  2556. $create_user = false;
  2557. $create_custom_profile_fields = false;
  2558. $create_tags = false;
  2559. $create_preferences = false;
  2560. }
  2561. //Here, if create_user, do it
  2562. if ($create_user) {
  2563. //Unset the id because it's going to be inserted with a new one
  2564. unset ($user->id);
  2565. /// Disable pictures based on global setting or existing empty value (old backups can contain wrong empties)
  2566. if (!empty($CFG->disableuserimages) || empty($user->picture)) {
  2567. $user->picture = 0;
  2568. }
  2569. //We need to analyse the AUTH field to recode it:
  2570. // - if the field isn't set, we are in a pre 1.4 backup and $CFG->registerauth will decide
  2571. // - if the auth isn't enabled in target site, $CFG->registerauth will decide
  2572. // - finally, if the auth resulting isn't enabled, default to 'manual'
  2573. if (empty($user->auth) || !is_enabled_auth($user->auth)) {
  2574. if ($CFG->registerauth == 'email') {
  2575. $user->auth = 'email';
  2576. } else {
  2577. $user->auth = 'manual';
  2578. }
  2579. }
  2580. if (!is_enabled_auth($user->auth)) { // Final auth check verify, default to manual if not enabled
  2581. $user->auth = 'manual';
  2582. }
  2583. // Now that we know the auth method, for users to be created without pass
  2584. // if password handling is internal and reset password is available
  2585. // we set the password to "restored" (plain text), so the login process
  2586. // will know how to handle that situation in order to allow the user to
  2587. // recover the password. MDL-20846
  2588. if (empty($user->password)) { // Only if restore comes without password
  2589. if (!array_key_exists($user->auth, $authcache)) { // Not in cache
  2590. $userauth = new stdClass();
  2591. $authplugin = get_auth_plugin($user->auth);
  2592. $userauth->preventpassindb = $authplugin->prevent_local_passwords();
  2593. $userauth->isinternal = $authplugin->is_internal();
  2594. $userauth->canresetpwd = $authplugin->can_reset_password();
  2595. $authcache[$user->auth] = $userauth;
  2596. } else {
  2597. $userauth = $authcache[$user->auth]; // Get from cache
  2598. }
  2599. // Most external plugins do not store passwords locally
  2600. if (!empty($userauth->preventpassindb)) {
  2601. $user->password = 'not cached';
  2602. // If Moodle is responsible for storing/validating pwd and reset functionality is available, mark
  2603. } else if ($userauth->isinternal and $userauth->canresetpwd) {
  2604. $user->password = 'restored';
  2605. }
  2606. }
  2607. //We need to process the POLICYAGREED field to recalculate it:
  2608. // - if the destination site is different (by wwwroot) reset it.
  2609. // - if the destination site is the same (by wwwroot), leave it unmodified
  2610. if (!backup_is_same_site($restore)) {
  2611. $user->policyagreed = 0;
  2612. } else {
  2613. //Nothing to do, we are in the same server
  2614. }
  2615. //Check if the theme exists in destination server
  2616. $themes = get_list_of_themes();
  2617. if (!in_array($user->theme, $themes)) {
  2618. $user->theme = '';
  2619. }
  2620. //We are going to create the user
  2621. //The structure is exactly as we need
  2622. $newid = insert_record ("user", addslashes_recursive($user));
  2623. //Put the new id
  2624. $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,"new");
  2625. }
  2626. ///TODO: This seccion is to support pre 1.7 course backups, using old roles
  2627. /// teacher, coursecreator, student.... providing a basic mapping to new ones.
  2628. /// Someday we'll drop support for them and this section will be safely deleted (2.0?)
  2629. //Here, if create_roles, do it as necessary
  2630. if ($create_roles) {
  2631. //Get the newid and current info from backup_ids
  2632. $data = backup_getid($restore->backup_unique_code,"user",$userid);
  2633. $newid = $data->new_id;
  2634. $currinfo = $data->info.",";
  2635. //Now, depending of the role, create records in user_studentes and user_teacher
  2636. //and/or mark it in backup_ids
  2637. if ($is_admin) {
  2638. //If the record (user_admins) doesn't exists
  2639. //Only put status in backup_ids
  2640. $currinfo = $currinfo."admin,";
  2641. $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
  2642. }
  2643. if ($is_coursecreator) {
  2644. //If the record (user_coursecreators) doesn't exists
  2645. //Only put status in backup_ids
  2646. $currinfo = $currinfo."coursecreator,";
  2647. $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
  2648. }
  2649. if ($is_needed) {
  2650. //Only put status in backup_ids
  2651. $currinfo = $currinfo."needed,";
  2652. $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
  2653. }
  2654. if ($is_teacher) {
  2655. //If the record (teacher) doesn't exists
  2656. //Put status in backup_ids
  2657. $currinfo = $currinfo."teacher,";
  2658. $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
  2659. //Set course and user
  2660. $user->roles['teacher']->course = $restore->course_id;
  2661. $user->roles['teacher']->userid = $newid;
  2662. //Need to analyse the enrol field
  2663. // - if it isn't set, set it to $CFG->enrol
  2664. // - if we are in a different server (by wwwroot), set it to $CFG->enrol
  2665. // - if we are in the same server (by wwwroot), maintain it unmodified.
  2666. if (empty($user->roles['teacher']->enrol)) {
  2667. $user->roles['teacher']->enrol = $CFG->enrol;
  2668. } else if (!backup_is_same_site($restore)) {
  2669. $user->roles['teacher']->enrol = $CFG->enrol;
  2670. } else {
  2671. //Nothing to do. Leave it unmodified
  2672. }
  2673. $rolesmapping = $restore->rolesmapping;
  2674. $context = get_context_instance(CONTEXT_COURSE, $restore->course_id);
  2675. if ($user->roles['teacher']->editall) {
  2676. role_assign($rolesmapping['defaultteacheredit'],
  2677. $newid,
  2678. 0,
  2679. $context->id,
  2680. $user->roles['teacher']->timestart,
  2681. $user->roles['teacher']->timeend,
  2682. 0,
  2683. $user->roles['teacher']->enrol);
  2684. // editting teacher
  2685. } else {
  2686. // non editting teacher
  2687. role_assign($rolesmapping['defaultteacher'],
  2688. $newid,
  2689. 0,
  2690. $context->id,
  2691. $user->roles['teacher']->timestart,
  2692. $user->roles['teacher']->timeend,
  2693. 0,
  2694. $user->roles['teacher']->enrol);
  2695. }
  2696. }
  2697. if ($is_student) {
  2698. //Put status in backup_ids
  2699. $currinfo = $currinfo."student,";
  2700. $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
  2701. //Set course and user
  2702. $user->roles['student']->course = $restore->course_id;
  2703. $user->roles['student']->userid = $newid;
  2704. //Need to analyse the enrol field
  2705. // - if it isn't set, set it to $CFG->enrol
  2706. // - if we are in a different server (by wwwroot), set it to $CFG->enrol
  2707. // - if we are in the same server (by wwwroot), maintain it unmodified.
  2708. if (empty($user->roles['student']->enrol)) {
  2709. $user->roles['student']->enrol = $CFG->enrol;
  2710. } else if (!backup_is_same_site($restore)) {
  2711. $user->roles['student']->enrol = $CFG->enrol;
  2712. } else {
  2713. //Nothing to do. Leave it unmodified
  2714. }
  2715. $rolesmapping = $restore->rolesmapping;
  2716. $context = get_context_instance(CONTEXT_COURSE, $restore->course_id);
  2717. role_assign($rolesmapping['defaultstudent'],
  2718. $newid,
  2719. 0,
  2720. $context->id,
  2721. $user->roles['student']->timestart,
  2722. $user->roles['student']->timeend,
  2723. 0,
  2724. $user->roles['student']->enrol);
  2725. }
  2726. if (!$is_course_user) {
  2727. //If the record (user) doesn't exists
  2728. if (!record_exists("user","id",$newid)) {
  2729. //Put status in backup_ids
  2730. $currinfo = $currinfo."user,";
  2731. $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
  2732. }
  2733. }
  2734. }
  2735. /// Here, if create_custom_profile_fields, do it as necessary
  2736. if ($create_custom_profile_fields) {
  2737. if (isset($user->user_custom_profile_fields)) {
  2738. foreach($user->user_custom_profile_fields as $udata) {
  2739. /// If the profile field has data and the profile shortname-datatype is defined in server
  2740. if ($udata->field_data) {
  2741. if ($field = get_record('user_info_field', 'shortname', $udata->field_name, 'datatype', $udata->field_type)) {
  2742. /// Insert the user_custom_profile_field
  2743. $rec = new object();
  2744. $rec->userid = $newid;
  2745. $rec->fieldid = $field->id;
  2746. $rec->data = $udata->field_data;
  2747. insert_record('user_info_data', $rec);
  2748. }
  2749. }
  2750. }
  2751. }
  2752. }
  2753. /// Here, if create_tags, do it as necessary
  2754. if ($create_tags) {
  2755. /// if tags are enabled and there are user tags
  2756. if (!empty($CFG->usetags) && isset($user->user_tags)) {
  2757. $tags = array();
  2758. foreach($user->user_tags as $user_tag) {
  2759. $tags[] = $user_tag->rawname;
  2760. }
  2761. tag_set('user', $newid, $tags);
  2762. }
  2763. }
  2764. //Here, if create_preferences, do it as necessary
  2765. if ($create_preferences) {
  2766. if (isset($user->user_preferences)) {
  2767. foreach($user->user_preferences as $user_preference) {
  2768. //We check if that user_preference exists in DB
  2769. if (!record_exists("user_preferences","userid",$newid,"name",$user_preference->name)) {
  2770. //Prepare the record and insert it
  2771. $user_preference->userid = $newid;
  2772. $status = insert_record("user_preferences",$user_preference);
  2773. }
  2774. }
  2775. }
  2776. }
  2777. //Do some output
  2778. $counter++;
  2779. if ($counter % 10 == 0) {
  2780. if (!defined('RESTORE_SILENTLY')) {
  2781. echo ".";
  2782. if ($counter % 200 == 0) {
  2783. echo "<br />";
  2784. }
  2785. }
  2786. backup_flush(300);
  2787. }
  2788. } /// End of loop over all the users loaded from backup_ids table
  2789. /// Inform about all the messages geerated while restoring users
  2790. if (!defined('RESTORE_SILENTLY')) {
  2791. if ($messages) {
  2792. echo '<ul>';
  2793. foreach ($messages as $message) {
  2794. echo '<li>' . $message . '</li>';
  2795. }
  2796. echo '</ul>';
  2797. }
  2798. }
  2799. }
  2800. return $status;
  2801. }
  2802. //This function creates all the structures messages and contacts
  2803. function restore_create_messages($restore,$xml_file) {
  2804. global $CFG;
  2805. $status = true;
  2806. //Check it exists
  2807. if (!file_exists($xml_file)) {
  2808. $status = false;
  2809. }
  2810. //Get info from xml
  2811. if ($status) {
  2812. //info will contain the id and name of every table
  2813. //(message, message_read and message_contacts)
  2814. //in backup_ids->info will be the real info (serialized)
  2815. $info = restore_read_xml_messages($restore,$xml_file);
  2816. //If we have info, then process messages & contacts
  2817. if ($info > 0) {
  2818. //Count how many we have
  2819. $unreadcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'message');
  2820. $readcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'message_read');
  2821. $contactcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'message_contacts');
  2822. if ($unreadcount || $readcount || $contactcount) {
  2823. //Start ul
  2824. if (!defined('RESTORE_SILENTLY')) {
  2825. echo '<ul>';
  2826. }
  2827. //Number of records to get in every chunk
  2828. $recordset_size = 4;
  2829. //Process unread
  2830. if ($unreadcount) {
  2831. if (!defined('RESTORE_SILENTLY')) {
  2832. echo '<li>'.get_string('unreadmessages','message').'</li>';
  2833. }
  2834. $counter = 0;
  2835. while ($counter < $unreadcount) {
  2836. //Fetch recordset_size records in each iteration
  2837. $recs = get_records_select("backup_ids","table_name = 'message' AND backup_code = '$restore->backup_unique_code'","old_id","old_id",$counter,$recordset_size);
  2838. if ($recs) {
  2839. foreach ($recs as $rec) {
  2840. //Get the full record from backup_ids
  2841. $data = backup_getid($restore->backup_unique_code,"message",$rec->old_id);
  2842. if ($data) {
  2843. //Now get completed xmlized object
  2844. $info = $data->info;
  2845. //traverse_xmlize($info); //Debug
  2846. //print_object ($GLOBALS['traverse_array']); //Debug
  2847. //$GLOBALS['traverse_array']=""; //Debug
  2848. //Now build the MESSAGE record structure
  2849. $dbrec = new object();
  2850. $dbrec->useridfrom = backup_todb($info['MESSAGE']['#']['USERIDFROM']['0']['#']);
  2851. $dbrec->useridto = backup_todb($info['MESSAGE']['#']['USERIDTO']['0']['#']);
  2852. $dbrec->message = backup_todb($info['MESSAGE']['#']['MESSAGE']['0']['#']);
  2853. $dbrec->format = backup_todb($info['MESSAGE']['#']['FORMAT']['0']['#']);
  2854. $dbrec->timecreated = backup_todb($info['MESSAGE']['#']['TIMECREATED']['0']['#']);
  2855. $dbrec->messagetype = backup_todb($info['MESSAGE']['#']['MESSAGETYPE']['0']['#']);
  2856. //We have to recode the useridfrom field
  2857. $user = backup_getid($restore->backup_unique_code,"user",$dbrec->useridfrom);
  2858. if ($user) {
  2859. //echo "User ".$dbrec->useridfrom." to user ".$user->new_id."<br />"; //Debug
  2860. $dbrec->useridfrom = $user->new_id;
  2861. }
  2862. //We have to recode the useridto field
  2863. $user = backup_getid($restore->backup_unique_code,"user",$dbrec->useridto);
  2864. if ($user) {
  2865. //echo "User ".$dbrec->useridto." to user ".$user->new_id."<br />"; //Debug
  2866. $dbrec->useridto = $user->new_id;
  2867. }
  2868. //Check if the record doesn't exist in DB!
  2869. $exist = get_record('message','useridfrom',$dbrec->useridfrom,
  2870. 'useridto', $dbrec->useridto,
  2871. 'timecreated',$dbrec->timecreated);
  2872. if (!$exist) {
  2873. //Not exist. Insert
  2874. $status = insert_record('message',$dbrec);
  2875. } else {
  2876. //Duplicate. Do nothing
  2877. }
  2878. }
  2879. //Do some output
  2880. $counter++;
  2881. if ($counter % 10 == 0) {
  2882. if (!defined('RESTORE_SILENTLY')) {
  2883. echo ".";
  2884. if ($counter % 200 == 0) {
  2885. echo "<br />";
  2886. }
  2887. }
  2888. backup_flush(300);
  2889. }
  2890. }
  2891. }
  2892. }
  2893. }
  2894. //Process read
  2895. if ($readcount) {
  2896. if (!defined('RESTORE_SILENTLY')) {
  2897. echo '<li>'.get_string('readmessages','message').'</li>';
  2898. }
  2899. $counter = 0;
  2900. while ($counter < $readcount) {
  2901. //Fetch recordset_size records in each iteration
  2902. $recs = get_records_select("backup_ids","table_name = 'message_read' AND backup_code = '$restore->backup_unique_code'","old_id","old_id",$counter,$recordset_size);
  2903. if ($recs) {
  2904. foreach ($recs as $rec) {
  2905. //Get the full record from backup_ids
  2906. $data = backup_getid($restore->backup_unique_code,"message_read",$rec->old_id);
  2907. if ($data) {
  2908. //Now get completed xmlized object
  2909. $info = $data->info;
  2910. //traverse_xmlize($info); //Debug
  2911. //print_object ($GLOBALS['traverse_array']); //Debug
  2912. //$GLOBALS['traverse_array']=""; //Debug
  2913. //Now build the MESSAGE_READ record structure
  2914. $dbrec->useridfrom = backup_todb($info['MESSAGE']['#']['USERIDFROM']['0']['#']);
  2915. $dbrec->useridto = backup_todb($info['MESSAGE']['#']['USERIDTO']['0']['#']);
  2916. $dbrec->message = backup_todb($info['MESSAGE']['#']['MESSAGE']['0']['#']);
  2917. $dbrec->format = backup_todb($info['MESSAGE']['#']['FORMAT']['0']['#']);
  2918. $dbrec->timecreated = backup_todb($info['MESSAGE']['#']['TIMECREATED']['0']['#']);
  2919. $dbrec->messagetype = backup_todb($info['MESSAGE']['#']['MESSAGETYPE']['0']['#']);
  2920. $dbrec->timeread = backup_todb($info['MESSAGE']['#']['TIMEREAD']['0']['#']);
  2921. $dbrec->mailed = backup_todb($info['MESSAGE']['#']['MAILED']['0']['#']);
  2922. //We have to recode the useridfrom field
  2923. $user = backup_getid($restore->backup_unique_code,"user",$dbrec->useridfrom);
  2924. if ($user) {
  2925. //echo "User ".$dbrec->useridfrom." to user ".$user->new_id."<br />"; //Debug
  2926. $dbrec->useridfrom = $user->new_id;
  2927. }
  2928. //We have to recode the useridto field
  2929. $user = backup_getid($restore->backup_unique_code,"user",$dbrec->useridto);
  2930. if ($user) {
  2931. //echo "User ".$dbrec->useridto." to user ".$user->new_id."<br />"; //Debug
  2932. $dbrec->useridto = $user->new_id;
  2933. }
  2934. //Check if the record doesn't exist in DB!
  2935. $exist = get_record('message_read','useridfrom',$dbrec->useridfrom,
  2936. 'useridto', $dbrec->useridto,
  2937. 'timecreated',$dbrec->timecreated);
  2938. if (!$exist) {
  2939. //Not exist. Insert
  2940. $status = insert_record('message_read',$dbrec);
  2941. } else {
  2942. //Duplicate. Do nothing
  2943. }
  2944. }
  2945. //Do some output
  2946. $counter++;
  2947. if ($counter % 10 == 0) {
  2948. if (!defined('RESTORE_SILENTLY')) {
  2949. echo ".";
  2950. if ($counter % 200 == 0) {
  2951. echo "<br />";
  2952. }
  2953. }
  2954. backup_flush(300);
  2955. }
  2956. }
  2957. }
  2958. }
  2959. }
  2960. //Process contacts
  2961. if ($contactcount) {
  2962. if (!defined('RESTORE_SILENTLY')) {
  2963. echo '<li>'.moodle_strtolower(get_string('contacts','message')).'</li>';
  2964. }
  2965. $counter = 0;
  2966. while ($counter < $contactcount) {
  2967. //Fetch recordset_size records in each iteration
  2968. $recs = get_records_select("backup_ids","table_name = 'message_contacts' AND backup_code = '$restore->backup_unique_code'","old_id","old_id",$counter,$recordset_size);
  2969. if ($recs) {
  2970. foreach ($recs as $rec) {
  2971. //Get the full record from backup_ids
  2972. $data = backup_getid($restore->backup_unique_code,"message_contacts",$rec->old_id);
  2973. if ($data) {
  2974. //Now get completed xmlized object
  2975. $info = $data->info;
  2976. //traverse_xmlize($info); //Debug
  2977. //print_object ($GLOBALS['traverse_array']); //Debug
  2978. //$GLOBALS['traverse_array']=""; //Debug
  2979. //Now build the MESSAGE_CONTACTS record structure
  2980. $dbrec->userid = backup_todb($info['CONTACT']['#']['USERID']['0']['#']);
  2981. $dbrec->contactid = backup_todb($info['CONTACT']['#']['CONTACTID']['0']['#']);
  2982. $dbrec->blocked = backup_todb($info['CONTACT']['#']['BLOCKED']['0']['#']);
  2983. //We have to recode the userid field
  2984. $user = backup_getid($restore->backup_unique_code,"user",$dbrec->userid);
  2985. if ($user) {
  2986. //echo "User ".$dbrec->userid." to user ".$user->new_id."<br />"; //Debug
  2987. $dbrec->userid = $user->new_id;
  2988. }
  2989. //We have to recode the contactid field
  2990. $user = backup_getid($restore->backup_unique_code,"user",$dbrec->contactid);
  2991. if ($user) {
  2992. //echo "User ".$dbrec->contactid." to user ".$user->new_id."<br />"; //Debug
  2993. $dbrec->contactid = $user->new_id;
  2994. }
  2995. //Check if the record doesn't exist in DB!
  2996. $exist = get_record('message_contacts','userid',$dbrec->userid,
  2997. 'contactid', $dbrec->contactid);
  2998. if (!$exist) {
  2999. //Not exist. Insert
  3000. $status = insert_record('message_contacts',$dbrec);
  3001. } else {
  3002. //Duplicate. Do nothing
  3003. }
  3004. }
  3005. //Do some output
  3006. $counter++;
  3007. if ($counter % 10 == 0) {
  3008. if (!defined('RESTORE_SILENTLY')) {
  3009. echo ".";
  3010. if ($counter % 200 == 0) {
  3011. echo "<br />";
  3012. }
  3013. }
  3014. backup_flush(300);
  3015. }
  3016. }
  3017. }
  3018. }
  3019. }
  3020. if (!defined('RESTORE_SILENTLY')) {
  3021. //End ul
  3022. echo '</ul>';
  3023. }
  3024. }
  3025. }
  3026. }
  3027. return $status;
  3028. }
  3029. //This function creates all the structures for blogs and blog tags
  3030. function restore_create_blogs($restore,$xml_file) {
  3031. global $CFG;
  3032. $status = true;
  3033. //Check it exists
  3034. if (!file_exists($xml_file)) {
  3035. $status = false;
  3036. }
  3037. //Get info from xml
  3038. if ($status) {
  3039. //info will contain the number of blogs in the backup file
  3040. //in backup_ids->info will be the real info (serialized)
  3041. $info = restore_read_xml_blogs($restore,$xml_file);
  3042. //If we have info, then process blogs & blog_tags
  3043. if ($info > 0) {
  3044. //Count how many we have
  3045. $blogcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'blog');
  3046. if ($blogcount) {
  3047. //Number of records to get in every chunk
  3048. $recordset_size = 4;
  3049. //Process blog
  3050. if ($blogcount) {
  3051. $counter = 0;
  3052. while ($counter < $blogcount) {
  3053. //Fetch recordset_size records in each iteration
  3054. $recs = get_records_select("backup_ids","table_name = 'blog' AND backup_code = '$restore->backup_unique_code'","old_id","old_id",$counter,$recordset_size);
  3055. if ($recs) {
  3056. foreach ($recs as $rec) {
  3057. //Get the full record from backup_ids
  3058. $data = backup_getid($restore->backup_unique_code,"blog",$rec->old_id);
  3059. if ($data) {
  3060. //Now get completed xmlized object
  3061. $info = $data->info;
  3062. //traverse_xmlize($info); //Debug
  3063. //print_object ($GLOBALS['traverse_array']); //Debug
  3064. //$GLOBALS['traverse_array']=""; //Debug
  3065. //Now build the BLOG record structure
  3066. $dbrec = new object();
  3067. $dbrec->module = backup_todb($info['BLOG']['#']['MODULE']['0']['#']);
  3068. $dbrec->userid = backup_todb($info['BLOG']['#']['USERID']['0']['#']);
  3069. $dbrec->courseid = backup_todb($info['BLOG']['#']['COURSEID']['0']['#']);
  3070. $dbrec->groupid = backup_todb($info['BLOG']['#']['GROUPID']['0']['#']);
  3071. $dbrec->moduleid = backup_todb($info['BLOG']['#']['MODULEID']['0']['#']);
  3072. $dbrec->coursemoduleid = backup_todb($info['BLOG']['#']['COURSEMODULEID']['0']['#']);
  3073. $dbrec->subject = backup_todb($info['BLOG']['#']['SUBJECT']['0']['#']);
  3074. $dbrec->summary = backup_todb($info['BLOG']['#']['SUMMARY']['0']['#']);
  3075. $dbrec->content = backup_todb($info['BLOG']['#']['CONTENT']['0']['#']);
  3076. $dbrec->uniquehash = backup_todb($info['BLOG']['#']['UNIQUEHASH']['0']['#']);
  3077. $dbrec->rating = backup_todb($info['BLOG']['#']['RATING']['0']['#']);
  3078. $dbrec->format = backup_todb($info['BLOG']['#']['FORMAT']['0']['#']);
  3079. $dbrec->attachment = backup_todb($info['BLOG']['#']['ATTACHMENT']['0']['#']);
  3080. $dbrec->publishstate = backup_todb($info['BLOG']['#']['PUBLISHSTATE']['0']['#']);
  3081. $dbrec->lastmodified = backup_todb($info['BLOG']['#']['LASTMODIFIED']['0']['#']);
  3082. $dbrec->created = backup_todb($info['BLOG']['#']['CREATED']['0']['#']);
  3083. $dbrec->usermodified = backup_todb($info['BLOG']['#']['USERMODIFIED']['0']['#']);
  3084. //We have to recode the userid field
  3085. $user = backup_getid($restore->backup_unique_code,"user",$dbrec->userid);
  3086. if ($user) {
  3087. //echo "User ".$dbrec->userid." to user ".$user->new_id."<br />"; //Debug
  3088. $dbrec->userid = $user->new_id;
  3089. }
  3090. //Check if the record doesn't exist in DB!
  3091. $exist = get_record('post','userid', $dbrec->userid,
  3092. 'subject', $dbrec->subject,
  3093. 'created', $dbrec->created);
  3094. $newblogid = 0;
  3095. if (!$exist) {
  3096. //Not exist. Insert
  3097. $newblogid = insert_record('post',$dbrec);
  3098. }
  3099. //Going to restore related tags. Check they are enabled and we have inserted a blog
  3100. if ($CFG->usetags && $newblogid) {
  3101. //Look for tags in this blog
  3102. if (isset($info['BLOG']['#']['BLOG_TAGS']['0']['#']['BLOG_TAG'])) {
  3103. $tagsarr = $info['BLOG']['#']['BLOG_TAGS']['0']['#']['BLOG_TAG'];
  3104. //Iterate over tags
  3105. $tags = array();
  3106. for($i = 0; $i < sizeof($tagsarr); $i++) {
  3107. $tag_info = $tagsarr[$i];
  3108. ///traverse_xmlize($tag_info); //Debug
  3109. ///print_object ($GLOBALS['traverse_array']); //Debug
  3110. ///$GLOBALS['traverse_array']=""; //Debug
  3111. $name = backup_todb($tag_info['#']['NAME']['0']['#']);
  3112. $rawname = backup_todb($tag_info['#']['RAWNAME']['0']['#']);
  3113. $tags[] = $rawname; //Rawname is all we need
  3114. }
  3115. tag_set('post', $newblogid, $tags); //Add all the tags in one API call
  3116. }
  3117. }
  3118. }
  3119. //Do some output
  3120. $counter++;
  3121. if ($counter % 10 == 0) {
  3122. if (!defined('RESTORE_SILENTLY')) {
  3123. echo ".";
  3124. if ($counter % 200 == 0) {
  3125. echo "<br />";
  3126. }
  3127. }
  3128. backup_flush(300);
  3129. }
  3130. }
  3131. }
  3132. }
  3133. }
  3134. }
  3135. }
  3136. }
  3137. return $status;
  3138. }
  3139. //This function creates all the categories and questions
  3140. //from xml
  3141. function restore_create_questions($restore,$xml_file) {
  3142. global $CFG, $db;
  3143. $status = true;
  3144. //Check it exists
  3145. if (!file_exists($xml_file)) {
  3146. $status = false;
  3147. }
  3148. //Get info from xml
  3149. if ($status) {
  3150. //info will contain the old_id of every category
  3151. //in backup_ids->info will be the real info (serialized)
  3152. $info = restore_read_xml_questions($restore,$xml_file);
  3153. }
  3154. //Now, if we have anything in info, we have to restore that
  3155. //categories/questions
  3156. if ($info) {
  3157. if ($info !== true) {
  3158. $status = $status && restore_question_categories($info, $restore);
  3159. }
  3160. } else {
  3161. $status = false;
  3162. }
  3163. return $status;
  3164. }
  3165. //This function creates all the scales
  3166. function restore_create_scales($restore,$xml_file) {
  3167. global $CFG, $USER, $db;
  3168. $status = true;
  3169. //Check it exists
  3170. if (!file_exists($xml_file)) {
  3171. $status = false;
  3172. }
  3173. //Get info from xml
  3174. if ($status) {
  3175. //scales will contain the old_id of every scale
  3176. //in backup_ids->info will be the real info (serialized)
  3177. $scales = restore_read_xml_scales($restore,$xml_file);
  3178. }
  3179. //Now, if we have anything in scales, we have to restore that
  3180. //scales
  3181. if ($scales) {
  3182. if ($scales !== true) {
  3183. //Iterate over each scale
  3184. foreach ($scales as $scale) {
  3185. //Get record from backup_ids
  3186. $data = backup_getid($restore->backup_unique_code,"scale",$scale->id);
  3187. if ($data) {
  3188. //Now get completed xmlized object
  3189. $info = $data->info;
  3190. //traverse_xmlize($info); //Debug
  3191. //print_object ($GLOBALS['traverse_array']); //Debug
  3192. //$GLOBALS['traverse_array']=""; //Debug
  3193. //Now build the SCALE record structure
  3194. $sca = new object();
  3195. $sca->courseid = backup_todb($info['SCALE']['#']['COURSEID']['0']['#']);
  3196. $sca->userid = backup_todb($info['SCALE']['#']['USERID']['0']['#']);
  3197. $sca->name = backup_todb($info['SCALE']['#']['NAME']['0']['#']);
  3198. $sca->scale = backup_todb($info['SCALE']['#']['SCALETEXT']['0']['#']);
  3199. $sca->description = backup_todb($info['SCALE']['#']['DESCRIPTION']['0']['#']);
  3200. $sca->timemodified = backup_todb($info['SCALE']['#']['TIMEMODIFIED']['0']['#']);
  3201. // Look for scale (by 'scale' both in standard (course=0) and current course
  3202. // with priority to standard scales (ORDER clause)
  3203. // scale is not course unique, use get_record_sql to suppress warning
  3204. // Going to compare LOB columns so, use the cross-db sql_compare_text() in both sides.
  3205. $compare_scale_clause = sql_compare_text('scale') . "=" . sql_compare_text("'" . $sca->scale . "'");
  3206. // Scale doesn't exist, create it
  3207. if (!$sca_db = get_record_sql("SELECT *
  3208. FROM {$CFG->prefix}scale
  3209. WHERE $compare_scale_clause
  3210. AND courseid IN (0, $restore->course_id)
  3211. ORDER BY courseid", true)) {
  3212. // Try to recode the user field, defaulting to current user if not found
  3213. $user = backup_getid($restore->backup_unique_code,"user",$sca->userid);
  3214. if ($user) {
  3215. $sca->userid = $user->new_id;
  3216. } else {
  3217. $sca->userid = $USER->id;
  3218. }
  3219. // If course scale, recode the course field
  3220. if ($sca->courseid != 0) {
  3221. $sca->courseid = $restore->course_id;
  3222. }
  3223. // If scale is standard, if user lacks perms to manage standar scales
  3224. // 'downgrade' them to course scales
  3225. if ($sca->courseid == 0 and !has_capability('moodle/course:managescales', get_context_instance(CONTEXT_SYSTEM), $sca->userid)) {
  3226. $sca->courseid = $restore->course_id;
  3227. }
  3228. //The structure is equal to the db, so insert the scale
  3229. $newid = insert_record ("scale",$sca);
  3230. // Scale exists, reuse it
  3231. } else {
  3232. $newid = $sca_db->id;
  3233. }
  3234. if ($newid) {
  3235. //We have the newid, update backup_ids
  3236. backup_putid($restore->backup_unique_code,"scale", $scale->id, $newid);
  3237. }
  3238. }
  3239. }
  3240. }
  3241. } else {
  3242. $status = false;
  3243. }
  3244. return $status;
  3245. }
  3246. /**
  3247. * Recode group ID field, and set group ID based on restore options.
  3248. * @return object Group object with new_id field.
  3249. */
  3250. function restore_group_getid($restore, $groupid) {
  3251. //We have to recode the groupid field
  3252. $group = backup_getid($restore->backup_unique_code, 'groups', $groupid);
  3253. if ($restore->groups == RESTORE_GROUPS_NONE or $restore->groups == RESTORE_GROUPINGS_ONLY) {
  3254. $group->new_id = 0;
  3255. }
  3256. return $group;
  3257. }
  3258. /**
  3259. * Recode grouping ID field, and set grouping ID based on restore options.
  3260. * @return object Group object with new_id field.
  3261. */
  3262. function restore_grouping_getid($restore, $groupingid) {
  3263. //We have to recode the groupid field
  3264. $grouping = backup_getid($restore->backup_unique_code, 'groupings', $groupingid);
  3265. if ($restore->groups != RESTORE_GROUPS_GROUPINGS and $restore->groups != RESTORE_GROUPINGS_ONLY) {
  3266. $grouping->new_id = 0;
  3267. }
  3268. return $grouping;
  3269. }
  3270. //This function creates all the groups
  3271. function restore_create_groups($restore,$xml_file) {
  3272. global $CFG;
  3273. //Check it exists
  3274. if (!file_exists($xml_file)) {
  3275. return false;
  3276. }
  3277. //Get info from xml
  3278. if (!$groups = restore_read_xml_groups($restore,$xml_file)) {
  3279. //groups will contain the old_id of every group
  3280. //in backup_ids->info will be the real info (serialized)
  3281. return false;
  3282. } else if ($groups === true) {
  3283. return true;
  3284. }
  3285. $status = true;
  3286. //Iterate over each group
  3287. foreach ($groups as $group) {
  3288. //Get record from backup_ids
  3289. $data = backup_getid($restore->backup_unique_code,"groups",$group->id);
  3290. if ($data) {
  3291. //Now get completed xmlized object
  3292. $info = $data->info;
  3293. //traverse_xmlize($info); //Debug
  3294. //print_object ($GLOBALS['traverse_array']); //Debug
  3295. //$GLOBALS['traverse_array']=""; //Debug
  3296. //Now build the GROUP record structure
  3297. $gro = new Object();
  3298. $gro->courseid = $restore->course_id;
  3299. $gro->name = backup_todb($info['GROUP']['#']['NAME']['0']['#']);
  3300. $gro->description = backup_todb($info['GROUP']['#']['DESCRIPTION']['0']['#']);
  3301. if (isset($info['GROUP']['#']['ENROLMENTKEY']['0']['#'])) {
  3302. $gro->enrolmentkey = backup_todb($info['GROUP']['#']['ENROLMENTKEY']['0']['#']);
  3303. } else {
  3304. $gro->enrolmentkey = backup_todb($info['GROUP']['#']['PASSWORD']['0']['#']);
  3305. }
  3306. $gro->picture = backup_todb($info['GROUP']['#']['PICTURE']['0']['#']);
  3307. $gro->hidepicture = backup_todb($info['GROUP']['#']['HIDEPICTURE']['0']['#']);
  3308. $gro->timecreated = backup_todb($info['GROUP']['#']['TIMECREATED']['0']['#']);
  3309. $gro->timemodified = backup_todb($info['GROUP']['#']['TIMEMODIFIED']['0']['#']);
  3310. //Now search if that group exists (by name and description field) in
  3311. //restore->course_id course
  3312. //Going to compare LOB columns so, use the cross-db sql_compare_text() in both sides.
  3313. $description_clause = '';
  3314. if (!empty($gro->description)) { /// Only for groups having a description
  3315. $literal_description = "'" . $gro->description . "'";
  3316. $description_clause = " AND " .
  3317. sql_compare_text('description') . " = " .
  3318. sql_compare_text($literal_description);
  3319. }
  3320. if (!$gro_db = get_record_sql("SELECT *
  3321. FROM {$CFG->prefix}groups
  3322. WHERE courseid = $restore->course_id AND
  3323. name = '{$gro->name}'" . $description_clause, true)) {
  3324. //If it doesn't exist, create
  3325. $newid = insert_record('groups', $gro);
  3326. } else {
  3327. //get current group id
  3328. $newid = $gro_db->id;
  3329. }
  3330. if ($newid) {
  3331. //We have the newid, update backup_ids
  3332. backup_putid($restore->backup_unique_code,"groups", $group->id, $newid);
  3333. } else {
  3334. $status = false;
  3335. continue;
  3336. }
  3337. //Now restore members in the groups_members, only if
  3338. //users are included
  3339. if ($restore->users != 2) {
  3340. if (!restore_create_groups_members($newid,$info,$restore)) {
  3341. $status = false;
  3342. }
  3343. }
  3344. }
  3345. }
  3346. //Now, restore group_files
  3347. if ($status) {
  3348. $status = restore_group_files($restore);
  3349. }
  3350. return $status;
  3351. }
  3352. //This function restores the groups_members
  3353. function restore_create_groups_members($group_id,$info,$restore) {
  3354. if (! isset($info['GROUP']['#']['MEMBERS']['0']['#']['MEMBER'])) {
  3355. //OK, some groups have no members.
  3356. return true;
  3357. }
  3358. //Get the members array
  3359. $members = $info['GROUP']['#']['MEMBERS']['0']['#']['MEMBER'];
  3360. $status = true;
  3361. //Iterate over members
  3362. for($i = 0; $i < sizeof($members); $i++) {
  3363. $mem_info = $members[$i];
  3364. //traverse_xmlize($mem_info); //Debug
  3365. //print_object ($GLOBALS['traverse_array']); //Debug
  3366. //$GLOBALS['traverse_array']=""; //Debug
  3367. //Now, build the GROUPS_MEMBERS record structure
  3368. $group_member = new Object();
  3369. $group_member->groupid = $group_id;
  3370. $group_member->userid = backup_todb($mem_info['#']['USERID']['0']['#']);
  3371. $group_member->timeadded = backup_todb($mem_info['#']['TIMEADDED']['0']['#']);
  3372. $newid = false;
  3373. //We have to recode the userid field
  3374. if (!$user = backup_getid($restore->backup_unique_code,"user",$group_member->userid)) {
  3375. debugging("group membership can not be restored, user id $group_member->userid not present in backup");
  3376. // do not not block the restore
  3377. continue;
  3378. }
  3379. $group_member->userid = $user->new_id;
  3380. //The structure is equal to the db, so insert the groups_members
  3381. if (record_exists("groups_members", 'groupid', $group_member->groupid, 'userid', $group_member->userid)) {
  3382. // user already member
  3383. } else if (!insert_record ("groups_members", $group_member)) {
  3384. $status = false;
  3385. continue;
  3386. }
  3387. //Do some output
  3388. if (($i+1) % 50 == 0) {
  3389. if (!defined('RESTORE_SILENTLY')) {
  3390. echo ".";
  3391. if (($i+1) % 1000 == 0) {
  3392. echo "<br />";
  3393. }
  3394. }
  3395. backup_flush(300);
  3396. }
  3397. }
  3398. return $status;
  3399. }
  3400. //This function creates all the groupings
  3401. function restore_create_groupings($restore,$xml_file) {
  3402. //Check it exists
  3403. if (!file_exists($xml_file)) {
  3404. return false;
  3405. }
  3406. //Get info from xml
  3407. if (!$groupings = restore_read_xml_groupings($restore,$xml_file)) {
  3408. return false;
  3409. } else if ($groupings === true) {
  3410. return true;
  3411. }
  3412. $status = true;
  3413. //Iterate over each group
  3414. foreach ($groupings as $grouping) {
  3415. if ($data = backup_getid($restore->backup_unique_code,"groupings",$grouping->id)) {
  3416. //Now get completed xmlized object
  3417. $info = $data->info;
  3418. //Now build the GROUPING record structure
  3419. $gro = new Object();
  3420. ///$gro->id = backup_todb($info['GROUPING']['#']['ID']['0']['#']);
  3421. $gro->courseid = $restore->course_id;
  3422. $gro->name = backup_todb($info['GROUPING']['#']['NAME']['0']['#']);
  3423. $gro->description = backup_todb($info['GROUPING']['#']['DESCRIPTION']['0']['#']);
  3424. $gro->configdata = backup_todb($info['GROUPING']['#']['CONFIGDATA']['0']['#']);
  3425. $gro->timecreated = backup_todb($info['GROUPING']['#']['TIMECREATED']['0']['#']);
  3426. //Now search if that group exists (by name and description field) in
  3427. if ($gro_db = get_record('groupings', 'courseid', $restore->course_id, 'name', $gro->name, 'description', $gro->description)) {
  3428. //get current group id
  3429. $newid = $gro_db->id;
  3430. } else {
  3431. //The structure is equal to the db, so insert the grouping
  3432. if (!$newid = insert_record('groupings', $gro)) {
  3433. $status = false;
  3434. continue;
  3435. }
  3436. }
  3437. //We have the newid, update backup_ids
  3438. backup_putid($restore->backup_unique_code,"groupings",
  3439. $grouping->id, $newid);
  3440. }
  3441. }
  3442. // now fix the defaultgroupingid in course
  3443. $course = get_record('course', 'id', $restore->course_id);
  3444. if ($course->defaultgroupingid) {
  3445. if ($grouping = restore_grouping_getid($restore, $course->defaultgroupingid)) {
  3446. set_field('course', 'defaultgroupingid', $grouping->new_id, 'id', $course->id);
  3447. } else {
  3448. set_field('course', 'defaultgroupingid', 0, 'id', $course->id);
  3449. }
  3450. }
  3451. return $status;
  3452. }
  3453. //This function creates all the groupingsgroups
  3454. function restore_create_groupings_groups($restore,$xml_file) {
  3455. //Check it exists
  3456. if (!file_exists($xml_file)) {
  3457. return false;
  3458. }
  3459. //Get info from xml
  3460. if (!$groupingsgroups = restore_read_xml_groupings_groups($restore,$xml_file)) {
  3461. return false;
  3462. } else if ($groupingsgroups === true) {
  3463. return true;
  3464. }
  3465. $status = true;
  3466. //Iterate over each group
  3467. foreach ($groupingsgroups as $groupinggroup) {
  3468. if ($data = backup_getid($restore->backup_unique_code,"groupingsgroups",$groupinggroup->id)) {
  3469. //Now get completed xmlized object
  3470. $info = $data->info;
  3471. //Now build the GROUPING record structure
  3472. $gro_member = new Object();
  3473. $gro_member->groupingid = backup_todb($info['GROUPINGGROUP']['#']['GROUPINGID']['0']['#']);
  3474. $gro_member->groupid = backup_todb($info['GROUPINGGROUP']['#']['GROUPID']['0']['#']);
  3475. $gro_member->timeadded = backup_todb($info['GROUPINGGROUP']['#']['TIMEADDED']['0']['#']);
  3476. if (!$grouping = backup_getid($restore->backup_unique_code,"groupings",$gro_member->groupingid)) {
  3477. $status = false;
  3478. continue;
  3479. }
  3480. if (!$group = backup_getid($restore->backup_unique_code,"groups",$gro_member->groupid)) {
  3481. $status = false;
  3482. continue;
  3483. }
  3484. $gro_member->groupid = $group->new_id;
  3485. $gro_member->groupingid = $grouping->new_id;
  3486. if (!get_record('groupings_groups', 'groupid', $gro_member->groupid, 'groupingid', $gro_member->groupingid)) {
  3487. if (!insert_record('groupings_groups', $gro_member)) {
  3488. $status = false;
  3489. }
  3490. }
  3491. }
  3492. }
  3493. return $status;
  3494. }
  3495. //This function creates all the course events
  3496. function restore_create_events($restore,$xml_file) {
  3497. global $CFG, $db;
  3498. $status = true;
  3499. //Check it exists
  3500. if (!file_exists($xml_file)) {
  3501. $status = false;
  3502. }
  3503. //Get info from xml
  3504. if ($status) {
  3505. //events will contain the old_id of every event
  3506. //in backup_ids->info will be the real info (serialized)
  3507. $events = restore_read_xml_events($restore,$xml_file);
  3508. }
  3509. //Get admin->id for later use
  3510. $admin = get_admin();
  3511. $adminid = $admin->id;
  3512. //Now, if we have anything in events, we have to restore that
  3513. //events
  3514. if ($events) {
  3515. if ($events !== true) {
  3516. //Iterate over each event
  3517. foreach ($events as $event) {
  3518. //Get record from backup_ids
  3519. $data = backup_getid($restore->backup_unique_code,"event",$event->id);
  3520. //Init variables
  3521. $create_event = false;
  3522. if ($data) {
  3523. //Now get completed xmlized object
  3524. $info = $data->info;
  3525. //traverse_xmlize($info); //Debug
  3526. //print_object ($GLOBALS['traverse_array']); //Debug
  3527. //$GLOBALS['traverse_array']=""; //Debug
  3528. //if necessary, write to restorelog and adjust date/time fields
  3529. if ($restore->course_startdateoffset) {
  3530. restore_log_date_changes('Events', $restore, $info['EVENT']['#'], array('TIMESTART'));
  3531. }
  3532. //Now build the EVENT record structure
  3533. $eve->name = backup_todb($info['EVENT']['#']['NAME']['0']['#']);
  3534. $eve->description = backup_todb($info['EVENT']['#']['DESCRIPTION']['0']['#']);
  3535. $eve->format = backup_todb($info['EVENT']['#']['FORMAT']['0']['#']);
  3536. $eve->courseid = $restore->course_id;
  3537. $eve->groupid = backup_todb($info['EVENT']['#']['GROUPID']['0']['#']);
  3538. $eve->userid = backup_todb($info['EVENT']['#']['USERID']['0']['#']);
  3539. $eve->repeatid = backup_todb($info['EVENT']['#']['REPEATID']['0']['#']);
  3540. $eve->modulename = "";
  3541. if (!empty($info['EVENT']['#']['MODULENAME'])) {
  3542. $eve->modulename = backup_todb($info['EVENT']['#']['MODULENAME']['0']['#']);
  3543. }
  3544. $eve->instance = 0;
  3545. $eve->eventtype = backup_todb($info['EVENT']['#']['EVENTTYPE']['0']['#']);
  3546. $eve->timestart = backup_todb($info['EVENT']['#']['TIMESTART']['0']['#']);
  3547. $eve->timeduration = backup_todb($info['EVENT']['#']['TIMEDURATION']['0']['#']);
  3548. $eve->visible = backup_todb($info['EVENT']['#']['VISIBLE']['0']['#']);
  3549. $eve->timemodified = backup_todb($info['EVENT']['#']['TIMEMODIFIED']['0']['#']);
  3550. //Now search if that event exists (by name, description, timestart fields) in
  3551. //restore->course_id course
  3552. //Going to compare LOB columns so, use the cross-db sql_compare_text() in both sides.
  3553. $compare_description_clause = sql_compare_text('description') . "=" . sql_compare_text("'" . $eve->description . "'");
  3554. $eve_db = get_record_select("event",
  3555. "courseid={$eve->courseid} AND name='{$eve->name}' AND $compare_description_clause AND timestart=$eve->timestart");
  3556. //If it doesn't exist, create
  3557. if (!$eve_db) {
  3558. $create_event = true;
  3559. }
  3560. //If we must create the event
  3561. if ($create_event) {
  3562. //We must recode the userid
  3563. $user = backup_getid($restore->backup_unique_code,"user",$eve->userid);
  3564. if ($user) {
  3565. $eve->userid = $user->new_id;
  3566. } else {
  3567. //Assign it to admin
  3568. $eve->userid = $adminid;
  3569. }
  3570. //We have to recode the groupid field
  3571. $group = backup_getid($restore->backup_unique_code,"groups",$eve->groupid);
  3572. if ($group) {
  3573. $eve->groupid = $group->new_id;
  3574. } else {
  3575. //Assign it to group 0
  3576. $eve->groupid = 0;
  3577. }
  3578. //The structure is equal to the db, so insert the event
  3579. $newid = insert_record ("event",$eve);
  3580. //We must recode the repeatid if the event has it
  3581. //The repeatid now refers to the id of the original event. (see Bug#5956)
  3582. if ($newid && !empty($eve->repeatid)) {
  3583. $repeat_rec = backup_getid($restore->backup_unique_code,"event_repeatid",$eve->repeatid);
  3584. if ($repeat_rec) { //Exists, so use it...
  3585. $eve->repeatid = $repeat_rec->new_id;
  3586. } else { //Doesn't exists, calculate the next and save it
  3587. $oldrepeatid = $eve->repeatid;
  3588. $eve->repeatid = $newid;
  3589. backup_putid($restore->backup_unique_code,"event_repeatid", $oldrepeatid, $eve->repeatid);
  3590. }
  3591. $eve->id = $newid;
  3592. // update the record to contain the correct repeatid
  3593. update_record('event',$eve);
  3594. }
  3595. } else {
  3596. //get current event id
  3597. $newid = $eve_db->id;
  3598. }
  3599. if ($newid) {
  3600. //We have the newid, update backup_ids
  3601. backup_putid($restore->backup_unique_code,"event",
  3602. $event->id, $newid);
  3603. }
  3604. }
  3605. }
  3606. }
  3607. } else {
  3608. $status = false;
  3609. }
  3610. return $status;
  3611. }
  3612. //This function decode things to make restore multi-site fully functional
  3613. //It does this conversions:
  3614. // - $@FILEPHP@$ ---|------------> $CFG->wwwroot/file.php/courseid (slasharguments on)
  3615. // |------------> $CFG->wwwroot/file.php?file=/courseid (slasharguments off)
  3616. //
  3617. // - $@SLASH@$ --|---------------> / (slasharguments on)
  3618. // |---------------> %2F (slasharguments off)
  3619. //
  3620. // - $@FORCEDOWNLOAD@$ --|-------> ?forcedownload=1 (slasharguments on)
  3621. // |-------> &amp;forcedownload=1(slasharguments off)
  3622. //Note: Inter-activities linking is being implemented as a final
  3623. //step in the restore execution, because we need to have it
  3624. //finished to know all the oldid, newid equivaleces
  3625. function restore_decode_absolute_links($content) {
  3626. global $CFG,$restore;
  3627. require_once($CFG->libdir.'/filelib.php');
  3628. /// MDL-14072: Prevent NULLs, empties and numbers to be processed by the
  3629. /// heavy interlinking. Just a few cpu cycles saved.
  3630. if ($content === NULL) {
  3631. return NULL;
  3632. } else if ($content === '') {
  3633. return '';
  3634. } else if (is_numeric($content)) {
  3635. return $content;
  3636. }
  3637. //Now decode wwwroot and file.php calls
  3638. $search = array ("$@FILEPHP@$");
  3639. $replace = array(get_file_url($restore->course_id));
  3640. $result = str_replace($search,$replace,$content);
  3641. //Now $@SLASH@$ and $@FORCEDOWNLOAD@$ MDL-18799
  3642. $search = array('$@SLASH@$', '$@FORCEDOWNLOAD@$');
  3643. if ($CFG->slasharguments) {
  3644. $replace = array('/', '?forcedownload=1');
  3645. } else {
  3646. $replace = array('%2F', '&amp;forcedownload=1');
  3647. }
  3648. $result = str_replace($search, $replace, $result);
  3649. if ($result != $content && debugging()) { //Debug
  3650. if (!defined('RESTORE_SILENTLY')) {
  3651. echo '<br /><hr />'.s($content).'<br />changed to<br />'.s($result).'<hr /><br />'; //Debug
  3652. }
  3653. } //Debug
  3654. return $result;
  3655. }
  3656. //This function restores the userfiles from the temp (user_files) directory to the
  3657. //dataroot/users directory
  3658. function restore_user_files($restore) {
  3659. global $CFG;
  3660. $status = true;
  3661. $counter = 0;
  3662. // 'users' is the old users folder, 'user' is the new one, with a new hierarchy. Detect which one is here and treat accordingly
  3663. //in CFG->dataroot
  3664. $dest_dir = $CFG->dataroot."/user";
  3665. $status = check_dir_exists($dest_dir,true);
  3666. //Now, we iterate over "user_files" records to check if that user dir must be
  3667. //copied (and renamed) to the "users" dir.
  3668. $rootdir = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/user_files";
  3669. //Check if directory exists
  3670. $userlist = array();
  3671. if (is_dir($rootdir) && ($list = list_directories ($rootdir))) {
  3672. $counter = 0;
  3673. foreach ($list as $dir) {
  3674. // If there are directories in this folder, we are in the new user hierarchy
  3675. if ($newlist = list_directories("$rootdir/$dir")) {
  3676. foreach ($newlist as $olduserid) {
  3677. $userlist[$olduserid] = "$rootdir/$dir/$olduserid";
  3678. }
  3679. } else {
  3680. $userlist[$dir] = "$rootdir/$dir";
  3681. }
  3682. }
  3683. foreach ($userlist as $olduserid => $backup_location) {
  3684. //Look for dir like username in backup_ids
  3685. //If that user exists in backup_ids
  3686. if ($user = backup_getid($restore->backup_unique_code,"user",$olduserid)) {
  3687. //Only if user has been created now or if it existed previously, but he hasn't got an image (see bug 1123)
  3688. $newuserdir = make_user_directory($user->new_id, true); // Doesn't create the folder, just returns the location
  3689. // restore images if new user or image does not exist yet
  3690. if (!empty($user->new) or !check_dir_exists($newuserdir)) {
  3691. if (make_user_directory($user->new_id)) { // Creates the folder
  3692. $status = backup_copy_file($backup_location, $newuserdir, true);
  3693. $counter ++;
  3694. }
  3695. //Do some output
  3696. if ($counter % 2 == 0) {
  3697. if (!defined('RESTORE_SILENTLY')) {
  3698. echo ".";
  3699. if ($counter % 40 == 0) {
  3700. echo "<br />";
  3701. }
  3702. }
  3703. backup_flush(300);
  3704. }
  3705. }
  3706. }
  3707. }
  3708. }
  3709. //If status is ok and whe have dirs created, returns counter to inform
  3710. if ($status and $counter) {
  3711. return $counter;
  3712. } else {
  3713. return $status;
  3714. }
  3715. }
  3716. //This function restores the groupfiles from the temp (group_files) directory to the
  3717. //dataroot/groups directory
  3718. function restore_group_files($restore) {
  3719. global $CFG;
  3720. $status = true;
  3721. $counter = 0;
  3722. //First, we check to "groups" exists and create is as necessary
  3723. //in CFG->dataroot
  3724. $dest_dir = $CFG->dataroot.'/groups';
  3725. $status = check_dir_exists($dest_dir,true);
  3726. //Now, we iterate over "group_files" records to check if that user dir must be
  3727. //copied (and renamed) to the "groups" dir.
  3728. $rootdir = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/group_files";
  3729. //Check if directory exists
  3730. if (is_dir($rootdir)) {
  3731. $list = list_directories ($rootdir);
  3732. if ($list) {
  3733. //Iterate
  3734. $counter = 0;
  3735. foreach ($list as $dir) {
  3736. //Look for dir like groupid in backup_ids
  3737. $data = get_record ("backup_ids","backup_code",$restore->backup_unique_code,
  3738. "table_name","groups",
  3739. "old_id",$dir);
  3740. //If that group exists in backup_ids
  3741. if ($data) {
  3742. if (!file_exists($dest_dir."/".$data->new_id)) {
  3743. $status = backup_copy_file($rootdir."/".$dir, $dest_dir."/".$data->new_id,true);
  3744. $counter ++;
  3745. }
  3746. //Do some output
  3747. if ($counter % 2 == 0) {
  3748. if (!defined('RESTORE_SILENTLY')) {
  3749. echo ".";
  3750. if ($counter % 40 == 0) {
  3751. echo "<br />";
  3752. }
  3753. }
  3754. backup_flush(300);
  3755. }
  3756. }
  3757. }
  3758. }
  3759. }
  3760. //If status is ok and whe have dirs created, returns counter to inform
  3761. if ($status and $counter) {
  3762. return $counter;
  3763. } else {
  3764. return $status;
  3765. }
  3766. }
  3767. //This function restores the course files from the temp (course_files) directory to the
  3768. //dataroot/course_id directory
  3769. function restore_course_files($restore) {
  3770. global $CFG;
  3771. $status = true;
  3772. $counter = 0;
  3773. //First, we check to "course_id" exists and create is as necessary
  3774. //in CFG->dataroot
  3775. $dest_dir = $CFG->dataroot."/".$restore->course_id;
  3776. $status = check_dir_exists($dest_dir,true);
  3777. //Now, we iterate over "course_files" records to check if that file/dir must be
  3778. //copied to the "dest_dir" dir.
  3779. $rootdir = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/course_files";
  3780. //Check if directory exists
  3781. if (is_dir($rootdir)) {
  3782. $list = list_directories_and_files ($rootdir);
  3783. if ($list) {
  3784. //Iterate
  3785. $counter = 0;
  3786. foreach ($list as $dir) {
  3787. //Copy the dir to its new location
  3788. //Only if destination file/dir doesn exists
  3789. if (!file_exists($dest_dir."/".$dir)) {
  3790. $status = backup_copy_file($rootdir."/".$dir,
  3791. $dest_dir."/".$dir,true);
  3792. $counter ++;
  3793. }
  3794. //Do some output
  3795. if ($counter % 2 == 0) {
  3796. if (!defined('RESTORE_SILENTLY')) {
  3797. echo ".";
  3798. if ($counter % 40 == 0) {
  3799. echo "<br />";
  3800. }
  3801. }
  3802. backup_flush(300);
  3803. }
  3804. }
  3805. }
  3806. }
  3807. //If status is ok and whe have dirs created, returns counter to inform
  3808. if ($status and $counter) {
  3809. return $counter;
  3810. } else {
  3811. return $status;
  3812. }
  3813. }
  3814. //This function restores the site files from the temp (site_files) directory to the
  3815. //dataroot/SITEID directory
  3816. function restore_site_files($restore) {
  3817. global $CFG;
  3818. $status = true;
  3819. $counter = 0;
  3820. //First, we check to "course_id" exists and create is as necessary
  3821. //in CFG->dataroot
  3822. $dest_dir = $CFG->dataroot."/".SITEID;
  3823. $status = check_dir_exists($dest_dir,true);
  3824. //Now, we iterate over "site_files" files to check if that file/dir must be
  3825. //copied to the "dest_dir" dir.
  3826. $rootdir = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/site_files";
  3827. //Check if directory exists
  3828. if (is_dir($rootdir)) {
  3829. $list = list_directories_and_files ($rootdir);
  3830. if ($list) {
  3831. //Iterate
  3832. $counter = 0;
  3833. foreach ($list as $dir) {
  3834. //Avoid copying maintenance.html. MDL-18594
  3835. if ($dir == 'maintenance.html') {
  3836. continue;
  3837. }
  3838. //Copy the dir to its new location
  3839. //Only if destination file/dir doesn exists
  3840. if (!file_exists($dest_dir."/".$dir)) {
  3841. $status = backup_copy_file($rootdir."/".$dir,
  3842. $dest_dir."/".$dir,true);
  3843. $counter ++;
  3844. }
  3845. //Do some output
  3846. if ($counter % 2 == 0) {
  3847. if (!defined('RESTORE_SILENTLY')) {
  3848. echo ".";
  3849. if ($counter % 40 == 0) {
  3850. echo "<br />";
  3851. }
  3852. }
  3853. backup_flush(300);
  3854. }
  3855. }
  3856. }
  3857. }
  3858. //If status is ok and whe have dirs created, returns counter to inform
  3859. if ($status and $counter) {
  3860. return $counter;
  3861. } else {
  3862. return $status;
  3863. }
  3864. }
  3865. //This function creates all the structures for every module in backup file
  3866. //Depending what has been selected.
  3867. function restore_create_modules($restore,$xml_file) {
  3868. global $CFG;
  3869. $status = true;
  3870. //Check it exists
  3871. if (!file_exists($xml_file)) {
  3872. $status = false;
  3873. }
  3874. //Get info from xml
  3875. if ($status) {
  3876. //info will contain the id and modtype of every module
  3877. //in backup_ids->info will be the real info (serialized)
  3878. $info = restore_read_xml_modules($restore,$xml_file);
  3879. }
  3880. //Now, if we have anything in info, we have to restore that mods
  3881. //from backup_ids (calling every mod restore function)
  3882. if ($info) {
  3883. if ($info !== true) {
  3884. if (!defined('RESTORE_SILENTLY')) {
  3885. echo '<ul>';
  3886. }
  3887. //Iterate over each module
  3888. foreach ($info as $mod) {
  3889. if (empty($restore->mods[$mod->modtype]->granular) // We don't care about per instance, i.e. restore all instances.
  3890. || (array_key_exists($mod->id,$restore->mods[$mod->modtype]->instances)
  3891. && !empty($restore->mods[$mod->modtype]->instances[$mod->id]->restore))) {
  3892. $modrestore = $mod->modtype."_restore_mods";
  3893. if (function_exists($modrestore)) { //Debug
  3894. // we want to restore all mods even when one fails
  3895. // incorrect code here ignored any errors during module restore in 1.6-1.8
  3896. $status = $status && $modrestore($mod,$restore);
  3897. } else {
  3898. //Something was wrong. Function should exist.
  3899. $status = false;
  3900. }
  3901. }
  3902. }
  3903. if (!defined('RESTORE_SILENTLY')) {
  3904. echo '</ul>';
  3905. }
  3906. }
  3907. } else {
  3908. $status = false;
  3909. }
  3910. return $status;
  3911. }
  3912. //This function creates all the structures for every log in backup file
  3913. //Depending what has been selected.
  3914. function restore_create_logs($restore,$xml_file) {
  3915. global $CFG,$db;
  3916. //Number of records to get in every chunk
  3917. $recordset_size = 4;
  3918. //Counter, points to current record
  3919. $counter = 0;
  3920. //To count all the recods to restore
  3921. $count_logs = 0;
  3922. $status = true;
  3923. //Check it exists
  3924. if (!file_exists($xml_file)) {
  3925. $status = false;
  3926. }
  3927. //Get info from xml
  3928. if ($status) {
  3929. //count_logs will contain the number of logs entries to process
  3930. //in backup_ids->info will be the real info (serialized)
  3931. $count_logs = restore_read_xml_logs($restore,$xml_file);
  3932. }
  3933. //Now, if we have records in count_logs, we have to restore that logs
  3934. //from backup_ids. This piece of code makes calls to:
  3935. // - restore_log_course() if it's a course log
  3936. // - restore_log_user() if it's a user log
  3937. // - restore_log_module() if it's a module log.
  3938. //And all is segmented in chunks to allow large recordsets to be restored !!
  3939. if ($count_logs > 0) {
  3940. while ($counter < $count_logs) {
  3941. //Get a chunk of records
  3942. //Take old_id twice to avoid adodb limitation
  3943. $logs = get_records_select("backup_ids","table_name = 'log' AND backup_code = '$restore->backup_unique_code'","old_id","old_id",$counter,$recordset_size);
  3944. //We have logs
  3945. if ($logs) {
  3946. //Iterate
  3947. foreach ($logs as $log) {
  3948. //Get the full record from backup_ids
  3949. $data = backup_getid($restore->backup_unique_code,"log",$log->old_id);
  3950. if ($data) {
  3951. //Now get completed xmlized object
  3952. $info = $data->info;
  3953. //traverse_xmlize($info); //Debug
  3954. //print_object ($GLOBALS['traverse_array']); //Debug
  3955. //$GLOBALS['traverse_array']=""; //Debug
  3956. //Now build the LOG record structure
  3957. $dblog = new object();
  3958. $dblog->time = backup_todb($info['LOG']['#']['TIME']['0']['#']);
  3959. $dblog->userid = backup_todb($info['LOG']['#']['USERID']['0']['#']);
  3960. $dblog->ip = backup_todb($info['LOG']['#']['IP']['0']['#']);
  3961. $dblog->course = $restore->course_id;
  3962. $dblog->module = backup_todb($info['LOG']['#']['MODULE']['0']['#']);
  3963. $dblog->cmid = backup_todb($info['LOG']['#']['CMID']['0']['#']);
  3964. $dblog->action = backup_todb($info['LOG']['#']['ACTION']['0']['#']);
  3965. $dblog->url = backup_todb($info['LOG']['#']['URL']['0']['#']);
  3966. $dblog->info = backup_todb($info['LOG']['#']['INFO']['0']['#']);
  3967. //We have to recode the userid field
  3968. $user = backup_getid($restore->backup_unique_code,"user",$dblog->userid);
  3969. if ($user) {
  3970. //echo "User ".$dblog->userid." to user ".$user->new_id."<br />"; //Debug
  3971. $dblog->userid = $user->new_id;
  3972. }
  3973. //We have to recode the cmid field (if module isn't "course" or "user")
  3974. if ($dblog->module != "course" and $dblog->module != "user") {
  3975. $cm = backup_getid($restore->backup_unique_code,"course_modules",$dblog->cmid);
  3976. if ($cm) {
  3977. //echo "Module ".$dblog->cmid." to module ".$cm->new_id."<br />"; //Debug
  3978. $dblog->cmid = $cm->new_id;
  3979. } else {
  3980. $dblog->cmid = 0;
  3981. }
  3982. }
  3983. //print_object ($dblog); //Debug
  3984. //Now, we redirect to the needed function to make all the work
  3985. if ($dblog->module == "course") {
  3986. //It's a course log,
  3987. $stat = restore_log_course($restore,$dblog);
  3988. } elseif ($dblog->module == "user") {
  3989. //It's a user log,
  3990. $stat = restore_log_user($restore,$dblog);
  3991. } else {
  3992. //It's a module log,
  3993. $stat = restore_log_module($restore,$dblog);
  3994. }
  3995. }
  3996. //Do some output
  3997. $counter++;
  3998. if ($counter % 10 == 0) {
  3999. if (!defined('RESTORE_SILENTLY')) {
  4000. echo ".";
  4001. if ($counter % 200 == 0) {
  4002. echo "<br />";
  4003. }
  4004. }
  4005. backup_flush(300);
  4006. }
  4007. }
  4008. } else {
  4009. //We never should arrive here
  4010. $counter = $count_logs;
  4011. $status = false;
  4012. }
  4013. }
  4014. }
  4015. return $status;
  4016. }
  4017. //This function inserts a course log record, calculating the URL field as necessary
  4018. function restore_log_course($restore,$log) {
  4019. $status = true;
  4020. $toinsert = false;
  4021. //echo "<hr />Before transformations<br />"; //Debug
  4022. //print_object($log); //Debug
  4023. //Depending of the action, we recode different things
  4024. switch ($log->action) {
  4025. case "view":
  4026. $log->url = "view.php?id=".$log->course;
  4027. $log->info = $log->course;
  4028. $toinsert = true;
  4029. break;
  4030. case "guest":
  4031. $log->url = "view.php?id=".$log->course;
  4032. $toinsert = true;
  4033. break;
  4034. case "user report":
  4035. //recode the info field (it's the user id)
  4036. $user = backup_getid($restore->backup_unique_code,"user",$log->info);
  4037. if ($user) {
  4038. $log->info = $user->new_id;
  4039. //Now, extract the mode from the url field
  4040. $mode = substr(strrchr($log->url,"="),1);
  4041. $log->url = "user.php?id=".$log->course."&user=".$log->info."&mode=".$mode;
  4042. $toinsert = true;
  4043. }
  4044. break;
  4045. case "add mod":
  4046. //Extract the course_module from the url field
  4047. $cmid = substr(strrchr($log->url,"="),1);
  4048. //recode the course_module to see it it has been restored
  4049. $cm = backup_getid($restore->backup_unique_code,"course_modules",$cmid);
  4050. if ($cm) {
  4051. $cmid = $cm->new_id;
  4052. //Extract the module name and the module id from the info field
  4053. $modname = strtok($log->info," ");
  4054. $modid = strtok(" ");
  4055. //recode the module id to see if it has been restored
  4056. $mod = backup_getid($restore->backup_unique_code,$modname,$modid);
  4057. if ($mod) {
  4058. $modid = $mod->new_id;
  4059. //Now I have everything so reconstruct url and info
  4060. $log->info = $modname." ".$modid;
  4061. $log->url = "../mod/".$modname."/view.php?id=".$cmid;
  4062. $toinsert = true;
  4063. }
  4064. }
  4065. break;
  4066. case "update mod":
  4067. //Extract the course_module from the url field
  4068. $cmid = substr(strrchr($log->url,"="),1);
  4069. //recode the course_module to see it it has been restored
  4070. $cm = backup_getid($restore->backup_unique_code,"course_modules",$cmid);
  4071. if ($cm) {
  4072. $cmid = $cm->new_id;
  4073. //Extract the module name and the module id from the info field
  4074. $modname = strtok($log->info," ");
  4075. $modid = strtok(" ");
  4076. //recode the module id to see if it has been restored
  4077. $mod = backup_getid($restore->backup_unique_code,$modname,$modid);
  4078. if ($mod) {
  4079. $modid = $mod->new_id;
  4080. //Now I have everything so reconstruct url and info
  4081. $log->info = $modname." ".$modid;
  4082. $log->url = "../mod/".$modname."/view.php?id=".$cmid;
  4083. $toinsert = true;
  4084. }
  4085. }
  4086. break;
  4087. case "delete mod":
  4088. $log->url = "view.php?id=".$log->course;
  4089. $toinsert = true;
  4090. break;
  4091. case "update":
  4092. $log->url = "edit.php?id=".$log->course;
  4093. $log->info = "";
  4094. $toinsert = true;
  4095. break;
  4096. case "unenrol":
  4097. //recode the info field (it's the user id)
  4098. $user = backup_getid($restore->backup_unique_code,"user",$log->info);
  4099. if ($user) {
  4100. $log->info = $user->new_id;
  4101. $log->url = "view.php?id=".$log->course;
  4102. $toinsert = true;
  4103. }
  4104. break;
  4105. case "enrol":
  4106. //recode the info field (it's the user id)
  4107. $user = backup_getid($restore->backup_unique_code,"user",$log->info);
  4108. if ($user) {
  4109. $log->info = $user->new_id;
  4110. $log->url = "view.php?id=".$log->course;
  4111. $toinsert = true;
  4112. }
  4113. break;
  4114. case "editsection":
  4115. //Extract the course_section from the url field
  4116. $secid = substr(strrchr($log->url,"="),1);
  4117. //recode the course_section to see if it has been restored
  4118. $sec = backup_getid($restore->backup_unique_code,"course_sections",$secid);
  4119. if ($sec) {
  4120. $secid = $sec->new_id;
  4121. //Now I have everything so reconstruct url and info
  4122. $log->url = "editsection.php?id=".$secid;
  4123. $toinsert = true;
  4124. }
  4125. break;
  4126. case "new":
  4127. $log->url = "view.php?id=".$log->course;
  4128. $log->info = "";
  4129. $toinsert = true;
  4130. break;
  4131. case "recent":
  4132. $log->url = "recent.php?id=".$log->course;
  4133. $log->info = "";
  4134. $toinsert = true;
  4135. break;
  4136. case "report log":
  4137. $log->url = "report/log/index.php?id=".$log->course;
  4138. $log->info = $log->course;
  4139. $toinsert = true;
  4140. break;
  4141. case "report live":
  4142. $log->url = "report/log/live.php?id=".$log->course;
  4143. $log->info = $log->course;
  4144. $toinsert = true;
  4145. break;
  4146. case "report outline":
  4147. $log->url = "report/outline/index.php?id=".$log->course;
  4148. $log->info = $log->course;
  4149. $toinsert = true;
  4150. break;
  4151. case "report participation":
  4152. $log->url = "report/participation/index.php?id=".$log->course;
  4153. $log->info = $log->course;
  4154. $toinsert = true;
  4155. break;
  4156. case "report stats":
  4157. $log->url = "report/stats/index.php?id=".$log->course;
  4158. $log->info = $log->course;
  4159. $toinsert = true;
  4160. break;
  4161. default:
  4162. echo "action (".$log->module."-".$log->action.") unknown. Not restored<br />"; //Debug
  4163. break;
  4164. }
  4165. //echo "After transformations<br />"; //Debug
  4166. //print_object($log); //Debug
  4167. //Now if $toinsert is set, insert the record
  4168. if ($toinsert) {
  4169. //echo "Inserting record<br />"; //Debug
  4170. $status = insert_record("log",$log);
  4171. }
  4172. return $status;
  4173. }
  4174. //This function inserts a user log record, calculating the URL field as necessary
  4175. function restore_log_user($restore,$log) {
  4176. $status = true;
  4177. $toinsert = false;
  4178. //echo "<hr />Before transformations<br />"; //Debug
  4179. //print_object($log); //Debug
  4180. //Depending of the action, we recode different things
  4181. switch ($log->action) {
  4182. case "view":
  4183. //recode the info field (it's the user id)
  4184. $user = backup_getid($restore->backup_unique_code,"user",$log->info);
  4185. if ($user) {
  4186. $log->info = $user->new_id;
  4187. $log->url = "view.php?id=".$log->info."&course=".$log->course;
  4188. $toinsert = true;
  4189. }
  4190. break;
  4191. case "change password":
  4192. //recode the info field (it's the user id)
  4193. $user = backup_getid($restore->backup_unique_code,"user",$log->info);
  4194. if ($user) {
  4195. $log->info = $user->new_id;
  4196. $log->url = "view.php?id=".$log->info."&course=".$log->course;
  4197. $toinsert = true;
  4198. }
  4199. break;
  4200. case "login":
  4201. //recode the info field (it's the user id)
  4202. $user = backup_getid($restore->backup_unique_code,"user",$log->info);
  4203. if ($user) {
  4204. $log->info = $user->new_id;
  4205. $log->url = "view.php?id=".$log->info."&course=".$log->course;
  4206. $toinsert = true;
  4207. }
  4208. break;
  4209. case "logout":
  4210. //recode the info field (it's the user id)
  4211. $user = backup_getid($restore->backup_unique_code,"user",$log->info);
  4212. if ($user) {
  4213. $log->info = $user->new_id;
  4214. $log->url = "view.php?id=".$log->info."&course=".$log->course;
  4215. $toinsert = true;
  4216. }
  4217. break;
  4218. case "view all":
  4219. $log->url = "view.php?id=".$log->course;
  4220. $log->info = "";
  4221. $toinsert = true;
  4222. case "update":
  4223. //We split the url by ampersand char
  4224. $first_part = strtok($log->url,"&");
  4225. //Get data after the = char. It's the user being updated
  4226. $userid = substr(strrchr($first_part,"="),1);
  4227. //Recode the user
  4228. $user = backup_getid($restore->backup_unique_code,"user",$userid);
  4229. if ($user) {
  4230. $log->info = "";
  4231. $log->url = "view.php?id=".$user->new_id."&course=".$log->course;
  4232. $toinsert = true;
  4233. }
  4234. break;
  4235. default:
  4236. echo "action (".$log->module."-".$log->action.") unknown. Not restored<br />"; //Debug
  4237. break;
  4238. }
  4239. //echo "After transformations<br />"; //Debug
  4240. //print_object($log); //Debug
  4241. //Now if $toinsert is set, insert the record
  4242. if ($toinsert) {
  4243. //echo "Inserting record<br />"; //Debug
  4244. $status = insert_record("log",$log);
  4245. }
  4246. return $status;
  4247. }
  4248. //This function inserts a module log record, calculating the URL field as necessary
  4249. function restore_log_module($restore,$log) {
  4250. $status = true;
  4251. $toinsert = false;
  4252. //echo "<hr />Before transformations<br />"; //Debug
  4253. //print_object($log); //Debug
  4254. //Now we see if the required function in the module exists
  4255. $function = $log->module."_restore_logs";
  4256. if (function_exists($function)) {
  4257. //Call the function
  4258. $log = $function($restore,$log);
  4259. //If everything is ok, mark the insert flag
  4260. if ($log) {
  4261. $toinsert = true;
  4262. }
  4263. }
  4264. //echo "After transformations<br />"; //Debug
  4265. //print_object($log); //Debug
  4266. //Now if $toinsert is set, insert the record
  4267. if ($toinsert) {
  4268. //echo "Inserting record<br />"; //Debug
  4269. $status = insert_record("log",$log);
  4270. }
  4271. return $status;
  4272. }
  4273. //This function adjusts the instance field into course_modules. It's executed after
  4274. //modules restore. There, we KNOW the new instance id !!
  4275. function restore_check_instances($restore) {
  4276. global $CFG;
  4277. $status = true;
  4278. //We are going to iterate over each course_module saved in backup_ids
  4279. $course_modules = get_records_sql("SELECT old_id,new_id
  4280. FROM {$CFG->prefix}backup_ids
  4281. WHERE backup_code = '$restore->backup_unique_code' AND
  4282. table_name = 'course_modules'");
  4283. if ($course_modules) {
  4284. foreach($course_modules as $cm) {
  4285. //Get full record, using backup_getids
  4286. $cm_module = backup_getid($restore->backup_unique_code,"course_modules",$cm->old_id);
  4287. //Now we are going to the REAL course_modules to get its type (field module)
  4288. $module = get_record("course_modules","id",$cm_module->new_id);
  4289. if ($module) {
  4290. //We know the module type id. Get the name from modules
  4291. $type = get_record("modules","id",$module->module);
  4292. if ($type) {
  4293. //We know the type name and the old_id. Get its new_id
  4294. //from backup_ids. It's the instance !!!
  4295. $instance = backup_getid($restore->backup_unique_code,$type->name,$cm_module->info);
  4296. if ($instance) {
  4297. //We have the new instance, so update the record in course_modules
  4298. $module->instance = $instance->new_id;
  4299. //print_object ($module); //Debug
  4300. $status = update_record("course_modules",$module);
  4301. } else {
  4302. $status = false;
  4303. }
  4304. } else {
  4305. $status = false;
  4306. }
  4307. } else {
  4308. $status = false;
  4309. }
  4310. // MDL-14326 remove empty course modules instance's (credit goes to John T. Macklin from Remote Learner)
  4311. $course_modules_inst_zero = get_records_sql("SELECT id, course, instance
  4312. FROM {$CFG->prefix}course_modules
  4313. WHERE id = '$cm_module->new_id' AND
  4314. instance = '0'");
  4315. if($course_modules_inst_zero){ // Clean up the invalid instances
  4316. foreach($course_modules_inst_zero as $course_modules_inst){
  4317. delete_records('course_modules', 'id',$course_modules_inst->id);
  4318. }
  4319. }
  4320. }
  4321. /// Finally, calculate modinfo cache.
  4322. rebuild_course_cache($restore->course_id);
  4323. }
  4324. return $status;
  4325. }
  4326. //=====================================================================================
  4327. //== ==
  4328. //== XML Functions (SAX) ==
  4329. //== ==
  4330. //=====================================================================================
  4331. /// This is the class used to split, in first instance, the monolithic moodle.xml into
  4332. /// smaller xml files allowing the MoodleParser later to process only the required info
  4333. /// based in each TODO, instead of processing the whole xml for each TODO. In theory
  4334. /// processing time can be reduced upto 1/20th of original time (depending of the
  4335. /// number of TODOs in the original moodle.xml file)
  4336. ///
  4337. /// Anyway, note it's a general splitter parser, and only needs to be instantiated
  4338. /// with the proper destination dir and the tosplit configuration. Be careful when
  4339. /// using it because it doesn't support XML attributes nor real cdata out from tags.
  4340. /// (both not used in the target Moodle backup files)
  4341. class moodle_splitter_parser {
  4342. var $level = 0; /// Level we are
  4343. var $tree = array(); /// Array of levels we are
  4344. var $cdata = ''; /// Raw storage for character data
  4345. var $content = ''; /// Content buffer to be printed to file
  4346. var $trailing= ''; /// Content of the trailing tree for each splited file
  4347. var $savepath = null; /// Path to store splited files
  4348. var $fhandler = null; /// Current file we are writing to
  4349. var $tosplit = array(); /// Array defining the files we want to split, in this format:
  4350. /// array( level/tag/level/tag => filename)
  4351. var $splitwords = array(); /// Denormalised array containing the potential tags
  4352. /// being a split point. To speed up check_split_point()
  4353. var $maxsplitlevel = 0; /// Precalculated max level where any split happens. To speed up check_split_point()
  4354. var $buffersize = 65536; /// 64KB is a good write buffer. Don't expect big benefits by increasing this.
  4355. var $repectformat = false; /// With this setting enabled, the splited files will look like the original one
  4356. /// with all the indentations 100% copied from original (character data outer tags).
  4357. /// But this is a waste of time from our perspective, and splited xml files are completely
  4358. /// functional without that, so we disable this for production, generating a more compact
  4359. /// XML quicker
  4360. /// PHP4 constructor
  4361. function moodle_splitter_parser($savepath, $tosplit = null) {
  4362. return $this->__construct($savepath, $tosplit);
  4363. }
  4364. /// PHP5 constructor
  4365. function __construct($savepath, $tosplit = null) {
  4366. $this->savepath = $savepath;
  4367. if (!empty($tosplit)) {
  4368. $this->tosplit = $tosplit;
  4369. } else { /// No tosplit list passed, process all the possible parts in one moodle.xml file
  4370. $this->tosplit = array(
  4371. '1/MOODLE_BACKUP/2/INFO' => 'split_info.xml',
  4372. '1/MOODLE_BACKUP/2/ROLES' => 'split_roles.xml',
  4373. '2/COURSE/3/HEADER' => 'split_course_header.xml',
  4374. '2/COURSE/3/BLOCKS' => 'split_blocks.xml',
  4375. '2/COURSE/3/SECTIONS' => 'split_sections.xml',
  4376. '2/COURSE/3/FORMATDATA' => 'split_formatdata.xml',
  4377. '2/COURSE/3/METACOURSE' => 'split_metacourse.xml',
  4378. '2/COURSE/3/GRADEBOOK' => 'split_gradebook.xml',
  4379. '2/COURSE/3/USERS' => 'split_users.xml',
  4380. '2/COURSE/3/MESSAGES' => 'split_messages.xml',
  4381. '2/COURSE/3/BLOGS' => 'split_blogs.xml',
  4382. '2/COURSE/3/QUESTION_CATEGORIES'=> 'split_questions.xml',
  4383. '2/COURSE/3/SCALES' => 'split_scales.xml',
  4384. '2/COURSE/3/GROUPS' => 'split_groups.xml',
  4385. '2/COURSE/3/GROUPINGS' => 'split_groupings.xml',
  4386. '2/COURSE/3/GROUPINGSGROUPS' => 'split_groupingsgroups.xml',
  4387. '2/COURSE/3/EVENTS' => 'split_events.xml',
  4388. '2/COURSE/3/MODULES' => 'split_modules.xml',
  4389. '2/COURSE/3/LOGS' => 'split_logs.xml'
  4390. );
  4391. }
  4392. /// Precalculate some info used to speedup checks
  4393. foreach ($this->tosplit as $key=>$value) {
  4394. $this->splitwords[basename($key)] = true;
  4395. if (((int) basename(dirname($key))) > $this->maxsplitlevel) {
  4396. $this->maxsplitlevel = (int) basename(dirname($key));
  4397. }
  4398. }
  4399. }
  4400. /// Given one tag being opened, check if it's one split point.
  4401. /// Return false or split filename
  4402. function check_split_point($tag) {
  4403. /// Quick check. Level < 2 cannot be a split point
  4404. if ($this->level < 2) {
  4405. return false;
  4406. }
  4407. /// Quick check. Current tag against potential splitwords
  4408. if (!isset($this->splitwords[$tag])) {
  4409. return false;
  4410. }
  4411. /// Prev test passed, take a look to 2-level tosplit
  4412. $keytocheck = ($this->level - 1) . '/' . $this->tree[$this->level - 1] . '/' . $this->level . '/' . $this->tree[$this->level];
  4413. if (!isset($this->tosplit[$keytocheck])) {
  4414. return false;
  4415. }
  4416. /// Prev test passed, we are in a split point, return new filename
  4417. return $this->tosplit[$keytocheck];
  4418. }
  4419. /// To append data (xml-escaped) to contents buffer
  4420. function character_data($parser, $data) {
  4421. ///$this->content .= preg_replace($this->entity_find, $this->entity_replace, $data); ///40% slower
  4422. ///$this->content .= str_replace($this->entity_find, $this->entity_replace, $data); ///25% slower
  4423. ///$this->content .= htmlspecialchars($data); ///the best
  4424. /// Instead of htmlspecialchars() each chunk of character data, we are going to
  4425. /// concat it without transformation and will apply the htmlspecialchars() when
  4426. /// that character data is, efectively, going to be added to contents buffer. This
  4427. /// makes the number of transformations to be reduced (speedup) and avoid potential
  4428. /// problems with transformations being applied "in the middle" of multibyte chars.
  4429. $this->cdata .= $data;
  4430. }
  4431. /// To detect start of tags, keeping level, tree and fhandle updated.
  4432. /// Also handles creation of split files
  4433. function start_tag($parser, $tag, $attrs) {
  4434. /// Update things before processing
  4435. $this->level++;
  4436. $this->tree[$this->level] = $tag;
  4437. /// Check if we need to start a new split file,
  4438. /// Speedup: we only do that if we haven't a fhandler and if level <= $maxsplitlevel
  4439. if ($this->level <= $this->maxsplitlevel && !$this->fhandler && $newfilename = $this->check_split_point($tag)) {
  4440. /// Open new file handler, init everything
  4441. $this->fhandler = fopen($this->savepath . '/' . $newfilename, 'w');
  4442. $this->content = '';
  4443. $this->cdata = '';
  4444. $this->trailing = '';
  4445. /// Build the original leading tree (and calculate the original trailing one)
  4446. for ($l = 1; $l < $this->level; $l++) {
  4447. $this->content .= "<{$this->tree[$l]}>\n";
  4448. $this->trailing = "\n</{$this->tree[$l]}>" . $this->trailing;
  4449. }
  4450. }
  4451. /// Perform xml-entities transformation and add to contents buffer together with opening tag.
  4452. /// Speedup. We lose nice formatting of the split XML but avoid 50% of transformations and XML is 100% equivalent
  4453. $this->content .= ($this->repectformat ? htmlspecialchars($this->cdata) : '') . "<$tag>";
  4454. $this->cdata = '';
  4455. }
  4456. /// To detect end of tags, keeping level, tree and fhandle updated, writting contents buffer to split file.
  4457. /// Also handles closing of split files
  4458. function end_tag($parser, $tag) {
  4459. /// Perform xml-entities transformation and add to contents buffer together with closing tag, repecting (or no) format
  4460. $this->content .= ($this->repectformat ? htmlspecialchars($this->cdata) : htmlspecialchars(trim($this->cdata))) . "</$tag>";
  4461. $this->cdata = '';
  4462. /// Check if we need to close current split file
  4463. /// Speedup: we only do that if we have a fhandler and if level <= $maxsplitlevel
  4464. if ($this->level <= $this->maxsplitlevel && $this->fhandler && $newfilename = $this->check_split_point($tag)) {
  4465. /// Write pending contents buffer before closing. It's a must
  4466. fwrite($this->fhandler, $this->content);
  4467. $this->content = "";
  4468. /// Write the original trailing tree for fhandler
  4469. fwrite($this->fhandler, $this->trailing);
  4470. fclose($this->fhandler);
  4471. $this->fhandler = null;
  4472. } else {
  4473. /// Normal write of contents (use one buffer to improve speed)
  4474. if ($this->fhandler && strlen($this->content) > $this->buffersize) {
  4475. fwrite($this->fhandler, $this->content);
  4476. $this->content = "";
  4477. }
  4478. }
  4479. /// Update things after processing
  4480. $this->tree[$this->level] = "";
  4481. $this->level--;
  4482. }
  4483. }
  4484. /// This function executes the moodle_splitter_parser, causing the monolithic moodle.xml
  4485. /// file to be splitted in n smaller files for better treatament by the MoodleParser in restore_read_xml()
  4486. function restore_split_xml ($xml_file, $preferences) {
  4487. $status = true;
  4488. $xml_parser = xml_parser_create('UTF-8');
  4489. $split_parser = new moodle_splitter_parser(dirname($xml_file));
  4490. xml_set_object($xml_parser,$split_parser);
  4491. xml_set_element_handler($xml_parser, 'start_tag', 'end_tag');
  4492. xml_set_character_data_handler($xml_parser, 'character_data');
  4493. $doteach = filesize($xml_file) / 20;
  4494. $fromdot = 0;
  4495. $fp = fopen($xml_file,"r")
  4496. or $status = false;
  4497. if ($status) {
  4498. $lasttime = time();
  4499. while ($data = fread($fp, 8192)) {
  4500. if (!defined('RESTORE_SILENTLY')) {
  4501. $fromdot += 8192;
  4502. if ($fromdot > $doteach) {
  4503. echo ".";
  4504. backup_flush(300);
  4505. $fromdot = 0;
  4506. }
  4507. if ((time() - $lasttime) > 10) {
  4508. $lasttime = time();
  4509. backup_flush(300);
  4510. }
  4511. }
  4512. xml_parse($xml_parser, $data, feof($fp))
  4513. or die(sprintf("XML error: %s at line %d",
  4514. xml_error_string(xml_get_error_code($xml_parser)),
  4515. xml_get_current_line_number($xml_parser)));
  4516. }
  4517. fclose($fp);
  4518. }
  4519. xml_parser_free($xml_parser);
  4520. return $status;
  4521. }
  4522. //This is the class used to do all the xml parse
  4523. class MoodleParser {
  4524. var $level = 0; //Level we are
  4525. var $counter = 0; //Counter
  4526. var $tree = array(); //Array of levels we are
  4527. var $content = ""; //Content under current level
  4528. var $todo = ""; //What we hav to do when parsing
  4529. var $info = ""; //Information collected. Temp storage. Used to return data after parsing.
  4530. var $temp = ""; //Temp storage.
  4531. var $preferences = ""; //Preferences about what to load !!
  4532. var $finished = false; //Flag to say xml_parse to stop
  4533. //This function is used to get the current contents property value
  4534. //They are trimed (and converted from utf8 if needed)
  4535. function getContents() {
  4536. return trim($this->content);
  4537. }
  4538. //This is the startTag handler we use where we are reading the info zone (todo="INFO")
  4539. function startElementInfo($parser, $tagName, $attrs) {
  4540. //Refresh properties
  4541. $this->level++;
  4542. $this->tree[$this->level] = $tagName;
  4543. //Output something to avoid browser timeouts...
  4544. //backup_flush();
  4545. //Check if we are into INFO zone
  4546. //if ($this->tree[2] == "INFO") //Debug
  4547. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4548. }
  4549. //This is the startTag handler we use where we are reading the info zone (todo="INFO")
  4550. function startElementRoles($parser, $tagName, $attrs) {
  4551. //Refresh properties
  4552. $this->level++;
  4553. $this->tree[$this->level] = $tagName;
  4554. //Output something to avoid browser timeouts...
  4555. //backup_flush();
  4556. //Check if we are into INFO zone
  4557. //if ($this->tree[2] == "INFO") //Debug
  4558. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4559. }
  4560. //This is the startTag handler we use where we are reading the course header zone (todo="COURSE_HEADER")
  4561. function startElementCourseHeader($parser, $tagName, $attrs) {
  4562. //Refresh properties
  4563. $this->level++;
  4564. $this->tree[$this->level] = $tagName;
  4565. //Output something to avoid browser timeouts...
  4566. //backup_flush();
  4567. //Check if we are into COURSE_HEADER zone
  4568. //if ($this->tree[3] == "HEADER") //Debug
  4569. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4570. }
  4571. //This is the startTag handler we use where we are reading the blocks zone (todo="BLOCKS")
  4572. function startElementBlocks($parser, $tagName, $attrs) {
  4573. //Refresh properties
  4574. $this->level++;
  4575. $this->tree[$this->level] = $tagName;
  4576. //Output something to avoid browser timeouts...
  4577. //backup_flush();
  4578. //Check if we are into BLOCKS zone
  4579. //if ($this->tree[3] == "BLOCKS") //Debug
  4580. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4581. //If we are under a BLOCK tag under a BLOCKS zone, accumule it
  4582. if (isset($this->tree[4]) and isset($this->tree[3])) { //
  4583. if ($this->tree[4] == "BLOCK" and $this->tree[3] == "BLOCKS") {
  4584. if (!isset($this->temp)) {
  4585. $this->temp = "";
  4586. }
  4587. $this->temp .= "<".$tagName.">";
  4588. }
  4589. }
  4590. }
  4591. //This is the startTag handler we use where we are reading the sections zone (todo="SECTIONS")
  4592. function startElementSections($parser, $tagName, $attrs) {
  4593. //Refresh properties
  4594. $this->level++;
  4595. $this->tree[$this->level] = $tagName;
  4596. //Output something to avoid browser timeouts...
  4597. //backup_flush();
  4598. //Check if we are into SECTIONS zone
  4599. //if ($this->tree[3] == "SECTIONS") //Debug
  4600. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4601. }
  4602. //This is the startTag handler we use where we are reading the optional format data zone (todo="FORMATDATA")
  4603. function startElementFormatData($parser, $tagName, $attrs) {
  4604. //Refresh properties
  4605. $this->level++;
  4606. $this->tree[$this->level] = $tagName;
  4607. //Output something to avoid browser timeouts...
  4608. //backup_flush();
  4609. //Accumulate all the data inside this tag
  4610. if (isset($this->tree[3]) && $this->tree[3] == "FORMATDATA") {
  4611. if (!isset($this->temp)) {
  4612. $this->temp = '';
  4613. }
  4614. $this->temp .= "<".$tagName.">";
  4615. }
  4616. //Check if we are into FORMATDATA zone
  4617. //if ($this->tree[3] == "FORMATDATA") //Debug
  4618. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4619. }
  4620. //This is the startTag handler we use where we are reading the metacourse zone (todo="METACOURSE")
  4621. function startElementMetacourse($parser, $tagName, $attrs) {
  4622. //Refresh properties
  4623. $this->level++;
  4624. $this->tree[$this->level] = $tagName;
  4625. //Output something to avoid browser timeouts...
  4626. //backup_flush();
  4627. //Check if we are into METACOURSE zone
  4628. //if ($this->tree[3] == "METACOURSE") //Debug
  4629. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4630. }
  4631. //This is the startTag handler we use where we are reading the gradebook zone (todo="GRADEBOOK")
  4632. function startElementGradebook($parser, $tagName, $attrs) {
  4633. //Refresh properties
  4634. $this->level++;
  4635. $this->tree[$this->level] = $tagName;
  4636. //Output something to avoid browser timeouts...
  4637. //backup_flush();
  4638. //Check if we are into GRADEBOOK zone
  4639. //if ($this->tree[3] == "GRADEBOOK") //Debug
  4640. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4641. //If we are under a GRADE_PREFERENCE, GRADE_LETTER or GRADE_CATEGORY tag under a GRADEBOOK zone, accumule it
  4642. if (isset($this->tree[5]) and isset($this->tree[3])) {
  4643. if (($this->tree[5] == "GRADE_ITEM" || $this->tree[5] == "GRADE_CATEGORY" || $this->tree[5] == "GRADE_LETTER" || $this->tree[5] == "GRADE_OUTCOME" || $this->tree[5] == "GRADE_OUTCOMES_COURSE" || $this->tree[5] == "GRADE_CATEGORIES_HISTORY" || $this->tree[5] == "GRADE_GRADES_HISTORY" || $this->tree[5] == "GRADE_TEXT_HISTORY" || $this->tree[5] == "GRADE_ITEM_HISTORY" || $this->tree[5] == "GRADE_OUTCOME_HISTORY") && ($this->tree[3] == "GRADEBOOK")) {
  4644. if (!isset($this->temp)) {
  4645. $this->temp = "";
  4646. }
  4647. $this->temp .= "<".$tagName.">";
  4648. }
  4649. }
  4650. }
  4651. //This is the startTag handler we use where we are reading the gradebook zone (todo="GRADEBOOK")
  4652. function startElementOldGradebook($parser, $tagName, $attrs) {
  4653. //Refresh properties
  4654. $this->level++;
  4655. $this->tree[$this->level] = $tagName;
  4656. //Output something to avoid browser timeouts...
  4657. //backup_flush();
  4658. //Check if we are into GRADEBOOK zone
  4659. //if ($this->tree[3] == "GRADEBOOK") //Debug
  4660. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4661. //If we are under a GRADE_PREFERENCE, GRADE_LETTER or GRADE_CATEGORY tag under a GRADEBOOK zone, accumule it
  4662. if (isset($this->tree[5]) and isset($this->tree[3])) {
  4663. if (($this->tree[5] == "GRADE_PREFERENCE" || $this->tree[5] == "GRADE_LETTER" || $this->tree[5] == "GRADE_CATEGORY" ) && ($this->tree[3] == "GRADEBOOK")) {
  4664. if (!isset($this->temp)) {
  4665. $this->temp = "";
  4666. }
  4667. $this->temp .= "<".$tagName.">";
  4668. }
  4669. }
  4670. }
  4671. //This is the startTag handler we use where we are reading the user zone (todo="USERS")
  4672. function startElementUsers($parser, $tagName, $attrs) {
  4673. //Refresh properties
  4674. $this->level++;
  4675. $this->tree[$this->level] = $tagName;
  4676. //Check if we are into USERS zone
  4677. //if ($this->tree[3] == "USERS") //Debug
  4678. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4679. }
  4680. //This is the startTag handler we use where we are reading the messages zone (todo="MESSAGES")
  4681. function startElementMessages($parser, $tagName, $attrs) {
  4682. //Refresh properties
  4683. $this->level++;
  4684. $this->tree[$this->level] = $tagName;
  4685. //Output something to avoid browser timeouts...
  4686. //backup_flush();
  4687. //Check if we are into MESSAGES zone
  4688. //if ($this->tree[3] == "MESSAGES") //Debug
  4689. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4690. //If we are under a MESSAGE tag under a MESSAGES zone, accumule it
  4691. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4692. if (($this->tree[4] == "MESSAGE" || (isset($this->tree[5]) && $this->tree[5] == "CONTACT" )) and ($this->tree[3] == "MESSAGES")) {
  4693. if (!isset($this->temp)) {
  4694. $this->temp = "";
  4695. }
  4696. $this->temp .= "<".$tagName.">";
  4697. }
  4698. }
  4699. }
  4700. //This is the startTag handler we use where we are reading the blogs zone (todo="BLOGS")
  4701. function startElementBlogs($parser, $tagName, $attrs) {
  4702. //Refresh properties
  4703. $this->level++;
  4704. $this->tree[$this->level] = $tagName;
  4705. //Output something to avoid browser timeouts...
  4706. //backup_flush();
  4707. //Check if we are into BLOGS zone
  4708. //if ($this->tree[3] == "BLOGS") //Debug
  4709. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4710. //If we are under a BLOG tag under a BLOGS zone, accumule it
  4711. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4712. if ($this->tree[4] == "BLOG" and $this->tree[3] == "BLOGS") {
  4713. if (!isset($this->temp)) {
  4714. $this->temp = "";
  4715. }
  4716. $this->temp .= "<".$tagName.">";
  4717. }
  4718. }
  4719. }
  4720. //This is the startTag handler we use where we are reading the questions zone (todo="QUESTIONS")
  4721. function startElementQuestions($parser, $tagName, $attrs) {
  4722. //Refresh properties
  4723. $this->level++;
  4724. $this->tree[$this->level] = $tagName;
  4725. //if ($tagName == "QUESTION_CATEGORY" && $this->tree[3] == "QUESTION_CATEGORIES") { //Debug
  4726. // echo "<P>QUESTION_CATEGORY: ".strftime ("%X",time()),"-"; //Debug
  4727. //} //Debug
  4728. //Output something to avoid browser timeouts...
  4729. //backup_flush();
  4730. //Check if we are into QUESTION_CATEGORIES zone
  4731. //if ($this->tree[3] == "QUESTION_CATEGORIES") //Debug
  4732. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4733. //If we are under a QUESTION_CATEGORY tag under a QUESTION_CATEGORIES zone, accumule it
  4734. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4735. if (($this->tree[4] == "QUESTION_CATEGORY") and ($this->tree[3] == "QUESTION_CATEGORIES")) {
  4736. if (!isset($this->temp)) {
  4737. $this->temp = "";
  4738. }
  4739. $this->temp .= "<".$tagName.">";
  4740. }
  4741. }
  4742. }
  4743. //This is the startTag handler we use where we are reading the scales zone (todo="SCALES")
  4744. function startElementScales($parser, $tagName, $attrs) {
  4745. //Refresh properties
  4746. $this->level++;
  4747. $this->tree[$this->level] = $tagName;
  4748. //if ($tagName == "SCALE" && $this->tree[3] == "SCALES") { //Debug
  4749. // echo "<P>SCALE: ".strftime ("%X",time()),"-"; //Debug
  4750. //} //Debug
  4751. //Output something to avoid browser timeouts...
  4752. //backup_flush();
  4753. //Check if we are into SCALES zone
  4754. //if ($this->tree[3] == "SCALES") //Debug
  4755. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4756. //If we are under a SCALE tag under a SCALES zone, accumule it
  4757. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4758. if (($this->tree[4] == "SCALE") and ($this->tree[3] == "SCALES")) {
  4759. if (!isset($this->temp)) {
  4760. $this->temp = "";
  4761. }
  4762. $this->temp .= "<".$tagName.">";
  4763. }
  4764. }
  4765. }
  4766. function startElementGroups($parser, $tagName, $attrs) {
  4767. //Refresh properties
  4768. $this->level++;
  4769. $this->tree[$this->level] = $tagName;
  4770. //if ($tagName == "GROUP" && $this->tree[3] == "GROUPS") { //Debug
  4771. // echo "<P>GROUP: ".strftime ("%X",time()),"-"; //Debug
  4772. //} //Debug
  4773. //Output something to avoid browser timeouts...
  4774. //backup_flush();
  4775. //Check if we are into GROUPS zone
  4776. //if ($this->tree[3] == "GROUPS") //Debug
  4777. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4778. //If we are under a GROUP tag under a GROUPS zone, accumule it
  4779. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4780. if (($this->tree[4] == "GROUP") and ($this->tree[3] == "GROUPS")) {
  4781. if (!isset($this->temp)) {
  4782. $this->temp = "";
  4783. }
  4784. $this->temp .= "<".$tagName.">";
  4785. }
  4786. }
  4787. }
  4788. function startElementGroupings($parser, $tagName, $attrs) {
  4789. //Refresh properties
  4790. $this->level++;
  4791. $this->tree[$this->level] = $tagName;
  4792. //if ($tagName == "GROUPING" && $this->tree[3] == "GROUPINGS") { //Debug
  4793. // echo "<P>GROUPING: ".strftime ("%X",time()),"-"; //Debug
  4794. //} //Debug
  4795. //Output something to avoid browser timeouts...
  4796. //backup_flush();
  4797. //Check if we are into GROUPINGS zone
  4798. //if ($this->tree[3] == "GROUPINGS") //Debug
  4799. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4800. //If we are under a GROUPING tag under a GROUPINGS zone, accumule it
  4801. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4802. if (($this->tree[4] == "GROUPING") and ($this->tree[3] == "GROUPINGS")) {
  4803. if (!isset($this->temp)) {
  4804. $this->temp = "";
  4805. }
  4806. $this->temp .= "<".$tagName.">";
  4807. }
  4808. }
  4809. }
  4810. function startElementGroupingsGroups($parser, $tagName, $attrs) {
  4811. //Refresh properties
  4812. $this->level++;
  4813. $this->tree[$this->level] = $tagName;
  4814. //if ($tagName == "GROUPINGGROUP" && $this->tree[3] == "GROUPINGSGROUPS") { //Debug
  4815. // echo "<P>GROUPINGSGROUP: ".strftime ("%X",time()),"-"; //Debug
  4816. //} //Debug
  4817. //Output something to avoid browser timeouts...
  4818. backup_flush();
  4819. //Check if we are into GROUPINGSGROUPS zone
  4820. //if ($this->tree[3] == "GROUPINGSGROUPS") //Debug
  4821. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4822. //If we are under a GROUPINGGROUP tag under a GROUPINGSGROUPS zone, accumule it
  4823. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4824. if (($this->tree[4] == "GROUPINGGROUP") and ($this->tree[3] == "GROUPINGSGROUPS")) {
  4825. if (!isset($this->temp)) {
  4826. $this->temp = "";
  4827. }
  4828. $this->temp .= "<".$tagName.">";
  4829. }
  4830. }
  4831. }
  4832. //This is the startTag handler we use where we are reading the events zone (todo="EVENTS")
  4833. function startElementEvents($parser, $tagName, $attrs) {
  4834. //Refresh properties
  4835. $this->level++;
  4836. $this->tree[$this->level] = $tagName;
  4837. //if ($tagName == "EVENT" && $this->tree[3] == "EVENTS") { //Debug
  4838. // echo "<P>EVENT: ".strftime ("%X",time()),"-"; //Debug
  4839. //} //Debug
  4840. //Output something to avoid browser timeouts...
  4841. //backup_flush();
  4842. //Check if we are into EVENTS zone
  4843. //if ($this->tree[3] == "EVENTS") //Debug
  4844. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4845. //If we are under a EVENT tag under a EVENTS zone, accumule it
  4846. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4847. if (($this->tree[4] == "EVENT") and ($this->tree[3] == "EVENTS")) {
  4848. if (!isset($this->temp)) {
  4849. $this->temp = "";
  4850. }
  4851. $this->temp .= "<".$tagName.">";
  4852. }
  4853. }
  4854. }
  4855. //This is the startTag handler we use where we are reading the modules zone (todo="MODULES")
  4856. function startElementModules($parser, $tagName, $attrs) {
  4857. //Refresh properties
  4858. $this->level++;
  4859. $this->tree[$this->level] = $tagName;
  4860. //if ($tagName == "MOD" && $this->tree[3] == "MODULES") { //Debug
  4861. // echo "<P>MOD: ".strftime ("%X",time()),"-"; //Debug
  4862. //} //Debug
  4863. //Output something to avoid browser timeouts...
  4864. //backup_flush();
  4865. //Check if we are into MODULES zone
  4866. //if ($this->tree[3] == "MODULES") //Debug
  4867. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4868. //If we are under a MOD tag under a MODULES zone, accumule it
  4869. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4870. if (($this->tree[4] == "MOD") and ($this->tree[3] == "MODULES")) {
  4871. if (!isset($this->temp)) {
  4872. $this->temp = "";
  4873. }
  4874. $this->temp .= "<".$tagName.">";
  4875. }
  4876. }
  4877. }
  4878. //This is the startTag handler we use where we are reading the logs zone (todo="LOGS")
  4879. function startElementLogs($parser, $tagName, $attrs) {
  4880. //Refresh properties
  4881. $this->level++;
  4882. $this->tree[$this->level] = $tagName;
  4883. //if ($tagName == "LOG" && $this->tree[3] == "LOGS") { //Debug
  4884. // echo "<P>LOG: ".strftime ("%X",time()),"-"; //Debug
  4885. //} //Debug
  4886. //Output something to avoid browser timeouts...
  4887. //backup_flush();
  4888. //Check if we are into LOGS zone
  4889. //if ($this->tree[3] == "LOGS") //Debug
  4890. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4891. //If we are under a LOG tag under a LOGS zone, accumule it
  4892. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4893. if (($this->tree[4] == "LOG") and ($this->tree[3] == "LOGS")) {
  4894. if (!isset($this->temp)) {
  4895. $this->temp = "";
  4896. }
  4897. $this->temp .= "<".$tagName.">";
  4898. }
  4899. }
  4900. }
  4901. //This is the startTag default handler we use when todo is undefined
  4902. function startElement($parser, $tagName, $attrs) {
  4903. $this->level++;
  4904. $this->tree[$this->level] = $tagName;
  4905. //Output something to avoid browser timeouts...
  4906. //backup_flush();
  4907. echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4908. }
  4909. //This is the endTag handler we use where we are reading the info zone (todo="INFO")
  4910. function endElementInfo($parser, $tagName) {
  4911. //Check if we are into INFO zone
  4912. if ($this->tree[2] == "INFO") {
  4913. //if (trim($this->content)) //Debug
  4914. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  4915. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  4916. //Dependig of different combinations, do different things
  4917. if ($this->level == 3) {
  4918. switch ($tagName) {
  4919. case "NAME":
  4920. $this->info->backup_name = $this->getContents();
  4921. break;
  4922. case "MOODLE_VERSION":
  4923. $this->info->backup_moodle_version = $this->getContents();
  4924. break;
  4925. case "MOODLE_RELEASE":
  4926. $this->info->backup_moodle_release = $this->getContents();
  4927. break;
  4928. case "BACKUP_VERSION":
  4929. $this->info->backup_backup_version = $this->getContents();
  4930. break;
  4931. case "BACKUP_RELEASE":
  4932. $this->info->backup_backup_release = $this->getContents();
  4933. break;
  4934. case "DATE":
  4935. $this->info->backup_date = $this->getContents();
  4936. break;
  4937. case "ORIGINAL_WWWROOT":
  4938. $this->info->original_wwwroot = $this->getContents();
  4939. break;
  4940. case "ORIGINAL_SITE_IDENTIFIER_HASH":
  4941. $this->info->original_siteidentifier = $this->getContents();
  4942. break;
  4943. case "MNET_REMOTEUSERS":
  4944. $this->info->mnet_remoteusers = $this->getContents();
  4945. break;
  4946. }
  4947. }
  4948. if ($this->tree[3] == "DETAILS") {
  4949. if ($this->level == 4) {
  4950. switch ($tagName) {
  4951. case "METACOURSE":
  4952. $this->info->backup_metacourse = $this->getContents();
  4953. break;
  4954. case "USERS":
  4955. $this->info->backup_users = $this->getContents();
  4956. break;
  4957. case "LOGS":
  4958. $this->info->backup_logs = $this->getContents();
  4959. break;
  4960. case "USERFILES":
  4961. $this->info->backup_user_files = $this->getContents();
  4962. break;
  4963. case "COURSEFILES":
  4964. $this->info->backup_course_files = $this->getContents();
  4965. break;
  4966. case "SITEFILES":
  4967. $this->info->backup_site_files = $this->getContents();
  4968. break;
  4969. case "GRADEBOOKHISTORIES":
  4970. $this->info->gradebook_histories = $this->getContents();
  4971. break;
  4972. case "MESSAGES":
  4973. $this->info->backup_messages = $this->getContents();
  4974. break;
  4975. case "BLOGS":
  4976. $this->info->backup_blogs = $this->getContents();
  4977. break;
  4978. case 'BLOCKFORMAT':
  4979. $this->info->backup_block_format = $this->getContents();
  4980. break;
  4981. }
  4982. }
  4983. if ($this->level == 5) {
  4984. switch ($tagName) {
  4985. case "NAME":
  4986. $this->info->tempName = $this->getContents();
  4987. break;
  4988. case "INCLUDED":
  4989. $this->info->mods[$this->info->tempName]->backup = $this->getContents();
  4990. break;
  4991. case "USERINFO":
  4992. $this->info->mods[$this->info->tempName]->userinfo = $this->getContents();
  4993. break;
  4994. }
  4995. }
  4996. if ($this->level == 7) {
  4997. switch ($tagName) {
  4998. case "ID":
  4999. $this->info->tempId = $this->getContents();
  5000. $this->info->mods[$this->info->tempName]->instances[$this->info->tempId]->id = $this->info->tempId;
  5001. break;
  5002. case "NAME":
  5003. $this->info->mods[$this->info->tempName]->instances[$this->info->tempId]->name = $this->getContents();
  5004. break;
  5005. case "INCLUDED":
  5006. $this->info->mods[$this->info->tempName]->instances[$this->info->tempId]->backup = $this->getContents();
  5007. break;
  5008. case "USERINFO":
  5009. $this->info->mods[$this->info->tempName]->instances[$this->info->tempId]->userinfo = $this->getContents();
  5010. break;
  5011. }
  5012. }
  5013. }
  5014. }
  5015. //Stop parsing if todo = INFO and tagName = INFO (en of the tag, of course)
  5016. //Speed up a lot (avoid parse all)
  5017. if ($tagName == "INFO") {
  5018. $this->finished = true;
  5019. }
  5020. //Clear things
  5021. $this->tree[$this->level] = "";
  5022. $this->level--;
  5023. $this->content = "";
  5024. }
  5025. function endElementRoles($parser, $tagName) {
  5026. //Check if we are into ROLES zone
  5027. if ($this->tree[2] == "ROLES") {
  5028. if ($this->tree[3] == "ROLE") {
  5029. if ($this->level == 4) {
  5030. switch ($tagName) {
  5031. case "ID": // this is the old id
  5032. $this->info->tempid = $this->getContents();
  5033. $this->info->roles[$this->info->tempid]->id = $this->info->tempid;
  5034. break;
  5035. case "NAME":
  5036. $this->info->roles[$this->info->tempid]->name = $this->getContents();;
  5037. break;
  5038. case "SHORTNAME":
  5039. $this->info->roles[$this->info->tempid]->shortname = $this->getContents();;
  5040. break;
  5041. case "NAMEINCOURSE": // custom name of the role in course
  5042. $this->info->roles[$this->info->tempid]->nameincourse = $this->getContents();;
  5043. break;
  5044. }
  5045. }
  5046. if ($this->level == 6) {
  5047. switch ($tagName) {
  5048. case "NAME":
  5049. $this->info->tempcapname = $this->getContents();
  5050. $this->info->roles[$this->info->tempid]->capabilities[$this->info->tempcapname]->name = $this->getContents();
  5051. break;
  5052. case "PERMISSION":
  5053. $this->info->roles[$this->info->tempid]->capabilities[$this->info->tempcapname]->permission = $this->getContents();
  5054. break;
  5055. case "TIMEMODIFIED":
  5056. $this->info->roles[$this->info->tempid]->capabilities[$this->info->tempcapname]->timemodified = $this->getContents();
  5057. break;
  5058. case "MODIFIERID":
  5059. $this->info->roles[$this->info->tempid]->capabilities[$this->info->tempcapname]->modifierid = $this->getContents();
  5060. break;
  5061. }
  5062. }
  5063. }
  5064. }
  5065. //Stop parsing if todo = ROLES and tagName = ROLES (en of the tag, of course)
  5066. //Speed up a lot (avoid parse all)
  5067. if ($tagName == "ROLES") {
  5068. $this->finished = true;
  5069. }
  5070. //Clear things
  5071. $this->tree[$this->level] = "";
  5072. $this->level--;
  5073. $this->content = "";
  5074. }
  5075. //This is the endTag handler we use where we are reading the course_header zone (todo="COURSE_HEADER")
  5076. function endElementCourseHeader($parser, $tagName) {
  5077. //Check if we are into COURSE_HEADER zone
  5078. if ($this->tree[3] == "HEADER") {
  5079. //if (trim($this->content)) //Debug
  5080. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  5081. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  5082. //Dependig of different combinations, do different things
  5083. if ($this->level == 4) {
  5084. switch ($tagName) {
  5085. case "ID":
  5086. $this->info->course_id = $this->getContents();
  5087. break;
  5088. case "PASSWORD":
  5089. $this->info->course_password = $this->getContents();
  5090. break;
  5091. case "FULLNAME":
  5092. $this->info->course_fullname = $this->getContents();
  5093. break;
  5094. case "SHORTNAME":
  5095. $this->info->course_shortname = $this->getContents();
  5096. break;
  5097. case "IDNUMBER":
  5098. $this->info->course_idnumber = $this->getContents();
  5099. break;
  5100. case "SUMMARY":
  5101. $this->info->course_summary = $this->getContents();
  5102. break;
  5103. case "FORMAT":
  5104. $this->info->course_format = $this->getContents();
  5105. break;
  5106. case "SHOWGRADES":
  5107. $this->info->course_showgrades = $this->getContents();
  5108. break;
  5109. case "BLOCKINFO":
  5110. $this->info->blockinfo = $this->getContents();
  5111. break;
  5112. case "NEWSITEMS":
  5113. $this->info->course_newsitems = $this->getContents();
  5114. break;
  5115. case "TEACHER":
  5116. $this->info->course_teacher = $this->getContents();
  5117. break;
  5118. case "TEACHERS":
  5119. $this->info->course_teachers = $this->getContents();
  5120. break;
  5121. case "STUDENT":
  5122. $this->info->course_student = $this->getContents();
  5123. break;
  5124. case "STUDENTS":
  5125. $this->info->course_students = $this->getContents();
  5126. break;
  5127. case "GUEST":
  5128. $this->info->course_guest = $this->getContents();
  5129. break;
  5130. case "STARTDATE":
  5131. $this->info->course_startdate = $this->getContents();
  5132. break;
  5133. case "NUMSECTIONS":
  5134. $this->info->course_numsections = $this->getContents();
  5135. break;
  5136. //case "SHOWRECENT": INFO: This is out in 1.3
  5137. // $this->info->course_showrecent = $this->getContents();
  5138. // break;
  5139. case "MAXBYTES":
  5140. $this->info->course_maxbytes = $this->getContents();
  5141. break;
  5142. case "SHOWREPORTS":
  5143. $this->info->course_showreports = $this->getContents();
  5144. break;
  5145. case "GROUPMODE":
  5146. $this->info->course_groupmode = $this->getContents();
  5147. break;
  5148. case "GROUPMODEFORCE":
  5149. $this->info->course_groupmodeforce = $this->getContents();
  5150. break;
  5151. case "DEFAULTGROUPINGID":
  5152. $this->info->course_defaultgroupingid = $this->getContents();
  5153. break;
  5154. case "LANG":
  5155. $this->info->course_lang = $this->getContents();
  5156. break;
  5157. case "THEME":
  5158. $this->info->course_theme = $this->getContents();
  5159. break;
  5160. case "COST":
  5161. $this->info->course_cost = $this->getContents();
  5162. break;
  5163. case "CURRENCY":
  5164. $this->info->course_currency = $this->getContents();
  5165. break;
  5166. case "MARKER":
  5167. $this->info->course_marker = $this->getContents();
  5168. break;
  5169. case "VISIBLE":
  5170. $this->info->course_visible = $this->getContents();
  5171. break;
  5172. case "HIDDENSECTIONS":
  5173. $this->info->course_hiddensections = $this->getContents();
  5174. break;
  5175. case "TIMECREATED":
  5176. $this->info->course_timecreated = $this->getContents();
  5177. break;
  5178. case "TIMEMODIFIED":
  5179. $this->info->course_timemodified = $this->getContents();
  5180. break;
  5181. case "METACOURSE":
  5182. $this->info->course_metacourse = $this->getContents();
  5183. break;
  5184. case "EXPIRENOTIFY":
  5185. $this->info->course_expirynotify = $this->getContents();
  5186. break;
  5187. case "NOTIFYSTUDENTS":
  5188. $this->info->course_notifystudents = $this->getContents();
  5189. break;
  5190. case "EXPIRYTHRESHOLD":
  5191. $this->info->course_expirythreshold = $this->getContents();
  5192. break;
  5193. case "ENROLLABLE":
  5194. $this->info->course_enrollable = $this->getContents();
  5195. break;
  5196. case "ENROLSTARTDATE":
  5197. $this->info->course_enrolstartdate = $this->getContents();
  5198. break;
  5199. case "ENROLENDDATE":
  5200. $this->info->course_enrolenddate = $this->getContents();
  5201. break;
  5202. case "ENROLPERIOD":
  5203. $this->info->course_enrolperiod = $this->getContents();
  5204. break;
  5205. }
  5206. }
  5207. if ($this->tree[4] == "CATEGORY") {
  5208. if ($this->level == 5) {
  5209. switch ($tagName) {
  5210. case "ID":
  5211. $this->info->category->id = $this->getContents();
  5212. break;
  5213. case "NAME":
  5214. $this->info->category->name = $this->getContents();
  5215. break;
  5216. }
  5217. }
  5218. }
  5219. if ($this->tree[4] == "ROLES_ASSIGNMENTS") {
  5220. if ($this->level == 6) {
  5221. switch ($tagName) {
  5222. case "NAME":
  5223. $this->info->tempname = $this->getContents();
  5224. break;
  5225. case "SHORTNAME":
  5226. $this->info->tempshortname = $this->getContents();
  5227. break;
  5228. case "ID":
  5229. $this->info->tempid = $this->getContents();
  5230. break;
  5231. }
  5232. }
  5233. if ($this->level == 8) {
  5234. switch ($tagName) {
  5235. case "USERID":
  5236. $this->info->roleassignments[$this->info->tempid]->name = $this->info->tempname;
  5237. $this->info->roleassignments[$this->info->tempid]->shortname = $this->info->tempshortname;
  5238. $this->info->tempuser = $this->getContents();
  5239. $this->info->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->userid = $this->getContents();
  5240. break;
  5241. case "HIDDEN":
  5242. $this->info->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->hidden = $this->getContents();
  5243. break;
  5244. case "TIMESTART":
  5245. $this->info->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timestart = $this->getContents();
  5246. break;
  5247. case "TIMEEND":
  5248. $this->info->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timeend = $this->getContents();
  5249. break;
  5250. case "TIMEMODIFIED":
  5251. $this->info->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timemodified = $this->getContents();
  5252. break;
  5253. case "MODIFIERID":
  5254. $this->info->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->modifierid = $this->getContents();
  5255. break;
  5256. case "ENROL":
  5257. $this->info->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->enrol = $this->getContents();
  5258. break;
  5259. case "SORTORDER":
  5260. $this->info->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->sortorder = $this->getContents();
  5261. break;
  5262. }
  5263. }
  5264. } /// ends role_assignments
  5265. if ($this->tree[4] == "ROLES_OVERRIDES") {
  5266. if ($this->level == 6) {
  5267. switch ($tagName) {
  5268. case "NAME":
  5269. $this->info->tempname = $this->getContents();
  5270. break;
  5271. case "SHORTNAME":
  5272. $this->info->tempshortname = $this->getContents();
  5273. break;
  5274. case "ID":
  5275. $this->info->tempid = $this->getContents();
  5276. break;
  5277. }
  5278. }
  5279. if ($this->level == 8) {
  5280. switch ($tagName) {
  5281. case "NAME":
  5282. $this->info->roleoverrides[$this->info->tempid]->name = $this->info->tempname;
  5283. $this->info->roleoverrides[$this->info->tempid]->shortname = $this->info->tempshortname;
  5284. $this->info->tempname = $this->getContents(); // change to name of capability
  5285. $this->info->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->name = $this->getContents();
  5286. break;
  5287. case "PERMISSION":
  5288. $this->info->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->permission = $this->getContents();
  5289. break;
  5290. case "TIMEMODIFIED":
  5291. $this->info->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->timemodified = $this->getContents();
  5292. break;
  5293. case "MODIFIERID":
  5294. $this->info->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->modifierid = $this->getContents();
  5295. break;
  5296. }
  5297. }
  5298. } /// ends role_overrides
  5299. }
  5300. //Stop parsing if todo = COURSE_HEADER and tagName = HEADER (en of the tag, of course)
  5301. //Speed up a lot (avoid parse all)
  5302. if ($tagName == "HEADER") {
  5303. $this->finished = true;
  5304. }
  5305. //Clear things
  5306. $this->tree[$this->level] = "";
  5307. $this->level--;
  5308. $this->content = "";
  5309. }
  5310. //This is the endTag handler we use where we are reading the sections zone (todo="BLOCKS")
  5311. function endElementBlocks($parser, $tagName) {
  5312. //Check if we are into BLOCKS zone
  5313. if ($this->tree[3] == 'BLOCKS') {
  5314. //if (trim($this->content)) //Debug
  5315. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  5316. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  5317. // Collect everything into $this->temp
  5318. if (!isset($this->temp)) {
  5319. $this->temp = "";
  5320. }
  5321. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  5322. //Dependig of different combinations, do different things
  5323. if ($this->level == 4) {
  5324. switch ($tagName) {
  5325. case 'BLOCK':
  5326. //We've finalized a block, get it
  5327. $this->info->instances[] = $this->info->tempinstance;
  5328. unset($this->info->tempinstance);
  5329. //Also, xmlize INSTANCEDATA and save to db
  5330. //Prepend XML standard header to info gathered
  5331. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5332. //Call to xmlize for this portion of xml data (one BLOCK)
  5333. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5334. $data = xmlize($xml_data,0);
  5335. //echo strftime ("%X",time())."<p>"; //Debug
  5336. //traverse_xmlize($data); //Debug
  5337. //print_object ($GLOBALS['traverse_array']); //Debug
  5338. //$GLOBALS['traverse_array']=""; //Debug
  5339. //Check for instancedata, is exists, then save to DB
  5340. if (isset($data['BLOCK']['#']['INSTANCEDATA']['0']['#'])) {
  5341. //Get old id
  5342. $oldid = $data['BLOCK']['#']['ID']['0']['#'];
  5343. //Get instancedata
  5344. if ($data = $data['BLOCK']['#']['INSTANCEDATA']['0']['#']) {
  5345. //Restore code calls this multiple times - so might already have the newid
  5346. if ($newid = backup_getid($this->preferences->backup_unique_code,'block_instance',$oldid)) {
  5347. $newid = $newid->new_id;
  5348. } else {
  5349. $newid = null;
  5350. }
  5351. //Save to DB, we will use it later
  5352. $status = backup_putid($this->preferences->backup_unique_code,'block_instance',$oldid,$newid,$data);
  5353. }
  5354. }
  5355. //Reset temp
  5356. unset($this->temp);
  5357. break;
  5358. default:
  5359. die($tagName);
  5360. }
  5361. }
  5362. if ($this->level == 5) {
  5363. switch ($tagName) {
  5364. case 'ID':
  5365. $this->info->tempinstance->id = $this->getContents();
  5366. case 'NAME':
  5367. $this->info->tempinstance->name = $this->getContents();
  5368. break;
  5369. case 'PAGEID':
  5370. $this->info->tempinstance->pageid = $this->getContents();
  5371. break;
  5372. case 'PAGETYPE':
  5373. $this->info->tempinstance->pagetype = $this->getContents();
  5374. break;
  5375. case 'POSITION':
  5376. $this->info->tempinstance->position = $this->getContents();
  5377. break;
  5378. case 'WEIGHT':
  5379. $this->info->tempinstance->weight = $this->getContents();
  5380. break;
  5381. case 'VISIBLE':
  5382. $this->info->tempinstance->visible = $this->getContents();
  5383. break;
  5384. case 'CONFIGDATA':
  5385. $this->info->tempinstance->configdata = $this->getContents();
  5386. break;
  5387. default:
  5388. break;
  5389. }
  5390. }
  5391. if ($this->tree[5] == "ROLES_ASSIGNMENTS") {
  5392. if ($this->level == 7) {
  5393. switch ($tagName) {
  5394. case "NAME":
  5395. $this->info->tempname = $this->getContents();
  5396. break;
  5397. case "SHORTNAME":
  5398. $this->info->tempshortname = $this->getContents();
  5399. break;
  5400. case "ID":
  5401. $this->info->tempid = $this->getContents(); // temp roleid
  5402. break;
  5403. }
  5404. }
  5405. if ($this->level == 9) {
  5406. switch ($tagName) {
  5407. case "USERID":
  5408. $this->info->tempinstance->roleassignments[$this->info->tempid]->name = $this->info->tempname;
  5409. $this->info->tempinstance->roleassignments[$this->info->tempid]->shortname = $this->info->tempshortname;
  5410. $this->info->tempuser = $this->getContents();
  5411. $this->info->tempinstance->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->userid = $this->getContents();
  5412. break;
  5413. case "HIDDEN":
  5414. $this->info->tempinstance->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->hidden = $this->getContents();
  5415. break;
  5416. case "TIMESTART":
  5417. $this->info->tempinstance->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timestart = $this->getContents();
  5418. break;
  5419. case "TIMEEND":
  5420. $this->info->tempinstance->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timeend = $this->getContents();
  5421. break;
  5422. case "TIMEMODIFIED":
  5423. $this->info->tempinstance->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timemodified = $this->getContents();
  5424. break;
  5425. case "MODIFIERID":
  5426. $this->info->tempinstance->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->modifierid = $this->getContents();
  5427. break;
  5428. case "ENROL":
  5429. $this->info->tempinstance->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->enrol = $this->getContents();
  5430. break;
  5431. case "SORTORDER":
  5432. $this->info->tempinstance->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->sortorder = $this->getContents();
  5433. break;
  5434. }
  5435. }
  5436. } /// ends role_assignments
  5437. if ($this->tree[5] == "ROLES_OVERRIDES") {
  5438. if ($this->level == 7) {
  5439. switch ($tagName) {
  5440. case "NAME":
  5441. $this->info->tempname = $this->getContents();
  5442. break;
  5443. case "SHORTNAME":
  5444. $this->info->tempshortname = $this->getContents();
  5445. break;
  5446. case "ID":
  5447. $this->info->tempid = $this->getContents(); // temp roleid
  5448. break;
  5449. }
  5450. }
  5451. if ($this->level == 9) {
  5452. switch ($tagName) {
  5453. case "NAME":
  5454. $this->info->tempinstance->roleoverrides[$this->info->tempid]->name = $this->info->tempname;
  5455. $this->info->tempinstance->roleoverrides[$this->info->tempid]->shortname = $this->info->tempshortname;
  5456. $this->info->tempname = $this->getContents(); // change to name of capability
  5457. $this->info->tempinstance->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->name = $this->getContents();
  5458. break;
  5459. case "PERMISSION":
  5460. $this->info->tempinstance->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->permission = $this->getContents();
  5461. break;
  5462. case "TIMEMODIFIED":
  5463. $this->info->tempinstance->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->timemodified = $this->getContents();
  5464. break;
  5465. case "MODIFIERID":
  5466. $this->info->tempinstance->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->modifierid = $this->getContents();
  5467. break;
  5468. }
  5469. }
  5470. } /// ends role_overrides
  5471. }
  5472. //Stop parsing if todo = BLOCKS and tagName = BLOCKS (en of the tag, of course)
  5473. //Speed up a lot (avoid parse all)
  5474. //WARNING: ONLY EXIT IF todo = BLOCKS (thus tree[3] = "BLOCKS") OTHERWISE
  5475. // THE BLOCKS TAG IN THE HEADER WILL TERMINATE US!
  5476. if ($this->tree[3] == 'BLOCKS' && $tagName == 'BLOCKS') {
  5477. $this->finished = true;
  5478. }
  5479. //Clear things
  5480. $this->tree[$this->level] = '';
  5481. $this->level--;
  5482. $this->content = "";
  5483. }
  5484. //This is the endTag handler we use where we are reading the sections zone (todo="SECTIONS")
  5485. function endElementSections($parser, $tagName) {
  5486. //Check if we are into SECTIONS zone
  5487. if ($this->tree[3] == "SECTIONS") {
  5488. //if (trim($this->content)) //Debug
  5489. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  5490. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  5491. //Dependig of different combinations, do different things
  5492. if ($this->level == 4) {
  5493. switch ($tagName) {
  5494. case "SECTION":
  5495. //We've finalized a section, get it
  5496. $this->info->sections[$this->info->tempsection->id] = $this->info->tempsection;
  5497. unset($this->info->tempsection);
  5498. }
  5499. }
  5500. if ($this->level == 5) {
  5501. switch ($tagName) {
  5502. case "ID":
  5503. $this->info->tempsection->id = $this->getContents();
  5504. break;
  5505. case "NUMBER":
  5506. $this->info->tempsection->number = $this->getContents();
  5507. break;
  5508. case "SUMMARY":
  5509. $this->info->tempsection->summary = $this->getContents();
  5510. break;
  5511. case "VISIBLE":
  5512. $this->info->tempsection->visible = $this->getContents();
  5513. break;
  5514. }
  5515. }
  5516. if ($this->level == 6) {
  5517. switch ($tagName) {
  5518. case "MOD":
  5519. if (!isset($this->info->tempmod->groupmode)) {
  5520. $this->info->tempmod->groupmode = 0;
  5521. }
  5522. if (!isset($this->info->tempmod->groupingid)) {
  5523. $this->info->tempmod->groupingid = 0;
  5524. }
  5525. if (!isset($this->info->tempmod->groupmembersonly)) {
  5526. $this->info->tempmod->groupmembersonly = 0;
  5527. }
  5528. if (!isset($this->info->tempmod->idnumber)) {
  5529. $this->info->tempmod->idnumber = null;
  5530. }
  5531. //We've finalized a mod, get it
  5532. $this->info->tempsection->mods[$this->info->tempmod->id]->type =
  5533. $this->info->tempmod->type;
  5534. $this->info->tempsection->mods[$this->info->tempmod->id]->instance =
  5535. $this->info->tempmod->instance;
  5536. $this->info->tempsection->mods[$this->info->tempmod->id]->added =
  5537. $this->info->tempmod->added;
  5538. $this->info->tempsection->mods[$this->info->tempmod->id]->score =
  5539. $this->info->tempmod->score;
  5540. $this->info->tempsection->mods[$this->info->tempmod->id]->indent =
  5541. $this->info->tempmod->indent;
  5542. $this->info->tempsection->mods[$this->info->tempmod->id]->visible =
  5543. $this->info->tempmod->visible;
  5544. $this->info->tempsection->mods[$this->info->tempmod->id]->groupmode =
  5545. $this->info->tempmod->groupmode;
  5546. $this->info->tempsection->mods[$this->info->tempmod->id]->groupingid =
  5547. $this->info->tempmod->groupingid;
  5548. $this->info->tempsection->mods[$this->info->tempmod->id]->groupmembersonly =
  5549. $this->info->tempmod->groupmembersonly;
  5550. $this->info->tempsection->mods[$this->info->tempmod->id]->idnumber =
  5551. $this->info->tempmod->idnumber;
  5552. unset($this->info->tempmod);
  5553. }
  5554. }
  5555. if ($this->level == 7) {
  5556. switch ($tagName) {
  5557. case "ID":
  5558. $this->info->tempmod->id = $this->getContents();
  5559. break;
  5560. case "TYPE":
  5561. $this->info->tempmod->type = $this->getContents();
  5562. break;
  5563. case "INSTANCE":
  5564. $this->info->tempmod->instance = $this->getContents();
  5565. break;
  5566. case "ADDED":
  5567. $this->info->tempmod->added = $this->getContents();
  5568. break;
  5569. case "SCORE":
  5570. $this->info->tempmod->score = $this->getContents();
  5571. break;
  5572. case "INDENT":
  5573. $this->info->tempmod->indent = $this->getContents();
  5574. break;
  5575. case "VISIBLE":
  5576. $this->info->tempmod->visible = $this->getContents();
  5577. break;
  5578. case "GROUPMODE":
  5579. $this->info->tempmod->groupmode = $this->getContents();
  5580. break;
  5581. case "GROUPINGID":
  5582. $this->info->tempmod->groupingid = $this->getContents();
  5583. break;
  5584. case "GROUPMEMBERSONLY":
  5585. $this->info->tempmod->groupmembersonly = $this->getContents();
  5586. break;
  5587. case "IDNUMBER":
  5588. $this->info->tempmod->idnumber = $this->getContents();
  5589. break;
  5590. default:
  5591. break;
  5592. }
  5593. }
  5594. if (isset($this->tree[7]) && $this->tree[7] == "ROLES_ASSIGNMENTS") {
  5595. if ($this->level == 9) {
  5596. switch ($tagName) {
  5597. case "NAME":
  5598. $this->info->tempname = $this->getContents();
  5599. break;
  5600. case "SHORTNAME":
  5601. $this->info->tempshortname = $this->getContents();
  5602. break;
  5603. case "ID":
  5604. $this->info->tempid = $this->getContents(); // temp roleid
  5605. break;
  5606. }
  5607. }
  5608. if ($this->level == 11) {
  5609. switch ($tagName) {
  5610. case "USERID":
  5611. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->name = $this->info->tempname;
  5612. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->shortname = $this->info->tempshortname;
  5613. $this->info->tempuser = $this->getContents();
  5614. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->userid = $this->getContents();
  5615. break;
  5616. case "HIDDEN":
  5617. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->hidden = $this->getContents();
  5618. break;
  5619. case "TIMESTART":
  5620. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timestart = $this->getContents();
  5621. break;
  5622. case "TIMEEND":
  5623. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timeend = $this->getContents();
  5624. break;
  5625. case "TIMEMODIFIED":
  5626. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timemodified = $this->getContents();
  5627. break;
  5628. case "MODIFIERID":
  5629. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->modifierid = $this->getContents();
  5630. break;
  5631. case "ENROL":
  5632. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->enrol = $this->getContents();
  5633. break;
  5634. case "SORTORDER":
  5635. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->sortorder = $this->getContents();
  5636. break;
  5637. }
  5638. }
  5639. } /// ends role_assignments
  5640. if (isset($this->tree[7]) && $this->tree[7] == "ROLES_OVERRIDES") {
  5641. if ($this->level == 9) {
  5642. switch ($tagName) {
  5643. case "NAME":
  5644. $this->info->tempname = $this->getContents();
  5645. break;
  5646. case "SHORTNAME":
  5647. $this->info->tempshortname = $this->getContents();
  5648. break;
  5649. case "ID":
  5650. $this->info->tempid = $this->getContents(); // temp roleid
  5651. break;
  5652. }
  5653. }
  5654. if ($this->level == 11) {
  5655. switch ($tagName) {
  5656. case "NAME":
  5657. $this->info->tempsection->mods[$this->info->tempmod->id]->roleoverrides[$this->info->tempid]->name = $this->info->tempname;
  5658. $this->info->tempsection->mods[$this->info->tempmod->id]->roleoverrides[$this->info->tempid]->shortname = $this->info->tempshortname;
  5659. $this->info->tempname = $this->getContents(); // change to name of capability
  5660. $this->info->tempsection->mods[$this->info->tempmod->id]->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->name = $this->getContents();
  5661. break;
  5662. case "PERMISSION":
  5663. $this->info->tempsection->mods[$this->info->tempmod->id]->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->permission = $this->getContents();
  5664. break;
  5665. case "TIMEMODIFIED":
  5666. $this->info->tempsection->mods[$this->info->tempmod->id]->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->timemodified = $this->getContents();
  5667. break;
  5668. case "MODIFIERID":
  5669. $this->info->tempsection->mods[$this->info->tempmod->id]->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->modifierid = $this->getContents();
  5670. break;
  5671. }
  5672. }
  5673. } /// ends role_overrides
  5674. }
  5675. //Stop parsing if todo = SECTIONS and tagName = SECTIONS (en of the tag, of course)
  5676. //Speed up a lot (avoid parse all)
  5677. if ($tagName == "SECTIONS") {
  5678. $this->finished = true;
  5679. }
  5680. //Clear things
  5681. $this->tree[$this->level] = "";
  5682. $this->level--;
  5683. $this->content = "";
  5684. }
  5685. //This is the endTag handler we use where we are reading the optional format data zone (todo="FORMATDATA")
  5686. function endElementFormatData($parser, $tagName) {
  5687. //Check if we are into FORMATDATA zone
  5688. if ($this->tree[3] == 'FORMATDATA') {
  5689. if (!isset($this->temp)) {
  5690. $this->temp = '';
  5691. }
  5692. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  5693. }
  5694. if($tagName=='FORMATDATA') {
  5695. //Did we have any data? If not don't bother
  5696. if($this->temp!='<FORMATDATA></FORMATDATA>') {
  5697. //Prepend XML standard header to info gathered
  5698. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5699. $this->temp='';
  5700. //Call to xmlize for this portion of xml data (the FORMATDATA block)
  5701. $this->info->format_data = xmlize($xml_data,0);
  5702. }
  5703. //Stop parsing at end of FORMATDATA
  5704. $this->finished=true;
  5705. }
  5706. //Clear things
  5707. $this->tree[$this->level] = "";
  5708. $this->level--;
  5709. $this->content = "";
  5710. }
  5711. //This is the endTag handler we use where we are reading the metacourse zone (todo="METACOURSE")
  5712. function endElementMetacourse($parser, $tagName) {
  5713. //Check if we are into METACOURSE zone
  5714. if ($this->tree[3] == 'METACOURSE') {
  5715. //if (trim($this->content)) //Debug
  5716. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  5717. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  5718. //Dependig of different combinations, do different things
  5719. if ($this->level == 5) {
  5720. switch ($tagName) {
  5721. case 'CHILD':
  5722. //We've finalized a child, get it
  5723. $this->info->childs[] = $this->info->tempmeta;
  5724. unset($this->info->tempmeta);
  5725. break;
  5726. case 'PARENT':
  5727. //We've finalized a parent, get it
  5728. $this->info->parents[] = $this->info->tempmeta;
  5729. unset($this->info->tempmeta);
  5730. break;
  5731. default:
  5732. die($tagName);
  5733. }
  5734. }
  5735. if ($this->level == 6) {
  5736. switch ($tagName) {
  5737. case 'ID':
  5738. $this->info->tempmeta->id = $this->getContents();
  5739. break;
  5740. case 'IDNUMBER':
  5741. $this->info->tempmeta->idnumber = $this->getContents();
  5742. break;
  5743. case 'SHORTNAME':
  5744. $this->info->tempmeta->shortname = $this->getContents();
  5745. break;
  5746. }
  5747. }
  5748. }
  5749. //Stop parsing if todo = METACOURSE and tagName = METACOURSE (en of the tag, of course)
  5750. //Speed up a lot (avoid parse all)
  5751. if ($this->tree[3] == 'METACOURSE' && $tagName == 'METACOURSE') {
  5752. $this->finished = true;
  5753. }
  5754. //Clear things
  5755. $this->tree[$this->level] = '';
  5756. $this->level--;
  5757. $this->content = "";
  5758. }
  5759. //This is the endTag handler we use where we are reading the gradebook zone (todo="GRADEBOOK")
  5760. function endElementGradebook($parser, $tagName) {
  5761. //Check if we are into GRADEBOOK zone
  5762. if ($this->tree[3] == "GRADEBOOK") {
  5763. //if (trim($this->content)) //Debug
  5764. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  5765. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n";//Debug
  5766. //Acumulate data to info (content + close tag)
  5767. //Reconvert: strip htmlchars again and trim to generate xml data
  5768. if (!isset($this->temp)) {
  5769. $this->temp = "";
  5770. }
  5771. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  5772. // We have finished outcome, grade_category or grade_item, reset accumulated
  5773. // data because they are close tags
  5774. if ($this->level == 4) {
  5775. $this->temp = "";
  5776. }
  5777. //If we've finished a grade item, xmlize it an save to db
  5778. if (($this->level == 5) and ($tagName == "GRADE_ITEM")) {
  5779. //Prepend XML standard header to info gathered
  5780. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5781. //Call to xmlize for this portion of xml data (one PREFERENCE)
  5782. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5783. $data = xmlize($xml_data,0);
  5784. $item_id = $data["GRADE_ITEM"]["#"]["ID"]["0"]["#"];
  5785. $this->counter++;
  5786. //Save to db
  5787. $status = backup_putid($this->preferences->backup_unique_code, 'grade_items', $item_id,
  5788. null,$data);
  5789. //Create returning info
  5790. $this->info = $this->counter;
  5791. //Reset temp
  5792. unset($this->temp);
  5793. }
  5794. //If we've finished a grade_category, xmlize it an save to db
  5795. if (($this->level == 5) and ($tagName == "GRADE_CATEGORY")) {
  5796. //Prepend XML standard header to info gathered
  5797. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5798. //Call to xmlize for this portion of xml data (one CATECORY)
  5799. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5800. $data = xmlize($xml_data,0);
  5801. $category_id = $data["GRADE_CATEGORY"]["#"]["ID"]["0"]["#"];
  5802. $this->counter++;
  5803. //Save to db
  5804. $status = backup_putid($this->preferences->backup_unique_code, 'grade_categories' ,$category_id,
  5805. null,$data);
  5806. //Create returning info
  5807. $this->info = $this->counter;
  5808. //Reset temp
  5809. unset($this->temp);
  5810. }
  5811. if (($this->level == 5) and ($tagName == "GRADE_LETTER")) {
  5812. //Prepend XML standard header to info gathered
  5813. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5814. //Call to xmlize for this portion of xml data (one CATECORY)
  5815. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5816. $data = xmlize($xml_data,0);
  5817. $letter_id = $data["GRADE_LETTER"]["#"]["ID"]["0"]["#"];
  5818. $this->counter++;
  5819. //Save to db
  5820. $status = backup_putid($this->preferences->backup_unique_code, 'grade_letters' ,$letter_id,
  5821. null,$data);
  5822. //Create returning info
  5823. $this->info = $this->counter;
  5824. //Reset temp
  5825. unset($this->temp);
  5826. }
  5827. //If we've finished a grade_outcome, xmlize it an save to db
  5828. if (($this->level == 5) and ($tagName == "GRADE_OUTCOME")) {
  5829. //Prepend XML standard header to info gathered
  5830. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5831. //Call to xmlize for this portion of xml data (one CATECORY)
  5832. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5833. $data = xmlize($xml_data,0);
  5834. $outcome_id = $data["GRADE_OUTCOME"]["#"]["ID"]["0"]["#"];
  5835. $this->counter++;
  5836. //Save to db
  5837. $status = backup_putid($this->preferences->backup_unique_code, 'grade_outcomes' ,$outcome_id,
  5838. null,$data);
  5839. //Create returning info
  5840. $this->info = $this->counter;
  5841. //Reset temp
  5842. unset($this->temp);
  5843. }
  5844. //If we've finished a grade_outcomes_course, xmlize it an save to db
  5845. if (($this->level == 5) and ($tagName == "GRADE_OUTCOMES_COURSE")) {
  5846. //Prepend XML standard header to info gathered
  5847. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5848. //Call to xmlize for this portion of xml data (one CATECORY)
  5849. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5850. $data = xmlize($xml_data,0);
  5851. $outcomes_course_id = $data["GRADE_OUTCOMES_COURSE"]["#"]["ID"]["0"]["#"];
  5852. $this->counter++;
  5853. //Save to db
  5854. $status = backup_putid($this->preferences->backup_unique_code, 'grade_outcomes_courses' ,$outcomes_course_id,
  5855. null,$data);
  5856. //Create returning info
  5857. $this->info = $this->counter;
  5858. //Reset temp
  5859. unset($this->temp);
  5860. }
  5861. if (($this->level == 5) and ($tagName == "GRADE_CATEGORIES_HISTORY")) {
  5862. //Prepend XML standard header to info gathered
  5863. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5864. //Call to xmlize for this portion of xml data (one PREFERENCE)
  5865. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5866. $data = xmlize($xml_data,0);
  5867. $id = $data["GRADE_CATEGORIES_HISTORY"]["#"]["ID"]["0"]["#"];
  5868. $this->counter++;
  5869. //Save to db
  5870. $status = backup_putid($this->preferences->backup_unique_code, 'grade_categories_history', $id,
  5871. null,$data);
  5872. //Create returning info
  5873. $this->info = $this->counter;
  5874. //Reset temp
  5875. unset($this->temp);
  5876. }
  5877. if (($this->level == 5) and ($tagName == "GRADE_GRADES_HISTORY")) {
  5878. //Prepend XML standard header to info gathered
  5879. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5880. //Call to xmlize for this portion of xml data (one PREFERENCE)
  5881. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5882. $data = xmlize($xml_data,0);
  5883. $id = $data["GRADE_GRADES_HISTORY"]["#"]["ID"]["0"]["#"];
  5884. $this->counter++;
  5885. //Save to db
  5886. $status = backup_putid($this->preferences->backup_unique_code, 'grade_grades_history', $id,
  5887. null,$data);
  5888. //Create returning info
  5889. $this->info = $this->counter;
  5890. //Reset temp
  5891. unset($this->temp);
  5892. }
  5893. if (($this->level == 5) and ($tagName == "GRADE_ITEM_HISTORY")) {
  5894. //Prepend XML standard header to info gathered
  5895. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5896. //Call to xmlize for this portion of xml data (one PREFERENCE)
  5897. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5898. $data = xmlize($xml_data,0);
  5899. $id = $data["GRADE_ITEM_HISTORY"]["#"]["ID"]["0"]["#"];
  5900. $this->counter++;
  5901. //Save to db
  5902. $status = backup_putid($this->preferences->backup_unique_code, 'grade_items_history', $id,
  5903. null,$data);
  5904. //Create returning info
  5905. $this->info = $this->counter;
  5906. //Reset temp
  5907. unset($this->temp);
  5908. }
  5909. if (($this->level == 5) and ($tagName == "GRADE_OUTCOME_HISTORY")) {
  5910. //Prepend XML standard header to info gathered
  5911. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5912. //Call to xmlize for this portion of xml data (one PREFERENCE)
  5913. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5914. $data = xmlize($xml_data,0);
  5915. $id = $data["GRADE_OUTCOME_HISTORY"]["#"]["ID"]["0"]["#"];
  5916. $this->counter++;
  5917. //Save to db
  5918. $status = backup_putid($this->preferences->backup_unique_code, 'grade_outcomes_history', $id,
  5919. null,$data);
  5920. //Create returning info
  5921. $this->info = $this->counter;
  5922. //Reset temp
  5923. unset($this->temp);
  5924. }
  5925. }
  5926. //Stop parsing if todo = GRADEBOOK and tagName = GRADEBOOK (en of the tag, of course)
  5927. //Speed up a lot (avoid parse all)
  5928. if ($tagName == "GRADEBOOK" and $this->level == 3) {
  5929. $this->finished = true;
  5930. $this->counter = 0;
  5931. }
  5932. //Clear things
  5933. $this->tree[$this->level] = "";
  5934. $this->level--;
  5935. $this->content = "";
  5936. }
  5937. //This is the endTag handler we use where we are reading the gradebook zone (todo="GRADEBOOK")
  5938. function endElementOldGradebook($parser, $tagName) {
  5939. //Check if we are into GRADEBOOK zone
  5940. if ($this->tree[3] == "GRADEBOOK") {
  5941. //if (trim($this->content)) //Debug
  5942. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  5943. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n";//Debug
  5944. //Acumulate data to info (content + close tag)
  5945. //Reconvert: strip htmlchars again and trim to generate xml data
  5946. if (!isset($this->temp)) {
  5947. $this->temp = "";
  5948. }
  5949. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  5950. //We have finished preferences, letters or categories, reset accumulated
  5951. //data because they are close tags
  5952. if ($this->level == 4) {
  5953. $this->temp = "";
  5954. }
  5955. //If we've finished a message, xmlize it an save to db
  5956. if (($this->level == 5) and ($tagName == "GRADE_PREFERENCE")) {
  5957. //Prepend XML standard header to info gathered
  5958. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5959. //Call to xmlize for this portion of xml data (one PREFERENCE)
  5960. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5961. $data = xmlize($xml_data,0);
  5962. //echo strftime ("%X",time())."<p>"; //Debug
  5963. //traverse_xmlize($data); //Debug
  5964. //print_object ($GLOBALS['traverse_array']); //Debug
  5965. //$GLOBALS['traverse_array']=""; //Debug
  5966. //Now, save data to db. We'll use it later
  5967. //Get id and status from data
  5968. $preference_id = $data["GRADE_PREFERENCE"]["#"]["ID"]["0"]["#"];
  5969. $this->counter++;
  5970. //Save to db
  5971. $status = backup_putid($this->preferences->backup_unique_code, 'grade_preferences', $preference_id,
  5972. null,$data);
  5973. //Create returning info
  5974. $this->info = $this->counter;
  5975. //Reset temp
  5976. unset($this->temp);
  5977. }
  5978. //If we've finished a grade_letter, xmlize it an save to db
  5979. if (($this->level == 5) and ($tagName == "GRADE_LETTER")) {
  5980. //Prepend XML standard header to info gathered
  5981. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5982. //Call to xmlize for this portion of xml data (one LETTER)
  5983. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5984. $data = xmlize($xml_data,0);
  5985. //echo strftime ("%X",time())."<p>"; //Debug
  5986. //traverse_xmlize($data); //Debug
  5987. //print_object ($GLOBALS['traverse_array']); //Debug
  5988. //$GLOBALS['traverse_array']=""; //Debug
  5989. //Now, save data to db. We'll use it later
  5990. //Get id and status from data
  5991. $letter_id = $data["GRADE_LETTER"]["#"]["ID"]["0"]["#"];
  5992. $this->counter++;
  5993. //Save to db
  5994. $status = backup_putid($this->preferences->backup_unique_code, 'grade_letter' ,$letter_id,
  5995. null,$data);
  5996. //Create returning info
  5997. $this->info = $this->counter;
  5998. //Reset temp
  5999. unset($this->temp);
  6000. }
  6001. //If we've finished a grade_category, xmlize it an save to db
  6002. if (($this->level == 5) and ($tagName == "GRADE_CATEGORY")) {
  6003. //Prepend XML standard header to info gathered
  6004. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6005. //Call to xmlize for this portion of xml data (one CATECORY)
  6006. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6007. $data = xmlize($xml_data,0);
  6008. //echo strftime ("%X",time())."<p>"; //Debug
  6009. //traverse_xmlize($data); //Debug
  6010. //print_object ($GLOBALS['traverse_array']); //Debug
  6011. //$GLOBALS['traverse_array']=""; //Debug
  6012. //Now, save data to db. We'll use it later
  6013. //Get id and status from data
  6014. $category_id = $data["GRADE_CATEGORY"]["#"]["ID"]["0"]["#"];
  6015. $this->counter++;
  6016. //Save to db
  6017. $status = backup_putid($this->preferences->backup_unique_code, 'grade_category' ,$category_id,
  6018. null,$data);
  6019. //Create returning info
  6020. $this->info = $this->counter;
  6021. //Reset temp
  6022. unset($this->temp);
  6023. }
  6024. }
  6025. //Stop parsing if todo = GRADEBOOK and tagName = GRADEBOOK (en of the tag, of course)
  6026. //Speed up a lot (avoid parse all)
  6027. if ($tagName == "GRADEBOOK" and $this->level == 3) {
  6028. $this->finished = true;
  6029. $this->counter = 0;
  6030. }
  6031. //Clear things
  6032. $this->tree[$this->level] = "";
  6033. $this->level--;
  6034. $this->content = "";
  6035. }
  6036. //This is the endTag handler we use where we are reading the users zone (todo="USERS")
  6037. function endElementUsers($parser, $tagName) {
  6038. global $CFG;
  6039. //Check if we are into USERS zone
  6040. if ($this->tree[3] == "USERS") {
  6041. //if (trim($this->content)) //Debug
  6042. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6043. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  6044. //Dependig of different combinations, do different things
  6045. if ($this->level == 4) {
  6046. switch ($tagName) {
  6047. case "USER":
  6048. //Increment counter
  6049. $this->counter++;
  6050. //Save to db, only save if record not already exist
  6051. // if there already is an new_id for this entry, just use that new_id?
  6052. $newuser = backup_getid($this->preferences->backup_unique_code,"user",$this->info->tempuser->id);
  6053. if (isset($newuser->new_id)) {
  6054. $newid = $newuser->new_id;
  6055. } else {
  6056. $newid = null;
  6057. }
  6058. backup_putid($this->preferences->backup_unique_code,"user",$this->info->tempuser->id,
  6059. $newid,$this->info->tempuser);
  6060. //Do some output
  6061. if ($this->counter % 10 == 0) {
  6062. if (!defined('RESTORE_SILENTLY')) {
  6063. echo ".";
  6064. if ($this->counter % 200 == 0) {
  6065. echo "<br />";
  6066. }
  6067. }
  6068. backup_flush(300);
  6069. }
  6070. //Delete temp obejct
  6071. unset($this->info->tempuser);
  6072. break;
  6073. }
  6074. }
  6075. if ($this->level == 5) {
  6076. switch ($tagName) {
  6077. case "ID":
  6078. $this->info->users[$this->getContents()] = $this->getContents();
  6079. $this->info->tempuser->id = $this->getContents();
  6080. break;
  6081. case "AUTH":
  6082. $this->info->tempuser->auth = $this->getContents();
  6083. break;
  6084. case "CONFIRMED":
  6085. $this->info->tempuser->confirmed = $this->getContents();
  6086. break;
  6087. case "POLICYAGREED":
  6088. $this->info->tempuser->policyagreed = $this->getContents();
  6089. break;
  6090. case "DELETED":
  6091. $this->info->tempuser->deleted = $this->getContents();
  6092. break;
  6093. case "USERNAME":
  6094. $this->info->tempuser->username = $this->getContents();
  6095. break;
  6096. case "PASSWORD":
  6097. $this->info->tempuser->password = $this->getContents();
  6098. break;
  6099. case "IDNUMBER":
  6100. $this->info->tempuser->idnumber = $this->getContents();
  6101. break;
  6102. case "FIRSTNAME":
  6103. $this->info->tempuser->firstname = $this->getContents();
  6104. break;
  6105. case "LASTNAME":
  6106. $this->info->tempuser->lastname = $this->getContents();
  6107. break;
  6108. case "EMAIL":
  6109. $this->info->tempuser->email = $this->getContents();
  6110. break;
  6111. case "EMAILSTOP":
  6112. $this->info->tempuser->emailstop = $this->getContents();
  6113. break;
  6114. case "ICQ":
  6115. $this->info->tempuser->icq = $this->getContents();
  6116. break;
  6117. case "SKYPE":
  6118. $this->info->tempuser->skype = $this->getContents();
  6119. break;
  6120. case "AIM":
  6121. $this->info->tempuser->aim = $this->getContents();
  6122. break;
  6123. case "YAHOO":
  6124. $this->info->tempuser->yahoo = $this->getContents();
  6125. break;
  6126. case "MSN":
  6127. $this->info->tempuser->msn = $this->getContents();
  6128. break;
  6129. case "PHONE1":
  6130. $this->info->tempuser->phone1 = $this->getContents();
  6131. break;
  6132. case "PHONE2":
  6133. $this->info->tempuser->phone2 = $this->getContents();
  6134. break;
  6135. case "INSTITUTION":
  6136. $this->info->tempuser->institution = $this->getContents();
  6137. break;
  6138. case "DEPARTMENT":
  6139. $this->info->tempuser->department = $this->getContents();
  6140. break;
  6141. case "ADDRESS":
  6142. $this->info->tempuser->address = $this->getContents();
  6143. break;
  6144. case "CITY":
  6145. $this->info->tempuser->city = $this->getContents();
  6146. break;
  6147. case "COUNTRY":
  6148. $this->info->tempuser->country = $this->getContents();
  6149. break;
  6150. case "LANG":
  6151. $this->info->tempuser->lang = $this->getContents();
  6152. break;
  6153. case "THEME":
  6154. $this->info->tempuser->theme = $this->getContents();
  6155. break;
  6156. case "TIMEZONE":
  6157. $this->info->tempuser->timezone = $this->getContents();
  6158. break;
  6159. case "FIRSTACCESS":
  6160. $this->info->tempuser->firstaccess = $this->getContents();
  6161. break;
  6162. case "LASTACCESS":
  6163. $this->info->tempuser->lastaccess = $this->getContents();
  6164. break;
  6165. case "LASTLOGIN":
  6166. $this->info->tempuser->lastlogin = $this->getContents();
  6167. break;
  6168. case "CURRENTLOGIN":
  6169. $this->info->tempuser->currentlogin = $this->getContents();
  6170. break;
  6171. case "LASTIP":
  6172. $this->info->tempuser->lastip = $this->getContents();
  6173. break;
  6174. case "PICTURE":
  6175. $this->info->tempuser->picture = $this->getContents();
  6176. break;
  6177. case "URL":
  6178. $this->info->tempuser->url = $this->getContents();
  6179. break;
  6180. case "DESCRIPTION":
  6181. $this->info->tempuser->description = $this->getContents();
  6182. break;
  6183. case "MAILFORMAT":
  6184. $this->info->tempuser->mailformat = $this->getContents();
  6185. break;
  6186. case "MAILDIGEST":
  6187. $this->info->tempuser->maildigest = $this->getContents();
  6188. break;
  6189. case "MAILDISPLAY":
  6190. $this->info->tempuser->maildisplay = $this->getContents();
  6191. break;
  6192. case "HTMLEDITOR":
  6193. $this->info->tempuser->htmleditor = $this->getContents();
  6194. break;
  6195. case "AJAX":
  6196. $this->info->tempuser->ajax = $this->getContents();
  6197. break;
  6198. case "AUTOSUBSCRIBE":
  6199. $this->info->tempuser->autosubscribe = $this->getContents();
  6200. break;
  6201. case "TRACKFORUMS":
  6202. $this->info->tempuser->trackforums = $this->getContents();
  6203. break;
  6204. case "MNETHOSTURL":
  6205. $this->info->tempuser->mnethosturl = $this->getContents();
  6206. break;
  6207. case "TIMEMODIFIED":
  6208. $this->info->tempuser->timemodified = $this->getContents();
  6209. break;
  6210. default:
  6211. break;
  6212. }
  6213. }
  6214. if ($this->level == 6 && $this->tree[5]!="ROLES_ASSIGNMENTS" && $this->tree[5]!="ROLES_OVERRIDES") {
  6215. switch ($tagName) {
  6216. case "ROLE":
  6217. //We've finalized a role, get it
  6218. $this->info->tempuser->roles[$this->info->temprole->type] = $this->info->temprole;
  6219. unset($this->info->temprole);
  6220. break;
  6221. case "USER_PREFERENCE":
  6222. //We've finalized a user_preference, get it
  6223. $this->info->tempuser->user_preferences[$this->info->tempuserpreference->name] = $this->info->tempuserpreference;
  6224. unset($this->info->tempuserpreference);
  6225. break;
  6226. case "USER_CUSTOM_PROFILE_FIELD":
  6227. //We've finalized a user_custom_profile_field, get it
  6228. $this->info->tempuser->user_custom_profile_fields[] = $this->info->tempusercustomprofilefield;
  6229. unset($this->info->tempusercustomprofilefield);
  6230. break;
  6231. case "USER_TAG":
  6232. //We've finalized a user_tag, get it
  6233. $this->info->tempuser->user_tags[] = $this->info->tempusertag;
  6234. unset($this->info->tempusertag);
  6235. break;
  6236. default:
  6237. break;
  6238. }
  6239. }
  6240. if ($this->level == 7 && $this->tree[5]!="ROLES_ASSIGNMENTS" && $this->tree[5]!="ROLES_OVERRIDES") {
  6241. /// If we are reading roles
  6242. if($this->tree[6] == 'ROLE') {
  6243. switch ($tagName) {
  6244. case "TYPE":
  6245. $this->info->temprole->type = $this->getContents();
  6246. break;
  6247. case "AUTHORITY":
  6248. $this->info->temprole->authority = $this->getContents();
  6249. break;
  6250. case "TEA_ROLE":
  6251. $this->info->temprole->tea_role = $this->getContents();
  6252. break;
  6253. case "EDITALL":
  6254. $this->info->temprole->editall = $this->getContents();
  6255. break;
  6256. case "TIMESTART":
  6257. $this->info->temprole->timestart = $this->getContents();
  6258. break;
  6259. case "TIMEEND":
  6260. $this->info->temprole->timeend = $this->getContents();
  6261. break;
  6262. case "TIMEMODIFIED":
  6263. $this->info->temprole->timemodified = $this->getContents();
  6264. break;
  6265. case "TIMESTART":
  6266. $this->info->temprole->timestart = $this->getContents();
  6267. break;
  6268. case "TIMEEND":
  6269. $this->info->temprole->timeend = $this->getContents();
  6270. break;
  6271. case "TIME":
  6272. $this->info->temprole->time = $this->getContents();
  6273. break;
  6274. case "TIMEACCESS":
  6275. $this->info->temprole->timeaccess = $this->getContents();
  6276. break;
  6277. case "ENROL":
  6278. $this->info->temprole->enrol = $this->getContents();
  6279. break;
  6280. default:
  6281. break;
  6282. }
  6283. /// If we are reading user_preferences
  6284. } else if ($this->tree[6] == 'USER_PREFERENCE') {
  6285. switch ($tagName) {
  6286. case "NAME":
  6287. $this->info->tempuserpreference->name = $this->getContents();
  6288. break;
  6289. case "VALUE":
  6290. $this->info->tempuserpreference->value = $this->getContents();
  6291. break;
  6292. default:
  6293. break;
  6294. }
  6295. /// If we are reading user_custom_profile_fields
  6296. } else if ($this->tree[6] == 'USER_CUSTOM_PROFILE_FIELD') {
  6297. switch ($tagName) {
  6298. case "FIELD_NAME":
  6299. $this->info->tempusercustomprofilefield->field_name = $this->getContents();
  6300. break;
  6301. case "FIELD_TYPE":
  6302. $this->info->tempusercustomprofilefield->field_type = $this->getContents();
  6303. break;
  6304. case "FIELD_DATA":
  6305. $this->info->tempusercustomprofilefield->field_data = $this->getContents();
  6306. break;
  6307. default:
  6308. break;
  6309. }
  6310. /// If we are reading user_tags
  6311. } else if ($this->tree[6] == 'USER_TAG') {
  6312. switch ($tagName) {
  6313. case "NAME":
  6314. $this->info->tempusertag->name = $this->getContents();
  6315. break;
  6316. case "RAWNAME":
  6317. $this->info->tempusertag->rawname = $this->getContents();
  6318. break;
  6319. default:
  6320. break;
  6321. }
  6322. }
  6323. }
  6324. if ($this->tree[5] == "ROLES_ASSIGNMENTS") {
  6325. if ($this->level == 7) {
  6326. switch ($tagName) {
  6327. case "NAME":
  6328. $this->info->tempname = $this->getContents();
  6329. break;
  6330. case "SHORTNAME":
  6331. $this->info->tempshortname = $this->getContents();
  6332. break;
  6333. case "ID":
  6334. $this->info->tempid = $this->getContents(); // temp roleid
  6335. break;
  6336. }
  6337. }
  6338. if ($this->level == 9) {
  6339. switch ($tagName) {
  6340. case "USERID":
  6341. $this->info->tempuser->roleassignments[$this->info->tempid]->name = $this->info->tempname;
  6342. $this->info->tempuser->roleassignments[$this->info->tempid]->shortname = $this->info->tempshortname;
  6343. $this->info->tempuserid = $this->getContents();
  6344. $this->info->tempuser->roleassignments[$this->info->tempid]->assignments[$this->info->tempuserid]->userid = $this->getContents();
  6345. break;
  6346. case "HIDDEN":
  6347. $this->info->tempuser->roleassignments[$this->info->tempid]->assignments[$this->info->tempuserid]->hidden = $this->getContents();
  6348. break;
  6349. case "TIMESTART":
  6350. $this->info->tempuser->roleassignments[$this->info->tempid]->assignments[$this->info->tempuserid]->timestart = $this->getContents();
  6351. break;
  6352. case "TIMEEND":
  6353. $this->info->tempuser->roleassignments[$this->info->tempid]->assignments[$this->info->tempuserid]->timeend = $this->getContents();
  6354. break;
  6355. case "TIMEMODIFIED":
  6356. $this->info->tempuser->roleassignments[$this->info->tempid]->assignments[$this->info->tempuserid]->timemodified = $this->getContents();
  6357. break;
  6358. case "MODIFIERID":
  6359. $this->info->tempuser->roleassignments[$this->info->tempid]->assignments[$this->info->tempuserid]->modifierid = $this->getContents();
  6360. break;
  6361. case "ENROL":
  6362. $this->info->tempuser->roleassignments[$this->info->tempid]->assignments[$this->info->tempuserid]->enrol = $this->getContents();
  6363. break;
  6364. case "SORTORDER":
  6365. $this->info->tempuser->roleassignments[$this->info->tempid]->assignments[$this->info->tempuserid]->sortorder = $this->getContents();
  6366. break;
  6367. }
  6368. }
  6369. } /// ends role_assignments
  6370. if ($this->tree[5] == "ROLES_OVERRIDES") {
  6371. if ($this->level == 7) {
  6372. switch ($tagName) {
  6373. case "NAME":
  6374. $this->info->tempname = $this->getContents();
  6375. break;
  6376. case "SHORTNAME":
  6377. $this->info->tempshortname = $this->getContents();
  6378. break;
  6379. case "ID":
  6380. $this->info->tempid = $this->getContents(); // temp roleid
  6381. break;
  6382. }
  6383. }
  6384. if ($this->level == 9) {
  6385. switch ($tagName) {
  6386. case "NAME":
  6387. $this->info->tempuser->roleoverrides[$this->info->tempid]->name = $this->info->tempname;
  6388. $this->info->tempuser->roleoverrides[$this->info->tempid]->shortname = $this->info->tempshortname;
  6389. $this->info->tempname = $this->getContents(); // change to name of capability
  6390. $this->info->tempuser->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->name = $this->getContents();
  6391. break;
  6392. case "PERMISSION":
  6393. $this->info->tempuser->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->permission = $this->getContents();
  6394. break;
  6395. case "TIMEMODIFIED":
  6396. $this->info->tempuser->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->timemodified = $this->getContents();
  6397. break;
  6398. case "MODIFIERID":
  6399. $this->info->tempuser->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->modifierid = $this->getContents();
  6400. break;
  6401. }
  6402. }
  6403. } /// ends role_overrides
  6404. } // closes if this->tree[3]=="users"
  6405. //Stop parsing if todo = USERS and tagName = USERS (en of the tag, of course)
  6406. //Speed up a lot (avoid parse all)
  6407. if ($tagName == "USERS" and $this->level == 3) {
  6408. $this->finished = true;
  6409. $this->counter = 0;
  6410. }
  6411. //Clear things
  6412. $this->tree[$this->level] = "";
  6413. $this->level--;
  6414. $this->content = "";
  6415. }
  6416. //This is the endTag handler we use where we are reading the messages zone (todo="MESSAGES")
  6417. function endElementMessages($parser, $tagName) {
  6418. //Check if we are into MESSAGES zone
  6419. if ($this->tree[3] == "MESSAGES") {
  6420. //if (trim($this->content)) //Debug
  6421. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6422. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n";//Debug
  6423. //Acumulate data to info (content + close tag)
  6424. //Reconvert: strip htmlchars again and trim to generate xml data
  6425. if (!isset($this->temp)) {
  6426. $this->temp = "";
  6427. }
  6428. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6429. //If we've finished a message, xmlize it an save to db
  6430. if (($this->level == 4) and ($tagName == "MESSAGE")) {
  6431. //Prepend XML standard header to info gathered
  6432. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6433. //Call to xmlize for this portion of xml data (one MESSAGE)
  6434. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6435. $data = xmlize($xml_data,0);
  6436. //echo strftime ("%X",time())."<p>"; //Debug
  6437. //traverse_xmlize($data); //Debug
  6438. //print_object ($GLOBALS['traverse_array']); //Debug
  6439. //$GLOBALS['traverse_array']=""; //Debug
  6440. //Now, save data to db. We'll use it later
  6441. //Get id and status from data
  6442. $message_id = $data["MESSAGE"]["#"]["ID"]["0"]["#"];
  6443. $message_status = $data["MESSAGE"]["#"]["STATUS"]["0"]["#"];
  6444. if ($message_status == "READ") {
  6445. $table = "message_read";
  6446. } else {
  6447. $table = "message";
  6448. }
  6449. $this->counter++;
  6450. //Save to db
  6451. $status = backup_putid($this->preferences->backup_unique_code, $table,$message_id,
  6452. null,$data);
  6453. //Create returning info
  6454. $this->info = $this->counter;
  6455. //Reset temp
  6456. unset($this->temp);
  6457. }
  6458. //If we've finished a contact, xmlize it an save to db
  6459. if (($this->level == 5) and ($tagName == "CONTACT")) {
  6460. //Prepend XML standard header to info gathered
  6461. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6462. //Call to xmlize for this portion of xml data (one MESSAGE)
  6463. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6464. $data = xmlize($xml_data,0);
  6465. //echo strftime ("%X",time())."<p>"; //Debug
  6466. //traverse_xmlize($data); //Debug
  6467. //print_object ($GLOBALS['traverse_array']); //Debug
  6468. //$GLOBALS['traverse_array']=""; //Debug
  6469. //Now, save data to db. We'll use it later
  6470. //Get id and status from data
  6471. $contact_id = $data["CONTACT"]["#"]["ID"]["0"]["#"];
  6472. $this->counter++;
  6473. //Save to db
  6474. $status = backup_putid($this->preferences->backup_unique_code, 'message_contacts' ,$contact_id,
  6475. null,$data);
  6476. //Create returning info
  6477. $this->info = $this->counter;
  6478. //Reset temp
  6479. unset($this->temp);
  6480. }
  6481. }
  6482. //Stop parsing if todo = MESSAGES and tagName = MESSAGES (en of the tag, of course)
  6483. //Speed up a lot (avoid parse all)
  6484. if ($tagName == "MESSAGES" and $this->level == 3) {
  6485. $this->finished = true;
  6486. $this->counter = 0;
  6487. }
  6488. //Clear things
  6489. $this->tree[$this->level] = "";
  6490. $this->level--;
  6491. $this->content = "";
  6492. }
  6493. //This is the endTag handler we use where we are reading the blogs zone (todo="BLOGS")
  6494. function endElementBlogs($parser, $tagName) {
  6495. //Check if we are into BLOGS zone
  6496. if ($this->tree[3] == "BLOGS") {
  6497. //if (trim($this->content)) //Debug
  6498. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6499. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n";//Debug
  6500. //Acumulate data to info (content + close tag)
  6501. //Reconvert: strip htmlchars again and trim to generate xml data
  6502. if (!isset($this->temp)) {
  6503. $this->temp = "";
  6504. }
  6505. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6506. //If we've finished a blog, xmlize it an save to db
  6507. if (($this->level == 4) and ($tagName == "BLOG")) {
  6508. //Prepend XML standard header to info gathered
  6509. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6510. //Call to xmlize for this portion of xml data (one BLOG)
  6511. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6512. $data = xmlize($xml_data,0);
  6513. //echo strftime ("%X",time())."<p>"; //Debug
  6514. //traverse_xmlize($data); //Debug
  6515. //print_object ($GLOBALS['traverse_array']); //Debug
  6516. //$GLOBALS['traverse_array']=""; //Debug
  6517. //Now, save data to db. We'll use it later
  6518. //Get id from data
  6519. $blog_id = $data["BLOG"]["#"]["ID"]["0"]["#"];
  6520. $this->counter++;
  6521. //Save to db
  6522. $status = backup_putid($this->preferences->backup_unique_code, 'blog', $blog_id,
  6523. null,$data);
  6524. //Create returning info
  6525. $this->info = $this->counter;
  6526. //Reset temp
  6527. unset($this->temp);
  6528. }
  6529. }
  6530. //Stop parsing if todo = BLOGS and tagName = BLOGS (end of the tag, of course)
  6531. //Speed up a lot (avoid parse all)
  6532. if ($tagName == "BLOGS" and $this->level == 3) {
  6533. $this->finished = true;
  6534. $this->counter = 0;
  6535. }
  6536. //Clear things
  6537. $this->tree[$this->level] = "";
  6538. $this->level--;
  6539. $this->content = "";
  6540. }
  6541. //This is the endTag handler we use where we are reading the questions zone (todo="QUESTIONS")
  6542. function endElementQuestions($parser, $tagName) {
  6543. //Check if we are into QUESTION_CATEGORIES zone
  6544. if ($this->tree[3] == "QUESTION_CATEGORIES") {
  6545. //if (trim($this->content)) //Debug
  6546. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6547. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  6548. //Acumulate data to info (content + close tag)
  6549. //Reconvert: strip htmlchars again and trim to generate xml data
  6550. if (!isset($this->temp)) {
  6551. $this->temp = "";
  6552. }
  6553. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6554. //If we've finished a mod, xmlize it an save to db
  6555. if (($this->level == 4) and ($tagName == "QUESTION_CATEGORY")) {
  6556. //Prepend XML standard header to info gathered
  6557. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6558. //Call to xmlize for this portion of xml data (one QUESTION_CATEGORY)
  6559. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6560. $data = xmlize($xml_data,0);
  6561. //echo strftime ("%X",time())."<p>"; //Debug
  6562. //traverse_xmlize($data); //Debug
  6563. //print_object ($GLOBALS['traverse_array']); //Debug
  6564. //$GLOBALS['traverse_array']=""; //Debug
  6565. //Now, save data to db. We'll use it later
  6566. //Get id from data
  6567. $category_id = $data["QUESTION_CATEGORY"]["#"]["ID"]["0"]["#"];
  6568. //Save to db
  6569. $status = backup_putid($this->preferences->backup_unique_code,"question_categories",$category_id,
  6570. null,$data);
  6571. //Create returning info
  6572. $ret_info = new object();
  6573. $ret_info->id = $category_id;
  6574. $this->info[] = $ret_info;
  6575. //Reset temp
  6576. unset($this->temp);
  6577. }
  6578. }
  6579. //Stop parsing if todo = QUESTION_CATEGORIES and tagName = QUESTION_CATEGORY (en of the tag, of course)
  6580. //Speed up a lot (avoid parse all)
  6581. if ($tagName == "QUESTION_CATEGORIES" and $this->level == 3) {
  6582. $this->finished = true;
  6583. }
  6584. //Clear things
  6585. $this->tree[$this->level] = "";
  6586. $this->level--;
  6587. $this->content = "";
  6588. }
  6589. //This is the endTag handler we use where we are reading the scales zone (todo="SCALES")
  6590. function endElementScales($parser, $tagName) {
  6591. //Check if we are into SCALES zone
  6592. if ($this->tree[3] == "SCALES") {
  6593. //if (trim($this->content)) //Debug
  6594. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6595. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  6596. //Acumulate data to info (content + close tag)
  6597. //Reconvert: strip htmlchars again and trim to generate xml data
  6598. if (!isset($this->temp)) {
  6599. $this->temp = "";
  6600. }
  6601. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6602. //If we've finished a scale, xmlize it an save to db
  6603. if (($this->level == 4) and ($tagName == "SCALE")) {
  6604. //Prepend XML standard header to info gathered
  6605. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6606. //Call to xmlize for this portion of xml data (one SCALE)
  6607. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6608. $data = xmlize($xml_data,0);
  6609. //echo strftime ("%X",time())."<p>"; //Debug
  6610. //traverse_xmlize($data); //Debug
  6611. //print_object ($GLOBALS['traverse_array']); //Debug
  6612. //$GLOBALS['traverse_array']=""; //Debug
  6613. //Now, save data to db. We'll use it later
  6614. //Get id and from data
  6615. $scale_id = $data["SCALE"]["#"]["ID"]["0"]["#"];
  6616. //Save to db
  6617. $status = backup_putid($this->preferences->backup_unique_code,"scale",$scale_id,
  6618. null,$data);
  6619. //Create returning info
  6620. $ret_info = new object();
  6621. $ret_info->id = $scale_id;
  6622. $this->info[] = $ret_info;
  6623. //Reset temp
  6624. unset($this->temp);
  6625. }
  6626. }
  6627. //Stop parsing if todo = SCALES and tagName = SCALE (en of the tag, of course)
  6628. //Speed up a lot (avoid parse all)
  6629. if ($tagName == "SCALES" and $this->level == 3) {
  6630. $this->finished = true;
  6631. }
  6632. //Clear things
  6633. $this->tree[$this->level] = "";
  6634. $this->level--;
  6635. $this->content = "";
  6636. }
  6637. //This is the endTag handler we use where we are reading the groups zone (todo="GROUPS")
  6638. function endElementGroups($parser, $tagName) {
  6639. //Check if we are into GROUPS zone
  6640. if ($this->tree[3] == "GROUPS") {
  6641. //if (trim($this->content)) //Debug
  6642. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6643. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  6644. //Acumulate data to info (content + close tag)
  6645. //Reconvert: strip htmlchars again and trim to generate xml data
  6646. if (!isset($this->temp)) {
  6647. $this->temp = "";
  6648. }
  6649. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6650. //If we've finished a group, xmlize it an save to db
  6651. if (($this->level == 4) and ($tagName == "GROUP")) {
  6652. //Prepend XML standard header to info gathered
  6653. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6654. //Call to xmlize for this portion of xml data (one GROUP)
  6655. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6656. $data = xmlize($xml_data,0);
  6657. //echo strftime ("%X",time())."<p>"; //Debug
  6658. //traverse_xmlize($data); //Debug
  6659. //print_object ($GLOBALS['traverse_array']); //Debug
  6660. //$GLOBALS['traverse_array']=""; //Debug
  6661. //Now, save data to db. We'll use it later
  6662. //Get id and from data
  6663. $group_id = $data["GROUP"]["#"]["ID"]["0"]["#"];
  6664. //Save to db
  6665. $status = backup_putid($this->preferences->backup_unique_code,"groups",$group_id,
  6666. null,$data);
  6667. //Create returning info
  6668. $ret_info = new Object();
  6669. $ret_info->id = $group_id;
  6670. $this->info[] = $ret_info;
  6671. //Reset temp
  6672. unset($this->temp);
  6673. }
  6674. }
  6675. //Stop parsing if todo = GROUPS and tagName = GROUP (en of the tag, of course)
  6676. //Speed up a lot (avoid parse all)
  6677. if ($tagName == "GROUPS" and $this->level == 3) {
  6678. $this->finished = true;
  6679. }
  6680. //Clear things
  6681. $this->tree[$this->level] = "";
  6682. $this->level--;
  6683. $this->content = "";
  6684. }
  6685. //This is the endTag handler we use where we are reading the groupings zone (todo="GROUPINGS")
  6686. function endElementGroupings($parser, $tagName) {
  6687. //Check if we are into GROUPINGS zone
  6688. if ($this->tree[3] == "GROUPINGS") {
  6689. //Acumulate data to info (content + close tag)
  6690. //Reconvert: strip htmlchars again and trim to generate xml data
  6691. if (!isset($this->temp)) {
  6692. $this->temp = "";
  6693. }
  6694. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6695. //If we've finished a group, xmlize it an save to db
  6696. if (($this->level == 4) and ($tagName == "GROUPING")) {
  6697. //Prepend XML standard header to info gathered
  6698. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6699. //Call to xmlize for this portion of xml data (one GROUPING)
  6700. $data = xmlize($xml_data,0);
  6701. //Now, save data to db. We'll use it later
  6702. //Get id and from data
  6703. $grouping_id = $data["GROUPING"]["#"]["ID"]["0"]["#"];
  6704. //Save to db
  6705. $status = backup_putid($this->preferences->backup_unique_code,"groupings",$grouping_id,
  6706. null,$data);
  6707. //Create returning info
  6708. $ret_info = new Object();
  6709. $ret_info->id = $grouping_id;
  6710. $this->info[] = $ret_info;
  6711. //Reset temp
  6712. unset($this->temp);
  6713. }
  6714. }
  6715. //Stop parsing if todo = GROUPINGS and tagName = GROUPING (en of the tag, of course)
  6716. //Speed up a lot (avoid parse all)
  6717. if ($tagName == "GROUPINGS" and $this->level == 3) {
  6718. $this->finished = true;
  6719. }
  6720. //Clear things
  6721. $this->tree[$this->level] = "";
  6722. $this->level--;
  6723. $this->content = "";
  6724. }
  6725. //This is the endTag handler we use where we are reading the groupingsgroups zone (todo="GROUPINGGROUPS")
  6726. function endElementGroupingsGroups($parser, $tagName) {
  6727. //Check if we are into GROUPINGSGROUPS zone
  6728. if ($this->tree[3] == "GROUPINGSGROUPS") {
  6729. //Acumulate data to info (content + close tag)
  6730. //Reconvert: strip htmlchars again and trim to generate xml data
  6731. if (!isset($this->temp)) {
  6732. $this->temp = "";
  6733. }
  6734. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6735. //If we've finished a group, xmlize it an save to db
  6736. if (($this->level == 4) and ($tagName == "GROUPINGGROUP")) {
  6737. //Prepend XML standard header to info gathered
  6738. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6739. //Call to xmlize for this portion of xml data (one GROUPING)
  6740. $data = xmlize($xml_data,0);
  6741. //Now, save data to db. We'll use it later
  6742. //Get id and from data
  6743. $groupinggroup_id = $data["GROUPINGGROUP"]["#"]["ID"]["0"]["#"];
  6744. //Save to db
  6745. $status = backup_putid($this->preferences->backup_unique_code,"groupingsgroups",$groupinggroup_id,
  6746. null,$data);
  6747. //Create returning info
  6748. $ret_info = new Object();
  6749. $ret_info->id = $groupinggroup_id;
  6750. $this->info[] = $ret_info;
  6751. //Reset temp
  6752. unset($this->temp);
  6753. }
  6754. }
  6755. //Stop parsing if todo = GROUPINGS and tagName = GROUPING (en of the tag, of course)
  6756. //Speed up a lot (avoid parse all)
  6757. if ($tagName == "GROUPINGSGROUPS" and $this->level == 3) {
  6758. $this->finished = true;
  6759. }
  6760. //Clear things
  6761. $this->tree[$this->level] = "";
  6762. $this->level--;
  6763. $this->content = "";
  6764. }
  6765. //This is the endTag handler we use where we are reading the events zone (todo="EVENTS")
  6766. function endElementEvents($parser, $tagName) {
  6767. //Check if we are into EVENTS zone
  6768. if ($this->tree[3] == "EVENTS") {
  6769. //if (trim($this->content)) //Debug
  6770. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6771. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  6772. //Acumulate data to info (content + close tag)
  6773. //Reconvert: strip htmlchars again and trim to generate xml data
  6774. if (!isset($this->temp)) {
  6775. $this->temp = "";
  6776. }
  6777. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6778. //If we've finished a event, xmlize it an save to db
  6779. if (($this->level == 4) and ($tagName == "EVENT")) {
  6780. //Prepend XML standard header to info gathered
  6781. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6782. //Call to xmlize for this portion of xml data (one EVENT)
  6783. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6784. $data = xmlize($xml_data,0);
  6785. //echo strftime ("%X",time())."<p>"; //Debug
  6786. //traverse_xmlize($data); //Debug
  6787. //print_object ($GLOBALS['traverse_array']); //Debug
  6788. //$GLOBALS['traverse_array']=""; //Debug
  6789. //Now, save data to db. We'll use it later
  6790. //Get id and from data
  6791. $event_id = $data["EVENT"]["#"]["ID"]["0"]["#"];
  6792. //Save to db
  6793. $status = backup_putid($this->preferences->backup_unique_code,"event",$event_id,
  6794. null,$data);
  6795. //Create returning info
  6796. $ret_info = new object();
  6797. $ret_info->id = $event_id;
  6798. $this->info[] = $ret_info;
  6799. //Reset temp
  6800. unset($this->temp);
  6801. }
  6802. }
  6803. //Stop parsing if todo = EVENTS and tagName = EVENT (en of the tag, of course)
  6804. //Speed up a lot (avoid parse all)
  6805. if ($tagName == "EVENTS" and $this->level == 3) {
  6806. $this->finished = true;
  6807. }
  6808. //Clear things
  6809. $this->tree[$this->level] = "";
  6810. $this->level--;
  6811. $this->content = "";
  6812. }
  6813. //This is the endTag handler we use where we are reading the modules zone (todo="MODULES")
  6814. function endElementModules($parser, $tagName) {
  6815. //Check if we are into MODULES zone
  6816. if ($this->tree[3] == "MODULES") {
  6817. //if (trim($this->content)) //Debug
  6818. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6819. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  6820. //Acumulate data to info (content + close tag)
  6821. //Reconvert: strip htmlchars again and trim to generate xml data
  6822. if (!isset($this->temp)) {
  6823. $this->temp = "";
  6824. }
  6825. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6826. //If we've finished a mod, xmlize it an save to db
  6827. if (($this->level == 4) and ($tagName == "MOD")) {
  6828. //Only process the module if efectively it has been selected for restore. MDL-18482
  6829. if (empty($this->preferences->mods[$this->temp_mod_type]->granular) // We don't care about per instance, i.e. restore all instances.
  6830. or (array_key_exists($this->temp_mod_id, $this->preferences->mods[$this->temp_mod_type]->instances)
  6831. and
  6832. !empty($this->preferences->mods[$this->temp_mod_type]->instances[$this->temp_mod_id]->restore))) {
  6833. //Prepend XML standard header to info gathered
  6834. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6835. //Call to xmlize for this portion of xml data (one MOD)
  6836. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6837. $data = xmlize($xml_data,0);
  6838. //echo strftime ("%X",time())."<p>"; //Debug
  6839. //traverse_xmlize($data); //Debug
  6840. //print_object ($GLOBALS['traverse_array']); //Debug
  6841. //$GLOBALS['traverse_array']=""; //Debug
  6842. //Now, save data to db. We'll use it later
  6843. //Get id and modtype from data
  6844. $mod_id = $data["MOD"]["#"]["ID"]["0"]["#"];
  6845. $mod_type = $data["MOD"]["#"]["MODTYPE"]["0"]["#"];
  6846. //Only if we've selected to restore it
  6847. if (!empty($this->preferences->mods[$mod_type]->restore)) {
  6848. //Save to db
  6849. $status = backup_putid($this->preferences->backup_unique_code,$mod_type,$mod_id,
  6850. null,$data);
  6851. //echo "<p>id: ".$mod_id."-".$mod_type." len.: ".strlen($sla_mod_temp)." to_db: ".$status."<p>"; //Debug
  6852. //Create returning info
  6853. $ret_info = new object();
  6854. $ret_info->id = $mod_id;
  6855. $ret_info->modtype = $mod_type;
  6856. $this->info[] = $ret_info;
  6857. }
  6858. } else {
  6859. debugging("Info: skipping $this->temp_mod_type activity with mod id: $this->temp_mod_id. Not selected for restore", DEBUG_DEVELOPER);
  6860. }
  6861. //Reset current mod_type and mod_id
  6862. unset($this->temp_mod_type);
  6863. unset($this->temp_mod_id);
  6864. //Reset temp
  6865. unset($this->temp);
  6866. }
  6867. /// Grab current mod id and type when available
  6868. if ($this->level == 5) {
  6869. if ($tagName == 'ID') {
  6870. $this->temp_mod_id = trim($this->content);
  6871. } else if ($tagName == 'MODTYPE') {
  6872. $this->temp_mod_type = trim($this->content);
  6873. }
  6874. }
  6875. }
  6876. //Stop parsing if todo = MODULES and tagName = MODULES (en of the tag, of course)
  6877. //Speed up a lot (avoid parse all)
  6878. if ($tagName == "MODULES" and $this->level == 3) {
  6879. $this->finished = true;
  6880. }
  6881. //Clear things
  6882. $this->tree[$this->level] = "";
  6883. $this->level--;
  6884. $this->content = "";
  6885. }
  6886. //This is the endTag handler we use where we are reading the logs zone (todo="LOGS")
  6887. function endElementLogs($parser, $tagName) {
  6888. //Check if we are into LOGS zone
  6889. if ($this->tree[3] == "LOGS") {
  6890. //if (trim($this->content)) //Debug
  6891. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6892. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  6893. //Acumulate data to info (content + close tag)
  6894. //Reconvert: strip htmlchars again and trim to generate xml data
  6895. if (!isset($this->temp)) {
  6896. $this->temp = "";
  6897. }
  6898. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6899. //If we've finished a log, xmlize it an save to db
  6900. if (($this->level == 4) and ($tagName == "LOG")) {
  6901. //Prepend XML standard header to info gathered
  6902. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6903. //Call to xmlize for this portion of xml data (one LOG)
  6904. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6905. $data = xmlize($xml_data,0);
  6906. //echo strftime ("%X",time())."<p>"; //Debug
  6907. //traverse_xmlize($data); //Debug
  6908. //print_object ($GLOBALS['traverse_array']); //Debug
  6909. //$GLOBALS['traverse_array']=""; //Debug
  6910. //Now, save data to db. We'll use it later
  6911. //Get id and modtype from data
  6912. $log_id = $data["LOG"]["#"]["ID"]["0"]["#"];
  6913. $log_module = $data["LOG"]["#"]["MODULE"]["0"]["#"];
  6914. //We only save log entries from backup file if they are:
  6915. // - Course logs
  6916. // - User logs
  6917. // - Module logs about one restored module
  6918. if ($log_module == "course" or
  6919. $log_module == "user" or
  6920. $this->preferences->mods[$log_module]->restore) {
  6921. //Increment counter
  6922. $this->counter++;
  6923. //Save to db
  6924. $status = backup_putid($this->preferences->backup_unique_code,"log",$log_id,
  6925. null,$data);
  6926. //echo "<p>id: ".$mod_id."-".$mod_type." len.: ".strlen($sla_mod_temp)." to_db: ".$status."<p>"; //Debug
  6927. //Create returning info
  6928. $this->info = $this->counter;
  6929. }
  6930. //Reset temp
  6931. unset($this->temp);
  6932. }
  6933. }
  6934. //Stop parsing if todo = LOGS and tagName = LOGS (en of the tag, of course)
  6935. //Speed up a lot (avoid parse all)
  6936. if ($tagName == "LOGS" and $this->level == 3) {
  6937. $this->finished = true;
  6938. $this->counter = 0;
  6939. }
  6940. //Clear things
  6941. $this->tree[$this->level] = "";
  6942. $this->level--;
  6943. $this->content = "";
  6944. }
  6945. //This is the endTag default handler we use when todo is undefined
  6946. function endElement($parser, $tagName) {
  6947. if (trim($this->content)) //Debug
  6948. echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6949. echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  6950. //Clear things
  6951. $this->tree[$this->level] = "";
  6952. $this->level--;
  6953. $this->content = "";
  6954. }
  6955. //This is the handler to read data contents (simple accumule it)
  6956. function characterData($parser, $data) {
  6957. $this->content .= $data;
  6958. }
  6959. }
  6960. //This function executes the MoodleParser
  6961. function restore_read_xml ($xml_file,$todo,$preferences) {
  6962. global $CFG;
  6963. $status = true;
  6964. /// If enabled in the site, use split files instead of original moodle.xml file
  6965. /// This will speed parsing speed upto 20x.
  6966. if (!empty($CFG->experimentalsplitrestore)) {
  6967. /// Use splite file, else nothing to process (saves one full parsing for each non-existing todo)
  6968. $splitfile= dirname($xml_file) . '/' . strtolower('split_' . $todo . '.xml');
  6969. if (file_exists($splitfile)) {
  6970. $xml_file = $splitfile;
  6971. debugging("Info: todo=$todo, using split file", DEBUG_DEVELOPER);
  6972. } else {
  6973. /// For some todos, that are used in earlier restore steps (restore_precheck(), restore_form...
  6974. /// allow fallback to monolithic moodle.xml. Those todos are at the beggining of the xml, so
  6975. /// it doesn't hurts too much.
  6976. if ($todo == 'INFO' || $todo == 'COURSE_HEADER' || $todo == 'ROLES') {
  6977. debugging("Info: todo=$todo, no split file. Fallback to moodle.xml", DEBUG_DEVELOPER);
  6978. } else {
  6979. debugging("Info: todo=$todo, no split file. Parse skipped", DEBUG_DEVELOPER);
  6980. return true;
  6981. }
  6982. }
  6983. }
  6984. $xml_parser = xml_parser_create('UTF-8');
  6985. $moodle_parser = new MoodleParser();
  6986. $moodle_parser->todo = $todo;
  6987. $moodle_parser->preferences = $preferences;
  6988. xml_set_object($xml_parser,$moodle_parser);
  6989. //Depending of the todo we use some element_handler or another
  6990. if ($todo == "INFO") {
  6991. xml_set_element_handler($xml_parser, "startElementInfo", "endElementInfo");
  6992. } else if ($todo == "ROLES") {
  6993. xml_set_element_handler($xml_parser, "startElementRoles", "endElementRoles");
  6994. } else if ($todo == "COURSE_HEADER") {
  6995. xml_set_element_handler($xml_parser, "startElementCourseHeader", "endElementCourseHeader");
  6996. } else if ($todo == 'BLOCKS') {
  6997. xml_set_element_handler($xml_parser, "startElementBlocks", "endElementBlocks");
  6998. } else if ($todo == "SECTIONS") {
  6999. xml_set_element_handler($xml_parser, "startElementSections", "endElementSections");
  7000. } else if ($todo == 'FORMATDATA') {
  7001. xml_set_element_handler($xml_parser, "startElementFormatData", "endElementFormatData");
  7002. } else if ($todo == "METACOURSE") {
  7003. xml_set_element_handler($xml_parser, "startElementMetacourse", "endElementMetacourse");
  7004. } else if ($todo == "GRADEBOOK") {
  7005. if ($preferences->backup_version > 2007090500) {
  7006. xml_set_element_handler($xml_parser, "startElementGradebook", "endElementGradebook");
  7007. } else {
  7008. xml_set_element_handler($xml_parser, "startElementOldGradebook", "endElementOldGradebook");
  7009. }
  7010. } else if ($todo == "USERS") {
  7011. xml_set_element_handler($xml_parser, "startElementUsers", "endElementUsers");
  7012. } else if ($todo == "MESSAGES") {
  7013. xml_set_element_handler($xml_parser, "startElementMessages", "endElementMessages");
  7014. } else if ($todo == "BLOGS") {
  7015. xml_set_element_handler($xml_parser, "startElementBlogs", "endElementBlogs");
  7016. } else if ($todo == "QUESTIONS") {
  7017. xml_set_element_handler($xml_parser, "startElementQuestions", "endElementQuestions");
  7018. } else if ($todo == "SCALES") {
  7019. xml_set_element_handler($xml_parser, "startElementScales", "endElementScales");
  7020. } else if ($todo == "GROUPS") {
  7021. xml_set_element_handler($xml_parser, "startElementGroups", "endElementGroups");
  7022. } else if ($todo == "GROUPINGS") {
  7023. xml_set_element_handler($xml_parser, "startElementGroupings", "endElementGroupings");
  7024. } else if ($todo == "GROUPINGSGROUPS") {
  7025. xml_set_element_handler($xml_parser, "startElementGroupingsGroups", "endElementGroupingsGroups");
  7026. } else if ($todo == "EVENTS") {
  7027. xml_set_element_handler($xml_parser, "startElementEvents", "endElementEvents");
  7028. } else if ($todo == "MODULES") {
  7029. xml_set_element_handler($xml_parser, "startElementModules", "endElementModules");
  7030. } else if ($todo == "LOGS") {
  7031. xml_set_element_handler($xml_parser, "startElementLogs", "endElementLogs");
  7032. } else {
  7033. //Define default handlers (must no be invoked when everything become finished)
  7034. xml_set_element_handler($xml_parser, "startElementInfo", "endElementInfo");
  7035. }
  7036. xml_set_character_data_handler($xml_parser, "characterData");
  7037. $fp = fopen($xml_file,"r")
  7038. or $status = false;
  7039. if ($status) {
  7040. // MDL-9290 performance improvement on reading large xml
  7041. $lasttime = time(); // crmas
  7042. while ($data = fread($fp, 8192) and !$moodle_parser->finished) {
  7043. if ((time() - $lasttime) > 5) {
  7044. $lasttime = time();
  7045. backup_flush(1);
  7046. }
  7047. xml_parse($xml_parser, $data, feof($fp))
  7048. or die(sprintf("XML error: %s at line %d",
  7049. xml_error_string(xml_get_error_code($xml_parser)),
  7050. xml_get_current_line_number($xml_parser)));
  7051. }
  7052. fclose($fp);
  7053. }
  7054. //Get info from parser
  7055. $info = $moodle_parser->info;
  7056. //Clear parser mem
  7057. xml_parser_free($xml_parser);
  7058. if ($status && !empty($info)) {
  7059. return $info;
  7060. } else {
  7061. return $status;
  7062. }
  7063. }
  7064. /**
  7065. * @param string $errorstr passed by reference, if silent is true,
  7066. * errorstr will be populated and this function will return false rather than calling error() or notify()
  7067. * @param boolean $noredirect (optional) if this is passed, this function will not print continue, or
  7068. * redirect to the next step in the restore process, instead will return $backup_unique_code
  7069. */
  7070. function restore_precheck($id,$file,&$errorstr,$noredirect=false) {
  7071. global $CFG, $SESSION;
  7072. //Prepend dataroot to variable to have the absolute path
  7073. $file = $CFG->dataroot."/".$file;
  7074. if (!defined('RESTORE_SILENTLY')) {
  7075. //Start the main table
  7076. echo "<table cellpadding=\"5\">";
  7077. echo "<tr><td>";
  7078. //Start the mail ul
  7079. echo "<ul>";
  7080. }
  7081. //Check the file exists
  7082. if (!is_file($file)) {
  7083. if (!defined('RESTORE_SILENTLY')) {
  7084. error ("File not exists ($file)");
  7085. } else {
  7086. $errorstr = "File not exists ($file)";
  7087. return false;
  7088. }
  7089. }
  7090. //Check the file name ends with .zip
  7091. if (!substr($file,-4) == ".zip") {
  7092. if (!defined('RESTORE_SILENTLY')) {
  7093. error ("File has an incorrect extension");
  7094. } else {
  7095. $errorstr = 'File has an incorrect extension';
  7096. return false;
  7097. }
  7098. }
  7099. //Now calculate the unique_code for this restore
  7100. $backup_unique_code = time();
  7101. //Now check and create the backup dir (if it doesn't exist)
  7102. if (!defined('RESTORE_SILENTLY')) {
  7103. echo "<li>".get_string("creatingtemporarystructures").'</li>';
  7104. }
  7105. $status = check_and_create_backup_dir($backup_unique_code);
  7106. //Empty dir
  7107. if ($status) {
  7108. $status = clear_backup_dir($backup_unique_code);
  7109. }
  7110. //Now delete old data and directories under dataroot/temp/backup
  7111. if ($status) {
  7112. if (!defined('RESTORE_SILENTLY')) {
  7113. echo "<li>".get_string("deletingolddata").'</li>';
  7114. }
  7115. $status = backup_delete_old_data();
  7116. }
  7117. //Now copy he zip file to dataroot/temp/backup/backup_unique_code
  7118. if ($status) {
  7119. if (!defined('RESTORE_SILENTLY')) {
  7120. echo "<li>".get_string("copyingzipfile").'</li>';
  7121. }
  7122. if (! $status = backup_copy_file($file,$CFG->dataroot."/temp/backup/".$backup_unique_code."/".basename($file))) {
  7123. if (!defined('RESTORE_SILENTLY')) {
  7124. notify("Error copying backup file. Invalid name or bad perms.");
  7125. } else {
  7126. $errorstr = "Error copying backup file. Invalid name or bad perms";
  7127. return false;
  7128. }
  7129. }
  7130. }
  7131. //Now unzip the file
  7132. if ($status) {
  7133. if (!defined('RESTORE_SILENTLY')) {
  7134. echo "<li>".get_string("unzippingbackup").'</li>';
  7135. }
  7136. if (! $status = restore_unzip ($CFG->dataroot."/temp/backup/".$backup_unique_code."/".basename($file))) {
  7137. if (!defined('RESTORE_SILENTLY')) {
  7138. notify("Error unzipping backup file. Invalid zip file.");
  7139. } else {
  7140. $errorstr = "Error unzipping backup file. Invalid zip file.";
  7141. return false;
  7142. }
  7143. }
  7144. }
  7145. // If experimental option is enabled (enableimsccimport)
  7146. // check for Common Cartridge packages and convert to Moodle format
  7147. if ($status && isset($CFG->enableimsccimport) && $CFG->enableimsccimport == 1) {
  7148. require_once($CFG->dirroot. '/backup/cc/restore_cc.php');
  7149. if (!defined('RESTORE_SILENTLY')) {
  7150. echo "<li>".get_string('checkingforimscc', 'imscc').'</li>';
  7151. }
  7152. $status = cc_convert($CFG->dataroot. DIRECTORY_SEPARATOR .'temp'. DIRECTORY_SEPARATOR . 'backup'. DIRECTORY_SEPARATOR . $backup_unique_code);
  7153. }
  7154. //Check for Blackboard backups and convert
  7155. if ($status){
  7156. require_once("$CFG->dirroot/backup/bb/restore_bb.php");
  7157. if (!defined('RESTORE_SILENTLY')) {
  7158. echo "<li>".get_string("checkingforbbexport").'</li>';
  7159. }
  7160. $status = blackboard_convert($CFG->dataroot."/temp/backup/".$backup_unique_code);
  7161. }
  7162. //Now check for the moodle.xml file
  7163. if ($status) {
  7164. $xml_file = $CFG->dataroot."/temp/backup/".$backup_unique_code."/moodle.xml";
  7165. if (!defined('RESTORE_SILENTLY')) {
  7166. echo "<li>".get_string("checkingbackup").'</li>';
  7167. }
  7168. if (! $status = restore_check_moodle_file ($xml_file)) {
  7169. if (!is_file($xml_file)) {
  7170. $errorstr = 'Error checking backup file. moodle.xml not found at root level of zip file.';
  7171. } else {
  7172. $errorstr = 'Error checking backup file. moodle.xml is incorrect or corrupted.';
  7173. }
  7174. if (!defined('RESTORE_SILENTLY')) {
  7175. notify($errorstr);
  7176. } else {
  7177. return false;
  7178. }
  7179. }
  7180. }
  7181. $info = "";
  7182. $course_header = "";
  7183. //Now read the info tag (all)
  7184. if ($status) {
  7185. if (!defined('RESTORE_SILENTLY')) {
  7186. echo "<li>".get_string("readinginfofrombackup").'</li>';
  7187. }
  7188. //Reading info from file
  7189. $info = restore_read_xml_info ($xml_file);
  7190. //Reading course_header from file
  7191. $course_header = restore_read_xml_course_header ($xml_file);
  7192. if(!is_object($course_header)){
  7193. // ensure we fail if there is no course header
  7194. $course_header = false;
  7195. }
  7196. }
  7197. if (!defined('RESTORE_SILENTLY')) {
  7198. //End the main ul
  7199. echo "</ul>\n";
  7200. //End the main table
  7201. echo "</td></tr>";
  7202. echo "</table>";
  7203. }
  7204. //We compare Moodle's versions
  7205. if ($status && $CFG->version < $info->backup_moodle_version) {
  7206. $message = new object();
  7207. $message->serverversion = $CFG->version;
  7208. $message->serverrelease = $CFG->release;
  7209. $message->backupversion = $info->backup_moodle_version;
  7210. $message->backuprelease = $info->backup_moodle_release;
  7211. print_simple_box(get_string('noticenewerbackup','',$message), "center", "70%", '', "20", "noticebox");
  7212. }
  7213. //Now we print in other table, the backup and the course it contains info
  7214. if ($info and $course_header and $status) {
  7215. //First, the course info
  7216. if (!defined('RESTORE_SILENTLY')) {
  7217. $status = restore_print_course_header($course_header);
  7218. }
  7219. //Now, the backup info
  7220. if ($status) {
  7221. if (!defined('RESTORE_SILENTLY')) {
  7222. $status = restore_print_info($info);
  7223. }
  7224. }
  7225. }
  7226. //Save course header and info into php session
  7227. if ($status) {
  7228. $SESSION->info = $info;
  7229. $SESSION->course_header = $course_header;
  7230. }
  7231. //Finally, a little form to continue
  7232. //with some hidden fields
  7233. if ($status) {
  7234. if (!defined('RESTORE_SILENTLY')) {
  7235. echo "<br /><div style='text-align:center'>";
  7236. $hidden["backup_unique_code"] = $backup_unique_code;
  7237. $hidden["launch"] = "form";
  7238. $hidden["file"] = $file;
  7239. $hidden["id"] = $id;
  7240. print_single_button("restore.php", $hidden, get_string("continue"),"post");
  7241. echo "</div>";
  7242. }
  7243. else {
  7244. if (empty($noredirect)) {
  7245. print_continue($CFG->wwwroot.'/backup/restore.php?backup_unique_code='.$backup_unique_code.'&launch=form&file='.$file.'&id='.$id.'&sesskey='.sesskey());
  7246. print_footer();
  7247. die;
  7248. } else {
  7249. return $backup_unique_code;
  7250. }
  7251. }
  7252. }
  7253. if (!$status) {
  7254. if (!defined('RESTORE_SILENTLY')) {
  7255. error ("An error has ocurred");
  7256. } else {
  7257. $errorstr = "An error has occured"; // helpful! :P
  7258. return false;
  7259. }
  7260. }
  7261. return true;
  7262. }
  7263. function restore_setup_for_check(&$restore,$backup_unique_code) {
  7264. global $SESSION;
  7265. $restore->backup_unique_code=$backup_unique_code;
  7266. $restore->users = 2; // yuk
  7267. // we set these from restore object on silent restore and from info (backup) object on import
  7268. $restore->course_files = isset($SESSION->restore->restore_course_files) ? $SESSION->restore->restore_course_files : $SESSION->info->backup_course_files;
  7269. $restore->site_files = isset($SESSION->restore->restore_site_files) ? $SESSION->restore->restore_site_files : $SESSION->info->backup_site_files;
  7270. if ($allmods = get_records("modules")) {
  7271. foreach ($allmods as $mod) {
  7272. $modname = $mod->name;
  7273. $var = "restore_".$modname;
  7274. //Now check that we have that module info in the backup file
  7275. if (isset($SESSION->info->mods[$modname]) && $SESSION->info->mods[$modname]->backup == "true") {
  7276. $restore->$var = 1;
  7277. }
  7278. }
  7279. }
  7280. // Calculate all session objects checksum and store them in session too
  7281. // so restore_execute.html (used by manual restore and import) will be
  7282. // able to detect any problem in session info.
  7283. restore_save_session_object_checksums($restore, $SESSION->info, $SESSION->course_header);
  7284. return true;
  7285. }
  7286. /**
  7287. * Save the checksum of the 3 main in-session restore objects (restore, info, course_header)
  7288. * so restore_execute.html will be able to check that all them have arrived correctly, without
  7289. * losing data for any type of session size limit/error. MDL-18469. Used both by manual restore
  7290. * and import
  7291. */
  7292. function restore_save_session_object_checksums($restore, $info, $course_header) {
  7293. global $SESSION;
  7294. $restore_checksums = array();
  7295. $restore_checksums['info'] = md5(serialize($info));
  7296. $restore_checksums['course_header'] = md5(serialize($course_header));
  7297. $restore_checksums['restore'] = md5(serialize($restore));
  7298. $SESSION->restore_checksums = $restore_checksums;
  7299. }
  7300. function backup_to_restore_array($backup,$k=0) {
  7301. if (is_array($backup) ) {
  7302. $restore = array();
  7303. foreach ($backup as $key => $value) {
  7304. $newkey = str_replace('backup','restore',$key);
  7305. $restore[$newkey] = backup_to_restore_array($value,$key);
  7306. }
  7307. }
  7308. else if (is_object($backup)) {
  7309. $restore = new stdClass();
  7310. $tmp = get_object_vars($backup);
  7311. foreach ($tmp as $key => $value) {
  7312. $newkey = str_replace('backup','restore',$key);
  7313. $restore->$newkey = backup_to_restore_array($value,$key);
  7314. }
  7315. }
  7316. else {
  7317. $newkey = str_replace('backup','restore',$k);
  7318. $restore = $backup;
  7319. }
  7320. return $restore;
  7321. }
  7322. /**
  7323. * compatibility function
  7324. * checks for per-instance backups AND
  7325. * older per-module backups
  7326. * and returns whether userdata has been selected.
  7327. */
  7328. function restore_userdata_selected($restore,$modname,$modid) {
  7329. // check first for per instance array
  7330. if (!empty($restore->mods[$modname]->granular)) { // supports per instance
  7331. return array_key_exists($modid,$restore->mods[$modname]->instances)
  7332. && !empty($restore->mods[$modname]->instances[$modid]->userinfo);
  7333. }
  7334. //print_object($restore->mods[$modname]);
  7335. return !empty($restore->mods[$modname]->userinfo);
  7336. }
  7337. function restore_execute(&$restore,$info,$course_header,&$errorstr) {
  7338. global $CFG, $USER;
  7339. $status = true;
  7340. //Checks for the required files/functions to restore every module
  7341. //and include them
  7342. if ($allmods = get_records("modules") ) {
  7343. foreach ($allmods as $mod) {
  7344. $modname = $mod->name;
  7345. $modfile = "$CFG->dirroot/mod/$modname/restorelib.php";
  7346. //If file exists and we have selected to restore that type of module
  7347. if ((file_exists($modfile)) and !empty($restore->mods[$modname]) and ($restore->mods[$modname]->restore)) {
  7348. include_once($modfile);
  7349. }
  7350. }
  7351. }
  7352. if (!defined('RESTORE_SILENTLY')) {
  7353. //Start the main table
  7354. echo "<table cellpadding=\"5\">";
  7355. echo "<tr><td>";
  7356. //Start the main ul
  7357. echo "<ul>";
  7358. }
  7359. //Location of the xml file
  7360. $xml_file = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/moodle.xml";
  7361. // Re-assure xml file is in place before any further process
  7362. if (! $status = restore_check_moodle_file($xml_file)) {
  7363. if (!is_file($xml_file)) {
  7364. $errorstr = 'Error checking backup file. moodle.xml not found. Session problem?';
  7365. } else {
  7366. $errorstr = 'Error checking backup file. moodle.xml is incorrect or corrupted. Session problem?';
  7367. }
  7368. if (!defined('RESTORE_SILENTLY')) {
  7369. notify($errorstr);
  7370. }
  7371. return false;
  7372. }
  7373. //Preprocess the moodle.xml file spliting into smaller chucks (modules, users, logs...)
  7374. //for optimal parsing later in the restore process.
  7375. if (!empty($CFG->experimentalsplitrestore)) {
  7376. if (!defined('RESTORE_SILENTLY')) {
  7377. echo '<li>'.get_string('preprocessingbackupfile') . '</li>';
  7378. }
  7379. //First of all, split moodle.xml into handy files
  7380. if (!restore_split_xml ($xml_file, $restore)) {
  7381. $errorstr = "Error proccessing moodle.xml file. Process ended.";
  7382. if (!defined('RESTORE_SILENTLY')) {
  7383. notify($errorstr);
  7384. }
  7385. return false;
  7386. }
  7387. }
  7388. // Precheck the users section, detecting various situations that can lead to problems, so
  7389. // we stop restore before performing any further action
  7390. if (!defined('RESTORE_SILENTLY')) {
  7391. echo '<li>'.get_string('restoreusersprecheck').'</li>';
  7392. }
  7393. if (!restore_precheck_users($xml_file, $restore, $problems)) {
  7394. $errorstr = get_string('restoreusersprecheckerror');
  7395. if (!empty($problems)) {
  7396. $errorstr .= ' (' . implode(', ', $problems) . ')';
  7397. }
  7398. if (!defined('RESTORE_SILENTLY')) {
  7399. notify($errorstr);
  7400. }
  7401. return false;
  7402. }
  7403. //If we've selected to restore into new course
  7404. //create it (course)
  7405. //Saving conversion id variables into backup_tables
  7406. if ($restore->restoreto == RESTORETO_NEW_COURSE) {
  7407. if (!defined('RESTORE_SILENTLY')) {
  7408. echo '<li>'.get_string('creatingnewcourse') . '</li>';
  7409. }
  7410. $oldidnumber = $course_header->course_idnumber;
  7411. if (!$status = restore_create_new_course($restore,$course_header)) {
  7412. if (!defined('RESTORE_SILENTLY')) {
  7413. notify("Error while creating the new empty course.");
  7414. } else {
  7415. $errorstr = "Error while creating the new empty course.";
  7416. return false;
  7417. }
  7418. }
  7419. //Print course fullname and shortname and category
  7420. if ($status) {
  7421. if (!defined('RESTORE_SILENTLY')) {
  7422. echo "<ul>";
  7423. echo "<li>".$course_header->course_fullname." (".$course_header->course_shortname.")".'</li>';
  7424. echo "<li>".get_string("category").": ".$course_header->category->name.'</li>';
  7425. if (!empty($oldidnumber)) {
  7426. echo "<li>".get_string("nomoreidnumber","moodle",$oldidnumber)."</li>";
  7427. }
  7428. echo "</ul>";
  7429. //Put the destination course_id
  7430. }
  7431. $restore->course_id = $course_header->course_id;
  7432. }
  7433. if ($status = restore_open_html($restore,$course_header)){
  7434. if (!defined('RESTORE_SILENTLY')) {
  7435. echo "<li>Creating the Restorelog.html in the course backup folder</li>";
  7436. }
  7437. }
  7438. } else {
  7439. $course = get_record("course","id",$restore->course_id);
  7440. if ($course) {
  7441. if (!defined('RESTORE_SILENTLY')) {
  7442. echo "<li>".get_string("usingexistingcourse");
  7443. echo "<ul>";
  7444. echo "<li>".get_string("from").": ".$course_header->course_fullname." (".$course_header->course_shortname.")".'</li>';
  7445. echo "<li>".get_string("to").": ". format_string($course->fullname) ." (".format_string($course->shortname).")".'</li>';
  7446. if (($restore->deleting)) {
  7447. echo "<li>".get_string("deletingexistingcoursedata").'</li>';
  7448. } else {
  7449. echo "<li>".get_string("addingdatatoexisting").'</li>';
  7450. }
  7451. echo "</ul></li>";
  7452. }
  7453. //If we have selected to restore deleting, we do it now.
  7454. if ($restore->deleting) {
  7455. if (!defined('RESTORE_SILENTLY')) {
  7456. echo "<li>".get_string("deletingolddata").'</li>';
  7457. }
  7458. $status = remove_course_contents($restore->course_id,false) and
  7459. delete_dir_contents($CFG->dataroot."/".$restore->course_id,"backupdata");
  7460. if ($status) {
  7461. //Now , this situation is equivalent to the "restore to new course" one (we
  7462. //have a course record and nothing more), so define it as "to new course"
  7463. $restore->restoreto = RESTORETO_NEW_COURSE;
  7464. } else {
  7465. if (!defined('RESTORE_SILENTLY')) {
  7466. notify("An error occurred while deleting some of the course contents.");
  7467. } else {
  7468. $errrostr = "An error occurred while deleting some of the course contents.";
  7469. return false;
  7470. }
  7471. }
  7472. }
  7473. } else {
  7474. if (!defined('RESTORE_SILENTLY')) {
  7475. notify("Error opening existing course.");
  7476. $status = false;
  7477. } else {
  7478. $errorstr = "Error opening existing course.";
  7479. return false;
  7480. }
  7481. }
  7482. }
  7483. //Now create users as needed
  7484. if ($status and ($restore->users == 0 or $restore->users == 1)) {
  7485. if (!defined('RESTORE_SILENTLY')) {
  7486. echo "<li>".get_string("creatingusers")."<br />";
  7487. }
  7488. if (!$status = restore_create_users($restore,$xml_file)) {
  7489. if (!defined('RESTORE_SILENTLY')) {
  7490. notify("Could not restore users.");
  7491. } else {
  7492. $errorstr = "Could not restore users.";
  7493. return false;
  7494. }
  7495. }
  7496. //Now print info about the work done
  7497. if ($status) {
  7498. $recs = get_records_sql("select old_id, new_id from {$CFG->prefix}backup_ids
  7499. where backup_code = '$restore->backup_unique_code' and
  7500. table_name = 'user'");
  7501. //We've records
  7502. if ($recs) {
  7503. $new_count = 0;
  7504. $exists_count = 0;
  7505. $student_count = 0;
  7506. $teacher_count = 0;
  7507. $counter = 0;
  7508. //Iterate, filling counters
  7509. foreach ($recs as $rec) {
  7510. //Get full record, using backup_getids
  7511. $record = backup_getid($restore->backup_unique_code,"user",$rec->old_id);
  7512. if (strpos($record->info,"new") !== false) {
  7513. $new_count++;
  7514. }
  7515. if (strpos($record->info,"exists") !== false) {
  7516. $exists_count++;
  7517. }
  7518. if (strpos($record->info,"student") !== false) {
  7519. $student_count++;
  7520. } else if (strpos($record->info,"teacher") !== false) {
  7521. $teacher_count++;
  7522. }
  7523. //Do some output
  7524. $counter++;
  7525. if ($counter % 10 == 0) {
  7526. if (!defined('RESTORE_SILENTLY')) {
  7527. echo ".";
  7528. if ($counter % 200 == 0) {
  7529. echo "<br />";
  7530. }
  7531. }
  7532. backup_flush(300);
  7533. }
  7534. }
  7535. if (!defined('RESTORE_SILENTLY')) {
  7536. //Now print information gathered
  7537. echo " (".get_string("new").": ".$new_count.", ".get_string("existing").": ".$exists_count.")";
  7538. echo "<ul>";
  7539. echo "<li>".get_string("students").": ".$student_count.'</li>';
  7540. echo "<li>".get_string("teachers").": ".$teacher_count.'</li>';
  7541. echo "</ul>";
  7542. }
  7543. } else {
  7544. if (!defined('RESTORE_SILENTLY')) {
  7545. notify("No users were found!");
  7546. } // no need to return false here, it's recoverable.
  7547. }
  7548. }
  7549. if (!defined('RESTORE_SILENTLY')) {
  7550. echo "</li>";
  7551. }
  7552. }
  7553. //Now create groups as needed
  7554. if ($status and ($restore->groups == RESTORE_GROUPS_ONLY or $restore->groups == RESTORE_GROUPS_GROUPINGS)) {
  7555. if (!defined('RESTORE_SILENTLY')) {
  7556. echo "<li>".get_string("creatinggroups");
  7557. }
  7558. if (!$status = restore_create_groups($restore,$xml_file)) {
  7559. if (!defined('RESTORE_SILENTLY')) {
  7560. notify("Could not restore groups!");
  7561. } else {
  7562. $errorstr = "Could not restore groups!";
  7563. return false;
  7564. }
  7565. }
  7566. if (!defined('RESTORE_SILENTLY')) {
  7567. echo '</li>';
  7568. }
  7569. }
  7570. //Now create groupings as needed
  7571. if ($status and ($restore->groups == RESTORE_GROUPINGS_ONLY or $restore->groups == RESTORE_GROUPS_GROUPINGS)) {
  7572. if (!defined('RESTORE_SILENTLY')) {
  7573. echo "<li>".get_string("creatinggroupings");
  7574. }
  7575. if (!$status = restore_create_groupings($restore,$xml_file)) {
  7576. if (!defined('RESTORE_SILENTLY')) {
  7577. notify("Could not restore groupings!");
  7578. } else {
  7579. $errorstr = "Could not restore groupings!";
  7580. return false;
  7581. }
  7582. }
  7583. if (!defined('RESTORE_SILENTLY')) {
  7584. echo '</li>';
  7585. }
  7586. }
  7587. //Now create groupingsgroups as needed
  7588. if ($status and $restore->groups == RESTORE_GROUPS_GROUPINGS) {
  7589. if (!defined('RESTORE_SILENTLY')) {
  7590. echo "<li>".get_string("creatinggroupingsgroups");
  7591. }
  7592. if (!$status = restore_create_groupings_groups($restore,$xml_file)) {
  7593. if (!defined('RESTORE_SILENTLY')) {
  7594. notify("Could not restore groups in groupings!");
  7595. } else {
  7596. $errorstr = "Could not restore groups in groupings!";
  7597. return false;
  7598. }
  7599. }
  7600. if (!defined('RESTORE_SILENTLY')) {
  7601. echo '</li>';
  7602. }
  7603. }
  7604. //Now create the course_sections and their associated course_modules
  7605. //we have to do this after groups and groupings are restored, because we need the new groupings id
  7606. if ($status) {
  7607. //Into new course
  7608. if ($restore->restoreto == RESTORETO_NEW_COURSE) {
  7609. if (!defined('RESTORE_SILENTLY')) {
  7610. echo "<li>".get_string("creatingsections");
  7611. }
  7612. if (!$status = restore_create_sections($restore,$xml_file)) {
  7613. if (!defined('RESTORE_SILENTLY')) {
  7614. notify("Error creating sections in the existing course.");
  7615. } else {
  7616. $errorstr = "Error creating sections in the existing course.";
  7617. return false;
  7618. }
  7619. }
  7620. if (!defined('RESTORE_SILENTLY')) {
  7621. echo '</li>';
  7622. }
  7623. //Into existing course
  7624. } else if ($restore->restoreto != RESTORETO_NEW_COURSE) {
  7625. if (!defined('RESTORE_SILENTLY')) {
  7626. echo "<li>".get_string("checkingsections");
  7627. }
  7628. if (!$status = restore_create_sections($restore,$xml_file)) {
  7629. if (!defined('RESTORE_SILENTLY')) {
  7630. notify("Error creating sections in the existing course.");
  7631. } else {
  7632. $errorstr = "Error creating sections in the existing course.";
  7633. return false;
  7634. }
  7635. }
  7636. if (!defined('RESTORE_SILENTLY')) {
  7637. echo '</li>';
  7638. }
  7639. //Error
  7640. } else {
  7641. if (!defined('RESTORE_SILENTLY')) {
  7642. notify("Neither a new course or an existing one was specified.");
  7643. $status = false;
  7644. } else {
  7645. $errorstr = "Neither a new course or an existing one was specified.";
  7646. return false;
  7647. }
  7648. }
  7649. }
  7650. //Now create metacourse info
  7651. if ($status and $restore->metacourse) {
  7652. //Only to new courses!
  7653. if ($restore->restoreto == RESTORETO_NEW_COURSE) {
  7654. if (!defined('RESTORE_SILENTLY')) {
  7655. echo "<li>".get_string("creatingmetacoursedata");
  7656. }
  7657. if (!$status = restore_create_metacourse($restore,$xml_file)) {
  7658. if (!defined('RESTORE_SILENTLY')) {
  7659. notify("Error creating metacourse in the course.");
  7660. } else {
  7661. $errorstr = "Error creating metacourse in the course.";
  7662. return false;
  7663. }
  7664. }
  7665. if (!defined('RESTORE_SILENTLY')) {
  7666. echo '</li>';
  7667. }
  7668. }
  7669. }
  7670. //Now create categories and questions as needed
  7671. if ($status) {
  7672. include_once("$CFG->dirroot/question/restorelib.php");
  7673. if (!defined('RESTORE_SILENTLY')) {
  7674. echo "<li>".get_string("creatingcategoriesandquestions");
  7675. echo "<ul>";
  7676. }
  7677. if (!$status = restore_create_questions($restore,$xml_file)) {
  7678. if (!defined('RESTORE_SILENTLY')) {
  7679. notify("Could not restore categories and questions!");
  7680. } else {
  7681. $errorstr = "Could not restore categories and questions!";
  7682. return false;
  7683. }
  7684. }
  7685. if (!defined('RESTORE_SILENTLY')) {
  7686. echo "</ul></li>";
  7687. }
  7688. }
  7689. //Now create user_files as needed
  7690. if ($status and ($restore->user_files)) {
  7691. if (!defined('RESTORE_SILENTLY')) {
  7692. echo "<li>".get_string("copyinguserfiles");
  7693. }
  7694. if (!$status = restore_user_files($restore)) {
  7695. if (!defined('RESTORE_SILENTLY')) {
  7696. notify("Could not restore user files!");
  7697. } else {
  7698. $errorstr = "Could not restore user files!";
  7699. return false;
  7700. }
  7701. }
  7702. //If all is ok (and we have a counter)
  7703. if ($status and ($status !== true)) {
  7704. //Inform about user dirs created from backup
  7705. if (!defined('RESTORE_SILENTLY')) {
  7706. echo "<ul>";
  7707. echo "<li>".get_string("userzones").": ".$status;
  7708. echo "</li></ul>";
  7709. }
  7710. }
  7711. if (!defined('RESTORE_SILENTLY')) {
  7712. echo '</li>';
  7713. }
  7714. }
  7715. //Now create course files as needed
  7716. if ($status and ($restore->course_files)) {
  7717. if (!defined('RESTORE_SILENTLY')) {
  7718. echo "<li>".get_string("copyingcoursefiles");
  7719. }
  7720. if (!$status = restore_course_files($restore)) {
  7721. if (empty($status)) {
  7722. notify("Could not restore course files!");
  7723. } else {
  7724. $errorstr = "Could not restore course files!";
  7725. return false;
  7726. }
  7727. }
  7728. //If all is ok (and we have a counter)
  7729. if ($status and ($status !== true)) {
  7730. //Inform about user dirs created from backup
  7731. if (!defined('RESTORE_SILENTLY')) {
  7732. echo "<ul>";
  7733. echo "<li>".get_string("filesfolders").": ".$status.'</li>';
  7734. echo "</ul>";
  7735. }
  7736. }
  7737. if (!defined('RESTORE_SILENTLY')) {
  7738. echo "</li>";
  7739. }
  7740. }
  7741. //Now create site files as needed
  7742. if ($status and ($restore->site_files)) {
  7743. if (!defined('RESTORE_SILENTLY')) {
  7744. echo "<li>".get_string('copyingsitefiles');
  7745. }
  7746. if (!$status = restore_site_files($restore)) {
  7747. if (empty($status)) {
  7748. notify("Could not restore site files!");
  7749. } else {
  7750. $errorstr = "Could not restore site files!";
  7751. return false;
  7752. }
  7753. }
  7754. //If all is ok (and we have a counter)
  7755. if ($status and ($status !== true)) {
  7756. //Inform about user dirs created from backup
  7757. if (!defined('RESTORE_SILENTLY')) {
  7758. echo "<ul>";
  7759. echo "<li>".get_string("filesfolders").": ".$status.'</li>';
  7760. echo "</ul>";
  7761. }
  7762. }
  7763. if (!defined('RESTORE_SILENTLY')) {
  7764. echo "</li>";
  7765. }
  7766. }
  7767. //Now create messages as needed
  7768. if ($status and ($restore->messages)) {
  7769. if (!defined('RESTORE_SILENTLY')) {
  7770. echo "<li>".get_string("creatingmessagesinfo");
  7771. }
  7772. if (!$status = restore_create_messages($restore,$xml_file)) {
  7773. if (!defined('RESTORE_SILENTLY')) {
  7774. notify("Could not restore messages!");
  7775. } else {
  7776. $errorstr = "Could not restore messages!";
  7777. return false;
  7778. }
  7779. }
  7780. if (!defined('RESTORE_SILENTLY')) {
  7781. echo "</li>";
  7782. }
  7783. }
  7784. //Now create blogs as needed
  7785. if ($status and ($restore->blogs)) {
  7786. if (!defined('RESTORE_SILENTLY')) {
  7787. echo "<li>".get_string("creatingblogsinfo");
  7788. }
  7789. if (!$status = restore_create_blogs($restore,$xml_file)) {
  7790. if (!defined('RESTORE_SILENTLY')) {
  7791. notify("Could not restore blogs!");
  7792. } else {
  7793. $errorstr = "Could not restore blogs!";
  7794. return false;
  7795. }
  7796. }
  7797. if (!defined('RESTORE_SILENTLY')) {
  7798. echo "</li>";
  7799. }
  7800. }
  7801. //Now create scales as needed
  7802. if ($status) {
  7803. if (!defined('RESTORE_SILENTLY')) {
  7804. echo "<li>".get_string("creatingscales");
  7805. }
  7806. if (!$status = restore_create_scales($restore,$xml_file)) {
  7807. if (!defined('RESTORE_SILENTLY')) {
  7808. notify("Could not restore custom scales!");
  7809. } else {
  7810. $errorstr = "Could not restore custom scales!";
  7811. return false;
  7812. }
  7813. }
  7814. if (!defined('RESTORE_SILENTLY')) {
  7815. echo '</li>';
  7816. }
  7817. }
  7818. //Now create events as needed
  7819. if ($status) {
  7820. if (!defined('RESTORE_SILENTLY')) {
  7821. echo "<li>".get_string("creatingevents");
  7822. }
  7823. if (!$status = restore_create_events($restore,$xml_file)) {
  7824. if (!defined('RESTORE_SILENTLY')) {
  7825. notify("Could not restore course events!");
  7826. } else {
  7827. $errorstr = "Could not restore course events!";
  7828. return false;
  7829. }
  7830. }
  7831. if (!defined('RESTORE_SILENTLY')) {
  7832. echo '</li>';
  7833. }
  7834. }
  7835. //Now create course modules as needed
  7836. if ($status) {
  7837. if (!defined('RESTORE_SILENTLY')) {
  7838. echo "<li>".get_string("creatingcoursemodules");
  7839. }
  7840. if (!$status = restore_create_modules($restore,$xml_file)) {
  7841. if (!defined('RESTORE_SILENTLY')) {
  7842. notify("Could not restore modules!");
  7843. } else {
  7844. $errorstr = "Could not restore modules!";
  7845. return false;
  7846. }
  7847. }
  7848. if (!defined('RESTORE_SILENTLY')) {
  7849. echo '</li>';
  7850. }
  7851. }
  7852. //Bring back the course blocks -- do it AFTER the modules!!!
  7853. if ($status) {
  7854. //If we are deleting and bringing into a course or making a new course, same situation
  7855. if ($restore->restoreto == RESTORETO_CURRENT_DELETING ||
  7856. $restore->restoreto == RESTORETO_EXISTING_DELETING ||
  7857. $restore->restoreto == RESTORETO_NEW_COURSE) {
  7858. if (!defined('RESTORE_SILENTLY')) {
  7859. echo '<li>'.get_string('creatingblocks');
  7860. }
  7861. $course_header->blockinfo = !empty($course_header->blockinfo) ? $course_header->blockinfo : NULL;
  7862. if (!$status = restore_create_blocks($restore, $info->backup_block_format, $course_header->blockinfo, $xml_file)) {
  7863. if (!defined('RESTORE_SILENTLY')) {
  7864. notify('Error while creating the course blocks');
  7865. } else {
  7866. $errorstr = "Error while creating the course blocks";
  7867. return false;
  7868. }
  7869. }
  7870. if (!defined('RESTORE_SILENTLY')) {
  7871. echo '</li>';
  7872. }
  7873. }
  7874. }
  7875. if ($status) {
  7876. //If we are deleting and bringing into a course or making a new course, same situation
  7877. if ($restore->restoreto == RESTORETO_CURRENT_DELETING ||
  7878. $restore->restoreto == RESTORETO_EXISTING_DELETING ||
  7879. $restore->restoreto == RESTORETO_NEW_COURSE) {
  7880. if (!defined('RESTORE_SILENTLY')) {
  7881. echo '<li>'.get_string('courseformatdata');
  7882. }
  7883. if (!$status = restore_set_format_data($restore, $xml_file)) {
  7884. $error = "Error while setting the course format data";
  7885. if (!defined('RESTORE_SILENTLY')) {
  7886. notify($error);
  7887. } else {
  7888. $errorstr=$error;
  7889. return false;
  7890. }
  7891. }
  7892. if (!defined('RESTORE_SILENTLY')) {
  7893. echo '</li>';
  7894. }
  7895. }
  7896. }
  7897. //Now create log entries as needed
  7898. if ($status and ($info->backup_logs == 'true' && $restore->logs)) {
  7899. if (!defined('RESTORE_SILENTLY')) {
  7900. echo "<li>".get_string("creatinglogentries");
  7901. }
  7902. if (!$status = restore_create_logs($restore,$xml_file)) {
  7903. if (!defined('RESTORE_SILENTLY')) {
  7904. notify("Could not restore logs!");
  7905. } else {
  7906. $errorstr = "Could not restore logs!";
  7907. return false;
  7908. }
  7909. }
  7910. if (!defined('RESTORE_SILENTLY')) {
  7911. echo '</li>';
  7912. }
  7913. }
  7914. //Now, if all is OK, adjust the instance field in course_modules !!
  7915. //this also calculates the final modinfo information so, after this,
  7916. //code needing it can be used (like role_assignments. MDL-13740)
  7917. if ($status) {
  7918. if (!defined('RESTORE_SILENTLY')) {
  7919. echo "<li>".get_string("checkinginstances");
  7920. }
  7921. if (!$status = restore_check_instances($restore)) {
  7922. if (!defined('RESTORE_SILENTLY')) {
  7923. notify("Could not adjust instances in course_modules!");
  7924. } else {
  7925. $errorstr = "Could not adjust instances in course_modules!";
  7926. return false;
  7927. }
  7928. }
  7929. if (!defined('RESTORE_SILENTLY')) {
  7930. echo '</li>';
  7931. }
  7932. }
  7933. //Now, if all is OK, adjust activity events
  7934. if ($status) {
  7935. if (!defined('RESTORE_SILENTLY')) {
  7936. echo "<li>".get_string("refreshingevents");
  7937. }
  7938. if (!$status = restore_refresh_events($restore)) {
  7939. if (!defined('RESTORE_SILENTLY')) {
  7940. notify("Could not refresh events for activities!");
  7941. } else {
  7942. $errorstr = "Could not refresh events for activities!";
  7943. return false;
  7944. }
  7945. }
  7946. if (!defined('RESTORE_SILENTLY')) {
  7947. echo '</li>';
  7948. }
  7949. }
  7950. //Now, if all is OK, adjust inter-activity links
  7951. if ($status) {
  7952. if (!defined('RESTORE_SILENTLY')) {
  7953. echo "<li>".get_string("decodinginternallinks");
  7954. }
  7955. if (!$status = restore_decode_content_links($restore)) {
  7956. if (!defined('RESTORE_SILENTLY')) {
  7957. notify("Could not decode content links!");
  7958. } else {
  7959. $errorstr = "Could not decode content links!";
  7960. return false;
  7961. }
  7962. }
  7963. if (!defined('RESTORE_SILENTLY')) {
  7964. echo '</li>';
  7965. }
  7966. }
  7967. //Now, with backup files prior to version 2005041100,
  7968. //convert all the wiki texts in the course to markdown
  7969. if ($status && $restore->backup_version < 2005041100) {
  7970. if (!defined('RESTORE_SILENTLY')) {
  7971. echo "<li>".get_string("convertingwikitomarkdown");
  7972. }
  7973. if (!$status = restore_convert_wiki2markdown($restore)) {
  7974. if (!defined('RESTORE_SILENTLY')) {
  7975. notify("Could not convert wiki texts to markdown!");
  7976. } else {
  7977. $errorstr = "Could not convert wiki texts to markdown!";
  7978. return false;
  7979. }
  7980. }
  7981. if (!defined('RESTORE_SILENTLY')) {
  7982. echo '</li>';
  7983. }
  7984. }
  7985. //Now create gradebook as needed -- AFTER modules and blocks!!!
  7986. if ($status) {
  7987. if ($restore->backup_version > 2007090500) {
  7988. if (!defined('RESTORE_SILENTLY')) {
  7989. echo "<li>".get_string("creatinggradebook");
  7990. }
  7991. if (!$status = restore_create_gradebook($restore,$xml_file)) {
  7992. if (!defined('RESTORE_SILENTLY')) {
  7993. notify("Could not restore gradebook!");
  7994. } else {
  7995. $errorstr = "Could not restore gradebook!";
  7996. return false;
  7997. }
  7998. }
  7999. if (!defined('RESTORE_SILENTLY')) {
  8000. echo '</li>';
  8001. }
  8002. } else {
  8003. // for moodle versions before 1.9, those grades need to be converted to use the new gradebook
  8004. // this code needs to execute *after* the course_modules are sorted out
  8005. if (!defined('RESTORE_SILENTLY')) {
  8006. echo "<li>".get_string("migratinggrades");
  8007. }
  8008. /// force full refresh of grading data before migration == crete all items first
  8009. if (!$status = restore_migrate_old_gradebook($restore,$xml_file)) {
  8010. if (!defined('RESTORE_SILENTLY')) {
  8011. notify("Could not migrate gradebook!");
  8012. } else {
  8013. $errorstr = "Could not migrade gradebook!";
  8014. return false;
  8015. }
  8016. }
  8017. if (!defined('RESTORE_SILENTLY')) {
  8018. echo '</li>';
  8019. }
  8020. }
  8021. /// force full refresh of grading data after all items are created
  8022. grade_force_full_regrading($restore->course_id);
  8023. grade_grab_course_grades($restore->course_id);
  8024. }
  8025. /*******************************************************************************
  8026. ************* Restore of Roles and Capabilities happens here ******************
  8027. *******************************************************************************/
  8028. // try to restore roles even when restore is going to fail - teachers might have
  8029. // at least some role assigned - this is not correct though
  8030. $status = restore_create_roles($restore, $xml_file) && $status;
  8031. $status = restore_roles_settings($restore, $xml_file) && $status;
  8032. //Now if all is OK, update:
  8033. // - course modinfo field
  8034. // - categories table
  8035. // - add user as teacher
  8036. if ($status) {
  8037. if (!defined('RESTORE_SILENTLY')) {
  8038. echo "<li>".get_string("checkingcourse");
  8039. }
  8040. //categories table
  8041. $course = get_record("course","id",$restore->course_id);
  8042. fix_course_sortorder();
  8043. // Check if the user has course update capability in the newly restored course
  8044. // there is no need to load his capabilities again, because restore_roles_settings
  8045. // would have loaded it anyway, if there is any assignments.
  8046. // fix for MDL-6831
  8047. $newcontext = get_context_instance(CONTEXT_COURSE, $restore->course_id);
  8048. if (!has_capability('moodle/course:manageactivities', $newcontext)) {
  8049. // fix for MDL-9065, use the new config setting if exists
  8050. if ($CFG->creatornewroleid) {
  8051. role_assign($CFG->creatornewroleid, $USER->id, 0, $newcontext->id);
  8052. } else {
  8053. if ($legacyteachers = get_roles_with_capability('moodle/legacy:editingteacher', CAP_ALLOW, get_context_instance(CONTEXT_SYSTEM))) {
  8054. if ($legacyteacher = array_shift($legacyteachers)) {
  8055. role_assign($legacyteacher->id, $USER->id, 0, $newcontext->id);
  8056. }
  8057. } else {
  8058. notify('Could not find a legacy teacher role. You might need your moodle admin to assign a role with editing privilages to this course.');
  8059. }
  8060. }
  8061. }
  8062. if (!defined('RESTORE_SILENTLY')) {
  8063. echo '</li>';
  8064. }
  8065. }
  8066. //Cleanup temps (files and db)
  8067. if ($status) {
  8068. if (!defined('RESTORE_SILENTLY')) {
  8069. echo "<li>".get_string("cleaningtempdata");
  8070. }
  8071. if (!$status = clean_temp_data ($restore)) {
  8072. if (!defined('RESTORE_SILENTLY')) {
  8073. notify("Could not clean up temporary data from files and database");
  8074. } else {
  8075. $errorstr = "Could not clean up temporary data from files and database";
  8076. return false;
  8077. }
  8078. }
  8079. if (!defined('RESTORE_SILENTLY')) {
  8080. echo '</li>';
  8081. }
  8082. }
  8083. // this is not a critical check - the result can be ignored
  8084. if (restore_close_html($restore)){
  8085. if (!defined('RESTORE_SILENTLY')) {
  8086. echo '<li>Closing the Restorelog.html file.</li>';
  8087. }
  8088. }
  8089. else {
  8090. if (!defined('RESTORE_SILENTLY')) {
  8091. notify("Could not close the restorelog.html file");
  8092. }
  8093. }
  8094. if (!defined('RESTORE_SILENTLY')) {
  8095. //End the main ul
  8096. echo "</ul>";
  8097. //End the main table
  8098. echo "</td></tr>";
  8099. echo "</table>";
  8100. }
  8101. return $status;
  8102. }
  8103. //Create, open and write header of the html log file
  8104. function restore_open_html($restore,$course_header) {
  8105. global $CFG;
  8106. $status = true;
  8107. //Open file for writing
  8108. //First, we check the course_id backup data folder exists and create it as necessary in CFG->dataroot
  8109. if (!$dest_dir = make_upload_directory("$restore->course_id/backupdata")) { // Backup folder
  8110. error("Could not create backupdata folder. The site administrator needs to fix the file permissions");
  8111. }
  8112. $status = check_dir_exists($dest_dir,true);
  8113. $restorelog_file = fopen("$dest_dir/restorelog.html","a");
  8114. //Add the stylesheet
  8115. $stylesheetshtml = '';
  8116. foreach ($CFG->stylesheets as $stylesheet) {
  8117. $stylesheetshtml .= '<link rel="stylesheet" type="text/css" href="'.$stylesheet.'" />'."\n";
  8118. }
  8119. ///Accessibility: added the 'lang' attribute to $direction, used in theme <html> tag.
  8120. $languagehtml = get_html_lang($dir=true);
  8121. //Write the header in the new logging file
  8122. fwrite ($restorelog_file,"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"");
  8123. fwrite ($restorelog_file," \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"> ");
  8124. fwrite ($restorelog_file,"<html dir=\"ltr\".$languagehtml.");
  8125. fwrite ($restorelog_file,"<head>");
  8126. fwrite ($restorelog_file,$stylesheetshtml);
  8127. fwrite ($restorelog_file,"<title>".$course_header->course_shortname." Restored </title>");
  8128. fwrite ($restorelog_file,"</head><body><br/><h1>The following changes were made during the Restoration of this Course.</h1><br/><br/>");
  8129. fwrite ($restorelog_file,"The Course ShortName is now - ".$course_header->course_shortname." The FullName is now - ".$course_header->course_fullname."<br/><br/>");
  8130. $startdate = addslashes($course_header->course_startdate);
  8131. $date = usergetdate($startdate);
  8132. fwrite ($restorelog_file,"The Originating Courses Start Date was " .$date['weekday'].", ".$date['mday']." ".$date['month']." ".$date['year']."");
  8133. $startdate += $restore->course_startdateoffset;
  8134. $date = usergetdate($startdate);
  8135. fwrite ($restorelog_file,"&nbsp;&nbsp;&nbsp;This Courses Start Date is now " .$date['weekday'].", ".$date['mday']." ".$date['month']." ".$date['year']."<br/><br/>");
  8136. if ($status) {
  8137. return $restorelog_file;
  8138. } else {
  8139. return false;
  8140. }
  8141. }
  8142. //Create & close footer of the html log file
  8143. function restore_close_html($restore) {
  8144. global $CFG;
  8145. $status = true;
  8146. //Open file for writing
  8147. //First, check that course_id/backupdata folder exists in CFG->dataroot
  8148. $dest_dir = $CFG->dataroot."/".$restore->course_id."/backupdata";
  8149. $status = check_dir_exists($dest_dir, true, true);
  8150. $restorelog_file = fopen("$dest_dir/restorelog.html","a");
  8151. //Write the footer to close the logging file
  8152. fwrite ($restorelog_file,"<br/>This file was written to directly by each modules restore process.");
  8153. fwrite ($restorelog_file,"<br/><br/>Log complete.</body></html>");
  8154. if ($status) {
  8155. return $restorelog_file;
  8156. } else {
  8157. return false;
  8158. }
  8159. }
  8160. /********************** Roles and Capabilities Related Functions *******************************/
  8161. /* Yu: Note recovering of role assignments/overrides need to take place after
  8162. users have been recovered, i.e. after we get their new_id, and after all
  8163. roles have been recreated or mapped. Contexts can be created on the fly.
  8164. The current order of restore is Restore (old) -> restore roles -> restore assignment/overrides
  8165. the order of restore among different contexts, i.e. course, mod, blocks, users should not matter
  8166. once roles and users have been restored.
  8167. */
  8168. /**
  8169. * This function restores all the needed roles for this course
  8170. * i.e. roles with an assignment in any of the mods or blocks,
  8171. * roles assigned on any user (e.g. parent role) and roles
  8172. * assigned at course levle
  8173. * This function should check for duplicate roles first
  8174. * It isn't now, just overwriting
  8175. */
  8176. function restore_create_roles($restore, $xmlfile) {
  8177. global $CFG;
  8178. if (!defined('RESTORE_SILENTLY')) {
  8179. echo "<li>".get_string("creatingrolesdefinitions").'</li>';
  8180. }
  8181. $info = restore_read_xml_roles($xmlfile);
  8182. $sitecontext = get_context_instance(CONTEXT_SYSTEM);
  8183. // the following code creates new roles
  8184. // but we could use more intelligent detection, and role mapping
  8185. // get role mapping info from $restore
  8186. $rolemappings = array();
  8187. if (!empty($restore->rolesmapping)) {
  8188. $rolemappings = $restore->rolesmapping;
  8189. }
  8190. // $info->roles will be empty for backups pre 1.7
  8191. if (isset($info->roles) && $info->roles) {
  8192. foreach ($info->roles as $oldroleid=>$roledata) {
  8193. if (empty($restore->rolesmapping)) {
  8194. // if this is empty altogether, we came from import or there's no roles used in course at all
  8195. // in this case, write the same oldid as this is the same site
  8196. // no need to do mapping
  8197. $status = backup_putid($restore->backup_unique_code,"role",$oldroleid,
  8198. $oldroleid); // adding a new id
  8199. continue; // do not create additonal roles;
  8200. }
  8201. // first we check if the roles are in the mappings
  8202. // if so, we just do a mapping i.e. update oldids table
  8203. if (isset($rolemappings[$oldroleid]) && $rolemappings[$oldroleid]) {
  8204. $status = backup_putid($restore->backup_unique_code,"role",$oldroleid,
  8205. $rolemappings[$oldroleid]); // adding a new id
  8206. // check for permissions before create new roles
  8207. } else if (has_capability('moodle/role:manage', get_context_instance(CONTEXT_SYSTEM))) {
  8208. // code to make new role name/short name if same role name or shortname exists
  8209. $fullname = $roledata->name;
  8210. $shortname = $roledata->shortname;
  8211. $currentfullname = "";
  8212. $currentshortname = "";
  8213. $counter = 0;
  8214. do {
  8215. if ($counter) {
  8216. $suffixfull = " ".get_string("copyasnoun")." ".$counter;
  8217. $suffixshort = "_".$counter;
  8218. } else {
  8219. $suffixfull = "";
  8220. $suffixshort = "";
  8221. }
  8222. $currentfullname = $fullname.$suffixfull;
  8223. // Limit the size of shortname - database column accepts <= 100 chars
  8224. $currentshortname = substr($shortname, 0, 100 - strlen($suffixshort)).$suffixshort;
  8225. $coursefull = get_record("role","name",addslashes($currentfullname));
  8226. $courseshort = get_record("role","shortname",addslashes($currentshortname));
  8227. $counter++;
  8228. } while ($coursefull || $courseshort);
  8229. $roledata->name = $currentfullname;
  8230. $roledata->shortname= $currentshortname;
  8231. // done finding a unique name
  8232. $newroleid = create_role(addslashes($roledata->name),addslashes($roledata->shortname),'');
  8233. $status = backup_putid($restore->backup_unique_code,"role",$oldroleid,
  8234. $newroleid); // adding a new id
  8235. foreach ($roledata->capabilities as $capability) {
  8236. $roleinfo = new object();
  8237. $roleinfo = (object)$capability;
  8238. $roleinfo->contextid = $sitecontext->id;
  8239. $roleinfo->capability = $capability->name;
  8240. $roleinfo->roleid = $newroleid;
  8241. insert_record('role_capabilities', $roleinfo);
  8242. }
  8243. } else {
  8244. // map the new role to course default role
  8245. if (!$default_role = get_field("course", "defaultrole", "id", $restore->course_id)) {
  8246. $default_role = $CFG->defaultcourseroleid;
  8247. }
  8248. $status = backup_putid($restore->backup_unique_code, "role", $oldroleid, $default_role);
  8249. }
  8250. /// Now, restore role nameincourse (only if the role had nameincourse in backup)
  8251. if (!empty($roledata->nameincourse)) {
  8252. $newrole = backup_getid($restore->backup_unique_code, 'role', $oldroleid); /// Look for target role
  8253. $coursecontext = get_context_instance(CONTEXT_COURSE, $restore->course_id); /// Look for target context
  8254. if (!empty($newrole->new_id) && !empty($coursecontext)) {
  8255. /// Check the role hasn't any custom name in context
  8256. if (!record_exists('role_names', 'roleid', $newrole->new_id, 'contextid', $coursecontext->id)) {
  8257. $rolename = new object();
  8258. $rolename->roleid = $newrole->new_id;
  8259. $rolename->contextid = $coursecontext->id;
  8260. $rolename->name = addslashes($roledata->nameincourse);
  8261. insert_record('role_names', $rolename);
  8262. }
  8263. }
  8264. }
  8265. }
  8266. }
  8267. return true;
  8268. }
  8269. /**
  8270. * this function restores role assignments and role overrides
  8271. * in course/user/block/mod level, it passed through
  8272. * the xml file again
  8273. */
  8274. function restore_roles_settings($restore, $xmlfile) {
  8275. // data pulls from course, mod, user, and blocks
  8276. /*******************************************************
  8277. * Restoring from course level assignments *
  8278. *******************************************************/
  8279. if (!defined('RESTORE_SILENTLY')) {
  8280. echo "<li>".get_string("creatingcourseroles").'</li>';
  8281. }
  8282. $course = restore_read_xml_course_header($xmlfile);
  8283. if (!isset($restore->rolesmapping)) {
  8284. $isimport = true; // course import from another course, or course with no role assignments
  8285. } else {
  8286. $isimport = false; // course restore with role assignments
  8287. }
  8288. if (!empty($course->roleassignments) && !$isimport) {
  8289. $courseassignments = $course->roleassignments;
  8290. foreach ($courseassignments as $oldroleid => $courseassignment) {
  8291. restore_write_roleassignments($restore, $courseassignment->assignments, "course", CONTEXT_COURSE, $course->course_id, $oldroleid);
  8292. }
  8293. }
  8294. /*****************************************************
  8295. * Restoring from course level overrides *
  8296. *****************************************************/
  8297. if (!empty($course->roleoverrides) && !$isimport) {
  8298. $courseoverrides = $course->roleoverrides;
  8299. foreach ($courseoverrides as $oldroleid => $courseoverride) {
  8300. // if not importing into exiting course, or creating new role, we are ok
  8301. // local course overrides to be respected (i.e. restored course overrides ignored)
  8302. if (($restore->restoreto != RESTORETO_CURRENT_ADDING && $restore->restoreto != RESTORETO_EXISTING_ADDING) || empty($restore->rolesmapping[$oldroleid])) {
  8303. restore_write_roleoverrides($restore, $courseoverride->overrides, "course", CONTEXT_COURSE, $course->course_id, $oldroleid);
  8304. }
  8305. }
  8306. }
  8307. /*******************************************************
  8308. * Restoring role assignments/overrdies *
  8309. * from module level assignments *
  8310. *******************************************************/
  8311. if (!defined('RESTORE_SILENTLY')) {
  8312. echo "<li>".get_string("creatingmodroles").'</li>';
  8313. }
  8314. $sections = restore_read_xml_sections($xmlfile);
  8315. $secs = $sections->sections;
  8316. foreach ($secs as $section) {
  8317. if (isset($section->mods)) {
  8318. foreach ($section->mods as $modid=>$mod) {
  8319. if (isset($mod->roleassignments) && !$isimport) {
  8320. foreach ($mod->roleassignments as $oldroleid=>$modassignment) {
  8321. restore_write_roleassignments($restore, $modassignment->assignments, "course_modules", CONTEXT_MODULE, $modid, $oldroleid);
  8322. }
  8323. }
  8324. // role overrides always applies, in import or backup/restore
  8325. if (isset($mod->roleoverrides)) {
  8326. foreach ($mod->roleoverrides as $oldroleid=>$modoverride) {
  8327. restore_write_roleoverrides($restore, $modoverride->overrides, "course_modules", CONTEXT_MODULE, $modid, $oldroleid);
  8328. }
  8329. }
  8330. }
  8331. }
  8332. }
  8333. /*************************************************
  8334. * Restoring assignments from blocks level *
  8335. * role assignments/overrides *
  8336. *************************************************/
  8337. if ($restore->restoreto != RESTORETO_CURRENT_ADDING && $restore->restoreto != RESTORETO_EXISTING_ADDING) { // skip altogether if restoring to exisitng course by adding
  8338. if (!defined('RESTORE_SILENTLY')) {
  8339. echo "<li>".get_string("creatingblocksroles").'</li>';
  8340. }
  8341. $blocks = restore_read_xml_blocks($restore, $xmlfile);
  8342. if (isset($blocks->instances)) {
  8343. foreach ($blocks->instances as $instance) {
  8344. if (isset($instance->roleassignments) && !$isimport) {
  8345. foreach ($instance->roleassignments as $oldroleid=>$blockassignment) {
  8346. restore_write_roleassignments($restore, $blockassignment->assignments, "block_instance", CONTEXT_BLOCK, $instance->id, $oldroleid);
  8347. }
  8348. }
  8349. // likewise block overrides should always be restored like mods
  8350. if (isset($instance->roleoverrides)) {
  8351. foreach ($instance->roleoverrides as $oldroleid=>$blockoverride) {
  8352. restore_write_roleoverrides($restore, $blockoverride->overrides, "block_instance", CONTEXT_BLOCK, $instance->id, $oldroleid);
  8353. }
  8354. }
  8355. }
  8356. }
  8357. }
  8358. /************************************************
  8359. * Restoring assignments from userid level *
  8360. * role assignments/overrides *
  8361. ************************************************/
  8362. if (!defined('RESTORE_SILENTLY')) {
  8363. echo "<li>".get_string("creatinguserroles").'</li>';
  8364. }
  8365. $info = restore_read_xml_users($restore, $xmlfile);
  8366. if (!empty($info->users) && !$isimport) { // no need to restore user assignments for imports (same course)
  8367. //For each user, take its info from backup_ids
  8368. foreach ($info->users as $userid) {
  8369. $rec = backup_getid($restore->backup_unique_code,"user",$userid);
  8370. if (isset($rec->info->roleassignments)) {
  8371. foreach ($rec->info->roleassignments as $oldroleid=>$userassignment) {
  8372. restore_write_roleassignments($restore, $userassignment->assignments, "user", CONTEXT_USER, $userid, $oldroleid);
  8373. }
  8374. }
  8375. if (isset($rec->info->roleoverrides)) {
  8376. foreach ($rec->info->roleoverrides as $oldroleid=>$useroverride) {
  8377. restore_write_roleoverrides($restore, $useroverride->overrides, "user", CONTEXT_USER, $userid, $oldroleid);
  8378. }
  8379. }
  8380. }
  8381. }
  8382. return true;
  8383. }
  8384. // auxillary function to write role assignments read from xml to db
  8385. function restore_write_roleassignments($restore, $assignments, $table, $contextlevel, $oldid, $oldroleid) {
  8386. $role = backup_getid($restore->backup_unique_code, "role", $oldroleid);
  8387. foreach ($assignments as $assignment) {
  8388. $olduser = backup_getid($restore->backup_unique_code,"user",$assignment->userid);
  8389. //Oh dear, $olduser... can be an object, $obj->string or bool!
  8390. if (!$olduser || (is_string($olduser->info) && $olduser->info == "notincourse")) { // it's possible that user is not in the course
  8391. continue;
  8392. }
  8393. $assignment->userid = $olduser->new_id; // new userid here
  8394. $oldmodifier = backup_getid($restore->backup_unique_code,"user",$assignment->modifierid);
  8395. $assignment->modifierid = !empty($oldmodifier->new_id) ? $oldmodifier->new_id : 0; // new modifier id here
  8396. $assignment->roleid = $role->new_id; // restored new role id
  8397. // hack to make the correct contextid for course level imports
  8398. if ($contextlevel == CONTEXT_COURSE) {
  8399. $oldinstance->new_id = $restore->course_id;
  8400. } else {
  8401. $oldinstance = backup_getid($restore->backup_unique_code,$table,$oldid);
  8402. }
  8403. // new instance id not found (not restored module/block/user)... skip any assignment
  8404. if (!$oldinstance || empty($oldinstance->new_id)) {
  8405. continue;
  8406. }
  8407. $newcontext = get_context_instance($contextlevel, $oldinstance->new_id);
  8408. $assignment->contextid = $newcontext->id; // new context id
  8409. // might already have same assignment
  8410. role_assign($assignment->roleid, $assignment->userid, 0, $assignment->contextid, $assignment->timestart, $assignment->timeend, $assignment->hidden, $assignment->enrol, $assignment->timemodified);
  8411. }
  8412. }
  8413. // auxillary function to write role assignments read from xml to db
  8414. function restore_write_roleoverrides($restore, $overrides, $table, $contextlevel, $oldid, $oldroleid) {
  8415. // it is possible to have an override not relevant to this course context.
  8416. // should be ignored(?)
  8417. if (!$role = backup_getid($restore->backup_unique_code, "role", $oldroleid)) {
  8418. return null;
  8419. }
  8420. foreach ($overrides as $override) {
  8421. $override->capability = $override->name;
  8422. $oldmodifier = backup_getid($restore->backup_unique_code,"user",$override->modifierid);
  8423. $override->modifierid = !empty($oldmodifier->new_id)?$oldmodifier->new_id:0; // new modifier id here
  8424. $override->roleid = $role->new_id; // restored new role id
  8425. // hack to make the correct contextid for course level imports
  8426. if ($contextlevel == CONTEXT_COURSE) {
  8427. $oldinstance->new_id = $restore->course_id;
  8428. } else {
  8429. $oldinstance = backup_getid($restore->backup_unique_code,$table,$oldid);
  8430. }
  8431. // new instance id not found (not restored module/block/user)... skip any override
  8432. if (!$oldinstance || empty($oldinstance->new_id)) {
  8433. continue;
  8434. }
  8435. $newcontext = get_context_instance($contextlevel, $oldinstance->new_id);
  8436. $override->contextid = $newcontext->id; // new context id
  8437. // use assign capability instead so we can add context to context_rel
  8438. assign_capability($override->capability, $override->permission, $override->roleid, $override->contextid);
  8439. }
  8440. }
  8441. /**
  8442. * true or false function to see if user can roll dates on restore (any course is enough)
  8443. * @return bool
  8444. */
  8445. function restore_user_can_roll_dates() {
  8446. global $USER;
  8447. // if user has moodle/restore:rolldates capability at system or any course cat return true
  8448. if (has_capability('moodle/restore:rolldates', get_context_instance(CONTEXT_SYSTEM))) {
  8449. return true;
  8450. }
  8451. // Non-cached - get accessinfo
  8452. if (isset($USER->access)) {
  8453. $accessinfo = $USER->access;
  8454. } else {
  8455. $accessinfo = get_user_access_sitewide($USER->id);
  8456. }
  8457. $courses = get_user_courses_bycap($USER->id, 'moodle/restore:rolldates', $accessinfo, true);
  8458. return !empty($courses);
  8459. }
  8460. //write activity date changes to the html log file, and update date values in the the xml array
  8461. function restore_log_date_changes($recordtype, &$restore, &$xml, $TAGS, $NAMETAG='NAME') {
  8462. global $CFG;
  8463. $openlog = false;
  8464. // loop through time fields in $TAGS
  8465. foreach ($TAGS as $TAG) {
  8466. // check $TAG has a sensible value
  8467. if (!empty($xml[$TAG][0]['#']) && is_string($xml[$TAG][0]['#']) && is_numeric($xml[$TAG][0]['#'])) {
  8468. if ($openlog==false) {
  8469. $openlog = true; // only come through here once
  8470. // open file for writing
  8471. $course_dir = "$CFG->dataroot/$restore->course_id/backupdata";
  8472. check_dir_exists($course_dir, true);
  8473. $restorelog = fopen("$course_dir/restorelog.html", "a");
  8474. // start output for this record
  8475. $msg = new stdClass();
  8476. $msg->recordtype = $recordtype;
  8477. $msg->recordname = $xml[$NAMETAG][0]['#'];
  8478. fwrite ($restorelog, get_string("backupdaterecordtype", "moodle", $msg));
  8479. }
  8480. // write old date to $restorelog
  8481. $value = $xml[$TAG][0]['#'];
  8482. $date = usergetdate($value);
  8483. $msg = new stdClass();
  8484. $msg->TAG = $TAG;
  8485. $msg->weekday = $date['weekday'];
  8486. $msg->mday = $date['mday'];
  8487. $msg->month = $date['month'];
  8488. $msg->year = $date['year'];
  8489. fwrite ($restorelog, get_string("backupdateold", "moodle", $msg));
  8490. // write new date to $restorelog
  8491. $value += $restore->course_startdateoffset;
  8492. $date = usergetdate($value);
  8493. $msg = new stdClass();
  8494. $msg->TAG = $TAG;
  8495. $msg->weekday = $date['weekday'];
  8496. $msg->mday = $date['mday'];
  8497. $msg->month = $date['month'];
  8498. $msg->year = $date['year'];
  8499. fwrite ($restorelog, get_string("backupdatenew", "moodle", $msg));
  8500. // update $value in $xml tree for calling module
  8501. $xml[$TAG][0]['#'] = "$value";
  8502. }
  8503. }
  8504. // close the restore log, if it was opened
  8505. if ($openlog) {
  8506. fclose($restorelog);
  8507. }
  8508. }
  8509. ?>