PageRenderTime 118ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 3ms

/moodle1917/backup/restorelib.php

https://github.com/gustavoramirezrugerio/moodle1.9.17
PHP | 9516 lines | 6546 code | 988 blank | 1982 comment | 1802 complexity | ce73768a77d9254fda3096220aa17ac7 MD5 | raw file
Possible License(s): LGPL-3.0, LGPL-2.1, BSD-3-Clause, LGPL-2.0, GPL-2.0
  1. <?php //$Id: restorelib.php,v 1.283.2.98 2011/10/19 19:39:26 moodlerobot 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. // We look for it
  181. preg_match_all($searchstring, $content, $foundset);
  182. // If found, then we are going to look for its new id (in backup tables)
  183. if ($foundset[0]) {
  184. // Iterate over foundset[2]. They are the old_ids
  185. foreach ($foundset[2] as $old_id) {
  186. // We get the needed variables here (course id)
  187. $rec = backup_getid($restore->backup_unique_code, 'course', $old_id);
  188. // Personalize the searchstring
  189. $searchstring = '/\$@(COURSEVIEWBYID)\*('.$old_id.')@\$/';
  190. // If it is a link to itself, replace it
  191. if (!empty($rec->new_id)) {
  192. $replacestring = $CFG->wwwroot . '/course/view.php?id=' . $rec->new_id;
  193. // It s a link to another course, keep it unmodified
  194. } else {
  195. $replacestring = $restore->original_wwwroot . '/course/view.php?id=' . $old_id;
  196. }
  197. // Perform the replacement
  198. $content = preg_replace($searchstring, $replacestring, $content);
  199. }
  200. }
  201. return $content;
  202. }
  203. //This function is called from all xxxx_decode_content_links_caller(),
  204. //its task is to ask all modules (maybe other linkable objects) to restore
  205. //links to them.
  206. function restore_decode_content_links_worker($content,$restore) {
  207. global $CFG;
  208. // Course links decoder
  209. $content = course_decode_content_links($content, $restore);
  210. // Module links decoders
  211. foreach($restore->mods as $name => $info) {
  212. $function_name = $name."_decode_content_links";
  213. if (function_exists($function_name)) {
  214. $content = $function_name($content,$restore);
  215. }
  216. }
  217. // For the current format, call decode_format_content_links if it exists
  218. static $format_function_name;
  219. if (!isset($format_function_name)) {
  220. $format_function_name = false;
  221. if ($format = get_field('course', 'format', 'id', $restore->course_id)) {
  222. if (file_exists("$CFG->dirroot/course/format/$format/restorelib.php")) {
  223. include_once("$CFG->dirroot/course/format/$format/restorelib.php");
  224. $function_name = $format.'_decode_format_content_links';
  225. if (function_exists($function_name)) {
  226. $format_function_name = $function_name;
  227. }
  228. }
  229. }
  230. }
  231. // If the above worked - then we have a function to call
  232. if ($format_function_name) {
  233. $content = $format_function_name($content, $restore);
  234. }
  235. // For each block, call its encode_content_links method
  236. static $blockobjects = null;
  237. if (!isset($blockobjects)) {
  238. $blockobjects = array();
  239. if ($blocks = get_records('block', 'visible', 1)) {
  240. foreach ($blocks as $block) {
  241. if ($blockobject = block_instance($block->name)) {
  242. $blockobjects[] = $blockobject;
  243. }
  244. }
  245. }
  246. }
  247. foreach ($blockobjects as $blockobject) {
  248. $content = $blockobject->decode_content_links($content,$restore);
  249. }
  250. return $content;
  251. }
  252. //This function converts all the wiki texts in the restored course
  253. //to the Markdown format. Used only for backup files prior 2005041100.
  254. //It calls every module xxxx_convert_wiki2markdown function
  255. function restore_convert_wiki2markdown($restore) {
  256. $status = true;
  257. if (!defined('RESTORE_SILENTLY')) {
  258. echo "<ul>";
  259. }
  260. foreach ($restore->mods as $name => $info) {
  261. //If the module is being restored
  262. if ($info->restore == 1) {
  263. //Check if the xxxx_restore_wiki2markdown exists
  264. $function_name = $name."_restore_wiki2markdown";
  265. if (function_exists($function_name)) {
  266. $status = $function_name($restore);
  267. if (!defined('RESTORE_SILENTLY')) {
  268. echo "<li>".get_string("modulenameplural",$name);
  269. echo '</li>';
  270. }
  271. }
  272. }
  273. }
  274. if (!defined('RESTORE_SILENTLY')) {
  275. echo "</ul>";
  276. }
  277. return $status;
  278. }
  279. //This function receives a wiki text in the restore process and
  280. //return it with every link to modules " modulename:moduleid"
  281. //converted if possible. See the space before modulename!!
  282. function restore_decode_wiki_content($content,$restore) {
  283. global $CFG;
  284. $result = $content;
  285. $searchstring='/ ([a-zA-Z]+):([0-9]+)\(([^)]+)\)/';
  286. //We look for it
  287. preg_match_all($searchstring,$content,$foundset);
  288. //If found, then we are going to look for its new id (in backup tables)
  289. if ($foundset[0]) {
  290. //print_object($foundset); //Debug
  291. //Iterate over foundset[2]. They are the old_ids
  292. foreach($foundset[2] as $old_id) {
  293. //We get the needed variables here (course id)
  294. $rec = backup_getid($restore->backup_unique_code,"course_modules",$old_id);
  295. //Personalize the searchstring
  296. $searchstring='/ ([a-zA-Z]+):'.$old_id.'\(([^)]+)\)/';
  297. //If it is a link to this course, update the link to its new location
  298. if($rec->new_id) {
  299. //Now replace it
  300. $result= preg_replace($searchstring,' $1:'.$rec->new_id.'($2)',$result);
  301. } else {
  302. //It's a foreign link so redirect it to its original URL
  303. $result= preg_replace($searchstring,$restore->original_wwwroot.'/mod/$1/view.php?id='.$old_id.'($2)',$result);
  304. }
  305. }
  306. }
  307. return $result;
  308. }
  309. //This function read the xml file and store it data from the info zone in an object
  310. function restore_read_xml_info ($xml_file) {
  311. //We call the main read_xml function, with todo = INFO
  312. $info = restore_read_xml ($xml_file,"INFO",false);
  313. return $info;
  314. }
  315. //This function read the xml file and store it data from the course header zone in an object
  316. function restore_read_xml_course_header ($xml_file) {
  317. //We call the main read_xml function, with todo = COURSE_HEADER
  318. $info = restore_read_xml ($xml_file,"COURSE_HEADER",false);
  319. return $info;
  320. }
  321. //This function read the xml file and store its data from the blocks in a object
  322. function restore_read_xml_blocks ($restore, $xml_file) {
  323. //We call the main read_xml function, with todo = BLOCKS
  324. $info = restore_read_xml ($xml_file,'BLOCKS',$restore);
  325. return $info;
  326. }
  327. //This function read the xml file and store its data from the sections in a object
  328. function restore_read_xml_sections ($xml_file) {
  329. //We call the main read_xml function, with todo = SECTIONS
  330. $info = restore_read_xml ($xml_file,"SECTIONS",false);
  331. return $info;
  332. }
  333. //This function read the xml file and store its data from the course format in an object
  334. function restore_read_xml_formatdata ($xml_file) {
  335. //We call the main read_xml function, with todo = FORMATDATA
  336. $info = restore_read_xml ($xml_file,'FORMATDATA',false);
  337. return $info;
  338. }
  339. //This function read the xml file and store its data from the metacourse in a object
  340. function restore_read_xml_metacourse ($xml_file) {
  341. //We call the main read_xml function, with todo = METACOURSE
  342. $info = restore_read_xml ($xml_file,"METACOURSE",false);
  343. return $info;
  344. }
  345. //This function read the xml file and store its data from the gradebook in a object
  346. function restore_read_xml_gradebook ($restore, $xml_file) {
  347. //We call the main read_xml function, with todo = GRADEBOOK
  348. $info = restore_read_xml ($xml_file,"GRADEBOOK",$restore);
  349. return $info;
  350. }
  351. //This function read the xml file and store its data from the users in
  352. //backup_ids->info db (and user's id in $info)
  353. function restore_read_xml_users ($restore,$xml_file) {
  354. //We call the main read_xml function, with todo = USERS
  355. $info = restore_read_xml ($xml_file,"USERS",$restore);
  356. return $info;
  357. }
  358. //This function read the xml file and store its data from the messages in
  359. //backup_ids->message backup_ids->message_read and backup_ids->contact and db (and their counters in info)
  360. function restore_read_xml_messages ($restore,$xml_file) {
  361. //We call the main read_xml function, with todo = MESSAGES
  362. $info = restore_read_xml ($xml_file,"MESSAGES",$restore);
  363. return $info;
  364. }
  365. //This function read the xml file and store its data from the blogs in
  366. //backup_ids->blog and backup_ids->blog_tag and db (and their counters in info)
  367. function restore_read_xml_blogs ($restore,$xml_file) {
  368. //We call the main read_xml function, with todo = BLOGS
  369. $info = restore_read_xml ($xml_file,"BLOGS",$restore);
  370. return $info;
  371. }
  372. //This function read the xml file and store its data from the questions in
  373. //backup_ids->info db (and category's id in $info)
  374. function restore_read_xml_questions ($restore,$xml_file) {
  375. //We call the main read_xml function, with todo = QUESTIONS
  376. $info = restore_read_xml ($xml_file,"QUESTIONS",$restore);
  377. return $info;
  378. }
  379. //This function read the xml file and store its data from the scales in
  380. //backup_ids->info db (and scale's id in $info)
  381. function restore_read_xml_scales ($restore,$xml_file) {
  382. //We call the main read_xml function, with todo = SCALES
  383. $info = restore_read_xml ($xml_file,"SCALES",$restore);
  384. return $info;
  385. }
  386. //This function read the xml file and store its data from the groups in
  387. //backup_ids->info db (and group's id in $info)
  388. function restore_read_xml_groups ($restore,$xml_file) {
  389. //We call the main read_xml function, with todo = GROUPS
  390. $info = restore_read_xml ($xml_file,"GROUPS",$restore);
  391. return $info;
  392. }
  393. //This function read the xml file and store its data from the groupings in
  394. //backup_ids->info db (and grouping's id in $info)
  395. function restore_read_xml_groupings ($restore,$xml_file) {
  396. //We call the main read_xml function, with todo = GROUPINGS
  397. $info = restore_read_xml ($xml_file,"GROUPINGS",$restore);
  398. return $info;
  399. }
  400. //This function read the xml file and store its data from the groupings in
  401. //backup_ids->info db (and grouping's id in $info)
  402. function restore_read_xml_groupings_groups ($restore,$xml_file) {
  403. //We call the main read_xml function, with todo = GROUPINGS
  404. $info = restore_read_xml ($xml_file,"GROUPINGSGROUPS",$restore);
  405. return $info;
  406. }
  407. //This function read the xml file and store its data from the events (course) in
  408. //backup_ids->info db (and event's id in $info)
  409. function restore_read_xml_events ($restore,$xml_file) {
  410. //We call the main read_xml function, with todo = EVENTS
  411. $info = restore_read_xml ($xml_file,"EVENTS",$restore);
  412. return $info;
  413. }
  414. //This function read the xml file and store its data from the modules in
  415. //backup_ids->info
  416. function restore_read_xml_modules ($restore,$xml_file) {
  417. //We call the main read_xml function, with todo = MODULES
  418. $info = restore_read_xml ($xml_file,"MODULES",$restore);
  419. return $info;
  420. }
  421. //This function read the xml file and store its data from the logs in
  422. //backup_ids->info
  423. function restore_read_xml_logs ($restore,$xml_file) {
  424. //We call the main read_xml function, with todo = LOGS
  425. $info = restore_read_xml ($xml_file,"LOGS",$restore);
  426. return $info;
  427. }
  428. function restore_read_xml_roles ($xml_file) {
  429. //We call the main read_xml function, with todo = ROLES
  430. $info = restore_read_xml ($xml_file,"ROLES",false);
  431. return $info;
  432. }
  433. //This function prints the contents from the info parammeter passed
  434. function restore_print_info ($info) {
  435. global $CFG;
  436. $status = true;
  437. if ($info) {
  438. $table = new object();
  439. //This is tha align to every ingo table
  440. $table->align = array ("right","left");
  441. //This is the nowrap clause
  442. $table->wrap = array ("","nowrap");
  443. //The width
  444. $table->width = "70%";
  445. //Put interesting info in table
  446. //The backup original name
  447. $tab[0][0] = "<b>".get_string("backuporiginalname").":</b>";
  448. $tab[0][1] = $info->backup_name;
  449. //The moodle version
  450. $tab[1][0] = "<b>".get_string("moodleversion").":</b>";
  451. $tab[1][1] = $info->backup_moodle_release." (".$info->backup_moodle_version.")";
  452. //The backup version
  453. $tab[2][0] = "<b>".get_string("backupversion").":</b>";
  454. $tab[2][1] = $info->backup_backup_release." (".$info->backup_backup_version.")";
  455. //The backup date
  456. $tab[3][0] = "<b>".get_string("backupdate").":</b>";
  457. $tab[3][1] = userdate($info->backup_date);
  458. //Is this the same Moodle install?
  459. if (!empty($info->original_siteidentifier)) {
  460. $tab[4][0] = "<b>".get_string("backupfromthissite").":</b>";
  461. if (backup_is_same_site($info)) {
  462. $tab[4][1] = get_string('yes');
  463. } else {
  464. $tab[4][1] = get_string('no');
  465. }
  466. }
  467. //Print title
  468. print_heading(get_string("backup").":");
  469. $table->data = $tab;
  470. //Print backup general info
  471. print_table($table);
  472. if ($info->backup_backup_version <= 2005070500) {
  473. notify(get_string('backupnonisowarning')); // Message informing that this backup may not work!
  474. }
  475. //Now backup contents in another table
  476. $tab = array();
  477. //First mods info
  478. $mods = $info->mods;
  479. $elem = 0;
  480. foreach ($mods as $key => $mod) {
  481. $tab[$elem][0] = "<b>".get_string("modulenameplural",$key).":</b>";
  482. if ($mod->backup == "false") {
  483. $tab[$elem][1] = get_string("notincluded");
  484. } else {
  485. if ($mod->userinfo == "true") {
  486. $tab[$elem][1] = get_string("included")." ".get_string("withuserdata");
  487. } else {
  488. $tab[$elem][1] = get_string("included")." ".get_string("withoutuserdata");
  489. }
  490. if (isset($mod->instances) && is_array($mod->instances) && count($mod->instances)) {
  491. foreach ($mod->instances as $instance) {
  492. if ($instance->backup) {
  493. $elem++;
  494. $tab[$elem][0] = $instance->name;
  495. if ($instance->userinfo == 'true') {
  496. $tab[$elem][1] = get_string("included")." ".get_string("withuserdata");
  497. } else {
  498. $tab[$elem][1] = get_string("included")." ".get_string("withoutuserdata");
  499. }
  500. }
  501. }
  502. }
  503. }
  504. $elem++;
  505. }
  506. //Metacourse info
  507. $tab[$elem][0] = "<b>".get_string("metacourse").":</b>";
  508. if ($info->backup_metacourse == "true") {
  509. $tab[$elem][1] = get_string("yes");
  510. } else {
  511. $tab[$elem][1] = get_string("no");
  512. }
  513. $elem++;
  514. //Users info
  515. $tab[$elem][0] = "<b>".get_string("users").":</b>";
  516. $tab[$elem][1] = get_string($info->backup_users);
  517. $elem++;
  518. //Logs info
  519. $tab[$elem][0] = "<b>".get_string("logs").":</b>";
  520. if ($info->backup_logs == "true") {
  521. $tab[$elem][1] = get_string("yes");
  522. } else {
  523. $tab[$elem][1] = get_string("no");
  524. }
  525. $elem++;
  526. //User Files info
  527. $tab[$elem][0] = "<b>".get_string("userfiles").":</b>";
  528. if ($info->backup_user_files == "true") {
  529. $tab[$elem][1] = get_string("yes");
  530. } else {
  531. $tab[$elem][1] = get_string("no");
  532. }
  533. $elem++;
  534. //Course Files info
  535. $tab[$elem][0] = "<b>".get_string("coursefiles").":</b>";
  536. if ($info->backup_course_files == "true") {
  537. $tab[$elem][1] = get_string("yes");
  538. } else {
  539. $tab[$elem][1] = get_string("no");
  540. }
  541. $elem++;
  542. //site Files info
  543. $tab[$elem][0] = "<b>".get_string("sitefiles").":</b>";
  544. if (isset($info->backup_site_files) && $info->backup_site_files == "true") {
  545. $tab[$elem][1] = get_string("yes");
  546. } else {
  547. $tab[$elem][1] = get_string("no");
  548. }
  549. $elem++;
  550. //gradebook history info
  551. $tab[$elem][0] = "<b>".get_string('gradebookhistories', 'grades').":</b>";
  552. if (isset($info->gradebook_histories) && $info->gradebook_histories == "true") {
  553. $tab[$elem][1] = get_string("yes");
  554. } else {
  555. $tab[$elem][1] = get_string("no");
  556. }
  557. $elem++;
  558. //Messages info (only showed if present)
  559. if ($info->backup_messages == 'true') {
  560. $tab[$elem][0] = "<b>".get_string('messages','message').":</b>";
  561. $tab[$elem][1] = get_string('yes');
  562. $elem++;
  563. } else {
  564. //Do nothing
  565. }
  566. $elem++;
  567. //Blogs info (only showed if present)
  568. if (isset($info->backup_blogs) && $info->backup_blogs == 'true') {
  569. $tab[$elem][0] = "<b>".get_string('blogs','blog').":</b>";
  570. $tab[$elem][1] = get_string('yes');
  571. $elem++;
  572. } else {
  573. //Do nothing
  574. }
  575. $table->data = $tab;
  576. //Print title
  577. print_heading(get_string("backupdetails").":");
  578. //Print backup general info
  579. print_table($table);
  580. } else {
  581. $status = false;
  582. }
  583. return $status;
  584. }
  585. //This function prints the contents from the course_header parammeter passed
  586. function restore_print_course_header ($course_header) {
  587. $status = true;
  588. if ($course_header) {
  589. $table = new object();
  590. //This is tha align to every ingo table
  591. $table->align = array ("right","left");
  592. //The width
  593. $table->width = "70%";
  594. //Put interesting course header in table
  595. //The course name
  596. $tab[0][0] = "<b>".get_string("name").":</b>";
  597. $tab[0][1] = $course_header->course_fullname." (".$course_header->course_shortname.")";
  598. //The course summary
  599. $tab[1][0] = "<b>".get_string("summary").":</b>";
  600. $tab[1][1] = $course_header->course_summary;
  601. $table->data = $tab;
  602. //Print title
  603. print_heading(get_string("course").":");
  604. //Print backup course header info
  605. print_table($table);
  606. } else {
  607. $status = false;
  608. }
  609. return $status;
  610. }
  611. /**
  612. * Given one user object (from backup file), perform all the neccesary
  613. * checks is order to decide how that user will be handled on restore.
  614. *
  615. * Note the function requires $user->mnethostid to be already calculated
  616. * so it's caller responsibility to set it
  617. *
  618. * This function is used both by @restore_precheck_users() and
  619. * @restore_create_users() to get consistent results in both places
  620. *
  621. * It returns:
  622. * - one user object (from DB), if match has been found and user will be remapped
  623. * - boolean true if the user needs to be created
  624. * - boolean false if some conflict happened and the user cannot be handled
  625. *
  626. * Each test is responsible for returning its results and interrupt
  627. * execution. At the end, boolean true (user needs to be created) will be
  628. * returned if no test has interrupted that.
  629. *
  630. * Here it's the logic applied, keep it updated:
  631. *
  632. * If restoring users from same site backup:
  633. * 1A - Normal check: If match by id and username and mnethost => ok, return target user
  634. * 1B - Handle users deleted in DB and "alive" in backup file:
  635. * If match by id and mnethost and user is deleted in DB and
  636. * (match by username LIKE 'backup_email.%' or by non empty email = md5(username)) => ok, return target user
  637. * 1C - Handle users deleted in backup file and "alive" in DB:
  638. * If match by id and mnethost and user is deleted in backup file
  639. * and match by email = email_without_time(backup_email) => ok, return target user
  640. * 1D - Conflict: If match by username and mnethost and doesn't match by id => conflict, return false
  641. * 1E - None of the above, return true => User needs to be created
  642. *
  643. * if restoring from another site backup (cannot match by id here, replace it by email/firstaccess combination):
  644. * 2A - Normal check: If match by username and mnethost and (email or non-zero firstaccess) => ok, return target user
  645. * 2B - Handle users deleted in DB and "alive" in backup file:
  646. * 2B1 - If match by mnethost and user is deleted in DB and not empty email = md5(username) and
  647. * (username LIKE 'backup_email.%' or non-zero firstaccess) => ok, return target user
  648. * 2B2 - If match by mnethost and user is deleted in DB and
  649. * username LIKE 'backup_email.%' and non-zero firstaccess) => ok, return target user
  650. * (to cover situations were md5(username) wasn't implemented on delete we requiere both)
  651. * 2C - Handle users deleted in backup file and "alive" in DB:
  652. * If match mnethost and user is deleted in backup file
  653. * and by email = email_without_time(backup_email) and non-zero firstaccess=> ok, return target user
  654. * 2D - Conflict: If match by username and mnethost and not by (email or non-zero firstaccess) => conflict, return false
  655. * 2E - None of the above, return true => User needs to be created
  656. *
  657. * Note: for DB deleted users email is stored in username field, hence we
  658. * are looking there for emails. See delete_user()
  659. * Note: for DB deleted users md5(username) is stored *sometimes* in the email field,
  660. * hence we are looking there for usernames if not empty. See delete_user()
  661. */
  662. function restore_check_user($restore, $user) {
  663. global $CFG;
  664. // Verify mnethostid is set, return error if not
  665. // it's parent responsibility to define that before
  666. // arriving here
  667. if (empty($user->mnethostid)) {
  668. debugging("restore_check_user() wrong use, mnethostid not set for user $user->username", DEBUG_DEVELOPER);
  669. return false;
  670. }
  671. // Handle checks from same site backups
  672. if (backup_is_same_site($restore) && empty($CFG->forcedifferentsitecheckingusersonrestore)) {
  673. // 1A - If match by id and username and mnethost => ok, return target user
  674. if ($rec = get_record('user', 'id', $user->id, 'username', addslashes($user->username), 'mnethostid', $user->mnethostid)) {
  675. return $rec; // Matching user found, return it
  676. }
  677. // 1B - Handle users deleted in DB and "alive" in backup file
  678. // Note: for DB deleted users email is stored in username field, hence we
  679. // are looking there for emails. See delete_user()
  680. // Note: for DB deleted users md5(username) is stored *sometimes* in the email field,
  681. // hence we are looking there for usernames if not empty. See delete_user()
  682. // If match by id and mnethost and user is deleted in DB and
  683. // match by username LIKE 'backup_email.%' or by non empty email = md5(username) => ok, return target user
  684. if ($rec = get_record_sql("SELECT *
  685. FROM {$CFG->prefix}user u
  686. WHERE id = $user->id
  687. AND mnethostid = $user->mnethostid
  688. AND deleted = 1
  689. AND (
  690. username LIKE '".addslashes($user->email).".%'
  691. OR (
  692. ".sql_isnotempty('user', 'email', false, false)."
  693. AND email = '".md5($user->username)."'
  694. )
  695. )")) {
  696. return $rec; // Matching user, deleted in DB found, return it
  697. }
  698. // 1C - Handle users deleted in backup file and "alive" in DB
  699. // If match by id and mnethost and user is deleted in backup file
  700. // and match by email = email_without_time(backup_email) => ok, return target user
  701. if ($user->deleted) {
  702. // Note: for DB deleted users email is stored in username field, hence we
  703. // are looking there for emails. See delete_user()
  704. // Trim time() from email
  705. $trimemail = preg_replace('/(.*?)\.[0-9]+.?$/', '\\1', $user->username);
  706. if ($rec = get_record_sql("SELECT *
  707. FROM {$CFG->prefix}user u
  708. WHERE id = $user->id
  709. AND mnethostid = $user->mnethostid
  710. AND email = '".addslashes($trimemail)."'")) {
  711. return $rec; // Matching user, deleted in backup file found, return it
  712. }
  713. }
  714. // 1D - If match by username and mnethost and doesn't match by id => conflict, return false
  715. if ($rec = get_record('user', 'username', addslashes($user->username), 'mnethostid', $user->mnethostid)) {
  716. if ($user->id != $rec->id) {
  717. return false; // Conflict, username already exists and belongs to another id
  718. }
  719. }
  720. // Handle checks from different site backups
  721. } else {
  722. // 2A - If match by username and mnethost and
  723. // (email or non-zero firstaccess) => ok, return target user
  724. if ($rec = get_record_sql("SELECT *
  725. FROM {$CFG->prefix}user u
  726. WHERE username = '".addslashes($user->username)."'
  727. AND mnethostid = $user->mnethostid
  728. AND (
  729. email = '".addslashes($user->email)."'
  730. OR (
  731. firstaccess != 0
  732. AND firstaccess = $user->firstaccess
  733. )
  734. )")) {
  735. return $rec; // Matching user found, return it
  736. }
  737. // 2B - Handle users deleted in DB and "alive" in backup file
  738. // Note: for DB deleted users email is stored in username field, hence we
  739. // are looking there for emails. See delete_user()
  740. // Note: for DB deleted users md5(username) is stored *sometimes* in the email field,
  741. // hence we are looking there for usernames if not empty. See delete_user()
  742. // 2B1 - If match by mnethost and user is deleted in DB and not empty email = md5(username) and
  743. // (by username LIKE 'backup_email.%' or non-zero firstaccess) => ok, return target user
  744. if ($rec = get_record_sql("SELECT *
  745. FROM {$CFG->prefix}user u
  746. WHERE mnethostid = $user->mnethostid
  747. AND deleted = 1
  748. AND ".sql_isnotempty('user', 'email', false, false)."
  749. AND email = '".md5($user->username)."'
  750. AND (
  751. username LIKE '".addslashes($user->email).".%'
  752. OR (
  753. firstaccess != 0
  754. AND firstaccess = $user->firstaccess
  755. )
  756. )")) {
  757. return $rec; // Matching user found, return it
  758. }
  759. // 2B2 - If match by mnethost and user is deleted in DB and
  760. // username LIKE 'backup_email.%' and non-zero firstaccess) => ok, return target user
  761. // (this covers situations where md5(username) wasn't being stored so we require both
  762. // the email & non-zero firstaccess to match)
  763. if ($rec = get_record_sql("SELECT *
  764. FROM {$CFG->prefix}user u
  765. WHERE mnethostid = $user->mnethostid
  766. AND deleted = 1
  767. AND username LIKE '".addslashes($user->email).".%'
  768. AND firstaccess != 0
  769. AND firstaccess = $user->firstaccess")) {
  770. return $rec; // Matching user found, return it
  771. }
  772. // 2C - Handle users deleted in backup file and "alive" in DB
  773. // If match mnethost and user is deleted in backup file
  774. // and match by email = email_without_time(backup_email) and non-zero firstaccess=> ok, return target user
  775. if ($user->deleted) {
  776. // Note: for DB deleted users email is stored in username field, hence we
  777. // are looking there for emails. See delete_user()
  778. // Trim time() from email
  779. $trimemail = preg_replace('/(.*?)\.[0-9]+.?$/', '\\1', $user->username);
  780. if ($rec = get_record_sql("SELECT *
  781. FROM {$CFG->prefix}user u
  782. WHERE mnethostid = $user->mnethostid
  783. AND email = '".addslashes($trimemail)."'
  784. AND firstaccess != 0
  785. AND firstaccess = $user->firstaccess")) {
  786. return $rec; // Matching user, deleted in backup file found, return it
  787. }
  788. }
  789. // 2D - If match by username and mnethost and not by (email or non-zero firstaccess) => conflict, return false
  790. if ($rec = get_record_sql("SELECT *
  791. FROM {$CFG->prefix}user u
  792. WHERE username = '".addslashes($user->username)."'
  793. AND mnethostid = $user->mnethostid
  794. AND NOT (
  795. email = '".addslashes($user->email)."'
  796. OR (
  797. firstaccess != 0
  798. AND firstaccess = $user->firstaccess
  799. )
  800. )")) {
  801. return false; // Conflict, username/mnethostid already exist and belong to another user (by email/firstaccess)
  802. }
  803. }
  804. // Arrived here, return true as the user will need to be created and no
  805. // conflicts have been found in the logic above. This covers:
  806. // 1E - else => user needs to be created, return true
  807. // 2E - else => user needs to be created, return true
  808. return true;
  809. }
  810. /**
  811. * For all the users being restored, check if they are going to cause problems
  812. * before executing the restore process itself, detecting situations like:
  813. * - conflicts preventing restore to continue - provided by @restore_check_user()
  814. * - prevent creation of users if not allowed - check some global settings/caps
  815. */
  816. function restore_precheck_users($xml_file, $restore, &$problems) {
  817. global $CFG;
  818. $status = true; // Init $status
  819. // We aren't restoring users, nothing to check, allow continue
  820. if ($restore->users == 2) {
  821. return true;
  822. }
  823. // Get array of users from xml file and load them in backup_ids table
  824. if (!$info = restore_read_xml_users($restore,$xml_file)) {
  825. return true; // No users, nothing to check, allow continue
  826. }
  827. // We are going to map mnethostid, so load all the available ones
  828. $mnethosts = get_records('mnet_host', '', '', 'wwwroot', 'wwwroot, id');
  829. // Calculate the context we are going to use for capability checking
  830. if (!empty($restore->course_id)) { // Know the target (existing) course, check capabilities there
  831. $context = get_context_instance(CONTEXT_COURSE, $restore->course_id);
  832. } else if (!empty($restore->restore_restorecatto)) { // Know the category, check capabilities there
  833. $context = get_context_instance(CONTEXT_COURSECAT, $restore->restore_restorecatto);
  834. } else { // Last resort, check capabilities at system level
  835. $context = get_context_instance(CONTEXT_SYSTEM);
  836. }
  837. // Calculate if we have perms to create users, by checking:
  838. // to 'moodle/restore:createuser' and 'moodle/restore:userinfo'
  839. // and also observe $CFG->disableusercreationonrestore
  840. $cancreateuser = false;
  841. if (has_capability('moodle/restore:createuser', $context) and
  842. has_capability('moodle/restore:userinfo', $context) and
  843. empty($CFG->disableusercreationonrestore)) { // Can create users
  844. $cancreateuser = true;
  845. }
  846. // Iterate over all users, checking if they are likely to cause problems on restore
  847. $counter = 0;
  848. foreach ($info->users as $userid) {
  849. $rec = backup_getid($restore->backup_unique_code, 'user', $userid);
  850. $user = $rec->info;
  851. // Find the correct mnethostid for user before performing any further check
  852. if (empty($user->mnethosturl) || $user->mnethosturl === $CFG->wwwroot) {
  853. $user->mnethostid = $CFG->mnet_localhost_id;
  854. } else {
  855. // fast url-to-id lookups
  856. if (isset($mnethosts[$user->mnethosturl])) {
  857. $user->mnethostid = $mnethosts[$user->mnethosturl]->id;
  858. } else {
  859. $user->mnethostid = $CFG->mnet_localhost_id;
  860. }
  861. }
  862. // Calculate the best way to handle this user from backup file
  863. $usercheck = restore_check_user($restore, $user);
  864. if (is_object($usercheck)) { // No problem, we have found one user in DB to be mapped to
  865. // Annotate it, for later process by restore_create_users(). Set new_id to mapping user->id
  866. backup_putid($restore->backup_unique_code, 'user', $userid, $usercheck->id, $user);
  867. } else if ($usercheck === false) { // Found conflict, report it as problem
  868. $problems[] = get_string('restoreuserconflict', '', $user->username);
  869. $status = false;
  870. } else if ($usercheck === true) { // User needs to be created, check if we are able
  871. if ($cancreateuser) { // Can create user, annotate it, for later process by restore_create_users(). Set new_id to 0
  872. backup_putid($restore->backup_unique_code, 'user', $userid, 0, $user);
  873. } else { // Cannot create user, report it as problem
  874. $problems[] = get_string('restorecannotcreateuser', '', $user->username);
  875. $status = false;
  876. }
  877. } else { // Shouldn't arrive here ever, something is for sure wrong in restore_check_user()
  878. if (!defined('RESTORE_SILENTLY')) {
  879. notify('Unexpected error pre-checking user ' . s($user->username) . ' from backup file');
  880. return false;
  881. }
  882. }
  883. // Do some output
  884. $counter++;
  885. if ($counter % 10 == 0) {
  886. if (!defined('RESTORE_SILENTLY')) {
  887. echo ".";
  888. if ($counter % 200 == 0) {
  889. echo "<br />";
  890. }
  891. }
  892. backup_flush(300);
  893. }
  894. }
  895. return $status;
  896. }
  897. //This function create a new course record.
  898. //When finished, course_header contains the id of the new course
  899. function restore_create_new_course($restore,&$course_header) {
  900. global $CFG, $SESSION;
  901. $status = true;
  902. $fullname = $course_header->course_fullname;
  903. $shortname = $course_header->course_shortname;
  904. $currentfullname = "";
  905. $currentshortname = "";
  906. $counter = 0;
  907. //Iteratere while the name exists
  908. do {
  909. if ($counter) {
  910. $suffixfull = " ".get_string("copyasnoun")." ".$counter;
  911. $suffixshort = "_".$counter;
  912. } else {
  913. $suffixfull = "";
  914. $suffixshort = "";
  915. }
  916. $currentfullname = $fullname.$suffixfull;
  917. // Limit the size of shortname - database column accepts <= 100 chars
  918. $currentshortname = substr($shortname, 0, 100 - strlen($suffixshort)).$suffixshort;
  919. $coursefull = get_record("course","fullname",addslashes($currentfullname));
  920. $courseshort = get_record("course","shortname",addslashes($currentshortname));
  921. $counter++;
  922. } while ($coursefull || $courseshort);
  923. //New name = currentname
  924. $course_header->course_fullname = $currentfullname;
  925. $course_header->course_shortname = $currentshortname;
  926. // first try to get it from restore
  927. if ($restore->restore_restorecatto) {
  928. $category = get_record('course_categories', 'id', $restore->restore_restorecatto);
  929. }
  930. // else we try to get it from the xml file
  931. //Now calculate the category
  932. if (empty($category)) {
  933. $category = get_record("course_categories","id",$course_header->category->id,
  934. "name",addslashes($course_header->category->name));
  935. }
  936. //If no exists, try by name only
  937. if (!$category) {
  938. $category = get_record("course_categories","name",addslashes($course_header->category->name));
  939. }
  940. //If no exists, get category id 1
  941. if (!$category) {
  942. $category = get_record("course_categories","id","1");
  943. }
  944. //If category 1 doesn'exists, lets create the course category (get it from backup file)
  945. if (!$category) {
  946. $ins_category = new object();
  947. $ins_category->name = addslashes($course_header->category->name);
  948. $ins_category->parent = 0;
  949. $ins_category->sortorder = 0;
  950. $ins_category->coursecount = 0;
  951. $ins_category->visible = 0; //To avoid interferences with the rest of the site
  952. $ins_category->timemodified = time();
  953. $newid = insert_record("course_categories",$ins_category);
  954. $category->id = $newid;
  955. $category->name = $course_header->category->name;
  956. }
  957. //If exists, put new category id
  958. if ($category) {
  959. $course_header->category->id = $category->id;
  960. $course_header->category->name = $category->name;
  961. //Error, cannot locate category
  962. } else {
  963. $course_header->category->id = 0;
  964. $course_header->category->name = get_string("unknowncategory");
  965. $status = false;
  966. }
  967. //Create the course_object
  968. if ($status) {
  969. $course = new object();
  970. $course->category = addslashes($course_header->category->id);
  971. $course->password = addslashes($course_header->course_password);
  972. $course->fullname = addslashes($course_header->course_fullname);
  973. $course->shortname = addslashes($course_header->course_shortname);
  974. $course->idnumber = addslashes($course_header->course_idnumber);
  975. $course->idnumber = ''; //addslashes($course_header->course_idnumber); // we don't want this at all.
  976. $course->summary = addslashes($course_header->course_summary);
  977. $course->format = addslashes($course_header->course_format);
  978. $course->showgrades = addslashes($course_header->course_showgrades);
  979. $course->newsitems = addslashes($course_header->course_newsitems);
  980. $course->teacher = addslashes($course_header->course_teacher);
  981. $course->teachers = addslashes($course_header->course_teachers);
  982. $course->student = addslashes($course_header->course_student);
  983. $course->students = addslashes($course_header->course_students);
  984. $course->guest = addslashes($course_header->course_guest);
  985. $course->startdate = addslashes($course_header->course_startdate);
  986. $course->startdate += $restore->course_startdateoffset;
  987. $course->numsections = addslashes($course_header->course_numsections);
  988. //$course->showrecent = addslashes($course_header->course_showrecent); INFO: This is out in 1.3
  989. $course->maxbytes = addslashes($course_header->course_maxbytes);
  990. $course->showreports = addslashes($course_header->course_showreports);
  991. if (isset($course_header->course_groupmode)) {
  992. $course->groupmode = addslashes($course_header->course_groupmode);
  993. }
  994. if (isset($course_header->course_groupmodeforce)) {
  995. $course->groupmodeforce = addslashes($course_header->course_groupmodeforce);
  996. }
  997. if (isset($course_header->course_defaultgroupingid)) {
  998. //keep the original now - convert after groupings restored
  999. $course->defaultgroupingid = addslashes($course_header->course_defaultgroupingid);
  1000. }
  1001. $course->lang = addslashes($course_header->course_lang);
  1002. $course->theme = addslashes($course_header->course_theme);
  1003. $course->cost = addslashes($course_header->course_cost);
  1004. $course->currency = isset($course_header->course_currency)?addslashes($course_header->course_currency):'';
  1005. $course->marker = addslashes($course_header->course_marker);
  1006. $course->visible = addslashes($course_header->course_visible);
  1007. $course->hiddensections = addslashes($course_header->course_hiddensections);
  1008. $course->timecreated = addslashes($course_header->course_timecreated);
  1009. $course->timemodified = addslashes($course_header->course_timemodified);
  1010. $course->metacourse = addslashes($course_header->course_metacourse);
  1011. $course->expirynotify = isset($course_header->course_expirynotify) ? addslashes($course_header->course_expirynotify):0;
  1012. $course->notifystudents = isset($course_header->course_notifystudents) ? addslashes($course_header->course_notifystudents) : 0;
  1013. $course->expirythreshold = isset($course_header->course_expirythreshold) ? addslashes($course_header->course_expirythreshold) : 0;
  1014. $course->enrollable = isset($course_header->course_enrollable) ? addslashes($course_header->course_enrollable) : 1;
  1015. $course->enrolstartdate = isset($course_header->course_enrolstartdate) ? addslashes($course_header->course_enrolstartdate) : 0;
  1016. if ($course->enrolstartdate) { //Roll course dates
  1017. $course->enrolstartdate += $restore->course_startdateoffset;
  1018. }
  1019. $course->enrolenddate = isset($course_header->course_enrolenddate) ? addslashes($course_header->course_enrolenddate) : 0;
  1020. if ($course->enrolenddate) { //Roll course dates
  1021. $course->enrolenddate += $restore->course_startdateoffset;
  1022. }
  1023. $course->enrolperiod = addslashes($course_header->course_enrolperiod);
  1024. //Calculate sortorder field
  1025. $sortmax = get_record_sql('SELECT MAX(sortorder) AS max
  1026. FROM ' . $CFG->prefix . 'course
  1027. WHERE category=' . $course->category);
  1028. if (!empty($sortmax->max)) {
  1029. $course->sortorder = $sortmax->max + 1;
  1030. unset($sortmax);
  1031. } else {
  1032. $course->sortorder = 100;
  1033. }
  1034. //Now, recode some languages (Moodle 1.5)
  1035. if ($course->lang == 'ma_nt') {
  1036. $course->lang = 'mi_nt';
  1037. }
  1038. //Disable course->metacourse if avoided in restore config
  1039. if (!$restore->metacourse) {
  1040. $course->metacourse = 0;
  1041. }
  1042. //Check if the theme exists in destination server
  1043. $themes = get_list_of_themes();
  1044. if (!in_array($course->theme, $themes)) {
  1045. $course->theme = '';
  1046. }
  1047. //Now insert the record
  1048. $newid = insert_record("course",$course);
  1049. if ($newid) {
  1050. //save old and new course id
  1051. backup_putid ($restore->backup_unique_code,"course",$course_header->course_id,$newid);
  1052. //Replace old course_id in course_header
  1053. $course_header->course_id = $newid;
  1054. $SESSION->restore->course_id = $newid;
  1055. return $newid;
  1056. } else {
  1057. $status = false;
  1058. }
  1059. }
  1060. return $status;
  1061. }
  1062. //This function creates all the block stuff when restoring courses
  1063. //It calls selectively to restore_create_block_instances() for 1.5
  1064. //and above backups. Upwards compatible with old blocks.
  1065. function restore_create_blocks($restore, $backup_block_format, $blockinfo, $xml_file) {
  1066. global $CFG;
  1067. $status = true;
  1068. blocks_delete_all_on_page(PAGE_COURSE_VIEW, $restore->course_id);
  1069. if (empty($backup_block_format)) { // This is a backup from Moodle < 1.5
  1070. if (empty($blockinfo)) {
  1071. // Looks like it's from Moodle < 1.3. Let's give the course default blocks...
  1072. $newpage = page_create_object(PAGE_COURSE_VIEW, $restore->course_id);
  1073. blocks_repopulate_page($newpage);
  1074. } else {
  1075. // We just have a blockinfo field, this is a legacy 1.4 or 1.3 backup
  1076. $blockrecords = get_records_select('block', '', '', 'name, id');
  1077. $temp_blocks_l = array();
  1078. $temp_blocks_r = array();
  1079. @list($temp_blocks_l, $temp_blocks_r) = explode(':', $blockinfo);
  1080. $temp_blocks = array(BLOCK_POS_LEFT => explode(',', $temp_blocks_l), BLOCK_POS_RIGHT => explode(',', $temp_blocks_r));
  1081. foreach($temp_blocks as $blockposition => $blocks) {
  1082. $blockweight = 0;
  1083. foreach($blocks as $blockname) {
  1084. if(!isset($blockrecords[$blockname])) {
  1085. // We don't know anything about this block!
  1086. continue;
  1087. }
  1088. $blockinstance = new stdClass;
  1089. // Remove any - prefix before doing the name-to-id mapping
  1090. if(substr($blockname, 0, 1) == '-') {
  1091. $blockname = substr($blockname, 1);
  1092. $blockinstance->visible = 0;
  1093. } else {
  1094. $blockinstance->visible = 1;
  1095. }
  1096. $blockinstance->blockid = $blockrecords[$blockname]->id;
  1097. $blockinstance->pageid = $restore->course_id;
  1098. $blockinstance->pagetype = PAGE_COURSE_VIEW;
  1099. $blockinstance->position = $blockposition;
  1100. $blockinstance->weight = $blockweight;
  1101. if(!$status = insert_record('block_instance', $blockinstance)) {
  1102. $status = false;
  1103. }
  1104. ++$blockweight;
  1105. }
  1106. }
  1107. }
  1108. } else if($backup_block_format == 'instances') {
  1109. $status = restore_create_block_instances($restore,$xml_file);
  1110. }
  1111. return $status;
  1112. }
  1113. //This function creates all the block_instances from xml when restoring in a
  1114. //new course
  1115. function restore_create_block_instances($restore,$xml_file) {
  1116. global $CFG;
  1117. $status = true;
  1118. //Check it exists
  1119. if (!file_exists($xml_file)) {
  1120. $status = false;
  1121. }
  1122. //Get info from xml
  1123. if ($status) {
  1124. $info = restore_read_xml_blocks($restore,$xml_file);
  1125. }
  1126. if(empty($info->instances)) {
  1127. return $status;
  1128. }
  1129. // First of all, iterate over the blocks to see which distinct pages we have
  1130. // in our hands and arrange the blocks accordingly.
  1131. $pageinstances = array();
  1132. foreach($info->instances as $instance) {
  1133. //pagetype and pageid black magic, we have to handle the case of blocks for the
  1134. //course, blocks from other pages in that course etc etc etc.
  1135. if($instance->pagetype == PAGE_COURSE_VIEW) {
  1136. // This one's easy...
  1137. $instance->pageid = $restore->course_id;
  1138. } else if (!empty($CFG->showblocksonmodpages)) {
  1139. $parts = explode('-', $instance->pagetype);
  1140. if($parts[0] == 'mod') {
  1141. if(!$restore->mods[$parts[1]]->restore) {
  1142. continue;
  1143. }
  1144. $getid = backup_getid($restore->backup_unique_code, $parts[1], $instance->pageid);
  1145. if (empty($getid->new_id)) {
  1146. // Failed, perhaps the module was not included in the restore MDL-13554
  1147. continue;
  1148. }
  1149. $instance->pageid = $getid->new_id;
  1150. }
  1151. else {
  1152. // Not invented here ;-)
  1153. continue;
  1154. }
  1155. } else {
  1156. // do not restore activity blocks if disabled
  1157. continue;
  1158. }
  1159. if(!isset($pageinstances[$instance->pagetype])) {
  1160. $pageinstances[$instance->pagetype] = array();
  1161. }
  1162. if(!isset($pageinstances[$instance->pagetype][$instance->pageid])) {
  1163. $pageinstances[$instance->pagetype][$instance->pageid] = array();
  1164. }
  1165. $pageinstances[$instance->pagetype][$instance->pageid][] = $instance;
  1166. }
  1167. $blocks = get_records_select('block', 'visible = 1', '', 'name, id, multiple');
  1168. // For each type of page we have restored
  1169. foreach($pageinstances as $thistypeinstances) {
  1170. // For each page id of that type
  1171. foreach($thistypeinstances as $thisidinstances) {
  1172. $addedblocks = array();
  1173. $maxweights = array();
  1174. // For each block instance in that page
  1175. foreach($thisidinstances as $instance) {
  1176. if(!isset($blocks[$instance->name])) {
  1177. //We are trying to restore a block we don't have...
  1178. continue;
  1179. }
  1180. //If we have already added this block once and multiples aren't allowed, disregard it
  1181. if(!$blocks[$instance->name]->multiple && isset($addedblocks[$instance->name])) {
  1182. continue;
  1183. }
  1184. //If its the first block we add to a new position, start weight counter equal to 0.
  1185. if(empty($maxweights[$instance->position])) {
  1186. $maxweights[$instance->position] = 0;
  1187. }
  1188. //If the instance weight is greater than the weight counter (we skipped some earlier
  1189. //blocks most probably), bring it back in line.
  1190. if($instance->weight > $maxweights[$instance->position]) {
  1191. $instance->weight = $maxweights[$instance->position];
  1192. }
  1193. //Add this instance
  1194. $instance->blockid = $blocks[$instance->name]->id;
  1195. // This will only be set if we come from 1.7 and above backups
  1196. // Also, must do this before insert (insert_record unsets id)
  1197. if (!empty($instance->id)) {
  1198. $oldid = $instance->id;
  1199. } else {
  1200. $oldid = 0;
  1201. }
  1202. if ($instance->id = insert_record('block_instance', $instance)) {
  1203. // Create block instance
  1204. if (!$blockobj = block_instance($instance->name, $instance)) {
  1205. $status = false;
  1206. break;
  1207. }
  1208. // Run the block restore if needed
  1209. if ($blockobj->backuprestore_instancedata_used()) {
  1210. // Get restore information
  1211. $data = backup_getid($restore->backup_unique_code,'block_instance',$oldid);
  1212. $data->new_id = $instance->id; // For completeness
  1213. if (!$blockobj->instance_restore($restore, $data)) {
  1214. $status = false;
  1215. break;
  1216. }
  1217. }
  1218. // Save oldid after block restore process because info will be over-written with blank string
  1219. if ($oldid) {
  1220. backup_putid ($restore->backup_unique_code,"block_instance",$oldid,$instance->id);
  1221. }
  1222. } else {
  1223. $status = false;
  1224. break;
  1225. }
  1226. //Get an object for the block and tell it it's been restored so it can update dates
  1227. //etc. if necessary
  1228. if ($blockobj = block_instance($instance->name,$instance)) {
  1229. $blockobj->after_restore($restore);
  1230. }
  1231. //Now we can increment the weight counter
  1232. ++$maxweights[$instance->position];
  1233. //Keep track of block types we have already added
  1234. $addedblocks[$instance->name] = true;
  1235. }
  1236. }
  1237. }
  1238. return $status;
  1239. }
  1240. //This function creates all the course_sections and course_modules from xml
  1241. //when restoring in a new course or simply checks sections and create records
  1242. //in backup_ids when restoring in a existing course
  1243. function restore_create_sections(&$restore, $xml_file) {
  1244. global $CFG,$db;
  1245. $status = true;
  1246. //Check it exists
  1247. if (!file_exists($xml_file)) {
  1248. $status = false;
  1249. }
  1250. //Get info from xml
  1251. if ($status) {
  1252. $info = restore_read_xml_sections($xml_file);
  1253. }
  1254. //Put the info in the DB, recoding ids and saving the in backup tables
  1255. $sequence = "";
  1256. if ($info) {
  1257. //For each, section, save it to db
  1258. foreach ($info->sections as $key => $sect) {
  1259. $sequence = "";
  1260. $section = new object();
  1261. $section->course = $restore->course_id;
  1262. $section->section = $sect->number;
  1263. $section->summary = backup_todb($sect->summary);
  1264. $section->visible = $sect->visible;
  1265. $section->sequence = "";
  1266. //Now calculate the section's newid
  1267. $newid = 0;
  1268. if ($restore->restoreto == RESTORETO_NEW_COURSE) {
  1269. //Save it to db (only if restoring to new course)
  1270. $newid = insert_record("course_sections",$section);
  1271. } else {
  1272. //Get section id when restoring in existing course
  1273. $rec = get_record("course_sections","course",$restore->course_id,
  1274. "section",$section->section);
  1275. //If section exists, has empty summary and backup has some summary, use it. MDL-8848
  1276. if ($rec && empty($rec->summary) && !empty($section->summary)) {
  1277. $rec->summary = $section->summary;
  1278. update_record("course_sections", $rec);
  1279. }
  1280. //If that section doesn't exist, get section 0 (every mod will be
  1281. //asigned there
  1282. if(!$rec) {
  1283. $rec = get_record("course_sections","course",$restore->course_id,
  1284. "section","0");
  1285. }
  1286. //New check. If section 0 doesn't exist, insert it here !!
  1287. //Teorically this never should happen but, in practice, some users
  1288. //have reported this issue.
  1289. if(!$rec) {
  1290. $zero_sec = new object();
  1291. $zero_sec->course = $restore->course_id;
  1292. $zero_sec->section = 0;
  1293. $zero_sec->summary = "";
  1294. $zero_sec->sequence = "";
  1295. $newid = insert_record("course_sections",$zero_sec);
  1296. $rec->id = $newid;
  1297. $rec->sequence = "";
  1298. }
  1299. $newid = $rec->id;
  1300. $sequence = $rec->sequence;
  1301. }
  1302. if ($newid) {
  1303. //save old and new section id
  1304. backup_putid ($restore->backup_unique_code,"course_sections",$key,$newid);
  1305. } else {
  1306. $status = false;
  1307. }
  1308. //If all is OK, go with associated mods
  1309. if ($status) {
  1310. //If we have mods in the section
  1311. if (!empty($sect->mods)) {
  1312. //For each mod inside section
  1313. foreach ($sect->mods as $keym => $mod) {
  1314. // Yu: This part is called repeatedly for every instance,
  1315. // so it is necessary to set the granular flag and check isset()
  1316. // when the first instance of this type of mod is processed.
  1317. //if (!isset($restore->mods[$mod->type]->granular) && isset($restore->mods[$mod->type]->instances) && is_array($restore->mods[$mod->type]->instances)) {
  1318. if (!isset($restore->mods[$mod->type]->granular)) {
  1319. if (isset($restore->mods[$mod->type]->instances) && is_array($restore->mods[$mod->type]->instances)) {
  1320. // This defines whether we want to restore specific
  1321. // instances of the modules (granular restore), or
  1322. // whether we don't care and just want to restore
  1323. // all module instances (non-granular).
  1324. $restore->mods[$mod->type]->granular = true;
  1325. } else {
  1326. $restore->mods[$mod->type]->granular = false;
  1327. }
  1328. }
  1329. //Check if we've to restore this module (and instance)
  1330. if (!empty($restore->mods[$mod->type]->restore)) {
  1331. if (empty($restore->mods[$mod->type]->granular) // we don't care about per instance
  1332. || (array_key_exists($mod->instance,$restore->mods[$mod->type]->instances)
  1333. && !empty($restore->mods[$mod->type]->instances[$mod->instance]->restore))) {
  1334. //Get the module id from modules
  1335. $module = get_record("modules","name",$mod->type);
  1336. if ($module) {
  1337. $course_module = new object();
  1338. $course_module->course = $restore->course_id;
  1339. $course_module->module = $module->id;
  1340. $course_module->section = $newid;
  1341. $course_module->added = $mod->added;
  1342. $course_module->score = $mod->score;
  1343. $course_module->indent = $mod->indent;
  1344. $course_module->visible = $mod->visible;
  1345. $course_module->groupmode = $mod->groupmode;
  1346. if ($mod->groupingid and $grouping = restore_grouping_getid($restore, $mod->groupingid)) {
  1347. $course_module->groupingid = $grouping->new_id;
  1348. } else {
  1349. $course_module->groupingid = 0;
  1350. }
  1351. $course_module->groupmembersonly = $mod->groupmembersonly;
  1352. $course_module->instance = 0;
  1353. //NOTE: The instance (new) is calculated and updated in db in the
  1354. // final step of the restore. We don't know it yet.
  1355. //print_object($course_module); //Debug
  1356. //Save it to db
  1357. if ($mod->idnumber) {
  1358. if (grade_verify_idnumber($mod->idnumber, $restore->course_id)) {
  1359. $course_module->idnumber = $mod->idnumber;
  1360. }
  1361. }
  1362. $newidmod = insert_record("course_modules", addslashes_recursive($course_module));
  1363. if ($newidmod) {
  1364. //save old and new module id
  1365. //In the info field, we save the original instance of the module
  1366. //to use it later
  1367. backup_putid ($restore->backup_unique_code,"course_modules",
  1368. $keym,$newidmod,$mod->instance);
  1369. $restore->mods[$mod->type]->instances[$mod->instance]->restored_as_course_module = $newidmod;
  1370. } else {
  1371. $status = false;
  1372. }
  1373. //Now, calculate the sequence field
  1374. if ($status) {
  1375. if ($sequence) {
  1376. $sequence .= ",".$newidmod;
  1377. } else {
  1378. $sequence = $newidmod;
  1379. }
  1380. }
  1381. } else {
  1382. $status = false;
  1383. }
  1384. }
  1385. }
  1386. }
  1387. }
  1388. }
  1389. //If all is OK, update sequence field in course_sections
  1390. if ($status) {
  1391. if (isset($sequence)) {
  1392. $update_rec = new object();
  1393. $update_rec->id = $newid;
  1394. $update_rec->sequence = $sequence;
  1395. $status = update_record("course_sections",$update_rec);
  1396. }
  1397. }
  1398. }
  1399. } else {
  1400. $status = false;
  1401. }
  1402. return $status;
  1403. }
  1404. //Called to set up any course-format specific data that may be in the file
  1405. function restore_set_format_data($restore,$xml_file) {
  1406. global $CFG,$db;
  1407. $status = true;
  1408. //Check it exists
  1409. if (!file_exists($xml_file)) {
  1410. return false;
  1411. }
  1412. //Load data from XML to info
  1413. if(!($info = restore_read_xml_formatdata($xml_file))) {
  1414. return false;
  1415. }
  1416. //Process format data if there is any
  1417. if (isset($info->format_data)) {
  1418. if(!$format=get_field('course','format','id',$restore->course_id)) {
  1419. return false;
  1420. }
  1421. // If there was any data then it must have a restore method
  1422. $file=$CFG->dirroot."/course/format/$format/restorelib.php";
  1423. if(!file_exists($file)) {
  1424. return false;
  1425. }
  1426. require_once($file);
  1427. $function=$format.'_restore_format_data';
  1428. if(!function_exists($function)) {
  1429. return false;
  1430. }
  1431. return $function($restore,$info->format_data);
  1432. }
  1433. // If we got here then there's no data, but that's cool
  1434. return true;
  1435. }
  1436. //This function creates all the metacourse data from xml, notifying
  1437. //about each incidence
  1438. function restore_create_metacourse($restore,$xml_file) {
  1439. global $CFG,$db;
  1440. $status = true;
  1441. //Check it exists
  1442. if (!file_exists($xml_file)) {
  1443. $status = false;
  1444. }
  1445. //Get info from xml
  1446. if ($status) {
  1447. //Load data from XML to info
  1448. $info = restore_read_xml_metacourse($xml_file);
  1449. }
  1450. //Process info about metacourse
  1451. if ($status and $info) {
  1452. //Process child records
  1453. if (!empty($info->childs)) {
  1454. foreach ($info->childs as $child) {
  1455. $dbcourse = false;
  1456. $dbmetacourse = false;
  1457. //Check if child course exists in destination server
  1458. //(by id in the same server or by idnumber and shortname in other server)
  1459. if (backup_is_same_site($restore)) {
  1460. //Same server, lets see by id
  1461. $dbcourse = get_record('course','id',$child->id);
  1462. } else {
  1463. //Different server, lets see by idnumber and shortname, and only ONE record
  1464. $dbcount = count_records('course','idnumber',$child->idnumber,'shortname',$child->shortname);
  1465. if ($dbcount == 1) {
  1466. $dbcourse = get_record('course','idnumber',$child->idnumber,'shortname',$child->shortname);
  1467. }
  1468. }
  1469. //If child course has been found, insert data
  1470. if ($dbcourse) {
  1471. $dbmetacourse->child_course = $dbcourse->id;
  1472. $dbmetacourse->parent_course = $restore->course_id;
  1473. $status = insert_record ('course_meta',$dbmetacourse);
  1474. } else {
  1475. //Child course not found, notice!
  1476. if (!defined('RESTORE_SILENTLY')) {
  1477. echo '<ul><li>'.get_string ('childcoursenotfound').' ('.$child->id.'/'.$child->idnumber.'/'.$child->shortname.')</li></ul>';
  1478. }
  1479. }
  1480. }
  1481. //Now, recreate student enrolments...
  1482. sync_metacourse($restore->course_id);
  1483. }
  1484. //Process parent records
  1485. if (!empty($info->parents)) {
  1486. foreach ($info->parents as $parent) {
  1487. $dbcourse = false;
  1488. $dbmetacourse = false;
  1489. //Check if parent course exists in destination server
  1490. //(by id in the same server or by idnumber and shortname in other server)
  1491. if (backup_is_same_site($restore)) {
  1492. //Same server, lets see by id
  1493. $dbcourse = get_record('course','id',$parent->id);
  1494. } else {
  1495. //Different server, lets see by idnumber and shortname, and only ONE record
  1496. $dbcount = count_records('course','idnumber',$parent->idnumber,'shortname',$parent->shortname);
  1497. if ($dbcount == 1) {
  1498. $dbcourse = get_record('course','idnumber',$parent->idnumber,'shortname',$parent->shortname);
  1499. }
  1500. }
  1501. //If parent course has been found, insert data if it is a metacourse
  1502. if ($dbcourse) {
  1503. if ($dbcourse->metacourse) {
  1504. $dbmetacourse->parent_course = $dbcourse->id;
  1505. $dbmetacourse->child_course = $restore->course_id;
  1506. $status = insert_record ('course_meta',$dbmetacourse);
  1507. //Now, recreate student enrolments in parent course
  1508. sync_metacourse($dbcourse->id);
  1509. } else {
  1510. //Parent course isn't metacourse, notice!
  1511. if (!defined('RESTORE_SILENTLY')) {
  1512. echo '<ul><li>'.get_string ('parentcoursenotmetacourse').' ('.$parent->id.'/'.$parent->idnumber.'/'.$parent->shortname.')</li></ul>';
  1513. }
  1514. }
  1515. } else {
  1516. //Parent course not found, notice!
  1517. if (!defined('RESTORE_SILENTLY')) {
  1518. echo '<ul><li>'.get_string ('parentcoursenotfound').' ('.$parent->id.'/'.$parent->idnumber.'/'.$parent->shortname.')</li></ul>';
  1519. }
  1520. }
  1521. }
  1522. }
  1523. }
  1524. return $status;
  1525. }
  1526. /**
  1527. * This function migrades all the pre 1.9 gradebook data from xml
  1528. */
  1529. function restore_migrate_old_gradebook($restore,$xml_file) {
  1530. global $CFG;
  1531. $status = true;
  1532. //Check it exists
  1533. if (!file_exists($xml_file)) {
  1534. return false;
  1535. }
  1536. // Get info from xml
  1537. // info will contain the number of record to process
  1538. $info = restore_read_xml_gradebook($restore, $xml_file);
  1539. // If we have info, then process
  1540. if (empty($info)) {
  1541. return $status;
  1542. }
  1543. // make sure top course category exists
  1544. $course_category = grade_category::fetch_course_category($restore->course_id);
  1545. $course_category->load_grade_item();
  1546. // we need to know if all grade items that were backed up are being restored
  1547. // if that is not the case, we do not restore grade categories nor gradeitems of category type or course type
  1548. // i.e. the aggregated grades of that category
  1549. $restoreall = true; // set to false if any grade_item is not selected/restored
  1550. $importing = !empty($SESSION->restore->importing); // there should not be a way to import old backups, but anyway ;-)
  1551. if ($importing) {
  1552. $restoreall = false;
  1553. } else {
  1554. $prev_grade_items = grade_item::fetch_all(array('courseid'=>$restore->course_id));
  1555. $prev_grade_cats = grade_category::fetch_all(array('courseid'=>$restore->course_id));
  1556. // if any categories already present, skip restore of categories from backup
  1557. if (count($prev_grade_items) > 1 or count($prev_grade_cats) > 1) {
  1558. $restoreall = false;
  1559. }
  1560. unset($prev_grade_items);
  1561. unset($prev_grade_cats);
  1562. }
  1563. // force creation of all grade_items - the course_modules already exist
  1564. grade_force_full_regrading($restore->course_id);
  1565. grade_grab_course_grades($restore->course_id);
  1566. // Start ul
  1567. if (!defined('RESTORE_SILENTLY')) {
  1568. echo '<ul>';
  1569. }
  1570. /// Process letters
  1571. $context = get_context_instance(CONTEXT_COURSE, $restore->course_id);
  1572. // respect current grade letters if defined
  1573. if ($status and $restoreall and !record_exists('grade_letters', 'contextid', $context->id)) {
  1574. if (!defined('RESTORE_SILENTLY')) {
  1575. echo '<li>'.get_string('gradeletters','grades').'</li>';
  1576. }
  1577. // Fetch recordset_size records in each iteration
  1578. $recs = get_records_select("backup_ids","table_name = 'grade_letter' AND backup_code = $restore->backup_unique_code",
  1579. "",
  1580. "old_id");
  1581. if ($recs) {
  1582. foreach ($recs as $rec) {
  1583. // Get the full record from backup_ids
  1584. $data = backup_getid($restore->backup_unique_code,'grade_letter',$rec->old_id);
  1585. if ($data) {
  1586. $info = $data->info;
  1587. $dbrec = new object();
  1588. $dbrec->contextid = $context->id;
  1589. $dbrec->lowerboundary = backup_todb($info['GRADE_LETTER']['#']['GRADE_LOW']['0']['#']);
  1590. $dbrec->letter = backup_todb($info['GRADE_LETTER']['#']['LETTER']['0']['#']);
  1591. insert_record('grade_letters', $dbrec);
  1592. }
  1593. }
  1594. }
  1595. }
  1596. if (!defined('RESTORE_SILENTLY')) {
  1597. echo '<li>'.get_string('categories','grades').'</li>';
  1598. }
  1599. //Fetch recordset_size records in each iteration
  1600. $recs = get_records_select("backup_ids","table_name = 'grade_category' AND backup_code = $restore->backup_unique_code",
  1601. "old_id",
  1602. "old_id");
  1603. $cat_count = count($recs);
  1604. if ($recs) {
  1605. foreach ($recs as $rec) {
  1606. //Get the full record from backup_ids
  1607. $data = backup_getid($restore->backup_unique_code,'grade_category',$rec->old_id);
  1608. if ($data) {
  1609. //Now get completed xmlized object
  1610. $info = $data->info;
  1611. if ($restoreall) {
  1612. if ($cat_count == 1) {
  1613. $course_category->fullname = backup_todb($info['GRADE_CATEGORY']['#']['NAME']['0']['#'], false);
  1614. $course_category->droplow = backup_todb($info['GRADE_CATEGORY']['#']['DROP_X_LOWEST']['0']['#'], false);
  1615. $course_category->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN2;
  1616. $course_category->aggregateonlygraded = 0;
  1617. $course_category->update('restore');
  1618. $grade_category = $course_category;
  1619. } else {
  1620. $grade_category = new grade_category();
  1621. $grade_category->courseid = $restore->course_id;
  1622. $grade_category->fullname = backup_todb($info['GRADE_CATEGORY']['#']['NAME']['0']['#'], false);
  1623. $grade_category->droplow = backup_todb($info['GRADE_CATEGORY']['#']['DROP_X_LOWEST']['0']['#'], false);
  1624. $grade_category->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN2;
  1625. $grade_category->aggregateonlygraded = 0;
  1626. $grade_category->insert('restore');
  1627. $grade_category->load_grade_item(); // force cretion of grade_item
  1628. }
  1629. } else {
  1630. $grade_category = null;
  1631. }
  1632. /// now, restore grade_items
  1633. $items = array();
  1634. if (!empty($info['GRADE_CATEGORY']['#']['GRADE_ITEMS']['0']['#']['GRADE_ITEM'])) {
  1635. //Iterate over items
  1636. foreach ($info['GRADE_CATEGORY']['#']['GRADE_ITEMS']['0']['#']['GRADE_ITEM'] as $ite_info) {
  1637. $modname = backup_todb($ite_info['#']['MODULE_NAME']['0']['#'], false);
  1638. $olditeminstance = backup_todb($ite_info['#']['CMINSTANCE']['0']['#'], false);
  1639. if (!$mod = backup_getid($restore->backup_unique_code,$modname, $olditeminstance)) {
  1640. continue; // not restored
  1641. }
  1642. $iteminstance = $mod->new_id;
  1643. if (!$cm = get_coursemodule_from_instance($modname, $iteminstance, $restore->course_id)) {
  1644. continue; // does not exist
  1645. }
  1646. if (!$grade_item = grade_item::fetch(array('itemtype'=>'mod', 'itemmodule'=>$cm->modname, 'iteminstance'=>$cm->instance, 'courseid'=>$cm->course, 'itemnumber'=>0))) {
  1647. continue; // no item yet??
  1648. }
  1649. if ($grade_category) {
  1650. $grade_item->sortorder = backup_todb($ite_info['#']['SORT_ORDER']['0']['#'], false);
  1651. $grade_item->set_parent($grade_category->id);
  1652. }
  1653. if ($importing
  1654. or ($grade_item->itemtype == 'mod' and !restore_userdata_selected($restore, $grade_item->itemmodule, $olditeminstance))) {
  1655. // module instance not selected when restored using granular
  1656. // skip this item
  1657. continue;
  1658. }
  1659. //Now process grade excludes
  1660. if (empty($ite_info['#']['GRADE_EXCEPTIONS'])) {
  1661. continue;
  1662. }
  1663. foreach($ite_info['#']['GRADE_EXCEPTIONS']['0']['#']['GRADE_EXCEPTION'] as $exc_info) {
  1664. if ($u = backup_getid($restore->backup_unique_code,"user",backup_todb($exc_info['#']['USERID']['0']['#']))) {
  1665. $userid = $u->new_id;
  1666. $grade_grade = new grade_grade(array('itemid'=>$grade_item->id, 'userid'=>$userid));
  1667. $grade_grade->excluded = 1;
  1668. if ($grade_grade->id) {
  1669. $grade_grade->update('restore');
  1670. } else {
  1671. $grade_grade->insert('restore');
  1672. }
  1673. }
  1674. }
  1675. }
  1676. }
  1677. }
  1678. }
  1679. }
  1680. if (!defined('RESTORE_SILENTLY')) {
  1681. //End ul
  1682. echo '</ul>';
  1683. }
  1684. return $status;
  1685. }
  1686. /**
  1687. * This function creates all the gradebook data from xml
  1688. */
  1689. function restore_create_gradebook($restore,$xml_file) {
  1690. global $CFG;
  1691. $status = true;
  1692. //Check it exists
  1693. if (!file_exists($xml_file)) {
  1694. return false;
  1695. }
  1696. // Get info from xml
  1697. // info will contain the number of record to process
  1698. $info = restore_read_xml_gradebook($restore, $xml_file);
  1699. // If we have info, then process
  1700. if (empty($info)) {
  1701. return $status;
  1702. }
  1703. if (empty($CFG->disablegradehistory) and isset($info->gradebook_histories) and $info->gradebook_histories == "true") {
  1704. $restore_histories = true;
  1705. } else {
  1706. $restore_histories = false;
  1707. }
  1708. // make sure top course category exists
  1709. $course_category = grade_category::fetch_course_category($restore->course_id);
  1710. $course_category->load_grade_item();
  1711. // we need to know if all grade items that were backed up are being restored
  1712. // if that is not the case, we do not restore grade categories nor gradeitems of category type or course type
  1713. // i.e. the aggregated grades of that category
  1714. $restoreall = true; // set to false if any grade_item is not selected/restored or already exist
  1715. $importing = !empty($SESSION->restore->importing);
  1716. if ($importing) {
  1717. $restoreall = false;
  1718. } else {
  1719. $prev_grade_items = grade_item::fetch_all(array('courseid'=>$restore->course_id));
  1720. $prev_grade_cats = grade_category::fetch_all(array('courseid'=>$restore->course_id));
  1721. // if any categories already present, skip restore of categories from backup - course item or category already exist
  1722. if (count($prev_grade_items) > 1 or count($prev_grade_cats) > 1) {
  1723. $restoreall = false;
  1724. }
  1725. unset($prev_grade_items);
  1726. unset($prev_grade_cats);
  1727. if ($restoreall) {
  1728. if ($recs = get_records_select("backup_ids","table_name = 'grade_items' AND backup_code = $restore->backup_unique_code", "", "old_id")) {
  1729. foreach ($recs as $rec) {
  1730. if ($data = backup_getid($restore->backup_unique_code,'grade_items',$rec->old_id)) {
  1731. $info = $data->info;
  1732. // do not restore if this grade_item is a mod, and
  1733. $itemtype = backup_todb($info['GRADE_ITEM']['#']['ITEMTYPE']['0']['#']);
  1734. if ($itemtype == 'mod') {
  1735. $olditeminstance = backup_todb($info['GRADE_ITEM']['#']['ITEMINSTANCE']['0']['#']);
  1736. $itemmodule = backup_todb($info['GRADE_ITEM']['#']['ITEMMODULE']['0']['#']);
  1737. if (empty($restore->mods[$itemmodule]->granular)) {
  1738. continue;
  1739. } else if (!empty($restore->mods[$itemmodule]->instances[$olditeminstance]->restore)) {
  1740. continue;
  1741. }
  1742. // at least one activity should not be restored - do not restore categories and manual items at all
  1743. $restoreall = false;
  1744. break;
  1745. }
  1746. }
  1747. }
  1748. }
  1749. }
  1750. }
  1751. // Start ul
  1752. if (!defined('RESTORE_SILENTLY')) {
  1753. echo '<ul>';
  1754. }
  1755. // array of restored categories - speedup ;-)
  1756. $cached_categories = array();
  1757. $outcomes = array();
  1758. /// Process letters
  1759. $context = get_context_instance(CONTEXT_COURSE, $restore->course_id);
  1760. // respect current grade letters if defined
  1761. if ($status and $restoreall and !record_exists('grade_letters', 'contextid', $context->id)) {
  1762. if (!defined('RESTORE_SILENTLY')) {
  1763. echo '<li>'.get_string('gradeletters','grades').'</li>';
  1764. }
  1765. // Fetch recordset_size records in each iteration
  1766. $recs = get_records_select("backup_ids","table_name = 'grade_letters' AND backup_code = $restore->backup_unique_code",
  1767. "",
  1768. "old_id");
  1769. if ($recs) {
  1770. foreach ($recs as $rec) {
  1771. // Get the full record from backup_ids
  1772. $data = backup_getid($restore->backup_unique_code,'grade_letters',$rec->old_id);
  1773. if ($data) {
  1774. $info = $data->info;
  1775. $dbrec = new object();
  1776. $dbrec->contextid = $context->id;
  1777. $dbrec->lowerboundary = backup_todb($info['GRADE_LETTER']['#']['LOWERBOUNDARY']['0']['#']);
  1778. $dbrec->letter = backup_todb($info['GRADE_LETTER']['#']['LETTER']['0']['#']);
  1779. insert_record('grade_letters', $dbrec);
  1780. }
  1781. }
  1782. }
  1783. }
  1784. /// Preprocess outcomes - do not store them yet!
  1785. if ($status and !$importing and $restoreall) {
  1786. if (!defined('RESTORE_SILENTLY')) {
  1787. echo '<li>'.get_string('gradeoutcomes','grades').'</li>';
  1788. }
  1789. $recs = get_records_select("backup_ids","table_name = 'grade_outcomes' AND backup_code = '$restore->backup_unique_code'",
  1790. "",
  1791. "old_id");
  1792. if ($recs) {
  1793. foreach ($recs as $rec) {
  1794. //Get the full record from backup_ids
  1795. $data = backup_getid($restore->backup_unique_code,'grade_outcomes',$rec->old_id);
  1796. if ($data) {
  1797. $info = $data->info;
  1798. //first find out if outcome already exists
  1799. $shortname = backup_todb($info['GRADE_OUTCOME']['#']['SHORTNAME']['0']['#']);
  1800. if ($candidates = get_records_sql("SELECT *
  1801. FROM {$CFG->prefix}grade_outcomes
  1802. WHERE (courseid IS NULL OR courseid = $restore->course_id)
  1803. AND shortname = '$shortname'
  1804. ORDER BY courseid ASC, id ASC")) {
  1805. $grade_outcome = reset($candidates);
  1806. $outcomes[$rec->old_id] = $grade_outcome;
  1807. continue;
  1808. }
  1809. $dbrec = new object();
  1810. if (has_capability('moodle/grade:manageoutcomes', get_context_instance(CONTEXT_SYSTEM))) {
  1811. $oldoutcome = backup_todb($info['GRADE_OUTCOME']['#']['COURSEID']['0']['#']);
  1812. if (empty($oldoutcome)) {
  1813. //site wide
  1814. $dbrec->courseid = null;
  1815. } else {
  1816. //course only
  1817. $dbrec->courseid = $restore->course_id;
  1818. }
  1819. } else {
  1820. // no permission to add site outcomes
  1821. $dbrec->courseid = $restore->course_id;
  1822. }
  1823. //Get the fields
  1824. $dbrec->shortname = backup_todb($info['GRADE_OUTCOME']['#']['SHORTNAME']['0']['#'], false);
  1825. $dbrec->fullname = backup_todb($info['GRADE_OUTCOME']['#']['FULLNAME']['0']['#'], false);
  1826. $dbrec->scaleid = backup_todb($info['GRADE_OUTCOME']['#']['SCALEID']['0']['#'], false);
  1827. $dbrec->description = backup_todb($info['GRADE_OUTCOME']['#']['DESCRIPTION']['0']['#'], false);
  1828. $dbrec->timecreated = backup_todb($info['GRADE_OUTCOME']['#']['TIMECREATED']['0']['#'], false);
  1829. $dbrec->timemodified = backup_todb($info['GRADE_OUTCOME']['#']['TIMEMODIFIED']['0']['#'], false);
  1830. $dbrec->usermodified = backup_todb($info['GRADE_OUTCOME']['#']['USERMODIFIED']['0']['#'], false);
  1831. //Need to recode the scaleid
  1832. if ($scale = backup_getid($restore->backup_unique_code, 'scale', $dbrec->scaleid)) {
  1833. $dbrec->scaleid = $scale->new_id;
  1834. }
  1835. //Need to recode the usermodified
  1836. if ($modifier = backup_getid($restore->backup_unique_code, 'user', $dbrec->usermodified)) {
  1837. $dbrec->usermodified = $modifier->new_id;
  1838. }
  1839. $grade_outcome = new grade_outcome($dbrec, false);
  1840. $outcomes[$rec->old_id] = $grade_outcome;
  1841. }
  1842. }
  1843. }
  1844. }
  1845. /// Process grade items and grades
  1846. if ($status) {
  1847. if (!defined('RESTORE_SILENTLY')) {
  1848. echo '<li>'.get_string('gradeitems','grades').'</li>';
  1849. }
  1850. $counter = 0;
  1851. //Fetch recordset_size records in each iteration
  1852. $recs = get_records_select("backup_ids","table_name = 'grade_items' AND backup_code = '$restore->backup_unique_code'",
  1853. "id", // restore in the backup order
  1854. "old_id");
  1855. if ($recs) {
  1856. foreach ($recs as $rec) {
  1857. //Get the full record from backup_ids
  1858. $data = backup_getid($restore->backup_unique_code,'grade_items',$rec->old_id);
  1859. if ($data) {
  1860. $info = $data->info;
  1861. // first find out if category or normal item
  1862. $itemtype = backup_todb($info['GRADE_ITEM']['#']['ITEMTYPE']['0']['#'], false);
  1863. if ($itemtype == 'course' or $itemtype == 'category') {
  1864. if (!$restoreall or $importing) {
  1865. continue;
  1866. }
  1867. $oldcat = backup_todb($info['GRADE_ITEM']['#']['ITEMINSTANCE']['0']['#'], false);
  1868. if (!$cdata = backup_getid($restore->backup_unique_code,'grade_categories',$oldcat)) {
  1869. continue;
  1870. }
  1871. $cinfo = $cdata->info;
  1872. unset($cdata);
  1873. if ($itemtype == 'course') {
  1874. $course_category->fullname = backup_todb($cinfo['GRADE_CATEGORY']['#']['FULLNAME']['0']['#'], false);
  1875. $course_category->aggregation = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATION']['0']['#'], false);
  1876. $course_category->keephigh = backup_todb($cinfo['GRADE_CATEGORY']['#']['KEEPHIGH']['0']['#'], false);
  1877. $course_category->droplow = backup_todb($cinfo['GRADE_CATEGORY']['#']['DROPLOW']['0']['#'], false);
  1878. $course_category->aggregateonlygraded = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATEONLYGRADED']['0']['#'], false);
  1879. $course_category->aggregateoutcomes = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATEOUTCOMES']['0']['#'], false);
  1880. $course_category->aggregatesubcats = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATESUBCATS']['0']['#'], false);
  1881. $course_category->timecreated = backup_todb($cinfo['GRADE_CATEGORY']['#']['TIMECREATED']['0']['#'], false);
  1882. $course_category->update('restore');
  1883. $status = backup_putid($restore->backup_unique_code,'grade_categories',$oldcat,$course_category->id) && $status;
  1884. $cached_categories[$oldcat] = $course_category;
  1885. $grade_item = $course_category->get_grade_item();
  1886. } else {
  1887. $oldparent = backup_todb($cinfo['GRADE_CATEGORY']['#']['PARENT']['0']['#'], false);
  1888. if (empty($cached_categories[$oldparent])) {
  1889. debugging('parent not found '.$oldparent);
  1890. continue; // parent not found, sorry
  1891. }
  1892. $grade_category = new grade_category();
  1893. $grade_category->courseid = $restore->course_id;
  1894. $grade_category->parent = $cached_categories[$oldparent]->id;
  1895. $grade_category->fullname = backup_todb($cinfo['GRADE_CATEGORY']['#']['FULLNAME']['0']['#'], false);
  1896. $grade_category->aggregation = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATION']['0']['#'], false);
  1897. $grade_category->keephigh = backup_todb($cinfo['GRADE_CATEGORY']['#']['KEEPHIGH']['0']['#'], false);
  1898. $grade_category->droplow = backup_todb($cinfo['GRADE_CATEGORY']['#']['DROPLOW']['0']['#'], false);
  1899. $grade_category->aggregateonlygraded = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATEONLYGRADED']['0']['#'], false);
  1900. $grade_category->aggregateoutcomes = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATEOUTCOMES']['0']['#'], false);
  1901. $grade_category->aggregatesubcats = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATESUBCATS']['0']['#'], false);
  1902. $grade_category->timecreated = backup_todb($cinfo['GRADE_CATEGORY']['#']['TIMECREATED']['0']['#'], false);
  1903. $grade_category->insert('restore');
  1904. $status = backup_putid($restore->backup_unique_code,'grade_categories',$oldcat,$grade_category->id) && $status;
  1905. $cached_categories[$oldcat] = $grade_category;
  1906. $grade_item = $grade_category->get_grade_item(); // creates grade_item too
  1907. }
  1908. unset($cinfo);
  1909. $idnumber = backup_todb($info['GRADE_ITEM']['#']['IDNUMBER']['0']['#'], false);
  1910. if (grade_verify_idnumber($idnumber, $restore->course_id)) {
  1911. $grade_item->idnumber = $idnumber;
  1912. }
  1913. $grade_item->itemname = backup_todb($info['GRADE_ITEM']['#']['ITEMNAME']['0']['#'], false);
  1914. $grade_item->iteminfo = backup_todb($info['GRADE_ITEM']['#']['ITEMINFO']['0']['#'], false);
  1915. $grade_item->gradetype = backup_todb($info['GRADE_ITEM']['#']['GRADETYPE']['0']['#'], false);
  1916. $grade_item->calculation = backup_todb($info['GRADE_ITEM']['#']['CALCULATION']['0']['#'], false);
  1917. $grade_item->grademax = backup_todb($info['GRADE_ITEM']['#']['GRADEMAX']['0']['#'], false);
  1918. $grade_item->grademin = backup_todb($info['GRADE_ITEM']['#']['GRADEMIN']['0']['#'], false);
  1919. $grade_item->gradepass = backup_todb($info['GRADE_ITEM']['#']['GRADEPASS']['0']['#'], false);
  1920. $grade_item->multfactor = backup_todb($info['GRADE_ITEM']['#']['MULTFACTOR']['0']['#'], false);
  1921. $grade_item->plusfactor = backup_todb($info['GRADE_ITEM']['#']['PLUSFACTOR']['0']['#'], false);
  1922. $grade_item->aggregationcoef = backup_todb($info['GRADE_ITEM']['#']['AGGREGATIONCOEF']['0']['#'], false);
  1923. $grade_item->display = backup_todb($info['GRADE_ITEM']['#']['DISPLAY']['0']['#'], false);
  1924. $grade_item->decimals = backup_todb($info['GRADE_ITEM']['#']['DECIMALS']['0']['#'], false);
  1925. $grade_item->hidden = backup_todb($info['GRADE_ITEM']['#']['HIDDEN']['0']['#'], false);
  1926. $grade_item->locked = backup_todb($info['GRADE_ITEM']['#']['LOCKED']['0']['#'], false);
  1927. $grade_item->locktime = backup_todb($info['GRADE_ITEM']['#']['LOCKTIME']['0']['#'], false);
  1928. $grade_item->timecreated = backup_todb($info['GRADE_ITEM']['#']['TIMECREATED']['0']['#'], false);
  1929. if (backup_todb($info['GRADE_ITEM']['#']['SCALEID']['0']['#'], false)) {
  1930. $scale = backup_getid($restore->backup_unique_code,"scale",backup_todb($info['GRADE_ITEM']['#']['SCALEID']['0']['#'], false));
  1931. $grade_item->scaleid = $scale->new_id;
  1932. }
  1933. if (backup_todb($info['GRADE_ITEM']['#']['OUTCOMEID']['0']['#'], false)) {
  1934. $outcome = backup_getid($restore->backup_unique_code,"grade_outcomes",backup_todb($info['GRADE_ITEM']['#']['OUTCOMEID']['0']['#'], false));
  1935. $grade_item->outcomeid = $outcome->new_id;
  1936. }
  1937. $grade_item->update('restore');
  1938. $status = backup_putid($restore->backup_unique_code,"grade_items", $rec->old_id, $grade_item->id) && $status;
  1939. } else {
  1940. if ($itemtype != 'mod' and (!$restoreall or $importing)) {
  1941. // not extra gradebook stuff if restoring individual activities or something already there
  1942. continue;
  1943. }
  1944. $dbrec = new object();
  1945. $dbrec->courseid = $restore->course_id;
  1946. $dbrec->itemtype = backup_todb($info['GRADE_ITEM']['#']['ITEMTYPE']['0']['#'], false);
  1947. $dbrec->itemmodule = backup_todb($info['GRADE_ITEM']['#']['ITEMMODULE']['0']['#'], false);
  1948. if ($itemtype == 'mod') {
  1949. // iteminstance should point to new mod
  1950. $olditeminstance = backup_todb($info['GRADE_ITEM']['#']['ITEMINSTANCE']['0']['#'], false);
  1951. $mod = backup_getid($restore->backup_unique_code,$dbrec->itemmodule, $olditeminstance);
  1952. $dbrec->iteminstance = $mod->new_id;
  1953. if (!$cm = get_coursemodule_from_instance($dbrec->itemmodule, $mod->new_id)) {
  1954. // item not restored - no item
  1955. continue;
  1956. }
  1957. // keep in sync with activity idnumber
  1958. $dbrec->idnumber = $cm->idnumber;
  1959. } else {
  1960. $idnumber = backup_todb($info['GRADE_ITEM']['#']['IDNUMBER']['0']['#'], false);
  1961. if (grade_verify_idnumber($idnumber, $restore->course_id)) {
  1962. //make sure the new idnumber is unique
  1963. $dbrec->idnumber = $idnumber;
  1964. }
  1965. }
  1966. $dbrec->itemname = backup_todb($info['GRADE_ITEM']['#']['ITEMNAME']['0']['#'], false);
  1967. $dbrec->itemtype = backup_todb($info['GRADE_ITEM']['#']['ITEMTYPE']['0']['#'], false);
  1968. $dbrec->itemmodule = backup_todb($info['GRADE_ITEM']['#']['ITEMMODULE']['0']['#'], false);
  1969. $dbrec->itemnumber = backup_todb($info['GRADE_ITEM']['#']['ITEMNUMBER']['0']['#'], false);
  1970. $dbrec->iteminfo = backup_todb($info['GRADE_ITEM']['#']['ITEMINFO']['0']['#'], false);
  1971. $dbrec->gradetype = backup_todb($info['GRADE_ITEM']['#']['GRADETYPE']['0']['#'], false);
  1972. $dbrec->calculation = backup_todb($info['GRADE_ITEM']['#']['CALCULATION']['0']['#'], false);
  1973. $dbrec->grademax = backup_todb($info['GRADE_ITEM']['#']['GRADEMAX']['0']['#'], false);
  1974. $dbrec->grademin = backup_todb($info['GRADE_ITEM']['#']['GRADEMIN']['0']['#'], false);
  1975. $dbrec->gradepass = backup_todb($info['GRADE_ITEM']['#']['GRADEPASS']['0']['#'], false);
  1976. $dbrec->multfactor = backup_todb($info['GRADE_ITEM']['#']['MULTFACTOR']['0']['#'], false);
  1977. $dbrec->plusfactor = backup_todb($info['GRADE_ITEM']['#']['PLUSFACTOR']['0']['#'], false);
  1978. $dbrec->aggregationcoef = backup_todb($info['GRADE_ITEM']['#']['AGGREGATIONCOEF']['0']['#'], false);
  1979. $dbrec->display = backup_todb($info['GRADE_ITEM']['#']['DISPLAY']['0']['#'], false);
  1980. $dbrec->decimals = backup_todb($info['GRADE_ITEM']['#']['DECIMALS']['0']['#'], false);
  1981. $dbrec->hidden = backup_todb($info['GRADE_ITEM']['#']['HIDDEN']['0']['#'], false);
  1982. $dbrec->locked = backup_todb($info['GRADE_ITEM']['#']['LOCKED']['0']['#'], false);
  1983. $dbrec->locktime = backup_todb($info['GRADE_ITEM']['#']['LOCKTIME']['0']['#'], false);
  1984. $dbrec->timecreated = backup_todb($info['GRADE_ITEM']['#']['TIMECREATED']['0']['#'], false);
  1985. if (backup_todb($info['GRADE_ITEM']['#']['SCALEID']['0']['#'], false)) {
  1986. $scale = backup_getid($restore->backup_unique_code,"scale",backup_todb($info['GRADE_ITEM']['#']['SCALEID']['0']['#'], false));
  1987. $dbrec->scaleid = $scale->new_id;
  1988. }
  1989. if (backup_todb($info['GRADE_ITEM']['#']['OUTCOMEID']['0']['#'])) {
  1990. $oldoutcome = backup_todb($info['GRADE_ITEM']['#']['OUTCOMEID']['0']['#']);
  1991. if (empty($outcomes[$oldoutcome])) {
  1992. continue; // error!
  1993. }
  1994. if (empty($outcomes[$oldoutcome]->id)) {
  1995. $outcomes[$oldoutcome]->insert('restore');
  1996. $outcomes[$oldoutcome]->use_in($restore->course_id);
  1997. backup_putid($restore->backup_unique_code, "grade_outcomes", $oldoutcome, $outcomes[$oldoutcome]->id);
  1998. }
  1999. $dbrec->outcomeid = $outcomes[$oldoutcome]->id;
  2000. }
  2001. $grade_item = new grade_item($dbrec, false);
  2002. $grade_item->insert('restore');
  2003. if ($restoreall) {
  2004. // set original parent if restored
  2005. $oldcat = $info['GRADE_ITEM']['#']['CATEGORYID']['0']['#'];
  2006. if (!empty($cached_categories[$oldcat])) {
  2007. $grade_item->set_parent($cached_categories[$oldcat]->id);
  2008. }
  2009. }
  2010. $status = backup_putid($restore->backup_unique_code,"grade_items", $rec->old_id, $grade_item->id) && $status;
  2011. }
  2012. // no need to restore grades if user data is not selected or importing activities
  2013. if ($importing
  2014. or ($grade_item->itemtype == 'mod' and !restore_userdata_selected($restore, $grade_item->itemmodule, $olditeminstance))) {
  2015. // module instance not selected when restored using granular
  2016. // skip this item
  2017. continue;
  2018. }
  2019. /// now, restore grade_grades
  2020. if (!empty($info['GRADE_ITEM']['#']['GRADE_GRADES']['0']['#']['GRADE'])) {
  2021. //Iterate over items
  2022. foreach ($info['GRADE_ITEM']['#']['GRADE_GRADES']['0']['#']['GRADE'] as $g_info) {
  2023. $grade = new grade_grade();
  2024. $grade->itemid = $grade_item->id;
  2025. $olduser = backup_todb($g_info['#']['USERID']['0']['#'], false);
  2026. $user = backup_getid($restore->backup_unique_code,"user",$olduser);
  2027. $grade->userid = $user->new_id;
  2028. $grade->rawgrade = backup_todb($g_info['#']['RAWGRADE']['0']['#'], false);
  2029. $grade->rawgrademax = backup_todb($g_info['#']['RAWGRADEMAX']['0']['#'], false);
  2030. $grade->rawgrademin = backup_todb($g_info['#']['RAWGRADEMIN']['0']['#'], false);
  2031. // need to find scaleid
  2032. if (backup_todb($g_info['#']['RAWSCALEID']['0']['#'])) {
  2033. $scale = backup_getid($restore->backup_unique_code,"scale",backup_todb($g_info['#']['RAWSCALEID']['0']['#'], false));
  2034. $grade->rawscaleid = $scale->new_id;
  2035. }
  2036. if (backup_todb($g_info['#']['USERMODIFIED']['0']['#'])) {
  2037. if ($modifier = backup_getid($restore->backup_unique_code,"user", backup_todb($g_info['#']['USERMODIFIED']['0']['#'], false))) {
  2038. $grade->usermodified = $modifier->new_id;
  2039. }
  2040. }
  2041. $grade->finalgrade = backup_todb($g_info['#']['FINALGRADE']['0']['#'], false);
  2042. $grade->hidden = backup_todb($g_info['#']['HIDDEN']['0']['#'], false);
  2043. $grade->locked = backup_todb($g_info['#']['LOCKED']['0']['#'], false);
  2044. $grade->locktime = backup_todb($g_info['#']['LOCKTIME']['0']['#'], false);
  2045. $grade->exported = backup_todb($g_info['#']['EXPORTED']['0']['#'], false);
  2046. $grade->overridden = backup_todb($g_info['#']['OVERRIDDEN']['0']['#'], false);
  2047. $grade->excluded = backup_todb($g_info['#']['EXCLUDED']['0']['#'], false);
  2048. $grade->feedback = backup_todb($g_info['#']['FEEDBACK']['0']['#'], false);
  2049. $grade->feedbackformat = backup_todb($g_info['#']['FEEDBACKFORMAT']['0']['#'], false);
  2050. $grade->information = backup_todb($g_info['#']['INFORMATION']['0']['#'], false);
  2051. $grade->informationformat = backup_todb($g_info['#']['INFORMATIONFORMAT']['0']['#'], false);
  2052. $grade->timecreated = backup_todb($g_info['#']['TIMECREATED']['0']['#'], false);
  2053. $grade->timemodified = backup_todb($g_info['#']['TIMEMODIFIED']['0']['#'], false);
  2054. $grade->insert('restore');
  2055. backup_putid($restore->backup_unique_code,"grade_grades", backup_todb($g_info['#']['ID']['0']['#']), $grade->id);
  2056. $counter++;
  2057. if ($counter % 20 == 0) {
  2058. if (!defined('RESTORE_SILENTLY')) {
  2059. echo ".";
  2060. if ($counter % 400 == 0) {
  2061. echo "<br />";
  2062. }
  2063. }
  2064. backup_flush(300);
  2065. }
  2066. }
  2067. }
  2068. }
  2069. }
  2070. }
  2071. }
  2072. /// add outcomes that are not used when doing full restore
  2073. if ($status and $restoreall) {
  2074. foreach ($outcomes as $oldoutcome=>$grade_outcome) {
  2075. if (empty($grade_outcome->id)) {
  2076. $grade_outcome->insert('restore');
  2077. $grade_outcome->use_in($restore->course_id);
  2078. backup_putid($restore->backup_unique_code, "grade_outcomes", $oldoutcome, $grade_outcome->id);
  2079. }
  2080. }
  2081. }
  2082. if ($status and !$importing and $restore_histories) {
  2083. /// following code is very inefficient
  2084. $gchcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'grade_categories_history');
  2085. $gghcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'grade_grades_history');
  2086. $gihcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'grade_items_history');
  2087. $gohcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'grade_outcomes_history');
  2088. // Number of records to get in every chunk
  2089. $recordset_size = 2;
  2090. // process histories
  2091. if ($gchcount && $status) {
  2092. if (!defined('RESTORE_SILENTLY')) {
  2093. echo '<li>'.get_string('gradecategoryhistory','grades').'</li>';
  2094. }
  2095. $counter = 0;
  2096. while ($counter < $gchcount) {
  2097. //Fetch recordset_size records in each iteration
  2098. $recs = get_records_select("backup_ids","table_name = 'grade_categories_history' AND backup_code = '$restore->backup_unique_code'",
  2099. "old_id",
  2100. "old_id",
  2101. $counter,
  2102. $recordset_size);
  2103. if ($recs) {
  2104. foreach ($recs as $rec) {
  2105. //Get the full record from backup_ids
  2106. $data = backup_getid($restore->backup_unique_code,'grade_categories_history',$rec->old_id);
  2107. if ($data) {
  2108. //Now get completed xmlized object
  2109. $info = $data->info;
  2110. //traverse_xmlize($info); //Debug
  2111. //print_object ($GLOBALS['traverse_array']); //Debug
  2112. //$GLOBALS['traverse_array']=""; //Debug
  2113. $oldobj = backup_getid($restore->backup_unique_code,"grade_categories", backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['OLDID']['0']['#']));
  2114. if (empty($oldobj->new_id)) {
  2115. // if the old object is not being restored, can't restoring its history
  2116. $counter++;
  2117. continue;
  2118. }
  2119. $dbrec->oldid = $oldobj->new_id;
  2120. $dbrec->action = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['ACTION']['0']['#']);
  2121. $dbrec->source = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['SOURCE']['0']['#']);
  2122. $dbrec->timemodified = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['TIMEMODIFIED']['0']['#']);
  2123. // loggeduser might not be restored, e.g. admin
  2124. if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['LOGGEDUSER']['0']['#']))) {
  2125. $dbrec->loggeduser = $oldobj->new_id;
  2126. }
  2127. // this item might not have a parent at all, do not skip it if no parent is specified
  2128. if (backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['PARENT']['0']['#'])) {
  2129. $oldobj = backup_getid($restore->backup_unique_code,"grade_categories", backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['PARENT']['0']['#']));
  2130. if (empty($oldobj->new_id)) {
  2131. // if the parent category not restored
  2132. $counter++;
  2133. continue;
  2134. }
  2135. }
  2136. $dbrec->parent = $oldobj->new_id;
  2137. $dbrec->depth = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['DEPTH']['0']['#']);
  2138. // path needs to be rebuilt
  2139. if ($path = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['PATH']['0']['#'])) {
  2140. // to preserve the path and make it work, we need to replace the categories one by one
  2141. // we first get the list of categories in current path
  2142. if ($paths = explode("/", $path)) {
  2143. $newpath = '';
  2144. foreach ($paths as $catid) {
  2145. if ($catid) {
  2146. // find the new corresponding path
  2147. $oldpath = backup_getid($restore->backup_unique_code,"grade_categories", $catid);
  2148. $newpath .= "/$oldpath->new_id";
  2149. }
  2150. }
  2151. $dbrec->path = $newpath;
  2152. }
  2153. }
  2154. $dbrec->fullname = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['FULLNAME']['0']['#']);
  2155. $dbrec->aggregation = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['AGGRETGATION']['0']['#']);
  2156. $dbrec->keephigh = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['KEEPHIGH']['0']['#']);
  2157. $dbrec->droplow = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['DROPLOW']['0']['#']);
  2158. $dbrec->aggregateonlygraded = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['AGGREGATEONLYGRADED']['0']['#']);
  2159. $dbrec->aggregateoutcomes = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['AGGREGATEOUTCOMES']['0']['#']);
  2160. $dbrec->aggregatesubcats = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['AGGREGATESUBCATS']['0']['#']);
  2161. $dbrec->courseid = $restore->course_id;
  2162. insert_record('grade_categories_history', $dbrec);
  2163. unset($dbrec);
  2164. }
  2165. //Increment counters
  2166. $counter++;
  2167. //Do some output
  2168. if ($counter % 1 == 0) {
  2169. if (!defined('RESTORE_SILENTLY')) {
  2170. echo ".";
  2171. if ($counter % 20 == 0) {
  2172. echo "<br />";
  2173. }
  2174. }
  2175. backup_flush(300);
  2176. }
  2177. }
  2178. }
  2179. }
  2180. }
  2181. // process histories
  2182. if ($gghcount && $status) {
  2183. if (!defined('RESTORE_SILENTLY')) {
  2184. echo '<li>'.get_string('gradegradeshistory','grades').'</li>';
  2185. }
  2186. $counter = 0;
  2187. while ($counter < $gghcount) {
  2188. //Fetch recordset_size records in each iteration
  2189. $recs = get_records_select("backup_ids","table_name = 'grade_grades_history' AND backup_code = '$restore->backup_unique_code'",
  2190. "old_id",
  2191. "old_id",
  2192. $counter,
  2193. $recordset_size);
  2194. if ($recs) {
  2195. foreach ($recs as $rec) {
  2196. //Get the full record from backup_ids
  2197. $data = backup_getid($restore->backup_unique_code,'grade_grades_history',$rec->old_id);
  2198. if ($data) {
  2199. //Now get completed xmlized object
  2200. $info = $data->info;
  2201. //traverse_xmlize($info); //Debug
  2202. //print_object ($GLOBALS['traverse_array']); //Debug
  2203. //$GLOBALS['traverse_array']=""; //Debug
  2204. $oldobj = backup_getid($restore->backup_unique_code,"grade_grades", backup_todb($info['GRADE_GRADES_HISTORY']['#']['OLDID']['0']['#']));
  2205. if (empty($oldobj->new_id)) {
  2206. // if the old object is not being restored, can't restoring its history
  2207. $counter++;
  2208. continue;
  2209. }
  2210. $dbrec->oldid = $oldobj->new_id;
  2211. $dbrec->action = backup_todb($info['GRADE_GRADES_HISTORY']['#']['ACTION']['0']['#']);
  2212. $dbrec->source = backup_todb($info['GRADE_GRADES_HISTORY']['#']['SOURCE']['0']['#']);
  2213. $dbrec->timemodified = backup_todb($info['GRADE_GRADES_HISTORY']['#']['TIMEMODIFIED']['0']['#']);
  2214. if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_GRADES_HISTORY']['#']['LOGGEDUSER']['0']['#']))) {
  2215. $dbrec->loggeduser = $oldobj->new_id;
  2216. }
  2217. $oldobj = backup_getid($restore->backup_unique_code,"grade_items", backup_todb($info['GRADE_GRADES_HISTORY']['#']['ITEMID']['0']['#']));
  2218. $dbrec->itemid = $oldobj->new_id;
  2219. if (empty($dbrec->itemid)) {
  2220. $counter++;
  2221. continue; // grade item not being restored
  2222. }
  2223. $oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_GRADES_HISTORY']['#']['USERID']['0']['#']));
  2224. $dbrec->userid = $oldobj->new_id;
  2225. $dbrec->rawgrade = backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWGRADE']['0']['#']);
  2226. $dbrec->rawgrademax = backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWGRADEMAX']['0']['#']);
  2227. $dbrec->rawgrademin = backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWGRADEMIN']['0']['#']);
  2228. if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_GRADES_HISTORY']['#']['USERMODIFIED']['0']['#']))) {
  2229. $dbrec->usermodified = $oldobj->new_id;
  2230. }
  2231. if (backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWSCALEID']['0']['#'])) {
  2232. $scale = backup_getid($restore->backup_unique_code,"scale",backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWSCALEID']['0']['#']));
  2233. $dbrec->rawscaleid = $scale->new_id;
  2234. }
  2235. $dbrec->finalgrade = backup_todb($info['GRADE_GRADES_HISTORY']['#']['FINALGRADE']['0']['#']);
  2236. $dbrec->hidden = backup_todb($info['GRADE_GRADES_HISTORY']['#']['HIDDEN']['0']['#']);
  2237. $dbrec->locked = backup_todb($info['GRADE_GRADES_HISTORY']['#']['LOCKED']['0']['#']);
  2238. $dbrec->locktime = backup_todb($info['GRADE_GRADES_HISTORY']['#']['LOCKTIME']['0']['#']);
  2239. $dbrec->exported = backup_todb($info['GRADE_GRADES_HISTORY']['#']['EXPORTED']['0']['#']);
  2240. $dbrec->overridden = backup_todb($info['GRADE_GRADES_HISTORY']['#']['OVERRIDDEN']['0']['#']);
  2241. $dbrec->excluded = backup_todb($info['GRADE_GRADES_HISTORY']['#']['EXCLUDED']['0']['#']);
  2242. $dbrec->feedback = backup_todb($info['GRADE_TEXT_HISTORY']['#']['FEEDBACK']['0']['#']);
  2243. $dbrec->feedbackformat = backup_todb($info['GRADE_TEXT_HISTORY']['#']['FEEDBACKFORMAT']['0']['#']);
  2244. $dbrec->information = backup_todb($info['GRADE_TEXT_HISTORY']['#']['INFORMATION']['0']['#']);
  2245. $dbrec->informationformat = backup_todb($info['GRADE_TEXT_HISTORY']['#']['INFORMATIONFORMAT']['0']['#']);
  2246. insert_record('grade_grades_history', $dbrec);
  2247. unset($dbrec);
  2248. }
  2249. //Increment counters
  2250. $counter++;
  2251. //Do some output
  2252. if ($counter % 1 == 0) {
  2253. if (!defined('RESTORE_SILENTLY')) {
  2254. echo ".";
  2255. if ($counter % 20 == 0) {
  2256. echo "<br />";
  2257. }
  2258. }
  2259. backup_flush(300);
  2260. }
  2261. }
  2262. }
  2263. }
  2264. }
  2265. // process histories
  2266. if ($gihcount && $status) {
  2267. if (!defined('RESTORE_SILENTLY')) {
  2268. echo '<li>'.get_string('gradeitemshistory','grades').'</li>';
  2269. }
  2270. $counter = 0;
  2271. while ($counter < $gihcount) {
  2272. //Fetch recordset_size records in each iteration
  2273. $recs = get_records_select("backup_ids","table_name = 'grade_items_history' AND backup_code = '$restore->backup_unique_code'",
  2274. "old_id",
  2275. "old_id",
  2276. $counter,
  2277. $recordset_size);
  2278. if ($recs) {
  2279. foreach ($recs as $rec) {
  2280. //Get the full record from backup_ids
  2281. $data = backup_getid($restore->backup_unique_code,'grade_items_history',$rec->old_id);
  2282. if ($data) {
  2283. //Now get completed xmlized object
  2284. $info = $data->info;
  2285. //traverse_xmlize($info); //Debug
  2286. //print_object ($GLOBALS['traverse_array']); //Debug
  2287. //$GLOBALS['traverse_array']=""; //Debug
  2288. $oldobj = backup_getid($restore->backup_unique_code,"grade_items", backup_todb($info['GRADE_ITEM_HISTORY']['#']['OLDID']['0']['#']));
  2289. if (empty($oldobj->new_id)) {
  2290. // if the old object is not being restored, can't restoring its history
  2291. $counter++;
  2292. continue;
  2293. }
  2294. $dbrec->oldid = $oldobj->new_id;
  2295. $dbrec->action = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ACTION']['0']['#']);
  2296. $dbrec->source = backup_todb($info['GRADE_ITEM_HISTORY']['#']['SOURCE']['0']['#']);
  2297. $dbrec->timemodified = backup_todb($info['GRADE_ITEM_HISTORY']['#']['TIMEMODIFIED']['0']['#']);
  2298. if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_ITEM_HISTORY']['#']['LOGGEDUSER']['0']['#']))) {
  2299. $dbrec->loggeduser = $oldobj->new_id;
  2300. }
  2301. $dbrec->courseid = $restore->course_id;
  2302. $oldobj = backup_getid($restore->backup_unique_code,'grade_categories',backup_todb($info['GRADE_ITEM_HISTORY']['#']['CATEGORYID']['0']['#']));
  2303. $oldobj->categoryid = $category->new_id;
  2304. if (empty($oldobj->categoryid)) {
  2305. $counter++;
  2306. continue; // category not restored
  2307. }
  2308. $dbrec->itemname= backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMNAME']['0']['#']);
  2309. $dbrec->itemtype = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMTYPE']['0']['#']);
  2310. $dbrec->itemmodule = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMMODULE']['0']['#']);
  2311. // code from grade_items restore
  2312. $iteminstance = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMINSTANCE']['0']['#']);
  2313. // do not restore if this grade_item is a mod, and
  2314. if ($dbrec->itemtype == 'mod') {
  2315. if (!restore_userdata_selected($restore, $dbrec->itemmodule, $iteminstance)) {
  2316. // module instance not selected when restored using granular
  2317. // skip this item
  2318. $counter++;
  2319. continue;
  2320. }
  2321. // iteminstance should point to new mod
  2322. $mod = backup_getid($restore->backup_unique_code,$dbrec->itemmodule, $iteminstance);
  2323. $dbrec->iteminstance = $mod->new_id;
  2324. } else if ($dbrec->itemtype == 'category') {
  2325. // the item instance should point to the new grade category
  2326. // only proceed if we are restoring all grade items
  2327. if ($restoreall) {
  2328. $category = backup_getid($restore->backup_unique_code,'grade_categories', $iteminstance);
  2329. $dbrec->iteminstance = $category->new_id;
  2330. } else {
  2331. // otherwise we can safely ignore this grade item and subsequent
  2332. // grade_raws, grade_finals etc
  2333. continue;
  2334. }
  2335. } elseif ($dbrec->itemtype == 'course') { // We don't restore course type to avoid duplicate course items
  2336. if ($restoreall) {
  2337. // TODO any special code needed here to restore course item without duplicating it?
  2338. // find the course category with depth 1, and course id = current course id
  2339. // this would have been already restored
  2340. $cat = get_record('grade_categories', 'depth', 1, 'courseid', $restore->course_id);
  2341. $dbrec->iteminstance = $cat->id;
  2342. } else {
  2343. $counter++;
  2344. continue;
  2345. }
  2346. }
  2347. $dbrec->itemnumber = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMNUMBER']['0']['#']);
  2348. $dbrec->iteminfo = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMINFO']['0']['#']);
  2349. $dbrec->idnumber = backup_todb($info['GRADE_ITEM_HISTORY']['#']['IDNUMBER']['0']['#']);
  2350. $dbrec->calculation = backup_todb($info['GRADE_ITEM_HISTORY']['#']['CALCULATION']['0']['#']);
  2351. $dbrec->gradetype = backup_todb($info['GRADE_ITEM_HISTORY']['#']['GRADETYPE']['0']['#']);
  2352. $dbrec->grademax = backup_todb($info['GRADE_ITEM_HISTORY']['#']['GRADEMAX']['0']['#']);
  2353. $dbrec->grademin = backup_todb($info['GRADE_ITEM_HISTORY']['#']['GRADEMIN']['0']['#']);
  2354. if ($oldobj = backup_getid($restore->backup_unique_code,"scale", backup_todb($info['GRADE_ITEM_HISTORY']['#']['SCALEID']['0']['#']))) {
  2355. // scaleid is optional
  2356. $dbrec->scaleid = $oldobj->new_id;
  2357. }
  2358. if ($oldobj = backup_getid($restore->backup_unique_code,"grade_outcomes", backup_todb($info['GRADE_ITEM_HISTORY']['#']['OUTCOMEID']['0']['#']))) {
  2359. // outcome is optional
  2360. $dbrec->outcomeid = $oldobj->new_id;
  2361. }
  2362. $dbrec->gradepass = backup_todb($info['GRADE_ITEM_HISTORY']['#']['GRADEPASS']['0']['#']);
  2363. $dbrec->multfactor = backup_todb($info['GRADE_ITEM_HISTORY']['#']['MULTFACTOR']['0']['#']);
  2364. $dbrec->plusfactor = backup_todb($info['GRADE_ITEM_HISTORY']['#']['PLUSFACTOR']['0']['#']);
  2365. $dbrec->aggregationcoef = backup_todb($info['GRADE_ITEM_HISTORY']['#']['AGGREGATIONCOEF']['0']['#']);
  2366. $dbrec->sortorder = backup_todb($info['GRADE_ITEM_HISTORY']['#']['SORTORDER']['0']['#']);
  2367. $dbrec->display = backup_todb($info['GRADE_ITEM_HISTORY']['#']['DISPLAY']['0']['#']);
  2368. $dbrec->decimals = backup_todb($info['GRADE_ITEM_HISTORY']['#']['DECIMALS']['0']['#']);
  2369. $dbrec->hidden = backup_todb($info['GRADE_ITEM_HISTORY']['#']['HIDDEN']['0']['#']);
  2370. $dbrec->locked = backup_todb($info['GRADE_ITEM_HISTORY']['#']['LOCKED']['0']['#']);
  2371. $dbrec->locktime = backup_todb($info['GRADE_ITEM_HISTORY']['#']['LOCKTIME']['0']['#']);
  2372. $dbrec->needsupdate = backup_todb($info['GRADE_ITEM_HISTORY']['#']['NEEDSUPDATE']['0']['#']);
  2373. insert_record('grade_items_history', $dbrec);
  2374. unset($dbrec);
  2375. }
  2376. //Increment counters
  2377. $counter++;
  2378. //Do some output
  2379. if ($counter % 1 == 0) {
  2380. if (!defined('RESTORE_SILENTLY')) {
  2381. echo ".";
  2382. if ($counter % 20 == 0) {
  2383. echo "<br />";
  2384. }
  2385. }
  2386. backup_flush(300);
  2387. }
  2388. }
  2389. }
  2390. }
  2391. }
  2392. // process histories
  2393. if ($gohcount && $status) {
  2394. if (!defined('RESTORE_SILENTLY')) {
  2395. echo '<li>'.get_string('gradeoutcomeshistory','grades').'</li>';
  2396. }
  2397. $counter = 0;
  2398. while ($counter < $gohcount) {
  2399. //Fetch recordset_size records in each iteration
  2400. $recs = get_records_select("backup_ids","table_name = 'grade_outcomes_history' AND backup_code = '$restore->backup_unique_code'",
  2401. "old_id",
  2402. "old_id",
  2403. $counter,
  2404. $recordset_size);
  2405. if ($recs) {
  2406. foreach ($recs as $rec) {
  2407. //Get the full record from backup_ids
  2408. $data = backup_getid($restore->backup_unique_code,'grade_outcomes_history',$rec->old_id);
  2409. if ($data) {
  2410. //Now get completed xmlized object
  2411. $info = $data->info;
  2412. //traverse_xmlize($info); //Debug
  2413. //print_object ($GLOBALS['traverse_array']); //Debug
  2414. //$GLOBALS['traverse_array']=""; //Debug
  2415. $oldobj = backup_getid($restore->backup_unique_code,"grade_outcomes", backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['OLDID']['0']['#']));
  2416. if (empty($oldobj->new_id)) {
  2417. // if the old object is not being restored, can't restoring its history
  2418. $counter++;
  2419. continue;
  2420. }
  2421. $dbrec->oldid = $oldobj->new_id;
  2422. $dbrec->action = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['ACTION']['0']['#']);
  2423. $dbrec->source = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['SOURCE']['0']['#']);
  2424. $dbrec->timemodified = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['TIMEMODIFIED']['0']['#']);
  2425. if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['LOGGEDUSER']['0']['#']))) {
  2426. $dbrec->loggeduser = $oldobj->new_id;
  2427. }
  2428. $dbrec->courseid = $restore->course_id;
  2429. $dbrec->shortname = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['SHORTNAME']['0']['#']);
  2430. $dbrec->fullname= backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['FULLNAME']['0']['#']);
  2431. $oldobj = backup_getid($restore->backup_unique_code,"scale", backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['SCALEID']['0']['#']));
  2432. $dbrec->scaleid = $oldobj->new_id;
  2433. $dbrec->description = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['DESCRIPTION']['0']['#']);
  2434. insert_record('grade_outcomes_history', $dbrec);
  2435. unset($dbrec);
  2436. }
  2437. //Increment counters
  2438. $counter++;
  2439. //Do some output
  2440. if ($counter % 1 == 0) {
  2441. if (!defined('RESTORE_SILENTLY')) {
  2442. echo ".";
  2443. if ($counter % 20 == 0) {
  2444. echo "<br />";
  2445. }
  2446. }
  2447. backup_flush(300);
  2448. }
  2449. }
  2450. }
  2451. }
  2452. }
  2453. }
  2454. if (!defined('RESTORE_SILENTLY')) {
  2455. //End ul
  2456. echo '</ul>';
  2457. }
  2458. return $status;
  2459. }
  2460. //This function creates all the user, user_students, user_teachers
  2461. //user_course_creators and user_admins from xml
  2462. function restore_create_users($restore,$xml_file) {
  2463. global $CFG, $db;
  2464. require_once ($CFG->dirroot.'/tag/lib.php');
  2465. $authcache = array(); // Cache to get some bits from authentication plugins
  2466. $status = true;
  2467. // Users have already been checked by restore_precheck_users() so they are loaded
  2468. // in backup_ids table. They don't need to be loaded (parsed) from XML again. Also, note
  2469. // the same function has performed the needed modifications in the $user->mnethostid field
  2470. // so we don't need to do it again here at all. Just some checks.
  2471. // Get users ids from backup_ids table
  2472. $userids = get_fieldset_select('backup_ids', 'old_id', "backup_code = $restore->backup_unique_code AND table_name = 'user'");
  2473. // Have users to process, proceed with them
  2474. if (!empty($userids)) {
  2475. /// Get languages for quick search later
  2476. $languages = get_list_of_languages();
  2477. /// Iterate over all users loaded from xml
  2478. $counter = 0;
  2479. /// Init trailing messages
  2480. $messages = array();
  2481. foreach ($userids as $userid) {
  2482. // Defaults
  2483. $user_exists = false; // By default user does not exist
  2484. $newid = null; // By default, there is not newid
  2485. // Get record from backup_ids
  2486. $useridsdbrec = backup_getid($restore->backup_unique_code, 'user', $userid);
  2487. // Based in restore_precheck_users() calculations, if the user exists
  2488. // new_id must contain the id of the matching user
  2489. if (!empty($useridsdbrec->new_id)) {
  2490. $user_exists = true;
  2491. $newid = $useridsdbrec->new_id;
  2492. }
  2493. $user = $useridsdbrec->info;
  2494. foreach (array_keys(get_object_vars($user)) as $field) {
  2495. if (!is_array($user->$field)) {
  2496. $user->$field = backup_todb($user->$field, false);
  2497. if (is_null($user->$field)) {
  2498. $user->$field = '';
  2499. }
  2500. }
  2501. }
  2502. //Now, recode some languages (Moodle 1.5)
  2503. if ($user->lang == 'ma_nt') {
  2504. $user->lang = 'mi_nt';
  2505. }
  2506. //Country list updates - MDL-13060
  2507. //Any user whose country code has been deleted or modified needs to be assigned a valid one.
  2508. $country_update_map = array(
  2509. 'ZR' => 'CD',
  2510. 'TP' => 'TL',
  2511. 'FX' => 'FR',
  2512. 'KO' => 'RS',
  2513. 'CS' => 'RS',
  2514. 'WA' => 'GB');
  2515. if (array_key_exists($user->country, $country_update_map)) {
  2516. $user->country = $country_update_map[$user->country];
  2517. }
  2518. //If language does not exist here - use site default
  2519. if (!array_key_exists($user->lang, $languages)) {
  2520. $user->lang = $CFG->lang;
  2521. }
  2522. //Check if it's admin and coursecreator
  2523. $is_admin = !empty($user->roles['admin']);
  2524. $is_coursecreator = !empty($user->roles['coursecreator']);
  2525. //Check if it's teacher and student
  2526. $is_teacher = !empty($user->roles['teacher']);
  2527. $is_student = !empty($user->roles['student']);
  2528. //Check if it's needed
  2529. $is_needed = !empty($user->roles['needed']);
  2530. //Calculate if it is a course user
  2531. //Has role teacher or student or needed
  2532. $is_course_user = ($is_teacher or $is_student or $is_needed);
  2533. // Only try to perform mnethost/auth modifications if restoring to another server
  2534. // or if, while restoring to same server, the user doesn't exists yet (rebuilt site)
  2535. //
  2536. // So existing user data in same server *won't be modified by restore anymore*,
  2537. // under any circumpstance. If somehting is wrong with existing data, it's server fault.
  2538. if (!backup_is_same_site($restore) || (backup_is_same_site($restore) && !$user_exists)) {
  2539. //Arriving here, any user with mnet auth and using $CFG->mnet_localhost_id is wrong
  2540. //as own server cannot be accesed over mnet. Change auth to manual and inform about the switch
  2541. if ($user->auth == 'mnet' && $user->mnethostid == $CFG->mnet_localhost_id) {
  2542. // Respect registerauth
  2543. if ($CFG->registerauth == 'email') {
  2544. $user->auth = 'email';
  2545. } else {
  2546. $user->auth = 'manual';
  2547. }
  2548. // inform about the automatic switch of authentication/host
  2549. if(empty($user->mnethosturl)) {
  2550. $user->mnethosturl = '----';
  2551. }
  2552. $messages[] = get_string('mnetrestore_extusers_switchuserauth', 'admin', $user);
  2553. }
  2554. }
  2555. unset($user->mnethosturl);
  2556. //Flags to see what parts are we going to restore
  2557. $create_user = true;
  2558. $create_roles = true;
  2559. $create_custom_profile_fields = true;
  2560. $create_tags = true;
  2561. $create_preferences = true;
  2562. //If we are restoring course users and it isn't a course user
  2563. if ($restore->users == 1 and !$is_course_user) {
  2564. //If only restoring course_users and user isn't a course_user, inform to $backup_ids
  2565. $status = backup_putid($restore->backup_unique_code,"user",$userid,null,'notincourse');
  2566. $create_user = false;
  2567. $create_roles = false;
  2568. $create_custom_profile_fields = false;
  2569. $create_tags = false;
  2570. $create_preferences = false;
  2571. }
  2572. if ($user_exists and $create_user) {
  2573. //If user exists mark its newid in backup_ids (the same than old)
  2574. $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,'exists');
  2575. $create_user = false;
  2576. $create_custom_profile_fields = false;
  2577. $create_tags = false;
  2578. $create_preferences = false;
  2579. }
  2580. //Here, if create_user, do it
  2581. if ($create_user) {
  2582. //Unset the id because it's going to be inserted with a new one
  2583. unset ($user->id);
  2584. /// Disable pictures based on global setting or existing empty value (old backups can contain wrong empties)
  2585. if (!empty($CFG->disableuserimages) || empty($user->picture)) {
  2586. $user->picture = 0;
  2587. }
  2588. //We need to analyse the AUTH field to recode it:
  2589. // - if the field isn't set, we are in a pre 1.4 backup and $CFG->registerauth will decide
  2590. // - if the auth isn't enabled in target site, $CFG->registerauth will decide
  2591. // - finally, if the auth resulting isn't enabled, default to 'manual'
  2592. if (empty($user->auth) || !is_enabled_auth($user->auth)) {
  2593. if ($CFG->registerauth == 'email') {
  2594. $user->auth = 'email';
  2595. } else {
  2596. $user->auth = 'manual';
  2597. }
  2598. }
  2599. if (!is_enabled_auth($user->auth)) { // Final auth check verify, default to manual if not enabled
  2600. $user->auth = 'manual';
  2601. }
  2602. // Now that we know the auth method, for users to be created without pass
  2603. // if password handling is internal and reset password is available
  2604. // we set the password to "restored" (plain text), so the login process
  2605. // will know how to handle that situation in order to allow the user to
  2606. // recover the password. MDL-20846
  2607. if (empty($user->password)) { // Only if restore comes without password
  2608. if (!array_key_exists($user->auth, $authcache)) { // Not in cache
  2609. $userauth = new stdClass();
  2610. $authplugin = get_auth_plugin($user->auth);
  2611. $userauth->preventpassindb = $authplugin->prevent_local_passwords();
  2612. $userauth->isinternal = $authplugin->is_internal();
  2613. $userauth->canresetpwd = $authplugin->can_reset_password();
  2614. $authcache[$user->auth] = $userauth;
  2615. } else {
  2616. $userauth = $authcache[$user->auth]; // Get from cache
  2617. }
  2618. // Most external plugins do not store passwords locally
  2619. if (!empty($userauth->preventpassindb)) {
  2620. $user->password = 'not cached';
  2621. // If Moodle is responsible for storing/validating pwd and reset functionality is available, mark
  2622. } else if ($userauth->isinternal and $userauth->canresetpwd) {
  2623. $user->password = 'restored';
  2624. }
  2625. }
  2626. //We need to process the POLICYAGREED field to recalculate it:
  2627. // - if the destination site is different (by wwwroot) reset it.
  2628. // - if the destination site is the same (by wwwroot), leave it unmodified
  2629. if (!backup_is_same_site($restore)) {
  2630. $user->policyagreed = 0;
  2631. } else {
  2632. //Nothing to do, we are in the same server
  2633. }
  2634. //Check if the theme exists in destination server
  2635. $themes = get_list_of_themes();
  2636. if (!in_array($user->theme, $themes)) {
  2637. $user->theme = '';
  2638. }
  2639. //We are going to create the user
  2640. //The structure is exactly as we need
  2641. $newid = insert_record ("user", addslashes_recursive($user));
  2642. //Put the new id
  2643. $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,"new");
  2644. }
  2645. ///TODO: This seccion is to support pre 1.7 course backups, using old roles
  2646. /// teacher, coursecreator, student.... providing a basic mapping to new ones.
  2647. /// Someday we'll drop support for them and this section will be safely deleted (2.0?)
  2648. //Here, if create_roles, do it as necessary
  2649. if ($create_roles) {
  2650. //Get the newid and current info from backup_ids
  2651. $data = backup_getid($restore->backup_unique_code,"user",$userid);
  2652. $newid = $data->new_id;
  2653. $currinfo = $data->info.",";
  2654. //Now, depending of the role, create records in user_studentes and user_teacher
  2655. //and/or mark it in backup_ids
  2656. if ($is_admin) {
  2657. //If the record (user_admins) doesn't exists
  2658. //Only put status in backup_ids
  2659. $currinfo = $currinfo."admin,";
  2660. $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
  2661. }
  2662. if ($is_coursecreator) {
  2663. //If the record (user_coursecreators) doesn't exists
  2664. //Only put status in backup_ids
  2665. $currinfo = $currinfo."coursecreator,";
  2666. $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
  2667. }
  2668. if ($is_needed) {
  2669. //Only put status in backup_ids
  2670. $currinfo = $currinfo."needed,";
  2671. $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
  2672. }
  2673. if ($is_teacher) {
  2674. //If the record (teacher) doesn't exists
  2675. //Put status in backup_ids
  2676. $currinfo = $currinfo."teacher,";
  2677. $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
  2678. //Set course and user
  2679. $user->roles['teacher']->course = $restore->course_id;
  2680. $user->roles['teacher']->userid = $newid;
  2681. //Need to analyse the enrol field
  2682. // - if it isn't set, set it to $CFG->enrol
  2683. // - if we are in a different server (by wwwroot), set it to $CFG->enrol
  2684. // - if we are in the same server (by wwwroot), maintain it unmodified.
  2685. if (empty($user->roles['teacher']->enrol)) {
  2686. $user->roles['teacher']->enrol = $CFG->enrol;
  2687. } else if (!backup_is_same_site($restore)) {
  2688. $user->roles['teacher']->enrol = $CFG->enrol;
  2689. } else {
  2690. //Nothing to do. Leave it unmodified
  2691. }
  2692. $rolesmapping = $restore->rolesmapping;
  2693. $context = get_context_instance(CONTEXT_COURSE, $restore->course_id);
  2694. if ($user->roles['teacher']->editall) {
  2695. role_assign($rolesmapping['defaultteacheredit'],
  2696. $newid,
  2697. 0,
  2698. $context->id,
  2699. $user->roles['teacher']->timestart,
  2700. $user->roles['teacher']->timeend,
  2701. 0,
  2702. $user->roles['teacher']->enrol);
  2703. // editting teacher
  2704. } else {
  2705. // non editting teacher
  2706. role_assign($rolesmapping['defaultteacher'],
  2707. $newid,
  2708. 0,
  2709. $context->id,
  2710. $user->roles['teacher']->timestart,
  2711. $user->roles['teacher']->timeend,
  2712. 0,
  2713. $user->roles['teacher']->enrol);
  2714. }
  2715. }
  2716. if ($is_student) {
  2717. //Put status in backup_ids
  2718. $currinfo = $currinfo."student,";
  2719. $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
  2720. //Set course and user
  2721. $user->roles['student']->course = $restore->course_id;
  2722. $user->roles['student']->userid = $newid;
  2723. //Need to analyse the enrol field
  2724. // - if it isn't set, set it to $CFG->enrol
  2725. // - if we are in a different server (by wwwroot), set it to $CFG->enrol
  2726. // - if we are in the same server (by wwwroot), maintain it unmodified.
  2727. if (empty($user->roles['student']->enrol)) {
  2728. $user->roles['student']->enrol = $CFG->enrol;
  2729. } else if (!backup_is_same_site($restore)) {
  2730. $user->roles['student']->enrol = $CFG->enrol;
  2731. } else {
  2732. //Nothing to do. Leave it unmodified
  2733. }
  2734. $rolesmapping = $restore->rolesmapping;
  2735. $context = get_context_instance(CONTEXT_COURSE, $restore->course_id);
  2736. role_assign($rolesmapping['defaultstudent'],
  2737. $newid,
  2738. 0,
  2739. $context->id,
  2740. $user->roles['student']->timestart,
  2741. $user->roles['student']->timeend,
  2742. 0,
  2743. $user->roles['student']->enrol);
  2744. }
  2745. if (!$is_course_user) {
  2746. //If the record (user) doesn't exists
  2747. if (!record_exists("user","id",$newid)) {
  2748. //Put status in backup_ids
  2749. $currinfo = $currinfo."user,";
  2750. $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
  2751. }
  2752. }
  2753. }
  2754. /// Here, if create_custom_profile_fields, do it as necessary
  2755. if ($create_custom_profile_fields) {
  2756. if (isset($user->user_custom_profile_fields)) {
  2757. foreach($user->user_custom_profile_fields as $udata) {
  2758. /// If the profile field has data and the profile shortname-datatype is defined in server
  2759. if ($udata->field_data) {
  2760. if ($field = get_record('user_info_field', 'shortname', $udata->field_name, 'datatype', $udata->field_type)) {
  2761. /// Insert the user_custom_profile_field
  2762. $rec = new object();
  2763. $rec->userid = $newid;
  2764. $rec->fieldid = $field->id;
  2765. $rec->data = $udata->field_data;
  2766. insert_record('user_info_data', $rec);
  2767. }
  2768. }
  2769. }
  2770. }
  2771. }
  2772. /// Here, if create_tags, do it as necessary
  2773. if ($create_tags) {
  2774. /// if tags are enabled and there are user tags
  2775. if (!empty($CFG->usetags) && isset($user->user_tags)) {
  2776. $tags = array();
  2777. foreach($user->user_tags as $user_tag) {
  2778. $tags[] = $user_tag->rawname;
  2779. }
  2780. tag_set('user', $newid, $tags);
  2781. }
  2782. }
  2783. //Here, if create_preferences, do it as necessary
  2784. if ($create_preferences) {
  2785. if (isset($user->user_preferences)) {
  2786. foreach($user->user_preferences as $user_preference) {
  2787. //We check if that user_preference exists in DB
  2788. if (!record_exists("user_preferences","userid",$newid,"name",$user_preference->name)) {
  2789. //Prepare the record and insert it
  2790. $user_preference->userid = $newid;
  2791. $status = insert_record("user_preferences",$user_preference);
  2792. }
  2793. }
  2794. }
  2795. }
  2796. //Do some output
  2797. $counter++;
  2798. if ($counter % 10 == 0) {
  2799. if (!defined('RESTORE_SILENTLY')) {
  2800. echo ".";
  2801. if ($counter % 200 == 0) {
  2802. echo "<br />";
  2803. }
  2804. }
  2805. backup_flush(300);
  2806. }
  2807. } /// End of loop over all the users loaded from backup_ids table
  2808. /// Inform about all the messages geerated while restoring users
  2809. if (!defined('RESTORE_SILENTLY')) {
  2810. if ($messages) {
  2811. echo '<ul>';
  2812. foreach ($messages as $message) {
  2813. echo '<li>' . $message . '</li>';
  2814. }
  2815. echo '</ul>';
  2816. }
  2817. }
  2818. }
  2819. return $status;
  2820. }
  2821. //This function creates all the structures messages and contacts
  2822. function restore_create_messages($restore,$xml_file) {
  2823. global $CFG;
  2824. $status = true;
  2825. //Check it exists
  2826. if (!file_exists($xml_file)) {
  2827. $status = false;
  2828. }
  2829. //Get info from xml
  2830. if ($status) {
  2831. //info will contain the id and name of every table
  2832. //(message, message_read and message_contacts)
  2833. //in backup_ids->info will be the real info (serialized)
  2834. $info = restore_read_xml_messages($restore,$xml_file);
  2835. //If we have info, then process messages & contacts
  2836. if ($info > 0) {
  2837. //Count how many we have
  2838. $unreadcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'message');
  2839. $readcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'message_read');
  2840. $contactcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'message_contacts');
  2841. if ($unreadcount || $readcount || $contactcount) {
  2842. //Start ul
  2843. if (!defined('RESTORE_SILENTLY')) {
  2844. echo '<ul>';
  2845. }
  2846. //Number of records to get in every chunk
  2847. $recordset_size = 4;
  2848. //Process unread
  2849. if ($unreadcount) {
  2850. if (!defined('RESTORE_SILENTLY')) {
  2851. echo '<li>'.get_string('unreadmessages','message').'</li>';
  2852. }
  2853. $counter = 0;
  2854. while ($counter < $unreadcount) {
  2855. //Fetch recordset_size records in each iteration
  2856. $recs = get_records_select("backup_ids","table_name = 'message' AND backup_code = '$restore->backup_unique_code'","old_id","old_id",$counter,$recordset_size);
  2857. if ($recs) {
  2858. foreach ($recs as $rec) {
  2859. //Get the full record from backup_ids
  2860. $data = backup_getid($restore->backup_unique_code,"message",$rec->old_id);
  2861. if ($data) {
  2862. //Now get completed xmlized object
  2863. $info = $data->info;
  2864. //traverse_xmlize($info); //Debug
  2865. //print_object ($GLOBALS['traverse_array']); //Debug
  2866. //$GLOBALS['traverse_array']=""; //Debug
  2867. //Now build the MESSAGE record structure
  2868. $dbrec = new object();
  2869. $dbrec->useridfrom = backup_todb($info['MESSAGE']['#']['USERIDFROM']['0']['#']);
  2870. $dbrec->useridto = backup_todb($info['MESSAGE']['#']['USERIDTO']['0']['#']);
  2871. $dbrec->message = backup_todb($info['MESSAGE']['#']['MESSAGE']['0']['#']);
  2872. $dbrec->format = backup_todb($info['MESSAGE']['#']['FORMAT']['0']['#']);
  2873. $dbrec->timecreated = backup_todb($info['MESSAGE']['#']['TIMECREATED']['0']['#']);
  2874. $dbrec->messagetype = backup_todb($info['MESSAGE']['#']['MESSAGETYPE']['0']['#']);
  2875. //We have to recode the useridfrom field
  2876. $user = backup_getid($restore->backup_unique_code,"user",$dbrec->useridfrom);
  2877. if ($user) {
  2878. //echo "User ".$dbrec->useridfrom." to user ".$user->new_id."<br />"; //Debug
  2879. $dbrec->useridfrom = $user->new_id;
  2880. }
  2881. //We have to recode the useridto field
  2882. $user = backup_getid($restore->backup_unique_code,"user",$dbrec->useridto);
  2883. if ($user) {
  2884. //echo "User ".$dbrec->useridto." to user ".$user->new_id."<br />"; //Debug
  2885. $dbrec->useridto = $user->new_id;
  2886. }
  2887. //Check if the record doesn't exist in DB!
  2888. $exist = get_record('message','useridfrom',$dbrec->useridfrom,
  2889. 'useridto', $dbrec->useridto,
  2890. 'timecreated',$dbrec->timecreated);
  2891. if (!$exist) {
  2892. //Not exist. Insert
  2893. $status = insert_record('message',$dbrec);
  2894. } else {
  2895. //Duplicate. Do nothing
  2896. }
  2897. }
  2898. //Do some output
  2899. $counter++;
  2900. if ($counter % 10 == 0) {
  2901. if (!defined('RESTORE_SILENTLY')) {
  2902. echo ".";
  2903. if ($counter % 200 == 0) {
  2904. echo "<br />";
  2905. }
  2906. }
  2907. backup_flush(300);
  2908. }
  2909. }
  2910. }
  2911. }
  2912. }
  2913. //Process read
  2914. if ($readcount) {
  2915. if (!defined('RESTORE_SILENTLY')) {
  2916. echo '<li>'.get_string('readmessages','message').'</li>';
  2917. }
  2918. $counter = 0;
  2919. while ($counter < $readcount) {
  2920. //Fetch recordset_size records in each iteration
  2921. $recs = get_records_select("backup_ids","table_name = 'message_read' AND backup_code = '$restore->backup_unique_code'","old_id","old_id",$counter,$recordset_size);
  2922. if ($recs) {
  2923. foreach ($recs as $rec) {
  2924. //Get the full record from backup_ids
  2925. $data = backup_getid($restore->backup_unique_code,"message_read",$rec->old_id);
  2926. if ($data) {
  2927. //Now get completed xmlized object
  2928. $info = $data->info;
  2929. //traverse_xmlize($info); //Debug
  2930. //print_object ($GLOBALS['traverse_array']); //Debug
  2931. //$GLOBALS['traverse_array']=""; //Debug
  2932. //Now build the MESSAGE_READ record structure
  2933. $dbrec->useridfrom = backup_todb($info['MESSAGE']['#']['USERIDFROM']['0']['#']);
  2934. $dbrec->useridto = backup_todb($info['MESSAGE']['#']['USERIDTO']['0']['#']);
  2935. $dbrec->message = backup_todb($info['MESSAGE']['#']['MESSAGE']['0']['#']);
  2936. $dbrec->format = backup_todb($info['MESSAGE']['#']['FORMAT']['0']['#']);
  2937. $dbrec->timecreated = backup_todb($info['MESSAGE']['#']['TIMECREATED']['0']['#']);
  2938. $dbrec->messagetype = backup_todb($info['MESSAGE']['#']['MESSAGETYPE']['0']['#']);
  2939. $dbrec->timeread = backup_todb($info['MESSAGE']['#']['TIMEREAD']['0']['#']);
  2940. $dbrec->mailed = backup_todb($info['MESSAGE']['#']['MAILED']['0']['#']);
  2941. //We have to recode the useridfrom field
  2942. $user = backup_getid($restore->backup_unique_code,"user",$dbrec->useridfrom);
  2943. if ($user) {
  2944. //echo "User ".$dbrec->useridfrom." to user ".$user->new_id."<br />"; //Debug
  2945. $dbrec->useridfrom = $user->new_id;
  2946. }
  2947. //We have to recode the useridto field
  2948. $user = backup_getid($restore->backup_unique_code,"user",$dbrec->useridto);
  2949. if ($user) {
  2950. //echo "User ".$dbrec->useridto." to user ".$user->new_id."<br />"; //Debug
  2951. $dbrec->useridto = $user->new_id;
  2952. }
  2953. //Check if the record doesn't exist in DB!
  2954. $exist = get_record('message_read','useridfrom',$dbrec->useridfrom,
  2955. 'useridto', $dbrec->useridto,
  2956. 'timecreated',$dbrec->timecreated);
  2957. if (!$exist) {
  2958. //Not exist. Insert
  2959. $status = insert_record('message_read',$dbrec);
  2960. } else {
  2961. //Duplicate. Do nothing
  2962. }
  2963. }
  2964. //Do some output
  2965. $counter++;
  2966. if ($counter % 10 == 0) {
  2967. if (!defined('RESTORE_SILENTLY')) {
  2968. echo ".";
  2969. if ($counter % 200 == 0) {
  2970. echo "<br />";
  2971. }
  2972. }
  2973. backup_flush(300);
  2974. }
  2975. }
  2976. }
  2977. }
  2978. }
  2979. //Process contacts
  2980. if ($contactcount) {
  2981. if (!defined('RESTORE_SILENTLY')) {
  2982. echo '<li>'.moodle_strtolower(get_string('contacts','message')).'</li>';
  2983. }
  2984. $counter = 0;
  2985. while ($counter < $contactcount) {
  2986. //Fetch recordset_size records in each iteration
  2987. $recs = get_records_select("backup_ids","table_name = 'message_contacts' AND backup_code = '$restore->backup_unique_code'","old_id","old_id",$counter,$recordset_size);
  2988. if ($recs) {
  2989. foreach ($recs as $rec) {
  2990. //Get the full record from backup_ids
  2991. $data = backup_getid($restore->backup_unique_code,"message_contacts",$rec->old_id);
  2992. if ($data) {
  2993. //Now get completed xmlized object
  2994. $info = $data->info;
  2995. //traverse_xmlize($info); //Debug
  2996. //print_object ($GLOBALS['traverse_array']); //Debug
  2997. //$GLOBALS['traverse_array']=""; //Debug
  2998. //Now build the MESSAGE_CONTACTS record structure
  2999. $dbrec->userid = backup_todb($info['CONTACT']['#']['USERID']['0']['#']);
  3000. $dbrec->contactid = backup_todb($info['CONTACT']['#']['CONTACTID']['0']['#']);
  3001. $dbrec->blocked = backup_todb($info['CONTACT']['#']['BLOCKED']['0']['#']);
  3002. //We have to recode the userid field
  3003. $user = backup_getid($restore->backup_unique_code,"user",$dbrec->userid);
  3004. if ($user) {
  3005. //echo "User ".$dbrec->userid." to user ".$user->new_id."<br />"; //Debug
  3006. $dbrec->userid = $user->new_id;
  3007. }
  3008. //We have to recode the contactid field
  3009. $user = backup_getid($restore->backup_unique_code,"user",$dbrec->contactid);
  3010. if ($user) {
  3011. //echo "User ".$dbrec->contactid." to user ".$user->new_id."<br />"; //Debug
  3012. $dbrec->contactid = $user->new_id;
  3013. }
  3014. //Check if the record doesn't exist in DB!
  3015. $exist = get_record('message_contacts','userid',$dbrec->userid,
  3016. 'contactid', $dbrec->contactid);
  3017. if (!$exist) {
  3018. //Not exist. Insert
  3019. $status = insert_record('message_contacts',$dbrec);
  3020. } else {
  3021. //Duplicate. Do nothing
  3022. }
  3023. }
  3024. //Do some output
  3025. $counter++;
  3026. if ($counter % 10 == 0) {
  3027. if (!defined('RESTORE_SILENTLY')) {
  3028. echo ".";
  3029. if ($counter % 200 == 0) {
  3030. echo "<br />";
  3031. }
  3032. }
  3033. backup_flush(300);
  3034. }
  3035. }
  3036. }
  3037. }
  3038. }
  3039. if (!defined('RESTORE_SILENTLY')) {
  3040. //End ul
  3041. echo '</ul>';
  3042. }
  3043. }
  3044. }
  3045. }
  3046. return $status;
  3047. }
  3048. //This function creates all the structures for blogs and blog tags
  3049. function restore_create_blogs($restore,$xml_file) {
  3050. global $CFG;
  3051. $status = true;
  3052. //Check it exists
  3053. if (!file_exists($xml_file)) {
  3054. $status = false;
  3055. }
  3056. //Get info from xml
  3057. if ($status) {
  3058. //info will contain the number of blogs in the backup file
  3059. //in backup_ids->info will be the real info (serialized)
  3060. $info = restore_read_xml_blogs($restore,$xml_file);
  3061. //If we have info, then process blogs & blog_tags
  3062. if ($info > 0) {
  3063. //Count how many we have
  3064. $blogcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'blog');
  3065. if ($blogcount) {
  3066. //Number of records to get in every chunk
  3067. $recordset_size = 4;
  3068. //Process blog
  3069. if ($blogcount) {
  3070. $counter = 0;
  3071. while ($counter < $blogcount) {
  3072. //Fetch recordset_size records in each iteration
  3073. $recs = get_records_select("backup_ids","table_name = 'blog' AND backup_code = '$restore->backup_unique_code'","old_id","old_id",$counter,$recordset_size);
  3074. if ($recs) {
  3075. foreach ($recs as $rec) {
  3076. //Get the full record from backup_ids
  3077. $data = backup_getid($restore->backup_unique_code,"blog",$rec->old_id);
  3078. if ($data) {
  3079. //Now get completed xmlized object
  3080. $info = $data->info;
  3081. //traverse_xmlize($info); //Debug
  3082. //print_object ($GLOBALS['traverse_array']); //Debug
  3083. //$GLOBALS['traverse_array']=""; //Debug
  3084. //Now build the BLOG record structure
  3085. $dbrec = new object();
  3086. $dbrec->module = backup_todb($info['BLOG']['#']['MODULE']['0']['#']);
  3087. $dbrec->userid = backup_todb($info['BLOG']['#']['USERID']['0']['#']);
  3088. $dbrec->courseid = backup_todb($info['BLOG']['#']['COURSEID']['0']['#']);
  3089. $dbrec->groupid = backup_todb($info['BLOG']['#']['GROUPID']['0']['#']);
  3090. $dbrec->moduleid = backup_todb($info['BLOG']['#']['MODULEID']['0']['#']);
  3091. $dbrec->coursemoduleid = backup_todb($info['BLOG']['#']['COURSEMODULEID']['0']['#']);
  3092. $dbrec->subject = backup_todb($info['BLOG']['#']['SUBJECT']['0']['#']);
  3093. $dbrec->summary = backup_todb($info['BLOG']['#']['SUMMARY']['0']['#']);
  3094. $dbrec->content = backup_todb($info['BLOG']['#']['CONTENT']['0']['#']);
  3095. $dbrec->uniquehash = backup_todb($info['BLOG']['#']['UNIQUEHASH']['0']['#']);
  3096. $dbrec->rating = backup_todb($info['BLOG']['#']['RATING']['0']['#']);
  3097. $dbrec->format = backup_todb($info['BLOG']['#']['FORMAT']['0']['#']);
  3098. $dbrec->attachment = backup_todb($info['BLOG']['#']['ATTACHMENT']['0']['#']);
  3099. $dbrec->publishstate = backup_todb($info['BLOG']['#']['PUBLISHSTATE']['0']['#']);
  3100. $dbrec->lastmodified = backup_todb($info['BLOG']['#']['LASTMODIFIED']['0']['#']);
  3101. $dbrec->created = backup_todb($info['BLOG']['#']['CREATED']['0']['#']);
  3102. $dbrec->usermodified = backup_todb($info['BLOG']['#']['USERMODIFIED']['0']['#']);
  3103. //We have to recode the userid field
  3104. $user = backup_getid($restore->backup_unique_code,"user",$dbrec->userid);
  3105. if ($user) {
  3106. //echo "User ".$dbrec->userid." to user ".$user->new_id."<br />"; //Debug
  3107. $dbrec->userid = $user->new_id;
  3108. }
  3109. //Check if the record doesn't exist in DB!
  3110. $exist = get_record('post','userid', $dbrec->userid,
  3111. 'subject', $dbrec->subject,
  3112. 'created', $dbrec->created);
  3113. $newblogid = 0;
  3114. if (!$exist) {
  3115. //Not exist. Insert
  3116. $newblogid = insert_record('post',$dbrec);
  3117. }
  3118. //Going to restore related tags. Check they are enabled and we have inserted a blog
  3119. if ($CFG->usetags && $newblogid) {
  3120. //Look for tags in this blog
  3121. if (isset($info['BLOG']['#']['BLOG_TAGS']['0']['#']['BLOG_TAG'])) {
  3122. $tagsarr = $info['BLOG']['#']['BLOG_TAGS']['0']['#']['BLOG_TAG'];
  3123. //Iterate over tags
  3124. $tags = array();
  3125. for($i = 0; $i < sizeof($tagsarr); $i++) {
  3126. $tag_info = $tagsarr[$i];
  3127. ///traverse_xmlize($tag_info); //Debug
  3128. ///print_object ($GLOBALS['traverse_array']); //Debug
  3129. ///$GLOBALS['traverse_array']=""; //Debug
  3130. $name = backup_todb($tag_info['#']['NAME']['0']['#']);
  3131. $rawname = backup_todb($tag_info['#']['RAWNAME']['0']['#']);
  3132. $tags[] = $rawname; //Rawname is all we need
  3133. }
  3134. tag_set('post', $newblogid, $tags); //Add all the tags in one API call
  3135. }
  3136. }
  3137. }
  3138. //Do some output
  3139. $counter++;
  3140. if ($counter % 10 == 0) {
  3141. if (!defined('RESTORE_SILENTLY')) {
  3142. echo ".";
  3143. if ($counter % 200 == 0) {
  3144. echo "<br />";
  3145. }
  3146. }
  3147. backup_flush(300);
  3148. }
  3149. }
  3150. }
  3151. }
  3152. }
  3153. }
  3154. }
  3155. }
  3156. return $status;
  3157. }
  3158. //This function creates all the categories and questions
  3159. //from xml
  3160. function restore_create_questions($restore,$xml_file) {
  3161. global $CFG, $db;
  3162. $status = true;
  3163. //Check it exists
  3164. if (!file_exists($xml_file)) {
  3165. $status = false;
  3166. }
  3167. //Get info from xml
  3168. if ($status) {
  3169. //info will contain the old_id of every category
  3170. //in backup_ids->info will be the real info (serialized)
  3171. $info = restore_read_xml_questions($restore,$xml_file);
  3172. }
  3173. //Now, if we have anything in info, we have to restore that
  3174. //categories/questions
  3175. if ($info) {
  3176. if ($info !== true) {
  3177. $status = $status && restore_question_categories($info, $restore);
  3178. }
  3179. } else {
  3180. $status = false;
  3181. }
  3182. return $status;
  3183. }
  3184. //This function creates all the scales
  3185. function restore_create_scales($restore,$xml_file) {
  3186. global $CFG, $USER, $db;
  3187. $status = true;
  3188. //Check it exists
  3189. if (!file_exists($xml_file)) {
  3190. $status = false;
  3191. }
  3192. //Get info from xml
  3193. if ($status) {
  3194. //scales will contain the old_id of every scale
  3195. //in backup_ids->info will be the real info (serialized)
  3196. $scales = restore_read_xml_scales($restore,$xml_file);
  3197. }
  3198. //Now, if we have anything in scales, we have to restore that
  3199. //scales
  3200. if ($scales) {
  3201. if ($scales !== true) {
  3202. //Iterate over each scale
  3203. foreach ($scales as $scale) {
  3204. //Get record from backup_ids
  3205. $data = backup_getid($restore->backup_unique_code,"scale",$scale->id);
  3206. if ($data) {
  3207. //Now get completed xmlized object
  3208. $info = $data->info;
  3209. //traverse_xmlize($info); //Debug
  3210. //print_object ($GLOBALS['traverse_array']); //Debug
  3211. //$GLOBALS['traverse_array']=""; //Debug
  3212. //Now build the SCALE record structure
  3213. $sca = new object();
  3214. $sca->courseid = backup_todb($info['SCALE']['#']['COURSEID']['0']['#']);
  3215. $sca->userid = backup_todb($info['SCALE']['#']['USERID']['0']['#']);
  3216. $sca->name = backup_todb($info['SCALE']['#']['NAME']['0']['#']);
  3217. $sca->scale = backup_todb($info['SCALE']['#']['SCALETEXT']['0']['#']);
  3218. $sca->description = backup_todb($info['SCALE']['#']['DESCRIPTION']['0']['#']);
  3219. $sca->timemodified = backup_todb($info['SCALE']['#']['TIMEMODIFIED']['0']['#']);
  3220. // Look for scale (by 'scale' both in standard (course=0) and current course
  3221. // with priority to standard scales (ORDER clause)
  3222. // scale is not course unique, use get_record_sql to suppress warning
  3223. // Going to compare LOB columns so, use the cross-db sql_compare_text() in both sides.
  3224. $compare_scale_clause = sql_compare_text('scale') . "=" . sql_compare_text("'" . $sca->scale . "'");
  3225. // Scale doesn't exist, create it
  3226. if (!$sca_db = get_record_sql("SELECT *
  3227. FROM {$CFG->prefix}scale
  3228. WHERE $compare_scale_clause
  3229. AND courseid IN (0, $restore->course_id)
  3230. ORDER BY courseid", true)) {
  3231. // Try to recode the user field, defaulting to current user if not found
  3232. $user = backup_getid($restore->backup_unique_code,"user",$sca->userid);
  3233. if ($user) {
  3234. $sca->userid = $user->new_id;
  3235. } else {
  3236. $sca->userid = $USER->id;
  3237. }
  3238. // If course scale, recode the course field
  3239. if ($sca->courseid != 0) {
  3240. $sca->courseid = $restore->course_id;
  3241. }
  3242. // If scale is standard, if user lacks perms to manage standar scales
  3243. // 'downgrade' them to course scales
  3244. if ($sca->courseid == 0 and !has_capability('moodle/course:managescales', get_context_instance(CONTEXT_SYSTEM), $sca->userid)) {
  3245. $sca->courseid = $restore->course_id;
  3246. }
  3247. //The structure is equal to the db, so insert the scale
  3248. $newid = insert_record ("scale",$sca);
  3249. // Scale exists, reuse it
  3250. } else {
  3251. $newid = $sca_db->id;
  3252. }
  3253. if ($newid) {
  3254. //We have the newid, update backup_ids
  3255. backup_putid($restore->backup_unique_code,"scale", $scale->id, $newid);
  3256. }
  3257. }
  3258. }
  3259. }
  3260. } else {
  3261. $status = false;
  3262. }
  3263. return $status;
  3264. }
  3265. /**
  3266. * Recode group ID field, and set group ID based on restore options.
  3267. * @return object Group object with new_id field.
  3268. */
  3269. function restore_group_getid($restore, $groupid) {
  3270. //We have to recode the groupid field
  3271. $group = backup_getid($restore->backup_unique_code, 'groups', $groupid);
  3272. if ($restore->groups == RESTORE_GROUPS_NONE or $restore->groups == RESTORE_GROUPINGS_ONLY) {
  3273. $group->new_id = 0;
  3274. }
  3275. return $group;
  3276. }
  3277. /**
  3278. * Recode grouping ID field, and set grouping ID based on restore options.
  3279. * @return object Group object with new_id field.
  3280. */
  3281. function restore_grouping_getid($restore, $groupingid) {
  3282. //We have to recode the groupid field
  3283. $grouping = backup_getid($restore->backup_unique_code, 'groupings', $groupingid);
  3284. if ($restore->groups != RESTORE_GROUPS_GROUPINGS and $restore->groups != RESTORE_GROUPINGS_ONLY) {
  3285. $grouping->new_id = 0;
  3286. }
  3287. return $grouping;
  3288. }
  3289. //This function creates all the groups
  3290. function restore_create_groups($restore,$xml_file) {
  3291. global $CFG;
  3292. //Check it exists
  3293. if (!file_exists($xml_file)) {
  3294. return false;
  3295. }
  3296. //Get info from xml
  3297. if (!$groups = restore_read_xml_groups($restore,$xml_file)) {
  3298. //groups will contain the old_id of every group
  3299. //in backup_ids->info will be the real info (serialized)
  3300. return false;
  3301. } else if ($groups === true) {
  3302. return true;
  3303. }
  3304. $status = true;
  3305. //Iterate over each group
  3306. foreach ($groups as $group) {
  3307. //Get record from backup_ids
  3308. $data = backup_getid($restore->backup_unique_code,"groups",$group->id);
  3309. if ($data) {
  3310. //Now get completed xmlized object
  3311. $info = $data->info;
  3312. //traverse_xmlize($info); //Debug
  3313. //print_object ($GLOBALS['traverse_array']); //Debug
  3314. //$GLOBALS['traverse_array']=""; //Debug
  3315. //Now build the GROUP record structure
  3316. $gro = new Object();
  3317. $gro->courseid = $restore->course_id;
  3318. $gro->name = backup_todb($info['GROUP']['#']['NAME']['0']['#']);
  3319. $gro->description = backup_todb($info['GROUP']['#']['DESCRIPTION']['0']['#']);
  3320. if (isset($info['GROUP']['#']['ENROLMENTKEY']['0']['#'])) {
  3321. $gro->enrolmentkey = backup_todb($info['GROUP']['#']['ENROLMENTKEY']['0']['#']);
  3322. } else {
  3323. $gro->enrolmentkey = backup_todb($info['GROUP']['#']['PASSWORD']['0']['#']);
  3324. }
  3325. $gro->picture = backup_todb($info['GROUP']['#']['PICTURE']['0']['#']);
  3326. $gro->hidepicture = backup_todb($info['GROUP']['#']['HIDEPICTURE']['0']['#']);
  3327. $gro->timecreated = backup_todb($info['GROUP']['#']['TIMECREATED']['0']['#']);
  3328. $gro->timemodified = backup_todb($info['GROUP']['#']['TIMEMODIFIED']['0']['#']);
  3329. //Now search if that group exists (by name and description field) in
  3330. //restore->course_id course
  3331. //Going to compare LOB columns so, use the cross-db sql_compare_text() in both sides.
  3332. $description_clause = '';
  3333. if (!empty($gro->description)) { /// Only for groups having a description
  3334. $literal_description = "'" . $gro->description . "'";
  3335. $description_clause = " AND " .
  3336. sql_compare_text('description') . " = " .
  3337. sql_compare_text($literal_description);
  3338. }
  3339. if (!$gro_db = get_record_sql("SELECT *
  3340. FROM {$CFG->prefix}groups
  3341. WHERE courseid = $restore->course_id AND
  3342. name = '{$gro->name}'" . $description_clause, true)) {
  3343. //If it doesn't exist, create
  3344. $newid = insert_record('groups', $gro);
  3345. } else {
  3346. //get current group id
  3347. $newid = $gro_db->id;
  3348. }
  3349. if ($newid) {
  3350. //We have the newid, update backup_ids
  3351. backup_putid($restore->backup_unique_code,"groups", $group->id, $newid);
  3352. } else {
  3353. $status = false;
  3354. continue;
  3355. }
  3356. //Now restore members in the groups_members, only if
  3357. //users are included
  3358. if ($restore->users != 2) {
  3359. if (!restore_create_groups_members($newid,$info,$restore)) {
  3360. $status = false;
  3361. }
  3362. }
  3363. }
  3364. }
  3365. //Now, restore group_files
  3366. if ($status) {
  3367. $status = restore_group_files($restore);
  3368. }
  3369. return $status;
  3370. }
  3371. //This function restores the groups_members
  3372. function restore_create_groups_members($group_id,$info,$restore) {
  3373. if (! isset($info['GROUP']['#']['MEMBERS']['0']['#']['MEMBER'])) {
  3374. //OK, some groups have no members.
  3375. return true;
  3376. }
  3377. //Get the members array
  3378. $members = $info['GROUP']['#']['MEMBERS']['0']['#']['MEMBER'];
  3379. $status = true;
  3380. //Iterate over members
  3381. for($i = 0; $i < sizeof($members); $i++) {
  3382. $mem_info = $members[$i];
  3383. //traverse_xmlize($mem_info); //Debug
  3384. //print_object ($GLOBALS['traverse_array']); //Debug
  3385. //$GLOBALS['traverse_array']=""; //Debug
  3386. //Now, build the GROUPS_MEMBERS record structure
  3387. $group_member = new Object();
  3388. $group_member->groupid = $group_id;
  3389. $group_member->userid = backup_todb($mem_info['#']['USERID']['0']['#']);
  3390. $group_member->timeadded = backup_todb($mem_info['#']['TIMEADDED']['0']['#']);
  3391. $newid = false;
  3392. //We have to recode the userid field
  3393. if (!$user = backup_getid($restore->backup_unique_code,"user",$group_member->userid)) {
  3394. debugging("group membership can not be restored, user id $group_member->userid not present in backup");
  3395. // do not not block the restore
  3396. continue;
  3397. }
  3398. $group_member->userid = $user->new_id;
  3399. //The structure is equal to the db, so insert the groups_members
  3400. if (record_exists("groups_members", 'groupid', $group_member->groupid, 'userid', $group_member->userid)) {
  3401. // user already member
  3402. } else if (!insert_record ("groups_members", $group_member)) {
  3403. $status = false;
  3404. continue;
  3405. }
  3406. //Do some output
  3407. if (($i+1) % 50 == 0) {
  3408. if (!defined('RESTORE_SILENTLY')) {
  3409. echo ".";
  3410. if (($i+1) % 1000 == 0) {
  3411. echo "<br />";
  3412. }
  3413. }
  3414. backup_flush(300);
  3415. }
  3416. }
  3417. return $status;
  3418. }
  3419. //This function creates all the groupings
  3420. function restore_create_groupings($restore,$xml_file) {
  3421. //Check it exists
  3422. if (!file_exists($xml_file)) {
  3423. return false;
  3424. }
  3425. //Get info from xml
  3426. if (!$groupings = restore_read_xml_groupings($restore,$xml_file)) {
  3427. return false;
  3428. } else if ($groupings === true) {
  3429. return true;
  3430. }
  3431. $status = true;
  3432. //Iterate over each group
  3433. foreach ($groupings as $grouping) {
  3434. if ($data = backup_getid($restore->backup_unique_code,"groupings",$grouping->id)) {
  3435. //Now get completed xmlized object
  3436. $info = $data->info;
  3437. //Now build the GROUPING record structure
  3438. $gro = new Object();
  3439. ///$gro->id = backup_todb($info['GROUPING']['#']['ID']['0']['#']);
  3440. $gro->courseid = $restore->course_id;
  3441. $gro->name = backup_todb($info['GROUPING']['#']['NAME']['0']['#']);
  3442. $gro->description = backup_todb($info['GROUPING']['#']['DESCRIPTION']['0']['#']);
  3443. $gro->configdata = backup_todb($info['GROUPING']['#']['CONFIGDATA']['0']['#']);
  3444. $gro->timecreated = backup_todb($info['GROUPING']['#']['TIMECREATED']['0']['#']);
  3445. //Now search if that group exists (by name and description field) in
  3446. if ($gro_db = get_record('groupings', 'courseid', $restore->course_id, 'name', $gro->name, 'description', $gro->description)) {
  3447. //get current group id
  3448. $newid = $gro_db->id;
  3449. } else {
  3450. //The structure is equal to the db, so insert the grouping
  3451. if (!$newid = insert_record('groupings', $gro)) {
  3452. $status = false;
  3453. continue;
  3454. }
  3455. }
  3456. //We have the newid, update backup_ids
  3457. backup_putid($restore->backup_unique_code,"groupings",
  3458. $grouping->id, $newid);
  3459. }
  3460. }
  3461. // now fix the defaultgroupingid in course
  3462. $course = get_record('course', 'id', $restore->course_id);
  3463. if ($course->defaultgroupingid) {
  3464. if ($grouping = restore_grouping_getid($restore, $course->defaultgroupingid)) {
  3465. set_field('course', 'defaultgroupingid', $grouping->new_id, 'id', $course->id);
  3466. } else {
  3467. set_field('course', 'defaultgroupingid', 0, 'id', $course->id);
  3468. }
  3469. }
  3470. return $status;
  3471. }
  3472. //This function creates all the groupingsgroups
  3473. function restore_create_groupings_groups($restore,$xml_file) {
  3474. //Check it exists
  3475. if (!file_exists($xml_file)) {
  3476. return false;
  3477. }
  3478. //Get info from xml
  3479. if (!$groupingsgroups = restore_read_xml_groupings_groups($restore,$xml_file)) {
  3480. return false;
  3481. } else if ($groupingsgroups === true) {
  3482. return true;
  3483. }
  3484. $status = true;
  3485. //Iterate over each group
  3486. foreach ($groupingsgroups as $groupinggroup) {
  3487. if ($data = backup_getid($restore->backup_unique_code,"groupingsgroups",$groupinggroup->id)) {
  3488. //Now get completed xmlized object
  3489. $info = $data->info;
  3490. //Now build the GROUPING record structure
  3491. $gro_member = new Object();
  3492. $gro_member->groupingid = backup_todb($info['GROUPINGGROUP']['#']['GROUPINGID']['0']['#']);
  3493. $gro_member->groupid = backup_todb($info['GROUPINGGROUP']['#']['GROUPID']['0']['#']);
  3494. $gro_member->timeadded = backup_todb($info['GROUPINGGROUP']['#']['TIMEADDED']['0']['#']);
  3495. if (!$grouping = backup_getid($restore->backup_unique_code,"groupings",$gro_member->groupingid)) {
  3496. $status = false;
  3497. continue;
  3498. }
  3499. if (!$group = backup_getid($restore->backup_unique_code,"groups",$gro_member->groupid)) {
  3500. $status = false;
  3501. continue;
  3502. }
  3503. $gro_member->groupid = $group->new_id;
  3504. $gro_member->groupingid = $grouping->new_id;
  3505. if (!get_record('groupings_groups', 'groupid', $gro_member->groupid, 'groupingid', $gro_member->groupingid)) {
  3506. if (!insert_record('groupings_groups', $gro_member)) {
  3507. $status = false;
  3508. }
  3509. }
  3510. }
  3511. }
  3512. return $status;
  3513. }
  3514. //This function creates all the course events
  3515. function restore_create_events($restore,$xml_file) {
  3516. global $CFG, $db;
  3517. $status = true;
  3518. //Check it exists
  3519. if (!file_exists($xml_file)) {
  3520. $status = false;
  3521. }
  3522. //Get info from xml
  3523. if ($status) {
  3524. //events will contain the old_id of every event
  3525. //in backup_ids->info will be the real info (serialized)
  3526. $events = restore_read_xml_events($restore,$xml_file);
  3527. }
  3528. //Get admin->id for later use
  3529. $admin = get_admin();
  3530. $adminid = $admin->id;
  3531. //Now, if we have anything in events, we have to restore that
  3532. //events
  3533. if ($events) {
  3534. if ($events !== true) {
  3535. //Iterate over each event
  3536. foreach ($events as $event) {
  3537. //Get record from backup_ids
  3538. $data = backup_getid($restore->backup_unique_code,"event",$event->id);
  3539. //Init variables
  3540. $create_event = false;
  3541. if ($data) {
  3542. //Now get completed xmlized object
  3543. $info = $data->info;
  3544. //traverse_xmlize($info); //Debug
  3545. //print_object ($GLOBALS['traverse_array']); //Debug
  3546. //$GLOBALS['traverse_array']=""; //Debug
  3547. //if necessary, write to restorelog and adjust date/time fields
  3548. if ($restore->course_startdateoffset) {
  3549. restore_log_date_changes('Events', $restore, $info['EVENT']['#'], array('TIMESTART'));
  3550. }
  3551. //Now build the EVENT record structure
  3552. $eve->name = backup_todb($info['EVENT']['#']['NAME']['0']['#']);
  3553. $eve->description = backup_todb($info['EVENT']['#']['DESCRIPTION']['0']['#']);
  3554. $eve->format = backup_todb($info['EVENT']['#']['FORMAT']['0']['#']);
  3555. $eve->courseid = $restore->course_id;
  3556. $eve->groupid = backup_todb($info['EVENT']['#']['GROUPID']['0']['#']);
  3557. $eve->userid = backup_todb($info['EVENT']['#']['USERID']['0']['#']);
  3558. $eve->repeatid = backup_todb($info['EVENT']['#']['REPEATID']['0']['#']);
  3559. $eve->modulename = "";
  3560. if (!empty($info['EVENT']['#']['MODULENAME'])) {
  3561. $eve->modulename = backup_todb($info['EVENT']['#']['MODULENAME']['0']['#']);
  3562. }
  3563. $eve->instance = 0;
  3564. $eve->eventtype = backup_todb($info['EVENT']['#']['EVENTTYPE']['0']['#']);
  3565. $eve->timestart = backup_todb($info['EVENT']['#']['TIMESTART']['0']['#']);
  3566. $eve->timeduration = backup_todb($info['EVENT']['#']['TIMEDURATION']['0']['#']);
  3567. $eve->visible = backup_todb($info['EVENT']['#']['VISIBLE']['0']['#']);
  3568. $eve->timemodified = backup_todb($info['EVENT']['#']['TIMEMODIFIED']['0']['#']);
  3569. //Now search if that event exists (by name, description, timestart fields) in
  3570. //restore->course_id course
  3571. //Going to compare LOB columns so, use the cross-db sql_compare_text() in both sides.
  3572. $compare_description_clause = sql_compare_text('description') . "=" . sql_compare_text("'" . $eve->description . "'");
  3573. $eve_db = get_record_select("event",
  3574. "courseid={$eve->courseid} AND name='{$eve->name}' AND $compare_description_clause AND timestart=$eve->timestart");
  3575. //If it doesn't exist, create
  3576. if (!$eve_db) {
  3577. $create_event = true;
  3578. }
  3579. //If we must create the event
  3580. if ($create_event) {
  3581. //We must recode the userid
  3582. $user = backup_getid($restore->backup_unique_code,"user",$eve->userid);
  3583. if ($user) {
  3584. $eve->userid = $user->new_id;
  3585. } else {
  3586. //Assign it to admin
  3587. $eve->userid = $adminid;
  3588. }
  3589. //We have to recode the groupid field
  3590. $group = backup_getid($restore->backup_unique_code,"groups",$eve->groupid);
  3591. if ($group) {
  3592. $eve->groupid = $group->new_id;
  3593. } else {
  3594. //Assign it to group 0
  3595. $eve->groupid = 0;
  3596. }
  3597. //The structure is equal to the db, so insert the event
  3598. $newid = insert_record ("event",$eve);
  3599. //We must recode the repeatid if the event has it
  3600. //The repeatid now refers to the id of the original event. (see Bug#5956)
  3601. if ($newid && !empty($eve->repeatid)) {
  3602. $repeat_rec = backup_getid($restore->backup_unique_code,"event_repeatid",$eve->repeatid);
  3603. if ($repeat_rec) { //Exists, so use it...
  3604. $eve->repeatid = $repeat_rec->new_id;
  3605. } else { //Doesn't exists, calculate the next and save it
  3606. $oldrepeatid = $eve->repeatid;
  3607. $eve->repeatid = $newid;
  3608. backup_putid($restore->backup_unique_code,"event_repeatid", $oldrepeatid, $eve->repeatid);
  3609. }
  3610. $eve->id = $newid;
  3611. // update the record to contain the correct repeatid
  3612. update_record('event',$eve);
  3613. }
  3614. } else {
  3615. //get current event id
  3616. $newid = $eve_db->id;
  3617. }
  3618. if ($newid) {
  3619. //We have the newid, update backup_ids
  3620. backup_putid($restore->backup_unique_code,"event",
  3621. $event->id, $newid);
  3622. }
  3623. }
  3624. }
  3625. }
  3626. } else {
  3627. $status = false;
  3628. }
  3629. return $status;
  3630. }
  3631. //This function decode things to make restore multi-site fully functional
  3632. //It does this conversions:
  3633. // - $@FILEPHP@$ ---|------------> $CFG->wwwroot/file.php/courseid (slasharguments on)
  3634. // |------------> $CFG->wwwroot/file.php?file=/courseid (slasharguments off)
  3635. //
  3636. // - $@SLASH@$ --|---------------> / (slasharguments on)
  3637. // |---------------> %2F (slasharguments off)
  3638. //
  3639. // - $@FORCEDOWNLOAD@$ --|-------> ?forcedownload=1 (slasharguments on)
  3640. // |-------> &amp;forcedownload=1(slasharguments off)
  3641. //Note: Inter-activities linking is being implemented as a final
  3642. //step in the restore execution, because we need to have it
  3643. //finished to know all the oldid, newid equivaleces
  3644. function restore_decode_absolute_links($content) {
  3645. global $CFG,$restore;
  3646. require_once($CFG->libdir.'/filelib.php');
  3647. /// MDL-14072: Prevent NULLs, empties and numbers to be processed by the
  3648. /// heavy interlinking. Just a few cpu cycles saved.
  3649. if ($content === NULL) {
  3650. return NULL;
  3651. } else if ($content === '') {
  3652. return '';
  3653. } else if (is_numeric($content)) {
  3654. return $content;
  3655. }
  3656. //Now decode wwwroot and file.php calls
  3657. $search = array ("$@FILEPHP@$");
  3658. $replace = array(get_file_url($restore->course_id));
  3659. $result = str_replace($search,$replace,$content);
  3660. //Now $@SLASH@$ and $@FORCEDOWNLOAD@$ MDL-18799
  3661. $search = array('$@SLASH@$', '$@FORCEDOWNLOAD@$');
  3662. if ($CFG->slasharguments) {
  3663. $replace = array('/', '?forcedownload=1');
  3664. } else {
  3665. $replace = array('%2F', '&amp;forcedownload=1');
  3666. }
  3667. $result = str_replace($search, $replace, $result);
  3668. if ($result != $content && debugging()) { //Debug
  3669. if (!defined('RESTORE_SILENTLY')) {
  3670. echo '<br /><hr />'.s($content).'<br />changed to<br />'.s($result).'<hr /><br />'; //Debug
  3671. }
  3672. } //Debug
  3673. return $result;
  3674. }
  3675. //This function restores the userfiles from the temp (user_files) directory to the
  3676. //dataroot/users directory
  3677. function restore_user_files($restore) {
  3678. global $CFG;
  3679. $status = true;
  3680. $counter = 0;
  3681. // 'users' is the old users folder, 'user' is the new one, with a new hierarchy. Detect which one is here and treat accordingly
  3682. //in CFG->dataroot
  3683. $dest_dir = $CFG->dataroot."/user";
  3684. $status = check_dir_exists($dest_dir,true);
  3685. //Now, we iterate over "user_files" records to check if that user dir must be
  3686. //copied (and renamed) to the "users" dir.
  3687. $rootdir = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/user_files";
  3688. //Check if directory exists
  3689. $userlist = array();
  3690. if (is_dir($rootdir) && ($list = list_directories ($rootdir))) {
  3691. $counter = 0;
  3692. foreach ($list as $dir) {
  3693. // If there are directories in this folder, we are in the new user hierarchy
  3694. if ($newlist = list_directories("$rootdir/$dir")) {
  3695. foreach ($newlist as $olduserid) {
  3696. $userlist[$olduserid] = "$rootdir/$dir/$olduserid";
  3697. }
  3698. } else {
  3699. $userlist[$dir] = "$rootdir/$dir";
  3700. }
  3701. }
  3702. foreach ($userlist as $olduserid => $backup_location) {
  3703. //Look for dir like username in backup_ids
  3704. //If that user exists in backup_ids
  3705. if ($user = backup_getid($restore->backup_unique_code,"user",$olduserid)) {
  3706. //Only if user has been created now or if it existed previously, but he hasn't got an image (see bug 1123)
  3707. $newuserdir = make_user_directory($user->new_id, true); // Doesn't create the folder, just returns the location
  3708. // restore images if new user or image does not exist yet
  3709. if (!empty($user->new) or !check_dir_exists($newuserdir)) {
  3710. if (make_user_directory($user->new_id)) { // Creates the folder
  3711. $status = backup_copy_file($backup_location, $newuserdir, true);
  3712. $counter ++;
  3713. }
  3714. //Do some output
  3715. if ($counter % 2 == 0) {
  3716. if (!defined('RESTORE_SILENTLY')) {
  3717. echo ".";
  3718. if ($counter % 40 == 0) {
  3719. echo "<br />";
  3720. }
  3721. }
  3722. backup_flush(300);
  3723. }
  3724. }
  3725. }
  3726. }
  3727. }
  3728. //If status is ok and whe have dirs created, returns counter to inform
  3729. if ($status and $counter) {
  3730. return $counter;
  3731. } else {
  3732. return $status;
  3733. }
  3734. }
  3735. //This function restores the groupfiles from the temp (group_files) directory to the
  3736. //dataroot/groups directory
  3737. function restore_group_files($restore) {
  3738. global $CFG;
  3739. $status = true;
  3740. $counter = 0;
  3741. //First, we check to "groups" exists and create is as necessary
  3742. //in CFG->dataroot
  3743. $dest_dir = $CFG->dataroot.'/groups';
  3744. $status = check_dir_exists($dest_dir,true);
  3745. //Now, we iterate over "group_files" records to check if that user dir must be
  3746. //copied (and renamed) to the "groups" dir.
  3747. $rootdir = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/group_files";
  3748. //Check if directory exists
  3749. if (is_dir($rootdir)) {
  3750. $list = list_directories ($rootdir);
  3751. if ($list) {
  3752. //Iterate
  3753. $counter = 0;
  3754. foreach ($list as $dir) {
  3755. //Look for dir like groupid in backup_ids
  3756. $data = get_record ("backup_ids","backup_code",$restore->backup_unique_code,
  3757. "table_name","groups",
  3758. "old_id",$dir);
  3759. //If that group exists in backup_ids
  3760. if ($data) {
  3761. if (!file_exists($dest_dir."/".$data->new_id)) {
  3762. $status = backup_copy_file($rootdir."/".$dir, $dest_dir."/".$data->new_id,true);
  3763. $counter ++;
  3764. }
  3765. //Do some output
  3766. if ($counter % 2 == 0) {
  3767. if (!defined('RESTORE_SILENTLY')) {
  3768. echo ".";
  3769. if ($counter % 40 == 0) {
  3770. echo "<br />";
  3771. }
  3772. }
  3773. backup_flush(300);
  3774. }
  3775. }
  3776. }
  3777. }
  3778. }
  3779. //If status is ok and whe have dirs created, returns counter to inform
  3780. if ($status and $counter) {
  3781. return $counter;
  3782. } else {
  3783. return $status;
  3784. }
  3785. }
  3786. //This function restores the course files from the temp (course_files) directory to the
  3787. //dataroot/course_id directory
  3788. function restore_course_files($restore) {
  3789. global $CFG;
  3790. $status = true;
  3791. $counter = 0;
  3792. //First, we check to "course_id" exists and create is as necessary
  3793. //in CFG->dataroot
  3794. $dest_dir = $CFG->dataroot."/".$restore->course_id;
  3795. $status = check_dir_exists($dest_dir,true);
  3796. //Now, we iterate over "course_files" records to check if that file/dir must be
  3797. //copied to the "dest_dir" dir.
  3798. $rootdir = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/course_files";
  3799. //Check if directory exists
  3800. if (is_dir($rootdir)) {
  3801. $list = list_directories_and_files ($rootdir);
  3802. if ($list) {
  3803. //Iterate
  3804. $counter = 0;
  3805. foreach ($list as $dir) {
  3806. //Copy the dir to its new location
  3807. //Only if destination file/dir doesn exists
  3808. if (!file_exists($dest_dir."/".$dir)) {
  3809. $status = backup_copy_file($rootdir."/".$dir,
  3810. $dest_dir."/".$dir,true);
  3811. $counter ++;
  3812. }
  3813. //Do some output
  3814. if ($counter % 2 == 0) {
  3815. if (!defined('RESTORE_SILENTLY')) {
  3816. echo ".";
  3817. if ($counter % 40 == 0) {
  3818. echo "<br />";
  3819. }
  3820. }
  3821. backup_flush(300);
  3822. }
  3823. }
  3824. }
  3825. }
  3826. //If status is ok and whe have dirs created, returns counter to inform
  3827. if ($status and $counter) {
  3828. return $counter;
  3829. } else {
  3830. return $status;
  3831. }
  3832. }
  3833. //This function restores the site files from the temp (site_files) directory to the
  3834. //dataroot/SITEID directory
  3835. function restore_site_files($restore) {
  3836. global $CFG;
  3837. $status = true;
  3838. $counter = 0;
  3839. //First, we check to "course_id" exists and create is as necessary
  3840. //in CFG->dataroot
  3841. $dest_dir = $CFG->dataroot."/".SITEID;
  3842. $status = check_dir_exists($dest_dir,true);
  3843. //Now, we iterate over "site_files" files to check if that file/dir must be
  3844. //copied to the "dest_dir" dir.
  3845. $rootdir = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/site_files";
  3846. //Check if directory exists
  3847. if (is_dir($rootdir)) {
  3848. $list = list_directories_and_files ($rootdir);
  3849. if ($list) {
  3850. //Iterate
  3851. $counter = 0;
  3852. foreach ($list as $dir) {
  3853. //Avoid copying maintenance.html. MDL-18594
  3854. if ($dir == 'maintenance.html') {
  3855. continue;
  3856. }
  3857. //Copy the dir to its new location
  3858. //Only if destination file/dir doesn exists
  3859. if (!file_exists($dest_dir."/".$dir)) {
  3860. $status = backup_copy_file($rootdir."/".$dir,
  3861. $dest_dir."/".$dir,true);
  3862. $counter ++;
  3863. }
  3864. //Do some output
  3865. if ($counter % 2 == 0) {
  3866. if (!defined('RESTORE_SILENTLY')) {
  3867. echo ".";
  3868. if ($counter % 40 == 0) {
  3869. echo "<br />";
  3870. }
  3871. }
  3872. backup_flush(300);
  3873. }
  3874. }
  3875. }
  3876. }
  3877. //If status is ok and whe have dirs created, returns counter to inform
  3878. if ($status and $counter) {
  3879. return $counter;
  3880. } else {
  3881. return $status;
  3882. }
  3883. }
  3884. //This function creates all the structures for every module in backup file
  3885. //Depending what has been selected.
  3886. function restore_create_modules($restore,$xml_file) {
  3887. global $CFG;
  3888. $status = true;
  3889. //Check it exists
  3890. if (!file_exists($xml_file)) {
  3891. $status = false;
  3892. }
  3893. //Get info from xml
  3894. if ($status) {
  3895. //info will contain the id and modtype of every module
  3896. //in backup_ids->info will be the real info (serialized)
  3897. $info = restore_read_xml_modules($restore,$xml_file);
  3898. }
  3899. //Now, if we have anything in info, we have to restore that mods
  3900. //from backup_ids (calling every mod restore function)
  3901. if ($info) {
  3902. if ($info !== true) {
  3903. if (!defined('RESTORE_SILENTLY')) {
  3904. echo '<ul>';
  3905. }
  3906. //Iterate over each module
  3907. foreach ($info as $mod) {
  3908. if (empty($restore->mods[$mod->modtype]->granular) // We don't care about per instance, i.e. restore all instances.
  3909. || (array_key_exists($mod->id,$restore->mods[$mod->modtype]->instances)
  3910. && !empty($restore->mods[$mod->modtype]->instances[$mod->id]->restore))) {
  3911. $modrestore = $mod->modtype."_restore_mods";
  3912. if (function_exists($modrestore)) { //Debug
  3913. // we want to restore all mods even when one fails
  3914. // incorrect code here ignored any errors during module restore in 1.6-1.8
  3915. $status = $status && $modrestore($mod,$restore);
  3916. } else {
  3917. //Something was wrong. Function should exist.
  3918. $status = false;
  3919. }
  3920. }
  3921. }
  3922. if (!defined('RESTORE_SILENTLY')) {
  3923. echo '</ul>';
  3924. }
  3925. }
  3926. } else {
  3927. $status = false;
  3928. }
  3929. return $status;
  3930. }
  3931. //This function creates all the structures for every log in backup file
  3932. //Depending what has been selected.
  3933. function restore_create_logs($restore,$xml_file) {
  3934. global $CFG,$db;
  3935. //Number of records to get in every chunk
  3936. $recordset_size = 4;
  3937. //Counter, points to current record
  3938. $counter = 0;
  3939. //To count all the recods to restore
  3940. $count_logs = 0;
  3941. $status = true;
  3942. //Check it exists
  3943. if (!file_exists($xml_file)) {
  3944. $status = false;
  3945. }
  3946. //Get info from xml
  3947. if ($status) {
  3948. //count_logs will contain the number of logs entries to process
  3949. //in backup_ids->info will be the real info (serialized)
  3950. $count_logs = restore_read_xml_logs($restore,$xml_file);
  3951. }
  3952. //Now, if we have records in count_logs, we have to restore that logs
  3953. //from backup_ids. This piece of code makes calls to:
  3954. // - restore_log_course() if it's a course log
  3955. // - restore_log_user() if it's a user log
  3956. // - restore_log_module() if it's a module log.
  3957. //And all is segmented in chunks to allow large recordsets to be restored !!
  3958. if ($count_logs > 0) {
  3959. while ($counter < $count_logs) {
  3960. //Get a chunk of records
  3961. //Take old_id twice to avoid adodb limitation
  3962. $logs = get_records_select("backup_ids","table_name = 'log' AND backup_code = '$restore->backup_unique_code'","old_id","old_id",$counter,$recordset_size);
  3963. //We have logs
  3964. if ($logs) {
  3965. //Iterate
  3966. foreach ($logs as $log) {
  3967. //Get the full record from backup_ids
  3968. $data = backup_getid($restore->backup_unique_code,"log",$log->old_id);
  3969. if ($data) {
  3970. //Now get completed xmlized object
  3971. $info = $data->info;
  3972. //traverse_xmlize($info); //Debug
  3973. //print_object ($GLOBALS['traverse_array']); //Debug
  3974. //$GLOBALS['traverse_array']=""; //Debug
  3975. //Now build the LOG record structure
  3976. $dblog = new object();
  3977. $dblog->time = backup_todb($info['LOG']['#']['TIME']['0']['#']);
  3978. $dblog->userid = backup_todb($info['LOG']['#']['USERID']['0']['#']);
  3979. $dblog->ip = backup_todb($info['LOG']['#']['IP']['0']['#']);
  3980. $dblog->course = $restore->course_id;
  3981. $dblog->module = backup_todb($info['LOG']['#']['MODULE']['0']['#']);
  3982. $dblog->cmid = backup_todb($info['LOG']['#']['CMID']['0']['#']);
  3983. $dblog->action = backup_todb($info['LOG']['#']['ACTION']['0']['#']);
  3984. $dblog->url = backup_todb($info['LOG']['#']['URL']['0']['#']);
  3985. $dblog->info = backup_todb($info['LOG']['#']['INFO']['0']['#']);
  3986. //We have to recode the userid field
  3987. $user = backup_getid($restore->backup_unique_code,"user",$dblog->userid);
  3988. if ($user) {
  3989. //echo "User ".$dblog->userid." to user ".$user->new_id."<br />"; //Debug
  3990. $dblog->userid = $user->new_id;
  3991. }
  3992. //We have to recode the cmid field (if module isn't "course" or "user")
  3993. if ($dblog->module != "course" and $dblog->module != "user") {
  3994. $cm = backup_getid($restore->backup_unique_code,"course_modules",$dblog->cmid);
  3995. if ($cm) {
  3996. //echo "Module ".$dblog->cmid." to module ".$cm->new_id."<br />"; //Debug
  3997. $dblog->cmid = $cm->new_id;
  3998. } else {
  3999. $dblog->cmid = 0;
  4000. }
  4001. }
  4002. //print_object ($dblog); //Debug
  4003. //Now, we redirect to the needed function to make all the work
  4004. if ($dblog->module == "course") {
  4005. //It's a course log,
  4006. $stat = restore_log_course($restore,$dblog);
  4007. } elseif ($dblog->module == "user") {
  4008. //It's a user log,
  4009. $stat = restore_log_user($restore,$dblog);
  4010. } else {
  4011. //It's a module log,
  4012. $stat = restore_log_module($restore,$dblog);
  4013. }
  4014. }
  4015. //Do some output
  4016. $counter++;
  4017. if ($counter % 10 == 0) {
  4018. if (!defined('RESTORE_SILENTLY')) {
  4019. echo ".";
  4020. if ($counter % 200 == 0) {
  4021. echo "<br />";
  4022. }
  4023. }
  4024. backup_flush(300);
  4025. }
  4026. }
  4027. } else {
  4028. //We never should arrive here
  4029. $counter = $count_logs;
  4030. $status = false;
  4031. }
  4032. }
  4033. }
  4034. return $status;
  4035. }
  4036. //This function inserts a course log record, calculating the URL field as necessary
  4037. function restore_log_course($restore,$log) {
  4038. $status = true;
  4039. $toinsert = false;
  4040. //echo "<hr />Before transformations<br />"; //Debug
  4041. //print_object($log); //Debug
  4042. //Depending of the action, we recode different things
  4043. switch ($log->action) {
  4044. case "view":
  4045. $log->url = "view.php?id=".$log->course;
  4046. $log->info = $log->course;
  4047. $toinsert = true;
  4048. break;
  4049. case "guest":
  4050. $log->url = "view.php?id=".$log->course;
  4051. $toinsert = true;
  4052. break;
  4053. case "user report":
  4054. //recode the info field (it's the user id)
  4055. $user = backup_getid($restore->backup_unique_code,"user",$log->info);
  4056. if ($user) {
  4057. $log->info = $user->new_id;
  4058. //Now, extract the mode from the url field
  4059. $mode = substr(strrchr($log->url,"="),1);
  4060. $log->url = "user.php?id=".$log->course."&user=".$log->info."&mode=".$mode;
  4061. $toinsert = true;
  4062. }
  4063. break;
  4064. case "add mod":
  4065. //Extract the course_module from the url field
  4066. $cmid = substr(strrchr($log->url,"="),1);
  4067. //recode the course_module to see it it has been restored
  4068. $cm = backup_getid($restore->backup_unique_code,"course_modules",$cmid);
  4069. if ($cm) {
  4070. $cmid = $cm->new_id;
  4071. //Extract the module name and the module id from the info field
  4072. $modname = strtok($log->info," ");
  4073. $modid = strtok(" ");
  4074. //recode the module id to see if it has been restored
  4075. $mod = backup_getid($restore->backup_unique_code,$modname,$modid);
  4076. if ($mod) {
  4077. $modid = $mod->new_id;
  4078. //Now I have everything so reconstruct url and info
  4079. $log->info = $modname." ".$modid;
  4080. $log->url = "../mod/".$modname."/view.php?id=".$cmid;
  4081. $toinsert = true;
  4082. }
  4083. }
  4084. break;
  4085. case "update mod":
  4086. //Extract the course_module from the url field
  4087. $cmid = substr(strrchr($log->url,"="),1);
  4088. //recode the course_module to see it it has been restored
  4089. $cm = backup_getid($restore->backup_unique_code,"course_modules",$cmid);
  4090. if ($cm) {
  4091. $cmid = $cm->new_id;
  4092. //Extract the module name and the module id from the info field
  4093. $modname = strtok($log->info," ");
  4094. $modid = strtok(" ");
  4095. //recode the module id to see if it has been restored
  4096. $mod = backup_getid($restore->backup_unique_code,$modname,$modid);
  4097. if ($mod) {
  4098. $modid = $mod->new_id;
  4099. //Now I have everything so reconstruct url and info
  4100. $log->info = $modname." ".$modid;
  4101. $log->url = "../mod/".$modname."/view.php?id=".$cmid;
  4102. $toinsert = true;
  4103. }
  4104. }
  4105. break;
  4106. case "delete mod":
  4107. $log->url = "view.php?id=".$log->course;
  4108. $toinsert = true;
  4109. break;
  4110. case "update":
  4111. $log->url = "edit.php?id=".$log->course;
  4112. $log->info = "";
  4113. $toinsert = true;
  4114. break;
  4115. case "unenrol":
  4116. //recode the info field (it's the user id)
  4117. $user = backup_getid($restore->backup_unique_code,"user",$log->info);
  4118. if ($user) {
  4119. $log->info = $user->new_id;
  4120. $log->url = "view.php?id=".$log->course;
  4121. $toinsert = true;
  4122. }
  4123. break;
  4124. case "enrol":
  4125. //recode the info field (it's the user id)
  4126. $user = backup_getid($restore->backup_unique_code,"user",$log->info);
  4127. if ($user) {
  4128. $log->info = $user->new_id;
  4129. $log->url = "view.php?id=".$log->course;
  4130. $toinsert = true;
  4131. }
  4132. break;
  4133. case "editsection":
  4134. //Extract the course_section from the url field
  4135. $secid = substr(strrchr($log->url,"="),1);
  4136. //recode the course_section to see if it has been restored
  4137. $sec = backup_getid($restore->backup_unique_code,"course_sections",$secid);
  4138. if ($sec) {
  4139. $secid = $sec->new_id;
  4140. //Now I have everything so reconstruct url and info
  4141. $log->url = "editsection.php?id=".$secid;
  4142. $toinsert = true;
  4143. }
  4144. break;
  4145. case "new":
  4146. $log->url = "view.php?id=".$log->course;
  4147. $log->info = "";
  4148. $toinsert = true;
  4149. break;
  4150. case "recent":
  4151. $log->url = "recent.php?id=".$log->course;
  4152. $log->info = "";
  4153. $toinsert = true;
  4154. break;
  4155. case "report log":
  4156. $log->url = "report/log/index.php?id=".$log->course;
  4157. $log->info = $log->course;
  4158. $toinsert = true;
  4159. break;
  4160. case "report live":
  4161. $log->url = "report/log/live.php?id=".$log->course;
  4162. $log->info = $log->course;
  4163. $toinsert = true;
  4164. break;
  4165. case "report outline":
  4166. $log->url = "report/outline/index.php?id=".$log->course;
  4167. $log->info = $log->course;
  4168. $toinsert = true;
  4169. break;
  4170. case "report participation":
  4171. $log->url = "report/participation/index.php?id=".$log->course;
  4172. $log->info = $log->course;
  4173. $toinsert = true;
  4174. break;
  4175. case "report stats":
  4176. $log->url = "report/stats/index.php?id=".$log->course;
  4177. $log->info = $log->course;
  4178. $toinsert = true;
  4179. break;
  4180. default:
  4181. echo "action (".$log->module."-".$log->action.") unknown. Not restored<br />"; //Debug
  4182. break;
  4183. }
  4184. //echo "After transformations<br />"; //Debug
  4185. //print_object($log); //Debug
  4186. //Now if $toinsert is set, insert the record
  4187. if ($toinsert) {
  4188. //echo "Inserting record<br />"; //Debug
  4189. $status = insert_record("log",$log);
  4190. }
  4191. return $status;
  4192. }
  4193. //This function inserts a user log record, calculating the URL field as necessary
  4194. function restore_log_user($restore,$log) {
  4195. $status = true;
  4196. $toinsert = false;
  4197. //echo "<hr />Before transformations<br />"; //Debug
  4198. //print_object($log); //Debug
  4199. //Depending of the action, we recode different things
  4200. switch ($log->action) {
  4201. case "view":
  4202. //recode the info field (it's the user id)
  4203. $user = backup_getid($restore->backup_unique_code,"user",$log->info);
  4204. if ($user) {
  4205. $log->info = $user->new_id;
  4206. $log->url = "view.php?id=".$log->info."&course=".$log->course;
  4207. $toinsert = true;
  4208. }
  4209. break;
  4210. case "change password":
  4211. //recode the info field (it's the user id)
  4212. $user = backup_getid($restore->backup_unique_code,"user",$log->info);
  4213. if ($user) {
  4214. $log->info = $user->new_id;
  4215. $log->url = "view.php?id=".$log->info."&course=".$log->course;
  4216. $toinsert = true;
  4217. }
  4218. break;
  4219. case "login":
  4220. //recode the info field (it's the user id)
  4221. $user = backup_getid($restore->backup_unique_code,"user",$log->info);
  4222. if ($user) {
  4223. $log->info = $user->new_id;
  4224. $log->url = "view.php?id=".$log->info."&course=".$log->course;
  4225. $toinsert = true;
  4226. }
  4227. break;
  4228. case "logout":
  4229. //recode the info field (it's the user id)
  4230. $user = backup_getid($restore->backup_unique_code,"user",$log->info);
  4231. if ($user) {
  4232. $log->info = $user->new_id;
  4233. $log->url = "view.php?id=".$log->info."&course=".$log->course;
  4234. $toinsert = true;
  4235. }
  4236. break;
  4237. case "view all":
  4238. $log->url = "view.php?id=".$log->course;
  4239. $log->info = "";
  4240. $toinsert = true;
  4241. case "update":
  4242. //We split the url by ampersand char
  4243. $first_part = strtok($log->url,"&");
  4244. //Get data after the = char. It's the user being updated
  4245. $userid = substr(strrchr($first_part,"="),1);
  4246. //Recode the user
  4247. $user = backup_getid($restore->backup_unique_code,"user",$userid);
  4248. if ($user) {
  4249. $log->info = "";
  4250. $log->url = "view.php?id=".$user->new_id."&course=".$log->course;
  4251. $toinsert = true;
  4252. }
  4253. break;
  4254. default:
  4255. echo "action (".$log->module."-".$log->action.") unknown. Not restored<br />"; //Debug
  4256. break;
  4257. }
  4258. //echo "After transformations<br />"; //Debug
  4259. //print_object($log); //Debug
  4260. //Now if $toinsert is set, insert the record
  4261. if ($toinsert) {
  4262. //echo "Inserting record<br />"; //Debug
  4263. $status = insert_record("log",$log);
  4264. }
  4265. return $status;
  4266. }
  4267. //This function inserts a module log record, calculating the URL field as necessary
  4268. function restore_log_module($restore,$log) {
  4269. $status = true;
  4270. $toinsert = false;
  4271. //echo "<hr />Before transformations<br />"; //Debug
  4272. //print_object($log); //Debug
  4273. //Now we see if the required function in the module exists
  4274. $function = $log->module."_restore_logs";
  4275. if (function_exists($function)) {
  4276. //Call the function
  4277. $log = $function($restore,$log);
  4278. //If everything is ok, mark the insert flag
  4279. if ($log) {
  4280. $toinsert = true;
  4281. }
  4282. }
  4283. //echo "After transformations<br />"; //Debug
  4284. //print_object($log); //Debug
  4285. //Now if $toinsert is set, insert the record
  4286. if ($toinsert) {
  4287. //echo "Inserting record<br />"; //Debug
  4288. $status = insert_record("log",$log);
  4289. }
  4290. return $status;
  4291. }
  4292. //This function adjusts the instance field into course_modules. It's executed after
  4293. //modules restore. There, we KNOW the new instance id !!
  4294. function restore_check_instances($restore) {
  4295. global $CFG;
  4296. $status = true;
  4297. //We are going to iterate over each course_module saved in backup_ids
  4298. $course_modules = get_records_sql("SELECT old_id,new_id
  4299. FROM {$CFG->prefix}backup_ids
  4300. WHERE backup_code = '$restore->backup_unique_code' AND
  4301. table_name = 'course_modules'");
  4302. if ($course_modules) {
  4303. foreach($course_modules as $cm) {
  4304. //Get full record, using backup_getids
  4305. $cm_module = backup_getid($restore->backup_unique_code,"course_modules",$cm->old_id);
  4306. //Now we are going to the REAL course_modules to get its type (field module)
  4307. $module = get_record("course_modules","id",$cm_module->new_id);
  4308. if ($module) {
  4309. //We know the module type id. Get the name from modules
  4310. $type = get_record("modules","id",$module->module);
  4311. if ($type) {
  4312. //We know the type name and the old_id. Get its new_id
  4313. //from backup_ids. It's the instance !!!
  4314. $instance = backup_getid($restore->backup_unique_code,$type->name,$cm_module->info);
  4315. if ($instance) {
  4316. //We have the new instance, so update the record in course_modules
  4317. $module->instance = $instance->new_id;
  4318. //print_object ($module); //Debug
  4319. $status = update_record("course_modules",$module);
  4320. } else {
  4321. $status = false;
  4322. }
  4323. } else {
  4324. $status = false;
  4325. }
  4326. } else {
  4327. $status = false;
  4328. }
  4329. // MDL-14326 remove empty course modules instance's (credit goes to John T. Macklin from Remote Learner)
  4330. $course_modules_inst_zero = get_records_sql("SELECT id, course, instance
  4331. FROM {$CFG->prefix}course_modules
  4332. WHERE id = '$cm_module->new_id' AND
  4333. instance = '0'");
  4334. if($course_modules_inst_zero){ // Clean up the invalid instances
  4335. foreach($course_modules_inst_zero as $course_modules_inst){
  4336. delete_records('course_modules', 'id',$course_modules_inst->id);
  4337. }
  4338. }
  4339. }
  4340. /// Finally, calculate modinfo cache.
  4341. rebuild_course_cache($restore->course_id);
  4342. }
  4343. return $status;
  4344. }
  4345. //=====================================================================================
  4346. //== ==
  4347. //== XML Functions (SAX) ==
  4348. //== ==
  4349. //=====================================================================================
  4350. /// This is the class used to split, in first instance, the monolithic moodle.xml into
  4351. /// smaller xml files allowing the MoodleParser later to process only the required info
  4352. /// based in each TODO, instead of processing the whole xml for each TODO. In theory
  4353. /// processing time can be reduced upto 1/20th of original time (depending of the
  4354. /// number of TODOs in the original moodle.xml file)
  4355. ///
  4356. /// Anyway, note it's a general splitter parser, and only needs to be instantiated
  4357. /// with the proper destination dir and the tosplit configuration. Be careful when
  4358. /// using it because it doesn't support XML attributes nor real cdata out from tags.
  4359. /// (both not used in the target Moodle backup files)
  4360. class moodle_splitter_parser {
  4361. var $level = 0; /// Level we are
  4362. var $tree = array(); /// Array of levels we are
  4363. var $cdata = ''; /// Raw storage for character data
  4364. var $content = ''; /// Content buffer to be printed to file
  4365. var $trailing= ''; /// Content of the trailing tree for each splited file
  4366. var $savepath = null; /// Path to store splited files
  4367. var $fhandler = null; /// Current file we are writing to
  4368. var $tosplit = array(); /// Array defining the files we want to split, in this format:
  4369. /// array( level/tag/level/tag => filename)
  4370. var $splitwords = array(); /// Denormalised array containing the potential tags
  4371. /// being a split point. To speed up check_split_point()
  4372. var $maxsplitlevel = 0; /// Precalculated max level where any split happens. To speed up check_split_point()
  4373. var $buffersize = 65536; /// 64KB is a good write buffer. Don't expect big benefits by increasing this.
  4374. var $repectformat = false; /// With this setting enabled, the splited files will look like the original one
  4375. /// with all the indentations 100% copied from original (character data outer tags).
  4376. /// But this is a waste of time from our perspective, and splited xml files are completely
  4377. /// functional without that, so we disable this for production, generating a more compact
  4378. /// XML quicker
  4379. /// PHP4 constructor
  4380. function moodle_splitter_parser($savepath, $tosplit = null) {
  4381. return $this->__construct($savepath, $tosplit);
  4382. }
  4383. /// PHP5 constructor
  4384. function __construct($savepath, $tosplit = null) {
  4385. $this->savepath = $savepath;
  4386. if (!empty($tosplit)) {
  4387. $this->tosplit = $tosplit;
  4388. } else { /// No tosplit list passed, process all the possible parts in one moodle.xml file
  4389. $this->tosplit = array(
  4390. '1/MOODLE_BACKUP/2/INFO' => 'split_info.xml',
  4391. '1/MOODLE_BACKUP/2/ROLES' => 'split_roles.xml',
  4392. '2/COURSE/3/HEADER' => 'split_course_header.xml',
  4393. '2/COURSE/3/BLOCKS' => 'split_blocks.xml',
  4394. '2/COURSE/3/SECTIONS' => 'split_sections.xml',
  4395. '2/COURSE/3/FORMATDATA' => 'split_formatdata.xml',
  4396. '2/COURSE/3/METACOURSE' => 'split_metacourse.xml',
  4397. '2/COURSE/3/GRADEBOOK' => 'split_gradebook.xml',
  4398. '2/COURSE/3/USERS' => 'split_users.xml',
  4399. '2/COURSE/3/MESSAGES' => 'split_messages.xml',
  4400. '2/COURSE/3/BLOGS' => 'split_blogs.xml',
  4401. '2/COURSE/3/QUESTION_CATEGORIES'=> 'split_questions.xml',
  4402. '2/COURSE/3/SCALES' => 'split_scales.xml',
  4403. '2/COURSE/3/GROUPS' => 'split_groups.xml',
  4404. '2/COURSE/3/GROUPINGS' => 'split_groupings.xml',
  4405. '2/COURSE/3/GROUPINGSGROUPS' => 'split_groupingsgroups.xml',
  4406. '2/COURSE/3/EVENTS' => 'split_events.xml',
  4407. '2/COURSE/3/MODULES' => 'split_modules.xml',
  4408. '2/COURSE/3/LOGS' => 'split_logs.xml'
  4409. );
  4410. }
  4411. /// Precalculate some info used to speedup checks
  4412. foreach ($this->tosplit as $key=>$value) {
  4413. $this->splitwords[basename($key)] = true;
  4414. if (((int) basename(dirname($key))) > $this->maxsplitlevel) {
  4415. $this->maxsplitlevel = (int) basename(dirname($key));
  4416. }
  4417. }
  4418. }
  4419. /// Given one tag being opened, check if it's one split point.
  4420. /// Return false or split filename
  4421. function check_split_point($tag) {
  4422. /// Quick check. Level < 2 cannot be a split point
  4423. if ($this->level < 2) {
  4424. return false;
  4425. }
  4426. /// Quick check. Current tag against potential splitwords
  4427. if (!isset($this->splitwords[$tag])) {
  4428. return false;
  4429. }
  4430. /// Prev test passed, take a look to 2-level tosplit
  4431. $keytocheck = ($this->level - 1) . '/' . $this->tree[$this->level - 1] . '/' . $this->level . '/' . $this->tree[$this->level];
  4432. if (!isset($this->tosplit[$keytocheck])) {
  4433. return false;
  4434. }
  4435. /// Prev test passed, we are in a split point, return new filename
  4436. return $this->tosplit[$keytocheck];
  4437. }
  4438. /// To append data (xml-escaped) to contents buffer
  4439. function character_data($parser, $data) {
  4440. ///$this->content .= preg_replace($this->entity_find, $this->entity_replace, $data); ///40% slower
  4441. ///$this->content .= str_replace($this->entity_find, $this->entity_replace, $data); ///25% slower
  4442. ///$this->content .= htmlspecialchars($data); ///the best
  4443. /// Instead of htmlspecialchars() each chunk of character data, we are going to
  4444. /// concat it without transformation and will apply the htmlspecialchars() when
  4445. /// that character data is, efectively, going to be added to contents buffer. This
  4446. /// makes the number of transformations to be reduced (speedup) and avoid potential
  4447. /// problems with transformations being applied "in the middle" of multibyte chars.
  4448. $this->cdata .= $data;
  4449. }
  4450. /// To detect start of tags, keeping level, tree and fhandle updated.
  4451. /// Also handles creation of split files
  4452. function start_tag($parser, $tag, $attrs) {
  4453. /// Update things before processing
  4454. $this->level++;
  4455. $this->tree[$this->level] = $tag;
  4456. /// Check if we need to start a new split file,
  4457. /// Speedup: we only do that if we haven't a fhandler and if level <= $maxsplitlevel
  4458. if ($this->level <= $this->maxsplitlevel && !$this->fhandler && $newfilename = $this->check_split_point($tag)) {
  4459. /// Open new file handler, init everything
  4460. $this->fhandler = fopen($this->savepath . '/' . $newfilename, 'w');
  4461. $this->content = '';
  4462. $this->cdata = '';
  4463. $this->trailing = '';
  4464. /// Build the original leading tree (and calculate the original trailing one)
  4465. for ($l = 1; $l < $this->level; $l++) {
  4466. $this->content .= "<{$this->tree[$l]}>\n";
  4467. $this->trailing = "\n</{$this->tree[$l]}>" . $this->trailing;
  4468. }
  4469. }
  4470. /// Perform xml-entities transformation and add to contents buffer together with opening tag.
  4471. /// Speedup. We lose nice formatting of the split XML but avoid 50% of transformations and XML is 100% equivalent
  4472. $this->content .= ($this->repectformat ? htmlspecialchars($this->cdata) : '') . "<$tag>";
  4473. $this->cdata = '';
  4474. }
  4475. /// To detect end of tags, keeping level, tree and fhandle updated, writting contents buffer to split file.
  4476. /// Also handles closing of split files
  4477. function end_tag($parser, $tag) {
  4478. /// Perform xml-entities transformation and add to contents buffer together with closing tag, repecting (or no) format
  4479. $this->content .= ($this->repectformat ? htmlspecialchars($this->cdata) : htmlspecialchars(trim($this->cdata))) . "</$tag>";
  4480. $this->cdata = '';
  4481. /// Check if we need to close current split file
  4482. /// Speedup: we only do that if we have a fhandler and if level <= $maxsplitlevel
  4483. if ($this->level <= $this->maxsplitlevel && $this->fhandler && $newfilename = $this->check_split_point($tag)) {
  4484. /// Write pending contents buffer before closing. It's a must
  4485. fwrite($this->fhandler, $this->content);
  4486. $this->content = "";
  4487. /// Write the original trailing tree for fhandler
  4488. fwrite($this->fhandler, $this->trailing);
  4489. fclose($this->fhandler);
  4490. $this->fhandler = null;
  4491. } else {
  4492. /// Normal write of contents (use one buffer to improve speed)
  4493. if ($this->fhandler && strlen($this->content) > $this->buffersize) {
  4494. fwrite($this->fhandler, $this->content);
  4495. $this->content = "";
  4496. }
  4497. }
  4498. /// Update things after processing
  4499. $this->tree[$this->level] = "";
  4500. $this->level--;
  4501. }
  4502. }
  4503. /// This function executes the moodle_splitter_parser, causing the monolithic moodle.xml
  4504. /// file to be splitted in n smaller files for better treatament by the MoodleParser in restore_read_xml()
  4505. function restore_split_xml ($xml_file, $preferences) {
  4506. $status = true;
  4507. $xml_parser = xml_parser_create('UTF-8');
  4508. $split_parser = new moodle_splitter_parser(dirname($xml_file));
  4509. xml_set_object($xml_parser,$split_parser);
  4510. xml_set_element_handler($xml_parser, 'start_tag', 'end_tag');
  4511. xml_set_character_data_handler($xml_parser, 'character_data');
  4512. $doteach = filesize($xml_file) / 20;
  4513. $fromdot = 0;
  4514. $fp = fopen($xml_file,"r")
  4515. or $status = false;
  4516. if ($status) {
  4517. $lasttime = time();
  4518. while ($data = fread($fp, 8192)) {
  4519. if (!defined('RESTORE_SILENTLY')) {
  4520. $fromdot += 8192;
  4521. if ($fromdot > $doteach) {
  4522. echo ".";
  4523. backup_flush(300);
  4524. $fromdot = 0;
  4525. }
  4526. if ((time() - $lasttime) > 10) {
  4527. $lasttime = time();
  4528. backup_flush(300);
  4529. }
  4530. }
  4531. xml_parse($xml_parser, $data, feof($fp))
  4532. or die(sprintf("XML error: %s at line %d",
  4533. xml_error_string(xml_get_error_code($xml_parser)),
  4534. xml_get_current_line_number($xml_parser)));
  4535. }
  4536. fclose($fp);
  4537. }
  4538. xml_parser_free($xml_parser);
  4539. return $status;
  4540. }
  4541. //This is the class used to do all the xml parse
  4542. class MoodleParser {
  4543. var $level = 0; //Level we are
  4544. var $counter = 0; //Counter
  4545. var $tree = array(); //Array of levels we are
  4546. var $content = ""; //Content under current level
  4547. var $todo = ""; //What we hav to do when parsing
  4548. var $info = ""; //Information collected. Temp storage. Used to return data after parsing.
  4549. var $temp = ""; //Temp storage.
  4550. var $preferences = ""; //Preferences about what to load !!
  4551. var $finished = false; //Flag to say xml_parse to stop
  4552. //This function is used to get the current contents property value
  4553. //They are trimed (and converted from utf8 if needed)
  4554. function getContents() {
  4555. return trim($this->content);
  4556. }
  4557. //This is the startTag handler we use where we are reading the info zone (todo="INFO")
  4558. function startElementInfo($parser, $tagName, $attrs) {
  4559. //Refresh properties
  4560. $this->level++;
  4561. $this->tree[$this->level] = $tagName;
  4562. //Output something to avoid browser timeouts...
  4563. //backup_flush();
  4564. //Check if we are into INFO zone
  4565. //if ($this->tree[2] == "INFO") //Debug
  4566. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4567. }
  4568. //This is the startTag handler we use where we are reading the info zone (todo="INFO")
  4569. function startElementRoles($parser, $tagName, $attrs) {
  4570. //Refresh properties
  4571. $this->level++;
  4572. $this->tree[$this->level] = $tagName;
  4573. //Output something to avoid browser timeouts...
  4574. //backup_flush();
  4575. //Check if we are into INFO zone
  4576. //if ($this->tree[2] == "INFO") //Debug
  4577. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4578. }
  4579. //This is the startTag handler we use where we are reading the course header zone (todo="COURSE_HEADER")
  4580. function startElementCourseHeader($parser, $tagName, $attrs) {
  4581. //Refresh properties
  4582. $this->level++;
  4583. $this->tree[$this->level] = $tagName;
  4584. //Output something to avoid browser timeouts...
  4585. //backup_flush();
  4586. //Check if we are into COURSE_HEADER zone
  4587. //if ($this->tree[3] == "HEADER") //Debug
  4588. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4589. }
  4590. //This is the startTag handler we use where we are reading the blocks zone (todo="BLOCKS")
  4591. function startElementBlocks($parser, $tagName, $attrs) {
  4592. //Refresh properties
  4593. $this->level++;
  4594. $this->tree[$this->level] = $tagName;
  4595. //Output something to avoid browser timeouts...
  4596. //backup_flush();
  4597. //Check if we are into BLOCKS zone
  4598. //if ($this->tree[3] == "BLOCKS") //Debug
  4599. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4600. //If we are under a BLOCK tag under a BLOCKS zone, accumule it
  4601. if (isset($this->tree[4]) and isset($this->tree[3])) { //
  4602. if ($this->tree[4] == "BLOCK" and $this->tree[3] == "BLOCKS") {
  4603. if (!isset($this->temp)) {
  4604. $this->temp = "";
  4605. }
  4606. $this->temp .= "<".$tagName.">";
  4607. }
  4608. }
  4609. }
  4610. //This is the startTag handler we use where we are reading the sections zone (todo="SECTIONS")
  4611. function startElementSections($parser, $tagName, $attrs) {
  4612. //Refresh properties
  4613. $this->level++;
  4614. $this->tree[$this->level] = $tagName;
  4615. //Output something to avoid browser timeouts...
  4616. //backup_flush();
  4617. //Check if we are into SECTIONS zone
  4618. //if ($this->tree[3] == "SECTIONS") //Debug
  4619. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4620. }
  4621. //This is the startTag handler we use where we are reading the optional format data zone (todo="FORMATDATA")
  4622. function startElementFormatData($parser, $tagName, $attrs) {
  4623. //Refresh properties
  4624. $this->level++;
  4625. $this->tree[$this->level] = $tagName;
  4626. //Output something to avoid browser timeouts...
  4627. //backup_flush();
  4628. //Accumulate all the data inside this tag
  4629. if (isset($this->tree[3]) && $this->tree[3] == "FORMATDATA") {
  4630. if (!isset($this->temp)) {
  4631. $this->temp = '';
  4632. }
  4633. $this->temp .= "<".$tagName.">";
  4634. }
  4635. //Check if we are into FORMATDATA zone
  4636. //if ($this->tree[3] == "FORMATDATA") //Debug
  4637. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4638. }
  4639. //This is the startTag handler we use where we are reading the metacourse zone (todo="METACOURSE")
  4640. function startElementMetacourse($parser, $tagName, $attrs) {
  4641. //Refresh properties
  4642. $this->level++;
  4643. $this->tree[$this->level] = $tagName;
  4644. //Output something to avoid browser timeouts...
  4645. //backup_flush();
  4646. //Check if we are into METACOURSE zone
  4647. //if ($this->tree[3] == "METACOURSE") //Debug
  4648. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4649. }
  4650. //This is the startTag handler we use where we are reading the gradebook zone (todo="GRADEBOOK")
  4651. function startElementGradebook($parser, $tagName, $attrs) {
  4652. //Refresh properties
  4653. $this->level++;
  4654. $this->tree[$this->level] = $tagName;
  4655. //Output something to avoid browser timeouts...
  4656. //backup_flush();
  4657. //Check if we are into GRADEBOOK zone
  4658. //if ($this->tree[3] == "GRADEBOOK") //Debug
  4659. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4660. //If we are under a GRADE_PREFERENCE, GRADE_LETTER or GRADE_CATEGORY tag under a GRADEBOOK zone, accumule it
  4661. if (isset($this->tree[5]) and isset($this->tree[3])) {
  4662. 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")) {
  4663. if (!isset($this->temp)) {
  4664. $this->temp = "";
  4665. }
  4666. $this->temp .= "<".$tagName.">";
  4667. }
  4668. }
  4669. }
  4670. //This is the startTag handler we use where we are reading the gradebook zone (todo="GRADEBOOK")
  4671. function startElementOldGradebook($parser, $tagName, $attrs) {
  4672. //Refresh properties
  4673. $this->level++;
  4674. $this->tree[$this->level] = $tagName;
  4675. //Output something to avoid browser timeouts...
  4676. //backup_flush();
  4677. //Check if we are into GRADEBOOK zone
  4678. //if ($this->tree[3] == "GRADEBOOK") //Debug
  4679. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4680. //If we are under a GRADE_PREFERENCE, GRADE_LETTER or GRADE_CATEGORY tag under a GRADEBOOK zone, accumule it
  4681. if (isset($this->tree[5]) and isset($this->tree[3])) {
  4682. if (($this->tree[5] == "GRADE_PREFERENCE" || $this->tree[5] == "GRADE_LETTER" || $this->tree[5] == "GRADE_CATEGORY" ) && ($this->tree[3] == "GRADEBOOK")) {
  4683. if (!isset($this->temp)) {
  4684. $this->temp = "";
  4685. }
  4686. $this->temp .= "<".$tagName.">";
  4687. }
  4688. }
  4689. }
  4690. //This is the startTag handler we use where we are reading the user zone (todo="USERS")
  4691. function startElementUsers($parser, $tagName, $attrs) {
  4692. //Refresh properties
  4693. $this->level++;
  4694. $this->tree[$this->level] = $tagName;
  4695. //Check if we are into USERS zone
  4696. //if ($this->tree[3] == "USERS") //Debug
  4697. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4698. }
  4699. //This is the startTag handler we use where we are reading the messages zone (todo="MESSAGES")
  4700. function startElementMessages($parser, $tagName, $attrs) {
  4701. //Refresh properties
  4702. $this->level++;
  4703. $this->tree[$this->level] = $tagName;
  4704. //Output something to avoid browser timeouts...
  4705. //backup_flush();
  4706. //Check if we are into MESSAGES zone
  4707. //if ($this->tree[3] == "MESSAGES") //Debug
  4708. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4709. //If we are under a MESSAGE tag under a MESSAGES zone, accumule it
  4710. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4711. if (($this->tree[4] == "MESSAGE" || (isset($this->tree[5]) && $this->tree[5] == "CONTACT" )) and ($this->tree[3] == "MESSAGES")) {
  4712. if (!isset($this->temp)) {
  4713. $this->temp = "";
  4714. }
  4715. $this->temp .= "<".$tagName.">";
  4716. }
  4717. }
  4718. }
  4719. //This is the startTag handler we use where we are reading the blogs zone (todo="BLOGS")
  4720. function startElementBlogs($parser, $tagName, $attrs) {
  4721. //Refresh properties
  4722. $this->level++;
  4723. $this->tree[$this->level] = $tagName;
  4724. //Output something to avoid browser timeouts...
  4725. //backup_flush();
  4726. //Check if we are into BLOGS zone
  4727. //if ($this->tree[3] == "BLOGS") //Debug
  4728. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4729. //If we are under a BLOG tag under a BLOGS zone, accumule it
  4730. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4731. if ($this->tree[4] == "BLOG" and $this->tree[3] == "BLOGS") {
  4732. if (!isset($this->temp)) {
  4733. $this->temp = "";
  4734. }
  4735. $this->temp .= "<".$tagName.">";
  4736. }
  4737. }
  4738. }
  4739. //This is the startTag handler we use where we are reading the questions zone (todo="QUESTIONS")
  4740. function startElementQuestions($parser, $tagName, $attrs) {
  4741. //Refresh properties
  4742. $this->level++;
  4743. $this->tree[$this->level] = $tagName;
  4744. //if ($tagName == "QUESTION_CATEGORY" && $this->tree[3] == "QUESTION_CATEGORIES") { //Debug
  4745. // echo "<P>QUESTION_CATEGORY: ".strftime ("%X",time()),"-"; //Debug
  4746. //} //Debug
  4747. //Output something to avoid browser timeouts...
  4748. //backup_flush();
  4749. //Check if we are into QUESTION_CATEGORIES zone
  4750. //if ($this->tree[3] == "QUESTION_CATEGORIES") //Debug
  4751. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4752. //If we are under a QUESTION_CATEGORY tag under a QUESTION_CATEGORIES zone, accumule it
  4753. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4754. if (($this->tree[4] == "QUESTION_CATEGORY") and ($this->tree[3] == "QUESTION_CATEGORIES")) {
  4755. if (!isset($this->temp)) {
  4756. $this->temp = "";
  4757. }
  4758. $this->temp .= "<".$tagName.">";
  4759. }
  4760. }
  4761. }
  4762. //This is the startTag handler we use where we are reading the scales zone (todo="SCALES")
  4763. function startElementScales($parser, $tagName, $attrs) {
  4764. //Refresh properties
  4765. $this->level++;
  4766. $this->tree[$this->level] = $tagName;
  4767. //if ($tagName == "SCALE" && $this->tree[3] == "SCALES") { //Debug
  4768. // echo "<P>SCALE: ".strftime ("%X",time()),"-"; //Debug
  4769. //} //Debug
  4770. //Output something to avoid browser timeouts...
  4771. //backup_flush();
  4772. //Check if we are into SCALES zone
  4773. //if ($this->tree[3] == "SCALES") //Debug
  4774. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4775. //If we are under a SCALE tag under a SCALES zone, accumule it
  4776. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4777. if (($this->tree[4] == "SCALE") and ($this->tree[3] == "SCALES")) {
  4778. if (!isset($this->temp)) {
  4779. $this->temp = "";
  4780. }
  4781. $this->temp .= "<".$tagName.">";
  4782. }
  4783. }
  4784. }
  4785. function startElementGroups($parser, $tagName, $attrs) {
  4786. //Refresh properties
  4787. $this->level++;
  4788. $this->tree[$this->level] = $tagName;
  4789. //if ($tagName == "GROUP" && $this->tree[3] == "GROUPS") { //Debug
  4790. // echo "<P>GROUP: ".strftime ("%X",time()),"-"; //Debug
  4791. //} //Debug
  4792. //Output something to avoid browser timeouts...
  4793. //backup_flush();
  4794. //Check if we are into GROUPS zone
  4795. //if ($this->tree[3] == "GROUPS") //Debug
  4796. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4797. //If we are under a GROUP tag under a GROUPS zone, accumule it
  4798. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4799. if (($this->tree[4] == "GROUP") and ($this->tree[3] == "GROUPS")) {
  4800. if (!isset($this->temp)) {
  4801. $this->temp = "";
  4802. }
  4803. $this->temp .= "<".$tagName.">";
  4804. }
  4805. }
  4806. }
  4807. function startElementGroupings($parser, $tagName, $attrs) {
  4808. //Refresh properties
  4809. $this->level++;
  4810. $this->tree[$this->level] = $tagName;
  4811. //if ($tagName == "GROUPING" && $this->tree[3] == "GROUPINGS") { //Debug
  4812. // echo "<P>GROUPING: ".strftime ("%X",time()),"-"; //Debug
  4813. //} //Debug
  4814. //Output something to avoid browser timeouts...
  4815. //backup_flush();
  4816. //Check if we are into GROUPINGS zone
  4817. //if ($this->tree[3] == "GROUPINGS") //Debug
  4818. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4819. //If we are under a GROUPING tag under a GROUPINGS zone, accumule it
  4820. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4821. if (($this->tree[4] == "GROUPING") and ($this->tree[3] == "GROUPINGS")) {
  4822. if (!isset($this->temp)) {
  4823. $this->temp = "";
  4824. }
  4825. $this->temp .= "<".$tagName.">";
  4826. }
  4827. }
  4828. }
  4829. function startElementGroupingsGroups($parser, $tagName, $attrs) {
  4830. //Refresh properties
  4831. $this->level++;
  4832. $this->tree[$this->level] = $tagName;
  4833. //if ($tagName == "GROUPINGGROUP" && $this->tree[3] == "GROUPINGSGROUPS") { //Debug
  4834. // echo "<P>GROUPINGSGROUP: ".strftime ("%X",time()),"-"; //Debug
  4835. //} //Debug
  4836. //Output something to avoid browser timeouts...
  4837. backup_flush();
  4838. //Check if we are into GROUPINGSGROUPS zone
  4839. //if ($this->tree[3] == "GROUPINGSGROUPS") //Debug
  4840. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4841. //If we are under a GROUPINGGROUP tag under a GROUPINGSGROUPS zone, accumule it
  4842. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4843. if (($this->tree[4] == "GROUPINGGROUP") and ($this->tree[3] == "GROUPINGSGROUPS")) {
  4844. if (!isset($this->temp)) {
  4845. $this->temp = "";
  4846. }
  4847. $this->temp .= "<".$tagName.">";
  4848. }
  4849. }
  4850. }
  4851. //This is the startTag handler we use where we are reading the events zone (todo="EVENTS")
  4852. function startElementEvents($parser, $tagName, $attrs) {
  4853. //Refresh properties
  4854. $this->level++;
  4855. $this->tree[$this->level] = $tagName;
  4856. //if ($tagName == "EVENT" && $this->tree[3] == "EVENTS") { //Debug
  4857. // echo "<P>EVENT: ".strftime ("%X",time()),"-"; //Debug
  4858. //} //Debug
  4859. //Output something to avoid browser timeouts...
  4860. //backup_flush();
  4861. //Check if we are into EVENTS zone
  4862. //if ($this->tree[3] == "EVENTS") //Debug
  4863. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4864. //If we are under a EVENT tag under a EVENTS zone, accumule it
  4865. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4866. if (($this->tree[4] == "EVENT") and ($this->tree[3] == "EVENTS")) {
  4867. if (!isset($this->temp)) {
  4868. $this->temp = "";
  4869. }
  4870. $this->temp .= "<".$tagName.">";
  4871. }
  4872. }
  4873. }
  4874. //This is the startTag handler we use where we are reading the modules zone (todo="MODULES")
  4875. function startElementModules($parser, $tagName, $attrs) {
  4876. //Refresh properties
  4877. $this->level++;
  4878. $this->tree[$this->level] = $tagName;
  4879. //if ($tagName == "MOD" && $this->tree[3] == "MODULES") { //Debug
  4880. // echo "<P>MOD: ".strftime ("%X",time()),"-"; //Debug
  4881. //} //Debug
  4882. //Output something to avoid browser timeouts...
  4883. //backup_flush();
  4884. //Check if we are into MODULES zone
  4885. //if ($this->tree[3] == "MODULES") //Debug
  4886. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4887. //If we are under a MOD tag under a MODULES zone, accumule it
  4888. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4889. if (($this->tree[4] == "MOD") and ($this->tree[3] == "MODULES")) {
  4890. if (!isset($this->temp)) {
  4891. $this->temp = "";
  4892. }
  4893. $this->temp .= "<".$tagName.">";
  4894. }
  4895. }
  4896. }
  4897. //This is the startTag handler we use where we are reading the logs zone (todo="LOGS")
  4898. function startElementLogs($parser, $tagName, $attrs) {
  4899. //Refresh properties
  4900. $this->level++;
  4901. $this->tree[$this->level] = $tagName;
  4902. //if ($tagName == "LOG" && $this->tree[3] == "LOGS") { //Debug
  4903. // echo "<P>LOG: ".strftime ("%X",time()),"-"; //Debug
  4904. //} //Debug
  4905. //Output something to avoid browser timeouts...
  4906. //backup_flush();
  4907. //Check if we are into LOGS zone
  4908. //if ($this->tree[3] == "LOGS") //Debug
  4909. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4910. //If we are under a LOG tag under a LOGS zone, accumule it
  4911. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4912. if (($this->tree[4] == "LOG") and ($this->tree[3] == "LOGS")) {
  4913. if (!isset($this->temp)) {
  4914. $this->temp = "";
  4915. }
  4916. $this->temp .= "<".$tagName.">";
  4917. }
  4918. }
  4919. }
  4920. //This is the startTag default handler we use when todo is undefined
  4921. function startElement($parser, $tagName, $attrs) {
  4922. $this->level++;
  4923. $this->tree[$this->level] = $tagName;
  4924. //Output something to avoid browser timeouts...
  4925. //backup_flush();
  4926. echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4927. }
  4928. //This is the endTag handler we use where we are reading the info zone (todo="INFO")
  4929. function endElementInfo($parser, $tagName) {
  4930. //Check if we are into INFO zone
  4931. if ($this->tree[2] == "INFO") {
  4932. //if (trim($this->content)) //Debug
  4933. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  4934. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  4935. //Dependig of different combinations, do different things
  4936. if ($this->level == 3) {
  4937. switch ($tagName) {
  4938. case "NAME":
  4939. $this->info->backup_name = $this->getContents();
  4940. break;
  4941. case "MOODLE_VERSION":
  4942. $this->info->backup_moodle_version = $this->getContents();
  4943. break;
  4944. case "MOODLE_RELEASE":
  4945. $this->info->backup_moodle_release = $this->getContents();
  4946. break;
  4947. case "BACKUP_VERSION":
  4948. $this->info->backup_backup_version = $this->getContents();
  4949. break;
  4950. case "BACKUP_RELEASE":
  4951. $this->info->backup_backup_release = $this->getContents();
  4952. break;
  4953. case "DATE":
  4954. $this->info->backup_date = $this->getContents();
  4955. break;
  4956. case "ORIGINAL_WWWROOT":
  4957. $this->info->original_wwwroot = $this->getContents();
  4958. break;
  4959. case "ORIGINAL_SITE_IDENTIFIER_HASH":
  4960. $this->info->original_siteidentifier = $this->getContents();
  4961. break;
  4962. case "MNET_REMOTEUSERS":
  4963. $this->info->mnet_remoteusers = $this->getContents();
  4964. break;
  4965. }
  4966. }
  4967. if ($this->tree[3] == "DETAILS") {
  4968. if ($this->level == 4) {
  4969. switch ($tagName) {
  4970. case "METACOURSE":
  4971. $this->info->backup_metacourse = $this->getContents();
  4972. break;
  4973. case "USERS":
  4974. $this->info->backup_users = $this->getContents();
  4975. break;
  4976. case "LOGS":
  4977. $this->info->backup_logs = $this->getContents();
  4978. break;
  4979. case "USERFILES":
  4980. $this->info->backup_user_files = $this->getContents();
  4981. break;
  4982. case "COURSEFILES":
  4983. $this->info->backup_course_files = $this->getContents();
  4984. break;
  4985. case "SITEFILES":
  4986. $this->info->backup_site_files = $this->getContents();
  4987. break;
  4988. case "GRADEBOOKHISTORIES":
  4989. $this->info->gradebook_histories = $this->getContents();
  4990. break;
  4991. case "MESSAGES":
  4992. $this->info->backup_messages = $this->getContents();
  4993. break;
  4994. case "BLOGS":
  4995. $this->info->backup_blogs = $this->getContents();
  4996. break;
  4997. case 'BLOCKFORMAT':
  4998. $this->info->backup_block_format = $this->getContents();
  4999. break;
  5000. }
  5001. }
  5002. if ($this->level == 5) {
  5003. switch ($tagName) {
  5004. case "NAME":
  5005. $this->info->tempName = $this->getContents();
  5006. break;
  5007. case "INCLUDED":
  5008. $this->info->mods[$this->info->tempName]->backup = $this->getContents();
  5009. break;
  5010. case "USERINFO":
  5011. $this->info->mods[$this->info->tempName]->userinfo = $this->getContents();
  5012. break;
  5013. }
  5014. }
  5015. if ($this->level == 7) {
  5016. switch ($tagName) {
  5017. case "ID":
  5018. $this->info->tempId = $this->getContents();
  5019. $this->info->mods[$this->info->tempName]->instances[$this->info->tempId]->id = $this->info->tempId;
  5020. break;
  5021. case "NAME":
  5022. $this->info->mods[$this->info->tempName]->instances[$this->info->tempId]->name = $this->getContents();
  5023. break;
  5024. case "INCLUDED":
  5025. $this->info->mods[$this->info->tempName]->instances[$this->info->tempId]->backup = $this->getContents();
  5026. break;
  5027. case "USERINFO":
  5028. $this->info->mods[$this->info->tempName]->instances[$this->info->tempId]->userinfo = $this->getContents();
  5029. break;
  5030. }
  5031. }
  5032. }
  5033. }
  5034. //Stop parsing if todo = INFO and tagName = INFO (en of the tag, of course)
  5035. //Speed up a lot (avoid parse all)
  5036. if ($tagName == "INFO") {
  5037. $this->finished = true;
  5038. }
  5039. //Clear things
  5040. $this->tree[$this->level] = "";
  5041. $this->level--;
  5042. $this->content = "";
  5043. }
  5044. function endElementRoles($parser, $tagName) {
  5045. //Check if we are into ROLES zone
  5046. if ($this->tree[2] == "ROLES") {
  5047. if ($this->tree[3] == "ROLE") {
  5048. if ($this->level == 4) {
  5049. switch ($tagName) {
  5050. case "ID": // this is the old id
  5051. $this->info->tempid = $this->getContents();
  5052. $this->info->roles[$this->info->tempid]->id = $this->info->tempid;
  5053. break;
  5054. case "NAME":
  5055. $this->info->roles[$this->info->tempid]->name = $this->getContents();;
  5056. break;
  5057. case "SHORTNAME":
  5058. $this->info->roles[$this->info->tempid]->shortname = $this->getContents();;
  5059. break;
  5060. case "NAMEINCOURSE": // custom name of the role in course
  5061. $this->info->roles[$this->info->tempid]->nameincourse = $this->getContents();;
  5062. break;
  5063. }
  5064. }
  5065. if ($this->level == 6) {
  5066. switch ($tagName) {
  5067. case "NAME":
  5068. $this->info->tempcapname = $this->getContents();
  5069. $this->info->roles[$this->info->tempid]->capabilities[$this->info->tempcapname]->name = $this->getContents();
  5070. break;
  5071. case "PERMISSION":
  5072. $this->info->roles[$this->info->tempid]->capabilities[$this->info->tempcapname]->permission = $this->getContents();
  5073. break;
  5074. case "TIMEMODIFIED":
  5075. $this->info->roles[$this->info->tempid]->capabilities[$this->info->tempcapname]->timemodified = $this->getContents();
  5076. break;
  5077. case "MODIFIERID":
  5078. $this->info->roles[$this->info->tempid]->capabilities[$this->info->tempcapname]->modifierid = $this->getContents();
  5079. break;
  5080. }
  5081. }
  5082. }
  5083. }
  5084. //Stop parsing if todo = ROLES and tagName = ROLES (en of the tag, of course)
  5085. //Speed up a lot (avoid parse all)
  5086. if ($tagName == "ROLES") {
  5087. $this->finished = true;
  5088. }
  5089. //Clear things
  5090. $this->tree[$this->level] = "";
  5091. $this->level--;
  5092. $this->content = "";
  5093. }
  5094. //This is the endTag handler we use where we are reading the course_header zone (todo="COURSE_HEADER")
  5095. function endElementCourseHeader($parser, $tagName) {
  5096. //Check if we are into COURSE_HEADER zone
  5097. if ($this->tree[3] == "HEADER") {
  5098. //if (trim($this->content)) //Debug
  5099. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  5100. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  5101. //Dependig of different combinations, do different things
  5102. if ($this->level == 4) {
  5103. switch ($tagName) {
  5104. case "ID":
  5105. $this->info->course_id = $this->getContents();
  5106. break;
  5107. case "PASSWORD":
  5108. $this->info->course_password = $this->getContents();
  5109. break;
  5110. case "FULLNAME":
  5111. $this->info->course_fullname = $this->getContents();
  5112. break;
  5113. case "SHORTNAME":
  5114. $this->info->course_shortname = $this->getContents();
  5115. break;
  5116. case "IDNUMBER":
  5117. $this->info->course_idnumber = $this->getContents();
  5118. break;
  5119. case "SUMMARY":
  5120. $this->info->course_summary = $this->getContents();
  5121. break;
  5122. case "FORMAT":
  5123. $this->info->course_format = $this->getContents();
  5124. break;
  5125. case "SHOWGRADES":
  5126. $this->info->course_showgrades = $this->getContents();
  5127. break;
  5128. case "BLOCKINFO":
  5129. $this->info->blockinfo = $this->getContents();
  5130. break;
  5131. case "NEWSITEMS":
  5132. $this->info->course_newsitems = $this->getContents();
  5133. break;
  5134. case "TEACHER":
  5135. $this->info->course_teacher = $this->getContents();
  5136. break;
  5137. case "TEACHERS":
  5138. $this->info->course_teachers = $this->getContents();
  5139. break;
  5140. case "STUDENT":
  5141. $this->info->course_student = $this->getContents();
  5142. break;
  5143. case "STUDENTS":
  5144. $this->info->course_students = $this->getContents();
  5145. break;
  5146. case "GUEST":
  5147. $this->info->course_guest = $this->getContents();
  5148. break;
  5149. case "STARTDATE":
  5150. $this->info->course_startdate = $this->getContents();
  5151. break;
  5152. case "NUMSECTIONS":
  5153. $this->info->course_numsections = $this->getContents();
  5154. break;
  5155. //case "SHOWRECENT": INFO: This is out in 1.3
  5156. // $this->info->course_showrecent = $this->getContents();
  5157. // break;
  5158. case "MAXBYTES":
  5159. $this->info->course_maxbytes = $this->getContents();
  5160. break;
  5161. case "SHOWREPORTS":
  5162. $this->info->course_showreports = $this->getContents();
  5163. break;
  5164. case "GROUPMODE":
  5165. $this->info->course_groupmode = $this->getContents();
  5166. break;
  5167. case "GROUPMODEFORCE":
  5168. $this->info->course_groupmodeforce = $this->getContents();
  5169. break;
  5170. case "DEFAULTGROUPINGID":
  5171. $this->info->course_defaultgroupingid = $this->getContents();
  5172. break;
  5173. case "LANG":
  5174. $this->info->course_lang = $this->getContents();
  5175. break;
  5176. case "THEME":
  5177. $this->info->course_theme = $this->getContents();
  5178. break;
  5179. case "COST":
  5180. $this->info->course_cost = $this->getContents();
  5181. break;
  5182. case "CURRENCY":
  5183. $this->info->course_currency = $this->getContents();
  5184. break;
  5185. case "MARKER":
  5186. $this->info->course_marker = $this->getContents();
  5187. break;
  5188. case "VISIBLE":
  5189. $this->info->course_visible = $this->getContents();
  5190. break;
  5191. case "HIDDENSECTIONS":
  5192. $this->info->course_hiddensections = $this->getContents();
  5193. break;
  5194. case "TIMECREATED":
  5195. $this->info->course_timecreated = $this->getContents();
  5196. break;
  5197. case "TIMEMODIFIED":
  5198. $this->info->course_timemodified = $this->getContents();
  5199. break;
  5200. case "METACOURSE":
  5201. $this->info->course_metacourse = $this->getContents();
  5202. break;
  5203. case "EXPIRENOTIFY":
  5204. $this->info->course_expirynotify = $this->getContents();
  5205. break;
  5206. case "NOTIFYSTUDENTS":
  5207. $this->info->course_notifystudents = $this->getContents();
  5208. break;
  5209. case "EXPIRYTHRESHOLD":
  5210. $this->info->course_expirythreshold = $this->getContents();
  5211. break;
  5212. case "ENROLLABLE":
  5213. $this->info->course_enrollable = $this->getContents();
  5214. break;
  5215. case "ENROLSTARTDATE":
  5216. $this->info->course_enrolstartdate = $this->getContents();
  5217. break;
  5218. case "ENROLENDDATE":
  5219. $this->info->course_enrolenddate = $this->getContents();
  5220. break;
  5221. case "ENROLPERIOD":
  5222. $this->info->course_enrolperiod = $this->getContents();
  5223. break;
  5224. }
  5225. }
  5226. if ($this->tree[4] == "CATEGORY") {
  5227. if ($this->level == 5) {
  5228. switch ($tagName) {
  5229. case "ID":
  5230. $this->info->category->id = $this->getContents();
  5231. break;
  5232. case "NAME":
  5233. $this->info->category->name = $this->getContents();
  5234. break;
  5235. }
  5236. }
  5237. }
  5238. if ($this->tree[4] == "ROLES_ASSIGNMENTS") {
  5239. if ($this->level == 6) {
  5240. switch ($tagName) {
  5241. case "NAME":
  5242. $this->info->tempname = $this->getContents();
  5243. break;
  5244. case "SHORTNAME":
  5245. $this->info->tempshortname = $this->getContents();
  5246. break;
  5247. case "ID":
  5248. $this->info->tempid = $this->getContents();
  5249. break;
  5250. }
  5251. }
  5252. if ($this->level == 8) {
  5253. switch ($tagName) {
  5254. case "USERID":
  5255. $this->info->roleassignments[$this->info->tempid]->name = $this->info->tempname;
  5256. $this->info->roleassignments[$this->info->tempid]->shortname = $this->info->tempshortname;
  5257. $this->info->tempuser = $this->getContents();
  5258. $this->info->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->userid = $this->getContents();
  5259. break;
  5260. case "HIDDEN":
  5261. $this->info->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->hidden = $this->getContents();
  5262. break;
  5263. case "TIMESTART":
  5264. $this->info->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timestart = $this->getContents();
  5265. break;
  5266. case "TIMEEND":
  5267. $this->info->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timeend = $this->getContents();
  5268. break;
  5269. case "TIMEMODIFIED":
  5270. $this->info->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timemodified = $this->getContents();
  5271. break;
  5272. case "MODIFIERID":
  5273. $this->info->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->modifierid = $this->getContents();
  5274. break;
  5275. case "ENROL":
  5276. $this->info->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->enrol = $this->getContents();
  5277. break;
  5278. case "SORTORDER":
  5279. $this->info->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->sortorder = $this->getContents();
  5280. break;
  5281. }
  5282. }
  5283. } /// ends role_assignments
  5284. if ($this->tree[4] == "ROLES_OVERRIDES") {
  5285. if ($this->level == 6) {
  5286. switch ($tagName) {
  5287. case "NAME":
  5288. $this->info->tempname = $this->getContents();
  5289. break;
  5290. case "SHORTNAME":
  5291. $this->info->tempshortname = $this->getContents();
  5292. break;
  5293. case "ID":
  5294. $this->info->tempid = $this->getContents();
  5295. break;
  5296. }
  5297. }
  5298. if ($this->level == 8) {
  5299. switch ($tagName) {
  5300. case "NAME":
  5301. $this->info->roleoverrides[$this->info->tempid]->name = $this->info->tempname;
  5302. $this->info->roleoverrides[$this->info->tempid]->shortname = $this->info->tempshortname;
  5303. $this->info->tempname = $this->getContents(); // change to name of capability
  5304. $this->info->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->name = $this->getContents();
  5305. break;
  5306. case "PERMISSION":
  5307. $this->info->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->permission = $this->getContents();
  5308. break;
  5309. case "TIMEMODIFIED":
  5310. $this->info->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->timemodified = $this->getContents();
  5311. break;
  5312. case "MODIFIERID":
  5313. $this->info->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->modifierid = $this->getContents();
  5314. break;
  5315. }
  5316. }
  5317. } /// ends role_overrides
  5318. }
  5319. //Stop parsing if todo = COURSE_HEADER and tagName = HEADER (en of the tag, of course)
  5320. //Speed up a lot (avoid parse all)
  5321. if ($tagName == "HEADER") {
  5322. $this->finished = true;
  5323. }
  5324. //Clear things
  5325. $this->tree[$this->level] = "";
  5326. $this->level--;
  5327. $this->content = "";
  5328. }
  5329. //This is the endTag handler we use where we are reading the sections zone (todo="BLOCKS")
  5330. function endElementBlocks($parser, $tagName) {
  5331. //Check if we are into BLOCKS zone
  5332. if ($this->tree[3] == 'BLOCKS') {
  5333. //if (trim($this->content)) //Debug
  5334. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  5335. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  5336. // Collect everything into $this->temp
  5337. if (!isset($this->temp)) {
  5338. $this->temp = "";
  5339. }
  5340. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  5341. //Dependig of different combinations, do different things
  5342. if ($this->level == 4) {
  5343. switch ($tagName) {
  5344. case 'BLOCK':
  5345. //We've finalized a block, get it
  5346. $this->info->instances[] = $this->info->tempinstance;
  5347. unset($this->info->tempinstance);
  5348. //Also, xmlize INSTANCEDATA and save to db
  5349. //Prepend XML standard header to info gathered
  5350. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5351. //Call to xmlize for this portion of xml data (one BLOCK)
  5352. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5353. $data = xmlize($xml_data,0);
  5354. //echo strftime ("%X",time())."<p>"; //Debug
  5355. //traverse_xmlize($data); //Debug
  5356. //print_object ($GLOBALS['traverse_array']); //Debug
  5357. //$GLOBALS['traverse_array']=""; //Debug
  5358. //Check for instancedata, is exists, then save to DB
  5359. if (isset($data['BLOCK']['#']['INSTANCEDATA']['0']['#'])) {
  5360. //Get old id
  5361. $oldid = $data['BLOCK']['#']['ID']['0']['#'];
  5362. //Get instancedata
  5363. if ($data = $data['BLOCK']['#']['INSTANCEDATA']['0']['#']) {
  5364. //Restore code calls this multiple times - so might already have the newid
  5365. if ($newid = backup_getid($this->preferences->backup_unique_code,'block_instance',$oldid)) {
  5366. $newid = $newid->new_id;
  5367. } else {
  5368. $newid = null;
  5369. }
  5370. //Save to DB, we will use it later
  5371. $status = backup_putid($this->preferences->backup_unique_code,'block_instance',$oldid,$newid,$data);
  5372. }
  5373. }
  5374. //Reset temp
  5375. unset($this->temp);
  5376. break;
  5377. default:
  5378. die($tagName);
  5379. }
  5380. }
  5381. if ($this->level == 5) {
  5382. switch ($tagName) {
  5383. case 'ID':
  5384. $this->info->tempinstance->id = $this->getContents();
  5385. case 'NAME':
  5386. $this->info->tempinstance->name = $this->getContents();
  5387. break;
  5388. case 'PAGEID':
  5389. $this->info->tempinstance->pageid = $this->getContents();
  5390. break;
  5391. case 'PAGETYPE':
  5392. $this->info->tempinstance->pagetype = $this->getContents();
  5393. break;
  5394. case 'POSITION':
  5395. $this->info->tempinstance->position = $this->getContents();
  5396. break;
  5397. case 'WEIGHT':
  5398. $this->info->tempinstance->weight = $this->getContents();
  5399. break;
  5400. case 'VISIBLE':
  5401. $this->info->tempinstance->visible = $this->getContents();
  5402. break;
  5403. case 'CONFIGDATA':
  5404. $this->info->tempinstance->configdata = $this->getContents();
  5405. break;
  5406. default:
  5407. break;
  5408. }
  5409. }
  5410. if ($this->tree[5] == "ROLES_ASSIGNMENTS") {
  5411. if ($this->level == 7) {
  5412. switch ($tagName) {
  5413. case "NAME":
  5414. $this->info->tempname = $this->getContents();
  5415. break;
  5416. case "SHORTNAME":
  5417. $this->info->tempshortname = $this->getContents();
  5418. break;
  5419. case "ID":
  5420. $this->info->tempid = $this->getContents(); // temp roleid
  5421. break;
  5422. }
  5423. }
  5424. if ($this->level == 9) {
  5425. switch ($tagName) {
  5426. case "USERID":
  5427. $this->info->tempinstance->roleassignments[$this->info->tempid]->name = $this->info->tempname;
  5428. $this->info->tempinstance->roleassignments[$this->info->tempid]->shortname = $this->info->tempshortname;
  5429. $this->info->tempuser = $this->getContents();
  5430. $this->info->tempinstance->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->userid = $this->getContents();
  5431. break;
  5432. case "HIDDEN":
  5433. $this->info->tempinstance->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->hidden = $this->getContents();
  5434. break;
  5435. case "TIMESTART":
  5436. $this->info->tempinstance->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timestart = $this->getContents();
  5437. break;
  5438. case "TIMEEND":
  5439. $this->info->tempinstance->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timeend = $this->getContents();
  5440. break;
  5441. case "TIMEMODIFIED":
  5442. $this->info->tempinstance->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timemodified = $this->getContents();
  5443. break;
  5444. case "MODIFIERID":
  5445. $this->info->tempinstance->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->modifierid = $this->getContents();
  5446. break;
  5447. case "ENROL":
  5448. $this->info->tempinstance->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->enrol = $this->getContents();
  5449. break;
  5450. case "SORTORDER":
  5451. $this->info->tempinstance->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->sortorder = $this->getContents();
  5452. break;
  5453. }
  5454. }
  5455. } /// ends role_assignments
  5456. if ($this->tree[5] == "ROLES_OVERRIDES") {
  5457. if ($this->level == 7) {
  5458. switch ($tagName) {
  5459. case "NAME":
  5460. $this->info->tempname = $this->getContents();
  5461. break;
  5462. case "SHORTNAME":
  5463. $this->info->tempshortname = $this->getContents();
  5464. break;
  5465. case "ID":
  5466. $this->info->tempid = $this->getContents(); // temp roleid
  5467. break;
  5468. }
  5469. }
  5470. if ($this->level == 9) {
  5471. switch ($tagName) {
  5472. case "NAME":
  5473. $this->info->tempinstance->roleoverrides[$this->info->tempid]->name = $this->info->tempname;
  5474. $this->info->tempinstance->roleoverrides[$this->info->tempid]->shortname = $this->info->tempshortname;
  5475. $this->info->tempname = $this->getContents(); // change to name of capability
  5476. $this->info->tempinstance->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->name = $this->getContents();
  5477. break;
  5478. case "PERMISSION":
  5479. $this->info->tempinstance->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->permission = $this->getContents();
  5480. break;
  5481. case "TIMEMODIFIED":
  5482. $this->info->tempinstance->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->timemodified = $this->getContents();
  5483. break;
  5484. case "MODIFIERID":
  5485. $this->info->tempinstance->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->modifierid = $this->getContents();
  5486. break;
  5487. }
  5488. }
  5489. } /// ends role_overrides
  5490. }
  5491. //Stop parsing if todo = BLOCKS and tagName = BLOCKS (en of the tag, of course)
  5492. //Speed up a lot (avoid parse all)
  5493. //WARNING: ONLY EXIT IF todo = BLOCKS (thus tree[3] = "BLOCKS") OTHERWISE
  5494. // THE BLOCKS TAG IN THE HEADER WILL TERMINATE US!
  5495. if ($this->tree[3] == 'BLOCKS' && $tagName == 'BLOCKS') {
  5496. $this->finished = true;
  5497. }
  5498. //Clear things
  5499. $this->tree[$this->level] = '';
  5500. $this->level--;
  5501. $this->content = "";
  5502. }
  5503. //This is the endTag handler we use where we are reading the sections zone (todo="SECTIONS")
  5504. function endElementSections($parser, $tagName) {
  5505. //Check if we are into SECTIONS zone
  5506. if ($this->tree[3] == "SECTIONS") {
  5507. //if (trim($this->content)) //Debug
  5508. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  5509. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  5510. //Dependig of different combinations, do different things
  5511. if ($this->level == 4) {
  5512. switch ($tagName) {
  5513. case "SECTION":
  5514. //We've finalized a section, get it
  5515. $this->info->sections[$this->info->tempsection->id] = $this->info->tempsection;
  5516. unset($this->info->tempsection);
  5517. }
  5518. }
  5519. if ($this->level == 5) {
  5520. switch ($tagName) {
  5521. case "ID":
  5522. $this->info->tempsection->id = $this->getContents();
  5523. break;
  5524. case "NUMBER":
  5525. $this->info->tempsection->number = $this->getContents();
  5526. break;
  5527. case "SUMMARY":
  5528. $this->info->tempsection->summary = $this->getContents();
  5529. break;
  5530. case "VISIBLE":
  5531. $this->info->tempsection->visible = $this->getContents();
  5532. break;
  5533. }
  5534. }
  5535. if ($this->level == 6) {
  5536. switch ($tagName) {
  5537. case "MOD":
  5538. if (!isset($this->info->tempmod->groupmode)) {
  5539. $this->info->tempmod->groupmode = 0;
  5540. }
  5541. if (!isset($this->info->tempmod->groupingid)) {
  5542. $this->info->tempmod->groupingid = 0;
  5543. }
  5544. if (!isset($this->info->tempmod->groupmembersonly)) {
  5545. $this->info->tempmod->groupmembersonly = 0;
  5546. }
  5547. if (!isset($this->info->tempmod->idnumber)) {
  5548. $this->info->tempmod->idnumber = null;
  5549. }
  5550. //We've finalized a mod, get it
  5551. $this->info->tempsection->mods[$this->info->tempmod->id]->type =
  5552. $this->info->tempmod->type;
  5553. $this->info->tempsection->mods[$this->info->tempmod->id]->instance =
  5554. $this->info->tempmod->instance;
  5555. $this->info->tempsection->mods[$this->info->tempmod->id]->added =
  5556. $this->info->tempmod->added;
  5557. $this->info->tempsection->mods[$this->info->tempmod->id]->score =
  5558. $this->info->tempmod->score;
  5559. $this->info->tempsection->mods[$this->info->tempmod->id]->indent =
  5560. $this->info->tempmod->indent;
  5561. $this->info->tempsection->mods[$this->info->tempmod->id]->visible =
  5562. $this->info->tempmod->visible;
  5563. $this->info->tempsection->mods[$this->info->tempmod->id]->groupmode =
  5564. $this->info->tempmod->groupmode;
  5565. $this->info->tempsection->mods[$this->info->tempmod->id]->groupingid =
  5566. $this->info->tempmod->groupingid;
  5567. $this->info->tempsection->mods[$this->info->tempmod->id]->groupmembersonly =
  5568. $this->info->tempmod->groupmembersonly;
  5569. $this->info->tempsection->mods[$this->info->tempmod->id]->idnumber =
  5570. $this->info->tempmod->idnumber;
  5571. unset($this->info->tempmod);
  5572. }
  5573. }
  5574. if ($this->level == 7) {
  5575. switch ($tagName) {
  5576. case "ID":
  5577. $this->info->tempmod->id = $this->getContents();
  5578. break;
  5579. case "TYPE":
  5580. $this->info->tempmod->type = $this->getContents();
  5581. break;
  5582. case "INSTANCE":
  5583. $this->info->tempmod->instance = $this->getContents();
  5584. break;
  5585. case "ADDED":
  5586. $this->info->tempmod->added = $this->getContents();
  5587. break;
  5588. case "SCORE":
  5589. $this->info->tempmod->score = $this->getContents();
  5590. break;
  5591. case "INDENT":
  5592. $this->info->tempmod->indent = $this->getContents();
  5593. break;
  5594. case "VISIBLE":
  5595. $this->info->tempmod->visible = $this->getContents();
  5596. break;
  5597. case "GROUPMODE":
  5598. $this->info->tempmod->groupmode = $this->getContents();
  5599. break;
  5600. case "GROUPINGID":
  5601. $this->info->tempmod->groupingid = $this->getContents();
  5602. break;
  5603. case "GROUPMEMBERSONLY":
  5604. $this->info->tempmod->groupmembersonly = $this->getContents();
  5605. break;
  5606. case "IDNUMBER":
  5607. $this->info->tempmod->idnumber = $this->getContents();
  5608. break;
  5609. default:
  5610. break;
  5611. }
  5612. }
  5613. if (isset($this->tree[7]) && $this->tree[7] == "ROLES_ASSIGNMENTS") {
  5614. if ($this->level == 9) {
  5615. switch ($tagName) {
  5616. case "NAME":
  5617. $this->info->tempname = $this->getContents();
  5618. break;
  5619. case "SHORTNAME":
  5620. $this->info->tempshortname = $this->getContents();
  5621. break;
  5622. case "ID":
  5623. $this->info->tempid = $this->getContents(); // temp roleid
  5624. break;
  5625. }
  5626. }
  5627. if ($this->level == 11) {
  5628. switch ($tagName) {
  5629. case "USERID":
  5630. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->name = $this->info->tempname;
  5631. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->shortname = $this->info->tempshortname;
  5632. $this->info->tempuser = $this->getContents();
  5633. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->userid = $this->getContents();
  5634. break;
  5635. case "HIDDEN":
  5636. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->hidden = $this->getContents();
  5637. break;
  5638. case "TIMESTART":
  5639. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timestart = $this->getContents();
  5640. break;
  5641. case "TIMEEND":
  5642. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timeend = $this->getContents();
  5643. break;
  5644. case "TIMEMODIFIED":
  5645. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timemodified = $this->getContents();
  5646. break;
  5647. case "MODIFIERID":
  5648. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->modifierid = $this->getContents();
  5649. break;
  5650. case "ENROL":
  5651. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->enrol = $this->getContents();
  5652. break;
  5653. case "SORTORDER":
  5654. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->sortorder = $this->getContents();
  5655. break;
  5656. }
  5657. }
  5658. } /// ends role_assignments
  5659. if (isset($this->tree[7]) && $this->tree[7] == "ROLES_OVERRIDES") {
  5660. if ($this->level == 9) {
  5661. switch ($tagName) {
  5662. case "NAME":
  5663. $this->info->tempname = $this->getContents();
  5664. break;
  5665. case "SHORTNAME":
  5666. $this->info->tempshortname = $this->getContents();
  5667. break;
  5668. case "ID":
  5669. $this->info->tempid = $this->getContents(); // temp roleid
  5670. break;
  5671. }
  5672. }
  5673. if ($this->level == 11) {
  5674. switch ($tagName) {
  5675. case "NAME":
  5676. $this->info->tempsection->mods[$this->info->tempmod->id]->roleoverrides[$this->info->tempid]->name = $this->info->tempname;
  5677. $this->info->tempsection->mods[$this->info->tempmod->id]->roleoverrides[$this->info->tempid]->shortname = $this->info->tempshortname;
  5678. $this->info->tempname = $this->getContents(); // change to name of capability
  5679. $this->info->tempsection->mods[$this->info->tempmod->id]->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->name = $this->getContents();
  5680. break;
  5681. case "PERMISSION":
  5682. $this->info->tempsection->mods[$this->info->tempmod->id]->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->permission = $this->getContents();
  5683. break;
  5684. case "TIMEMODIFIED":
  5685. $this->info->tempsection->mods[$this->info->tempmod->id]->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->timemodified = $this->getContents();
  5686. break;
  5687. case "MODIFIERID":
  5688. $this->info->tempsection->mods[$this->info->tempmod->id]->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->modifierid = $this->getContents();
  5689. break;
  5690. }
  5691. }
  5692. } /// ends role_overrides
  5693. }
  5694. //Stop parsing if todo = SECTIONS and tagName = SECTIONS (en of the tag, of course)
  5695. //Speed up a lot (avoid parse all)
  5696. if ($tagName == "SECTIONS") {
  5697. $this->finished = true;
  5698. }
  5699. //Clear things
  5700. $this->tree[$this->level] = "";
  5701. $this->level--;
  5702. $this->content = "";
  5703. }
  5704. //This is the endTag handler we use where we are reading the optional format data zone (todo="FORMATDATA")
  5705. function endElementFormatData($parser, $tagName) {
  5706. //Check if we are into FORMATDATA zone
  5707. if ($this->tree[3] == 'FORMATDATA') {
  5708. if (!isset($this->temp)) {
  5709. $this->temp = '';
  5710. }
  5711. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  5712. }
  5713. if($tagName=='FORMATDATA') {
  5714. //Did we have any data? If not don't bother
  5715. if($this->temp!='<FORMATDATA></FORMATDATA>') {
  5716. //Prepend XML standard header to info gathered
  5717. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5718. $this->temp='';
  5719. //Call to xmlize for this portion of xml data (the FORMATDATA block)
  5720. $this->info->format_data = xmlize($xml_data,0);
  5721. }
  5722. //Stop parsing at end of FORMATDATA
  5723. $this->finished=true;
  5724. }
  5725. //Clear things
  5726. $this->tree[$this->level] = "";
  5727. $this->level--;
  5728. $this->content = "";
  5729. }
  5730. //This is the endTag handler we use where we are reading the metacourse zone (todo="METACOURSE")
  5731. function endElementMetacourse($parser, $tagName) {
  5732. //Check if we are into METACOURSE zone
  5733. if ($this->tree[3] == 'METACOURSE') {
  5734. //if (trim($this->content)) //Debug
  5735. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  5736. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  5737. //Dependig of different combinations, do different things
  5738. if ($this->level == 5) {
  5739. switch ($tagName) {
  5740. case 'CHILD':
  5741. //We've finalized a child, get it
  5742. $this->info->childs[] = $this->info->tempmeta;
  5743. unset($this->info->tempmeta);
  5744. break;
  5745. case 'PARENT':
  5746. //We've finalized a parent, get it
  5747. $this->info->parents[] = $this->info->tempmeta;
  5748. unset($this->info->tempmeta);
  5749. break;
  5750. default:
  5751. die($tagName);
  5752. }
  5753. }
  5754. if ($this->level == 6) {
  5755. switch ($tagName) {
  5756. case 'ID':
  5757. $this->info->tempmeta->id = $this->getContents();
  5758. break;
  5759. case 'IDNUMBER':
  5760. $this->info->tempmeta->idnumber = $this->getContents();
  5761. break;
  5762. case 'SHORTNAME':
  5763. $this->info->tempmeta->shortname = $this->getContents();
  5764. break;
  5765. }
  5766. }
  5767. }
  5768. //Stop parsing if todo = METACOURSE and tagName = METACOURSE (en of the tag, of course)
  5769. //Speed up a lot (avoid parse all)
  5770. if ($this->tree[3] == 'METACOURSE' && $tagName == 'METACOURSE') {
  5771. $this->finished = true;
  5772. }
  5773. //Clear things
  5774. $this->tree[$this->level] = '';
  5775. $this->level--;
  5776. $this->content = "";
  5777. }
  5778. //This is the endTag handler we use where we are reading the gradebook zone (todo="GRADEBOOK")
  5779. function endElementGradebook($parser, $tagName) {
  5780. //Check if we are into GRADEBOOK zone
  5781. if ($this->tree[3] == "GRADEBOOK") {
  5782. //if (trim($this->content)) //Debug
  5783. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  5784. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n";//Debug
  5785. //Acumulate data to info (content + close tag)
  5786. //Reconvert: strip htmlchars again and trim to generate xml data
  5787. if (!isset($this->temp)) {
  5788. $this->temp = "";
  5789. }
  5790. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  5791. // We have finished outcome, grade_category or grade_item, reset accumulated
  5792. // data because they are close tags
  5793. if ($this->level == 4) {
  5794. $this->temp = "";
  5795. }
  5796. //If we've finished a grade item, xmlize it an save to db
  5797. if (($this->level == 5) and ($tagName == "GRADE_ITEM")) {
  5798. //Prepend XML standard header to info gathered
  5799. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5800. //Call to xmlize for this portion of xml data (one PREFERENCE)
  5801. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5802. $data = xmlize($xml_data,0);
  5803. $item_id = $data["GRADE_ITEM"]["#"]["ID"]["0"]["#"];
  5804. $this->counter++;
  5805. //Save to db
  5806. $status = backup_putid($this->preferences->backup_unique_code, 'grade_items', $item_id,
  5807. null,$data);
  5808. //Create returning info
  5809. $this->info = $this->counter;
  5810. //Reset temp
  5811. unset($this->temp);
  5812. }
  5813. //If we've finished a grade_category, xmlize it an save to db
  5814. if (($this->level == 5) and ($tagName == "GRADE_CATEGORY")) {
  5815. //Prepend XML standard header to info gathered
  5816. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5817. //Call to xmlize for this portion of xml data (one CATECORY)
  5818. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5819. $data = xmlize($xml_data,0);
  5820. $category_id = $data["GRADE_CATEGORY"]["#"]["ID"]["0"]["#"];
  5821. $this->counter++;
  5822. //Save to db
  5823. $status = backup_putid($this->preferences->backup_unique_code, 'grade_categories' ,$category_id,
  5824. null,$data);
  5825. //Create returning info
  5826. $this->info = $this->counter;
  5827. //Reset temp
  5828. unset($this->temp);
  5829. }
  5830. if (($this->level == 5) and ($tagName == "GRADE_LETTER")) {
  5831. //Prepend XML standard header to info gathered
  5832. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5833. //Call to xmlize for this portion of xml data (one CATECORY)
  5834. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5835. $data = xmlize($xml_data,0);
  5836. $letter_id = $data["GRADE_LETTER"]["#"]["ID"]["0"]["#"];
  5837. $this->counter++;
  5838. //Save to db
  5839. $status = backup_putid($this->preferences->backup_unique_code, 'grade_letters' ,$letter_id,
  5840. null,$data);
  5841. //Create returning info
  5842. $this->info = $this->counter;
  5843. //Reset temp
  5844. unset($this->temp);
  5845. }
  5846. //If we've finished a grade_outcome, xmlize it an save to db
  5847. if (($this->level == 5) and ($tagName == "GRADE_OUTCOME")) {
  5848. //Prepend XML standard header to info gathered
  5849. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5850. //Call to xmlize for this portion of xml data (one CATECORY)
  5851. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5852. $data = xmlize($xml_data,0);
  5853. $outcome_id = $data["GRADE_OUTCOME"]["#"]["ID"]["0"]["#"];
  5854. $this->counter++;
  5855. //Save to db
  5856. $status = backup_putid($this->preferences->backup_unique_code, 'grade_outcomes' ,$outcome_id,
  5857. null,$data);
  5858. //Create returning info
  5859. $this->info = $this->counter;
  5860. //Reset temp
  5861. unset($this->temp);
  5862. }
  5863. //If we've finished a grade_outcomes_course, xmlize it an save to db
  5864. if (($this->level == 5) and ($tagName == "GRADE_OUTCOMES_COURSE")) {
  5865. //Prepend XML standard header to info gathered
  5866. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5867. //Call to xmlize for this portion of xml data (one CATECORY)
  5868. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5869. $data = xmlize($xml_data,0);
  5870. $outcomes_course_id = $data["GRADE_OUTCOMES_COURSE"]["#"]["ID"]["0"]["#"];
  5871. $this->counter++;
  5872. //Save to db
  5873. $status = backup_putid($this->preferences->backup_unique_code, 'grade_outcomes_courses' ,$outcomes_course_id,
  5874. null,$data);
  5875. //Create returning info
  5876. $this->info = $this->counter;
  5877. //Reset temp
  5878. unset($this->temp);
  5879. }
  5880. if (($this->level == 5) and ($tagName == "GRADE_CATEGORIES_HISTORY")) {
  5881. //Prepend XML standard header to info gathered
  5882. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5883. //Call to xmlize for this portion of xml data (one PREFERENCE)
  5884. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5885. $data = xmlize($xml_data,0);
  5886. $id = $data["GRADE_CATEGORIES_HISTORY"]["#"]["ID"]["0"]["#"];
  5887. $this->counter++;
  5888. //Save to db
  5889. $status = backup_putid($this->preferences->backup_unique_code, 'grade_categories_history', $id,
  5890. null,$data);
  5891. //Create returning info
  5892. $this->info = $this->counter;
  5893. //Reset temp
  5894. unset($this->temp);
  5895. }
  5896. if (($this->level == 5) and ($tagName == "GRADE_GRADES_HISTORY")) {
  5897. //Prepend XML standard header to info gathered
  5898. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5899. //Call to xmlize for this portion of xml data (one PREFERENCE)
  5900. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5901. $data = xmlize($xml_data,0);
  5902. $id = $data["GRADE_GRADES_HISTORY"]["#"]["ID"]["0"]["#"];
  5903. $this->counter++;
  5904. //Save to db
  5905. $status = backup_putid($this->preferences->backup_unique_code, 'grade_grades_history', $id,
  5906. null,$data);
  5907. //Create returning info
  5908. $this->info = $this->counter;
  5909. //Reset temp
  5910. unset($this->temp);
  5911. }
  5912. if (($this->level == 5) and ($tagName == "GRADE_ITEM_HISTORY")) {
  5913. //Prepend XML standard header to info gathered
  5914. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5915. //Call to xmlize for this portion of xml data (one PREFERENCE)
  5916. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5917. $data = xmlize($xml_data,0);
  5918. $id = $data["GRADE_ITEM_HISTORY"]["#"]["ID"]["0"]["#"];
  5919. $this->counter++;
  5920. //Save to db
  5921. $status = backup_putid($this->preferences->backup_unique_code, 'grade_items_history', $id,
  5922. null,$data);
  5923. //Create returning info
  5924. $this->info = $this->counter;
  5925. //Reset temp
  5926. unset($this->temp);
  5927. }
  5928. if (($this->level == 5) and ($tagName == "GRADE_OUTCOME_HISTORY")) {
  5929. //Prepend XML standard header to info gathered
  5930. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5931. //Call to xmlize for this portion of xml data (one PREFERENCE)
  5932. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5933. $data = xmlize($xml_data,0);
  5934. $id = $data["GRADE_OUTCOME_HISTORY"]["#"]["ID"]["0"]["#"];
  5935. $this->counter++;
  5936. //Save to db
  5937. $status = backup_putid($this->preferences->backup_unique_code, 'grade_outcomes_history', $id,
  5938. null,$data);
  5939. //Create returning info
  5940. $this->info = $this->counter;
  5941. //Reset temp
  5942. unset($this->temp);
  5943. }
  5944. }
  5945. //Stop parsing if todo = GRADEBOOK and tagName = GRADEBOOK (en of the tag, of course)
  5946. //Speed up a lot (avoid parse all)
  5947. if ($tagName == "GRADEBOOK" and $this->level == 3) {
  5948. $this->finished = true;
  5949. $this->counter = 0;
  5950. }
  5951. //Clear things
  5952. $this->tree[$this->level] = "";
  5953. $this->level--;
  5954. $this->content = "";
  5955. }
  5956. //This is the endTag handler we use where we are reading the gradebook zone (todo="GRADEBOOK")
  5957. function endElementOldGradebook($parser, $tagName) {
  5958. //Check if we are into GRADEBOOK zone
  5959. if ($this->tree[3] == "GRADEBOOK") {
  5960. //if (trim($this->content)) //Debug
  5961. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  5962. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n";//Debug
  5963. //Acumulate data to info (content + close tag)
  5964. //Reconvert: strip htmlchars again and trim to generate xml data
  5965. if (!isset($this->temp)) {
  5966. $this->temp = "";
  5967. }
  5968. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  5969. //We have finished preferences, letters or categories, reset accumulated
  5970. //data because they are close tags
  5971. if ($this->level == 4) {
  5972. $this->temp = "";
  5973. }
  5974. //If we've finished a message, xmlize it an save to db
  5975. if (($this->level == 5) and ($tagName == "GRADE_PREFERENCE")) {
  5976. //Prepend XML standard header to info gathered
  5977. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5978. //Call to xmlize for this portion of xml data (one PREFERENCE)
  5979. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5980. $data = xmlize($xml_data,0);
  5981. //echo strftime ("%X",time())."<p>"; //Debug
  5982. //traverse_xmlize($data); //Debug
  5983. //print_object ($GLOBALS['traverse_array']); //Debug
  5984. //$GLOBALS['traverse_array']=""; //Debug
  5985. //Now, save data to db. We'll use it later
  5986. //Get id and status from data
  5987. $preference_id = $data["GRADE_PREFERENCE"]["#"]["ID"]["0"]["#"];
  5988. $this->counter++;
  5989. //Save to db
  5990. $status = backup_putid($this->preferences->backup_unique_code, 'grade_preferences', $preference_id,
  5991. null,$data);
  5992. //Create returning info
  5993. $this->info = $this->counter;
  5994. //Reset temp
  5995. unset($this->temp);
  5996. }
  5997. //If we've finished a grade_letter, xmlize it an save to db
  5998. if (($this->level == 5) and ($tagName == "GRADE_LETTER")) {
  5999. //Prepend XML standard header to info gathered
  6000. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6001. //Call to xmlize for this portion of xml data (one LETTER)
  6002. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6003. $data = xmlize($xml_data,0);
  6004. //echo strftime ("%X",time())."<p>"; //Debug
  6005. //traverse_xmlize($data); //Debug
  6006. //print_object ($GLOBALS['traverse_array']); //Debug
  6007. //$GLOBALS['traverse_array']=""; //Debug
  6008. //Now, save data to db. We'll use it later
  6009. //Get id and status from data
  6010. $letter_id = $data["GRADE_LETTER"]["#"]["ID"]["0"]["#"];
  6011. $this->counter++;
  6012. //Save to db
  6013. $status = backup_putid($this->preferences->backup_unique_code, 'grade_letter' ,$letter_id,
  6014. null,$data);
  6015. //Create returning info
  6016. $this->info = $this->counter;
  6017. //Reset temp
  6018. unset($this->temp);
  6019. }
  6020. //If we've finished a grade_category, xmlize it an save to db
  6021. if (($this->level == 5) and ($tagName == "GRADE_CATEGORY")) {
  6022. //Prepend XML standard header to info gathered
  6023. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6024. //Call to xmlize for this portion of xml data (one CATECORY)
  6025. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6026. $data = xmlize($xml_data,0);
  6027. //echo strftime ("%X",time())."<p>"; //Debug
  6028. //traverse_xmlize($data); //Debug
  6029. //print_object ($GLOBALS['traverse_array']); //Debug
  6030. //$GLOBALS['traverse_array']=""; //Debug
  6031. //Now, save data to db. We'll use it later
  6032. //Get id and status from data
  6033. $category_id = $data["GRADE_CATEGORY"]["#"]["ID"]["0"]["#"];
  6034. $this->counter++;
  6035. //Save to db
  6036. $status = backup_putid($this->preferences->backup_unique_code, 'grade_category' ,$category_id,
  6037. null,$data);
  6038. //Create returning info
  6039. $this->info = $this->counter;
  6040. //Reset temp
  6041. unset($this->temp);
  6042. }
  6043. }
  6044. //Stop parsing if todo = GRADEBOOK and tagName = GRADEBOOK (en of the tag, of course)
  6045. //Speed up a lot (avoid parse all)
  6046. if ($tagName == "GRADEBOOK" and $this->level == 3) {
  6047. $this->finished = true;
  6048. $this->counter = 0;
  6049. }
  6050. //Clear things
  6051. $this->tree[$this->level] = "";
  6052. $this->level--;
  6053. $this->content = "";
  6054. }
  6055. //This is the endTag handler we use where we are reading the users zone (todo="USERS")
  6056. function endElementUsers($parser, $tagName) {
  6057. global $CFG;
  6058. //Check if we are into USERS zone
  6059. if ($this->tree[3] == "USERS") {
  6060. //if (trim($this->content)) //Debug
  6061. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6062. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  6063. //Dependig of different combinations, do different things
  6064. if ($this->level == 4) {
  6065. switch ($tagName) {
  6066. case "USER":
  6067. //Increment counter
  6068. $this->counter++;
  6069. //Save to db, only save if record not already exist
  6070. // if there already is an new_id for this entry, just use that new_id?
  6071. $newuser = backup_getid($this->preferences->backup_unique_code,"user",$this->info->tempuser->id);
  6072. if (isset($newuser->new_id)) {
  6073. $newid = $newuser->new_id;
  6074. } else {
  6075. $newid = null;
  6076. }
  6077. backup_putid($this->preferences->backup_unique_code,"user",$this->info->tempuser->id,
  6078. $newid,$this->info->tempuser);
  6079. //Do some output
  6080. if ($this->counter % 10 == 0) {
  6081. if (!defined('RESTORE_SILENTLY')) {
  6082. echo ".";
  6083. if ($this->counter % 200 == 0) {
  6084. echo "<br />";
  6085. }
  6086. }
  6087. backup_flush(300);
  6088. }
  6089. //Delete temp obejct
  6090. unset($this->info->tempuser);
  6091. break;
  6092. }
  6093. }
  6094. if ($this->level == 5) {
  6095. switch ($tagName) {
  6096. case "ID":
  6097. $this->info->users[$this->getContents()] = $this->getContents();
  6098. $this->info->tempuser->id = $this->getContents();
  6099. break;
  6100. case "AUTH":
  6101. $this->info->tempuser->auth = $this->getContents();
  6102. break;
  6103. case "CONFIRMED":
  6104. $this->info->tempuser->confirmed = $this->getContents();
  6105. break;
  6106. case "POLICYAGREED":
  6107. $this->info->tempuser->policyagreed = $this->getContents();
  6108. break;
  6109. case "DELETED":
  6110. $this->info->tempuser->deleted = $this->getContents();
  6111. break;
  6112. case "USERNAME":
  6113. $this->info->tempuser->username = $this->getContents();
  6114. break;
  6115. case "PASSWORD":
  6116. $this->info->tempuser->password = $this->getContents();
  6117. break;
  6118. case "IDNUMBER":
  6119. $this->info->tempuser->idnumber = $this->getContents();
  6120. break;
  6121. case "FIRSTNAME":
  6122. $this->info->tempuser->firstname = $this->getContents();
  6123. break;
  6124. case "LASTNAME":
  6125. $this->info->tempuser->lastname = $this->getContents();
  6126. break;
  6127. case "EMAIL":
  6128. $this->info->tempuser->email = $this->getContents();
  6129. break;
  6130. case "EMAILSTOP":
  6131. $this->info->tempuser->emailstop = $this->getContents();
  6132. break;
  6133. case "ICQ":
  6134. $this->info->tempuser->icq = $this->getContents();
  6135. break;
  6136. case "SKYPE":
  6137. $this->info->tempuser->skype = $this->getContents();
  6138. break;
  6139. case "AIM":
  6140. $this->info->tempuser->aim = $this->getContents();
  6141. break;
  6142. case "YAHOO":
  6143. $this->info->tempuser->yahoo = $this->getContents();
  6144. break;
  6145. case "MSN":
  6146. $this->info->tempuser->msn = $this->getContents();
  6147. break;
  6148. case "PHONE1":
  6149. $this->info->tempuser->phone1 = $this->getContents();
  6150. break;
  6151. case "PHONE2":
  6152. $this->info->tempuser->phone2 = $this->getContents();
  6153. break;
  6154. case "INSTITUTION":
  6155. $this->info->tempuser->institution = $this->getContents();
  6156. break;
  6157. case "DEPARTMENT":
  6158. $this->info->tempuser->department = $this->getContents();
  6159. break;
  6160. case "ADDRESS":
  6161. $this->info->tempuser->address = $this->getContents();
  6162. break;
  6163. case "CITY":
  6164. $this->info->tempuser->city = $this->getContents();
  6165. break;
  6166. case "COUNTRY":
  6167. $this->info->tempuser->country = $this->getContents();
  6168. break;
  6169. case "LANG":
  6170. $this->info->tempuser->lang = $this->getContents();
  6171. break;
  6172. case "THEME":
  6173. $this->info->tempuser->theme = $this->getContents();
  6174. break;
  6175. case "TIMEZONE":
  6176. $this->info->tempuser->timezone = $this->getContents();
  6177. break;
  6178. case "FIRSTACCESS":
  6179. $this->info->tempuser->firstaccess = $this->getContents();
  6180. break;
  6181. case "LASTACCESS":
  6182. $this->info->tempuser->lastaccess = $this->getContents();
  6183. break;
  6184. case "LASTLOGIN":
  6185. $this->info->tempuser->lastlogin = $this->getContents();
  6186. break;
  6187. case "CURRENTLOGIN":
  6188. $this->info->tempuser->currentlogin = $this->getContents();
  6189. break;
  6190. case "LASTIP":
  6191. $this->info->tempuser->lastip = $this->getContents();
  6192. break;
  6193. case "PICTURE":
  6194. $this->info->tempuser->picture = $this->getContents();
  6195. break;
  6196. case "URL":
  6197. $this->info->tempuser->url = $this->getContents();
  6198. break;
  6199. case "DESCRIPTION":
  6200. $this->info->tempuser->description = $this->getContents();
  6201. break;
  6202. case "MAILFORMAT":
  6203. $this->info->tempuser->mailformat = $this->getContents();
  6204. break;
  6205. case "MAILDIGEST":
  6206. $this->info->tempuser->maildigest = $this->getContents();
  6207. break;
  6208. case "MAILDISPLAY":
  6209. $this->info->tempuser->maildisplay = $this->getContents();
  6210. break;
  6211. case "HTMLEDITOR":
  6212. $this->info->tempuser->htmleditor = $this->getContents();
  6213. break;
  6214. case "AJAX":
  6215. $this->info->tempuser->ajax = $this->getContents();
  6216. break;
  6217. case "AUTOSUBSCRIBE":
  6218. $this->info->tempuser->autosubscribe = $this->getContents();
  6219. break;
  6220. case "TRACKFORUMS":
  6221. $this->info->tempuser->trackforums = $this->getContents();
  6222. break;
  6223. case "MNETHOSTURL":
  6224. $this->info->tempuser->mnethosturl = $this->getContents();
  6225. break;
  6226. case "TIMEMODIFIED":
  6227. $this->info->tempuser->timemodified = $this->getContents();
  6228. break;
  6229. default:
  6230. break;
  6231. }
  6232. }
  6233. if ($this->level == 6 && $this->tree[5]!="ROLES_ASSIGNMENTS" && $this->tree[5]!="ROLES_OVERRIDES") {
  6234. switch ($tagName) {
  6235. case "ROLE":
  6236. //We've finalized a role, get it
  6237. $this->info->tempuser->roles[$this->info->temprole->type] = $this->info->temprole;
  6238. unset($this->info->temprole);
  6239. break;
  6240. case "USER_PREFERENCE":
  6241. //We've finalized a user_preference, get it
  6242. $this->info->tempuser->user_preferences[$this->info->tempuserpreference->name] = $this->info->tempuserpreference;
  6243. unset($this->info->tempuserpreference);
  6244. break;
  6245. case "USER_CUSTOM_PROFILE_FIELD":
  6246. //We've finalized a user_custom_profile_field, get it
  6247. $this->info->tempuser->user_custom_profile_fields[] = $this->info->tempusercustomprofilefield;
  6248. unset($this->info->tempusercustomprofilefield);
  6249. break;
  6250. case "USER_TAG":
  6251. //We've finalized a user_tag, get it
  6252. $this->info->tempuser->user_tags[] = $this->info->tempusertag;
  6253. unset($this->info->tempusertag);
  6254. break;
  6255. default:
  6256. break;
  6257. }
  6258. }
  6259. if ($this->level == 7 && $this->tree[5]!="ROLES_ASSIGNMENTS" && $this->tree[5]!="ROLES_OVERRIDES") {
  6260. /// If we are reading roles
  6261. if($this->tree[6] == 'ROLE') {
  6262. switch ($tagName) {
  6263. case "TYPE":
  6264. $this->info->temprole->type = $this->getContents();
  6265. break;
  6266. case "AUTHORITY":
  6267. $this->info->temprole->authority = $this->getContents();
  6268. break;
  6269. case "TEA_ROLE":
  6270. $this->info->temprole->tea_role = $this->getContents();
  6271. break;
  6272. case "EDITALL":
  6273. $this->info->temprole->editall = $this->getContents();
  6274. break;
  6275. case "TIMESTART":
  6276. $this->info->temprole->timestart = $this->getContents();
  6277. break;
  6278. case "TIMEEND":
  6279. $this->info->temprole->timeend = $this->getContents();
  6280. break;
  6281. case "TIMEMODIFIED":
  6282. $this->info->temprole->timemodified = $this->getContents();
  6283. break;
  6284. case "TIMESTART":
  6285. $this->info->temprole->timestart = $this->getContents();
  6286. break;
  6287. case "TIMEEND":
  6288. $this->info->temprole->timeend = $this->getContents();
  6289. break;
  6290. case "TIME":
  6291. $this->info->temprole->time = $this->getContents();
  6292. break;
  6293. case "TIMEACCESS":
  6294. $this->info->temprole->timeaccess = $this->getContents();
  6295. break;
  6296. case "ENROL":
  6297. $this->info->temprole->enrol = $this->getContents();
  6298. break;
  6299. default:
  6300. break;
  6301. }
  6302. /// If we are reading user_preferences
  6303. } else if ($this->tree[6] == 'USER_PREFERENCE') {
  6304. switch ($tagName) {
  6305. case "NAME":
  6306. $this->info->tempuserpreference->name = $this->getContents();
  6307. break;
  6308. case "VALUE":
  6309. $this->info->tempuserpreference->value = $this->getContents();
  6310. break;
  6311. default:
  6312. break;
  6313. }
  6314. /// If we are reading user_custom_profile_fields
  6315. } else if ($this->tree[6] == 'USER_CUSTOM_PROFILE_FIELD') {
  6316. switch ($tagName) {
  6317. case "FIELD_NAME":
  6318. $this->info->tempusercustomprofilefield->field_name = $this->getContents();
  6319. break;
  6320. case "FIELD_TYPE":
  6321. $this->info->tempusercustomprofilefield->field_type = $this->getContents();
  6322. break;
  6323. case "FIELD_DATA":
  6324. $this->info->tempusercustomprofilefield->field_data = $this->getContents();
  6325. break;
  6326. default:
  6327. break;
  6328. }
  6329. /// If we are reading user_tags
  6330. } else if ($this->tree[6] == 'USER_TAG') {
  6331. switch ($tagName) {
  6332. case "NAME":
  6333. $this->info->tempusertag->name = $this->getContents();
  6334. break;
  6335. case "RAWNAME":
  6336. $this->info->tempusertag->rawname = $this->getContents();
  6337. break;
  6338. default:
  6339. break;
  6340. }
  6341. }
  6342. }
  6343. if ($this->tree[5] == "ROLES_ASSIGNMENTS") {
  6344. if ($this->level == 7) {
  6345. switch ($tagName) {
  6346. case "NAME":
  6347. $this->info->tempname = $this->getContents();
  6348. break;
  6349. case "SHORTNAME":
  6350. $this->info->tempshortname = $this->getContents();
  6351. break;
  6352. case "ID":
  6353. $this->info->tempid = $this->getContents(); // temp roleid
  6354. break;
  6355. }
  6356. }
  6357. if ($this->level == 9) {
  6358. switch ($tagName) {
  6359. case "USERID":
  6360. $this->info->tempuser->roleassignments[$this->info->tempid]->name = $this->info->tempname;
  6361. $this->info->tempuser->roleassignments[$this->info->tempid]->shortname = $this->info->tempshortname;
  6362. $this->info->tempuserid = $this->getContents();
  6363. $this->info->tempuser->roleassignments[$this->info->tempid]->assignments[$this->info->tempuserid]->userid = $this->getContents();
  6364. break;
  6365. case "HIDDEN":
  6366. $this->info->tempuser->roleassignments[$this->info->tempid]->assignments[$this->info->tempuserid]->hidden = $this->getContents();
  6367. break;
  6368. case "TIMESTART":
  6369. $this->info->tempuser->roleassignments[$this->info->tempid]->assignments[$this->info->tempuserid]->timestart = $this->getContents();
  6370. break;
  6371. case "TIMEEND":
  6372. $this->info->tempuser->roleassignments[$this->info->tempid]->assignments[$this->info->tempuserid]->timeend = $this->getContents();
  6373. break;
  6374. case "TIMEMODIFIED":
  6375. $this->info->tempuser->roleassignments[$this->info->tempid]->assignments[$this->info->tempuserid]->timemodified = $this->getContents();
  6376. break;
  6377. case "MODIFIERID":
  6378. $this->info->tempuser->roleassignments[$this->info->tempid]->assignments[$this->info->tempuserid]->modifierid = $this->getContents();
  6379. break;
  6380. case "ENROL":
  6381. $this->info->tempuser->roleassignments[$this->info->tempid]->assignments[$this->info->tempuserid]->enrol = $this->getContents();
  6382. break;
  6383. case "SORTORDER":
  6384. $this->info->tempuser->roleassignments[$this->info->tempid]->assignments[$this->info->tempuserid]->sortorder = $this->getContents();
  6385. break;
  6386. }
  6387. }
  6388. } /// ends role_assignments
  6389. if ($this->tree[5] == "ROLES_OVERRIDES") {
  6390. if ($this->level == 7) {
  6391. switch ($tagName) {
  6392. case "NAME":
  6393. $this->info->tempname = $this->getContents();
  6394. break;
  6395. case "SHORTNAME":
  6396. $this->info->tempshortname = $this->getContents();
  6397. break;
  6398. case "ID":
  6399. $this->info->tempid = $this->getContents(); // temp roleid
  6400. break;
  6401. }
  6402. }
  6403. if ($this->level == 9) {
  6404. switch ($tagName) {
  6405. case "NAME":
  6406. $this->info->tempuser->roleoverrides[$this->info->tempid]->name = $this->info->tempname;
  6407. $this->info->tempuser->roleoverrides[$this->info->tempid]->shortname = $this->info->tempshortname;
  6408. $this->info->tempname = $this->getContents(); // change to name of capability
  6409. $this->info->tempuser->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->name = $this->getContents();
  6410. break;
  6411. case "PERMISSION":
  6412. $this->info->tempuser->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->permission = $this->getContents();
  6413. break;
  6414. case "TIMEMODIFIED":
  6415. $this->info->tempuser->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->timemodified = $this->getContents();
  6416. break;
  6417. case "MODIFIERID":
  6418. $this->info->tempuser->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->modifierid = $this->getContents();
  6419. break;
  6420. }
  6421. }
  6422. } /// ends role_overrides
  6423. } // closes if this->tree[3]=="users"
  6424. //Stop parsing if todo = USERS and tagName = USERS (en of the tag, of course)
  6425. //Speed up a lot (avoid parse all)
  6426. if ($tagName == "USERS" and $this->level == 3) {
  6427. $this->finished = true;
  6428. $this->counter = 0;
  6429. }
  6430. //Clear things
  6431. $this->tree[$this->level] = "";
  6432. $this->level--;
  6433. $this->content = "";
  6434. }
  6435. //This is the endTag handler we use where we are reading the messages zone (todo="MESSAGES")
  6436. function endElementMessages($parser, $tagName) {
  6437. //Check if we are into MESSAGES zone
  6438. if ($this->tree[3] == "MESSAGES") {
  6439. //if (trim($this->content)) //Debug
  6440. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6441. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n";//Debug
  6442. //Acumulate data to info (content + close tag)
  6443. //Reconvert: strip htmlchars again and trim to generate xml data
  6444. if (!isset($this->temp)) {
  6445. $this->temp = "";
  6446. }
  6447. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6448. //If we've finished a message, xmlize it an save to db
  6449. if (($this->level == 4) and ($tagName == "MESSAGE")) {
  6450. //Prepend XML standard header to info gathered
  6451. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6452. //Call to xmlize for this portion of xml data (one MESSAGE)
  6453. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6454. $data = xmlize($xml_data,0);
  6455. //echo strftime ("%X",time())."<p>"; //Debug
  6456. //traverse_xmlize($data); //Debug
  6457. //print_object ($GLOBALS['traverse_array']); //Debug
  6458. //$GLOBALS['traverse_array']=""; //Debug
  6459. //Now, save data to db. We'll use it later
  6460. //Get id and status from data
  6461. $message_id = $data["MESSAGE"]["#"]["ID"]["0"]["#"];
  6462. $message_status = $data["MESSAGE"]["#"]["STATUS"]["0"]["#"];
  6463. if ($message_status == "READ") {
  6464. $table = "message_read";
  6465. } else {
  6466. $table = "message";
  6467. }
  6468. $this->counter++;
  6469. //Save to db
  6470. $status = backup_putid($this->preferences->backup_unique_code, $table,$message_id,
  6471. null,$data);
  6472. //Create returning info
  6473. $this->info = $this->counter;
  6474. //Reset temp
  6475. unset($this->temp);
  6476. }
  6477. //If we've finished a contact, xmlize it an save to db
  6478. if (($this->level == 5) and ($tagName == "CONTACT")) {
  6479. //Prepend XML standard header to info gathered
  6480. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6481. //Call to xmlize for this portion of xml data (one MESSAGE)
  6482. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6483. $data = xmlize($xml_data,0);
  6484. //echo strftime ("%X",time())."<p>"; //Debug
  6485. //traverse_xmlize($data); //Debug
  6486. //print_object ($GLOBALS['traverse_array']); //Debug
  6487. //$GLOBALS['traverse_array']=""; //Debug
  6488. //Now, save data to db. We'll use it later
  6489. //Get id and status from data
  6490. $contact_id = $data["CONTACT"]["#"]["ID"]["0"]["#"];
  6491. $this->counter++;
  6492. //Save to db
  6493. $status = backup_putid($this->preferences->backup_unique_code, 'message_contacts' ,$contact_id,
  6494. null,$data);
  6495. //Create returning info
  6496. $this->info = $this->counter;
  6497. //Reset temp
  6498. unset($this->temp);
  6499. }
  6500. }
  6501. //Stop parsing if todo = MESSAGES and tagName = MESSAGES (en of the tag, of course)
  6502. //Speed up a lot (avoid parse all)
  6503. if ($tagName == "MESSAGES" and $this->level == 3) {
  6504. $this->finished = true;
  6505. $this->counter = 0;
  6506. }
  6507. //Clear things
  6508. $this->tree[$this->level] = "";
  6509. $this->level--;
  6510. $this->content = "";
  6511. }
  6512. //This is the endTag handler we use where we are reading the blogs zone (todo="BLOGS")
  6513. function endElementBlogs($parser, $tagName) {
  6514. //Check if we are into BLOGS zone
  6515. if ($this->tree[3] == "BLOGS") {
  6516. //if (trim($this->content)) //Debug
  6517. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6518. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n";//Debug
  6519. //Acumulate data to info (content + close tag)
  6520. //Reconvert: strip htmlchars again and trim to generate xml data
  6521. if (!isset($this->temp)) {
  6522. $this->temp = "";
  6523. }
  6524. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6525. //If we've finished a blog, xmlize it an save to db
  6526. if (($this->level == 4) and ($tagName == "BLOG")) {
  6527. //Prepend XML standard header to info gathered
  6528. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6529. //Call to xmlize for this portion of xml data (one BLOG)
  6530. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6531. $data = xmlize($xml_data,0);
  6532. //echo strftime ("%X",time())."<p>"; //Debug
  6533. //traverse_xmlize($data); //Debug
  6534. //print_object ($GLOBALS['traverse_array']); //Debug
  6535. //$GLOBALS['traverse_array']=""; //Debug
  6536. //Now, save data to db. We'll use it later
  6537. //Get id from data
  6538. $blog_id = $data["BLOG"]["#"]["ID"]["0"]["#"];
  6539. $this->counter++;
  6540. //Save to db
  6541. $status = backup_putid($this->preferences->backup_unique_code, 'blog', $blog_id,
  6542. null,$data);
  6543. //Create returning info
  6544. $this->info = $this->counter;
  6545. //Reset temp
  6546. unset($this->temp);
  6547. }
  6548. }
  6549. //Stop parsing if todo = BLOGS and tagName = BLOGS (end of the tag, of course)
  6550. //Speed up a lot (avoid parse all)
  6551. if ($tagName == "BLOGS" and $this->level == 3) {
  6552. $this->finished = true;
  6553. $this->counter = 0;
  6554. }
  6555. //Clear things
  6556. $this->tree[$this->level] = "";
  6557. $this->level--;
  6558. $this->content = "";
  6559. }
  6560. //This is the endTag handler we use where we are reading the questions zone (todo="QUESTIONS")
  6561. function endElementQuestions($parser, $tagName) {
  6562. //Check if we are into QUESTION_CATEGORIES zone
  6563. if ($this->tree[3] == "QUESTION_CATEGORIES") {
  6564. //if (trim($this->content)) //Debug
  6565. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6566. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  6567. //Acumulate data to info (content + close tag)
  6568. //Reconvert: strip htmlchars again and trim to generate xml data
  6569. if (!isset($this->temp)) {
  6570. $this->temp = "";
  6571. }
  6572. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6573. //If we've finished a mod, xmlize it an save to db
  6574. if (($this->level == 4) and ($tagName == "QUESTION_CATEGORY")) {
  6575. //Prepend XML standard header to info gathered
  6576. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6577. //Call to xmlize for this portion of xml data (one QUESTION_CATEGORY)
  6578. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6579. $data = xmlize($xml_data,0);
  6580. //echo strftime ("%X",time())."<p>"; //Debug
  6581. //traverse_xmlize($data); //Debug
  6582. //print_object ($GLOBALS['traverse_array']); //Debug
  6583. //$GLOBALS['traverse_array']=""; //Debug
  6584. //Now, save data to db. We'll use it later
  6585. //Get id from data
  6586. $category_id = $data["QUESTION_CATEGORY"]["#"]["ID"]["0"]["#"];
  6587. //Save to db
  6588. $status = backup_putid($this->preferences->backup_unique_code,"question_categories",$category_id,
  6589. null,$data);
  6590. //Create returning info
  6591. $ret_info = new object();
  6592. $ret_info->id = $category_id;
  6593. $this->info[] = $ret_info;
  6594. //Reset temp
  6595. unset($this->temp);
  6596. }
  6597. }
  6598. //Stop parsing if todo = QUESTION_CATEGORIES and tagName = QUESTION_CATEGORY (en of the tag, of course)
  6599. //Speed up a lot (avoid parse all)
  6600. if ($tagName == "QUESTION_CATEGORIES" and $this->level == 3) {
  6601. $this->finished = true;
  6602. }
  6603. //Clear things
  6604. $this->tree[$this->level] = "";
  6605. $this->level--;
  6606. $this->content = "";
  6607. }
  6608. //This is the endTag handler we use where we are reading the scales zone (todo="SCALES")
  6609. function endElementScales($parser, $tagName) {
  6610. //Check if we are into SCALES zone
  6611. if ($this->tree[3] == "SCALES") {
  6612. //if (trim($this->content)) //Debug
  6613. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6614. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  6615. //Acumulate data to info (content + close tag)
  6616. //Reconvert: strip htmlchars again and trim to generate xml data
  6617. if (!isset($this->temp)) {
  6618. $this->temp = "";
  6619. }
  6620. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6621. //If we've finished a scale, xmlize it an save to db
  6622. if (($this->level == 4) and ($tagName == "SCALE")) {
  6623. //Prepend XML standard header to info gathered
  6624. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6625. //Call to xmlize for this portion of xml data (one SCALE)
  6626. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6627. $data = xmlize($xml_data,0);
  6628. //echo strftime ("%X",time())."<p>"; //Debug
  6629. //traverse_xmlize($data); //Debug
  6630. //print_object ($GLOBALS['traverse_array']); //Debug
  6631. //$GLOBALS['traverse_array']=""; //Debug
  6632. //Now, save data to db. We'll use it later
  6633. //Get id and from data
  6634. $scale_id = $data["SCALE"]["#"]["ID"]["0"]["#"];
  6635. //Save to db
  6636. $status = backup_putid($this->preferences->backup_unique_code,"scale",$scale_id,
  6637. null,$data);
  6638. //Create returning info
  6639. $ret_info = new object();
  6640. $ret_info->id = $scale_id;
  6641. $this->info[] = $ret_info;
  6642. //Reset temp
  6643. unset($this->temp);
  6644. }
  6645. }
  6646. //Stop parsing if todo = SCALES and tagName = SCALE (en of the tag, of course)
  6647. //Speed up a lot (avoid parse all)
  6648. if ($tagName == "SCALES" and $this->level == 3) {
  6649. $this->finished = true;
  6650. }
  6651. //Clear things
  6652. $this->tree[$this->level] = "";
  6653. $this->level--;
  6654. $this->content = "";
  6655. }
  6656. //This is the endTag handler we use where we are reading the groups zone (todo="GROUPS")
  6657. function endElementGroups($parser, $tagName) {
  6658. //Check if we are into GROUPS zone
  6659. if ($this->tree[3] == "GROUPS") {
  6660. //if (trim($this->content)) //Debug
  6661. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6662. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  6663. //Acumulate data to info (content + close tag)
  6664. //Reconvert: strip htmlchars again and trim to generate xml data
  6665. if (!isset($this->temp)) {
  6666. $this->temp = "";
  6667. }
  6668. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6669. //If we've finished a group, xmlize it an save to db
  6670. if (($this->level == 4) and ($tagName == "GROUP")) {
  6671. //Prepend XML standard header to info gathered
  6672. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6673. //Call to xmlize for this portion of xml data (one GROUP)
  6674. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6675. $data = xmlize($xml_data,0);
  6676. //echo strftime ("%X",time())."<p>"; //Debug
  6677. //traverse_xmlize($data); //Debug
  6678. //print_object ($GLOBALS['traverse_array']); //Debug
  6679. //$GLOBALS['traverse_array']=""; //Debug
  6680. //Now, save data to db. We'll use it later
  6681. //Get id and from data
  6682. $group_id = $data["GROUP"]["#"]["ID"]["0"]["#"];
  6683. //Save to db
  6684. $status = backup_putid($this->preferences->backup_unique_code,"groups",$group_id,
  6685. null,$data);
  6686. //Create returning info
  6687. $ret_info = new Object();
  6688. $ret_info->id = $group_id;
  6689. $this->info[] = $ret_info;
  6690. //Reset temp
  6691. unset($this->temp);
  6692. }
  6693. }
  6694. //Stop parsing if todo = GROUPS and tagName = GROUP (en of the tag, of course)
  6695. //Speed up a lot (avoid parse all)
  6696. if ($tagName == "GROUPS" and $this->level == 3) {
  6697. $this->finished = true;
  6698. }
  6699. //Clear things
  6700. $this->tree[$this->level] = "";
  6701. $this->level--;
  6702. $this->content = "";
  6703. }
  6704. //This is the endTag handler we use where we are reading the groupings zone (todo="GROUPINGS")
  6705. function endElementGroupings($parser, $tagName) {
  6706. //Check if we are into GROUPINGS zone
  6707. if ($this->tree[3] == "GROUPINGS") {
  6708. //Acumulate data to info (content + close tag)
  6709. //Reconvert: strip htmlchars again and trim to generate xml data
  6710. if (!isset($this->temp)) {
  6711. $this->temp = "";
  6712. }
  6713. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6714. //If we've finished a group, xmlize it an save to db
  6715. if (($this->level == 4) and ($tagName == "GROUPING")) {
  6716. //Prepend XML standard header to info gathered
  6717. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6718. //Call to xmlize for this portion of xml data (one GROUPING)
  6719. $data = xmlize($xml_data,0);
  6720. //Now, save data to db. We'll use it later
  6721. //Get id and from data
  6722. $grouping_id = $data["GROUPING"]["#"]["ID"]["0"]["#"];
  6723. //Save to db
  6724. $status = backup_putid($this->preferences->backup_unique_code,"groupings",$grouping_id,
  6725. null,$data);
  6726. //Create returning info
  6727. $ret_info = new Object();
  6728. $ret_info->id = $grouping_id;
  6729. $this->info[] = $ret_info;
  6730. //Reset temp
  6731. unset($this->temp);
  6732. }
  6733. }
  6734. //Stop parsing if todo = GROUPINGS and tagName = GROUPING (en of the tag, of course)
  6735. //Speed up a lot (avoid parse all)
  6736. if ($tagName == "GROUPINGS" and $this->level == 3) {
  6737. $this->finished = true;
  6738. }
  6739. //Clear things
  6740. $this->tree[$this->level] = "";
  6741. $this->level--;
  6742. $this->content = "";
  6743. }
  6744. //This is the endTag handler we use where we are reading the groupingsgroups zone (todo="GROUPINGGROUPS")
  6745. function endElementGroupingsGroups($parser, $tagName) {
  6746. //Check if we are into GROUPINGSGROUPS zone
  6747. if ($this->tree[3] == "GROUPINGSGROUPS") {
  6748. //Acumulate data to info (content + close tag)
  6749. //Reconvert: strip htmlchars again and trim to generate xml data
  6750. if (!isset($this->temp)) {
  6751. $this->temp = "";
  6752. }
  6753. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6754. //If we've finished a group, xmlize it an save to db
  6755. if (($this->level == 4) and ($tagName == "GROUPINGGROUP")) {
  6756. //Prepend XML standard header to info gathered
  6757. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6758. //Call to xmlize for this portion of xml data (one GROUPING)
  6759. $data = xmlize($xml_data,0);
  6760. //Now, save data to db. We'll use it later
  6761. //Get id and from data
  6762. $groupinggroup_id = $data["GROUPINGGROUP"]["#"]["ID"]["0"]["#"];
  6763. //Save to db
  6764. $status = backup_putid($this->preferences->backup_unique_code,"groupingsgroups",$groupinggroup_id,
  6765. null,$data);
  6766. //Create returning info
  6767. $ret_info = new Object();
  6768. $ret_info->id = $groupinggroup_id;
  6769. $this->info[] = $ret_info;
  6770. //Reset temp
  6771. unset($this->temp);
  6772. }
  6773. }
  6774. //Stop parsing if todo = GROUPINGS and tagName = GROUPING (en of the tag, of course)
  6775. //Speed up a lot (avoid parse all)
  6776. if ($tagName == "GROUPINGSGROUPS" and $this->level == 3) {
  6777. $this->finished = true;
  6778. }
  6779. //Clear things
  6780. $this->tree[$this->level] = "";
  6781. $this->level--;
  6782. $this->content = "";
  6783. }
  6784. //This is the endTag handler we use where we are reading the events zone (todo="EVENTS")
  6785. function endElementEvents($parser, $tagName) {
  6786. //Check if we are into EVENTS zone
  6787. if ($this->tree[3] == "EVENTS") {
  6788. //if (trim($this->content)) //Debug
  6789. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6790. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  6791. //Acumulate data to info (content + close tag)
  6792. //Reconvert: strip htmlchars again and trim to generate xml data
  6793. if (!isset($this->temp)) {
  6794. $this->temp = "";
  6795. }
  6796. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6797. //If we've finished a event, xmlize it an save to db
  6798. if (($this->level == 4) and ($tagName == "EVENT")) {
  6799. //Prepend XML standard header to info gathered
  6800. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6801. //Call to xmlize for this portion of xml data (one EVENT)
  6802. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6803. $data = xmlize($xml_data,0);
  6804. //echo strftime ("%X",time())."<p>"; //Debug
  6805. //traverse_xmlize($data); //Debug
  6806. //print_object ($GLOBALS['traverse_array']); //Debug
  6807. //$GLOBALS['traverse_array']=""; //Debug
  6808. //Now, save data to db. We'll use it later
  6809. //Get id and from data
  6810. $event_id = $data["EVENT"]["#"]["ID"]["0"]["#"];
  6811. //Save to db
  6812. $status = backup_putid($this->preferences->backup_unique_code,"event",$event_id,
  6813. null,$data);
  6814. //Create returning info
  6815. $ret_info = new object();
  6816. $ret_info->id = $event_id;
  6817. $this->info[] = $ret_info;
  6818. //Reset temp
  6819. unset($this->temp);
  6820. }
  6821. }
  6822. //Stop parsing if todo = EVENTS and tagName = EVENT (en of the tag, of course)
  6823. //Speed up a lot (avoid parse all)
  6824. if ($tagName == "EVENTS" and $this->level == 3) {
  6825. $this->finished = true;
  6826. }
  6827. //Clear things
  6828. $this->tree[$this->level] = "";
  6829. $this->level--;
  6830. $this->content = "";
  6831. }
  6832. //This is the endTag handler we use where we are reading the modules zone (todo="MODULES")
  6833. function endElementModules($parser, $tagName) {
  6834. //Check if we are into MODULES zone
  6835. if ($this->tree[3] == "MODULES") {
  6836. //if (trim($this->content)) //Debug
  6837. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6838. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  6839. //Acumulate data to info (content + close tag)
  6840. //Reconvert: strip htmlchars again and trim to generate xml data
  6841. if (!isset($this->temp)) {
  6842. $this->temp = "";
  6843. }
  6844. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6845. //If we've finished a mod, xmlize it an save to db
  6846. if (($this->level == 4) and ($tagName == "MOD")) {
  6847. //Only process the module if efectively it has been selected for restore. MDL-18482
  6848. if (empty($this->preferences->mods[$this->temp_mod_type]->granular) // We don't care about per instance, i.e. restore all instances.
  6849. or (array_key_exists($this->temp_mod_id, $this->preferences->mods[$this->temp_mod_type]->instances)
  6850. and
  6851. !empty($this->preferences->mods[$this->temp_mod_type]->instances[$this->temp_mod_id]->restore))) {
  6852. //Prepend XML standard header to info gathered
  6853. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6854. //Call to xmlize for this portion of xml data (one MOD)
  6855. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6856. $data = xmlize($xml_data,0);
  6857. //echo strftime ("%X",time())."<p>"; //Debug
  6858. //traverse_xmlize($data); //Debug
  6859. //print_object ($GLOBALS['traverse_array']); //Debug
  6860. //$GLOBALS['traverse_array']=""; //Debug
  6861. //Now, save data to db. We'll use it later
  6862. //Get id and modtype from data
  6863. $mod_id = $data["MOD"]["#"]["ID"]["0"]["#"];
  6864. $mod_type = $data["MOD"]["#"]["MODTYPE"]["0"]["#"];
  6865. //Only if we've selected to restore it
  6866. if (!empty($this->preferences->mods[$mod_type]->restore)) {
  6867. //Save to db
  6868. $status = backup_putid($this->preferences->backup_unique_code,$mod_type,$mod_id,
  6869. null,$data);
  6870. //echo "<p>id: ".$mod_id."-".$mod_type." len.: ".strlen($sla_mod_temp)." to_db: ".$status."<p>"; //Debug
  6871. //Create returning info
  6872. $ret_info = new object();
  6873. $ret_info->id = $mod_id;
  6874. $ret_info->modtype = $mod_type;
  6875. $this->info[] = $ret_info;
  6876. }
  6877. } else {
  6878. debugging("Info: skipping $this->temp_mod_type activity with mod id: $this->temp_mod_id. Not selected for restore", DEBUG_DEVELOPER);
  6879. }
  6880. //Reset current mod_type and mod_id
  6881. unset($this->temp_mod_type);
  6882. unset($this->temp_mod_id);
  6883. //Reset temp
  6884. unset($this->temp);
  6885. }
  6886. /// Grab current mod id and type when available
  6887. if ($this->level == 5) {
  6888. if ($tagName == 'ID') {
  6889. $this->temp_mod_id = trim($this->content);
  6890. } else if ($tagName == 'MODTYPE') {
  6891. $this->temp_mod_type = trim($this->content);
  6892. }
  6893. }
  6894. }
  6895. //Stop parsing if todo = MODULES and tagName = MODULES (en of the tag, of course)
  6896. //Speed up a lot (avoid parse all)
  6897. if ($tagName == "MODULES" and $this->level == 3) {
  6898. $this->finished = true;
  6899. }
  6900. //Clear things
  6901. $this->tree[$this->level] = "";
  6902. $this->level--;
  6903. $this->content = "";
  6904. }
  6905. //This is the endTag handler we use where we are reading the logs zone (todo="LOGS")
  6906. function endElementLogs($parser, $tagName) {
  6907. //Check if we are into LOGS zone
  6908. if ($this->tree[3] == "LOGS") {
  6909. //if (trim($this->content)) //Debug
  6910. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6911. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  6912. //Acumulate data to info (content + close tag)
  6913. //Reconvert: strip htmlchars again and trim to generate xml data
  6914. if (!isset($this->temp)) {
  6915. $this->temp = "";
  6916. }
  6917. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6918. //If we've finished a log, xmlize it an save to db
  6919. if (($this->level == 4) and ($tagName == "LOG")) {
  6920. //Prepend XML standard header to info gathered
  6921. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6922. //Call to xmlize for this portion of xml data (one LOG)
  6923. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6924. $data = xmlize($xml_data,0);
  6925. //echo strftime ("%X",time())."<p>"; //Debug
  6926. //traverse_xmlize($data); //Debug
  6927. //print_object ($GLOBALS['traverse_array']); //Debug
  6928. //$GLOBALS['traverse_array']=""; //Debug
  6929. //Now, save data to db. We'll use it later
  6930. //Get id and modtype from data
  6931. $log_id = $data["LOG"]["#"]["ID"]["0"]["#"];
  6932. $log_module = $data["LOG"]["#"]["MODULE"]["0"]["#"];
  6933. //We only save log entries from backup file if they are:
  6934. // - Course logs
  6935. // - User logs
  6936. // - Module logs about one restored module
  6937. if ($log_module == "course" or
  6938. $log_module == "user" or
  6939. $this->preferences->mods[$log_module]->restore) {
  6940. //Increment counter
  6941. $this->counter++;
  6942. //Save to db
  6943. $status = backup_putid($this->preferences->backup_unique_code,"log",$log_id,
  6944. null,$data);
  6945. //echo "<p>id: ".$mod_id."-".$mod_type." len.: ".strlen($sla_mod_temp)." to_db: ".$status."<p>"; //Debug
  6946. //Create returning info
  6947. $this->info = $this->counter;
  6948. }
  6949. //Reset temp
  6950. unset($this->temp);
  6951. }
  6952. }
  6953. //Stop parsing if todo = LOGS and tagName = LOGS (en of the tag, of course)
  6954. //Speed up a lot (avoid parse all)
  6955. if ($tagName == "LOGS" and $this->level == 3) {
  6956. $this->finished = true;
  6957. $this->counter = 0;
  6958. }
  6959. //Clear things
  6960. $this->tree[$this->level] = "";
  6961. $this->level--;
  6962. $this->content = "";
  6963. }
  6964. //This is the endTag default handler we use when todo is undefined
  6965. function endElement($parser, $tagName) {
  6966. if (trim($this->content)) //Debug
  6967. echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6968. echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  6969. //Clear things
  6970. $this->tree[$this->level] = "";
  6971. $this->level--;
  6972. $this->content = "";
  6973. }
  6974. //This is the handler to read data contents (simple accumule it)
  6975. function characterData($parser, $data) {
  6976. $this->content .= $data;
  6977. }
  6978. }
  6979. //This function executes the MoodleParser
  6980. function restore_read_xml ($xml_file,$todo,$preferences) {
  6981. global $CFG;
  6982. $status = true;
  6983. /// If enabled in the site, use split files instead of original moodle.xml file
  6984. /// This will speed parsing speed upto 20x.
  6985. if (!empty($CFG->experimentalsplitrestore)) {
  6986. /// Use splite file, else nothing to process (saves one full parsing for each non-existing todo)
  6987. $splitfile= dirname($xml_file) . '/' . strtolower('split_' . $todo . '.xml');
  6988. if (file_exists($splitfile)) {
  6989. $xml_file = $splitfile;
  6990. debugging("Info: todo=$todo, using split file", DEBUG_DEVELOPER);
  6991. } else {
  6992. /// For some todos, that are used in earlier restore steps (restore_precheck(), restore_form...
  6993. /// allow fallback to monolithic moodle.xml. Those todos are at the beggining of the xml, so
  6994. /// it doesn't hurts too much.
  6995. if ($todo == 'INFO' || $todo == 'COURSE_HEADER' || $todo == 'ROLES') {
  6996. debugging("Info: todo=$todo, no split file. Fallback to moodle.xml", DEBUG_DEVELOPER);
  6997. } else {
  6998. debugging("Info: todo=$todo, no split file. Parse skipped", DEBUG_DEVELOPER);
  6999. return true;
  7000. }
  7001. }
  7002. }
  7003. $xml_parser = xml_parser_create('UTF-8');
  7004. $moodle_parser = new MoodleParser();
  7005. $moodle_parser->todo = $todo;
  7006. $moodle_parser->preferences = $preferences;
  7007. xml_set_object($xml_parser,$moodle_parser);
  7008. //Depending of the todo we use some element_handler or another
  7009. if ($todo == "INFO") {
  7010. xml_set_element_handler($xml_parser, "startElementInfo", "endElementInfo");
  7011. } else if ($todo == "ROLES") {
  7012. xml_set_element_handler($xml_parser, "startElementRoles", "endElementRoles");
  7013. } else if ($todo == "COURSE_HEADER") {
  7014. xml_set_element_handler($xml_parser, "startElementCourseHeader", "endElementCourseHeader");
  7015. } else if ($todo == 'BLOCKS') {
  7016. xml_set_element_handler($xml_parser, "startElementBlocks", "endElementBlocks");
  7017. } else if ($todo == "SECTIONS") {
  7018. xml_set_element_handler($xml_parser, "startElementSections", "endElementSections");
  7019. } else if ($todo == 'FORMATDATA') {
  7020. xml_set_element_handler($xml_parser, "startElementFormatData", "endElementFormatData");
  7021. } else if ($todo == "METACOURSE") {
  7022. xml_set_element_handler($xml_parser, "startElementMetacourse", "endElementMetacourse");
  7023. } else if ($todo == "GRADEBOOK") {
  7024. if ($preferences->backup_version > 2007090500) {
  7025. xml_set_element_handler($xml_parser, "startElementGradebook", "endElementGradebook");
  7026. } else {
  7027. xml_set_element_handler($xml_parser, "startElementOldGradebook", "endElementOldGradebook");
  7028. }
  7029. } else if ($todo == "USERS") {
  7030. xml_set_element_handler($xml_parser, "startElementUsers", "endElementUsers");
  7031. } else if ($todo == "MESSAGES") {
  7032. xml_set_element_handler($xml_parser, "startElementMessages", "endElementMessages");
  7033. } else if ($todo == "BLOGS") {
  7034. xml_set_element_handler($xml_parser, "startElementBlogs", "endElementBlogs");
  7035. } else if ($todo == "QUESTIONS") {
  7036. xml_set_element_handler($xml_parser, "startElementQuestions", "endElementQuestions");
  7037. } else if ($todo == "SCALES") {
  7038. xml_set_element_handler($xml_parser, "startElementScales", "endElementScales");
  7039. } else if ($todo == "GROUPS") {
  7040. xml_set_element_handler($xml_parser, "startElementGroups", "endElementGroups");
  7041. } else if ($todo == "GROUPINGS") {
  7042. xml_set_element_handler($xml_parser, "startElementGroupings", "endElementGroupings");
  7043. } else if ($todo == "GROUPINGSGROUPS") {
  7044. xml_set_element_handler($xml_parser, "startElementGroupingsGroups", "endElementGroupingsGroups");
  7045. } else if ($todo == "EVENTS") {
  7046. xml_set_element_handler($xml_parser, "startElementEvents", "endElementEvents");
  7047. } else if ($todo == "MODULES") {
  7048. xml_set_element_handler($xml_parser, "startElementModules", "endElementModules");
  7049. } else if ($todo == "LOGS") {
  7050. xml_set_element_handler($xml_parser, "startElementLogs", "endElementLogs");
  7051. } else {
  7052. //Define default handlers (must no be invoked when everything become finished)
  7053. xml_set_element_handler($xml_parser, "startElementInfo", "endElementInfo");
  7054. }
  7055. xml_set_character_data_handler($xml_parser, "characterData");
  7056. $fp = fopen($xml_file,"r")
  7057. or $status = false;
  7058. if ($status) {
  7059. // MDL-9290 performance improvement on reading large xml
  7060. $lasttime = time(); // crmas
  7061. while ($data = fread($fp, 8192) and !$moodle_parser->finished) {
  7062. if ((time() - $lasttime) > 5) {
  7063. $lasttime = time();
  7064. backup_flush(1);
  7065. }
  7066. xml_parse($xml_parser, $data, feof($fp))
  7067. or die(sprintf("XML error: %s at line %d",
  7068. xml_error_string(xml_get_error_code($xml_parser)),
  7069. xml_get_current_line_number($xml_parser)));
  7070. }
  7071. fclose($fp);
  7072. }
  7073. //Get info from parser
  7074. $info = $moodle_parser->info;
  7075. //Clear parser mem
  7076. xml_parser_free($xml_parser);
  7077. if ($status && !empty($info)) {
  7078. return $info;
  7079. } else {
  7080. return $status;
  7081. }
  7082. }
  7083. /**
  7084. * @param string $errorstr passed by reference, if silent is true,
  7085. * errorstr will be populated and this function will return false rather than calling error() or notify()
  7086. * @param boolean $noredirect (optional) if this is passed, this function will not print continue, or
  7087. * redirect to the next step in the restore process, instead will return $backup_unique_code
  7088. */
  7089. function restore_precheck($id,$file,&$errorstr,$noredirect=false) {
  7090. global $CFG, $SESSION;
  7091. //Prepend dataroot to variable to have the absolute path
  7092. $file = $CFG->dataroot."/".$file;
  7093. if (!defined('RESTORE_SILENTLY')) {
  7094. //Start the main table
  7095. echo "<table cellpadding=\"5\">";
  7096. echo "<tr><td>";
  7097. //Start the mail ul
  7098. echo "<ul>";
  7099. }
  7100. //Check the file exists
  7101. if (!is_file($file)) {
  7102. if (!defined('RESTORE_SILENTLY')) {
  7103. error ("File not exists ($file)");
  7104. } else {
  7105. $errorstr = "File not exists ($file)";
  7106. return false;
  7107. }
  7108. }
  7109. //Check the file name ends with .zip
  7110. if (!substr($file,-4) == ".zip") {
  7111. if (!defined('RESTORE_SILENTLY')) {
  7112. error ("File has an incorrect extension");
  7113. } else {
  7114. $errorstr = 'File has an incorrect extension';
  7115. return false;
  7116. }
  7117. }
  7118. //Now calculate the unique_code for this restore
  7119. $backup_unique_code = time();
  7120. //Now check and create the backup dir (if it doesn't exist)
  7121. if (!defined('RESTORE_SILENTLY')) {
  7122. echo "<li>".get_string("creatingtemporarystructures").'</li>';
  7123. }
  7124. $status = check_and_create_backup_dir($backup_unique_code);
  7125. //Empty dir
  7126. if ($status) {
  7127. $status = clear_backup_dir($backup_unique_code);
  7128. }
  7129. //Now delete old data and directories under dataroot/temp/backup
  7130. if ($status) {
  7131. if (!defined('RESTORE_SILENTLY')) {
  7132. echo "<li>".get_string("deletingolddata").'</li>';
  7133. }
  7134. $status = backup_delete_old_data();
  7135. }
  7136. //Now copy he zip file to dataroot/temp/backup/backup_unique_code
  7137. if ($status) {
  7138. if (!defined('RESTORE_SILENTLY')) {
  7139. echo "<li>".get_string("copyingzipfile").'</li>';
  7140. }
  7141. if (! $status = backup_copy_file($file,$CFG->dataroot."/temp/backup/".$backup_unique_code."/".basename($file))) {
  7142. if (!defined('RESTORE_SILENTLY')) {
  7143. notify("Error copying backup file. Invalid name or bad perms.");
  7144. } else {
  7145. $errorstr = "Error copying backup file. Invalid name or bad perms";
  7146. return false;
  7147. }
  7148. }
  7149. }
  7150. //Now unzip the file
  7151. if ($status) {
  7152. if (!defined('RESTORE_SILENTLY')) {
  7153. echo "<li>".get_string("unzippingbackup").'</li>';
  7154. }
  7155. if (! $status = restore_unzip ($CFG->dataroot."/temp/backup/".$backup_unique_code."/".basename($file))) {
  7156. if (!defined('RESTORE_SILENTLY')) {
  7157. notify("Error unzipping backup file. Invalid zip file.");
  7158. } else {
  7159. $errorstr = "Error unzipping backup file. Invalid zip file.";
  7160. return false;
  7161. }
  7162. }
  7163. }
  7164. // If experimental option is enabled (enableimsccimport)
  7165. // check for Common Cartridge packages and convert to Moodle format
  7166. if ($status && isset($CFG->enableimsccimport) && $CFG->enableimsccimport == 1) {
  7167. require_once($CFG->dirroot. '/backup/cc/restore_cc.php');
  7168. if (!defined('RESTORE_SILENTLY')) {
  7169. echo "<li>".get_string('checkingforimscc', 'imscc').'</li>';
  7170. }
  7171. $status = cc_convert($CFG->dataroot. DIRECTORY_SEPARATOR .'temp'. DIRECTORY_SEPARATOR . 'backup'. DIRECTORY_SEPARATOR . $backup_unique_code);
  7172. }
  7173. //Check for Blackboard backups and convert
  7174. if ($status){
  7175. require_once("$CFG->dirroot/backup/bb/restore_bb.php");
  7176. if (!defined('RESTORE_SILENTLY')) {
  7177. echo "<li>".get_string("checkingforbbexport").'</li>';
  7178. }
  7179. $status = blackboard_convert($CFG->dataroot."/temp/backup/".$backup_unique_code);
  7180. }
  7181. //Now check for the moodle.xml file
  7182. if ($status) {
  7183. $xml_file = $CFG->dataroot."/temp/backup/".$backup_unique_code."/moodle.xml";
  7184. if (!defined('RESTORE_SILENTLY')) {
  7185. echo "<li>".get_string("checkingbackup").'</li>';
  7186. }
  7187. if (! $status = restore_check_moodle_file ($xml_file)) {
  7188. if (!is_file($xml_file)) {
  7189. $errorstr = 'Error checking backup file. moodle.xml not found at root level of zip file.';
  7190. } else {
  7191. $errorstr = 'Error checking backup file. moodle.xml is incorrect or corrupted.';
  7192. }
  7193. if (!defined('RESTORE_SILENTLY')) {
  7194. notify($errorstr);
  7195. } else {
  7196. return false;
  7197. }
  7198. }
  7199. }
  7200. $info = "";
  7201. $course_header = "";
  7202. //Now read the info tag (all)
  7203. if ($status) {
  7204. if (!defined('RESTORE_SILENTLY')) {
  7205. echo "<li>".get_string("readinginfofrombackup").'</li>';
  7206. }
  7207. //Reading info from file
  7208. $info = restore_read_xml_info ($xml_file);
  7209. //Reading course_header from file
  7210. $course_header = restore_read_xml_course_header ($xml_file);
  7211. if(!is_object($course_header)){
  7212. // ensure we fail if there is no course header
  7213. $course_header = false;
  7214. }
  7215. }
  7216. if (!defined('RESTORE_SILENTLY')) {
  7217. //End the main ul
  7218. echo "</ul>\n";
  7219. //End the main table
  7220. echo "</td></tr>";
  7221. echo "</table>";
  7222. }
  7223. //We compare Moodle's versions
  7224. if ($status && $CFG->version < $info->backup_moodle_version) {
  7225. $message = new object();
  7226. $message->serverversion = $CFG->version;
  7227. $message->serverrelease = $CFG->release;
  7228. $message->backupversion = $info->backup_moodle_version;
  7229. $message->backuprelease = $info->backup_moodle_release;
  7230. print_simple_box(get_string('noticenewerbackup','',$message), "center", "70%", '', "20", "noticebox");
  7231. }
  7232. //Now we print in other table, the backup and the course it contains info
  7233. if ($info and $course_header and $status) {
  7234. //First, the course info
  7235. if (!defined('RESTORE_SILENTLY')) {
  7236. $status = restore_print_course_header($course_header);
  7237. }
  7238. //Now, the backup info
  7239. if ($status) {
  7240. if (!defined('RESTORE_SILENTLY')) {
  7241. $status = restore_print_info($info);
  7242. }
  7243. }
  7244. }
  7245. //Save course header and info into php session
  7246. if ($status) {
  7247. $SESSION->info = $info;
  7248. $SESSION->course_header = $course_header;
  7249. }
  7250. //Finally, a little form to continue
  7251. //with some hidden fields
  7252. if ($status) {
  7253. if (!defined('RESTORE_SILENTLY')) {
  7254. echo "<br /><div style='text-align:center'>";
  7255. $hidden["backup_unique_code"] = $backup_unique_code;
  7256. $hidden["launch"] = "form";
  7257. $hidden["file"] = $file;
  7258. $hidden["id"] = $id;
  7259. print_single_button("restore.php", $hidden, get_string("continue"),"post");
  7260. echo "</div>";
  7261. }
  7262. else {
  7263. if (empty($noredirect)) {
  7264. print_continue($CFG->wwwroot.'/backup/restore.php?backup_unique_code='.$backup_unique_code.'&launch=form&file='.$file.'&id='.$id.'&sesskey='.sesskey());
  7265. print_footer();
  7266. die;
  7267. } else {
  7268. return $backup_unique_code;
  7269. }
  7270. }
  7271. }
  7272. if (!$status) {
  7273. if (!defined('RESTORE_SILENTLY')) {
  7274. error ("An error has ocurred");
  7275. } else {
  7276. $errorstr = "An error has occured"; // helpful! :P
  7277. return false;
  7278. }
  7279. }
  7280. return true;
  7281. }
  7282. function restore_setup_for_check(&$restore,$backup_unique_code) {
  7283. global $SESSION;
  7284. $restore->backup_unique_code=$backup_unique_code;
  7285. $restore->users = 2; // yuk
  7286. // we set these from restore object on silent restore and from info (backup) object on import
  7287. $restore->course_files = isset($SESSION->restore->restore_course_files) ? $SESSION->restore->restore_course_files : $SESSION->info->backup_course_files;
  7288. $restore->site_files = isset($SESSION->restore->restore_site_files) ? $SESSION->restore->restore_site_files : $SESSION->info->backup_site_files;
  7289. if ($allmods = get_records("modules")) {
  7290. foreach ($allmods as $mod) {
  7291. $modname = $mod->name;
  7292. $var = "restore_".$modname;
  7293. //Now check that we have that module info in the backup file
  7294. if (isset($SESSION->info->mods[$modname]) && $SESSION->info->mods[$modname]->backup == "true") {
  7295. $restore->$var = 1;
  7296. }
  7297. }
  7298. }
  7299. // Calculate all session objects checksum and store them in session too
  7300. // so restore_execute.html (used by manual restore and import) will be
  7301. // able to detect any problem in session info.
  7302. restore_save_session_object_checksums($restore, $SESSION->info, $SESSION->course_header);
  7303. return true;
  7304. }
  7305. /**
  7306. * Save the checksum of the 3 main in-session restore objects (restore, info, course_header)
  7307. * so restore_execute.html will be able to check that all them have arrived correctly, without
  7308. * losing data for any type of session size limit/error. MDL-18469. Used both by manual restore
  7309. * and import
  7310. */
  7311. function restore_save_session_object_checksums($restore, $info, $course_header) {
  7312. global $SESSION;
  7313. $restore_checksums = array();
  7314. $restore_checksums['info'] = md5(serialize($info));
  7315. $restore_checksums['course_header'] = md5(serialize($course_header));
  7316. $restore_checksums['restore'] = md5(serialize($restore));
  7317. $SESSION->restore_checksums = $restore_checksums;
  7318. }
  7319. function backup_to_restore_array($backup,$k=0) {
  7320. if (is_array($backup) ) {
  7321. $restore = array();
  7322. foreach ($backup as $key => $value) {
  7323. $newkey = str_replace('backup','restore',$key);
  7324. $restore[$newkey] = backup_to_restore_array($value,$key);
  7325. }
  7326. }
  7327. else if (is_object($backup)) {
  7328. $restore = new stdClass();
  7329. $tmp = get_object_vars($backup);
  7330. foreach ($tmp as $key => $value) {
  7331. $newkey = str_replace('backup','restore',$key);
  7332. $restore->$newkey = backup_to_restore_array($value,$key);
  7333. }
  7334. }
  7335. else {
  7336. $newkey = str_replace('backup','restore',$k);
  7337. $restore = $backup;
  7338. }
  7339. return $restore;
  7340. }
  7341. /**
  7342. * compatibility function
  7343. * checks for per-instance backups AND
  7344. * older per-module backups
  7345. * and returns whether userdata has been selected.
  7346. */
  7347. function restore_userdata_selected($restore,$modname,$modid) {
  7348. // check first for per instance array
  7349. if (!empty($restore->mods[$modname]->granular)) { // supports per instance
  7350. return array_key_exists($modid,$restore->mods[$modname]->instances)
  7351. && !empty($restore->mods[$modname]->instances[$modid]->userinfo);
  7352. }
  7353. //print_object($restore->mods[$modname]);
  7354. return !empty($restore->mods[$modname]->userinfo);
  7355. }
  7356. function restore_execute(&$restore,$info,$course_header,&$errorstr) {
  7357. global $CFG, $USER;
  7358. $status = true;
  7359. //Checks for the required files/functions to restore every module
  7360. //and include them
  7361. if ($allmods = get_records("modules") ) {
  7362. foreach ($allmods as $mod) {
  7363. $modname = $mod->name;
  7364. $modfile = "$CFG->dirroot/mod/$modname/restorelib.php";
  7365. //If file exists and we have selected to restore that type of module
  7366. if ((file_exists($modfile)) and !empty($restore->mods[$modname]) and ($restore->mods[$modname]->restore)) {
  7367. include_once($modfile);
  7368. }
  7369. }
  7370. }
  7371. if (!defined('RESTORE_SILENTLY')) {
  7372. //Start the main table
  7373. echo "<table cellpadding=\"5\">";
  7374. echo "<tr><td>";
  7375. //Start the main ul
  7376. echo "<ul>";
  7377. }
  7378. //Location of the xml file
  7379. $xml_file = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/moodle.xml";
  7380. // Re-assure xml file is in place before any further process
  7381. if (! $status = restore_check_moodle_file($xml_file)) {
  7382. if (!is_file($xml_file)) {
  7383. $errorstr = 'Error checking backup file. moodle.xml not found. Session problem?';
  7384. } else {
  7385. $errorstr = 'Error checking backup file. moodle.xml is incorrect or corrupted. Session problem?';
  7386. }
  7387. if (!defined('RESTORE_SILENTLY')) {
  7388. notify($errorstr);
  7389. }
  7390. return false;
  7391. }
  7392. //Preprocess the moodle.xml file spliting into smaller chucks (modules, users, logs...)
  7393. //for optimal parsing later in the restore process.
  7394. if (!empty($CFG->experimentalsplitrestore)) {
  7395. if (!defined('RESTORE_SILENTLY')) {
  7396. echo '<li>'.get_string('preprocessingbackupfile') . '</li>';
  7397. }
  7398. //First of all, split moodle.xml into handy files
  7399. if (!restore_split_xml ($xml_file, $restore)) {
  7400. $errorstr = "Error proccessing moodle.xml file. Process ended.";
  7401. if (!defined('RESTORE_SILENTLY')) {
  7402. notify($errorstr);
  7403. }
  7404. return false;
  7405. }
  7406. }
  7407. // Precheck the users section, detecting various situations that can lead to problems, so
  7408. // we stop restore before performing any further action
  7409. if (!defined('RESTORE_SILENTLY')) {
  7410. echo '<li>'.get_string('restoreusersprecheck').'</li>';
  7411. }
  7412. if (!restore_precheck_users($xml_file, $restore, $problems)) {
  7413. $errorstr = get_string('restoreusersprecheckerror');
  7414. if (!empty($problems)) {
  7415. $errorstr .= ' (' . implode(', ', $problems) . ')';
  7416. }
  7417. if (!defined('RESTORE_SILENTLY')) {
  7418. notify($errorstr);
  7419. }
  7420. return false;
  7421. }
  7422. //If we've selected to restore into new course
  7423. //create it (course)
  7424. //Saving conversion id variables into backup_tables
  7425. if ($restore->restoreto == RESTORETO_NEW_COURSE) {
  7426. if (!defined('RESTORE_SILENTLY')) {
  7427. echo '<li>'.get_string('creatingnewcourse') . '</li>';
  7428. }
  7429. $oldidnumber = $course_header->course_idnumber;
  7430. if (!$status = restore_create_new_course($restore,$course_header)) {
  7431. if (!defined('RESTORE_SILENTLY')) {
  7432. notify("Error while creating the new empty course.");
  7433. } else {
  7434. $errorstr = "Error while creating the new empty course.";
  7435. return false;
  7436. }
  7437. }
  7438. //Print course fullname and shortname and category
  7439. if ($status) {
  7440. if (!defined('RESTORE_SILENTLY')) {
  7441. echo "<ul>";
  7442. echo "<li>".$course_header->course_fullname." (".$course_header->course_shortname.")".'</li>';
  7443. echo "<li>".get_string("category").": ".$course_header->category->name.'</li>';
  7444. if (!empty($oldidnumber)) {
  7445. echo "<li>".get_string("nomoreidnumber","moodle",$oldidnumber)."</li>";
  7446. }
  7447. echo "</ul>";
  7448. //Put the destination course_id
  7449. }
  7450. $restore->course_id = $course_header->course_id;
  7451. }
  7452. if ($status = restore_open_html($restore,$course_header)){
  7453. if (!defined('RESTORE_SILENTLY')) {
  7454. echo "<li>Creating the Restorelog.html in the course backup folder</li>";
  7455. }
  7456. }
  7457. } else {
  7458. $course = get_record("course","id",$restore->course_id);
  7459. if ($course) {
  7460. if (!defined('RESTORE_SILENTLY')) {
  7461. echo "<li>".get_string("usingexistingcourse");
  7462. echo "<ul>";
  7463. echo "<li>".get_string("from").": ".$course_header->course_fullname." (".$course_header->course_shortname.")".'</li>';
  7464. echo "<li>".get_string("to").": ". format_string($course->fullname) ." (".format_string($course->shortname).")".'</li>';
  7465. if (($restore->deleting)) {
  7466. echo "<li>".get_string("deletingexistingcoursedata").'</li>';
  7467. } else {
  7468. echo "<li>".get_string("addingdatatoexisting").'</li>';
  7469. }
  7470. echo "</ul></li>";
  7471. }
  7472. //If we have selected to restore deleting, we do it now.
  7473. if ($restore->deleting) {
  7474. if (!defined('RESTORE_SILENTLY')) {
  7475. echo "<li>".get_string("deletingolddata").'</li>';
  7476. }
  7477. $status = remove_course_contents($restore->course_id,false) and
  7478. delete_dir_contents($CFG->dataroot."/".$restore->course_id,"backupdata");
  7479. if ($status) {
  7480. //Now , this situation is equivalent to the "restore to new course" one (we
  7481. //have a course record and nothing more), so define it as "to new course"
  7482. $restore->restoreto = RESTORETO_NEW_COURSE;
  7483. } else {
  7484. if (!defined('RESTORE_SILENTLY')) {
  7485. notify("An error occurred while deleting some of the course contents.");
  7486. } else {
  7487. $errrostr = "An error occurred while deleting some of the course contents.";
  7488. return false;
  7489. }
  7490. }
  7491. }
  7492. } else {
  7493. if (!defined('RESTORE_SILENTLY')) {
  7494. notify("Error opening existing course.");
  7495. $status = false;
  7496. } else {
  7497. $errorstr = "Error opening existing course.";
  7498. return false;
  7499. }
  7500. }
  7501. }
  7502. //Now create users as needed
  7503. if ($status and ($restore->users == 0 or $restore->users == 1)) {
  7504. if (!defined('RESTORE_SILENTLY')) {
  7505. echo "<li>".get_string("creatingusers")."<br />";
  7506. }
  7507. if (!$status = restore_create_users($restore,$xml_file)) {
  7508. if (!defined('RESTORE_SILENTLY')) {
  7509. notify("Could not restore users.");
  7510. } else {
  7511. $errorstr = "Could not restore users.";
  7512. return false;
  7513. }
  7514. }
  7515. //Now print info about the work done
  7516. if ($status) {
  7517. $recs = get_records_sql("select old_id, new_id from {$CFG->prefix}backup_ids
  7518. where backup_code = '$restore->backup_unique_code' and
  7519. table_name = 'user'");
  7520. //We've records
  7521. if ($recs) {
  7522. $new_count = 0;
  7523. $exists_count = 0;
  7524. $student_count = 0;
  7525. $teacher_count = 0;
  7526. $counter = 0;
  7527. //Iterate, filling counters
  7528. foreach ($recs as $rec) {
  7529. //Get full record, using backup_getids
  7530. $record = backup_getid($restore->backup_unique_code,"user",$rec->old_id);
  7531. if (strpos($record->info,"new") !== false) {
  7532. $new_count++;
  7533. }
  7534. if (strpos($record->info,"exists") !== false) {
  7535. $exists_count++;
  7536. }
  7537. if (strpos($record->info,"student") !== false) {
  7538. $student_count++;
  7539. } else if (strpos($record->info,"teacher") !== false) {
  7540. $teacher_count++;
  7541. }
  7542. //Do some output
  7543. $counter++;
  7544. if ($counter % 10 == 0) {
  7545. if (!defined('RESTORE_SILENTLY')) {
  7546. echo ".";
  7547. if ($counter % 200 == 0) {
  7548. echo "<br />";
  7549. }
  7550. }
  7551. backup_flush(300);
  7552. }
  7553. }
  7554. if (!defined('RESTORE_SILENTLY')) {
  7555. //Now print information gathered
  7556. echo " (".get_string("new").": ".$new_count.", ".get_string("existing").": ".$exists_count.")";
  7557. echo "<ul>";
  7558. echo "<li>".get_string("students").": ".$student_count.'</li>';
  7559. echo "<li>".get_string("teachers").": ".$teacher_count.'</li>';
  7560. echo "</ul>";
  7561. }
  7562. } else {
  7563. if (!defined('RESTORE_SILENTLY')) {
  7564. notify("No users were found!");
  7565. } // no need to return false here, it's recoverable.
  7566. }
  7567. }
  7568. if (!defined('RESTORE_SILENTLY')) {
  7569. echo "</li>";
  7570. }
  7571. }
  7572. //Now create groups as needed
  7573. if ($status and ($restore->groups == RESTORE_GROUPS_ONLY or $restore->groups == RESTORE_GROUPS_GROUPINGS)) {
  7574. if (!defined('RESTORE_SILENTLY')) {
  7575. echo "<li>".get_string("creatinggroups");
  7576. }
  7577. if (!$status = restore_create_groups($restore,$xml_file)) {
  7578. if (!defined('RESTORE_SILENTLY')) {
  7579. notify("Could not restore groups!");
  7580. } else {
  7581. $errorstr = "Could not restore groups!";
  7582. return false;
  7583. }
  7584. }
  7585. if (!defined('RESTORE_SILENTLY')) {
  7586. echo '</li>';
  7587. }
  7588. }
  7589. //Now create groupings as needed
  7590. if ($status and ($restore->groups == RESTORE_GROUPINGS_ONLY or $restore->groups == RESTORE_GROUPS_GROUPINGS)) {
  7591. if (!defined('RESTORE_SILENTLY')) {
  7592. echo "<li>".get_string("creatinggroupings");
  7593. }
  7594. if (!$status = restore_create_groupings($restore,$xml_file)) {
  7595. if (!defined('RESTORE_SILENTLY')) {
  7596. notify("Could not restore groupings!");
  7597. } else {
  7598. $errorstr = "Could not restore groupings!";
  7599. return false;
  7600. }
  7601. }
  7602. if (!defined('RESTORE_SILENTLY')) {
  7603. echo '</li>';
  7604. }
  7605. }
  7606. //Now create groupingsgroups as needed
  7607. if ($status and $restore->groups == RESTORE_GROUPS_GROUPINGS) {
  7608. if (!defined('RESTORE_SILENTLY')) {
  7609. echo "<li>".get_string("creatinggroupingsgroups");
  7610. }
  7611. if (!$status = restore_create_groupings_groups($restore,$xml_file)) {
  7612. if (!defined('RESTORE_SILENTLY')) {
  7613. notify("Could not restore groups in groupings!");
  7614. } else {
  7615. $errorstr = "Could not restore groups in groupings!";
  7616. return false;
  7617. }
  7618. }
  7619. if (!defined('RESTORE_SILENTLY')) {
  7620. echo '</li>';
  7621. }
  7622. }
  7623. //Now create the course_sections and their associated course_modules
  7624. //we have to do this after groups and groupings are restored, because we need the new groupings id
  7625. if ($status) {
  7626. //Into new course
  7627. if ($restore->restoreto == RESTORETO_NEW_COURSE) {
  7628. if (!defined('RESTORE_SILENTLY')) {
  7629. echo "<li>".get_string("creatingsections");
  7630. }
  7631. if (!$status = restore_create_sections($restore,$xml_file)) {
  7632. if (!defined('RESTORE_SILENTLY')) {
  7633. notify("Error creating sections in the existing course.");
  7634. } else {
  7635. $errorstr = "Error creating sections in the existing course.";
  7636. return false;
  7637. }
  7638. }
  7639. if (!defined('RESTORE_SILENTLY')) {
  7640. echo '</li>';
  7641. }
  7642. //Into existing course
  7643. } else if ($restore->restoreto != RESTORETO_NEW_COURSE) {
  7644. if (!defined('RESTORE_SILENTLY')) {
  7645. echo "<li>".get_string("checkingsections");
  7646. }
  7647. if (!$status = restore_create_sections($restore,$xml_file)) {
  7648. if (!defined('RESTORE_SILENTLY')) {
  7649. notify("Error creating sections in the existing course.");
  7650. } else {
  7651. $errorstr = "Error creating sections in the existing course.";
  7652. return false;
  7653. }
  7654. }
  7655. if (!defined('RESTORE_SILENTLY')) {
  7656. echo '</li>';
  7657. }
  7658. //Error
  7659. } else {
  7660. if (!defined('RESTORE_SILENTLY')) {
  7661. notify("Neither a new course or an existing one was specified.");
  7662. $status = false;
  7663. } else {
  7664. $errorstr = "Neither a new course or an existing one was specified.";
  7665. return false;
  7666. }
  7667. }
  7668. }
  7669. //Now create metacourse info
  7670. if ($status and $restore->metacourse) {
  7671. //Only to new courses!
  7672. if ($restore->restoreto == RESTORETO_NEW_COURSE) {
  7673. if (!defined('RESTORE_SILENTLY')) {
  7674. echo "<li>".get_string("creatingmetacoursedata");
  7675. }
  7676. if (!$status = restore_create_metacourse($restore,$xml_file)) {
  7677. if (!defined('RESTORE_SILENTLY')) {
  7678. notify("Error creating metacourse in the course.");
  7679. } else {
  7680. $errorstr = "Error creating metacourse in the course.";
  7681. return false;
  7682. }
  7683. }
  7684. if (!defined('RESTORE_SILENTLY')) {
  7685. echo '</li>';
  7686. }
  7687. }
  7688. }
  7689. //Now create categories and questions as needed
  7690. if ($status) {
  7691. include_once("$CFG->dirroot/question/restorelib.php");
  7692. if (!defined('RESTORE_SILENTLY')) {
  7693. echo "<li>".get_string("creatingcategoriesandquestions");
  7694. echo "<ul>";
  7695. }
  7696. if (!$status = restore_create_questions($restore,$xml_file)) {
  7697. if (!defined('RESTORE_SILENTLY')) {
  7698. notify("Could not restore categories and questions!");
  7699. } else {
  7700. $errorstr = "Could not restore categories and questions!";
  7701. return false;
  7702. }
  7703. }
  7704. if (!defined('RESTORE_SILENTLY')) {
  7705. echo "</ul></li>";
  7706. }
  7707. }
  7708. //Now create user_files as needed
  7709. if ($status and ($restore->user_files)) {
  7710. if (!defined('RESTORE_SILENTLY')) {
  7711. echo "<li>".get_string("copyinguserfiles");
  7712. }
  7713. if (!$status = restore_user_files($restore)) {
  7714. if (!defined('RESTORE_SILENTLY')) {
  7715. notify("Could not restore user files!");
  7716. } else {
  7717. $errorstr = "Could not restore user files!";
  7718. return false;
  7719. }
  7720. }
  7721. //If all is ok (and we have a counter)
  7722. if ($status and ($status !== true)) {
  7723. //Inform about user dirs created from backup
  7724. if (!defined('RESTORE_SILENTLY')) {
  7725. echo "<ul>";
  7726. echo "<li>".get_string("userzones").": ".$status;
  7727. echo "</li></ul>";
  7728. }
  7729. }
  7730. if (!defined('RESTORE_SILENTLY')) {
  7731. echo '</li>';
  7732. }
  7733. }
  7734. //Now create course files as needed
  7735. if ($status and ($restore->course_files)) {
  7736. if (!defined('RESTORE_SILENTLY')) {
  7737. echo "<li>".get_string("copyingcoursefiles");
  7738. }
  7739. if (!$status = restore_course_files($restore)) {
  7740. if (empty($status)) {
  7741. notify("Could not restore course files!");
  7742. } else {
  7743. $errorstr = "Could not restore course files!";
  7744. return false;
  7745. }
  7746. }
  7747. //If all is ok (and we have a counter)
  7748. if ($status and ($status !== true)) {
  7749. //Inform about user dirs created from backup
  7750. if (!defined('RESTORE_SILENTLY')) {
  7751. echo "<ul>";
  7752. echo "<li>".get_string("filesfolders").": ".$status.'</li>';
  7753. echo "</ul>";
  7754. }
  7755. }
  7756. if (!defined('RESTORE_SILENTLY')) {
  7757. echo "</li>";
  7758. }
  7759. }
  7760. //Now create site files as needed
  7761. if ($status and ($restore->site_files)) {
  7762. if (!defined('RESTORE_SILENTLY')) {
  7763. echo "<li>".get_string('copyingsitefiles');
  7764. }
  7765. if (!$status = restore_site_files($restore)) {
  7766. if (empty($status)) {
  7767. notify("Could not restore site files!");
  7768. } else {
  7769. $errorstr = "Could not restore site files!";
  7770. return false;
  7771. }
  7772. }
  7773. //If all is ok (and we have a counter)
  7774. if ($status and ($status !== true)) {
  7775. //Inform about user dirs created from backup
  7776. if (!defined('RESTORE_SILENTLY')) {
  7777. echo "<ul>";
  7778. echo "<li>".get_string("filesfolders").": ".$status.'</li>';
  7779. echo "</ul>";
  7780. }
  7781. }
  7782. if (!defined('RESTORE_SILENTLY')) {
  7783. echo "</li>";
  7784. }
  7785. }
  7786. //Now create messages as needed
  7787. if ($status and ($restore->messages)) {
  7788. if (!defined('RESTORE_SILENTLY')) {
  7789. echo "<li>".get_string("creatingmessagesinfo");
  7790. }
  7791. if (!$status = restore_create_messages($restore,$xml_file)) {
  7792. if (!defined('RESTORE_SILENTLY')) {
  7793. notify("Could not restore messages!");
  7794. } else {
  7795. $errorstr = "Could not restore messages!";
  7796. return false;
  7797. }
  7798. }
  7799. if (!defined('RESTORE_SILENTLY')) {
  7800. echo "</li>";
  7801. }
  7802. }
  7803. //Now create blogs as needed
  7804. if ($status and ($restore->blogs)) {
  7805. if (!defined('RESTORE_SILENTLY')) {
  7806. echo "<li>".get_string("creatingblogsinfo");
  7807. }
  7808. if (!$status = restore_create_blogs($restore,$xml_file)) {
  7809. if (!defined('RESTORE_SILENTLY')) {
  7810. notify("Could not restore blogs!");
  7811. } else {
  7812. $errorstr = "Could not restore blogs!";
  7813. return false;
  7814. }
  7815. }
  7816. if (!defined('RESTORE_SILENTLY')) {
  7817. echo "</li>";
  7818. }
  7819. }
  7820. //Now create scales as needed
  7821. if ($status) {
  7822. if (!defined('RESTORE_SILENTLY')) {
  7823. echo "<li>".get_string("creatingscales");
  7824. }
  7825. if (!$status = restore_create_scales($restore,$xml_file)) {
  7826. if (!defined('RESTORE_SILENTLY')) {
  7827. notify("Could not restore custom scales!");
  7828. } else {
  7829. $errorstr = "Could not restore custom scales!";
  7830. return false;
  7831. }
  7832. }
  7833. if (!defined('RESTORE_SILENTLY')) {
  7834. echo '</li>';
  7835. }
  7836. }
  7837. //Now create events as needed
  7838. if ($status) {
  7839. if (!defined('RESTORE_SILENTLY')) {
  7840. echo "<li>".get_string("creatingevents");
  7841. }
  7842. if (!$status = restore_create_events($restore,$xml_file)) {
  7843. if (!defined('RESTORE_SILENTLY')) {
  7844. notify("Could not restore course events!");
  7845. } else {
  7846. $errorstr = "Could not restore course events!";
  7847. return false;
  7848. }
  7849. }
  7850. if (!defined('RESTORE_SILENTLY')) {
  7851. echo '</li>';
  7852. }
  7853. }
  7854. //Now create course modules as needed
  7855. if ($status) {
  7856. if (!defined('RESTORE_SILENTLY')) {
  7857. echo "<li>".get_string("creatingcoursemodules");
  7858. }
  7859. if (!$status = restore_create_modules($restore,$xml_file)) {
  7860. if (!defined('RESTORE_SILENTLY')) {
  7861. notify("Could not restore modules!");
  7862. } else {
  7863. $errorstr = "Could not restore modules!";
  7864. return false;
  7865. }
  7866. }
  7867. if (!defined('RESTORE_SILENTLY')) {
  7868. echo '</li>';
  7869. }
  7870. }
  7871. //Bring back the course blocks -- do it AFTER the modules!!!
  7872. if ($status) {
  7873. //If we are deleting and bringing into a course or making a new course, same situation
  7874. if ($restore->restoreto == RESTORETO_CURRENT_DELETING ||
  7875. $restore->restoreto == RESTORETO_EXISTING_DELETING ||
  7876. $restore->restoreto == RESTORETO_NEW_COURSE) {
  7877. if (!defined('RESTORE_SILENTLY')) {
  7878. echo '<li>'.get_string('creatingblocks');
  7879. }
  7880. $course_header->blockinfo = !empty($course_header->blockinfo) ? $course_header->blockinfo : NULL;
  7881. if (!$status = restore_create_blocks($restore, $info->backup_block_format, $course_header->blockinfo, $xml_file)) {
  7882. if (!defined('RESTORE_SILENTLY')) {
  7883. notify('Error while creating the course blocks');
  7884. } else {
  7885. $errorstr = "Error while creating the course blocks";
  7886. return false;
  7887. }
  7888. }
  7889. if (!defined('RESTORE_SILENTLY')) {
  7890. echo '</li>';
  7891. }
  7892. }
  7893. }
  7894. if ($status) {
  7895. //If we are deleting and bringing into a course or making a new course, same situation
  7896. if ($restore->restoreto == RESTORETO_CURRENT_DELETING ||
  7897. $restore->restoreto == RESTORETO_EXISTING_DELETING ||
  7898. $restore->restoreto == RESTORETO_NEW_COURSE) {
  7899. if (!defined('RESTORE_SILENTLY')) {
  7900. echo '<li>'.get_string('courseformatdata');
  7901. }
  7902. if (!$status = restore_set_format_data($restore, $xml_file)) {
  7903. $error = "Error while setting the course format data";
  7904. if (!defined('RESTORE_SILENTLY')) {
  7905. notify($error);
  7906. } else {
  7907. $errorstr=$error;
  7908. return false;
  7909. }
  7910. }
  7911. if (!defined('RESTORE_SILENTLY')) {
  7912. echo '</li>';
  7913. }
  7914. }
  7915. }
  7916. //Now create log entries as needed
  7917. if ($status and ($info->backup_logs == 'true' && $restore->logs)) {
  7918. if (!defined('RESTORE_SILENTLY')) {
  7919. echo "<li>".get_string("creatinglogentries");
  7920. }
  7921. if (!$status = restore_create_logs($restore,$xml_file)) {
  7922. if (!defined('RESTORE_SILENTLY')) {
  7923. notify("Could not restore logs!");
  7924. } else {
  7925. $errorstr = "Could not restore logs!";
  7926. return false;
  7927. }
  7928. }
  7929. if (!defined('RESTORE_SILENTLY')) {
  7930. echo '</li>';
  7931. }
  7932. }
  7933. //Now, if all is OK, adjust the instance field in course_modules !!
  7934. //this also calculates the final modinfo information so, after this,
  7935. //code needing it can be used (like role_assignments. MDL-13740)
  7936. if ($status) {
  7937. if (!defined('RESTORE_SILENTLY')) {
  7938. echo "<li>".get_string("checkinginstances");
  7939. }
  7940. if (!$status = restore_check_instances($restore)) {
  7941. if (!defined('RESTORE_SILENTLY')) {
  7942. notify("Could not adjust instances in course_modules!");
  7943. } else {
  7944. $errorstr = "Could not adjust instances in course_modules!";
  7945. return false;
  7946. }
  7947. }
  7948. if (!defined('RESTORE_SILENTLY')) {
  7949. echo '</li>';
  7950. }
  7951. }
  7952. //Now, if all is OK, adjust activity events
  7953. if ($status) {
  7954. if (!defined('RESTORE_SILENTLY')) {
  7955. echo "<li>".get_string("refreshingevents");
  7956. }
  7957. if (!$status = restore_refresh_events($restore)) {
  7958. if (!defined('RESTORE_SILENTLY')) {
  7959. notify("Could not refresh events for activities!");
  7960. } else {
  7961. $errorstr = "Could not refresh events for activities!";
  7962. return false;
  7963. }
  7964. }
  7965. if (!defined('RESTORE_SILENTLY')) {
  7966. echo '</li>';
  7967. }
  7968. }
  7969. //Now, if all is OK, adjust inter-activity links
  7970. if ($status) {
  7971. if (!defined('RESTORE_SILENTLY')) {
  7972. echo "<li>".get_string("decodinginternallinks");
  7973. }
  7974. if (!$status = restore_decode_content_links($restore)) {
  7975. if (!defined('RESTORE_SILENTLY')) {
  7976. notify("Could not decode content links!");
  7977. } else {
  7978. $errorstr = "Could not decode content links!";
  7979. return false;
  7980. }
  7981. }
  7982. if (!defined('RESTORE_SILENTLY')) {
  7983. echo '</li>';
  7984. }
  7985. }
  7986. //Now, with backup files prior to version 2005041100,
  7987. //convert all the wiki texts in the course to markdown
  7988. if ($status && $restore->backup_version < 2005041100) {
  7989. if (!defined('RESTORE_SILENTLY')) {
  7990. echo "<li>".get_string("convertingwikitomarkdown");
  7991. }
  7992. if (!$status = restore_convert_wiki2markdown($restore)) {
  7993. if (!defined('RESTORE_SILENTLY')) {
  7994. notify("Could not convert wiki texts to markdown!");
  7995. } else {
  7996. $errorstr = "Could not convert wiki texts to markdown!";
  7997. return false;
  7998. }
  7999. }
  8000. if (!defined('RESTORE_SILENTLY')) {
  8001. echo '</li>';
  8002. }
  8003. }
  8004. //Now create gradebook as needed -- AFTER modules and blocks!!!
  8005. if ($status) {
  8006. if ($restore->backup_version > 2007090500) {
  8007. if (!defined('RESTORE_SILENTLY')) {
  8008. echo "<li>".get_string("creatinggradebook");
  8009. }
  8010. if (!$status = restore_create_gradebook($restore,$xml_file)) {
  8011. if (!defined('RESTORE_SILENTLY')) {
  8012. notify("Could not restore gradebook!");
  8013. } else {
  8014. $errorstr = "Could not restore gradebook!";
  8015. return false;
  8016. }
  8017. }
  8018. if (!defined('RESTORE_SILENTLY')) {
  8019. echo '</li>';
  8020. }
  8021. } else {
  8022. // for moodle versions before 1.9, those grades need to be converted to use the new gradebook
  8023. // this code needs to execute *after* the course_modules are sorted out
  8024. if (!defined('RESTORE_SILENTLY')) {
  8025. echo "<li>".get_string("migratinggrades");
  8026. }
  8027. /// force full refresh of grading data before migration == crete all items first
  8028. if (!$status = restore_migrate_old_gradebook($restore,$xml_file)) {
  8029. if (!defined('RESTORE_SILENTLY')) {
  8030. notify("Could not migrate gradebook!");
  8031. } else {
  8032. $errorstr = "Could not migrade gradebook!";
  8033. return false;
  8034. }
  8035. }
  8036. if (!defined('RESTORE_SILENTLY')) {
  8037. echo '</li>';
  8038. }
  8039. }
  8040. /// force full refresh of grading data after all items are created
  8041. grade_force_full_regrading($restore->course_id);
  8042. grade_grab_course_grades($restore->course_id);
  8043. }
  8044. /*******************************************************************************
  8045. ************* Restore of Roles and Capabilities happens here ******************
  8046. *******************************************************************************/
  8047. // try to restore roles even when restore is going to fail - teachers might have
  8048. // at least some role assigned - this is not correct though
  8049. $status = restore_create_roles($restore, $xml_file) && $status;
  8050. $status = restore_roles_settings($restore, $xml_file) && $status;
  8051. //Now if all is OK, update:
  8052. // - course modinfo field
  8053. // - categories table
  8054. // - add user as teacher
  8055. if ($status) {
  8056. if (!defined('RESTORE_SILENTLY')) {
  8057. echo "<li>".get_string("checkingcourse");
  8058. }
  8059. //categories table
  8060. $course = get_record("course","id",$restore->course_id);
  8061. fix_course_sortorder();
  8062. // Check if the user has course update capability in the newly restored course
  8063. // there is no need to load his capabilities again, because restore_roles_settings
  8064. // would have loaded it anyway, if there is any assignments.
  8065. // fix for MDL-6831
  8066. $newcontext = get_context_instance(CONTEXT_COURSE, $restore->course_id);
  8067. if (!has_capability('moodle/course:manageactivities', $newcontext)) {
  8068. // fix for MDL-9065, use the new config setting if exists
  8069. if ($CFG->creatornewroleid) {
  8070. role_assign($CFG->creatornewroleid, $USER->id, 0, $newcontext->id);
  8071. } else {
  8072. if ($legacyteachers = get_roles_with_capability('moodle/legacy:editingteacher', CAP_ALLOW, get_context_instance(CONTEXT_SYSTEM))) {
  8073. if ($legacyteacher = array_shift($legacyteachers)) {
  8074. role_assign($legacyteacher->id, $USER->id, 0, $newcontext->id);
  8075. }
  8076. } else {
  8077. notify('Could not find a legacy teacher role. You might need your moodle admin to assign a role with editing privilages to this course.');
  8078. }
  8079. }
  8080. }
  8081. if (!defined('RESTORE_SILENTLY')) {
  8082. echo '</li>';
  8083. }
  8084. }
  8085. //Cleanup temps (files and db)
  8086. if ($status) {
  8087. if (!defined('RESTORE_SILENTLY')) {
  8088. echo "<li>".get_string("cleaningtempdata");
  8089. }
  8090. if (!$status = clean_temp_data ($restore)) {
  8091. if (!defined('RESTORE_SILENTLY')) {
  8092. notify("Could not clean up temporary data from files and database");
  8093. } else {
  8094. $errorstr = "Could not clean up temporary data from files and database";
  8095. return false;
  8096. }
  8097. }
  8098. if (!defined('RESTORE_SILENTLY')) {
  8099. echo '</li>';
  8100. }
  8101. }
  8102. // this is not a critical check - the result can be ignored
  8103. if (restore_close_html($restore)){
  8104. if (!defined('RESTORE_SILENTLY')) {
  8105. echo '<li>Closing the Restorelog.html file.</li>';
  8106. }
  8107. }
  8108. else {
  8109. if (!defined('RESTORE_SILENTLY')) {
  8110. notify("Could not close the restorelog.html file");
  8111. }
  8112. }
  8113. if (!defined('RESTORE_SILENTLY')) {
  8114. //End the main ul
  8115. echo "</ul>";
  8116. //End the main table
  8117. echo "</td></tr>";
  8118. echo "</table>";
  8119. }
  8120. return $status;
  8121. }
  8122. //Create, open and write header of the html log file
  8123. function restore_open_html($restore,$course_header) {
  8124. global $CFG;
  8125. $status = true;
  8126. //Open file for writing
  8127. //First, we check the course_id backup data folder exists and create it as necessary in CFG->dataroot
  8128. if (!$dest_dir = make_upload_directory("$restore->course_id/backupdata")) { // Backup folder
  8129. error("Could not create backupdata folder. The site administrator needs to fix the file permissions");
  8130. }
  8131. $status = check_dir_exists($dest_dir,true);
  8132. $restorelog_file = fopen("$dest_dir/restorelog.html","a");
  8133. //Add the stylesheet
  8134. $stylesheetshtml = '';
  8135. foreach ($CFG->stylesheets as $stylesheet) {
  8136. $stylesheetshtml .= '<link rel="stylesheet" type="text/css" href="'.$stylesheet.'" />'."\n";
  8137. }
  8138. ///Accessibility: added the 'lang' attribute to $direction, used in theme <html> tag.
  8139. $languagehtml = get_html_lang($dir=true);
  8140. //Write the header in the new logging file
  8141. fwrite ($restorelog_file,"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"");
  8142. fwrite ($restorelog_file," \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"> ");
  8143. fwrite ($restorelog_file,"<html dir=\"ltr\".$languagehtml.");
  8144. fwrite ($restorelog_file,"<head>");
  8145. fwrite ($restorelog_file,$stylesheetshtml);
  8146. fwrite ($restorelog_file,"<title>".$course_header->course_shortname." Restored </title>");
  8147. fwrite ($restorelog_file,"</head><body><br/><h1>The following changes were made during the Restoration of this Course.</h1><br/><br/>");
  8148. fwrite ($restorelog_file,"The Course ShortName is now - ".$course_header->course_shortname." The FullName is now - ".$course_header->course_fullname."<br/><br/>");
  8149. $startdate = addslashes($course_header->course_startdate);
  8150. $date = usergetdate($startdate);
  8151. fwrite ($restorelog_file,"The Originating Courses Start Date was " .$date['weekday'].", ".$date['mday']." ".$date['month']." ".$date['year']."");
  8152. $startdate += $restore->course_startdateoffset;
  8153. $date = usergetdate($startdate);
  8154. fwrite ($restorelog_file,"&nbsp;&nbsp;&nbsp;This Courses Start Date is now " .$date['weekday'].", ".$date['mday']." ".$date['month']." ".$date['year']."<br/><br/>");
  8155. if ($status) {
  8156. return $restorelog_file;
  8157. } else {
  8158. return false;
  8159. }
  8160. }
  8161. //Create & close footer of the html log file
  8162. function restore_close_html($restore) {
  8163. global $CFG;
  8164. $status = true;
  8165. //Open file for writing
  8166. //First, check that course_id/backupdata folder exists in CFG->dataroot
  8167. $dest_dir = $CFG->dataroot."/".$restore->course_id."/backupdata";
  8168. $status = check_dir_exists($dest_dir, true, true);
  8169. $restorelog_file = fopen("$dest_dir/restorelog.html","a");
  8170. //Write the footer to close the logging file
  8171. fwrite ($restorelog_file,"<br/>This file was written to directly by each modules restore process.");
  8172. fwrite ($restorelog_file,"<br/><br/>Log complete.</body></html>");
  8173. if ($status) {
  8174. return $restorelog_file;
  8175. } else {
  8176. return false;
  8177. }
  8178. }
  8179. /********************** Roles and Capabilities Related Functions *******************************/
  8180. /* Yu: Note recovering of role assignments/overrides need to take place after
  8181. users have been recovered, i.e. after we get their new_id, and after all
  8182. roles have been recreated or mapped. Contexts can be created on the fly.
  8183. The current order of restore is Restore (old) -> restore roles -> restore assignment/overrides
  8184. the order of restore among different contexts, i.e. course, mod, blocks, users should not matter
  8185. once roles and users have been restored.
  8186. */
  8187. /**
  8188. * This function restores all the needed roles for this course
  8189. * i.e. roles with an assignment in any of the mods or blocks,
  8190. * roles assigned on any user (e.g. parent role) and roles
  8191. * assigned at course levle
  8192. * This function should check for duplicate roles first
  8193. * It isn't now, just overwriting
  8194. */
  8195. function restore_create_roles($restore, $xmlfile) {
  8196. global $CFG;
  8197. if (!defined('RESTORE_SILENTLY')) {
  8198. echo "<li>".get_string("creatingrolesdefinitions").'</li>';
  8199. }
  8200. $info = restore_read_xml_roles($xmlfile);
  8201. $sitecontext = get_context_instance(CONTEXT_SYSTEM);
  8202. // the following code creates new roles
  8203. // but we could use more intelligent detection, and role mapping
  8204. // get role mapping info from $restore
  8205. $rolemappings = array();
  8206. if (!empty($restore->rolesmapping)) {
  8207. $rolemappings = $restore->rolesmapping;
  8208. }
  8209. // $info->roles will be empty for backups pre 1.7
  8210. if (isset($info->roles) && $info->roles) {
  8211. foreach ($info->roles as $oldroleid=>$roledata) {
  8212. if (empty($restore->rolesmapping)) {
  8213. // if this is empty altogether, we came from import or there's no roles used in course at all
  8214. // in this case, write the same oldid as this is the same site
  8215. // no need to do mapping
  8216. $status = backup_putid($restore->backup_unique_code,"role",$oldroleid,
  8217. $oldroleid); // adding a new id
  8218. continue; // do not create additonal roles;
  8219. }
  8220. // first we check if the roles are in the mappings
  8221. // if so, we just do a mapping i.e. update oldids table
  8222. if (isset($rolemappings[$oldroleid]) && $rolemappings[$oldroleid]) {
  8223. $status = backup_putid($restore->backup_unique_code,"role",$oldroleid,
  8224. $rolemappings[$oldroleid]); // adding a new id
  8225. // check for permissions before create new roles
  8226. } else if (has_capability('moodle/role:manage', get_context_instance(CONTEXT_SYSTEM))) {
  8227. // code to make new role name/short name if same role name or shortname exists
  8228. $fullname = $roledata->name;
  8229. $shortname = $roledata->shortname;
  8230. $currentfullname = "";
  8231. $currentshortname = "";
  8232. $counter = 0;
  8233. do {
  8234. if ($counter) {
  8235. $suffixfull = " ".get_string("copyasnoun")." ".$counter;
  8236. $suffixshort = "_".$counter;
  8237. } else {
  8238. $suffixfull = "";
  8239. $suffixshort = "";
  8240. }
  8241. $currentfullname = $fullname.$suffixfull;
  8242. // Limit the size of shortname - database column accepts <= 100 chars
  8243. $currentshortname = substr($shortname, 0, 100 - strlen($suffixshort)).$suffixshort;
  8244. $coursefull = get_record("role","name",addslashes($currentfullname));
  8245. $courseshort = get_record("role","shortname",addslashes($currentshortname));
  8246. $counter++;
  8247. } while ($coursefull || $courseshort);
  8248. $roledata->name = $currentfullname;
  8249. $roledata->shortname= $currentshortname;
  8250. // done finding a unique name
  8251. $newroleid = create_role(addslashes($roledata->name),addslashes($roledata->shortname),'');
  8252. $status = backup_putid($restore->backup_unique_code,"role",$oldroleid,
  8253. $newroleid); // adding a new id
  8254. foreach ($roledata->capabilities as $capability) {
  8255. $roleinfo = new object();
  8256. $roleinfo = (object)$capability;
  8257. $roleinfo->contextid = $sitecontext->id;
  8258. $roleinfo->capability = $capability->name;
  8259. $roleinfo->roleid = $newroleid;
  8260. insert_record('role_capabilities', $roleinfo);
  8261. }
  8262. } else {
  8263. // map the new role to course default role
  8264. if (!$default_role = get_field("course", "defaultrole", "id", $restore->course_id)) {
  8265. $default_role = $CFG->defaultcourseroleid;
  8266. }
  8267. $status = backup_putid($restore->backup_unique_code, "role", $oldroleid, $default_role);
  8268. }
  8269. /// Now, restore role nameincourse (only if the role had nameincourse in backup)
  8270. if (!empty($roledata->nameincourse)) {
  8271. $newrole = backup_getid($restore->backup_unique_code, 'role', $oldroleid); /// Look for target role
  8272. $coursecontext = get_context_instance(CONTEXT_COURSE, $restore->course_id); /// Look for target context
  8273. if (!empty($newrole->new_id) && !empty($coursecontext)) {
  8274. /// Check the role hasn't any custom name in context
  8275. if (!record_exists('role_names', 'roleid', $newrole->new_id, 'contextid', $coursecontext->id)) {
  8276. $rolename = new object();
  8277. $rolename->roleid = $newrole->new_id;
  8278. $rolename->contextid = $coursecontext->id;
  8279. $rolename->name = addslashes($roledata->nameincourse);
  8280. insert_record('role_names', $rolename);
  8281. }
  8282. }
  8283. }
  8284. }
  8285. }
  8286. return true;
  8287. }
  8288. /**
  8289. * this function restores role assignments and role overrides
  8290. * in course/user/block/mod level, it passed through
  8291. * the xml file again
  8292. */
  8293. function restore_roles_settings($restore, $xmlfile) {
  8294. // data pulls from course, mod, user, and blocks
  8295. /*******************************************************
  8296. * Restoring from course level assignments *
  8297. *******************************************************/
  8298. if (!defined('RESTORE_SILENTLY')) {
  8299. echo "<li>".get_string("creatingcourseroles").'</li>';
  8300. }
  8301. $course = restore_read_xml_course_header($xmlfile);
  8302. if (!isset($restore->rolesmapping)) {
  8303. $isimport = true; // course import from another course, or course with no role assignments
  8304. } else {
  8305. $isimport = false; // course restore with role assignments
  8306. }
  8307. if (!empty($course->roleassignments) && !$isimport) {
  8308. $courseassignments = $course->roleassignments;
  8309. foreach ($courseassignments as $oldroleid => $courseassignment) {
  8310. restore_write_roleassignments($restore, $courseassignment->assignments, "course", CONTEXT_COURSE, $course->course_id, $oldroleid);
  8311. }
  8312. }
  8313. /*****************************************************
  8314. * Restoring from course level overrides *
  8315. *****************************************************/
  8316. if (!empty($course->roleoverrides) && !$isimport) {
  8317. $courseoverrides = $course->roleoverrides;
  8318. foreach ($courseoverrides as $oldroleid => $courseoverride) {
  8319. // if not importing into exiting course, or creating new role, we are ok
  8320. // local course overrides to be respected (i.e. restored course overrides ignored)
  8321. if (($restore->restoreto != RESTORETO_CURRENT_ADDING && $restore->restoreto != RESTORETO_EXISTING_ADDING) || empty($restore->rolesmapping[$oldroleid])) {
  8322. restore_write_roleoverrides($restore, $courseoverride->overrides, "course", CONTEXT_COURSE, $course->course_id, $oldroleid);
  8323. }
  8324. }
  8325. }
  8326. /*******************************************************
  8327. * Restoring role assignments/overrdies *
  8328. * from module level assignments *
  8329. *******************************************************/
  8330. if (!defined('RESTORE_SILENTLY')) {
  8331. echo "<li>".get_string("creatingmodroles").'</li>';
  8332. }
  8333. $sections = restore_read_xml_sections($xmlfile);
  8334. $secs = $sections->sections;
  8335. foreach ($secs as $section) {
  8336. if (isset($section->mods)) {
  8337. foreach ($section->mods as $modid=>$mod) {
  8338. if (isset($mod->roleassignments) && !$isimport) {
  8339. foreach ($mod->roleassignments as $oldroleid=>$modassignment) {
  8340. restore_write_roleassignments($restore, $modassignment->assignments, "course_modules", CONTEXT_MODULE, $modid, $oldroleid);
  8341. }
  8342. }
  8343. // role overrides always applies, in import or backup/restore
  8344. if (isset($mod->roleoverrides)) {
  8345. foreach ($mod->roleoverrides as $oldroleid=>$modoverride) {
  8346. restore_write_roleoverrides($restore, $modoverride->overrides, "course_modules", CONTEXT_MODULE, $modid, $oldroleid);
  8347. }
  8348. }
  8349. }
  8350. }
  8351. }
  8352. /*************************************************
  8353. * Restoring assignments from blocks level *
  8354. * role assignments/overrides *
  8355. *************************************************/
  8356. if ($restore->restoreto != RESTORETO_CURRENT_ADDING && $restore->restoreto != RESTORETO_EXISTING_ADDING) { // skip altogether if restoring to exisitng course by adding
  8357. if (!defined('RESTORE_SILENTLY')) {
  8358. echo "<li>".get_string("creatingblocksroles").'</li>';
  8359. }
  8360. $blocks = restore_read_xml_blocks($restore, $xmlfile);
  8361. if (isset($blocks->instances)) {
  8362. foreach ($blocks->instances as $instance) {
  8363. if (isset($instance->roleassignments) && !$isimport) {
  8364. foreach ($instance->roleassignments as $oldroleid=>$blockassignment) {
  8365. restore_write_roleassignments($restore, $blockassignment->assignments, "block_instance", CONTEXT_BLOCK, $instance->id, $oldroleid);
  8366. }
  8367. }
  8368. // likewise block overrides should always be restored like mods
  8369. if (isset($instance->roleoverrides)) {
  8370. foreach ($instance->roleoverrides as $oldroleid=>$blockoverride) {
  8371. restore_write_roleoverrides($restore, $blockoverride->overrides, "block_instance", CONTEXT_BLOCK, $instance->id, $oldroleid);
  8372. }
  8373. }
  8374. }
  8375. }
  8376. }
  8377. /************************************************
  8378. * Restoring assignments from userid level *
  8379. * role assignments/overrides *
  8380. ************************************************/
  8381. if (!defined('RESTORE_SILENTLY')) {
  8382. echo "<li>".get_string("creatinguserroles").'</li>';
  8383. }
  8384. $info = restore_read_xml_users($restore, $xmlfile);
  8385. if (!empty($info->users) && !$isimport) { // no need to restore user assignments for imports (same course)
  8386. //For each user, take its info from backup_ids
  8387. foreach ($info->users as $userid) {
  8388. $rec = backup_getid($restore->backup_unique_code,"user",$userid);
  8389. if (isset($rec->info->roleassignments)) {
  8390. foreach ($rec->info->roleassignments as $oldroleid=>$userassignment) {
  8391. restore_write_roleassignments($restore, $userassignment->assignments, "user", CONTEXT_USER, $userid, $oldroleid);
  8392. }
  8393. }
  8394. if (isset($rec->info->roleoverrides)) {
  8395. foreach ($rec->info->roleoverrides as $oldroleid=>$useroverride) {
  8396. restore_write_roleoverrides($restore, $useroverride->overrides, "user", CONTEXT_USER, $userid, $oldroleid);
  8397. }
  8398. }
  8399. }
  8400. }
  8401. return true;
  8402. }
  8403. // auxillary function to write role assignments read from xml to db
  8404. function restore_write_roleassignments($restore, $assignments, $table, $contextlevel, $oldid, $oldroleid) {
  8405. $role = backup_getid($restore->backup_unique_code, "role", $oldroleid);
  8406. foreach ($assignments as $assignment) {
  8407. $olduser = backup_getid($restore->backup_unique_code,"user",$assignment->userid);
  8408. //Oh dear, $olduser... can be an object, $obj->string or bool!
  8409. if (!$olduser || (is_string($olduser->info) && $olduser->info == "notincourse")) { // it's possible that user is not in the course
  8410. continue;
  8411. }
  8412. $assignment->userid = $olduser->new_id; // new userid here
  8413. $oldmodifier = backup_getid($restore->backup_unique_code,"user",$assignment->modifierid);
  8414. $assignment->modifierid = !empty($oldmodifier->new_id) ? $oldmodifier->new_id : 0; // new modifier id here
  8415. $assignment->roleid = $role->new_id; // restored new role id
  8416. // hack to make the correct contextid for course level imports
  8417. if ($contextlevel == CONTEXT_COURSE) {
  8418. $oldinstance->new_id = $restore->course_id;
  8419. } else {
  8420. $oldinstance = backup_getid($restore->backup_unique_code,$table,$oldid);
  8421. }
  8422. // new instance id not found (not restored module/block/user)... skip any assignment
  8423. if (!$oldinstance || empty($oldinstance->new_id)) {
  8424. continue;
  8425. }
  8426. $newcontext = get_context_instance($contextlevel, $oldinstance->new_id);
  8427. $assignment->contextid = $newcontext->id; // new context id
  8428. // might already have same assignment
  8429. role_assign($assignment->roleid, $assignment->userid, 0, $assignment->contextid, $assignment->timestart, $assignment->timeend, $assignment->hidden, $assignment->enrol, $assignment->timemodified);
  8430. }
  8431. }
  8432. // auxillary function to write role assignments read from xml to db
  8433. function restore_write_roleoverrides($restore, $overrides, $table, $contextlevel, $oldid, $oldroleid) {
  8434. // it is possible to have an override not relevant to this course context.
  8435. // should be ignored(?)
  8436. if (!$role = backup_getid($restore->backup_unique_code, "role", $oldroleid)) {
  8437. return null;
  8438. }
  8439. foreach ($overrides as $override) {
  8440. $override->capability = $override->name;
  8441. $oldmodifier = backup_getid($restore->backup_unique_code,"user",$override->modifierid);
  8442. $override->modifierid = !empty($oldmodifier->new_id)?$oldmodifier->new_id:0; // new modifier id here
  8443. $override->roleid = $role->new_id; // restored new role id
  8444. // hack to make the correct contextid for course level imports
  8445. if ($contextlevel == CONTEXT_COURSE) {
  8446. $oldinstance->new_id = $restore->course_id;
  8447. } else {
  8448. $oldinstance = backup_getid($restore->backup_unique_code,$table,$oldid);
  8449. }
  8450. // new instance id not found (not restored module/block/user)... skip any override
  8451. if (!$oldinstance || empty($oldinstance->new_id)) {
  8452. continue;
  8453. }
  8454. $newcontext = get_context_instance($contextlevel, $oldinstance->new_id);
  8455. $override->contextid = $newcontext->id; // new context id
  8456. // use assign capability instead so we can add context to context_rel
  8457. assign_capability($override->capability, $override->permission, $override->roleid, $override->contextid);
  8458. }
  8459. }
  8460. /**
  8461. * true or false function to see if user can roll dates on restore (any course is enough)
  8462. * @return bool
  8463. */
  8464. function restore_user_can_roll_dates() {
  8465. global $USER;
  8466. // if user has moodle/restore:rolldates capability at system or any course cat return true
  8467. if (has_capability('moodle/restore:rolldates', get_context_instance(CONTEXT_SYSTEM))) {
  8468. return true;
  8469. }
  8470. // Non-cached - get accessinfo
  8471. if (isset($USER->access)) {
  8472. $accessinfo = $USER->access;
  8473. } else {
  8474. $accessinfo = get_user_access_sitewide($USER->id);
  8475. }
  8476. $courses = get_user_courses_bycap($USER->id, 'moodle/restore:rolldates', $accessinfo, true);
  8477. return !empty($courses);
  8478. }
  8479. //write activity date changes to the html log file, and update date values in the the xml array
  8480. function restore_log_date_changes($recordtype, &$restore, &$xml, $TAGS, $NAMETAG='NAME') {
  8481. global $CFG;
  8482. $openlog = false;
  8483. // loop through time fields in $TAGS
  8484. foreach ($TAGS as $TAG) {
  8485. // check $TAG has a sensible value
  8486. if (!empty($xml[$TAG][0]['#']) && is_string($xml[$TAG][0]['#']) && is_numeric($xml[$TAG][0]['#'])) {
  8487. if ($openlog==false) {
  8488. $openlog = true; // only come through here once
  8489. // open file for writing
  8490. $course_dir = "$CFG->dataroot/$restore->course_id/backupdata";
  8491. check_dir_exists($course_dir, true);
  8492. $restorelog = fopen("$course_dir/restorelog.html", "a");
  8493. // start output for this record
  8494. $msg = new stdClass();
  8495. $msg->recordtype = $recordtype;
  8496. $msg->recordname = $xml[$NAMETAG][0]['#'];
  8497. fwrite ($restorelog, get_string("backupdaterecordtype", "moodle", $msg));
  8498. }
  8499. // write old date to $restorelog
  8500. $value = $xml[$TAG][0]['#'];
  8501. $date = usergetdate($value);
  8502. $msg = new stdClass();
  8503. $msg->TAG = $TAG;
  8504. $msg->weekday = $date['weekday'];
  8505. $msg->mday = $date['mday'];
  8506. $msg->month = $date['month'];
  8507. $msg->year = $date['year'];
  8508. fwrite ($restorelog, get_string("backupdateold", "moodle", $msg));
  8509. // write new date to $restorelog
  8510. $value += $restore->course_startdateoffset;
  8511. $date = usergetdate($value);
  8512. $msg = new stdClass();
  8513. $msg->TAG = $TAG;
  8514. $msg->weekday = $date['weekday'];
  8515. $msg->mday = $date['mday'];
  8516. $msg->month = $date['month'];
  8517. $msg->year = $date['year'];
  8518. fwrite ($restorelog, get_string("backupdatenew", "moodle", $msg));
  8519. // update $value in $xml tree for calling module
  8520. $xml[$TAG][0]['#'] = "$value";
  8521. }
  8522. }
  8523. // close the restore log, if it was opened
  8524. if ($openlog) {
  8525. fclose($restorelog);
  8526. }
  8527. }
  8528. ?>