PageRenderTime 114ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 3ms

/moodle/backup/restorelib.php

https://bitbucket.org/geek745/moodle-db2
PHP | 9133 lines | 6341 code | 942 blank | 1850 comment | 1739 complexity | 32db839c51da903d88e3e021cedaa498 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause, LGPL-2.0
  1. <?php //$Id: restorelib.php,v 1.283.2.79 2009/10/06 01:22:15 stronk7 Exp $
  2. //Functions used in restore
  3. require_once($CFG->libdir.'/gradelib.php');
  4. /**
  5. * Group backup/restore constants, 0.
  6. */
  7. define('RESTORE_GROUPS_NONE', 0);
  8. /**
  9. * Group backup/restore constants, 1.
  10. */
  11. define('RESTORE_GROUPS_ONLY', 1);
  12. /**
  13. * Group backup/restore constants, 2.
  14. */
  15. define('RESTORE_GROUPINGS_ONLY', 2);
  16. /**
  17. * Group backup/restore constants, course/all.
  18. */
  19. define('RESTORE_GROUPS_GROUPINGS', 3);
  20. //This function unzips a zip file in the same directory that it is
  21. //It automatically uses pclzip or command line unzip
  22. function restore_unzip ($file) {
  23. return unzip_file($file, '', false);
  24. }
  25. //This function checks if moodle.xml seems to be a valid xml file
  26. //(exists, has an xml header and a course main tag
  27. function restore_check_moodle_file ($file) {
  28. $status = true;
  29. //Check if it exists
  30. if ($status = is_file($file)) {
  31. //Open it and read the first 200 bytes (chars)
  32. $handle = fopen ($file, "r");
  33. $first_chars = fread($handle,200);
  34. $status = fclose ($handle);
  35. //Chek if it has the requires strings
  36. if ($status) {
  37. $status = strpos($first_chars,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
  38. if ($status !== false) {
  39. $status = strpos($first_chars,"<MOODLE_BACKUP>");
  40. }
  41. }
  42. }
  43. return $status;
  44. }
  45. //This function iterates over all modules in backup file, searching for a
  46. //MODNAME_refresh_events() to execute. Perhaps it should ve moved to central Moodle...
  47. function restore_refresh_events($restore) {
  48. global $CFG;
  49. $status = true;
  50. //Take all modules in backup
  51. $modules = $restore->mods;
  52. //Iterate
  53. foreach($modules as $name => $module) {
  54. //Only if the module is being restored
  55. if (isset($module->restore) && $module->restore == 1) {
  56. //Include module library
  57. include_once("$CFG->dirroot/mod/$name/lib.php");
  58. //If module_refresh_events exists
  59. $function_name = $name."_refresh_events";
  60. if (function_exists($function_name)) {
  61. $status = $function_name($restore->course_id);
  62. }
  63. }
  64. }
  65. return $status;
  66. }
  67. //This function makes all the necessary calls to xxxx_decode_content_links_caller()
  68. //function in each module/block/course format..., passing them the desired contents to be decoded
  69. //from backup format to destination site/course in order to mantain inter-activities
  70. //working in the backup/restore process
  71. function restore_decode_content_links($restore) {
  72. global $CFG;
  73. $status = true;
  74. if (!defined('RESTORE_SILENTLY')) {
  75. echo "<ul>";
  76. }
  77. // Recode links in the course summary.
  78. if (!defined('RESTORE_SILENTLY')) {
  79. echo '<li>' . get_string('from') . ' ' . get_string('course');
  80. }
  81. $course = get_record('course', 'id', $restore->course_id, '', '', '', '', 'id,summary');
  82. $coursesummary = backup_todb($course->summary,false); // Exception: Process FILEPHP (not available when restored) MDL-18222
  83. $coursesummary = restore_decode_content_links_worker($coursesummary, $restore);
  84. if ($coursesummary != $course->summary) {
  85. $course->summary = addslashes($coursesummary);
  86. if (!update_record('course', $course)) {
  87. $status = false;
  88. }
  89. }
  90. if (!defined('RESTORE_SILENTLY')) {
  91. echo '</li>';
  92. }
  93. // Recode links in section summaries.
  94. $sections = get_records('course_sections', 'course', $restore->course_id, 'id', 'id,summary');
  95. if ($sections) {
  96. if (!defined('RESTORE_SILENTLY')) {
  97. echo '<li>' . get_string('from') . ' ' . get_string('sections');
  98. }
  99. foreach ($sections as $section) {
  100. $sectionsummary = restore_decode_content_links_worker($section->summary, $restore);
  101. if ($sectionsummary != $section->summary) {
  102. $section->summary = addslashes($sectionsummary);
  103. if (!update_record('course_sections', $section)) {
  104. $status = false;
  105. }
  106. }
  107. }
  108. if (!defined('RESTORE_SILENTLY')) {
  109. echo '</li>';
  110. }
  111. }
  112. // Restore links in modules.
  113. foreach ($restore->mods as $name => $info) {
  114. //If the module is being restored
  115. if (isset($info->restore) && $info->restore == 1) {
  116. //Check if the xxxx_decode_content_links_caller exists
  117. include_once("$CFG->dirroot/mod/$name/restorelib.php");
  118. $function_name = $name."_decode_content_links_caller";
  119. if (function_exists($function_name)) {
  120. if (!defined('RESTORE_SILENTLY')) {
  121. echo "<li>".get_string ("from")." ".get_string("modulenameplural",$name);
  122. }
  123. $status = $function_name($restore) && $status;
  124. if (!defined('RESTORE_SILENTLY')) {
  125. echo '</li>';
  126. }
  127. }
  128. }
  129. }
  130. // For the course format call its decode_content_links method (if it exists)
  131. $format = get_field('course', 'format', 'id', $restore->course_id);
  132. if (file_exists("$CFG->dirroot/course/format/$format/restorelib.php")) {
  133. include_once("$CFG->dirroot/course/format/$format/restorelib.php");
  134. $function_name = $format.'_decode_format_content_links_caller';
  135. if (function_exists($function_name)) {
  136. if (!defined('RESTORE_SILENTLY')) {
  137. echo "<li>".get_string ("from")." ".get_string("format").' '.$format;
  138. }
  139. $status = $function_name($restore);
  140. if (!defined('RESTORE_SILENTLY')) {
  141. echo '</li>';
  142. }
  143. }
  144. }
  145. // Process all html text also in blocks too
  146. if (!defined('RESTORE_SILENTLY')) {
  147. echo '<li>'.get_string ('from').' '.get_string('blocks');
  148. }
  149. if ($blocks = get_records('block', 'visible', 1)) {
  150. foreach ($blocks as $block) {
  151. if ($blockobject = block_instance($block->name)) {
  152. $blockobject->decode_content_links_caller($restore);
  153. }
  154. }
  155. }
  156. if (!defined('RESTORE_SILENTLY')) {
  157. echo '</li>';
  158. }
  159. // Restore links in questions.
  160. require_once("$CFG->dirroot/question/restorelib.php");
  161. if (!defined('RESTORE_SILENTLY')) {
  162. echo '<li>' . get_string('from') . ' ' . get_string('questions', 'quiz');
  163. }
  164. $status = question_decode_content_links_caller($restore) && $status;
  165. if (!defined('RESTORE_SILENTLY')) {
  166. echo '</li>';
  167. }
  168. if (!defined('RESTORE_SILENTLY')) {
  169. echo "</ul>";
  170. }
  171. return $status;
  172. }
  173. //This function is called from all xxxx_decode_content_links_caller(),
  174. //its task is to ask all modules (maybe other linkable objects) to restore
  175. //links to them.
  176. function restore_decode_content_links_worker($content,$restore) {
  177. global $CFG;
  178. foreach($restore->mods as $name => $info) {
  179. $function_name = $name."_decode_content_links";
  180. if (function_exists($function_name)) {
  181. $content = $function_name($content,$restore);
  182. }
  183. }
  184. // For the current format, call decode_format_content_links if it exists
  185. static $format_function_name;
  186. if (!isset($format_function_name)) {
  187. $format_function_name = false;
  188. if ($format = get_field('course', 'format', 'id', $restore->course_id)) {
  189. if (file_exists("$CFG->dirroot/course/format/$format/restorelib.php")) {
  190. include_once("$CFG->dirroot/course/format/$format/restorelib.php");
  191. $function_name = $format.'_decode_format_content_links';
  192. if (function_exists($function_name)) {
  193. $format_function_name = $function_name;
  194. }
  195. }
  196. }
  197. }
  198. // If the above worked - then we have a function to call
  199. if ($format_function_name) {
  200. $content = $format_function_name($content, $restore);
  201. }
  202. // For each block, call its encode_content_links method
  203. static $blockobjects = null;
  204. if (!isset($blockobjects)) {
  205. $blockobjects = array();
  206. if ($blocks = get_records('block', 'visible', 1)) {
  207. foreach ($blocks as $block) {
  208. if ($blockobject = block_instance($block->name)) {
  209. $blockobjects[] = $blockobject;
  210. }
  211. }
  212. }
  213. }
  214. foreach ($blockobjects as $blockobject) {
  215. $content = $blockobject->decode_content_links($content,$restore);
  216. }
  217. return $content;
  218. }
  219. //This function converts all the wiki texts in the restored course
  220. //to the Markdown format. Used only for backup files prior 2005041100.
  221. //It calls every module xxxx_convert_wiki2markdown function
  222. function restore_convert_wiki2markdown($restore) {
  223. $status = true;
  224. if (!defined('RESTORE_SILENTLY')) {
  225. echo "<ul>";
  226. }
  227. foreach ($restore->mods as $name => $info) {
  228. //If the module is being restored
  229. if ($info->restore == 1) {
  230. //Check if the xxxx_restore_wiki2markdown exists
  231. $function_name = $name."_restore_wiki2markdown";
  232. if (function_exists($function_name)) {
  233. $status = $function_name($restore);
  234. if (!defined('RESTORE_SILENTLY')) {
  235. echo "<li>".get_string("modulenameplural",$name);
  236. echo '</li>';
  237. }
  238. }
  239. }
  240. }
  241. if (!defined('RESTORE_SILENTLY')) {
  242. echo "</ul>";
  243. }
  244. return $status;
  245. }
  246. //This function receives a wiki text in the restore process and
  247. //return it with every link to modules " modulename:moduleid"
  248. //converted if possible. See the space before modulename!!
  249. function restore_decode_wiki_content($content,$restore) {
  250. global $CFG;
  251. $result = $content;
  252. $searchstring='/ ([a-zA-Z]+):([0-9]+)\(([^)]+)\)/';
  253. //We look for it
  254. preg_match_all($searchstring,$content,$foundset);
  255. //If found, then we are going to look for its new id (in backup tables)
  256. if ($foundset[0]) {
  257. //print_object($foundset); //Debug
  258. //Iterate over foundset[2]. They are the old_ids
  259. foreach($foundset[2] as $old_id) {
  260. //We get the needed variables here (course id)
  261. $rec = backup_getid($restore->backup_unique_code,"course_modules",$old_id);
  262. //Personalize the searchstring
  263. $searchstring='/ ([a-zA-Z]+):'.$old_id.'\(([^)]+)\)/';
  264. //If it is a link to this course, update the link to its new location
  265. if($rec->new_id) {
  266. //Now replace it
  267. $result= preg_replace($searchstring,' $1:'.$rec->new_id.'($2)',$result);
  268. } else {
  269. //It's a foreign link so redirect it to its original URL
  270. $result= preg_replace($searchstring,$restore->original_wwwroot.'/mod/$1/view.php?id='.$old_id.'($2)',$result);
  271. }
  272. }
  273. }
  274. return $result;
  275. }
  276. //This function read the xml file and store it data from the info zone in an object
  277. function restore_read_xml_info ($xml_file) {
  278. //We call the main read_xml function, with todo = INFO
  279. $info = restore_read_xml ($xml_file,"INFO",false);
  280. return $info;
  281. }
  282. //This function read the xml file and store it data from the course header zone in an object
  283. function restore_read_xml_course_header ($xml_file) {
  284. //We call the main read_xml function, with todo = COURSE_HEADER
  285. $info = restore_read_xml ($xml_file,"COURSE_HEADER",false);
  286. return $info;
  287. }
  288. //This function read the xml file and store its data from the blocks in a object
  289. function restore_read_xml_blocks ($restore, $xml_file) {
  290. //We call the main read_xml function, with todo = BLOCKS
  291. $info = restore_read_xml ($xml_file,'BLOCKS',$restore);
  292. return $info;
  293. }
  294. //This function read the xml file and store its data from the sections in a object
  295. function restore_read_xml_sections ($xml_file) {
  296. //We call the main read_xml function, with todo = SECTIONS
  297. $info = restore_read_xml ($xml_file,"SECTIONS",false);
  298. return $info;
  299. }
  300. //This function read the xml file and store its data from the course format in an object
  301. function restore_read_xml_formatdata ($xml_file) {
  302. //We call the main read_xml function, with todo = FORMATDATA
  303. $info = restore_read_xml ($xml_file,'FORMATDATA',false);
  304. return $info;
  305. }
  306. //This function read the xml file and store its data from the metacourse in a object
  307. function restore_read_xml_metacourse ($xml_file) {
  308. //We call the main read_xml function, with todo = METACOURSE
  309. $info = restore_read_xml ($xml_file,"METACOURSE",false);
  310. return $info;
  311. }
  312. //This function read the xml file and store its data from the gradebook in a object
  313. function restore_read_xml_gradebook ($restore, $xml_file) {
  314. //We call the main read_xml function, with todo = GRADEBOOK
  315. $info = restore_read_xml ($xml_file,"GRADEBOOK",$restore);
  316. return $info;
  317. }
  318. //This function read the xml file and store its data from the users in
  319. //backup_ids->info db (and user's id in $info)
  320. function restore_read_xml_users ($restore,$xml_file) {
  321. //We call the main read_xml function, with todo = USERS
  322. $info = restore_read_xml ($xml_file,"USERS",$restore);
  323. return $info;
  324. }
  325. //This function read the xml file and store its data from the messages in
  326. //backup_ids->message backup_ids->message_read and backup_ids->contact and db (and their counters in info)
  327. function restore_read_xml_messages ($restore,$xml_file) {
  328. //We call the main read_xml function, with todo = MESSAGES
  329. $info = restore_read_xml ($xml_file,"MESSAGES",$restore);
  330. return $info;
  331. }
  332. //This function read the xml file and store its data from the blogs in
  333. //backup_ids->blog and backup_ids->blog_tag and db (and their counters in info)
  334. function restore_read_xml_blogs ($restore,$xml_file) {
  335. //We call the main read_xml function, with todo = BLOGS
  336. $info = restore_read_xml ($xml_file,"BLOGS",$restore);
  337. return $info;
  338. }
  339. //This function read the xml file and store its data from the questions in
  340. //backup_ids->info db (and category's id in $info)
  341. function restore_read_xml_questions ($restore,$xml_file) {
  342. //We call the main read_xml function, with todo = QUESTIONS
  343. $info = restore_read_xml ($xml_file,"QUESTIONS",$restore);
  344. return $info;
  345. }
  346. //This function read the xml file and store its data from the scales in
  347. //backup_ids->info db (and scale's id in $info)
  348. function restore_read_xml_scales ($restore,$xml_file) {
  349. //We call the main read_xml function, with todo = SCALES
  350. $info = restore_read_xml ($xml_file,"SCALES",$restore);
  351. return $info;
  352. }
  353. //This function read the xml file and store its data from the groups in
  354. //backup_ids->info db (and group's id in $info)
  355. function restore_read_xml_groups ($restore,$xml_file) {
  356. //We call the main read_xml function, with todo = GROUPS
  357. $info = restore_read_xml ($xml_file,"GROUPS",$restore);
  358. return $info;
  359. }
  360. //This function read the xml file and store its data from the groupings in
  361. //backup_ids->info db (and grouping's id in $info)
  362. function restore_read_xml_groupings ($restore,$xml_file) {
  363. //We call the main read_xml function, with todo = GROUPINGS
  364. $info = restore_read_xml ($xml_file,"GROUPINGS",$restore);
  365. return $info;
  366. }
  367. //This function read the xml file and store its data from the groupings in
  368. //backup_ids->info db (and grouping's id in $info)
  369. function restore_read_xml_groupings_groups ($restore,$xml_file) {
  370. //We call the main read_xml function, with todo = GROUPINGS
  371. $info = restore_read_xml ($xml_file,"GROUPINGSGROUPS",$restore);
  372. return $info;
  373. }
  374. //This function read the xml file and store its data from the events (course) in
  375. //backup_ids->info db (and event's id in $info)
  376. function restore_read_xml_events ($restore,$xml_file) {
  377. //We call the main read_xml function, with todo = EVENTS
  378. $info = restore_read_xml ($xml_file,"EVENTS",$restore);
  379. return $info;
  380. }
  381. //This function read the xml file and store its data from the modules in
  382. //backup_ids->info
  383. function restore_read_xml_modules ($restore,$xml_file) {
  384. //We call the main read_xml function, with todo = MODULES
  385. $info = restore_read_xml ($xml_file,"MODULES",$restore);
  386. return $info;
  387. }
  388. //This function read the xml file and store its data from the logs in
  389. //backup_ids->info
  390. function restore_read_xml_logs ($restore,$xml_file) {
  391. //We call the main read_xml function, with todo = LOGS
  392. $info = restore_read_xml ($xml_file,"LOGS",$restore);
  393. return $info;
  394. }
  395. function restore_read_xml_roles ($xml_file) {
  396. //We call the main read_xml function, with todo = ROLES
  397. $info = restore_read_xml ($xml_file,"ROLES",false);
  398. return $info;
  399. }
  400. //This function prints the contents from the info parammeter passed
  401. function restore_print_info ($info) {
  402. global $CFG;
  403. $status = true;
  404. if ($info) {
  405. $table = new object();
  406. //This is tha align to every ingo table
  407. $table->align = array ("right","left");
  408. //This is the nowrap clause
  409. $table->wrap = array ("","nowrap");
  410. //The width
  411. $table->width = "70%";
  412. //Put interesting info in table
  413. //The backup original name
  414. $tab[0][0] = "<b>".get_string("backuporiginalname").":</b>";
  415. $tab[0][1] = $info->backup_name;
  416. //The moodle version
  417. $tab[1][0] = "<b>".get_string("moodleversion").":</b>";
  418. $tab[1][1] = $info->backup_moodle_release." (".$info->backup_moodle_version.")";
  419. //The backup version
  420. $tab[2][0] = "<b>".get_string("backupversion").":</b>";
  421. $tab[2][1] = $info->backup_backup_release." (".$info->backup_backup_version.")";
  422. //The backup date
  423. $tab[3][0] = "<b>".get_string("backupdate").":</b>";
  424. $tab[3][1] = userdate($info->backup_date);
  425. //Is this the same Moodle install?
  426. if (!empty($info->original_siteidentifier)) {
  427. $tab[4][0] = "<b>".get_string("backupfromthissite").":</b>";
  428. if (backup_is_same_site($info)) {
  429. $tab[4][1] = get_string('yes');
  430. } else {
  431. $tab[4][1] = get_string('no');
  432. }
  433. }
  434. //Print title
  435. print_heading(get_string("backup").":");
  436. $table->data = $tab;
  437. //Print backup general info
  438. print_table($table);
  439. if ($info->backup_backup_version <= 2005070500) {
  440. notify(get_string('backupnonisowarning')); // Message informing that this backup may not work!
  441. }
  442. //Now backup contents in another table
  443. $tab = array();
  444. //First mods info
  445. $mods = $info->mods;
  446. $elem = 0;
  447. foreach ($mods as $key => $mod) {
  448. $tab[$elem][0] = "<b>".get_string("modulenameplural",$key).":</b>";
  449. if ($mod->backup == "false") {
  450. $tab[$elem][1] = get_string("notincluded");
  451. } else {
  452. if ($mod->userinfo == "true") {
  453. $tab[$elem][1] = get_string("included")." ".get_string("withuserdata");
  454. } else {
  455. $tab[$elem][1] = get_string("included")." ".get_string("withoutuserdata");
  456. }
  457. if (isset($mod->instances) && is_array($mod->instances) && count($mod->instances)) {
  458. foreach ($mod->instances as $instance) {
  459. if ($instance->backup) {
  460. $elem++;
  461. $tab[$elem][0] = $instance->name;
  462. if ($instance->userinfo == 'true') {
  463. $tab[$elem][1] = get_string("included")." ".get_string("withuserdata");
  464. } else {
  465. $tab[$elem][1] = get_string("included")." ".get_string("withoutuserdata");
  466. }
  467. }
  468. }
  469. }
  470. }
  471. $elem++;
  472. }
  473. //Metacourse info
  474. $tab[$elem][0] = "<b>".get_string("metacourse").":</b>";
  475. if ($info->backup_metacourse == "true") {
  476. $tab[$elem][1] = get_string("yes");
  477. } else {
  478. $tab[$elem][1] = get_string("no");
  479. }
  480. $elem++;
  481. //Users info
  482. $tab[$elem][0] = "<b>".get_string("users").":</b>";
  483. $tab[$elem][1] = get_string($info->backup_users);
  484. $elem++;
  485. //Logs info
  486. $tab[$elem][0] = "<b>".get_string("logs").":</b>";
  487. if ($info->backup_logs == "true") {
  488. $tab[$elem][1] = get_string("yes");
  489. } else {
  490. $tab[$elem][1] = get_string("no");
  491. }
  492. $elem++;
  493. //User Files info
  494. $tab[$elem][0] = "<b>".get_string("userfiles").":</b>";
  495. if ($info->backup_user_files == "true") {
  496. $tab[$elem][1] = get_string("yes");
  497. } else {
  498. $tab[$elem][1] = get_string("no");
  499. }
  500. $elem++;
  501. //Course Files info
  502. $tab[$elem][0] = "<b>".get_string("coursefiles").":</b>";
  503. if ($info->backup_course_files == "true") {
  504. $tab[$elem][1] = get_string("yes");
  505. } else {
  506. $tab[$elem][1] = get_string("no");
  507. }
  508. $elem++;
  509. //site Files info
  510. $tab[$elem][0] = "<b>".get_string("sitefiles").":</b>";
  511. if (isset($info->backup_site_files) && $info->backup_site_files == "true") {
  512. $tab[$elem][1] = get_string("yes");
  513. } else {
  514. $tab[$elem][1] = get_string("no");
  515. }
  516. $elem++;
  517. //gradebook history info
  518. $tab[$elem][0] = "<b>".get_string('gradebookhistories', 'grades').":</b>";
  519. if (isset($info->gradebook_histories) && $info->gradebook_histories == "true") {
  520. $tab[$elem][1] = get_string("yes");
  521. } else {
  522. $tab[$elem][1] = get_string("no");
  523. }
  524. $elem++;
  525. //Messages info (only showed if present)
  526. if ($info->backup_messages == 'true') {
  527. $tab[$elem][0] = "<b>".get_string('messages','message').":</b>";
  528. $tab[$elem][1] = get_string('yes');
  529. $elem++;
  530. } else {
  531. //Do nothing
  532. }
  533. $elem++;
  534. //Blogs info (only showed if present)
  535. if (isset($info->backup_blogs) && $info->backup_blogs == 'true') {
  536. $tab[$elem][0] = "<b>".get_string('blogs','blog').":</b>";
  537. $tab[$elem][1] = get_string('yes');
  538. $elem++;
  539. } else {
  540. //Do nothing
  541. }
  542. $table->data = $tab;
  543. //Print title
  544. print_heading(get_string("backupdetails").":");
  545. //Print backup general info
  546. print_table($table);
  547. } else {
  548. $status = false;
  549. }
  550. return $status;
  551. }
  552. //This function prints the contents from the course_header parammeter passed
  553. function restore_print_course_header ($course_header) {
  554. $status = true;
  555. if ($course_header) {
  556. $table = new object();
  557. //This is tha align to every ingo table
  558. $table->align = array ("right","left");
  559. //The width
  560. $table->width = "70%";
  561. //Put interesting course header in table
  562. //The course name
  563. $tab[0][0] = "<b>".get_string("name").":</b>";
  564. $tab[0][1] = $course_header->course_fullname." (".$course_header->course_shortname.")";
  565. //The course summary
  566. $tab[1][0] = "<b>".get_string("summary").":</b>";
  567. $tab[1][1] = $course_header->course_summary;
  568. $table->data = $tab;
  569. //Print title
  570. print_heading(get_string("course").":");
  571. //Print backup course header info
  572. print_table($table);
  573. } else {
  574. $status = false;
  575. }
  576. return $status;
  577. }
  578. //This function create a new course record.
  579. //When finished, course_header contains the id of the new course
  580. function restore_create_new_course($restore,&$course_header) {
  581. global $CFG;
  582. $status = true;
  583. $fullname = $course_header->course_fullname;
  584. $shortname = $course_header->course_shortname;
  585. $currentfullname = "";
  586. $currentshortname = "";
  587. $counter = 0;
  588. //Iteratere while the name exists
  589. do {
  590. if ($counter) {
  591. $suffixfull = " ".get_string("copyasnoun")." ".$counter;
  592. $suffixshort = "_".$counter;
  593. } else {
  594. $suffixfull = "";
  595. $suffixshort = "";
  596. }
  597. $currentfullname = $fullname.$suffixfull;
  598. // Limit the size of shortname - database column accepts <= 100 chars
  599. $currentshortname = substr($shortname, 0, 100 - strlen($suffixshort)).$suffixshort;
  600. $coursefull = get_record("course","fullname",addslashes($currentfullname));
  601. $courseshort = get_record("course","shortname",addslashes($currentshortname));
  602. $counter++;
  603. } while ($coursefull || $courseshort);
  604. //New name = currentname
  605. $course_header->course_fullname = $currentfullname;
  606. $course_header->course_shortname = $currentshortname;
  607. // first try to get it from restore
  608. if ($restore->restore_restorecatto) {
  609. $category = get_record('course_categories', 'id', $restore->restore_restorecatto);
  610. }
  611. // else we try to get it from the xml file
  612. //Now calculate the category
  613. if (empty($category)) {
  614. $category = get_record("course_categories","id",$course_header->category->id,
  615. "name",addslashes($course_header->category->name));
  616. }
  617. //If no exists, try by name only
  618. if (!$category) {
  619. $category = get_record("course_categories","name",addslashes($course_header->category->name));
  620. }
  621. //If no exists, get category id 1
  622. if (!$category) {
  623. $category = get_record("course_categories","id","1");
  624. }
  625. //If category 1 doesn'exists, lets create the course category (get it from backup file)
  626. if (!$category) {
  627. $ins_category = new object();
  628. $ins_category->name = addslashes($course_header->category->name);
  629. $ins_category->parent = 0;
  630. $ins_category->sortorder = 0;
  631. $ins_category->coursecount = 0;
  632. $ins_category->visible = 0; //To avoid interferences with the rest of the site
  633. $ins_category->timemodified = time();
  634. $newid = insert_record("course_categories",$ins_category);
  635. $category->id = $newid;
  636. $category->name = $course_header->category->name;
  637. }
  638. //If exists, put new category id
  639. if ($category) {
  640. $course_header->category->id = $category->id;
  641. $course_header->category->name = $category->name;
  642. //Error, cannot locate category
  643. } else {
  644. $course_header->category->id = 0;
  645. $course_header->category->name = get_string("unknowncategory");
  646. $status = false;
  647. }
  648. //Create the course_object
  649. if ($status) {
  650. $course = new object();
  651. $course->category = addslashes($course_header->category->id);
  652. $course->password = addslashes($course_header->course_password);
  653. $course->fullname = addslashes($course_header->course_fullname);
  654. $course->shortname = addslashes($course_header->course_shortname);
  655. $course->idnumber = addslashes($course_header->course_idnumber);
  656. $course->idnumber = ''; //addslashes($course_header->course_idnumber); // we don't want this at all.
  657. $course->summary = addslashes($course_header->course_summary);
  658. $course->format = addslashes($course_header->course_format);
  659. $course->showgrades = addslashes($course_header->course_showgrades);
  660. $course->newsitems = addslashes($course_header->course_newsitems);
  661. $course->teacher = addslashes($course_header->course_teacher);
  662. $course->teachers = addslashes($course_header->course_teachers);
  663. $course->student = addslashes($course_header->course_student);
  664. $course->students = addslashes($course_header->course_students);
  665. $course->guest = addslashes($course_header->course_guest);
  666. $course->startdate = addslashes($course_header->course_startdate);
  667. $course->startdate += $restore->course_startdateoffset;
  668. $course->numsections = addslashes($course_header->course_numsections);
  669. //$course->showrecent = addslashes($course_header->course_showrecent); INFO: This is out in 1.3
  670. $course->maxbytes = addslashes($course_header->course_maxbytes);
  671. $course->showreports = addslashes($course_header->course_showreports);
  672. if (isset($course_header->course_groupmode)) {
  673. $course->groupmode = addslashes($course_header->course_groupmode);
  674. }
  675. if (isset($course_header->course_groupmodeforce)) {
  676. $course->groupmodeforce = addslashes($course_header->course_groupmodeforce);
  677. }
  678. if (isset($course_header->course_defaultgroupingid)) {
  679. //keep the original now - convert after groupings restored
  680. $course->defaultgroupingid = addslashes($course_header->course_defaultgroupingid);
  681. }
  682. $course->lang = addslashes($course_header->course_lang);
  683. $course->theme = addslashes($course_header->course_theme);
  684. $course->cost = addslashes($course_header->course_cost);
  685. $course->currency = isset($course_header->course_currency)?addslashes($course_header->course_currency):'';
  686. $course->marker = addslashes($course_header->course_marker);
  687. $course->visible = addslashes($course_header->course_visible);
  688. $course->hiddensections = addslashes($course_header->course_hiddensections);
  689. $course->timecreated = addslashes($course_header->course_timecreated);
  690. $course->timemodified = addslashes($course_header->course_timemodified);
  691. $course->metacourse = addslashes($course_header->course_metacourse);
  692. $course->expirynotify = isset($course_header->course_expirynotify) ? addslashes($course_header->course_expirynotify):0;
  693. $course->notifystudents = isset($course_header->course_notifystudents) ? addslashes($course_header->course_notifystudents) : 0;
  694. $course->expirythreshold = isset($course_header->course_expirythreshold) ? addslashes($course_header->course_expirythreshold) : 0;
  695. $course->enrollable = isset($course_header->course_enrollable) ? addslashes($course_header->course_enrollable) : 1;
  696. $course->enrolstartdate = isset($course_header->course_enrolstartdate) ? addslashes($course_header->course_enrolstartdate) : 0;
  697. if ($course->enrolstartdate) { //Roll course dates
  698. $course->enrolstartdate += $restore->course_startdateoffset;
  699. }
  700. $course->enrolenddate = isset($course_header->course_enrolenddate) ? addslashes($course_header->course_enrolenddate) : 0;
  701. if ($course->enrolenddate) { //Roll course dates
  702. $course->enrolenddate += $restore->course_startdateoffset;
  703. }
  704. $course->enrolperiod = addslashes($course_header->course_enrolperiod);
  705. //Calculate sortorder field
  706. $sortmax = get_record_sql('SELECT MAX(sortorder) AS max
  707. FROM ' . $CFG->prefix . 'course
  708. WHERE category=' . $course->category);
  709. if (!empty($sortmax->max)) {
  710. $course->sortorder = $sortmax->max + 1;
  711. unset($sortmax);
  712. } else {
  713. $course->sortorder = 100;
  714. }
  715. //Now, recode some languages (Moodle 1.5)
  716. if ($course->lang == 'ma_nt') {
  717. $course->lang = 'mi_nt';
  718. }
  719. //Disable course->metacourse if avoided in restore config
  720. if (!$restore->metacourse) {
  721. $course->metacourse = 0;
  722. }
  723. //Check if the theme exists in destination server
  724. $themes = get_list_of_themes();
  725. if (!in_array($course->theme, $themes)) {
  726. $course->theme = '';
  727. }
  728. //Now insert the record
  729. $newid = insert_record("course",$course);
  730. if ($newid) {
  731. //save old and new course id
  732. backup_putid ($restore->backup_unique_code,"course",$course_header->course_id,$newid);
  733. //Replace old course_id in course_header
  734. $course_header->course_id = $newid;
  735. } else {
  736. $status = false;
  737. }
  738. }
  739. return $status;
  740. }
  741. //This function creates all the block stuff when restoring courses
  742. //It calls selectively to restore_create_block_instances() for 1.5
  743. //and above backups. Upwards compatible with old blocks.
  744. function restore_create_blocks($restore, $backup_block_format, $blockinfo, $xml_file) {
  745. global $CFG;
  746. $status = true;
  747. blocks_delete_all_on_page(PAGE_COURSE_VIEW, $restore->course_id);
  748. if (empty($backup_block_format)) { // This is a backup from Moodle < 1.5
  749. if (empty($blockinfo)) {
  750. // Looks like it's from Moodle < 1.3. Let's give the course default blocks...
  751. $newpage = page_create_object(PAGE_COURSE_VIEW, $restore->course_id);
  752. blocks_repopulate_page($newpage);
  753. } else {
  754. // We just have a blockinfo field, this is a legacy 1.4 or 1.3 backup
  755. $blockrecords = get_records_select('block', '', '', 'name, id');
  756. $temp_blocks_l = array();
  757. $temp_blocks_r = array();
  758. @list($temp_blocks_l, $temp_blocks_r) = explode(':', $blockinfo);
  759. $temp_blocks = array(BLOCK_POS_LEFT => explode(',', $temp_blocks_l), BLOCK_POS_RIGHT => explode(',', $temp_blocks_r));
  760. foreach($temp_blocks as $blockposition => $blocks) {
  761. $blockweight = 0;
  762. foreach($blocks as $blockname) {
  763. if(!isset($blockrecords[$blockname])) {
  764. // We don't know anything about this block!
  765. continue;
  766. }
  767. $blockinstance = new stdClass;
  768. // Remove any - prefix before doing the name-to-id mapping
  769. if(substr($blockname, 0, 1) == '-') {
  770. $blockname = substr($blockname, 1);
  771. $blockinstance->visible = 0;
  772. } else {
  773. $blockinstance->visible = 1;
  774. }
  775. $blockinstance->blockid = $blockrecords[$blockname]->id;
  776. $blockinstance->pageid = $restore->course_id;
  777. $blockinstance->pagetype = PAGE_COURSE_VIEW;
  778. $blockinstance->position = $blockposition;
  779. $blockinstance->weight = $blockweight;
  780. if(!$status = insert_record('block_instance', $blockinstance)) {
  781. $status = false;
  782. }
  783. ++$blockweight;
  784. }
  785. }
  786. }
  787. } else if($backup_block_format == 'instances') {
  788. $status = restore_create_block_instances($restore,$xml_file);
  789. }
  790. return $status;
  791. }
  792. //This function creates all the block_instances from xml when restoring in a
  793. //new course
  794. function restore_create_block_instances($restore,$xml_file) {
  795. global $CFG;
  796. $status = true;
  797. //Check it exists
  798. if (!file_exists($xml_file)) {
  799. $status = false;
  800. }
  801. //Get info from xml
  802. if ($status) {
  803. $info = restore_read_xml_blocks($restore,$xml_file);
  804. }
  805. if(empty($info->instances)) {
  806. return $status;
  807. }
  808. // First of all, iterate over the blocks to see which distinct pages we have
  809. // in our hands and arrange the blocks accordingly.
  810. $pageinstances = array();
  811. foreach($info->instances as $instance) {
  812. //pagetype and pageid black magic, we have to handle the case of blocks for the
  813. //course, blocks from other pages in that course etc etc etc.
  814. if($instance->pagetype == PAGE_COURSE_VIEW) {
  815. // This one's easy...
  816. $instance->pageid = $restore->course_id;
  817. } else if (!empty($CFG->showblocksonmodpages)) {
  818. $parts = explode('-', $instance->pagetype);
  819. if($parts[0] == 'mod') {
  820. if(!$restore->mods[$parts[1]]->restore) {
  821. continue;
  822. }
  823. $getid = backup_getid($restore->backup_unique_code, $parts[1], $instance->pageid);
  824. if (empty($getid->new_id)) {
  825. // Failed, perhaps the module was not included in the restore MDL-13554
  826. continue;
  827. }
  828. $instance->pageid = $getid->new_id;
  829. }
  830. else {
  831. // Not invented here ;-)
  832. continue;
  833. }
  834. } else {
  835. // do not restore activity blocks if disabled
  836. continue;
  837. }
  838. if(!isset($pageinstances[$instance->pagetype])) {
  839. $pageinstances[$instance->pagetype] = array();
  840. }
  841. if(!isset($pageinstances[$instance->pagetype][$instance->pageid])) {
  842. $pageinstances[$instance->pagetype][$instance->pageid] = array();
  843. }
  844. $pageinstances[$instance->pagetype][$instance->pageid][] = $instance;
  845. }
  846. $blocks = get_records_select('block', 'visible = 1', '', 'name, id, multiple');
  847. // For each type of page we have restored
  848. foreach($pageinstances as $thistypeinstances) {
  849. // For each page id of that type
  850. foreach($thistypeinstances as $thisidinstances) {
  851. $addedblocks = array();
  852. $maxweights = array();
  853. // For each block instance in that page
  854. foreach($thisidinstances as $instance) {
  855. if(!isset($blocks[$instance->name])) {
  856. //We are trying to restore a block we don't have...
  857. continue;
  858. }
  859. //If we have already added this block once and multiples aren't allowed, disregard it
  860. if(!$blocks[$instance->name]->multiple && isset($addedblocks[$instance->name])) {
  861. continue;
  862. }
  863. //If its the first block we add to a new position, start weight counter equal to 0.
  864. if(empty($maxweights[$instance->position])) {
  865. $maxweights[$instance->position] = 0;
  866. }
  867. //If the instance weight is greater than the weight counter (we skipped some earlier
  868. //blocks most probably), bring it back in line.
  869. if($instance->weight > $maxweights[$instance->position]) {
  870. $instance->weight = $maxweights[$instance->position];
  871. }
  872. //Add this instance
  873. $instance->blockid = $blocks[$instance->name]->id;
  874. // This will only be set if we come from 1.7 and above backups
  875. // Also, must do this before insert (insert_record unsets id)
  876. if (!empty($instance->id)) {
  877. $oldid = $instance->id;
  878. } else {
  879. $oldid = 0;
  880. }
  881. if ($instance->id = insert_record('block_instance', $instance)) {
  882. // Create block instance
  883. if (!$blockobj = block_instance($instance->name, $instance)) {
  884. $status = false;
  885. break;
  886. }
  887. // Run the block restore if needed
  888. if ($blockobj->backuprestore_instancedata_used()) {
  889. // Get restore information
  890. $data = backup_getid($restore->backup_unique_code,'block_instance',$oldid);
  891. $data->new_id = $instance->id; // For completeness
  892. if (!$blockobj->instance_restore($restore, $data)) {
  893. $status = false;
  894. break;
  895. }
  896. }
  897. // Save oldid after block restore process because info will be over-written with blank string
  898. if ($oldid) {
  899. backup_putid ($restore->backup_unique_code,"block_instance",$oldid,$instance->id);
  900. }
  901. } else {
  902. $status = false;
  903. break;
  904. }
  905. //Get an object for the block and tell it it's been restored so it can update dates
  906. //etc. if necessary
  907. if ($blockobj = block_instance($instance->name,$instance)) {
  908. $blockobj->after_restore($restore);
  909. }
  910. //Now we can increment the weight counter
  911. ++$maxweights[$instance->position];
  912. //Keep track of block types we have already added
  913. $addedblocks[$instance->name] = true;
  914. }
  915. }
  916. }
  917. return $status;
  918. }
  919. //This function creates all the course_sections and course_modules from xml
  920. //when restoring in a new course or simply checks sections and create records
  921. //in backup_ids when restoring in a existing course
  922. function restore_create_sections(&$restore, $xml_file) {
  923. global $CFG,$db;
  924. $status = true;
  925. //Check it exists
  926. if (!file_exists($xml_file)) {
  927. $status = false;
  928. }
  929. //Get info from xml
  930. if ($status) {
  931. $info = restore_read_xml_sections($xml_file);
  932. }
  933. //Put the info in the DB, recoding ids and saving the in backup tables
  934. $sequence = "";
  935. if ($info) {
  936. //For each, section, save it to db
  937. foreach ($info->sections as $key => $sect) {
  938. $sequence = "";
  939. $section = new object();
  940. $section->course = $restore->course_id;
  941. $section->section = $sect->number;
  942. $section->summary = backup_todb($sect->summary);
  943. $section->visible = $sect->visible;
  944. $section->sequence = "";
  945. //Now calculate the section's newid
  946. $newid = 0;
  947. if ($restore->restoreto == RESTORETO_NEW_COURSE) {
  948. //Save it to db (only if restoring to new course)
  949. $newid = insert_record("course_sections",$section);
  950. } else {
  951. //Get section id when restoring in existing course
  952. $rec = get_record("course_sections","course",$restore->course_id,
  953. "section",$section->section);
  954. //If section exists, has empty summary and backup has some summary, use it. MDL-8848
  955. if ($rec && empty($rec->summary) && !empty($section->summary)) {
  956. $rec->summary = $section->summary;
  957. update_record("course_sections", $rec);
  958. }
  959. //If that section doesn't exist, get section 0 (every mod will be
  960. //asigned there
  961. if(!$rec) {
  962. $rec = get_record("course_sections","course",$restore->course_id,
  963. "section","0");
  964. }
  965. //New check. If section 0 doesn't exist, insert it here !!
  966. //Teorically this never should happen but, in practice, some users
  967. //have reported this issue.
  968. if(!$rec) {
  969. $zero_sec = new object();
  970. $zero_sec->course = $restore->course_id;
  971. $zero_sec->section = 0;
  972. $zero_sec->summary = "";
  973. $zero_sec->sequence = "";
  974. $newid = insert_record("course_sections",$zero_sec);
  975. $rec->id = $newid;
  976. $rec->sequence = "";
  977. }
  978. $newid = $rec->id;
  979. $sequence = $rec->sequence;
  980. }
  981. if ($newid) {
  982. //save old and new section id
  983. backup_putid ($restore->backup_unique_code,"course_sections",$key,$newid);
  984. } else {
  985. $status = false;
  986. }
  987. //If all is OK, go with associated mods
  988. if ($status) {
  989. //If we have mods in the section
  990. if (!empty($sect->mods)) {
  991. //For each mod inside section
  992. foreach ($sect->mods as $keym => $mod) {
  993. // Yu: This part is called repeatedly for every instance,
  994. // so it is necessary to set the granular flag and check isset()
  995. // when the first instance of this type of mod is processed.
  996. //if (!isset($restore->mods[$mod->type]->granular) && isset($restore->mods[$mod->type]->instances) && is_array($restore->mods[$mod->type]->instances)) {
  997. if (!isset($restore->mods[$mod->type]->granular)) {
  998. if (isset($restore->mods[$mod->type]->instances) && is_array($restore->mods[$mod->type]->instances)) {
  999. // This defines whether we want to restore specific
  1000. // instances of the modules (granular restore), or
  1001. // whether we don't care and just want to restore
  1002. // all module instances (non-granular).
  1003. $restore->mods[$mod->type]->granular = true;
  1004. } else {
  1005. $restore->mods[$mod->type]->granular = false;
  1006. }
  1007. }
  1008. //Check if we've to restore this module (and instance)
  1009. if (!empty($restore->mods[$mod->type]->restore)) {
  1010. if (empty($restore->mods[$mod->type]->granular) // we don't care about per instance
  1011. || (array_key_exists($mod->instance,$restore->mods[$mod->type]->instances)
  1012. && !empty($restore->mods[$mod->type]->instances[$mod->instance]->restore))) {
  1013. //Get the module id from modules
  1014. $module = get_record("modules","name",$mod->type);
  1015. if ($module) {
  1016. $course_module = new object();
  1017. $course_module->course = $restore->course_id;
  1018. $course_module->module = $module->id;
  1019. $course_module->section = $newid;
  1020. $course_module->added = $mod->added;
  1021. $course_module->score = $mod->score;
  1022. $course_module->indent = $mod->indent;
  1023. $course_module->visible = $mod->visible;
  1024. $course_module->groupmode = $mod->groupmode;
  1025. if ($mod->groupingid and $grouping = restore_grouping_getid($restore, $mod->groupingid)) {
  1026. $course_module->groupingid = $grouping->new_id;
  1027. } else {
  1028. $course_module->groupingid = 0;
  1029. }
  1030. $course_module->groupmembersonly = $mod->groupmembersonly;
  1031. $course_module->instance = 0;
  1032. //NOTE: The instance (new) is calculated and updated in db in the
  1033. // final step of the restore. We don't know it yet.
  1034. //print_object($course_module); //Debug
  1035. //Save it to db
  1036. if ($mod->idnumber) {
  1037. if (grade_verify_idnumber($mod->idnumber, $restore->course_id)) {
  1038. $course_module->idnumber = $mod->idnumber;
  1039. }
  1040. }
  1041. $newidmod = insert_record("course_modules", addslashes_recursive($course_module));
  1042. if ($newidmod) {
  1043. //save old and new module id
  1044. //In the info field, we save the original instance of the module
  1045. //to use it later
  1046. backup_putid ($restore->backup_unique_code,"course_modules",
  1047. $keym,$newidmod,$mod->instance);
  1048. $restore->mods[$mod->type]->instances[$mod->instance]->restored_as_course_module = $newidmod;
  1049. } else {
  1050. $status = false;
  1051. }
  1052. //Now, calculate the sequence field
  1053. if ($status) {
  1054. if ($sequence) {
  1055. $sequence .= ",".$newidmod;
  1056. } else {
  1057. $sequence = $newidmod;
  1058. }
  1059. }
  1060. } else {
  1061. $status = false;
  1062. }
  1063. }
  1064. }
  1065. }
  1066. }
  1067. }
  1068. //If all is OK, update sequence field in course_sections
  1069. if ($status) {
  1070. if (isset($sequence)) {
  1071. $update_rec = new object();
  1072. $update_rec->id = $newid;
  1073. $update_rec->sequence = $sequence;
  1074. $status = update_record("course_sections",$update_rec);
  1075. }
  1076. }
  1077. }
  1078. } else {
  1079. $status = false;
  1080. }
  1081. return $status;
  1082. }
  1083. //Called to set up any course-format specific data that may be in the file
  1084. function restore_set_format_data($restore,$xml_file) {
  1085. global $CFG,$db;
  1086. $status = true;
  1087. //Check it exists
  1088. if (!file_exists($xml_file)) {
  1089. return false;
  1090. }
  1091. //Load data from XML to info
  1092. if(!($info = restore_read_xml_formatdata($xml_file))) {
  1093. return false;
  1094. }
  1095. //Process format data if there is any
  1096. if (isset($info->format_data)) {
  1097. if(!$format=get_field('course','format','id',$restore->course_id)) {
  1098. return false;
  1099. }
  1100. // If there was any data then it must have a restore method
  1101. $file=$CFG->dirroot."/course/format/$format/restorelib.php";
  1102. if(!file_exists($file)) {
  1103. return false;
  1104. }
  1105. require_once($file);
  1106. $function=$format.'_restore_format_data';
  1107. if(!function_exists($function)) {
  1108. return false;
  1109. }
  1110. return $function($restore,$info->format_data);
  1111. }
  1112. // If we got here then there's no data, but that's cool
  1113. return true;
  1114. }
  1115. //This function creates all the metacourse data from xml, notifying
  1116. //about each incidence
  1117. function restore_create_metacourse($restore,$xml_file) {
  1118. global $CFG,$db;
  1119. $status = true;
  1120. //Check it exists
  1121. if (!file_exists($xml_file)) {
  1122. $status = false;
  1123. }
  1124. //Get info from xml
  1125. if ($status) {
  1126. //Load data from XML to info
  1127. $info = restore_read_xml_metacourse($xml_file);
  1128. }
  1129. //Process info about metacourse
  1130. if ($status and $info) {
  1131. //Process child records
  1132. if (!empty($info->childs)) {
  1133. foreach ($info->childs as $child) {
  1134. $dbcourse = false;
  1135. $dbmetacourse = false;
  1136. //Check if child course exists in destination server
  1137. //(by id in the same server or by idnumber and shortname in other server)
  1138. if (backup_is_same_site($restore)) {
  1139. //Same server, lets see by id
  1140. $dbcourse = get_record('course','id',$child->id);
  1141. } else {
  1142. //Different server, lets see by idnumber and shortname, and only ONE record
  1143. $dbcount = count_records('course','idnumber',$child->idnumber,'shortname',$child->shortname);
  1144. if ($dbcount == 1) {
  1145. $dbcourse = get_record('course','idnumber',$child->idnumber,'shortname',$child->shortname);
  1146. }
  1147. }
  1148. //If child course has been found, insert data
  1149. if ($dbcourse) {
  1150. $dbmetacourse->child_course = $dbcourse->id;
  1151. $dbmetacourse->parent_course = $restore->course_id;
  1152. $status = insert_record ('course_meta',$dbmetacourse);
  1153. } else {
  1154. //Child course not found, notice!
  1155. if (!defined('RESTORE_SILENTLY')) {
  1156. echo '<ul><li>'.get_string ('childcoursenotfound').' ('.$child->id.'/'.$child->idnumber.'/'.$child->shortname.')</li></ul>';
  1157. }
  1158. }
  1159. }
  1160. //Now, recreate student enrolments...
  1161. sync_metacourse($restore->course_id);
  1162. }
  1163. //Process parent records
  1164. if (!empty($info->parents)) {
  1165. foreach ($info->parents as $parent) {
  1166. $dbcourse = false;
  1167. $dbmetacourse = false;
  1168. //Check if parent course exists in destination server
  1169. //(by id in the same server or by idnumber and shortname in other server)
  1170. if (backup_is_same_site($restore)) {
  1171. //Same server, lets see by id
  1172. $dbcourse = get_record('course','id',$parent->id);
  1173. } else {
  1174. //Different server, lets see by idnumber and shortname, and only ONE record
  1175. $dbcount = count_records('course','idnumber',$parent->idnumber,'shortname',$parent->shortname);
  1176. if ($dbcount == 1) {
  1177. $dbcourse = get_record('course','idnumber',$parent->idnumber,'shortname',$parent->shortname);
  1178. }
  1179. }
  1180. //If parent course has been found, insert data if it is a metacourse
  1181. if ($dbcourse) {
  1182. if ($dbcourse->metacourse) {
  1183. $dbmetacourse->parent_course = $dbcourse->id;
  1184. $dbmetacourse->child_course = $restore->course_id;
  1185. $status = insert_record ('course_meta',$dbmetacourse);
  1186. //Now, recreate student enrolments in parent course
  1187. sync_metacourse($dbcourse->id);
  1188. } else {
  1189. //Parent course isn't metacourse, notice!
  1190. if (!defined('RESTORE_SILENTLY')) {
  1191. echo '<ul><li>'.get_string ('parentcoursenotmetacourse').' ('.$parent->id.'/'.$parent->idnumber.'/'.$parent->shortname.')</li></ul>';
  1192. }
  1193. }
  1194. } else {
  1195. //Parent course not found, notice!
  1196. if (!defined('RESTORE_SILENTLY')) {
  1197. echo '<ul><li>'.get_string ('parentcoursenotfound').' ('.$parent->id.'/'.$parent->idnumber.'/'.$parent->shortname.')</li></ul>';
  1198. }
  1199. }
  1200. }
  1201. }
  1202. }
  1203. return $status;
  1204. }
  1205. /**
  1206. * This function migrades all the pre 1.9 gradebook data from xml
  1207. */
  1208. function restore_migrate_old_gradebook($restore,$xml_file) {
  1209. global $CFG;
  1210. $status = true;
  1211. //Check it exists
  1212. if (!file_exists($xml_file)) {
  1213. return false;
  1214. }
  1215. // Get info from xml
  1216. // info will contain the number of record to process
  1217. $info = restore_read_xml_gradebook($restore, $xml_file);
  1218. // If we have info, then process
  1219. if (empty($info)) {
  1220. return $status;
  1221. }
  1222. // make sure top course category exists
  1223. $course_category = grade_category::fetch_course_category($restore->course_id);
  1224. $course_category->load_grade_item();
  1225. // we need to know if all grade items that were backed up are being restored
  1226. // if that is not the case, we do not restore grade categories nor gradeitems of category type or course type
  1227. // i.e. the aggregated grades of that category
  1228. $restoreall = true; // set to false if any grade_item is not selected/restored
  1229. $importing = !empty($SESSION->restore->importing); // there should not be a way to import old backups, but anyway ;-)
  1230. if ($importing) {
  1231. $restoreall = false;
  1232. } else {
  1233. $prev_grade_items = grade_item::fetch_all(array('courseid'=>$restore->course_id));
  1234. $prev_grade_cats = grade_category::fetch_all(array('courseid'=>$restore->course_id));
  1235. // if any categories already present, skip restore of categories from backup
  1236. if (count($prev_grade_items) > 1 or count($prev_grade_cats) > 1) {
  1237. $restoreall = false;
  1238. }
  1239. unset($prev_grade_items);
  1240. unset($prev_grade_cats);
  1241. }
  1242. // force creation of all grade_items - the course_modules already exist
  1243. grade_force_full_regrading($restore->course_id);
  1244. grade_grab_course_grades($restore->course_id);
  1245. // Start ul
  1246. if (!defined('RESTORE_SILENTLY')) {
  1247. echo '<ul>';
  1248. }
  1249. /// Process letters
  1250. $context = get_context_instance(CONTEXT_COURSE, $restore->course_id);
  1251. // respect current grade letters if defined
  1252. if ($status and $restoreall and !record_exists('grade_letters', 'contextid', $context->id)) {
  1253. if (!defined('RESTORE_SILENTLY')) {
  1254. echo '<li>'.get_string('gradeletters','grades').'</li>';
  1255. }
  1256. // Fetch recordset_size records in each iteration
  1257. $recs = get_records_select("backup_ids","table_name = 'grade_letter' AND backup_code = $restore->backup_unique_code",
  1258. "",
  1259. "old_id");
  1260. if ($recs) {
  1261. foreach ($recs as $rec) {
  1262. // Get the full record from backup_ids
  1263. $data = backup_getid($restore->backup_unique_code,'grade_letter',$rec->old_id);
  1264. if ($data) {
  1265. $info = $data->info;
  1266. $dbrec = new object();
  1267. $dbrec->contextid = $context->id;
  1268. $dbrec->lowerboundary = backup_todb($info['GRADE_LETTER']['#']['GRADE_LOW']['0']['#']);
  1269. $dbrec->letter = backup_todb($info['GRADE_LETTER']['#']['LETTER']['0']['#']);
  1270. insert_record('grade_letters', $dbrec);
  1271. }
  1272. }
  1273. }
  1274. }
  1275. if (!defined('RESTORE_SILENTLY')) {
  1276. echo '<li>'.get_string('categories','grades').'</li>';
  1277. }
  1278. //Fetch recordset_size records in each iteration
  1279. $recs = get_records_select("backup_ids","table_name = 'grade_category' AND backup_code = $restore->backup_unique_code",
  1280. "old_id",
  1281. "old_id");
  1282. $cat_count = count($recs);
  1283. if ($recs) {
  1284. foreach ($recs as $rec) {
  1285. //Get the full record from backup_ids
  1286. $data = backup_getid($restore->backup_unique_code,'grade_category',$rec->old_id);
  1287. if ($data) {
  1288. //Now get completed xmlized object
  1289. $info = $data->info;
  1290. if ($restoreall) {
  1291. if ($cat_count == 1) {
  1292. $course_category->fullname = backup_todb($info['GRADE_CATEGORY']['#']['NAME']['0']['#'], false);
  1293. $course_category->droplow = backup_todb($info['GRADE_CATEGORY']['#']['DROP_X_LOWEST']['0']['#'], false);
  1294. $course_category->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN2;
  1295. $course_category->aggregateonlygraded = 0;
  1296. $course_category->update('restore');
  1297. $grade_category = $course_category;
  1298. } else {
  1299. $grade_category = new grade_category();
  1300. $grade_category->courseid = $restore->course_id;
  1301. $grade_category->fullname = backup_todb($info['GRADE_CATEGORY']['#']['NAME']['0']['#'], false);
  1302. $grade_category->droplow = backup_todb($info['GRADE_CATEGORY']['#']['DROP_X_LOWEST']['0']['#'], false);
  1303. $grade_category->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN2;
  1304. $grade_category->aggregateonlygraded = 0;
  1305. $grade_category->insert('restore');
  1306. $grade_category->load_grade_item(); // force cretion of grade_item
  1307. }
  1308. } else {
  1309. $grade_category = null;
  1310. }
  1311. /// now, restore grade_items
  1312. $items = array();
  1313. if (!empty($info['GRADE_CATEGORY']['#']['GRADE_ITEMS']['0']['#']['GRADE_ITEM'])) {
  1314. //Iterate over items
  1315. foreach ($info['GRADE_CATEGORY']['#']['GRADE_ITEMS']['0']['#']['GRADE_ITEM'] as $ite_info) {
  1316. $modname = backup_todb($ite_info['#']['MODULE_NAME']['0']['#'], false);
  1317. $olditeminstance = backup_todb($ite_info['#']['CMINSTANCE']['0']['#'], false);
  1318. if (!$mod = backup_getid($restore->backup_unique_code,$modname, $olditeminstance)) {
  1319. continue; // not restored
  1320. }
  1321. $iteminstance = $mod->new_id;
  1322. if (!$cm = get_coursemodule_from_instance($modname, $iteminstance, $restore->course_id)) {
  1323. continue; // does not exist
  1324. }
  1325. if (!$grade_item = grade_item::fetch(array('itemtype'=>'mod', 'itemmodule'=>$cm->modname, 'iteminstance'=>$cm->instance, 'courseid'=>$cm->course, 'itemnumber'=>0))) {
  1326. continue; // no item yet??
  1327. }
  1328. if ($grade_category) {
  1329. $grade_item->sortorder = backup_todb($ite_info['#']['SORT_ORDER']['0']['#'], false);
  1330. $grade_item->set_parent($grade_category->id);
  1331. }
  1332. if ($importing
  1333. or ($grade_item->itemtype == 'mod' and !restore_userdata_selected($restore, $grade_item->itemmodule, $olditeminstance))) {
  1334. // module instance not selected when restored using granular
  1335. // skip this item
  1336. continue;
  1337. }
  1338. //Now process grade excludes
  1339. if (empty($ite_info['#']['GRADE_EXCEPTIONS'])) {
  1340. continue;
  1341. }
  1342. foreach($ite_info['#']['GRADE_EXCEPTIONS']['0']['#']['GRADE_EXCEPTION'] as $exc_info) {
  1343. if ($u = backup_getid($restore->backup_unique_code,"user",backup_todb($exc_info['#']['USERID']['0']['#']))) {
  1344. $userid = $u->new_id;
  1345. $grade_grade = new grade_grade(array('itemid'=>$grade_item->id, 'userid'=>$userid));
  1346. $grade_grade->excluded = 1;
  1347. if ($grade_grade->id) {
  1348. $grade_grade->update('restore');
  1349. } else {
  1350. $grade_grade->insert('restore');
  1351. }
  1352. }
  1353. }
  1354. }
  1355. }
  1356. }
  1357. }
  1358. }
  1359. if (!defined('RESTORE_SILENTLY')) {
  1360. //End ul
  1361. echo '</ul>';
  1362. }
  1363. return $status;
  1364. }
  1365. /**
  1366. * This function creates all the gradebook data from xml
  1367. */
  1368. function restore_create_gradebook($restore,$xml_file) {
  1369. global $CFG;
  1370. $status = true;
  1371. //Check it exists
  1372. if (!file_exists($xml_file)) {
  1373. return false;
  1374. }
  1375. // Get info from xml
  1376. // info will contain the number of record to process
  1377. $info = restore_read_xml_gradebook($restore, $xml_file);
  1378. // If we have info, then process
  1379. if (empty($info)) {
  1380. return $status;
  1381. }
  1382. if (empty($CFG->disablegradehistory) and isset($info->gradebook_histories) and $info->gradebook_histories == "true") {
  1383. $restore_histories = true;
  1384. } else {
  1385. $restore_histories = false;
  1386. }
  1387. // make sure top course category exists
  1388. $course_category = grade_category::fetch_course_category($restore->course_id);
  1389. $course_category->load_grade_item();
  1390. // we need to know if all grade items that were backed up are being restored
  1391. // if that is not the case, we do not restore grade categories nor gradeitems of category type or course type
  1392. // i.e. the aggregated grades of that category
  1393. $restoreall = true; // set to false if any grade_item is not selected/restored or already exist
  1394. $importing = !empty($SESSION->restore->importing);
  1395. if ($importing) {
  1396. $restoreall = false;
  1397. } else {
  1398. $prev_grade_items = grade_item::fetch_all(array('courseid'=>$restore->course_id));
  1399. $prev_grade_cats = grade_category::fetch_all(array('courseid'=>$restore->course_id));
  1400. // if any categories already present, skip restore of categories from backup - course item or category already exist
  1401. if (count($prev_grade_items) > 1 or count($prev_grade_cats) > 1) {
  1402. $restoreall = false;
  1403. }
  1404. unset($prev_grade_items);
  1405. unset($prev_grade_cats);
  1406. if ($restoreall) {
  1407. if ($recs = get_records_select("backup_ids","table_name = 'grade_items' AND backup_code = $restore->backup_unique_code", "", "old_id")) {
  1408. foreach ($recs as $rec) {
  1409. if ($data = backup_getid($restore->backup_unique_code,'grade_items',$rec->old_id)) {
  1410. $info = $data->info;
  1411. // do not restore if this grade_item is a mod, and
  1412. $itemtype = backup_todb($info['GRADE_ITEM']['#']['ITEMTYPE']['0']['#']);
  1413. if ($itemtype == 'mod') {
  1414. $olditeminstance = backup_todb($info['GRADE_ITEM']['#']['ITEMINSTANCE']['0']['#']);
  1415. $itemmodule = backup_todb($info['GRADE_ITEM']['#']['ITEMMODULE']['0']['#']);
  1416. if (empty($restore->mods[$itemmodule]->granular)) {
  1417. continue;
  1418. } else if (!empty($restore->mods[$itemmodule]->instances[$olditeminstance]->restore)) {
  1419. continue;
  1420. }
  1421. // at least one activity should not be restored - do not restore categories and manual items at all
  1422. $restoreall = false;
  1423. break;
  1424. }
  1425. }
  1426. }
  1427. }
  1428. }
  1429. }
  1430. // Start ul
  1431. if (!defined('RESTORE_SILENTLY')) {
  1432. echo '<ul>';
  1433. }
  1434. // array of restored categories - speedup ;-)
  1435. $cached_categories = array();
  1436. $outcomes = array();
  1437. /// Process letters
  1438. $context = get_context_instance(CONTEXT_COURSE, $restore->course_id);
  1439. // respect current grade letters if defined
  1440. if ($status and $restoreall and !record_exists('grade_letters', 'contextid', $context->id)) {
  1441. if (!defined('RESTORE_SILENTLY')) {
  1442. echo '<li>'.get_string('gradeletters','grades').'</li>';
  1443. }
  1444. // Fetch recordset_size records in each iteration
  1445. $recs = get_records_select("backup_ids","table_name = 'grade_letters' AND backup_code = $restore->backup_unique_code",
  1446. "",
  1447. "old_id");
  1448. if ($recs) {
  1449. foreach ($recs as $rec) {
  1450. // Get the full record from backup_ids
  1451. $data = backup_getid($restore->backup_unique_code,'grade_letters',$rec->old_id);
  1452. if ($data) {
  1453. $info = $data->info;
  1454. $dbrec = new object();
  1455. $dbrec->contextid = $context->id;
  1456. $dbrec->lowerboundary = backup_todb($info['GRADE_LETTER']['#']['LOWERBOUNDARY']['0']['#']);
  1457. $dbrec->letter = backup_todb($info['GRADE_LETTER']['#']['LETTER']['0']['#']);
  1458. insert_record('grade_letters', $dbrec);
  1459. }
  1460. }
  1461. }
  1462. }
  1463. /// Preprocess outcomes - do not store them yet!
  1464. if ($status and !$importing and $restoreall) {
  1465. if (!defined('RESTORE_SILENTLY')) {
  1466. echo '<li>'.get_string('gradeoutcomes','grades').'</li>';
  1467. }
  1468. $recs = get_records_select("backup_ids","table_name = 'grade_outcomes' AND backup_code = '$restore->backup_unique_code'",
  1469. "",
  1470. "old_id");
  1471. if ($recs) {
  1472. foreach ($recs as $rec) {
  1473. //Get the full record from backup_ids
  1474. $data = backup_getid($restore->backup_unique_code,'grade_outcomes',$rec->old_id);
  1475. if ($data) {
  1476. $info = $data->info;
  1477. //first find out if outcome already exists
  1478. $shortname = backup_todb($info['GRADE_OUTCOME']['#']['SHORTNAME']['0']['#']);
  1479. if ($candidates = get_records_sql("SELECT *
  1480. FROM {$CFG->prefix}grade_outcomes
  1481. WHERE (courseid IS NULL OR courseid = $restore->course_id)
  1482. AND shortname = '$shortname'
  1483. ORDER BY courseid ASC, id ASC")) {
  1484. $grade_outcome = reset($candidates);
  1485. $outcomes[$rec->old_id] = $grade_outcome;
  1486. continue;
  1487. }
  1488. $dbrec = new object();
  1489. if (has_capability('moodle/grade:manageoutcomes', get_context_instance(CONTEXT_SYSTEM))) {
  1490. $oldoutcome = backup_todb($info['GRADE_OUTCOME']['#']['COURSEID']['0']['#']);
  1491. if (empty($oldoutcome)) {
  1492. //site wide
  1493. $dbrec->courseid = null;
  1494. } else {
  1495. //course only
  1496. $dbrec->courseid = $restore->course_id;
  1497. }
  1498. } else {
  1499. // no permission to add site outcomes
  1500. $dbrec->courseid = $restore->course_id;
  1501. }
  1502. //Get the fields
  1503. $dbrec->shortname = backup_todb($info['GRADE_OUTCOME']['#']['SHORTNAME']['0']['#'], false);
  1504. $dbrec->fullname = backup_todb($info['GRADE_OUTCOME']['#']['FULLNAME']['0']['#'], false);
  1505. $dbrec->scaleid = backup_todb($info['GRADE_OUTCOME']['#']['SCALEID']['0']['#'], false);
  1506. $dbrec->description = backup_todb($info['GRADE_OUTCOME']['#']['DESCRIPTION']['0']['#'], false);
  1507. $dbrec->timecreated = backup_todb($info['GRADE_OUTCOME']['#']['TIMECREATED']['0']['#'], false);
  1508. $dbrec->timemodified = backup_todb($info['GRADE_OUTCOME']['#']['TIMEMODIFIED']['0']['#'], false);
  1509. $dbrec->usermodified = backup_todb($info['GRADE_OUTCOME']['#']['USERMODIFIED']['0']['#'], false);
  1510. //Need to recode the scaleid
  1511. if ($scale = backup_getid($restore->backup_unique_code, 'scale', $dbrec->scaleid)) {
  1512. $dbrec->scaleid = $scale->new_id;
  1513. }
  1514. //Need to recode the usermodified
  1515. if ($modifier = backup_getid($restore->backup_unique_code, 'user', $dbrec->usermodified)) {
  1516. $dbrec->usermodified = $modifier->new_id;
  1517. }
  1518. $grade_outcome = new grade_outcome($dbrec, false);
  1519. $outcomes[$rec->old_id] = $grade_outcome;
  1520. }
  1521. }
  1522. }
  1523. }
  1524. /// Process grade items and grades
  1525. if ($status) {
  1526. if (!defined('RESTORE_SILENTLY')) {
  1527. echo '<li>'.get_string('gradeitems','grades').'</li>';
  1528. }
  1529. $counter = 0;
  1530. //Fetch recordset_size records in each iteration
  1531. $recs = get_records_select("backup_ids","table_name = 'grade_items' AND backup_code = '$restore->backup_unique_code'",
  1532. "id", // restore in the backup order
  1533. "old_id");
  1534. if ($recs) {
  1535. foreach ($recs as $rec) {
  1536. //Get the full record from backup_ids
  1537. $data = backup_getid($restore->backup_unique_code,'grade_items',$rec->old_id);
  1538. if ($data) {
  1539. $info = $data->info;
  1540. // first find out if category or normal item
  1541. $itemtype = backup_todb($info['GRADE_ITEM']['#']['ITEMTYPE']['0']['#'], false);
  1542. if ($itemtype == 'course' or $itemtype == 'category') {
  1543. if (!$restoreall or $importing) {
  1544. continue;
  1545. }
  1546. $oldcat = backup_todb($info['GRADE_ITEM']['#']['ITEMINSTANCE']['0']['#'], false);
  1547. if (!$cdata = backup_getid($restore->backup_unique_code,'grade_categories',$oldcat)) {
  1548. continue;
  1549. }
  1550. $cinfo = $cdata->info;
  1551. unset($cdata);
  1552. if ($itemtype == 'course') {
  1553. $course_category->fullname = backup_todb($cinfo['GRADE_CATEGORY']['#']['FULLNAME']['0']['#'], false);
  1554. $course_category->aggregation = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATION']['0']['#'], false);
  1555. $course_category->keephigh = backup_todb($cinfo['GRADE_CATEGORY']['#']['KEEPHIGH']['0']['#'], false);
  1556. $course_category->droplow = backup_todb($cinfo['GRADE_CATEGORY']['#']['DROPLOW']['0']['#'], false);
  1557. $course_category->aggregateonlygraded = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATEONLYGRADED']['0']['#'], false);
  1558. $course_category->aggregateoutcomes = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATEOUTCOMES']['0']['#'], false);
  1559. $course_category->aggregatesubcats = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATESUBCATS']['0']['#'], false);
  1560. $course_category->timecreated = backup_todb($cinfo['GRADE_CATEGORY']['#']['TIMECREATED']['0']['#'], false);
  1561. $course_category->update('restore');
  1562. $status = backup_putid($restore->backup_unique_code,'grade_categories',$oldcat,$course_category->id) && $status;
  1563. $cached_categories[$oldcat] = $course_category;
  1564. $grade_item = $course_category->get_grade_item();
  1565. } else {
  1566. $oldparent = backup_todb($cinfo['GRADE_CATEGORY']['#']['PARENT']['0']['#'], false);
  1567. if (empty($cached_categories[$oldparent])) {
  1568. debugging('parent not found '.$oldparent);
  1569. continue; // parent not found, sorry
  1570. }
  1571. $grade_category = new grade_category();
  1572. $grade_category->courseid = $restore->course_id;
  1573. $grade_category->parent = $cached_categories[$oldparent]->id;
  1574. $grade_category->fullname = backup_todb($cinfo['GRADE_CATEGORY']['#']['FULLNAME']['0']['#'], false);
  1575. $grade_category->aggregation = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATION']['0']['#'], false);
  1576. $grade_category->keephigh = backup_todb($cinfo['GRADE_CATEGORY']['#']['KEEPHIGH']['0']['#'], false);
  1577. $grade_category->droplow = backup_todb($cinfo['GRADE_CATEGORY']['#']['DROPLOW']['0']['#'], false);
  1578. $grade_category->aggregateonlygraded = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATEONLYGRADED']['0']['#'], false);
  1579. $grade_category->aggregateoutcomes = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATEOUTCOMES']['0']['#'], false);
  1580. $grade_category->aggregatesubcats = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATESUBCATS']['0']['#'], false);
  1581. $grade_category->timecreated = backup_todb($cinfo['GRADE_CATEGORY']['#']['TIMECREATED']['0']['#'], false);
  1582. $grade_category->insert('restore');
  1583. $status = backup_putid($restore->backup_unique_code,'grade_categories',$oldcat,$grade_category->id) && $status;
  1584. $cached_categories[$oldcat] = $grade_category;
  1585. $grade_item = $grade_category->get_grade_item(); // creates grade_item too
  1586. }
  1587. unset($cinfo);
  1588. $idnumber = backup_todb($info['GRADE_ITEM']['#']['IDNUMBER']['0']['#'], false);
  1589. if (grade_verify_idnumber($idnumber, $restore->course_id)) {
  1590. $grade_item->idnumber = $idnumber;
  1591. }
  1592. $grade_item->itemname = backup_todb($info['GRADE_ITEM']['#']['ITEMNAME']['0']['#'], false);
  1593. $grade_item->iteminfo = backup_todb($info['GRADE_ITEM']['#']['ITEMINFO']['0']['#'], false);
  1594. $grade_item->gradetype = backup_todb($info['GRADE_ITEM']['#']['GRADETYPE']['0']['#'], false);
  1595. $grade_item->calculation = backup_todb($info['GRADE_ITEM']['#']['CALCULATION']['0']['#'], false);
  1596. $grade_item->grademax = backup_todb($info['GRADE_ITEM']['#']['GRADEMAX']['0']['#'], false);
  1597. $grade_item->grademin = backup_todb($info['GRADE_ITEM']['#']['GRADEMIN']['0']['#'], false);
  1598. $grade_item->gradepass = backup_todb($info['GRADE_ITEM']['#']['GRADEPASS']['0']['#'], false);
  1599. $grade_item->multfactor = backup_todb($info['GRADE_ITEM']['#']['MULTFACTOR']['0']['#'], false);
  1600. $grade_item->plusfactor = backup_todb($info['GRADE_ITEM']['#']['PLUSFACTOR']['0']['#'], false);
  1601. $grade_item->aggregationcoef = backup_todb($info['GRADE_ITEM']['#']['AGGREGATIONCOEF']['0']['#'], false);
  1602. $grade_item->display = backup_todb($info['GRADE_ITEM']['#']['DISPLAY']['0']['#'], false);
  1603. $grade_item->decimals = backup_todb($info['GRADE_ITEM']['#']['DECIMALS']['0']['#'], false);
  1604. $grade_item->hidden = backup_todb($info['GRADE_ITEM']['#']['HIDDEN']['0']['#'], false);
  1605. $grade_item->locked = backup_todb($info['GRADE_ITEM']['#']['LOCKED']['0']['#'], false);
  1606. $grade_item->locktime = backup_todb($info['GRADE_ITEM']['#']['LOCKTIME']['0']['#'], false);
  1607. $grade_item->timecreated = backup_todb($info['GRADE_ITEM']['#']['TIMECREATED']['0']['#'], false);
  1608. if (backup_todb($info['GRADE_ITEM']['#']['SCALEID']['0']['#'], false)) {
  1609. $scale = backup_getid($restore->backup_unique_code,"scale",backup_todb($info['GRADE_ITEM']['#']['SCALEID']['0']['#'], false));
  1610. $grade_item->scaleid = $scale->new_id;
  1611. }
  1612. if (backup_todb($info['GRADE_ITEM']['#']['OUTCOMEID']['0']['#'], false)) {
  1613. $outcome = backup_getid($restore->backup_unique_code,"grade_outcomes",backup_todb($info['GRADE_ITEM']['#']['OUTCOMEID']['0']['#'], false));
  1614. $grade_item->outcomeid = $outcome->new_id;
  1615. }
  1616. $grade_item->update('restore');
  1617. $status = backup_putid($restore->backup_unique_code,"grade_items", $rec->old_id, $grade_item->id) && $status;
  1618. } else {
  1619. if ($itemtype != 'mod' and (!$restoreall or $importing)) {
  1620. // not extra gradebook stuff if restoring individual activities or something already there
  1621. continue;
  1622. }
  1623. $dbrec = new object();
  1624. $dbrec->courseid = $restore->course_id;
  1625. $dbrec->itemtype = backup_todb($info['GRADE_ITEM']['#']['ITEMTYPE']['0']['#'], false);
  1626. $dbrec->itemmodule = backup_todb($info['GRADE_ITEM']['#']['ITEMMODULE']['0']['#'], false);
  1627. if ($itemtype == 'mod') {
  1628. // iteminstance should point to new mod
  1629. $olditeminstance = backup_todb($info['GRADE_ITEM']['#']['ITEMINSTANCE']['0']['#'], false);
  1630. $mod = backup_getid($restore->backup_unique_code,$dbrec->itemmodule, $olditeminstance);
  1631. $dbrec->iteminstance = $mod->new_id;
  1632. if (!$cm = get_coursemodule_from_instance($dbrec->itemmodule, $mod->new_id)) {
  1633. // item not restored - no item
  1634. continue;
  1635. }
  1636. // keep in sync with activity idnumber
  1637. $dbrec->idnumber = $cm->idnumber;
  1638. } else {
  1639. $idnumber = backup_todb($info['GRADE_ITEM']['#']['IDNUMBER']['0']['#'], false);
  1640. if (grade_verify_idnumber($idnumber, $restore->course_id)) {
  1641. //make sure the new idnumber is unique
  1642. $dbrec->idnumber = $idnumber;
  1643. }
  1644. }
  1645. $dbrec->itemname = backup_todb($info['GRADE_ITEM']['#']['ITEMNAME']['0']['#'], false);
  1646. $dbrec->itemtype = backup_todb($info['GRADE_ITEM']['#']['ITEMTYPE']['0']['#'], false);
  1647. $dbrec->itemmodule = backup_todb($info['GRADE_ITEM']['#']['ITEMMODULE']['0']['#'], false);
  1648. $dbrec->itemnumber = backup_todb($info['GRADE_ITEM']['#']['ITEMNUMBER']['0']['#'], false);
  1649. $dbrec->iteminfo = backup_todb($info['GRADE_ITEM']['#']['ITEMINFO']['0']['#'], false);
  1650. $dbrec->gradetype = backup_todb($info['GRADE_ITEM']['#']['GRADETYPE']['0']['#'], false);
  1651. $dbrec->calculation = backup_todb($info['GRADE_ITEM']['#']['CALCULATION']['0']['#'], false);
  1652. $dbrec->grademax = backup_todb($info['GRADE_ITEM']['#']['GRADEMAX']['0']['#'], false);
  1653. $dbrec->grademin = backup_todb($info['GRADE_ITEM']['#']['GRADEMIN']['0']['#'], false);
  1654. $dbrec->gradepass = backup_todb($info['GRADE_ITEM']['#']['GRADEPASS']['0']['#'], false);
  1655. $dbrec->multfactor = backup_todb($info['GRADE_ITEM']['#']['MULTFACTOR']['0']['#'], false);
  1656. $dbrec->plusfactor = backup_todb($info['GRADE_ITEM']['#']['PLUSFACTOR']['0']['#'], false);
  1657. $dbrec->aggregationcoef = backup_todb($info['GRADE_ITEM']['#']['AGGREGATIONCOEF']['0']['#'], false);
  1658. $dbrec->display = backup_todb($info['GRADE_ITEM']['#']['DISPLAY']['0']['#'], false);
  1659. $dbrec->decimals = backup_todb($info['GRADE_ITEM']['#']['DECIMALS']['0']['#'], false);
  1660. $dbrec->hidden = backup_todb($info['GRADE_ITEM']['#']['HIDDEN']['0']['#'], false);
  1661. $dbrec->locked = backup_todb($info['GRADE_ITEM']['#']['LOCKED']['0']['#'], false);
  1662. $dbrec->locktime = backup_todb($info['GRADE_ITEM']['#']['LOCKTIME']['0']['#'], false);
  1663. $dbrec->timecreated = backup_todb($info['GRADE_ITEM']['#']['TIMECREATED']['0']['#'], false);
  1664. if (backup_todb($info['GRADE_ITEM']['#']['SCALEID']['0']['#'], false)) {
  1665. $scale = backup_getid($restore->backup_unique_code,"scale",backup_todb($info['GRADE_ITEM']['#']['SCALEID']['0']['#'], false));
  1666. $dbrec->scaleid = $scale->new_id;
  1667. }
  1668. if (backup_todb($info['GRADE_ITEM']['#']['OUTCOMEID']['0']['#'])) {
  1669. $oldoutcome = backup_todb($info['GRADE_ITEM']['#']['OUTCOMEID']['0']['#']);
  1670. if (empty($outcomes[$oldoutcome])) {
  1671. continue; // error!
  1672. }
  1673. if (empty($outcomes[$oldoutcome]->id)) {
  1674. $outcomes[$oldoutcome]->insert('restore');
  1675. $outcomes[$oldoutcome]->use_in($restore->course_id);
  1676. backup_putid($restore->backup_unique_code, "grade_outcomes", $oldoutcome, $outcomes[$oldoutcome]->id);
  1677. }
  1678. $dbrec->outcomeid = $outcomes[$oldoutcome]->id;
  1679. }
  1680. $grade_item = new grade_item($dbrec, false);
  1681. $grade_item->insert('restore');
  1682. if ($restoreall) {
  1683. // set original parent if restored
  1684. $oldcat = $info['GRADE_ITEM']['#']['CATEGORYID']['0']['#'];
  1685. if (!empty($cached_categories[$oldcat])) {
  1686. $grade_item->set_parent($cached_categories[$oldcat]->id);
  1687. }
  1688. }
  1689. $status = backup_putid($restore->backup_unique_code,"grade_items", $rec->old_id, $grade_item->id) && $status;
  1690. }
  1691. // no need to restore grades if user data is not selected or importing activities
  1692. if ($importing
  1693. or ($grade_item->itemtype == 'mod' and !restore_userdata_selected($restore, $grade_item->itemmodule, $olditeminstance))) {
  1694. // module instance not selected when restored using granular
  1695. // skip this item
  1696. continue;
  1697. }
  1698. /// now, restore grade_grades
  1699. if (!empty($info['GRADE_ITEM']['#']['GRADE_GRADES']['0']['#']['GRADE'])) {
  1700. //Iterate over items
  1701. foreach ($info['GRADE_ITEM']['#']['GRADE_GRADES']['0']['#']['GRADE'] as $g_info) {
  1702. $grade = new grade_grade();
  1703. $grade->itemid = $grade_item->id;
  1704. $olduser = backup_todb($g_info['#']['USERID']['0']['#'], false);
  1705. $user = backup_getid($restore->backup_unique_code,"user",$olduser);
  1706. $grade->userid = $user->new_id;
  1707. $grade->rawgrade = backup_todb($g_info['#']['RAWGRADE']['0']['#'], false);
  1708. $grade->rawgrademax = backup_todb($g_info['#']['RAWGRADEMAX']['0']['#'], false);
  1709. $grade->rawgrademin = backup_todb($g_info['#']['RAWGRADEMIN']['0']['#'], false);
  1710. // need to find scaleid
  1711. if (backup_todb($g_info['#']['RAWSCALEID']['0']['#'])) {
  1712. $scale = backup_getid($restore->backup_unique_code,"scale",backup_todb($g_info['#']['RAWSCALEID']['0']['#'], false));
  1713. $grade->rawscaleid = $scale->new_id;
  1714. }
  1715. if (backup_todb($g_info['#']['USERMODIFIED']['0']['#'])) {
  1716. if ($modifier = backup_getid($restore->backup_unique_code,"user", backup_todb($g_info['#']['USERMODIFIED']['0']['#'], false))) {
  1717. $grade->usermodified = $modifier->new_id;
  1718. }
  1719. }
  1720. $grade->finalgrade = backup_todb($g_info['#']['FINALGRADE']['0']['#'], false);
  1721. $grade->hidden = backup_todb($g_info['#']['HIDDEN']['0']['#'], false);
  1722. $grade->locked = backup_todb($g_info['#']['LOCKED']['0']['#'], false);
  1723. $grade->locktime = backup_todb($g_info['#']['LOCKTIME']['0']['#'], false);
  1724. $grade->exported = backup_todb($g_info['#']['EXPORTED']['0']['#'], false);
  1725. $grade->overridden = backup_todb($g_info['#']['OVERRIDDEN']['0']['#'], false);
  1726. $grade->excluded = backup_todb($g_info['#']['EXCLUDED']['0']['#'], false);
  1727. $grade->feedback = backup_todb($g_info['#']['FEEDBACK']['0']['#'], false);
  1728. $grade->feedbackformat = backup_todb($g_info['#']['FEEDBACKFORMAT']['0']['#'], false);
  1729. $grade->information = backup_todb($g_info['#']['INFORMATION']['0']['#'], false);
  1730. $grade->informationformat = backup_todb($g_info['#']['INFORMATIONFORMAT']['0']['#'], false);
  1731. $grade->timecreated = backup_todb($g_info['#']['TIMECREATED']['0']['#'], false);
  1732. $grade->timemodified = backup_todb($g_info['#']['TIMEMODIFIED']['0']['#'], false);
  1733. $grade->insert('restore');
  1734. backup_putid($restore->backup_unique_code,"grade_grades", backup_todb($g_info['#']['ID']['0']['#']), $grade->id);
  1735. $counter++;
  1736. if ($counter % 20 == 0) {
  1737. if (!defined('RESTORE_SILENTLY')) {
  1738. echo ".";
  1739. if ($counter % 400 == 0) {
  1740. echo "<br />";
  1741. }
  1742. }
  1743. backup_flush(300);
  1744. }
  1745. }
  1746. }
  1747. }
  1748. }
  1749. }
  1750. }
  1751. /// add outcomes that are not used when doing full restore
  1752. if ($status and $restoreall) {
  1753. foreach ($outcomes as $oldoutcome=>$grade_outcome) {
  1754. if (empty($grade_outcome->id)) {
  1755. $grade_outcome->insert('restore');
  1756. $grade_outcome->use_in($restore->course_id);
  1757. backup_putid($restore->backup_unique_code, "grade_outcomes", $oldoutcome, $grade_outcome->id);
  1758. }
  1759. }
  1760. }
  1761. if ($status and !$importing and $restore_histories) {
  1762. /// following code is very inefficient
  1763. $gchcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'grade_categories_history');
  1764. $gghcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'grade_grades_history');
  1765. $gihcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'grade_items_history');
  1766. $gohcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'grade_outcomes_history');
  1767. // Number of records to get in every chunk
  1768. $recordset_size = 2;
  1769. // process histories
  1770. if ($gchcount && $status) {
  1771. if (!defined('RESTORE_SILENTLY')) {
  1772. echo '<li>'.get_string('gradecategoryhistory','grades').'</li>';
  1773. }
  1774. $counter = 0;
  1775. while ($counter < $gchcount) {
  1776. //Fetch recordset_size records in each iteration
  1777. $recs = get_records_select("backup_ids","table_name = 'grade_categories_history' AND backup_code = '$restore->backup_unique_code'",
  1778. "old_id",
  1779. "old_id",
  1780. $counter,
  1781. $recordset_size);
  1782. if ($recs) {
  1783. foreach ($recs as $rec) {
  1784. //Get the full record from backup_ids
  1785. $data = backup_getid($restore->backup_unique_code,'grade_categories_history',$rec->old_id);
  1786. if ($data) {
  1787. //Now get completed xmlized object
  1788. $info = $data->info;
  1789. //traverse_xmlize($info); //Debug
  1790. //print_object ($GLOBALS['traverse_array']); //Debug
  1791. //$GLOBALS['traverse_array']=""; //Debug
  1792. $oldobj = backup_getid($restore->backup_unique_code,"grade_categories", backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['OLDID']['0']['#']));
  1793. if (empty($oldobj->new_id)) {
  1794. // if the old object is not being restored, can't restoring its history
  1795. $counter++;
  1796. continue;
  1797. }
  1798. $dbrec->oldid = $oldobj->new_id;
  1799. $dbrec->action = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['ACTION']['0']['#']);
  1800. $dbrec->source = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['SOURCE']['0']['#']);
  1801. $dbrec->timemodified = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['TIMEMODIFIED']['0']['#']);
  1802. // loggeduser might not be restored, e.g. admin
  1803. if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['LOGGEDUSER']['0']['#']))) {
  1804. $dbrec->loggeduser = $oldobj->new_id;
  1805. }
  1806. // this item might not have a parent at all, do not skip it if no parent is specified
  1807. if (backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['PARENT']['0']['#'])) {
  1808. $oldobj = backup_getid($restore->backup_unique_code,"grade_categories", backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['PARENT']['0']['#']));
  1809. if (empty($oldobj->new_id)) {
  1810. // if the parent category not restored
  1811. $counter++;
  1812. continue;
  1813. }
  1814. }
  1815. $dbrec->parent = $oldobj->new_id;
  1816. $dbrec->depth = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['DEPTH']['0']['#']);
  1817. // path needs to be rebuilt
  1818. if ($path = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['PATH']['0']['#'])) {
  1819. // to preserve the path and make it work, we need to replace the categories one by one
  1820. // we first get the list of categories in current path
  1821. if ($paths = explode("/", $path)) {
  1822. $newpath = '';
  1823. foreach ($paths as $catid) {
  1824. if ($catid) {
  1825. // find the new corresponding path
  1826. $oldpath = backup_getid($restore->backup_unique_code,"grade_categories", $catid);
  1827. $newpath .= "/$oldpath->new_id";
  1828. }
  1829. }
  1830. $dbrec->path = $newpath;
  1831. }
  1832. }
  1833. $dbrec->fullname = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['FULLNAME']['0']['#']);
  1834. $dbrec->aggregation = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['AGGRETGATION']['0']['#']);
  1835. $dbrec->keephigh = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['KEEPHIGH']['0']['#']);
  1836. $dbrec->droplow = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['DROPLOW']['0']['#']);
  1837. $dbrec->aggregateonlygraded = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['AGGREGATEONLYGRADED']['0']['#']);
  1838. $dbrec->aggregateoutcomes = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['AGGREGATEOUTCOMES']['0']['#']);
  1839. $dbrec->aggregatesubcats = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['AGGREGATESUBCATS']['0']['#']);
  1840. $dbrec->courseid = $restore->course_id;
  1841. insert_record('grade_categories_history', $dbrec);
  1842. unset($dbrec);
  1843. }
  1844. //Increment counters
  1845. $counter++;
  1846. //Do some output
  1847. if ($counter % 1 == 0) {
  1848. if (!defined('RESTORE_SILENTLY')) {
  1849. echo ".";
  1850. if ($counter % 20 == 0) {
  1851. echo "<br />";
  1852. }
  1853. }
  1854. backup_flush(300);
  1855. }
  1856. }
  1857. }
  1858. }
  1859. }
  1860. // process histories
  1861. if ($gghcount && $status) {
  1862. if (!defined('RESTORE_SILENTLY')) {
  1863. echo '<li>'.get_string('gradegradeshistory','grades').'</li>';
  1864. }
  1865. $counter = 0;
  1866. while ($counter < $gghcount) {
  1867. //Fetch recordset_size records in each iteration
  1868. $recs = get_records_select("backup_ids","table_name = 'grade_grades_history' AND backup_code = '$restore->backup_unique_code'",
  1869. "old_id",
  1870. "old_id",
  1871. $counter,
  1872. $recordset_size);
  1873. if ($recs) {
  1874. foreach ($recs as $rec) {
  1875. //Get the full record from backup_ids
  1876. $data = backup_getid($restore->backup_unique_code,'grade_grades_history',$rec->old_id);
  1877. if ($data) {
  1878. //Now get completed xmlized object
  1879. $info = $data->info;
  1880. //traverse_xmlize($info); //Debug
  1881. //print_object ($GLOBALS['traverse_array']); //Debug
  1882. //$GLOBALS['traverse_array']=""; //Debug
  1883. $oldobj = backup_getid($restore->backup_unique_code,"grade_grades", backup_todb($info['GRADE_GRADES_HISTORY']['#']['OLDID']['0']['#']));
  1884. if (empty($oldobj->new_id)) {
  1885. // if the old object is not being restored, can't restoring its history
  1886. $counter++;
  1887. continue;
  1888. }
  1889. $dbrec->oldid = $oldobj->new_id;
  1890. $dbrec->action = backup_todb($info['GRADE_GRADES_HISTORY']['#']['ACTION']['0']['#']);
  1891. $dbrec->source = backup_todb($info['GRADE_GRADES_HISTORY']['#']['SOURCE']['0']['#']);
  1892. $dbrec->timemodified = backup_todb($info['GRADE_GRADES_HISTORY']['#']['TIMEMODIFIED']['0']['#']);
  1893. if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_GRADES_HISTORY']['#']['LOGGEDUSER']['0']['#']))) {
  1894. $dbrec->loggeduser = $oldobj->new_id;
  1895. }
  1896. $oldobj = backup_getid($restore->backup_unique_code,"grade_items", backup_todb($info['GRADE_GRADES_HISTORY']['#']['ITEMID']['0']['#']));
  1897. $dbrec->itemid = $oldobj->new_id;
  1898. if (empty($dbrec->itemid)) {
  1899. $counter++;
  1900. continue; // grade item not being restored
  1901. }
  1902. $oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_GRADES_HISTORY']['#']['USERID']['0']['#']));
  1903. $dbrec->userid = $oldobj->new_id;
  1904. $dbrec->rawgrade = backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWGRADE']['0']['#']);
  1905. $dbrec->rawgrademax = backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWGRADEMAX']['0']['#']);
  1906. $dbrec->rawgrademin = backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWGRADEMIN']['0']['#']);
  1907. if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_GRADES_HISTORY']['#']['USERMODIFIED']['0']['#']))) {
  1908. $dbrec->usermodified = $oldobj->new_id;
  1909. }
  1910. if (backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWSCALEID']['0']['#'])) {
  1911. $scale = backup_getid($restore->backup_unique_code,"scale",backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWSCALEID']['0']['#']));
  1912. $dbrec->rawscaleid = $scale->new_id;
  1913. }
  1914. $dbrec->finalgrade = backup_todb($info['GRADE_GRADES_HISTORY']['#']['FINALGRADE']['0']['#']);
  1915. $dbrec->hidden = backup_todb($info['GRADE_GRADES_HISTORY']['#']['HIDDEN']['0']['#']);
  1916. $dbrec->locked = backup_todb($info['GRADE_GRADES_HISTORY']['#']['LOCKED']['0']['#']);
  1917. $dbrec->locktime = backup_todb($info['GRADE_GRADES_HISTORY']['#']['LOCKTIME']['0']['#']);
  1918. $dbrec->exported = backup_todb($info['GRADE_GRADES_HISTORY']['#']['EXPORTED']['0']['#']);
  1919. $dbrec->overridden = backup_todb($info['GRADE_GRADES_HISTORY']['#']['OVERRIDDEN']['0']['#']);
  1920. $dbrec->excluded = backup_todb($info['GRADE_GRADES_HISTORY']['#']['EXCLUDED']['0']['#']);
  1921. $dbrec->feedback = backup_todb($info['GRADE_TEXT_HISTORY']['#']['FEEDBACK']['0']['#']);
  1922. $dbrec->feedbackformat = backup_todb($info['GRADE_TEXT_HISTORY']['#']['FEEDBACKFORMAT']['0']['#']);
  1923. $dbrec->information = backup_todb($info['GRADE_TEXT_HISTORY']['#']['INFORMATION']['0']['#']);
  1924. $dbrec->informationformat = backup_todb($info['GRADE_TEXT_HISTORY']['#']['INFORMATIONFORMAT']['0']['#']);
  1925. insert_record('grade_grades_history', $dbrec);
  1926. unset($dbrec);
  1927. }
  1928. //Increment counters
  1929. $counter++;
  1930. //Do some output
  1931. if ($counter % 1 == 0) {
  1932. if (!defined('RESTORE_SILENTLY')) {
  1933. echo ".";
  1934. if ($counter % 20 == 0) {
  1935. echo "<br />";
  1936. }
  1937. }
  1938. backup_flush(300);
  1939. }
  1940. }
  1941. }
  1942. }
  1943. }
  1944. // process histories
  1945. if ($gihcount && $status) {
  1946. if (!defined('RESTORE_SILENTLY')) {
  1947. echo '<li>'.get_string('gradeitemshistory','grades').'</li>';
  1948. }
  1949. $counter = 0;
  1950. while ($counter < $gihcount) {
  1951. //Fetch recordset_size records in each iteration
  1952. $recs = get_records_select("backup_ids","table_name = 'grade_items_history' AND backup_code = '$restore->backup_unique_code'",
  1953. "old_id",
  1954. "old_id",
  1955. $counter,
  1956. $recordset_size);
  1957. if ($recs) {
  1958. foreach ($recs as $rec) {
  1959. //Get the full record from backup_ids
  1960. $data = backup_getid($restore->backup_unique_code,'grade_items_history',$rec->old_id);
  1961. if ($data) {
  1962. //Now get completed xmlized object
  1963. $info = $data->info;
  1964. //traverse_xmlize($info); //Debug
  1965. //print_object ($GLOBALS['traverse_array']); //Debug
  1966. //$GLOBALS['traverse_array']=""; //Debug
  1967. $oldobj = backup_getid($restore->backup_unique_code,"grade_items", backup_todb($info['GRADE_ITEM_HISTORY']['#']['OLDID']['0']['#']));
  1968. if (empty($oldobj->new_id)) {
  1969. // if the old object is not being restored, can't restoring its history
  1970. $counter++;
  1971. continue;
  1972. }
  1973. $dbrec->oldid = $oldobj->new_id;
  1974. $dbrec->action = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ACTION']['0']['#']);
  1975. $dbrec->source = backup_todb($info['GRADE_ITEM_HISTORY']['#']['SOURCE']['0']['#']);
  1976. $dbrec->timemodified = backup_todb($info['GRADE_ITEM_HISTORY']['#']['TIMEMODIFIED']['0']['#']);
  1977. if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_ITEM_HISTORY']['#']['LOGGEDUSER']['0']['#']))) {
  1978. $dbrec->loggeduser = $oldobj->new_id;
  1979. }
  1980. $dbrec->courseid = $restore->course_id;
  1981. $oldobj = backup_getid($restore->backup_unique_code,'grade_categories',backup_todb($info['GRADE_ITEM_HISTORY']['#']['CATEGORYID']['0']['#']));
  1982. $oldobj->categoryid = $category->new_id;
  1983. if (empty($oldobj->categoryid)) {
  1984. $counter++;
  1985. continue; // category not restored
  1986. }
  1987. $dbrec->itemname= backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMNAME']['0']['#']);
  1988. $dbrec->itemtype = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMTYPE']['0']['#']);
  1989. $dbrec->itemmodule = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMMODULE']['0']['#']);
  1990. // code from grade_items restore
  1991. $iteminstance = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMINSTANCE']['0']['#']);
  1992. // do not restore if this grade_item is a mod, and
  1993. if ($dbrec->itemtype == 'mod') {
  1994. if (!restore_userdata_selected($restore, $dbrec->itemmodule, $iteminstance)) {
  1995. // module instance not selected when restored using granular
  1996. // skip this item
  1997. $counter++;
  1998. continue;
  1999. }
  2000. // iteminstance should point to new mod
  2001. $mod = backup_getid($restore->backup_unique_code,$dbrec->itemmodule, $iteminstance);
  2002. $dbrec->iteminstance = $mod->new_id;
  2003. } else if ($dbrec->itemtype == 'category') {
  2004. // the item instance should point to the new grade category
  2005. // only proceed if we are restoring all grade items
  2006. if ($restoreall) {
  2007. $category = backup_getid($restore->backup_unique_code,'grade_categories', $iteminstance);
  2008. $dbrec->iteminstance = $category->new_id;
  2009. } else {
  2010. // otherwise we can safely ignore this grade item and subsequent
  2011. // grade_raws, grade_finals etc
  2012. continue;
  2013. }
  2014. } elseif ($dbrec->itemtype == 'course') { // We don't restore course type to avoid duplicate course items
  2015. if ($restoreall) {
  2016. // TODO any special code needed here to restore course item without duplicating it?
  2017. // find the course category with depth 1, and course id = current course id
  2018. // this would have been already restored
  2019. $cat = get_record('grade_categories', 'depth', 1, 'courseid', $restore->course_id);
  2020. $dbrec->iteminstance = $cat->id;
  2021. } else {
  2022. $counter++;
  2023. continue;
  2024. }
  2025. }
  2026. $dbrec->itemnumber = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMNUMBER']['0']['#']);
  2027. $dbrec->iteminfo = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMINFO']['0']['#']);
  2028. $dbrec->idnumber = backup_todb($info['GRADE_ITEM_HISTORY']['#']['IDNUMBER']['0']['#']);
  2029. $dbrec->calculation = backup_todb($info['GRADE_ITEM_HISTORY']['#']['CALCULATION']['0']['#']);
  2030. $dbrec->gradetype = backup_todb($info['GRADE_ITEM_HISTORY']['#']['GRADETYPE']['0']['#']);
  2031. $dbrec->grademax = backup_todb($info['GRADE_ITEM_HISTORY']['#']['GRADEMAX']['0']['#']);
  2032. $dbrec->grademin = backup_todb($info['GRADE_ITEM_HISTORY']['#']['GRADEMIN']['0']['#']);
  2033. if ($oldobj = backup_getid($restore->backup_unique_code,"scale", backup_todb($info['GRADE_ITEM_HISTORY']['#']['SCALEID']['0']['#']))) {
  2034. // scaleid is optional
  2035. $dbrec->scaleid = $oldobj->new_id;
  2036. }
  2037. if ($oldobj = backup_getid($restore->backup_unique_code,"grade_outcomes", backup_todb($info['GRADE_ITEM_HISTORY']['#']['OUTCOMEID']['0']['#']))) {
  2038. // outcome is optional
  2039. $dbrec->outcomeid = $oldobj->new_id;
  2040. }
  2041. $dbrec->gradepass = backup_todb($info['GRADE_ITEM_HISTORY']['#']['GRADEPASS']['0']['#']);
  2042. $dbrec->multfactor = backup_todb($info['GRADE_ITEM_HISTORY']['#']['MULTFACTOR']['0']['#']);
  2043. $dbrec->plusfactor = backup_todb($info['GRADE_ITEM_HISTORY']['#']['PLUSFACTOR']['0']['#']);
  2044. $dbrec->aggregationcoef = backup_todb($info['GRADE_ITEM_HISTORY']['#']['AGGREGATIONCOEF']['0']['#']);
  2045. $dbrec->sortorder = backup_todb($info['GRADE_ITEM_HISTORY']['#']['SORTORDER']['0']['#']);
  2046. $dbrec->display = backup_todb($info['GRADE_ITEM_HISTORY']['#']['DISPLAY']['0']['#']);
  2047. $dbrec->decimals = backup_todb($info['GRADE_ITEM_HISTORY']['#']['DECIMALS']['0']['#']);
  2048. $dbrec->hidden = backup_todb($info['GRADE_ITEM_HISTORY']['#']['HIDDEN']['0']['#']);
  2049. $dbrec->locked = backup_todb($info['GRADE_ITEM_HISTORY']['#']['LOCKED']['0']['#']);
  2050. $dbrec->locktime = backup_todb($info['GRADE_ITEM_HISTORY']['#']['LOCKTIME']['0']['#']);
  2051. $dbrec->needsupdate = backup_todb($info['GRADE_ITEM_HISTORY']['#']['NEEDSUPDATE']['0']['#']);
  2052. insert_record('grade_items_history', $dbrec);
  2053. unset($dbrec);
  2054. }
  2055. //Increment counters
  2056. $counter++;
  2057. //Do some output
  2058. if ($counter % 1 == 0) {
  2059. if (!defined('RESTORE_SILENTLY')) {
  2060. echo ".";
  2061. if ($counter % 20 == 0) {
  2062. echo "<br />";
  2063. }
  2064. }
  2065. backup_flush(300);
  2066. }
  2067. }
  2068. }
  2069. }
  2070. }
  2071. // process histories
  2072. if ($gohcount && $status) {
  2073. if (!defined('RESTORE_SILENTLY')) {
  2074. echo '<li>'.get_string('gradeoutcomeshistory','grades').'</li>';
  2075. }
  2076. $counter = 0;
  2077. while ($counter < $gohcount) {
  2078. //Fetch recordset_size records in each iteration
  2079. $recs = get_records_select("backup_ids","table_name = 'grade_outcomes_history' AND backup_code = '$restore->backup_unique_code'",
  2080. "old_id",
  2081. "old_id",
  2082. $counter,
  2083. $recordset_size);
  2084. if ($recs) {
  2085. foreach ($recs as $rec) {
  2086. //Get the full record from backup_ids
  2087. $data = backup_getid($restore->backup_unique_code,'grade_outcomes_history',$rec->old_id);
  2088. if ($data) {
  2089. //Now get completed xmlized object
  2090. $info = $data->info;
  2091. //traverse_xmlize($info); //Debug
  2092. //print_object ($GLOBALS['traverse_array']); //Debug
  2093. //$GLOBALS['traverse_array']=""; //Debug
  2094. $oldobj = backup_getid($restore->backup_unique_code,"grade_outcomes", backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['OLDID']['0']['#']));
  2095. if (empty($oldobj->new_id)) {
  2096. // if the old object is not being restored, can't restoring its history
  2097. $counter++;
  2098. continue;
  2099. }
  2100. $dbrec->oldid = $oldobj->new_id;
  2101. $dbrec->action = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['ACTION']['0']['#']);
  2102. $dbrec->source = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['SOURCE']['0']['#']);
  2103. $dbrec->timemodified = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['TIMEMODIFIED']['0']['#']);
  2104. if ($oldobj = backup_getid($restore->backup_unique_code,"user", backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['LOGGEDUSER']['0']['#']))) {
  2105. $dbrec->loggeduser = $oldobj->new_id;
  2106. }
  2107. $dbrec->courseid = $restore->course_id;
  2108. $dbrec->shortname = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['SHORTNAME']['0']['#']);
  2109. $dbrec->fullname= backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['FULLNAME']['0']['#']);
  2110. $oldobj = backup_getid($restore->backup_unique_code,"scale", backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['SCALEID']['0']['#']));
  2111. $dbrec->scaleid = $oldobj->new_id;
  2112. $dbrec->description = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['DESCRIPTION']['0']['#']);
  2113. insert_record('grade_outcomes_history', $dbrec);
  2114. unset($dbrec);
  2115. }
  2116. //Increment counters
  2117. $counter++;
  2118. //Do some output
  2119. if ($counter % 1 == 0) {
  2120. if (!defined('RESTORE_SILENTLY')) {
  2121. echo ".";
  2122. if ($counter % 20 == 0) {
  2123. echo "<br />";
  2124. }
  2125. }
  2126. backup_flush(300);
  2127. }
  2128. }
  2129. }
  2130. }
  2131. }
  2132. }
  2133. if (!defined('RESTORE_SILENTLY')) {
  2134. //End ul
  2135. echo '</ul>';
  2136. }
  2137. return $status;
  2138. }
  2139. //This function creates all the user, user_students, user_teachers
  2140. //user_course_creators and user_admins from xml
  2141. function restore_create_users($restore,$xml_file) {
  2142. global $CFG, $db;
  2143. require_once ($CFG->dirroot.'/tag/lib.php');
  2144. $status = true;
  2145. //Check it exists
  2146. if (!file_exists($xml_file)) {
  2147. $status = false;
  2148. }
  2149. //Get info from xml
  2150. if ($status) {
  2151. //info will contain the old_id of every user
  2152. //in backup_ids->info will be the real info (serialized)
  2153. $info = restore_read_xml_users($restore,$xml_file);
  2154. }
  2155. //Now, get evey user_id from $info and user data from $backup_ids
  2156. //and create the necessary db structures
  2157. if (!empty($info->users)) {
  2158. /// Grab mnethosts keyed by wwwroot, to map to id
  2159. $mnethosts = get_records('mnet_host', '', '',
  2160. 'wwwroot', 'wwwroot, id');
  2161. /// Get languages for quick search later
  2162. $languages = get_list_of_languages();
  2163. /// Iterate over all users loaded from xml
  2164. $counter = 0;
  2165. /// Init trailing messages
  2166. $messages = array();
  2167. foreach ($info->users as $userid) {
  2168. $rec = backup_getid($restore->backup_unique_code,"user",$userid);
  2169. $user = $rec->info;
  2170. foreach (array_keys(get_object_vars($user)) as $field) {
  2171. if (!is_array($user->$field)) {
  2172. $user->$field = backup_todb($user->$field);
  2173. if (is_null($user->$field)) {
  2174. $user->$field = '';
  2175. }
  2176. }
  2177. }
  2178. //Now, recode some languages (Moodle 1.5)
  2179. if ($user->lang == 'ma_nt') {
  2180. $user->lang = 'mi_nt';
  2181. }
  2182. //Country list updates - MDL-13060
  2183. //Any user whose country code has been deleted or modified needs to be assigned a valid one.
  2184. $country_update_map = array(
  2185. 'ZR' => 'CD',
  2186. 'TP' => 'TL',
  2187. 'FX' => 'FR',
  2188. 'KO' => 'RS',
  2189. 'CS' => 'RS',
  2190. 'WA' => 'GB');
  2191. if (array_key_exists($user->country, $country_update_map)) {
  2192. $user->country = $country_update_map[$user->country];
  2193. }
  2194. //If language does not exist here - use site default
  2195. if (!array_key_exists($user->lang, $languages)) {
  2196. $user->lang = $CFG->lang;
  2197. }
  2198. //Check if it's admin and coursecreator
  2199. $is_admin = !empty($user->roles['admin']);
  2200. $is_coursecreator = !empty($user->roles['coursecreator']);
  2201. //Check if it's teacher and student
  2202. $is_teacher = !empty($user->roles['teacher']);
  2203. $is_student = !empty($user->roles['student']);
  2204. //Check if it's needed
  2205. $is_needed = !empty($user->roles['needed']);
  2206. //Calculate if it is a course user
  2207. //Has role teacher or student or needed
  2208. $is_course_user = ($is_teacher or $is_student or $is_needed);
  2209. // in case we are restoring to same server, look for user by id
  2210. // it should return record always, but in sites rebuilt from scratch
  2211. // and being reconstructed using course backups
  2212. $user_data = false;
  2213. if (backup_is_same_site($restore)) {
  2214. $user_data = get_record('user', 'id', $user->id);
  2215. }
  2216. // Only try to perform mnethost/auth modifications if restoring to another server
  2217. // or if, while restoring to same server, the user doesn't exists yet (rebuilt site)
  2218. //
  2219. // So existing user data in same server *won't be modified by restore anymore*,
  2220. // under any circumpstance. If somehting is wrong with existing data, it's server fault.
  2221. if (!backup_is_same_site($restore) || (backup_is_same_site($restore) && !$user_data)) {
  2222. //Calculate mnethostid
  2223. if (empty($user->mnethosturl) || $user->mnethosturl===$CFG->wwwroot) {
  2224. $user->mnethostid = $CFG->mnet_localhost_id;
  2225. } else {
  2226. // fast url-to-id lookups
  2227. if (isset($mnethosts[$user->mnethosturl])) {
  2228. $user->mnethostid = $mnethosts[$user->mnethosturl]->id;
  2229. } else {
  2230. $user->mnethostid = $CFG->mnet_localhost_id;
  2231. }
  2232. }
  2233. //Arriving here, any user with mnet auth and using $CFG->mnet_localhost_id is wrong
  2234. //as own server cannot be accesed over mnet. Change auth to manual and inform about the switch
  2235. if ($user->auth == 'mnet' && $user->mnethostid == $CFG->mnet_localhost_id) {
  2236. // Respect registerauth
  2237. if ($CFG->registerauth == 'email') {
  2238. $user->auth = 'email';
  2239. } else {
  2240. $user->auth = 'manual';
  2241. }
  2242. // inform about the automatic switch of authentication/host
  2243. if(empty($user->mnethosturl)) {
  2244. $user->mnethosturl = '----';
  2245. }
  2246. $messages[] = get_string('mnetrestore_extusers_switchuserauth', 'admin', $user);
  2247. }
  2248. }
  2249. unset($user->mnethosturl);
  2250. //To store user->id along all the iteration
  2251. $newid=null;
  2252. //check if it exists (by username) and get its id
  2253. $user_exists = true;
  2254. if (!backup_is_same_site($restore)) { /// Restoring to another server, look for existing user based on fields
  2255. /// If restoring to same server, look has been performed some lines above (by id)
  2256. $user_data = get_record('user', 'username', addslashes($user->username), 'mnethostid', $user->mnethostid);
  2257. }
  2258. if (!$user_data) {
  2259. $user_exists = false;
  2260. } else {
  2261. $newid = $user_data->id;
  2262. }
  2263. //Flags to see what parts are we going to restore
  2264. $create_user = true;
  2265. $create_roles = true;
  2266. $create_custom_profile_fields = true;
  2267. $create_tags = true;
  2268. $create_preferences = true;
  2269. //If we are restoring course users and it isn't a course user
  2270. if ($restore->users == 1 and !$is_course_user) {
  2271. //If only restoring course_users and user isn't a course_user, inform to $backup_ids
  2272. $status = backup_putid($restore->backup_unique_code,"user",$userid,null,'notincourse');
  2273. $create_user = false;
  2274. $create_roles = false;
  2275. $create_custom_profile_fields = false;
  2276. $create_tags = false;
  2277. $create_preferences = false;
  2278. }
  2279. if ($user_exists and $create_user) {
  2280. //If user exists mark its newid in backup_ids (the same than old)
  2281. $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,'exists');
  2282. $create_user = false;
  2283. $create_custom_profile_fields = false;
  2284. $create_tags = false;
  2285. $create_preferences = false;
  2286. }
  2287. //Here, if create_user, do it
  2288. if ($create_user) {
  2289. //Unset the id because it's going to be inserted with a new one
  2290. unset ($user->id);
  2291. // relink the descriptions
  2292. $user->description = stripslashes($user->description);
  2293. /// Disable pictures based on global setting or existing empty value (old backups can contain wrong empties)
  2294. if (!empty($CFG->disableuserimages) || empty($user->picture)) {
  2295. $user->picture = 0;
  2296. }
  2297. //We need to analyse the AUTH field to recode it:
  2298. // - if the field isn't set, we are in a pre 1.4 backup and we'll
  2299. // use manual
  2300. if (empty($user->auth)) {
  2301. if ($CFG->registerauth == 'email') {
  2302. $user->auth = 'email';
  2303. } else {
  2304. $user->auth = 'manual';
  2305. }
  2306. }
  2307. //We need to process the POLICYAGREED field to recalculate it:
  2308. // - if the destination site is different (by wwwroot) reset it.
  2309. // - if the destination site is the same (by wwwroot), leave it unmodified
  2310. if (!backup_is_same_site($restore)) {
  2311. $user->policyagreed = 0;
  2312. } else {
  2313. //Nothing to do, we are in the same server
  2314. }
  2315. //Check if the theme exists in destination server
  2316. $themes = get_list_of_themes();
  2317. if (!in_array($user->theme, $themes)) {
  2318. $user->theme = '';
  2319. }
  2320. //We are going to create the user
  2321. //The structure is exactly as we need
  2322. $newid = insert_record ("user", addslashes_recursive($user));
  2323. //Put the new id
  2324. $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,"new");
  2325. }
  2326. ///TODO: This seccion is to support pre 1.7 course backups, using old roles
  2327. /// teacher, coursecreator, student.... providing a basic mapping to new ones.
  2328. /// Someday we'll drop support for them and this section will be safely deleted (2.0?)
  2329. //Here, if create_roles, do it as necessary
  2330. if ($create_roles) {
  2331. //Get the newid and current info from backup_ids
  2332. $data = backup_getid($restore->backup_unique_code,"user",$userid);
  2333. $newid = $data->new_id;
  2334. $currinfo = $data->info.",";
  2335. //Now, depending of the role, create records in user_studentes and user_teacher
  2336. //and/or mark it in backup_ids
  2337. if ($is_admin) {
  2338. //If the record (user_admins) doesn't exists
  2339. //Only put status in backup_ids
  2340. $currinfo = $currinfo."admin,";
  2341. $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
  2342. }
  2343. if ($is_coursecreator) {
  2344. //If the record (user_coursecreators) doesn't exists
  2345. //Only put status in backup_ids
  2346. $currinfo = $currinfo."coursecreator,";
  2347. $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
  2348. }
  2349. if ($is_needed) {
  2350. //Only put status in backup_ids
  2351. $currinfo = $currinfo."needed,";
  2352. $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
  2353. }
  2354. if ($is_teacher) {
  2355. //If the record (teacher) doesn't exists
  2356. //Put status in backup_ids
  2357. $currinfo = $currinfo."teacher,";
  2358. $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
  2359. //Set course and user
  2360. $user->roles['teacher']->course = $restore->course_id;
  2361. $user->roles['teacher']->userid = $newid;
  2362. //Need to analyse the enrol field
  2363. // - if it isn't set, set it to $CFG->enrol
  2364. // - if we are in a different server (by wwwroot), set it to $CFG->enrol
  2365. // - if we are in the same server (by wwwroot), maintain it unmodified.
  2366. if (empty($user->roles['teacher']->enrol)) {
  2367. $user->roles['teacher']->enrol = $CFG->enrol;
  2368. } else if (!backup_is_same_site($restore)) {
  2369. $user->roles['teacher']->enrol = $CFG->enrol;
  2370. } else {
  2371. //Nothing to do. Leave it unmodified
  2372. }
  2373. $rolesmapping = $restore->rolesmapping;
  2374. $context = get_context_instance(CONTEXT_COURSE, $restore->course_id);
  2375. if ($user->roles['teacher']->editall) {
  2376. role_assign($rolesmapping['defaultteacheredit'],
  2377. $newid,
  2378. 0,
  2379. $context->id,
  2380. $user->roles['teacher']->timestart,
  2381. $user->roles['teacher']->timeend,
  2382. 0,
  2383. $user->roles['teacher']->enrol);
  2384. // editting teacher
  2385. } else {
  2386. // non editting teacher
  2387. role_assign($rolesmapping['defaultteacher'],
  2388. $newid,
  2389. 0,
  2390. $context->id,
  2391. $user->roles['teacher']->timestart,
  2392. $user->roles['teacher']->timeend,
  2393. 0,
  2394. $user->roles['teacher']->enrol);
  2395. }
  2396. }
  2397. if ($is_student) {
  2398. //Put status in backup_ids
  2399. $currinfo = $currinfo."student,";
  2400. $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
  2401. //Set course and user
  2402. $user->roles['student']->course = $restore->course_id;
  2403. $user->roles['student']->userid = $newid;
  2404. //Need to analyse the enrol field
  2405. // - if it isn't set, set it to $CFG->enrol
  2406. // - if we are in a different server (by wwwroot), set it to $CFG->enrol
  2407. // - if we are in the same server (by wwwroot), maintain it unmodified.
  2408. if (empty($user->roles['student']->enrol)) {
  2409. $user->roles['student']->enrol = $CFG->enrol;
  2410. } else if (!backup_is_same_site($restore)) {
  2411. $user->roles['student']->enrol = $CFG->enrol;
  2412. } else {
  2413. //Nothing to do. Leave it unmodified
  2414. }
  2415. $rolesmapping = $restore->rolesmapping;
  2416. $context = get_context_instance(CONTEXT_COURSE, $restore->course_id);
  2417. role_assign($rolesmapping['defaultstudent'],
  2418. $newid,
  2419. 0,
  2420. $context->id,
  2421. $user->roles['student']->timestart,
  2422. $user->roles['student']->timeend,
  2423. 0,
  2424. $user->roles['student']->enrol);
  2425. }
  2426. if (!$is_course_user) {
  2427. //If the record (user) doesn't exists
  2428. if (!record_exists("user","id",$newid)) {
  2429. //Put status in backup_ids
  2430. $currinfo = $currinfo."user,";
  2431. $status = backup_putid($restore->backup_unique_code,"user",$userid,$newid,$currinfo);
  2432. }
  2433. }
  2434. }
  2435. /// Here, if create_custom_profile_fields, do it as necessary
  2436. if ($create_custom_profile_fields) {
  2437. if (isset($user->user_custom_profile_fields)) {
  2438. foreach($user->user_custom_profile_fields as $udata) {
  2439. /// If the profile field has data and the profile shortname-datatype is defined in server
  2440. if ($udata->field_data) {
  2441. if ($field = get_record('user_info_field', 'shortname', $udata->field_name, 'datatype', $udata->field_type)) {
  2442. /// Insert the user_custom_profile_field
  2443. $rec = new object();
  2444. $rec->userid = $newid;
  2445. $rec->fieldid = $field->id;
  2446. $rec->data = $udata->field_data;
  2447. insert_record('user_info_data', $rec);
  2448. }
  2449. }
  2450. }
  2451. }
  2452. }
  2453. /// Here, if create_tags, do it as necessary
  2454. if ($create_tags) {
  2455. /// if tags are enabled and there are user tags
  2456. if (!empty($CFG->usetags) && isset($user->user_tags)) {
  2457. $tags = array();
  2458. foreach($user->user_tags as $user_tag) {
  2459. $tags[] = $user_tag->rawname;
  2460. }
  2461. tag_set('user', $newid, $tags);
  2462. }
  2463. }
  2464. //Here, if create_preferences, do it as necessary
  2465. if ($create_preferences) {
  2466. if (isset($user->user_preferences)) {
  2467. foreach($user->user_preferences as $user_preference) {
  2468. //We check if that user_preference exists in DB
  2469. if (!record_exists("user_preferences","userid",$newid,"name",$user_preference->name)) {
  2470. //Prepare the record and insert it
  2471. $user_preference->userid = $newid;
  2472. $status = insert_record("user_preferences",$user_preference);
  2473. }
  2474. }
  2475. }
  2476. }
  2477. //Do some output
  2478. $counter++;
  2479. if ($counter % 10 == 0) {
  2480. if (!defined('RESTORE_SILENTLY')) {
  2481. echo ".";
  2482. if ($counter % 200 == 0) {
  2483. echo "<br />";
  2484. }
  2485. }
  2486. backup_flush(300);
  2487. }
  2488. } /// End of loop over all the users loaded from xml
  2489. /// Inform about all the messages geerated while restoring users
  2490. if (!defined('RESTORE_SILENTLY')) {
  2491. if ($messages) {
  2492. echo '<ul>';
  2493. foreach ($messages as $message) {
  2494. echo '<li>' . $message . '</li>';
  2495. }
  2496. echo '</ul>';
  2497. }
  2498. }
  2499. }
  2500. return $status;
  2501. }
  2502. //This function creates all the structures messages and contacts
  2503. function restore_create_messages($restore,$xml_file) {
  2504. global $CFG;
  2505. $status = true;
  2506. //Check it exists
  2507. if (!file_exists($xml_file)) {
  2508. $status = false;
  2509. }
  2510. //Get info from xml
  2511. if ($status) {
  2512. //info will contain the id and name of every table
  2513. //(message, message_read and message_contacts)
  2514. //in backup_ids->info will be the real info (serialized)
  2515. $info = restore_read_xml_messages($restore,$xml_file);
  2516. //If we have info, then process messages & contacts
  2517. if ($info > 0) {
  2518. //Count how many we have
  2519. $unreadcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'message');
  2520. $readcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'message_read');
  2521. $contactcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'message_contacts');
  2522. if ($unreadcount || $readcount || $contactcount) {
  2523. //Start ul
  2524. if (!defined('RESTORE_SILENTLY')) {
  2525. echo '<ul>';
  2526. }
  2527. //Number of records to get in every chunk
  2528. $recordset_size = 4;
  2529. //Process unread
  2530. if ($unreadcount) {
  2531. if (!defined('RESTORE_SILENTLY')) {
  2532. echo '<li>'.get_string('unreadmessages','message').'</li>';
  2533. }
  2534. $counter = 0;
  2535. while ($counter < $unreadcount) {
  2536. //Fetch recordset_size records in each iteration
  2537. $recs = get_records_select("backup_ids","table_name = 'message' AND backup_code = '$restore->backup_unique_code'","old_id","old_id",$counter,$recordset_size);
  2538. if ($recs) {
  2539. foreach ($recs as $rec) {
  2540. //Get the full record from backup_ids
  2541. $data = backup_getid($restore->backup_unique_code,"message",$rec->old_id);
  2542. if ($data) {
  2543. //Now get completed xmlized object
  2544. $info = $data->info;
  2545. //traverse_xmlize($info); //Debug
  2546. //print_object ($GLOBALS['traverse_array']); //Debug
  2547. //$GLOBALS['traverse_array']=""; //Debug
  2548. //Now build the MESSAGE record structure
  2549. $dbrec = new object();
  2550. $dbrec->useridfrom = backup_todb($info['MESSAGE']['#']['USERIDFROM']['0']['#']);
  2551. $dbrec->useridto = backup_todb($info['MESSAGE']['#']['USERIDTO']['0']['#']);
  2552. $dbrec->message = backup_todb($info['MESSAGE']['#']['MESSAGE']['0']['#']);
  2553. $dbrec->format = backup_todb($info['MESSAGE']['#']['FORMAT']['0']['#']);
  2554. $dbrec->timecreated = backup_todb($info['MESSAGE']['#']['TIMECREATED']['0']['#']);
  2555. $dbrec->messagetype = backup_todb($info['MESSAGE']['#']['MESSAGETYPE']['0']['#']);
  2556. //We have to recode the useridfrom field
  2557. $user = backup_getid($restore->backup_unique_code,"user",$dbrec->useridfrom);
  2558. if ($user) {
  2559. //echo "User ".$dbrec->useridfrom." to user ".$user->new_id."<br />"; //Debug
  2560. $dbrec->useridfrom = $user->new_id;
  2561. }
  2562. //We have to recode the useridto field
  2563. $user = backup_getid($restore->backup_unique_code,"user",$dbrec->useridto);
  2564. if ($user) {
  2565. //echo "User ".$dbrec->useridto." to user ".$user->new_id."<br />"; //Debug
  2566. $dbrec->useridto = $user->new_id;
  2567. }
  2568. //Check if the record doesn't exist in DB!
  2569. $exist = get_record('message','useridfrom',$dbrec->useridfrom,
  2570. 'useridto', $dbrec->useridto,
  2571. 'timecreated',$dbrec->timecreated);
  2572. if (!$exist) {
  2573. //Not exist. Insert
  2574. $status = insert_record('message',$dbrec);
  2575. } else {
  2576. //Duplicate. Do nothing
  2577. }
  2578. }
  2579. //Do some output
  2580. $counter++;
  2581. if ($counter % 10 == 0) {
  2582. if (!defined('RESTORE_SILENTLY')) {
  2583. echo ".";
  2584. if ($counter % 200 == 0) {
  2585. echo "<br />";
  2586. }
  2587. }
  2588. backup_flush(300);
  2589. }
  2590. }
  2591. }
  2592. }
  2593. }
  2594. //Process read
  2595. if ($readcount) {
  2596. if (!defined('RESTORE_SILENTLY')) {
  2597. echo '<li>'.get_string('readmessages','message').'</li>';
  2598. }
  2599. $counter = 0;
  2600. while ($counter < $readcount) {
  2601. //Fetch recordset_size records in each iteration
  2602. $recs = get_records_select("backup_ids","table_name = 'message_read' AND backup_code = '$restore->backup_unique_code'","old_id","old_id",$counter,$recordset_size);
  2603. if ($recs) {
  2604. foreach ($recs as $rec) {
  2605. //Get the full record from backup_ids
  2606. $data = backup_getid($restore->backup_unique_code,"message_read",$rec->old_id);
  2607. if ($data) {
  2608. //Now get completed xmlized object
  2609. $info = $data->info;
  2610. //traverse_xmlize($info); //Debug
  2611. //print_object ($GLOBALS['traverse_array']); //Debug
  2612. //$GLOBALS['traverse_array']=""; //Debug
  2613. //Now build the MESSAGE_READ record structure
  2614. $dbrec->useridfrom = backup_todb($info['MESSAGE']['#']['USERIDFROM']['0']['#']);
  2615. $dbrec->useridto = backup_todb($info['MESSAGE']['#']['USERIDTO']['0']['#']);
  2616. $dbrec->message = backup_todb($info['MESSAGE']['#']['MESSAGE']['0']['#']);
  2617. $dbrec->format = backup_todb($info['MESSAGE']['#']['FORMAT']['0']['#']);
  2618. $dbrec->timecreated = backup_todb($info['MESSAGE']['#']['TIMECREATED']['0']['#']);
  2619. $dbrec->messagetype = backup_todb($info['MESSAGE']['#']['MESSAGETYPE']['0']['#']);
  2620. $dbrec->timeread = backup_todb($info['MESSAGE']['#']['TIMEREAD']['0']['#']);
  2621. $dbrec->mailed = backup_todb($info['MESSAGE']['#']['MAILED']['0']['#']);
  2622. //We have to recode the useridfrom field
  2623. $user = backup_getid($restore->backup_unique_code,"user",$dbrec->useridfrom);
  2624. if ($user) {
  2625. //echo "User ".$dbrec->useridfrom." to user ".$user->new_id."<br />"; //Debug
  2626. $dbrec->useridfrom = $user->new_id;
  2627. }
  2628. //We have to recode the useridto field
  2629. $user = backup_getid($restore->backup_unique_code,"user",$dbrec->useridto);
  2630. if ($user) {
  2631. //echo "User ".$dbrec->useridto." to user ".$user->new_id."<br />"; //Debug
  2632. $dbrec->useridto = $user->new_id;
  2633. }
  2634. //Check if the record doesn't exist in DB!
  2635. $exist = get_record('message_read','useridfrom',$dbrec->useridfrom,
  2636. 'useridto', $dbrec->useridto,
  2637. 'timecreated',$dbrec->timecreated);
  2638. if (!$exist) {
  2639. //Not exist. Insert
  2640. $status = insert_record('message_read',$dbrec);
  2641. } else {
  2642. //Duplicate. Do nothing
  2643. }
  2644. }
  2645. //Do some output
  2646. $counter++;
  2647. if ($counter % 10 == 0) {
  2648. if (!defined('RESTORE_SILENTLY')) {
  2649. echo ".";
  2650. if ($counter % 200 == 0) {
  2651. echo "<br />";
  2652. }
  2653. }
  2654. backup_flush(300);
  2655. }
  2656. }
  2657. }
  2658. }
  2659. }
  2660. //Process contacts
  2661. if ($contactcount) {
  2662. if (!defined('RESTORE_SILENTLY')) {
  2663. echo '<li>'.moodle_strtolower(get_string('contacts','message')).'</li>';
  2664. }
  2665. $counter = 0;
  2666. while ($counter < $contactcount) {
  2667. //Fetch recordset_size records in each iteration
  2668. $recs = get_records_select("backup_ids","table_name = 'message_contacts' AND backup_code = '$restore->backup_unique_code'","old_id","old_id",$counter,$recordset_size);
  2669. if ($recs) {
  2670. foreach ($recs as $rec) {
  2671. //Get the full record from backup_ids
  2672. $data = backup_getid($restore->backup_unique_code,"message_contacts",$rec->old_id);
  2673. if ($data) {
  2674. //Now get completed xmlized object
  2675. $info = $data->info;
  2676. //traverse_xmlize($info); //Debug
  2677. //print_object ($GLOBALS['traverse_array']); //Debug
  2678. //$GLOBALS['traverse_array']=""; //Debug
  2679. //Now build the MESSAGE_CONTACTS record structure
  2680. $dbrec->userid = backup_todb($info['CONTACT']['#']['USERID']['0']['#']);
  2681. $dbrec->contactid = backup_todb($info['CONTACT']['#']['CONTACTID']['0']['#']);
  2682. $dbrec->blocked = backup_todb($info['CONTACT']['#']['BLOCKED']['0']['#']);
  2683. //We have to recode the userid field
  2684. $user = backup_getid($restore->backup_unique_code,"user",$dbrec->userid);
  2685. if ($user) {
  2686. //echo "User ".$dbrec->userid." to user ".$user->new_id."<br />"; //Debug
  2687. $dbrec->userid = $user->new_id;
  2688. }
  2689. //We have to recode the contactid field
  2690. $user = backup_getid($restore->backup_unique_code,"user",$dbrec->contactid);
  2691. if ($user) {
  2692. //echo "User ".$dbrec->contactid." to user ".$user->new_id."<br />"; //Debug
  2693. $dbrec->contactid = $user->new_id;
  2694. }
  2695. //Check if the record doesn't exist in DB!
  2696. $exist = get_record('message_contacts','userid',$dbrec->userid,
  2697. 'contactid', $dbrec->contactid);
  2698. if (!$exist) {
  2699. //Not exist. Insert
  2700. $status = insert_record('message_contacts',$dbrec);
  2701. } else {
  2702. //Duplicate. Do nothing
  2703. }
  2704. }
  2705. //Do some output
  2706. $counter++;
  2707. if ($counter % 10 == 0) {
  2708. if (!defined('RESTORE_SILENTLY')) {
  2709. echo ".";
  2710. if ($counter % 200 == 0) {
  2711. echo "<br />";
  2712. }
  2713. }
  2714. backup_flush(300);
  2715. }
  2716. }
  2717. }
  2718. }
  2719. }
  2720. if (!defined('RESTORE_SILENTLY')) {
  2721. //End ul
  2722. echo '</ul>';
  2723. }
  2724. }
  2725. }
  2726. }
  2727. return $status;
  2728. }
  2729. //This function creates all the structures for blogs and blog tags
  2730. function restore_create_blogs($restore,$xml_file) {
  2731. global $CFG;
  2732. $status = true;
  2733. //Check it exists
  2734. if (!file_exists($xml_file)) {
  2735. $status = false;
  2736. }
  2737. //Get info from xml
  2738. if ($status) {
  2739. //info will contain the number of blogs in the backup file
  2740. //in backup_ids->info will be the real info (serialized)
  2741. $info = restore_read_xml_blogs($restore,$xml_file);
  2742. //If we have info, then process blogs & blog_tags
  2743. if ($info > 0) {
  2744. //Count how many we have
  2745. $blogcount = count_records ('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'blog');
  2746. if ($blogcount) {
  2747. //Number of records to get in every chunk
  2748. $recordset_size = 4;
  2749. //Process blog
  2750. if ($blogcount) {
  2751. $counter = 0;
  2752. while ($counter < $blogcount) {
  2753. //Fetch recordset_size records in each iteration
  2754. $recs = get_records_select("backup_ids","table_name = 'blog' AND backup_code = '$restore->backup_unique_code'","old_id","old_id",$counter,$recordset_size);
  2755. if ($recs) {
  2756. foreach ($recs as $rec) {
  2757. //Get the full record from backup_ids
  2758. $data = backup_getid($restore->backup_unique_code,"blog",$rec->old_id);
  2759. if ($data) {
  2760. //Now get completed xmlized object
  2761. $info = $data->info;
  2762. //traverse_xmlize($info); //Debug
  2763. //print_object ($GLOBALS['traverse_array']); //Debug
  2764. //$GLOBALS['traverse_array']=""; //Debug
  2765. //Now build the BLOG record structure
  2766. $dbrec = new object();
  2767. $dbrec->module = backup_todb($info['BLOG']['#']['MODULE']['0']['#']);
  2768. $dbrec->userid = backup_todb($info['BLOG']['#']['USERID']['0']['#']);
  2769. $dbrec->courseid = backup_todb($info['BLOG']['#']['COURSEID']['0']['#']);
  2770. $dbrec->groupid = backup_todb($info['BLOG']['#']['GROUPID']['0']['#']);
  2771. $dbrec->moduleid = backup_todb($info['BLOG']['#']['MODULEID']['0']['#']);
  2772. $dbrec->coursemoduleid = backup_todb($info['BLOG']['#']['COURSEMODULEID']['0']['#']);
  2773. $dbrec->subject = backup_todb($info['BLOG']['#']['SUBJECT']['0']['#']);
  2774. $dbrec->summary = backup_todb($info['BLOG']['#']['SUMMARY']['0']['#']);
  2775. $dbrec->content = backup_todb($info['BLOG']['#']['CONTENT']['0']['#']);
  2776. $dbrec->uniquehash = backup_todb($info['BLOG']['#']['UNIQUEHASH']['0']['#']);
  2777. $dbrec->rating = backup_todb($info['BLOG']['#']['RATING']['0']['#']);
  2778. $dbrec->format = backup_todb($info['BLOG']['#']['FORMAT']['0']['#']);
  2779. $dbrec->attachment = backup_todb($info['BLOG']['#']['ATTACHMENT']['0']['#']);
  2780. $dbrec->publishstate = backup_todb($info['BLOG']['#']['PUBLISHSTATE']['0']['#']);
  2781. $dbrec->lastmodified = backup_todb($info['BLOG']['#']['LASTMODIFIED']['0']['#']);
  2782. $dbrec->created = backup_todb($info['BLOG']['#']['CREATED']['0']['#']);
  2783. $dbrec->usermodified = backup_todb($info['BLOG']['#']['USERMODIFIED']['0']['#']);
  2784. //We have to recode the userid field
  2785. $user = backup_getid($restore->backup_unique_code,"user",$dbrec->userid);
  2786. if ($user) {
  2787. //echo "User ".$dbrec->userid." to user ".$user->new_id."<br />"; //Debug
  2788. $dbrec->userid = $user->new_id;
  2789. }
  2790. //Check if the record doesn't exist in DB!
  2791. $exist = get_record('post','userid', $dbrec->userid,
  2792. 'subject', $dbrec->subject,
  2793. 'created', $dbrec->created);
  2794. $newblogid = 0;
  2795. if (!$exist) {
  2796. //Not exist. Insert
  2797. $newblogid = insert_record('post',$dbrec);
  2798. }
  2799. //Going to restore related tags. Check they are enabled and we have inserted a blog
  2800. if ($CFG->usetags && $newblogid) {
  2801. //Look for tags in this blog
  2802. if (isset($info['BLOG']['#']['BLOG_TAGS']['0']['#']['BLOG_TAG'])) {
  2803. $tagsarr = $info['BLOG']['#']['BLOG_TAGS']['0']['#']['BLOG_TAG'];
  2804. //Iterate over tags
  2805. $tags = array();
  2806. for($i = 0; $i < sizeof($tagsarr); $i++) {
  2807. $tag_info = $tagsarr[$i];
  2808. ///traverse_xmlize($tag_info); //Debug
  2809. ///print_object ($GLOBALS['traverse_array']); //Debug
  2810. ///$GLOBALS['traverse_array']=""; //Debug
  2811. $name = backup_todb($tag_info['#']['NAME']['0']['#']);
  2812. $rawname = backup_todb($tag_info['#']['RAWNAME']['0']['#']);
  2813. $tags[] = $rawname; //Rawname is all we need
  2814. }
  2815. tag_set('post', $newblogid, $tags); //Add all the tags in one API call
  2816. }
  2817. }
  2818. }
  2819. //Do some output
  2820. $counter++;
  2821. if ($counter % 10 == 0) {
  2822. if (!defined('RESTORE_SILENTLY')) {
  2823. echo ".";
  2824. if ($counter % 200 == 0) {
  2825. echo "<br />";
  2826. }
  2827. }
  2828. backup_flush(300);
  2829. }
  2830. }
  2831. }
  2832. }
  2833. }
  2834. }
  2835. }
  2836. }
  2837. return $status;
  2838. }
  2839. //This function creates all the categories and questions
  2840. //from xml
  2841. function restore_create_questions($restore,$xml_file) {
  2842. global $CFG, $db;
  2843. $status = true;
  2844. //Check it exists
  2845. if (!file_exists($xml_file)) {
  2846. $status = false;
  2847. }
  2848. //Get info from xml
  2849. if ($status) {
  2850. //info will contain the old_id of every category
  2851. //in backup_ids->info will be the real info (serialized)
  2852. $info = restore_read_xml_questions($restore,$xml_file);
  2853. }
  2854. //Now, if we have anything in info, we have to restore that
  2855. //categories/questions
  2856. if ($info) {
  2857. if ($info !== true) {
  2858. $status = $status && restore_question_categories($info, $restore);
  2859. }
  2860. } else {
  2861. $status = false;
  2862. }
  2863. return $status;
  2864. }
  2865. //This function creates all the scales
  2866. function restore_create_scales($restore,$xml_file) {
  2867. global $CFG, $db;
  2868. $status = true;
  2869. //Check it exists
  2870. if (!file_exists($xml_file)) {
  2871. $status = false;
  2872. }
  2873. //Get info from xml
  2874. if ($status) {
  2875. //scales will contain the old_id of every scale
  2876. //in backup_ids->info will be the real info (serialized)
  2877. $scales = restore_read_xml_scales($restore,$xml_file);
  2878. }
  2879. //Now, if we have anything in scales, we have to restore that
  2880. //scales
  2881. if ($scales) {
  2882. //Get admin->id for later use
  2883. $admin = get_admin();
  2884. $adminid = $admin->id;
  2885. if ($scales !== true) {
  2886. //Iterate over each scale
  2887. foreach ($scales as $scale) {
  2888. //Get record from backup_ids
  2889. $data = backup_getid($restore->backup_unique_code,"scale",$scale->id);
  2890. //Init variables
  2891. $create_scale = false;
  2892. if ($data) {
  2893. //Now get completed xmlized object
  2894. $info = $data->info;
  2895. //traverse_xmlize($info); //Debug
  2896. //print_object ($GLOBALS['traverse_array']); //Debug
  2897. //$GLOBALS['traverse_array']=""; //Debug
  2898. //Now build the SCALE record structure
  2899. $sca = new object();
  2900. $sca->courseid = backup_todb($info['SCALE']['#']['COURSEID']['0']['#']);
  2901. $sca->userid = backup_todb($info['SCALE']['#']['USERID']['0']['#']);
  2902. $sca->name = backup_todb($info['SCALE']['#']['NAME']['0']['#']);
  2903. $sca->scale = backup_todb($info['SCALE']['#']['SCALETEXT']['0']['#']);
  2904. $sca->description = backup_todb($info['SCALE']['#']['DESCRIPTION']['0']['#']);
  2905. $sca->timemodified = backup_todb($info['SCALE']['#']['TIMEMODIFIED']['0']['#']);
  2906. //Now search if that scale exists (by scale field) in course 0 (Standar scale)
  2907. //or in restore->course_id course (Personal scale)
  2908. if ($sca->courseid == 0) {
  2909. $course_to_search = 0;
  2910. } else {
  2911. $course_to_search = $restore->course_id;
  2912. }
  2913. // scale is not course unique, use get_record_sql to suppress warning
  2914. //Going to compare LOB columns so, use the cross-db sql_compare_text() in both sides.
  2915. $compare_scale_clause = sql_compare_text('scale') . "=" . sql_compare_text("'" . $sca->scale . "'");
  2916. $sca_db = get_record_sql("SELECT * FROM {$CFG->prefix}scale
  2917. WHERE $compare_scale_clause
  2918. AND courseid = $course_to_search", true);
  2919. //If it doesn't exist, create
  2920. if (!$sca_db) {
  2921. $create_scale = true;
  2922. }
  2923. //If we must create the scale
  2924. if ($create_scale) {
  2925. //Me must recode the courseid if it's <> 0 (common scale)
  2926. if ($sca->courseid != 0) {
  2927. $sca->courseid = $restore->course_id;
  2928. }
  2929. //We must recode the userid
  2930. $user = backup_getid($restore->backup_unique_code,"user",$sca->userid);
  2931. if ($user) {
  2932. $sca->userid = $user->new_id;
  2933. } else {
  2934. //Assign it to admin
  2935. $sca->userid = $adminid;
  2936. }
  2937. //The structure is equal to the db, so insert the scale
  2938. $newid = insert_record ("scale",$sca);
  2939. } else {
  2940. //get current scale id
  2941. $newid = $sca_db->id;
  2942. }
  2943. if ($newid) {
  2944. //We have the newid, update backup_ids
  2945. backup_putid($restore->backup_unique_code,"scale",
  2946. $scale->id, $newid);
  2947. }
  2948. }
  2949. }
  2950. }
  2951. } else {
  2952. $status = false;
  2953. }
  2954. return $status;
  2955. }
  2956. /**
  2957. * Recode group ID field, and set group ID based on restore options.
  2958. * @return object Group object with new_id field.
  2959. */
  2960. function restore_group_getid($restore, $groupid) {
  2961. //We have to recode the groupid field
  2962. $group = backup_getid($restore->backup_unique_code, 'groups', $groupid);
  2963. if ($restore->groups == RESTORE_GROUPS_NONE or $restore->groups == RESTORE_GROUPINGS_ONLY) {
  2964. $group->new_id = 0;
  2965. }
  2966. return $group;
  2967. }
  2968. /**
  2969. * Recode grouping ID field, and set grouping ID based on restore options.
  2970. * @return object Group object with new_id field.
  2971. */
  2972. function restore_grouping_getid($restore, $groupingid) {
  2973. //We have to recode the groupid field
  2974. $grouping = backup_getid($restore->backup_unique_code, 'groupings', $groupingid);
  2975. if ($restore->groups != RESTORE_GROUPS_GROUPINGS and $restore->groups != RESTORE_GROUPINGS_ONLY) {
  2976. $grouping->new_id = 0;
  2977. }
  2978. return $grouping;
  2979. }
  2980. //This function creates all the groups
  2981. function restore_create_groups($restore,$xml_file) {
  2982. global $CFG;
  2983. //Check it exists
  2984. if (!file_exists($xml_file)) {
  2985. return false;
  2986. }
  2987. //Get info from xml
  2988. if (!$groups = restore_read_xml_groups($restore,$xml_file)) {
  2989. //groups will contain the old_id of every group
  2990. //in backup_ids->info will be the real info (serialized)
  2991. return false;
  2992. } else if ($groups === true) {
  2993. return true;
  2994. }
  2995. $status = true;
  2996. //Iterate over each group
  2997. foreach ($groups as $group) {
  2998. //Get record from backup_ids
  2999. $data = backup_getid($restore->backup_unique_code,"groups",$group->id);
  3000. if ($data) {
  3001. //Now get completed xmlized object
  3002. $info = $data->info;
  3003. //traverse_xmlize($info); //Debug
  3004. //print_object ($GLOBALS['traverse_array']); //Debug
  3005. //$GLOBALS['traverse_array']=""; //Debug
  3006. //Now build the GROUP record structure
  3007. $gro = new Object();
  3008. $gro->courseid = $restore->course_id;
  3009. $gro->name = backup_todb($info['GROUP']['#']['NAME']['0']['#']);
  3010. $gro->description = backup_todb($info['GROUP']['#']['DESCRIPTION']['0']['#']);
  3011. if (isset($info['GROUP']['#']['ENROLMENTKEY']['0']['#'])) {
  3012. $gro->enrolmentkey = backup_todb($info['GROUP']['#']['ENROLMENTKEY']['0']['#']);
  3013. } else {
  3014. $gro->enrolmentkey = backup_todb($info['GROUP']['#']['PASSWORD']['0']['#']);
  3015. }
  3016. $gro->picture = backup_todb($info['GROUP']['#']['PICTURE']['0']['#']);
  3017. $gro->hidepicture = backup_todb($info['GROUP']['#']['HIDEPICTURE']['0']['#']);
  3018. $gro->timecreated = backup_todb($info['GROUP']['#']['TIMECREATED']['0']['#']);
  3019. $gro->timemodified = backup_todb($info['GROUP']['#']['TIMEMODIFIED']['0']['#']);
  3020. //Now search if that group exists (by name and description field) in
  3021. //restore->course_id course
  3022. //Going to compare LOB columns so, use the cross-db sql_compare_text() in both sides.
  3023. $description_clause = '';
  3024. if (!empty($gro->description)) { /// Only for groups having a description
  3025. $literal_description = "'" . $gro->description . "'";
  3026. $description_clause = " AND " .
  3027. sql_compare_text('description') . " = " .
  3028. sql_compare_text($literal_description);
  3029. }
  3030. if (!$gro_db = get_record_sql("SELECT *
  3031. FROM {$CFG->prefix}groups
  3032. WHERE courseid = $restore->course_id AND
  3033. name = '{$gro->name}'" . $description_clause, true)) {
  3034. //If it doesn't exist, create
  3035. $newid = insert_record('groups', $gro);
  3036. } else {
  3037. //get current group id
  3038. $newid = $gro_db->id;
  3039. }
  3040. if ($newid) {
  3041. //We have the newid, update backup_ids
  3042. backup_putid($restore->backup_unique_code,"groups", $group->id, $newid);
  3043. } else {
  3044. $status = false;
  3045. continue;
  3046. }
  3047. //Now restore members in the groups_members, only if
  3048. //users are included
  3049. if ($restore->users != 2) {
  3050. if (!restore_create_groups_members($newid,$info,$restore)) {
  3051. $status = false;
  3052. }
  3053. }
  3054. }
  3055. }
  3056. //Now, restore group_files
  3057. if ($status) {
  3058. $status = restore_group_files($restore);
  3059. }
  3060. return $status;
  3061. }
  3062. //This function restores the groups_members
  3063. function restore_create_groups_members($group_id,$info,$restore) {
  3064. if (! isset($info['GROUP']['#']['MEMBERS']['0']['#']['MEMBER'])) {
  3065. //OK, some groups have no members.
  3066. return true;
  3067. }
  3068. //Get the members array
  3069. $members = $info['GROUP']['#']['MEMBERS']['0']['#']['MEMBER'];
  3070. $status = true;
  3071. //Iterate over members
  3072. for($i = 0; $i < sizeof($members); $i++) {
  3073. $mem_info = $members[$i];
  3074. //traverse_xmlize($mem_info); //Debug
  3075. //print_object ($GLOBALS['traverse_array']); //Debug
  3076. //$GLOBALS['traverse_array']=""; //Debug
  3077. //Now, build the GROUPS_MEMBERS record structure
  3078. $group_member = new Object();
  3079. $group_member->groupid = $group_id;
  3080. $group_member->userid = backup_todb($mem_info['#']['USERID']['0']['#']);
  3081. $group_member->timeadded = backup_todb($mem_info['#']['TIMEADDED']['0']['#']);
  3082. $newid = false;
  3083. //We have to recode the userid field
  3084. if (!$user = backup_getid($restore->backup_unique_code,"user",$group_member->userid)) {
  3085. debugging("group membership can not be restored, user id $group_member->userid not present in backup");
  3086. // do not not block the restore
  3087. continue;
  3088. }
  3089. $group_member->userid = $user->new_id;
  3090. //The structure is equal to the db, so insert the groups_members
  3091. if (record_exists("groups_members", 'groupid', $group_member->groupid, 'userid', $group_member->userid)) {
  3092. // user already member
  3093. } else if (!insert_record ("groups_members", $group_member)) {
  3094. $status = false;
  3095. continue;
  3096. }
  3097. //Do some output
  3098. if (($i+1) % 50 == 0) {
  3099. if (!defined('RESTORE_SILENTLY')) {
  3100. echo ".";
  3101. if (($i+1) % 1000 == 0) {
  3102. echo "<br />";
  3103. }
  3104. }
  3105. backup_flush(300);
  3106. }
  3107. }
  3108. return $status;
  3109. }
  3110. //This function creates all the groupings
  3111. function restore_create_groupings($restore,$xml_file) {
  3112. //Check it exists
  3113. if (!file_exists($xml_file)) {
  3114. return false;
  3115. }
  3116. //Get info from xml
  3117. if (!$groupings = restore_read_xml_groupings($restore,$xml_file)) {
  3118. return false;
  3119. } else if ($groupings === true) {
  3120. return true;
  3121. }
  3122. $status = true;
  3123. //Iterate over each group
  3124. foreach ($groupings as $grouping) {
  3125. if ($data = backup_getid($restore->backup_unique_code,"groupings",$grouping->id)) {
  3126. //Now get completed xmlized object
  3127. $info = $data->info;
  3128. //Now build the GROUPING record structure
  3129. $gro = new Object();
  3130. ///$gro->id = backup_todb($info['GROUPING']['#']['ID']['0']['#']);
  3131. $gro->courseid = $restore->course_id;
  3132. $gro->name = backup_todb($info['GROUPING']['#']['NAME']['0']['#']);
  3133. $gro->description = backup_todb($info['GROUPING']['#']['DESCRIPTION']['0']['#']);
  3134. $gro->configdata = backup_todb($info['GROUPING']['#']['CONFIGDATA']['0']['#']);
  3135. $gro->timecreated = backup_todb($info['GROUPING']['#']['TIMECREATED']['0']['#']);
  3136. //Now search if that group exists (by name and description field) in
  3137. if ($gro_db = get_record('groupings', 'courseid', $restore->course_id, 'name', $gro->name, 'description', $gro->description)) {
  3138. //get current group id
  3139. $newid = $gro_db->id;
  3140. } else {
  3141. //The structure is equal to the db, so insert the grouping
  3142. if (!$newid = insert_record('groupings', $gro)) {
  3143. $status = false;
  3144. continue;
  3145. }
  3146. }
  3147. //We have the newid, update backup_ids
  3148. backup_putid($restore->backup_unique_code,"groupings",
  3149. $grouping->id, $newid);
  3150. }
  3151. }
  3152. // now fix the defaultgroupingid in course
  3153. $course = get_record('course', 'id', $restore->course_id);
  3154. if ($course->defaultgroupingid) {
  3155. if ($grouping = restore_grouping_getid($restore, $course->defaultgroupingid)) {
  3156. set_field('course', 'defaultgroupingid', $grouping->new_id, 'id', $course->id);
  3157. } else {
  3158. set_field('course', 'defaultgroupingid', 0, 'id', $course->id);
  3159. }
  3160. }
  3161. return $status;
  3162. }
  3163. //This function creates all the groupingsgroups
  3164. function restore_create_groupings_groups($restore,$xml_file) {
  3165. //Check it exists
  3166. if (!file_exists($xml_file)) {
  3167. return false;
  3168. }
  3169. //Get info from xml
  3170. if (!$groupingsgroups = restore_read_xml_groupings_groups($restore,$xml_file)) {
  3171. return false;
  3172. } else if ($groupingsgroups === true) {
  3173. return true;
  3174. }
  3175. $status = true;
  3176. //Iterate over each group
  3177. foreach ($groupingsgroups as $groupinggroup) {
  3178. if ($data = backup_getid($restore->backup_unique_code,"groupingsgroups",$groupinggroup->id)) {
  3179. //Now get completed xmlized object
  3180. $info = $data->info;
  3181. //Now build the GROUPING record structure
  3182. $gro_member = new Object();
  3183. $gro_member->groupingid = backup_todb($info['GROUPINGGROUP']['#']['GROUPINGID']['0']['#']);
  3184. $gro_member->groupid = backup_todb($info['GROUPINGGROUP']['#']['GROUPID']['0']['#']);
  3185. $gro_member->timeadded = backup_todb($info['GROUPINGGROUP']['#']['TIMEADDED']['0']['#']);
  3186. if (!$grouping = backup_getid($restore->backup_unique_code,"groupings",$gro_member->groupingid)) {
  3187. $status = false;
  3188. continue;
  3189. }
  3190. if (!$group = backup_getid($restore->backup_unique_code,"groups",$gro_member->groupid)) {
  3191. $status = false;
  3192. continue;
  3193. }
  3194. $gro_member->groupid = $group->new_id;
  3195. $gro_member->groupingid = $grouping->new_id;
  3196. if (!get_record('groupings_groups', 'groupid', $gro_member->groupid, 'groupingid', $gro_member->groupingid)) {
  3197. if (!insert_record('groupings_groups', $gro_member)) {
  3198. $status = false;
  3199. }
  3200. }
  3201. }
  3202. }
  3203. return $status;
  3204. }
  3205. //This function creates all the course events
  3206. function restore_create_events($restore,$xml_file) {
  3207. global $CFG, $db;
  3208. $status = true;
  3209. //Check it exists
  3210. if (!file_exists($xml_file)) {
  3211. $status = false;
  3212. }
  3213. //Get info from xml
  3214. if ($status) {
  3215. //events will contain the old_id of every event
  3216. //in backup_ids->info will be the real info (serialized)
  3217. $events = restore_read_xml_events($restore,$xml_file);
  3218. }
  3219. //Get admin->id for later use
  3220. $admin = get_admin();
  3221. $adminid = $admin->id;
  3222. //Now, if we have anything in events, we have to restore that
  3223. //events
  3224. if ($events) {
  3225. if ($events !== true) {
  3226. //Iterate over each event
  3227. foreach ($events as $event) {
  3228. //Get record from backup_ids
  3229. $data = backup_getid($restore->backup_unique_code,"event",$event->id);
  3230. //Init variables
  3231. $create_event = false;
  3232. if ($data) {
  3233. //Now get completed xmlized object
  3234. $info = $data->info;
  3235. //traverse_xmlize($info); //Debug
  3236. //print_object ($GLOBALS['traverse_array']); //Debug
  3237. //$GLOBALS['traverse_array']=""; //Debug
  3238. //if necessary, write to restorelog and adjust date/time fields
  3239. if ($restore->course_startdateoffset) {
  3240. restore_log_date_changes('Events', $restore, $info['EVENT']['#'], array('TIMESTART'));
  3241. }
  3242. //Now build the EVENT record structure
  3243. $eve->name = backup_todb($info['EVENT']['#']['NAME']['0']['#']);
  3244. $eve->description = backup_todb($info['EVENT']['#']['DESCRIPTION']['0']['#']);
  3245. $eve->format = backup_todb($info['EVENT']['#']['FORMAT']['0']['#']);
  3246. $eve->courseid = $restore->course_id;
  3247. $eve->groupid = backup_todb($info['EVENT']['#']['GROUPID']['0']['#']);
  3248. $eve->userid = backup_todb($info['EVENT']['#']['USERID']['0']['#']);
  3249. $eve->repeatid = backup_todb($info['EVENT']['#']['REPEATID']['0']['#']);
  3250. $eve->modulename = "";
  3251. if (!empty($info['EVENT']['#']['MODULENAME'])) {
  3252. $eve->modulename = backup_todb($info['EVENT']['#']['MODULENAME']['0']['#']);
  3253. }
  3254. $eve->instance = 0;
  3255. $eve->eventtype = backup_todb($info['EVENT']['#']['EVENTTYPE']['0']['#']);
  3256. $eve->timestart = backup_todb($info['EVENT']['#']['TIMESTART']['0']['#']);
  3257. $eve->timeduration = backup_todb($info['EVENT']['#']['TIMEDURATION']['0']['#']);
  3258. $eve->visible = backup_todb($info['EVENT']['#']['VISIBLE']['0']['#']);
  3259. $eve->timemodified = backup_todb($info['EVENT']['#']['TIMEMODIFIED']['0']['#']);
  3260. //Now search if that event exists (by name, description, timestart fields) in
  3261. //restore->course_id course
  3262. //Going to compare LOB columns so, use the cross-db sql_compare_text() in both sides.
  3263. $compare_description_clause = sql_compare_text('description') . "=" . sql_compare_text("'" . $eve->description . "'");
  3264. $eve_db = get_record_select("event",
  3265. "courseid={$eve->courseid} AND name='{$eve->name}' AND $compare_description_clause AND timestart=$eve->timestart");
  3266. //If it doesn't exist, create
  3267. if (!$eve_db) {
  3268. $create_event = true;
  3269. }
  3270. //If we must create the event
  3271. if ($create_event) {
  3272. //We must recode the userid
  3273. $user = backup_getid($restore->backup_unique_code,"user",$eve->userid);
  3274. if ($user) {
  3275. $eve->userid = $user->new_id;
  3276. } else {
  3277. //Assign it to admin
  3278. $eve->userid = $adminid;
  3279. }
  3280. //We have to recode the groupid field
  3281. $group = backup_getid($restore->backup_unique_code,"groups",$eve->groupid);
  3282. if ($group) {
  3283. $eve->groupid = $group->new_id;
  3284. } else {
  3285. //Assign it to group 0
  3286. $eve->groupid = 0;
  3287. }
  3288. //The structure is equal to the db, so insert the event
  3289. $newid = insert_record ("event",$eve);
  3290. //We must recode the repeatid if the event has it
  3291. //The repeatid now refers to the id of the original event. (see Bug#5956)
  3292. if ($newid && !empty($eve->repeatid)) {
  3293. $repeat_rec = backup_getid($restore->backup_unique_code,"event_repeatid",$eve->repeatid);
  3294. if ($repeat_rec) { //Exists, so use it...
  3295. $eve->repeatid = $repeat_rec->new_id;
  3296. } else { //Doesn't exists, calculate the next and save it
  3297. $oldrepeatid = $eve->repeatid;
  3298. $eve->repeatid = $newid;
  3299. backup_putid($restore->backup_unique_code,"event_repeatid", $oldrepeatid, $eve->repeatid);
  3300. }
  3301. $eve->id = $newid;
  3302. // update the record to contain the correct repeatid
  3303. update_record('event',$eve);
  3304. }
  3305. } else {
  3306. //get current event id
  3307. $newid = $eve_db->id;
  3308. }
  3309. if ($newid) {
  3310. //We have the newid, update backup_ids
  3311. backup_putid($restore->backup_unique_code,"event",
  3312. $event->id, $newid);
  3313. }
  3314. }
  3315. }
  3316. }
  3317. } else {
  3318. $status = false;
  3319. }
  3320. return $status;
  3321. }
  3322. //This function decode things to make restore multi-site fully functional
  3323. //It does this conversions:
  3324. // - $@FILEPHP@$ ---|------------> $CFG->wwwroot/file.php/courseid (slasharguments on)
  3325. // |------------> $CFG->wwwroot/file.php?file=/courseid (slasharguments off)
  3326. //
  3327. // - $@SLASH@$ --|---------------> / (slasharguments on)
  3328. // |---------------> %2F (slasharguments off)
  3329. //
  3330. // - $@FORCEDOWNLOAD@$ --|-------> ?forcedownload=1 (slasharguments on)
  3331. // |-------> &amp;forcedownload=1(slasharguments off)
  3332. //Note: Inter-activities linking is being implemented as a final
  3333. //step in the restore execution, because we need to have it
  3334. //finished to know all the oldid, newid equivaleces
  3335. function restore_decode_absolute_links($content) {
  3336. global $CFG,$restore;
  3337. require_once($CFG->libdir.'/filelib.php');
  3338. /// MDL-14072: Prevent NULLs, empties and numbers to be processed by the
  3339. /// heavy interlinking. Just a few cpu cycles saved.
  3340. if ($content === NULL) {
  3341. return NULL;
  3342. } else if ($content === '') {
  3343. return '';
  3344. } else if (is_numeric($content)) {
  3345. return $content;
  3346. }
  3347. //Now decode wwwroot and file.php calls
  3348. $search = array ("$@FILEPHP@$");
  3349. $replace = array(get_file_url($restore->course_id));
  3350. $result = str_replace($search,$replace,$content);
  3351. //Now $@SLASH@$ and $@FORCEDOWNLOAD@$ MDL-18799
  3352. $search = array('$@SLASH@$', '$@FORCEDOWNLOAD@$');
  3353. if ($CFG->slasharguments) {
  3354. $replace = array('/', '?forcedownload=1');
  3355. } else {
  3356. $replace = array('%2F', '&amp;forcedownload=1');
  3357. }
  3358. $result = str_replace($search, $replace, $result);
  3359. if ($result != $content && debugging()) { //Debug
  3360. if (!defined('RESTORE_SILENTLY')) {
  3361. echo '<br /><hr />'.s($content).'<br />changed to<br />'.s($result).'<hr /><br />'; //Debug
  3362. }
  3363. } //Debug
  3364. return $result;
  3365. }
  3366. //This function restores the userfiles from the temp (user_files) directory to the
  3367. //dataroot/users directory
  3368. function restore_user_files($restore) {
  3369. global $CFG;
  3370. $status = true;
  3371. $counter = 0;
  3372. // 'users' is the old users folder, 'user' is the new one, with a new hierarchy. Detect which one is here and treat accordingly
  3373. //in CFG->dataroot
  3374. $dest_dir = $CFG->dataroot."/user";
  3375. $status = check_dir_exists($dest_dir,true);
  3376. //Now, we iterate over "user_files" records to check if that user dir must be
  3377. //copied (and renamed) to the "users" dir.
  3378. $rootdir = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/user_files";
  3379. //Check if directory exists
  3380. $userlist = array();
  3381. if (is_dir($rootdir) && ($list = list_directories ($rootdir))) {
  3382. $counter = 0;
  3383. foreach ($list as $dir) {
  3384. // If there are directories in this folder, we are in the new user hierarchy
  3385. if ($newlist = list_directories("$rootdir/$dir")) {
  3386. foreach ($newlist as $olduserid) {
  3387. $userlist[$olduserid] = "$rootdir/$dir/$olduserid";
  3388. }
  3389. } else {
  3390. $userlist[$dir] = "$rootdir/$dir";
  3391. }
  3392. }
  3393. foreach ($userlist as $olduserid => $backup_location) {
  3394. //Look for dir like username in backup_ids
  3395. //If that user exists in backup_ids
  3396. if ($user = backup_getid($restore->backup_unique_code,"user",$olduserid)) {
  3397. //Only if user has been created now or if it existed previously, but he hasn't got an image (see bug 1123)
  3398. $newuserdir = make_user_directory($user->new_id, true); // Doesn't create the folder, just returns the location
  3399. // restore images if new user or image does not exist yet
  3400. if (!empty($user->new) or !check_dir_exists($newuserdir)) {
  3401. if (make_user_directory($user->new_id)) { // Creates the folder
  3402. $status = backup_copy_file($backup_location, $newuserdir, true);
  3403. $counter ++;
  3404. }
  3405. //Do some output
  3406. if ($counter % 2 == 0) {
  3407. if (!defined('RESTORE_SILENTLY')) {
  3408. echo ".";
  3409. if ($counter % 40 == 0) {
  3410. echo "<br />";
  3411. }
  3412. }
  3413. backup_flush(300);
  3414. }
  3415. }
  3416. }
  3417. }
  3418. }
  3419. //If status is ok and whe have dirs created, returns counter to inform
  3420. if ($status and $counter) {
  3421. return $counter;
  3422. } else {
  3423. return $status;
  3424. }
  3425. }
  3426. //This function restores the groupfiles from the temp (group_files) directory to the
  3427. //dataroot/groups directory
  3428. function restore_group_files($restore) {
  3429. global $CFG;
  3430. $status = true;
  3431. $counter = 0;
  3432. //First, we check to "groups" exists and create is as necessary
  3433. //in CFG->dataroot
  3434. $dest_dir = $CFG->dataroot.'/groups';
  3435. $status = check_dir_exists($dest_dir,true);
  3436. //Now, we iterate over "group_files" records to check if that user dir must be
  3437. //copied (and renamed) to the "groups" dir.
  3438. $rootdir = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/group_files";
  3439. //Check if directory exists
  3440. if (is_dir($rootdir)) {
  3441. $list = list_directories ($rootdir);
  3442. if ($list) {
  3443. //Iterate
  3444. $counter = 0;
  3445. foreach ($list as $dir) {
  3446. //Look for dir like groupid in backup_ids
  3447. $data = get_record ("backup_ids","backup_code",$restore->backup_unique_code,
  3448. "table_name","groups",
  3449. "old_id",$dir);
  3450. //If that group exists in backup_ids
  3451. if ($data) {
  3452. if (!file_exists($dest_dir."/".$data->new_id)) {
  3453. $status = backup_copy_file($rootdir."/".$dir, $dest_dir."/".$data->new_id,true);
  3454. $counter ++;
  3455. }
  3456. //Do some output
  3457. if ($counter % 2 == 0) {
  3458. if (!defined('RESTORE_SILENTLY')) {
  3459. echo ".";
  3460. if ($counter % 40 == 0) {
  3461. echo "<br />";
  3462. }
  3463. }
  3464. backup_flush(300);
  3465. }
  3466. }
  3467. }
  3468. }
  3469. }
  3470. //If status is ok and whe have dirs created, returns counter to inform
  3471. if ($status and $counter) {
  3472. return $counter;
  3473. } else {
  3474. return $status;
  3475. }
  3476. }
  3477. //This function restores the course files from the temp (course_files) directory to the
  3478. //dataroot/course_id directory
  3479. function restore_course_files($restore) {
  3480. global $CFG;
  3481. $status = true;
  3482. $counter = 0;
  3483. //First, we check to "course_id" exists and create is as necessary
  3484. //in CFG->dataroot
  3485. $dest_dir = $CFG->dataroot."/".$restore->course_id;
  3486. $status = check_dir_exists($dest_dir,true);
  3487. //Now, we iterate over "course_files" records to check if that file/dir must be
  3488. //copied to the "dest_dir" dir.
  3489. $rootdir = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/course_files";
  3490. //Check if directory exists
  3491. if (is_dir($rootdir)) {
  3492. $list = list_directories_and_files ($rootdir);
  3493. if ($list) {
  3494. //Iterate
  3495. $counter = 0;
  3496. foreach ($list as $dir) {
  3497. //Copy the dir to its new location
  3498. //Only if destination file/dir doesn exists
  3499. if (!file_exists($dest_dir."/".$dir)) {
  3500. $status = backup_copy_file($rootdir."/".$dir,
  3501. $dest_dir."/".$dir,true);
  3502. $counter ++;
  3503. }
  3504. //Do some output
  3505. if ($counter % 2 == 0) {
  3506. if (!defined('RESTORE_SILENTLY')) {
  3507. echo ".";
  3508. if ($counter % 40 == 0) {
  3509. echo "<br />";
  3510. }
  3511. }
  3512. backup_flush(300);
  3513. }
  3514. }
  3515. }
  3516. }
  3517. //If status is ok and whe have dirs created, returns counter to inform
  3518. if ($status and $counter) {
  3519. return $counter;
  3520. } else {
  3521. return $status;
  3522. }
  3523. }
  3524. //This function restores the site files from the temp (site_files) directory to the
  3525. //dataroot/SITEID directory
  3526. function restore_site_files($restore) {
  3527. global $CFG;
  3528. $status = true;
  3529. $counter = 0;
  3530. //First, we check to "course_id" exists and create is as necessary
  3531. //in CFG->dataroot
  3532. $dest_dir = $CFG->dataroot."/".SITEID;
  3533. $status = check_dir_exists($dest_dir,true);
  3534. //Now, we iterate over "site_files" files to check if that file/dir must be
  3535. //copied to the "dest_dir" dir.
  3536. $rootdir = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/site_files";
  3537. //Check if directory exists
  3538. if (is_dir($rootdir)) {
  3539. $list = list_directories_and_files ($rootdir);
  3540. if ($list) {
  3541. //Iterate
  3542. $counter = 0;
  3543. foreach ($list as $dir) {
  3544. //Avoid copying maintenance.html. MDL-18594
  3545. if ($dir == 'maintenance.html') {
  3546. continue;
  3547. }
  3548. //Copy the dir to its new location
  3549. //Only if destination file/dir doesn exists
  3550. if (!file_exists($dest_dir."/".$dir)) {
  3551. $status = backup_copy_file($rootdir."/".$dir,
  3552. $dest_dir."/".$dir,true);
  3553. $counter ++;
  3554. }
  3555. //Do some output
  3556. if ($counter % 2 == 0) {
  3557. if (!defined('RESTORE_SILENTLY')) {
  3558. echo ".";
  3559. if ($counter % 40 == 0) {
  3560. echo "<br />";
  3561. }
  3562. }
  3563. backup_flush(300);
  3564. }
  3565. }
  3566. }
  3567. }
  3568. //If status is ok and whe have dirs created, returns counter to inform
  3569. if ($status and $counter) {
  3570. return $counter;
  3571. } else {
  3572. return $status;
  3573. }
  3574. }
  3575. //This function creates all the structures for every module in backup file
  3576. //Depending what has been selected.
  3577. function restore_create_modules($restore,$xml_file) {
  3578. global $CFG;
  3579. $status = true;
  3580. //Check it exists
  3581. if (!file_exists($xml_file)) {
  3582. $status = false;
  3583. }
  3584. //Get info from xml
  3585. if ($status) {
  3586. //info will contain the id and modtype of every module
  3587. //in backup_ids->info will be the real info (serialized)
  3588. $info = restore_read_xml_modules($restore,$xml_file);
  3589. }
  3590. //Now, if we have anything in info, we have to restore that mods
  3591. //from backup_ids (calling every mod restore function)
  3592. if ($info) {
  3593. if ($info !== true) {
  3594. if (!defined('RESTORE_SILENTLY')) {
  3595. echo '<ul>';
  3596. }
  3597. //Iterate over each module
  3598. foreach ($info as $mod) {
  3599. if (empty($restore->mods[$mod->modtype]->granular) // We don't care about per instance, i.e. restore all instances.
  3600. || (array_key_exists($mod->id,$restore->mods[$mod->modtype]->instances)
  3601. && !empty($restore->mods[$mod->modtype]->instances[$mod->id]->restore))) {
  3602. $modrestore = $mod->modtype."_restore_mods";
  3603. if (function_exists($modrestore)) { //Debug
  3604. // we want to restore all mods even when one fails
  3605. // incorrect code here ignored any errors during module restore in 1.6-1.8
  3606. $status = $status && $modrestore($mod,$restore);
  3607. } else {
  3608. //Something was wrong. Function should exist.
  3609. $status = false;
  3610. }
  3611. }
  3612. }
  3613. if (!defined('RESTORE_SILENTLY')) {
  3614. echo '</ul>';
  3615. }
  3616. }
  3617. } else {
  3618. $status = false;
  3619. }
  3620. return $status;
  3621. }
  3622. //This function creates all the structures for every log in backup file
  3623. //Depending what has been selected.
  3624. function restore_create_logs($restore,$xml_file) {
  3625. global $CFG,$db;
  3626. //Number of records to get in every chunk
  3627. $recordset_size = 4;
  3628. //Counter, points to current record
  3629. $counter = 0;
  3630. //To count all the recods to restore
  3631. $count_logs = 0;
  3632. $status = true;
  3633. //Check it exists
  3634. if (!file_exists($xml_file)) {
  3635. $status = false;
  3636. }
  3637. //Get info from xml
  3638. if ($status) {
  3639. //count_logs will contain the number of logs entries to process
  3640. //in backup_ids->info will be the real info (serialized)
  3641. $count_logs = restore_read_xml_logs($restore,$xml_file);
  3642. }
  3643. //Now, if we have records in count_logs, we have to restore that logs
  3644. //from backup_ids. This piece of code makes calls to:
  3645. // - restore_log_course() if it's a course log
  3646. // - restore_log_user() if it's a user log
  3647. // - restore_log_module() if it's a module log.
  3648. //And all is segmented in chunks to allow large recordsets to be restored !!
  3649. if ($count_logs > 0) {
  3650. while ($counter < $count_logs) {
  3651. //Get a chunk of records
  3652. //Take old_id twice to avoid adodb limitation
  3653. $logs = get_records_select("backup_ids","table_name = 'log' AND backup_code = '$restore->backup_unique_code'","old_id","old_id",$counter,$recordset_size);
  3654. //We have logs
  3655. if ($logs) {
  3656. //Iterate
  3657. foreach ($logs as $log) {
  3658. //Get the full record from backup_ids
  3659. $data = backup_getid($restore->backup_unique_code,"log",$log->old_id);
  3660. if ($data) {
  3661. //Now get completed xmlized object
  3662. $info = $data->info;
  3663. //traverse_xmlize($info); //Debug
  3664. //print_object ($GLOBALS['traverse_array']); //Debug
  3665. //$GLOBALS['traverse_array']=""; //Debug
  3666. //Now build the LOG record structure
  3667. $dblog = new object();
  3668. $dblog->time = backup_todb($info['LOG']['#']['TIME']['0']['#']);
  3669. $dblog->userid = backup_todb($info['LOG']['#']['USERID']['0']['#']);
  3670. $dblog->ip = backup_todb($info['LOG']['#']['IP']['0']['#']);
  3671. $dblog->course = $restore->course_id;
  3672. $dblog->module = backup_todb($info['LOG']['#']['MODULE']['0']['#']);
  3673. $dblog->cmid = backup_todb($info['LOG']['#']['CMID']['0']['#']);
  3674. $dblog->action = backup_todb($info['LOG']['#']['ACTION']['0']['#']);
  3675. $dblog->url = backup_todb($info['LOG']['#']['URL']['0']['#']);
  3676. $dblog->info = backup_todb($info['LOG']['#']['INFO']['0']['#']);
  3677. //We have to recode the userid field
  3678. $user = backup_getid($restore->backup_unique_code,"user",$dblog->userid);
  3679. if ($user) {
  3680. //echo "User ".$dblog->userid." to user ".$user->new_id."<br />"; //Debug
  3681. $dblog->userid = $user->new_id;
  3682. }
  3683. //We have to recode the cmid field (if module isn't "course" or "user")
  3684. if ($dblog->module != "course" and $dblog->module != "user") {
  3685. $cm = backup_getid($restore->backup_unique_code,"course_modules",$dblog->cmid);
  3686. if ($cm) {
  3687. //echo "Module ".$dblog->cmid." to module ".$cm->new_id."<br />"; //Debug
  3688. $dblog->cmid = $cm->new_id;
  3689. } else {
  3690. $dblog->cmid = 0;
  3691. }
  3692. }
  3693. //print_object ($dblog); //Debug
  3694. //Now, we redirect to the needed function to make all the work
  3695. if ($dblog->module == "course") {
  3696. //It's a course log,
  3697. $stat = restore_log_course($restore,$dblog);
  3698. } elseif ($dblog->module == "user") {
  3699. //It's a user log,
  3700. $stat = restore_log_user($restore,$dblog);
  3701. } else {
  3702. //It's a module log,
  3703. $stat = restore_log_module($restore,$dblog);
  3704. }
  3705. }
  3706. //Do some output
  3707. $counter++;
  3708. if ($counter % 10 == 0) {
  3709. if (!defined('RESTORE_SILENTLY')) {
  3710. echo ".";
  3711. if ($counter % 200 == 0) {
  3712. echo "<br />";
  3713. }
  3714. }
  3715. backup_flush(300);
  3716. }
  3717. }
  3718. } else {
  3719. //We never should arrive here
  3720. $counter = $count_logs;
  3721. $status = false;
  3722. }
  3723. }
  3724. }
  3725. return $status;
  3726. }
  3727. //This function inserts a course log record, calculating the URL field as necessary
  3728. function restore_log_course($restore,$log) {
  3729. $status = true;
  3730. $toinsert = false;
  3731. //echo "<hr />Before transformations<br />"; //Debug
  3732. //print_object($log); //Debug
  3733. //Depending of the action, we recode different things
  3734. switch ($log->action) {
  3735. case "view":
  3736. $log->url = "view.php?id=".$log->course;
  3737. $log->info = $log->course;
  3738. $toinsert = true;
  3739. break;
  3740. case "guest":
  3741. $log->url = "view.php?id=".$log->course;
  3742. $toinsert = true;
  3743. break;
  3744. case "user report":
  3745. //recode the info field (it's the user id)
  3746. $user = backup_getid($restore->backup_unique_code,"user",$log->info);
  3747. if ($user) {
  3748. $log->info = $user->new_id;
  3749. //Now, extract the mode from the url field
  3750. $mode = substr(strrchr($log->url,"="),1);
  3751. $log->url = "user.php?id=".$log->course."&user=".$log->info."&mode=".$mode;
  3752. $toinsert = true;
  3753. }
  3754. break;
  3755. case "add mod":
  3756. //Extract the course_module from the url field
  3757. $cmid = substr(strrchr($log->url,"="),1);
  3758. //recode the course_module to see it it has been restored
  3759. $cm = backup_getid($restore->backup_unique_code,"course_modules",$cmid);
  3760. if ($cm) {
  3761. $cmid = $cm->new_id;
  3762. //Extract the module name and the module id from the info field
  3763. $modname = strtok($log->info," ");
  3764. $modid = strtok(" ");
  3765. //recode the module id to see if it has been restored
  3766. $mod = backup_getid($restore->backup_unique_code,$modname,$modid);
  3767. if ($mod) {
  3768. $modid = $mod->new_id;
  3769. //Now I have everything so reconstruct url and info
  3770. $log->info = $modname." ".$modid;
  3771. $log->url = "../mod/".$modname."/view.php?id=".$cmid;
  3772. $toinsert = true;
  3773. }
  3774. }
  3775. break;
  3776. case "update mod":
  3777. //Extract the course_module from the url field
  3778. $cmid = substr(strrchr($log->url,"="),1);
  3779. //recode the course_module to see it it has been restored
  3780. $cm = backup_getid($restore->backup_unique_code,"course_modules",$cmid);
  3781. if ($cm) {
  3782. $cmid = $cm->new_id;
  3783. //Extract the module name and the module id from the info field
  3784. $modname = strtok($log->info," ");
  3785. $modid = strtok(" ");
  3786. //recode the module id to see if it has been restored
  3787. $mod = backup_getid($restore->backup_unique_code,$modname,$modid);
  3788. if ($mod) {
  3789. $modid = $mod->new_id;
  3790. //Now I have everything so reconstruct url and info
  3791. $log->info = $modname." ".$modid;
  3792. $log->url = "../mod/".$modname."/view.php?id=".$cmid;
  3793. $toinsert = true;
  3794. }
  3795. }
  3796. break;
  3797. case "delete mod":
  3798. $log->url = "view.php?id=".$log->course;
  3799. $toinsert = true;
  3800. break;
  3801. case "update":
  3802. $log->url = "edit.php?id=".$log->course;
  3803. $log->info = "";
  3804. $toinsert = true;
  3805. break;
  3806. case "unenrol":
  3807. //recode the info field (it's the user id)
  3808. $user = backup_getid($restore->backup_unique_code,"user",$log->info);
  3809. if ($user) {
  3810. $log->info = $user->new_id;
  3811. $log->url = "view.php?id=".$log->course;
  3812. $toinsert = true;
  3813. }
  3814. break;
  3815. case "enrol":
  3816. //recode the info field (it's the user id)
  3817. $user = backup_getid($restore->backup_unique_code,"user",$log->info);
  3818. if ($user) {
  3819. $log->info = $user->new_id;
  3820. $log->url = "view.php?id=".$log->course;
  3821. $toinsert = true;
  3822. }
  3823. break;
  3824. case "editsection":
  3825. //Extract the course_section from the url field
  3826. $secid = substr(strrchr($log->url,"="),1);
  3827. //recode the course_section to see if it has been restored
  3828. $sec = backup_getid($restore->backup_unique_code,"course_sections",$secid);
  3829. if ($sec) {
  3830. $secid = $sec->new_id;
  3831. //Now I have everything so reconstruct url and info
  3832. $log->url = "editsection.php?id=".$secid;
  3833. $toinsert = true;
  3834. }
  3835. break;
  3836. case "new":
  3837. $log->url = "view.php?id=".$log->course;
  3838. $log->info = "";
  3839. $toinsert = true;
  3840. break;
  3841. case "recent":
  3842. $log->url = "recent.php?id=".$log->course;
  3843. $log->info = "";
  3844. $toinsert = true;
  3845. break;
  3846. case "report log":
  3847. $log->url = "report/log/index.php?id=".$log->course;
  3848. $log->info = $log->course;
  3849. $toinsert = true;
  3850. break;
  3851. case "report live":
  3852. $log->url = "report/log/live.php?id=".$log->course;
  3853. $log->info = $log->course;
  3854. $toinsert = true;
  3855. break;
  3856. case "report outline":
  3857. $log->url = "report/outline/index.php?id=".$log->course;
  3858. $log->info = $log->course;
  3859. $toinsert = true;
  3860. break;
  3861. case "report participation":
  3862. $log->url = "report/participation/index.php?id=".$log->course;
  3863. $log->info = $log->course;
  3864. $toinsert = true;
  3865. break;
  3866. case "report stats":
  3867. $log->url = "report/stats/index.php?id=".$log->course;
  3868. $log->info = $log->course;
  3869. $toinsert = true;
  3870. break;
  3871. default:
  3872. echo "action (".$log->module."-".$log->action.") unknown. Not restored<br />"; //Debug
  3873. break;
  3874. }
  3875. //echo "After transformations<br />"; //Debug
  3876. //print_object($log); //Debug
  3877. //Now if $toinsert is set, insert the record
  3878. if ($toinsert) {
  3879. //echo "Inserting record<br />"; //Debug
  3880. $status = insert_record("log",$log);
  3881. }
  3882. return $status;
  3883. }
  3884. //This function inserts a user log record, calculating the URL field as necessary
  3885. function restore_log_user($restore,$log) {
  3886. $status = true;
  3887. $toinsert = false;
  3888. //echo "<hr />Before transformations<br />"; //Debug
  3889. //print_object($log); //Debug
  3890. //Depending of the action, we recode different things
  3891. switch ($log->action) {
  3892. case "view":
  3893. //recode the info field (it's the user id)
  3894. $user = backup_getid($restore->backup_unique_code,"user",$log->info);
  3895. if ($user) {
  3896. $log->info = $user->new_id;
  3897. $log->url = "view.php?id=".$log->info."&course=".$log->course;
  3898. $toinsert = true;
  3899. }
  3900. break;
  3901. case "change password":
  3902. //recode the info field (it's the user id)
  3903. $user = backup_getid($restore->backup_unique_code,"user",$log->info);
  3904. if ($user) {
  3905. $log->info = $user->new_id;
  3906. $log->url = "view.php?id=".$log->info."&course=".$log->course;
  3907. $toinsert = true;
  3908. }
  3909. break;
  3910. case "login":
  3911. //recode the info field (it's the user id)
  3912. $user = backup_getid($restore->backup_unique_code,"user",$log->info);
  3913. if ($user) {
  3914. $log->info = $user->new_id;
  3915. $log->url = "view.php?id=".$log->info."&course=".$log->course;
  3916. $toinsert = true;
  3917. }
  3918. break;
  3919. case "logout":
  3920. //recode the info field (it's the user id)
  3921. $user = backup_getid($restore->backup_unique_code,"user",$log->info);
  3922. if ($user) {
  3923. $log->info = $user->new_id;
  3924. $log->url = "view.php?id=".$log->info."&course=".$log->course;
  3925. $toinsert = true;
  3926. }
  3927. break;
  3928. case "view all":
  3929. $log->url = "view.php?id=".$log->course;
  3930. $log->info = "";
  3931. $toinsert = true;
  3932. case "update":
  3933. //We split the url by ampersand char
  3934. $first_part = strtok($log->url,"&");
  3935. //Get data after the = char. It's the user being updated
  3936. $userid = substr(strrchr($first_part,"="),1);
  3937. //Recode the user
  3938. $user = backup_getid($restore->backup_unique_code,"user",$userid);
  3939. if ($user) {
  3940. $log->info = "";
  3941. $log->url = "view.php?id=".$user->new_id."&course=".$log->course;
  3942. $toinsert = true;
  3943. }
  3944. break;
  3945. default:
  3946. echo "action (".$log->module."-".$log->action.") unknown. Not restored<br />"; //Debug
  3947. break;
  3948. }
  3949. //echo "After transformations<br />"; //Debug
  3950. //print_object($log); //Debug
  3951. //Now if $toinsert is set, insert the record
  3952. if ($toinsert) {
  3953. //echo "Inserting record<br />"; //Debug
  3954. $status = insert_record("log",$log);
  3955. }
  3956. return $status;
  3957. }
  3958. //This function inserts a module log record, calculating the URL field as necessary
  3959. function restore_log_module($restore,$log) {
  3960. $status = true;
  3961. $toinsert = false;
  3962. //echo "<hr />Before transformations<br />"; //Debug
  3963. //print_object($log); //Debug
  3964. //Now we see if the required function in the module exists
  3965. $function = $log->module."_restore_logs";
  3966. if (function_exists($function)) {
  3967. //Call the function
  3968. $log = $function($restore,$log);
  3969. //If everything is ok, mark the insert flag
  3970. if ($log) {
  3971. $toinsert = true;
  3972. }
  3973. }
  3974. //echo "After transformations<br />"; //Debug
  3975. //print_object($log); //Debug
  3976. //Now if $toinsert is set, insert the record
  3977. if ($toinsert) {
  3978. //echo "Inserting record<br />"; //Debug
  3979. $status = insert_record("log",$log);
  3980. }
  3981. return $status;
  3982. }
  3983. //This function adjusts the instance field into course_modules. It's executed after
  3984. //modules restore. There, we KNOW the new instance id !!
  3985. function restore_check_instances($restore) {
  3986. global $CFG;
  3987. $status = true;
  3988. //We are going to iterate over each course_module saved in backup_ids
  3989. $course_modules = get_records_sql("SELECT old_id,new_id
  3990. FROM {$CFG->prefix}backup_ids
  3991. WHERE backup_code = '$restore->backup_unique_code' AND
  3992. table_name = 'course_modules'");
  3993. if ($course_modules) {
  3994. foreach($course_modules as $cm) {
  3995. //Get full record, using backup_getids
  3996. $cm_module = backup_getid($restore->backup_unique_code,"course_modules",$cm->old_id);
  3997. //Now we are going to the REAL course_modules to get its type (field module)
  3998. $module = get_record("course_modules","id",$cm_module->new_id);
  3999. if ($module) {
  4000. //We know the module type id. Get the name from modules
  4001. $type = get_record("modules","id",$module->module);
  4002. if ($type) {
  4003. //We know the type name and the old_id. Get its new_id
  4004. //from backup_ids. It's the instance !!!
  4005. $instance = backup_getid($restore->backup_unique_code,$type->name,$cm_module->info);
  4006. if ($instance) {
  4007. //We have the new instance, so update the record in course_modules
  4008. $module->instance = $instance->new_id;
  4009. //print_object ($module); //Debug
  4010. $status = update_record("course_modules",$module);
  4011. } else {
  4012. $status = false;
  4013. }
  4014. } else {
  4015. $status = false;
  4016. }
  4017. } else {
  4018. $status = false;
  4019. }
  4020. // MDL-14326 remove empty course modules instance's (credit goes to John T. Macklin from Remote Learner)
  4021. $course_modules_inst_zero = get_records_sql("SELECT id, course, instance
  4022. FROM {$CFG->prefix}course_modules
  4023. WHERE id = '$cm_module->new_id' AND
  4024. instance = '0'");
  4025. if($course_modules_inst_zero){ // Clean up the invalid instances
  4026. foreach($course_modules_inst_zero as $course_modules_inst){
  4027. delete_records('course_modules', 'id',$course_modules_inst->id);
  4028. }
  4029. }
  4030. }
  4031. /// Finally, calculate modinfo cache.
  4032. rebuild_course_cache($restore->course_id);
  4033. }
  4034. return $status;
  4035. }
  4036. //=====================================================================================
  4037. //== ==
  4038. //== XML Functions (SAX) ==
  4039. //== ==
  4040. //=====================================================================================
  4041. /// This is the class used to split, in first instance, the monolithic moodle.xml into
  4042. /// smaller xml files allowing the MoodleParser later to process only the required info
  4043. /// based in each TODO, instead of processing the whole xml for each TODO. In theory
  4044. /// processing time can be reduced upto 1/20th of original time (depending of the
  4045. /// number of TODOs in the original moodle.xml file)
  4046. ///
  4047. /// Anyway, note it's a general splitter parser, and only needs to be instantiated
  4048. /// with the proper destination dir and the tosplit configuration. Be careful when
  4049. /// using it because it doesn't support XML attributes nor real cdata out from tags.
  4050. /// (both not used in the target Moodle backup files)
  4051. class moodle_splitter_parser {
  4052. var $level = 0; /// Level we are
  4053. var $tree = array(); /// Array of levels we are
  4054. var $cdata = ''; /// Raw storage for character data
  4055. var $content = ''; /// Content buffer to be printed to file
  4056. var $trailing= ''; /// Content of the trailing tree for each splited file
  4057. var $savepath = null; /// Path to store splited files
  4058. var $fhandler = null; /// Current file we are writing to
  4059. var $tosplit = array(); /// Array defining the files we want to split, in this format:
  4060. /// array( level/tag/level/tag => filename)
  4061. var $splitwords = array(); /// Denormalised array containing the potential tags
  4062. /// being a split point. To speed up check_split_point()
  4063. var $maxsplitlevel = 0; /// Precalculated max level where any split happens. To speed up check_split_point()
  4064. var $buffersize = 65536; /// 64KB is a good write buffer. Don't expect big benefits by increasing this.
  4065. var $repectformat = false; /// With this setting enabled, the splited files will look like the original one
  4066. /// with all the indentations 100% copied from original (character data outer tags).
  4067. /// But this is a waste of time from our perspective, and splited xml files are completely
  4068. /// functional without that, so we disable this for production, generating a more compact
  4069. /// XML quicker
  4070. /// PHP4 constructor
  4071. function moodle_splitter_parser($savepath, $tosplit = null) {
  4072. return $this->__construct($savepath, $tosplit);
  4073. }
  4074. /// PHP5 constructor
  4075. function __construct($savepath, $tosplit = null) {
  4076. $this->savepath = $savepath;
  4077. if (!empty($tosplit)) {
  4078. $this->tosplit = $tosplit;
  4079. } else { /// No tosplit list passed, process all the possible parts in one moodle.xml file
  4080. $this->tosplit = array(
  4081. '1/MOODLE_BACKUP/2/INFO' => 'split_info.xml',
  4082. '1/MOODLE_BACKUP/2/ROLES' => 'split_roles.xml',
  4083. '2/COURSE/3/HEADER' => 'split_course_header.xml',
  4084. '2/COURSE/3/BLOCKS' => 'split_blocks.xml',
  4085. '2/COURSE/3/SECTIONS' => 'split_sections.xml',
  4086. '2/COURSE/3/FORMATDATA' => 'split_formatdata.xml',
  4087. '2/COURSE/3/METACOURSE' => 'split_metacourse.xml',
  4088. '2/COURSE/3/GRADEBOOK' => 'split_gradebook.xml',
  4089. '2/COURSE/3/USERS' => 'split_users.xml',
  4090. '2/COURSE/3/MESSAGES' => 'split_messages.xml',
  4091. '2/COURSE/3/BLOGS' => 'split_blogs.xml',
  4092. '2/COURSE/3/QUESTION_CATEGORIES'=> 'split_questions.xml',
  4093. '2/COURSE/3/SCALES' => 'split_scales.xml',
  4094. '2/COURSE/3/GROUPS' => 'split_groups.xml',
  4095. '2/COURSE/3/GROUPINGS' => 'split_groupings.xml',
  4096. '2/COURSE/3/GROUPINGSGROUPS' => 'split_groupingsgroups.xml',
  4097. '2/COURSE/3/EVENTS' => 'split_events.xml',
  4098. '2/COURSE/3/MODULES' => 'split_modules.xml',
  4099. '2/COURSE/3/LOGS' => 'split_logs.xml'
  4100. );
  4101. }
  4102. /// Precalculate some info used to speedup checks
  4103. foreach ($this->tosplit as $key=>$value) {
  4104. $this->splitwords[basename($key)] = true;
  4105. if (((int) basename(dirname($key))) > $this->maxsplitlevel) {
  4106. $this->maxsplitlevel = (int) basename(dirname($key));
  4107. }
  4108. }
  4109. }
  4110. /// Given one tag being opened, check if it's one split point.
  4111. /// Return false or split filename
  4112. function check_split_point($tag) {
  4113. /// Quick check. Level < 2 cannot be a split point
  4114. if ($this->level < 2) {
  4115. return false;
  4116. }
  4117. /// Quick check. Current tag against potential splitwords
  4118. if (!isset($this->splitwords[$tag])) {
  4119. return false;
  4120. }
  4121. /// Prev test passed, take a look to 2-level tosplit
  4122. $keytocheck = ($this->level - 1) . '/' . $this->tree[$this->level - 1] . '/' . $this->level . '/' . $this->tree[$this->level];
  4123. if (!isset($this->tosplit[$keytocheck])) {
  4124. return false;
  4125. }
  4126. /// Prev test passed, we are in a split point, return new filename
  4127. return $this->tosplit[$keytocheck];
  4128. }
  4129. /// To append data (xml-escaped) to contents buffer
  4130. function character_data($parser, $data) {
  4131. ///$this->content .= preg_replace($this->entity_find, $this->entity_replace, $data); ///40% slower
  4132. ///$this->content .= str_replace($this->entity_find, $this->entity_replace, $data); ///25% slower
  4133. ///$this->content .= htmlspecialchars($data); ///the best
  4134. /// Instead of htmlspecialchars() each chunk of character data, we are going to
  4135. /// concat it without transformation and will apply the htmlspecialchars() when
  4136. /// that character data is, efectively, going to be added to contents buffer. This
  4137. /// makes the number of transformations to be reduced (speedup) and avoid potential
  4138. /// problems with transformations being applied "in the middle" of multibyte chars.
  4139. $this->cdata .= $data;
  4140. }
  4141. /// To detect start of tags, keeping level, tree and fhandle updated.
  4142. /// Also handles creation of split files
  4143. function start_tag($parser, $tag, $attrs) {
  4144. /// Update things before processing
  4145. $this->level++;
  4146. $this->tree[$this->level] = $tag;
  4147. /// Check if we need to start a new split file,
  4148. /// Speedup: we only do that if we haven't a fhandler and if level <= $maxsplitlevel
  4149. if ($this->level <= $this->maxsplitlevel && !$this->fhandler && $newfilename = $this->check_split_point($tag)) {
  4150. /// Open new file handler, init everything
  4151. $this->fhandler = fopen($this->savepath . '/' . $newfilename, 'w');
  4152. $this->content = '';
  4153. $this->cdata = '';
  4154. $this->trailing = '';
  4155. /// Build the original leading tree (and calculate the original trailing one)
  4156. for ($l = 1; $l < $this->level; $l++) {
  4157. $this->content .= "<{$this->tree[$l]}>\n";
  4158. $this->trailing = "\n</{$this->tree[$l]}>" . $this->trailing;
  4159. }
  4160. }
  4161. /// Perform xml-entities transformation and add to contents buffer together with opening tag.
  4162. /// Speedup. We lose nice formatting of the split XML but avoid 50% of transformations and XML is 100% equivalent
  4163. $this->content .= ($this->repectformat ? htmlspecialchars($this->cdata) : '') . "<$tag>";
  4164. $this->cdata = '';
  4165. }
  4166. /// To detect end of tags, keeping level, tree and fhandle updated, writting contents buffer to split file.
  4167. /// Also handles closing of split files
  4168. function end_tag($parser, $tag) {
  4169. /// Perform xml-entities transformation and add to contents buffer together with closing tag, repecting (or no) format
  4170. $this->content .= ($this->repectformat ? htmlspecialchars($this->cdata) : htmlspecialchars(trim($this->cdata))) . "</$tag>";
  4171. $this->cdata = '';
  4172. /// Check if we need to close current split file
  4173. /// Speedup: we only do that if we have a fhandler and if level <= $maxsplitlevel
  4174. if ($this->level <= $this->maxsplitlevel && $this->fhandler && $newfilename = $this->check_split_point($tag)) {
  4175. /// Write pending contents buffer before closing. It's a must
  4176. fwrite($this->fhandler, $this->content);
  4177. $this->content = "";
  4178. /// Write the original trailing tree for fhandler
  4179. fwrite($this->fhandler, $this->trailing);
  4180. fclose($this->fhandler);
  4181. $this->fhandler = null;
  4182. } else {
  4183. /// Normal write of contents (use one buffer to improve speed)
  4184. if ($this->fhandler && strlen($this->content) > $this->buffersize) {
  4185. fwrite($this->fhandler, $this->content);
  4186. $this->content = "";
  4187. }
  4188. }
  4189. /// Update things after processing
  4190. $this->tree[$this->level] = "";
  4191. $this->level--;
  4192. }
  4193. }
  4194. /// This function executes the moodle_splitter_parser, causing the monolithic moodle.xml
  4195. /// file to be splitted in n smaller files for better treatament by the MoodleParser in restore_read_xml()
  4196. function restore_split_xml ($xml_file, $preferences) {
  4197. $status = true;
  4198. $xml_parser = xml_parser_create('UTF-8');
  4199. $split_parser = new moodle_splitter_parser(dirname($xml_file));
  4200. xml_set_object($xml_parser,$split_parser);
  4201. xml_set_element_handler($xml_parser, 'start_tag', 'end_tag');
  4202. xml_set_character_data_handler($xml_parser, 'character_data');
  4203. $doteach = filesize($xml_file) / 20;
  4204. $fromdot = 0;
  4205. $fp = fopen($xml_file,"r")
  4206. or $status = false;
  4207. if ($status) {
  4208. $lasttime = time();
  4209. while ($data = fread($fp, 8192)) {
  4210. if (!defined('RESTORE_SILENTLY')) {
  4211. $fromdot += 8192;
  4212. if ($fromdot > $doteach) {
  4213. echo ".";
  4214. backup_flush(300);
  4215. $fromdot = 0;
  4216. }
  4217. if ((time() - $lasttime) > 10) {
  4218. $lasttime = time();
  4219. backup_flush(300);
  4220. }
  4221. }
  4222. xml_parse($xml_parser, $data, feof($fp))
  4223. or die(sprintf("XML error: %s at line %d",
  4224. xml_error_string(xml_get_error_code($xml_parser)),
  4225. xml_get_current_line_number($xml_parser)));
  4226. }
  4227. fclose($fp);
  4228. }
  4229. xml_parser_free($xml_parser);
  4230. return $status;
  4231. }
  4232. //This is the class used to do all the xml parse
  4233. class MoodleParser {
  4234. var $level = 0; //Level we are
  4235. var $counter = 0; //Counter
  4236. var $tree = array(); //Array of levels we are
  4237. var $content = ""; //Content under current level
  4238. var $todo = ""; //What we hav to do when parsing
  4239. var $info = ""; //Information collected. Temp storage. Used to return data after parsing.
  4240. var $temp = ""; //Temp storage.
  4241. var $preferences = ""; //Preferences about what to load !!
  4242. var $finished = false; //Flag to say xml_parse to stop
  4243. //This function is used to get the current contents property value
  4244. //They are trimed (and converted from utf8 if needed)
  4245. function getContents() {
  4246. return trim($this->content);
  4247. }
  4248. //This is the startTag handler we use where we are reading the info zone (todo="INFO")
  4249. function startElementInfo($parser, $tagName, $attrs) {
  4250. //Refresh properties
  4251. $this->level++;
  4252. $this->tree[$this->level] = $tagName;
  4253. //Output something to avoid browser timeouts...
  4254. //backup_flush();
  4255. //Check if we are into INFO zone
  4256. //if ($this->tree[2] == "INFO") //Debug
  4257. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4258. }
  4259. //This is the startTag handler we use where we are reading the info zone (todo="INFO")
  4260. function startElementRoles($parser, $tagName, $attrs) {
  4261. //Refresh properties
  4262. $this->level++;
  4263. $this->tree[$this->level] = $tagName;
  4264. //Output something to avoid browser timeouts...
  4265. //backup_flush();
  4266. //Check if we are into INFO zone
  4267. //if ($this->tree[2] == "INFO") //Debug
  4268. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4269. }
  4270. //This is the startTag handler we use where we are reading the course header zone (todo="COURSE_HEADER")
  4271. function startElementCourseHeader($parser, $tagName, $attrs) {
  4272. //Refresh properties
  4273. $this->level++;
  4274. $this->tree[$this->level] = $tagName;
  4275. //Output something to avoid browser timeouts...
  4276. //backup_flush();
  4277. //Check if we are into COURSE_HEADER zone
  4278. //if ($this->tree[3] == "HEADER") //Debug
  4279. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4280. }
  4281. //This is the startTag handler we use where we are reading the blocks zone (todo="BLOCKS")
  4282. function startElementBlocks($parser, $tagName, $attrs) {
  4283. //Refresh properties
  4284. $this->level++;
  4285. $this->tree[$this->level] = $tagName;
  4286. //Output something to avoid browser timeouts...
  4287. //backup_flush();
  4288. //Check if we are into BLOCKS zone
  4289. //if ($this->tree[3] == "BLOCKS") //Debug
  4290. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4291. //If we are under a BLOCK tag under a BLOCKS zone, accumule it
  4292. if (isset($this->tree[4]) and isset($this->tree[3])) { //
  4293. if ($this->tree[4] == "BLOCK" and $this->tree[3] == "BLOCKS") {
  4294. if (!isset($this->temp)) {
  4295. $this->temp = "";
  4296. }
  4297. $this->temp .= "<".$tagName.">";
  4298. }
  4299. }
  4300. }
  4301. //This is the startTag handler we use where we are reading the sections zone (todo="SECTIONS")
  4302. function startElementSections($parser, $tagName, $attrs) {
  4303. //Refresh properties
  4304. $this->level++;
  4305. $this->tree[$this->level] = $tagName;
  4306. //Output something to avoid browser timeouts...
  4307. //backup_flush();
  4308. //Check if we are into SECTIONS zone
  4309. //if ($this->tree[3] == "SECTIONS") //Debug
  4310. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4311. }
  4312. //This is the startTag handler we use where we are reading the optional format data zone (todo="FORMATDATA")
  4313. function startElementFormatData($parser, $tagName, $attrs) {
  4314. //Refresh properties
  4315. $this->level++;
  4316. $this->tree[$this->level] = $tagName;
  4317. //Output something to avoid browser timeouts...
  4318. //backup_flush();
  4319. //Accumulate all the data inside this tag
  4320. if (isset($this->tree[3]) && $this->tree[3] == "FORMATDATA") {
  4321. if (!isset($this->temp)) {
  4322. $this->temp = '';
  4323. }
  4324. $this->temp .= "<".$tagName.">";
  4325. }
  4326. //Check if we are into FORMATDATA zone
  4327. //if ($this->tree[3] == "FORMATDATA") //Debug
  4328. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4329. }
  4330. //This is the startTag handler we use where we are reading the metacourse zone (todo="METACOURSE")
  4331. function startElementMetacourse($parser, $tagName, $attrs) {
  4332. //Refresh properties
  4333. $this->level++;
  4334. $this->tree[$this->level] = $tagName;
  4335. //Output something to avoid browser timeouts...
  4336. //backup_flush();
  4337. //Check if we are into METACOURSE zone
  4338. //if ($this->tree[3] == "METACOURSE") //Debug
  4339. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4340. }
  4341. //This is the startTag handler we use where we are reading the gradebook zone (todo="GRADEBOOK")
  4342. function startElementGradebook($parser, $tagName, $attrs) {
  4343. //Refresh properties
  4344. $this->level++;
  4345. $this->tree[$this->level] = $tagName;
  4346. //Output something to avoid browser timeouts...
  4347. //backup_flush();
  4348. //Check if we are into GRADEBOOK zone
  4349. //if ($this->tree[3] == "GRADEBOOK") //Debug
  4350. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4351. //If we are under a GRADE_PREFERENCE, GRADE_LETTER or GRADE_CATEGORY tag under a GRADEBOOK zone, accumule it
  4352. if (isset($this->tree[5]) and isset($this->tree[3])) {
  4353. 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")) {
  4354. if (!isset($this->temp)) {
  4355. $this->temp = "";
  4356. }
  4357. $this->temp .= "<".$tagName.">";
  4358. }
  4359. }
  4360. }
  4361. //This is the startTag handler we use where we are reading the gradebook zone (todo="GRADEBOOK")
  4362. function startElementOldGradebook($parser, $tagName, $attrs) {
  4363. //Refresh properties
  4364. $this->level++;
  4365. $this->tree[$this->level] = $tagName;
  4366. //Output something to avoid browser timeouts...
  4367. //backup_flush();
  4368. //Check if we are into GRADEBOOK zone
  4369. //if ($this->tree[3] == "GRADEBOOK") //Debug
  4370. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4371. //If we are under a GRADE_PREFERENCE, GRADE_LETTER or GRADE_CATEGORY tag under a GRADEBOOK zone, accumule it
  4372. if (isset($this->tree[5]) and isset($this->tree[3])) {
  4373. if (($this->tree[5] == "GRADE_PREFERENCE" || $this->tree[5] == "GRADE_LETTER" || $this->tree[5] == "GRADE_CATEGORY" ) && ($this->tree[3] == "GRADEBOOK")) {
  4374. if (!isset($this->temp)) {
  4375. $this->temp = "";
  4376. }
  4377. $this->temp .= "<".$tagName.">";
  4378. }
  4379. }
  4380. }
  4381. //This is the startTag handler we use where we are reading the user zone (todo="USERS")
  4382. function startElementUsers($parser, $tagName, $attrs) {
  4383. //Refresh properties
  4384. $this->level++;
  4385. $this->tree[$this->level] = $tagName;
  4386. //Check if we are into USERS zone
  4387. //if ($this->tree[3] == "USERS") //Debug
  4388. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4389. }
  4390. //This is the startTag handler we use where we are reading the messages zone (todo="MESSAGES")
  4391. function startElementMessages($parser, $tagName, $attrs) {
  4392. //Refresh properties
  4393. $this->level++;
  4394. $this->tree[$this->level] = $tagName;
  4395. //Output something to avoid browser timeouts...
  4396. //backup_flush();
  4397. //Check if we are into MESSAGES zone
  4398. //if ($this->tree[3] == "MESSAGES") //Debug
  4399. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4400. //If we are under a MESSAGE tag under a MESSAGES zone, accumule it
  4401. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4402. if (($this->tree[4] == "MESSAGE" || (isset($this->tree[5]) && $this->tree[5] == "CONTACT" )) and ($this->tree[3] == "MESSAGES")) {
  4403. if (!isset($this->temp)) {
  4404. $this->temp = "";
  4405. }
  4406. $this->temp .= "<".$tagName.">";
  4407. }
  4408. }
  4409. }
  4410. //This is the startTag handler we use where we are reading the blogs zone (todo="BLOGS")
  4411. function startElementBlogs($parser, $tagName, $attrs) {
  4412. //Refresh properties
  4413. $this->level++;
  4414. $this->tree[$this->level] = $tagName;
  4415. //Output something to avoid browser timeouts...
  4416. //backup_flush();
  4417. //Check if we are into BLOGS zone
  4418. //if ($this->tree[3] == "BLOGS") //Debug
  4419. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4420. //If we are under a BLOG tag under a BLOGS zone, accumule it
  4421. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4422. if ($this->tree[4] == "BLOG" and $this->tree[3] == "BLOGS") {
  4423. if (!isset($this->temp)) {
  4424. $this->temp = "";
  4425. }
  4426. $this->temp .= "<".$tagName.">";
  4427. }
  4428. }
  4429. }
  4430. //This is the startTag handler we use where we are reading the questions zone (todo="QUESTIONS")
  4431. function startElementQuestions($parser, $tagName, $attrs) {
  4432. //Refresh properties
  4433. $this->level++;
  4434. $this->tree[$this->level] = $tagName;
  4435. //if ($tagName == "QUESTION_CATEGORY" && $this->tree[3] == "QUESTION_CATEGORIES") { //Debug
  4436. // echo "<P>QUESTION_CATEGORY: ".strftime ("%X",time()),"-"; //Debug
  4437. //} //Debug
  4438. //Output something to avoid browser timeouts...
  4439. //backup_flush();
  4440. //Check if we are into QUESTION_CATEGORIES zone
  4441. //if ($this->tree[3] == "QUESTION_CATEGORIES") //Debug
  4442. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4443. //If we are under a QUESTION_CATEGORY tag under a QUESTION_CATEGORIES zone, accumule it
  4444. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4445. if (($this->tree[4] == "QUESTION_CATEGORY") and ($this->tree[3] == "QUESTION_CATEGORIES")) {
  4446. if (!isset($this->temp)) {
  4447. $this->temp = "";
  4448. }
  4449. $this->temp .= "<".$tagName.">";
  4450. }
  4451. }
  4452. }
  4453. //This is the startTag handler we use where we are reading the scales zone (todo="SCALES")
  4454. function startElementScales($parser, $tagName, $attrs) {
  4455. //Refresh properties
  4456. $this->level++;
  4457. $this->tree[$this->level] = $tagName;
  4458. //if ($tagName == "SCALE" && $this->tree[3] == "SCALES") { //Debug
  4459. // echo "<P>SCALE: ".strftime ("%X",time()),"-"; //Debug
  4460. //} //Debug
  4461. //Output something to avoid browser timeouts...
  4462. //backup_flush();
  4463. //Check if we are into SCALES zone
  4464. //if ($this->tree[3] == "SCALES") //Debug
  4465. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4466. //If we are under a SCALE tag under a SCALES zone, accumule it
  4467. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4468. if (($this->tree[4] == "SCALE") and ($this->tree[3] == "SCALES")) {
  4469. if (!isset($this->temp)) {
  4470. $this->temp = "";
  4471. }
  4472. $this->temp .= "<".$tagName.">";
  4473. }
  4474. }
  4475. }
  4476. function startElementGroups($parser, $tagName, $attrs) {
  4477. //Refresh properties
  4478. $this->level++;
  4479. $this->tree[$this->level] = $tagName;
  4480. //if ($tagName == "GROUP" && $this->tree[3] == "GROUPS") { //Debug
  4481. // echo "<P>GROUP: ".strftime ("%X",time()),"-"; //Debug
  4482. //} //Debug
  4483. //Output something to avoid browser timeouts...
  4484. //backup_flush();
  4485. //Check if we are into GROUPS zone
  4486. //if ($this->tree[3] == "GROUPS") //Debug
  4487. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4488. //If we are under a GROUP tag under a GROUPS zone, accumule it
  4489. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4490. if (($this->tree[4] == "GROUP") and ($this->tree[3] == "GROUPS")) {
  4491. if (!isset($this->temp)) {
  4492. $this->temp = "";
  4493. }
  4494. $this->temp .= "<".$tagName.">";
  4495. }
  4496. }
  4497. }
  4498. function startElementGroupings($parser, $tagName, $attrs) {
  4499. //Refresh properties
  4500. $this->level++;
  4501. $this->tree[$this->level] = $tagName;
  4502. //if ($tagName == "GROUPING" && $this->tree[3] == "GROUPINGS") { //Debug
  4503. // echo "<P>GROUPING: ".strftime ("%X",time()),"-"; //Debug
  4504. //} //Debug
  4505. //Output something to avoid browser timeouts...
  4506. //backup_flush();
  4507. //Check if we are into GROUPINGS zone
  4508. //if ($this->tree[3] == "GROUPINGS") //Debug
  4509. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4510. //If we are under a GROUPING tag under a GROUPINGS zone, accumule it
  4511. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4512. if (($this->tree[4] == "GROUPING") and ($this->tree[3] == "GROUPINGS")) {
  4513. if (!isset($this->temp)) {
  4514. $this->temp = "";
  4515. }
  4516. $this->temp .= "<".$tagName.">";
  4517. }
  4518. }
  4519. }
  4520. function startElementGroupingsGroups($parser, $tagName, $attrs) {
  4521. //Refresh properties
  4522. $this->level++;
  4523. $this->tree[$this->level] = $tagName;
  4524. //if ($tagName == "GROUPINGGROUP" && $this->tree[3] == "GROUPINGSGROUPS") { //Debug
  4525. // echo "<P>GROUPINGSGROUP: ".strftime ("%X",time()),"-"; //Debug
  4526. //} //Debug
  4527. //Output something to avoid browser timeouts...
  4528. backup_flush();
  4529. //Check if we are into GROUPINGSGROUPS zone
  4530. //if ($this->tree[3] == "GROUPINGSGROUPS") //Debug
  4531. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4532. //If we are under a GROUPINGGROUP tag under a GROUPINGSGROUPS zone, accumule it
  4533. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4534. if (($this->tree[4] == "GROUPINGGROUP") and ($this->tree[3] == "GROUPINGSGROUPS")) {
  4535. if (!isset($this->temp)) {
  4536. $this->temp = "";
  4537. }
  4538. $this->temp .= "<".$tagName.">";
  4539. }
  4540. }
  4541. }
  4542. //This is the startTag handler we use where we are reading the events zone (todo="EVENTS")
  4543. function startElementEvents($parser, $tagName, $attrs) {
  4544. //Refresh properties
  4545. $this->level++;
  4546. $this->tree[$this->level] = $tagName;
  4547. //if ($tagName == "EVENT" && $this->tree[3] == "EVENTS") { //Debug
  4548. // echo "<P>EVENT: ".strftime ("%X",time()),"-"; //Debug
  4549. //} //Debug
  4550. //Output something to avoid browser timeouts...
  4551. //backup_flush();
  4552. //Check if we are into EVENTS zone
  4553. //if ($this->tree[3] == "EVENTS") //Debug
  4554. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4555. //If we are under a EVENT tag under a EVENTS zone, accumule it
  4556. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4557. if (($this->tree[4] == "EVENT") and ($this->tree[3] == "EVENTS")) {
  4558. if (!isset($this->temp)) {
  4559. $this->temp = "";
  4560. }
  4561. $this->temp .= "<".$tagName.">";
  4562. }
  4563. }
  4564. }
  4565. //This is the startTag handler we use where we are reading the modules zone (todo="MODULES")
  4566. function startElementModules($parser, $tagName, $attrs) {
  4567. //Refresh properties
  4568. $this->level++;
  4569. $this->tree[$this->level] = $tagName;
  4570. //if ($tagName == "MOD" && $this->tree[3] == "MODULES") { //Debug
  4571. // echo "<P>MOD: ".strftime ("%X",time()),"-"; //Debug
  4572. //} //Debug
  4573. //Output something to avoid browser timeouts...
  4574. //backup_flush();
  4575. //Check if we are into MODULES zone
  4576. //if ($this->tree[3] == "MODULES") //Debug
  4577. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4578. //If we are under a MOD tag under a MODULES zone, accumule it
  4579. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4580. if (($this->tree[4] == "MOD") and ($this->tree[3] == "MODULES")) {
  4581. if (!isset($this->temp)) {
  4582. $this->temp = "";
  4583. }
  4584. $this->temp .= "<".$tagName.">";
  4585. }
  4586. }
  4587. }
  4588. //This is the startTag handler we use where we are reading the logs zone (todo="LOGS")
  4589. function startElementLogs($parser, $tagName, $attrs) {
  4590. //Refresh properties
  4591. $this->level++;
  4592. $this->tree[$this->level] = $tagName;
  4593. //if ($tagName == "LOG" && $this->tree[3] == "LOGS") { //Debug
  4594. // echo "<P>LOG: ".strftime ("%X",time()),"-"; //Debug
  4595. //} //Debug
  4596. //Output something to avoid browser timeouts...
  4597. //backup_flush();
  4598. //Check if we are into LOGS zone
  4599. //if ($this->tree[3] == "LOGS") //Debug
  4600. // echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4601. //If we are under a LOG tag under a LOGS zone, accumule it
  4602. if (isset($this->tree[4]) and isset($this->tree[3])) {
  4603. if (($this->tree[4] == "LOG") and ($this->tree[3] == "LOGS")) {
  4604. if (!isset($this->temp)) {
  4605. $this->temp = "";
  4606. }
  4607. $this->temp .= "<".$tagName.">";
  4608. }
  4609. }
  4610. }
  4611. //This is the startTag default handler we use when todo is undefined
  4612. function startElement($parser, $tagName, $attrs) {
  4613. $this->level++;
  4614. $this->tree[$this->level] = $tagName;
  4615. //Output something to avoid browser timeouts...
  4616. //backup_flush();
  4617. echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;".$tagName."&gt;<br />\n"; //Debug
  4618. }
  4619. //This is the endTag handler we use where we are reading the info zone (todo="INFO")
  4620. function endElementInfo($parser, $tagName) {
  4621. //Check if we are into INFO zone
  4622. if ($this->tree[2] == "INFO") {
  4623. //if (trim($this->content)) //Debug
  4624. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  4625. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  4626. //Dependig of different combinations, do different things
  4627. if ($this->level == 3) {
  4628. switch ($tagName) {
  4629. case "NAME":
  4630. $this->info->backup_name = $this->getContents();
  4631. break;
  4632. case "MOODLE_VERSION":
  4633. $this->info->backup_moodle_version = $this->getContents();
  4634. break;
  4635. case "MOODLE_RELEASE":
  4636. $this->info->backup_moodle_release = $this->getContents();
  4637. break;
  4638. case "BACKUP_VERSION":
  4639. $this->info->backup_backup_version = $this->getContents();
  4640. break;
  4641. case "BACKUP_RELEASE":
  4642. $this->info->backup_backup_release = $this->getContents();
  4643. break;
  4644. case "DATE":
  4645. $this->info->backup_date = $this->getContents();
  4646. break;
  4647. case "ORIGINAL_WWWROOT":
  4648. $this->info->original_wwwroot = $this->getContents();
  4649. break;
  4650. case "ORIGINAL_SITE_IDENTIFIER_HASH":
  4651. $this->info->original_siteidentifier = $this->getContents();
  4652. break;
  4653. case "MNET_REMOTEUSERS":
  4654. $this->info->mnet_remoteusers = $this->getContents();
  4655. break;
  4656. }
  4657. }
  4658. if ($this->tree[3] == "DETAILS") {
  4659. if ($this->level == 4) {
  4660. switch ($tagName) {
  4661. case "METACOURSE":
  4662. $this->info->backup_metacourse = $this->getContents();
  4663. break;
  4664. case "USERS":
  4665. $this->info->backup_users = $this->getContents();
  4666. break;
  4667. case "LOGS":
  4668. $this->info->backup_logs = $this->getContents();
  4669. break;
  4670. case "USERFILES":
  4671. $this->info->backup_user_files = $this->getContents();
  4672. break;
  4673. case "COURSEFILES":
  4674. $this->info->backup_course_files = $this->getContents();
  4675. break;
  4676. case "SITEFILES":
  4677. $this->info->backup_site_files = $this->getContents();
  4678. break;
  4679. case "GRADEBOOKHISTORIES":
  4680. $this->info->gradebook_histories = $this->getContents();
  4681. break;
  4682. case "MESSAGES":
  4683. $this->info->backup_messages = $this->getContents();
  4684. break;
  4685. case "BLOGS":
  4686. $this->info->backup_blogs = $this->getContents();
  4687. break;
  4688. case 'BLOCKFORMAT':
  4689. $this->info->backup_block_format = $this->getContents();
  4690. break;
  4691. }
  4692. }
  4693. if ($this->level == 5) {
  4694. switch ($tagName) {
  4695. case "NAME":
  4696. $this->info->tempName = $this->getContents();
  4697. break;
  4698. case "INCLUDED":
  4699. $this->info->mods[$this->info->tempName]->backup = $this->getContents();
  4700. break;
  4701. case "USERINFO":
  4702. $this->info->mods[$this->info->tempName]->userinfo = $this->getContents();
  4703. break;
  4704. }
  4705. }
  4706. if ($this->level == 7) {
  4707. switch ($tagName) {
  4708. case "ID":
  4709. $this->info->tempId = $this->getContents();
  4710. $this->info->mods[$this->info->tempName]->instances[$this->info->tempId]->id = $this->info->tempId;
  4711. break;
  4712. case "NAME":
  4713. $this->info->mods[$this->info->tempName]->instances[$this->info->tempId]->name = $this->getContents();
  4714. break;
  4715. case "INCLUDED":
  4716. $this->info->mods[$this->info->tempName]->instances[$this->info->tempId]->backup = $this->getContents();
  4717. break;
  4718. case "USERINFO":
  4719. $this->info->mods[$this->info->tempName]->instances[$this->info->tempId]->userinfo = $this->getContents();
  4720. break;
  4721. }
  4722. }
  4723. }
  4724. }
  4725. //Stop parsing if todo = INFO and tagName = INFO (en of the tag, of course)
  4726. //Speed up a lot (avoid parse all)
  4727. if ($tagName == "INFO") {
  4728. $this->finished = true;
  4729. }
  4730. //Clear things
  4731. $this->tree[$this->level] = "";
  4732. $this->level--;
  4733. $this->content = "";
  4734. }
  4735. function endElementRoles($parser, $tagName) {
  4736. //Check if we are into ROLES zone
  4737. if ($this->tree[2] == "ROLES") {
  4738. if ($this->tree[3] == "ROLE") {
  4739. if ($this->level == 4) {
  4740. switch ($tagName) {
  4741. case "ID": // this is the old id
  4742. $this->info->tempid = $this->getContents();
  4743. $this->info->roles[$this->info->tempid]->id = $this->info->tempid;
  4744. break;
  4745. case "NAME":
  4746. $this->info->roles[$this->info->tempid]->name = $this->getContents();;
  4747. break;
  4748. case "SHORTNAME":
  4749. $this->info->roles[$this->info->tempid]->shortname = $this->getContents();;
  4750. break;
  4751. case "NAMEINCOURSE": // custom name of the role in course
  4752. $this->info->roles[$this->info->tempid]->nameincourse = $this->getContents();;
  4753. break;
  4754. }
  4755. }
  4756. if ($this->level == 6) {
  4757. switch ($tagName) {
  4758. case "NAME":
  4759. $this->info->tempcapname = $this->getContents();
  4760. $this->info->roles[$this->info->tempid]->capabilities[$this->info->tempcapname]->name = $this->getContents();
  4761. break;
  4762. case "PERMISSION":
  4763. $this->info->roles[$this->info->tempid]->capabilities[$this->info->tempcapname]->permission = $this->getContents();
  4764. break;
  4765. case "TIMEMODIFIED":
  4766. $this->info->roles[$this->info->tempid]->capabilities[$this->info->tempcapname]->timemodified = $this->getContents();
  4767. break;
  4768. case "MODIFIERID":
  4769. $this->info->roles[$this->info->tempid]->capabilities[$this->info->tempcapname]->modifierid = $this->getContents();
  4770. break;
  4771. }
  4772. }
  4773. }
  4774. }
  4775. //Stop parsing if todo = ROLES and tagName = ROLES (en of the tag, of course)
  4776. //Speed up a lot (avoid parse all)
  4777. if ($tagName == "ROLES") {
  4778. $this->finished = true;
  4779. }
  4780. //Clear things
  4781. $this->tree[$this->level] = "";
  4782. $this->level--;
  4783. $this->content = "";
  4784. }
  4785. //This is the endTag handler we use where we are reading the course_header zone (todo="COURSE_HEADER")
  4786. function endElementCourseHeader($parser, $tagName) {
  4787. //Check if we are into COURSE_HEADER zone
  4788. if ($this->tree[3] == "HEADER") {
  4789. //if (trim($this->content)) //Debug
  4790. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  4791. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  4792. //Dependig of different combinations, do different things
  4793. if ($this->level == 4) {
  4794. switch ($tagName) {
  4795. case "ID":
  4796. $this->info->course_id = $this->getContents();
  4797. break;
  4798. case "PASSWORD":
  4799. $this->info->course_password = $this->getContents();
  4800. break;
  4801. case "FULLNAME":
  4802. $this->info->course_fullname = $this->getContents();
  4803. break;
  4804. case "SHORTNAME":
  4805. $this->info->course_shortname = $this->getContents();
  4806. break;
  4807. case "IDNUMBER":
  4808. $this->info->course_idnumber = $this->getContents();
  4809. break;
  4810. case "SUMMARY":
  4811. $this->info->course_summary = $this->getContents();
  4812. break;
  4813. case "FORMAT":
  4814. $this->info->course_format = $this->getContents();
  4815. break;
  4816. case "SHOWGRADES":
  4817. $this->info->course_showgrades = $this->getContents();
  4818. break;
  4819. case "BLOCKINFO":
  4820. $this->info->blockinfo = $this->getContents();
  4821. break;
  4822. case "NEWSITEMS":
  4823. $this->info->course_newsitems = $this->getContents();
  4824. break;
  4825. case "TEACHER":
  4826. $this->info->course_teacher = $this->getContents();
  4827. break;
  4828. case "TEACHERS":
  4829. $this->info->course_teachers = $this->getContents();
  4830. break;
  4831. case "STUDENT":
  4832. $this->info->course_student = $this->getContents();
  4833. break;
  4834. case "STUDENTS":
  4835. $this->info->course_students = $this->getContents();
  4836. break;
  4837. case "GUEST":
  4838. $this->info->course_guest = $this->getContents();
  4839. break;
  4840. case "STARTDATE":
  4841. $this->info->course_startdate = $this->getContents();
  4842. break;
  4843. case "NUMSECTIONS":
  4844. $this->info->course_numsections = $this->getContents();
  4845. break;
  4846. //case "SHOWRECENT": INFO: This is out in 1.3
  4847. // $this->info->course_showrecent = $this->getContents();
  4848. // break;
  4849. case "MAXBYTES":
  4850. $this->info->course_maxbytes = $this->getContents();
  4851. break;
  4852. case "SHOWREPORTS":
  4853. $this->info->course_showreports = $this->getContents();
  4854. break;
  4855. case "GROUPMODE":
  4856. $this->info->course_groupmode = $this->getContents();
  4857. break;
  4858. case "GROUPMODEFORCE":
  4859. $this->info->course_groupmodeforce = $this->getContents();
  4860. break;
  4861. case "DEFAULTGROUPINGID":
  4862. $this->info->course_defaultgroupingid = $this->getContents();
  4863. break;
  4864. case "LANG":
  4865. $this->info->course_lang = $this->getContents();
  4866. break;
  4867. case "THEME":
  4868. $this->info->course_theme = $this->getContents();
  4869. break;
  4870. case "COST":
  4871. $this->info->course_cost = $this->getContents();
  4872. break;
  4873. case "CURRENCY":
  4874. $this->info->course_currency = $this->getContents();
  4875. break;
  4876. case "MARKER":
  4877. $this->info->course_marker = $this->getContents();
  4878. break;
  4879. case "VISIBLE":
  4880. $this->info->course_visible = $this->getContents();
  4881. break;
  4882. case "HIDDENSECTIONS":
  4883. $this->info->course_hiddensections = $this->getContents();
  4884. break;
  4885. case "TIMECREATED":
  4886. $this->info->course_timecreated = $this->getContents();
  4887. break;
  4888. case "TIMEMODIFIED":
  4889. $this->info->course_timemodified = $this->getContents();
  4890. break;
  4891. case "METACOURSE":
  4892. $this->info->course_metacourse = $this->getContents();
  4893. break;
  4894. case "EXPIRENOTIFY":
  4895. $this->info->course_expirynotify = $this->getContents();
  4896. break;
  4897. case "NOTIFYSTUDENTS":
  4898. $this->info->course_notifystudents = $this->getContents();
  4899. break;
  4900. case "EXPIRYTHRESHOLD":
  4901. $this->info->course_expirythreshold = $this->getContents();
  4902. break;
  4903. case "ENROLLABLE":
  4904. $this->info->course_enrollable = $this->getContents();
  4905. break;
  4906. case "ENROLSTARTDATE":
  4907. $this->info->course_enrolstartdate = $this->getContents();
  4908. break;
  4909. case "ENROLENDDATE":
  4910. $this->info->course_enrolenddate = $this->getContents();
  4911. break;
  4912. case "ENROLPERIOD":
  4913. $this->info->course_enrolperiod = $this->getContents();
  4914. break;
  4915. }
  4916. }
  4917. if ($this->tree[4] == "CATEGORY") {
  4918. if ($this->level == 5) {
  4919. switch ($tagName) {
  4920. case "ID":
  4921. $this->info->category->id = $this->getContents();
  4922. break;
  4923. case "NAME":
  4924. $this->info->category->name = $this->getContents();
  4925. break;
  4926. }
  4927. }
  4928. }
  4929. if ($this->tree[4] == "ROLES_ASSIGNMENTS") {
  4930. if ($this->level == 6) {
  4931. switch ($tagName) {
  4932. case "NAME":
  4933. $this->info->tempname = $this->getContents();
  4934. break;
  4935. case "SHORTNAME":
  4936. $this->info->tempshortname = $this->getContents();
  4937. break;
  4938. case "ID":
  4939. $this->info->tempid = $this->getContents();
  4940. break;
  4941. }
  4942. }
  4943. if ($this->level == 8) {
  4944. switch ($tagName) {
  4945. case "USERID":
  4946. $this->info->roleassignments[$this->info->tempid]->name = $this->info->tempname;
  4947. $this->info->roleassignments[$this->info->tempid]->shortname = $this->info->tempshortname;
  4948. $this->info->tempuser = $this->getContents();
  4949. $this->info->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->userid = $this->getContents();
  4950. break;
  4951. case "HIDDEN":
  4952. $this->info->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->hidden = $this->getContents();
  4953. break;
  4954. case "TIMESTART":
  4955. $this->info->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timestart = $this->getContents();
  4956. break;
  4957. case "TIMEEND":
  4958. $this->info->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timeend = $this->getContents();
  4959. break;
  4960. case "TIMEMODIFIED":
  4961. $this->info->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timemodified = $this->getContents();
  4962. break;
  4963. case "MODIFIERID":
  4964. $this->info->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->modifierid = $this->getContents();
  4965. break;
  4966. case "ENROL":
  4967. $this->info->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->enrol = $this->getContents();
  4968. break;
  4969. case "SORTORDER":
  4970. $this->info->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->sortorder = $this->getContents();
  4971. break;
  4972. }
  4973. }
  4974. } /// ends role_assignments
  4975. if ($this->tree[4] == "ROLES_OVERRIDES") {
  4976. if ($this->level == 6) {
  4977. switch ($tagName) {
  4978. case "NAME":
  4979. $this->info->tempname = $this->getContents();
  4980. break;
  4981. case "SHORTNAME":
  4982. $this->info->tempshortname = $this->getContents();
  4983. break;
  4984. case "ID":
  4985. $this->info->tempid = $this->getContents();
  4986. break;
  4987. }
  4988. }
  4989. if ($this->level == 8) {
  4990. switch ($tagName) {
  4991. case "NAME":
  4992. $this->info->roleoverrides[$this->info->tempid]->name = $this->info->tempname;
  4993. $this->info->roleoverrides[$this->info->tempid]->shortname = $this->info->tempshortname;
  4994. $this->info->tempname = $this->getContents(); // change to name of capability
  4995. $this->info->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->name = $this->getContents();
  4996. break;
  4997. case "PERMISSION":
  4998. $this->info->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->permission = $this->getContents();
  4999. break;
  5000. case "TIMEMODIFIED":
  5001. $this->info->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->timemodified = $this->getContents();
  5002. break;
  5003. case "MODIFIERID":
  5004. $this->info->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->modifierid = $this->getContents();
  5005. break;
  5006. }
  5007. }
  5008. } /// ends role_overrides
  5009. }
  5010. //Stop parsing if todo = COURSE_HEADER and tagName = HEADER (en of the tag, of course)
  5011. //Speed up a lot (avoid parse all)
  5012. if ($tagName == "HEADER") {
  5013. $this->finished = true;
  5014. }
  5015. //Clear things
  5016. $this->tree[$this->level] = "";
  5017. $this->level--;
  5018. $this->content = "";
  5019. }
  5020. //This is the endTag handler we use where we are reading the sections zone (todo="BLOCKS")
  5021. function endElementBlocks($parser, $tagName) {
  5022. //Check if we are into BLOCKS zone
  5023. if ($this->tree[3] == 'BLOCKS') {
  5024. //if (trim($this->content)) //Debug
  5025. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  5026. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  5027. // Collect everything into $this->temp
  5028. if (!isset($this->temp)) {
  5029. $this->temp = "";
  5030. }
  5031. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  5032. //Dependig of different combinations, do different things
  5033. if ($this->level == 4) {
  5034. switch ($tagName) {
  5035. case 'BLOCK':
  5036. //We've finalized a block, get it
  5037. $this->info->instances[] = $this->info->tempinstance;
  5038. unset($this->info->tempinstance);
  5039. //Also, xmlize INSTANCEDATA and save to db
  5040. //Prepend XML standard header to info gathered
  5041. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5042. //Call to xmlize for this portion of xml data (one BLOCK)
  5043. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5044. $data = xmlize($xml_data,0);
  5045. //echo strftime ("%X",time())."<p>"; //Debug
  5046. //traverse_xmlize($data); //Debug
  5047. //print_object ($GLOBALS['traverse_array']); //Debug
  5048. //$GLOBALS['traverse_array']=""; //Debug
  5049. //Check for instancedata, is exists, then save to DB
  5050. if (isset($data['BLOCK']['#']['INSTANCEDATA']['0']['#'])) {
  5051. //Get old id
  5052. $oldid = $data['BLOCK']['#']['ID']['0']['#'];
  5053. //Get instancedata
  5054. if ($data = $data['BLOCK']['#']['INSTANCEDATA']['0']['#']) {
  5055. //Restore code calls this multiple times - so might already have the newid
  5056. if ($newid = backup_getid($this->preferences->backup_unique_code,'block_instance',$oldid)) {
  5057. $newid = $newid->new_id;
  5058. } else {
  5059. $newid = null;
  5060. }
  5061. //Save to DB, we will use it later
  5062. $status = backup_putid($this->preferences->backup_unique_code,'block_instance',$oldid,$newid,$data);
  5063. }
  5064. }
  5065. //Reset temp
  5066. unset($this->temp);
  5067. break;
  5068. default:
  5069. die($tagName);
  5070. }
  5071. }
  5072. if ($this->level == 5) {
  5073. switch ($tagName) {
  5074. case 'ID':
  5075. $this->info->tempinstance->id = $this->getContents();
  5076. case 'NAME':
  5077. $this->info->tempinstance->name = $this->getContents();
  5078. break;
  5079. case 'PAGEID':
  5080. $this->info->tempinstance->pageid = $this->getContents();
  5081. break;
  5082. case 'PAGETYPE':
  5083. $this->info->tempinstance->pagetype = $this->getContents();
  5084. break;
  5085. case 'POSITION':
  5086. $this->info->tempinstance->position = $this->getContents();
  5087. break;
  5088. case 'WEIGHT':
  5089. $this->info->tempinstance->weight = $this->getContents();
  5090. break;
  5091. case 'VISIBLE':
  5092. $this->info->tempinstance->visible = $this->getContents();
  5093. break;
  5094. case 'CONFIGDATA':
  5095. $this->info->tempinstance->configdata = $this->getContents();
  5096. break;
  5097. default:
  5098. break;
  5099. }
  5100. }
  5101. if ($this->tree[5] == "ROLES_ASSIGNMENTS") {
  5102. if ($this->level == 7) {
  5103. switch ($tagName) {
  5104. case "NAME":
  5105. $this->info->tempname = $this->getContents();
  5106. break;
  5107. case "SHORTNAME":
  5108. $this->info->tempshortname = $this->getContents();
  5109. break;
  5110. case "ID":
  5111. $this->info->tempid = $this->getContents(); // temp roleid
  5112. break;
  5113. }
  5114. }
  5115. if ($this->level == 9) {
  5116. switch ($tagName) {
  5117. case "USERID":
  5118. $this->info->tempinstance->roleassignments[$this->info->tempid]->name = $this->info->tempname;
  5119. $this->info->tempinstance->roleassignments[$this->info->tempid]->shortname = $this->info->tempshortname;
  5120. $this->info->tempuser = $this->getContents();
  5121. $this->info->tempinstance->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->userid = $this->getContents();
  5122. break;
  5123. case "HIDDEN":
  5124. $this->info->tempinstance->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->hidden = $this->getContents();
  5125. break;
  5126. case "TIMESTART":
  5127. $this->info->tempinstance->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timestart = $this->getContents();
  5128. break;
  5129. case "TIMEEND":
  5130. $this->info->tempinstance->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timeend = $this->getContents();
  5131. break;
  5132. case "TIMEMODIFIED":
  5133. $this->info->tempinstance->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timemodified = $this->getContents();
  5134. break;
  5135. case "MODIFIERID":
  5136. $this->info->tempinstance->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->modifierid = $this->getContents();
  5137. break;
  5138. case "ENROL":
  5139. $this->info->tempinstance->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->enrol = $this->getContents();
  5140. break;
  5141. case "SORTORDER":
  5142. $this->info->tempinstance->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->sortorder = $this->getContents();
  5143. break;
  5144. }
  5145. }
  5146. } /// ends role_assignments
  5147. if ($this->tree[5] == "ROLES_OVERRIDES") {
  5148. if ($this->level == 7) {
  5149. switch ($tagName) {
  5150. case "NAME":
  5151. $this->info->tempname = $this->getContents();
  5152. break;
  5153. case "SHORTNAME":
  5154. $this->info->tempshortname = $this->getContents();
  5155. break;
  5156. case "ID":
  5157. $this->info->tempid = $this->getContents(); // temp roleid
  5158. break;
  5159. }
  5160. }
  5161. if ($this->level == 9) {
  5162. switch ($tagName) {
  5163. case "NAME":
  5164. $this->info->tempinstance->roleoverrides[$this->info->tempid]->name = $this->info->tempname;
  5165. $this->info->tempinstance->roleoverrides[$this->info->tempid]->shortname = $this->info->tempshortname;
  5166. $this->info->tempname = $this->getContents(); // change to name of capability
  5167. $this->info->tempinstance->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->name = $this->getContents();
  5168. break;
  5169. case "PERMISSION":
  5170. $this->info->tempinstance->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->permission = $this->getContents();
  5171. break;
  5172. case "TIMEMODIFIED":
  5173. $this->info->tempinstance->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->timemodified = $this->getContents();
  5174. break;
  5175. case "MODIFIERID":
  5176. $this->info->tempinstance->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->modifierid = $this->getContents();
  5177. break;
  5178. }
  5179. }
  5180. } /// ends role_overrides
  5181. }
  5182. //Stop parsing if todo = BLOCKS and tagName = BLOCKS (en of the tag, of course)
  5183. //Speed up a lot (avoid parse all)
  5184. //WARNING: ONLY EXIT IF todo = BLOCKS (thus tree[3] = "BLOCKS") OTHERWISE
  5185. // THE BLOCKS TAG IN THE HEADER WILL TERMINATE US!
  5186. if ($this->tree[3] == 'BLOCKS' && $tagName == 'BLOCKS') {
  5187. $this->finished = true;
  5188. }
  5189. //Clear things
  5190. $this->tree[$this->level] = '';
  5191. $this->level--;
  5192. $this->content = "";
  5193. }
  5194. //This is the endTag handler we use where we are reading the sections zone (todo="SECTIONS")
  5195. function endElementSections($parser, $tagName) {
  5196. //Check if we are into SECTIONS zone
  5197. if ($this->tree[3] == "SECTIONS") {
  5198. //if (trim($this->content)) //Debug
  5199. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  5200. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  5201. //Dependig of different combinations, do different things
  5202. if ($this->level == 4) {
  5203. switch ($tagName) {
  5204. case "SECTION":
  5205. //We've finalized a section, get it
  5206. $this->info->sections[$this->info->tempsection->id] = $this->info->tempsection;
  5207. unset($this->info->tempsection);
  5208. }
  5209. }
  5210. if ($this->level == 5) {
  5211. switch ($tagName) {
  5212. case "ID":
  5213. $this->info->tempsection->id = $this->getContents();
  5214. break;
  5215. case "NUMBER":
  5216. $this->info->tempsection->number = $this->getContents();
  5217. break;
  5218. case "SUMMARY":
  5219. $this->info->tempsection->summary = $this->getContents();
  5220. break;
  5221. case "VISIBLE":
  5222. $this->info->tempsection->visible = $this->getContents();
  5223. break;
  5224. }
  5225. }
  5226. if ($this->level == 6) {
  5227. switch ($tagName) {
  5228. case "MOD":
  5229. if (!isset($this->info->tempmod->groupmode)) {
  5230. $this->info->tempmod->groupmode = 0;
  5231. }
  5232. if (!isset($this->info->tempmod->groupingid)) {
  5233. $this->info->tempmod->groupingid = 0;
  5234. }
  5235. if (!isset($this->info->tempmod->groupmembersonly)) {
  5236. $this->info->tempmod->groupmembersonly = 0;
  5237. }
  5238. if (!isset($this->info->tempmod->idnumber)) {
  5239. $this->info->tempmod->idnumber = null;
  5240. }
  5241. //We've finalized a mod, get it
  5242. $this->info->tempsection->mods[$this->info->tempmod->id]->type =
  5243. $this->info->tempmod->type;
  5244. $this->info->tempsection->mods[$this->info->tempmod->id]->instance =
  5245. $this->info->tempmod->instance;
  5246. $this->info->tempsection->mods[$this->info->tempmod->id]->added =
  5247. $this->info->tempmod->added;
  5248. $this->info->tempsection->mods[$this->info->tempmod->id]->score =
  5249. $this->info->tempmod->score;
  5250. $this->info->tempsection->mods[$this->info->tempmod->id]->indent =
  5251. $this->info->tempmod->indent;
  5252. $this->info->tempsection->mods[$this->info->tempmod->id]->visible =
  5253. $this->info->tempmod->visible;
  5254. $this->info->tempsection->mods[$this->info->tempmod->id]->groupmode =
  5255. $this->info->tempmod->groupmode;
  5256. $this->info->tempsection->mods[$this->info->tempmod->id]->groupingid =
  5257. $this->info->tempmod->groupingid;
  5258. $this->info->tempsection->mods[$this->info->tempmod->id]->groupmembersonly =
  5259. $this->info->tempmod->groupmembersonly;
  5260. $this->info->tempsection->mods[$this->info->tempmod->id]->idnumber =
  5261. $this->info->tempmod->idnumber;
  5262. unset($this->info->tempmod);
  5263. }
  5264. }
  5265. if ($this->level == 7) {
  5266. switch ($tagName) {
  5267. case "ID":
  5268. $this->info->tempmod->id = $this->getContents();
  5269. break;
  5270. case "TYPE":
  5271. $this->info->tempmod->type = $this->getContents();
  5272. break;
  5273. case "INSTANCE":
  5274. $this->info->tempmod->instance = $this->getContents();
  5275. break;
  5276. case "ADDED":
  5277. $this->info->tempmod->added = $this->getContents();
  5278. break;
  5279. case "SCORE":
  5280. $this->info->tempmod->score = $this->getContents();
  5281. break;
  5282. case "INDENT":
  5283. $this->info->tempmod->indent = $this->getContents();
  5284. break;
  5285. case "VISIBLE":
  5286. $this->info->tempmod->visible = $this->getContents();
  5287. break;
  5288. case "GROUPMODE":
  5289. $this->info->tempmod->groupmode = $this->getContents();
  5290. break;
  5291. case "GROUPINGID":
  5292. $this->info->tempmod->groupingid = $this->getContents();
  5293. break;
  5294. case "GROUPMEMBERSONLY":
  5295. $this->info->tempmod->groupmembersonly = $this->getContents();
  5296. break;
  5297. case "IDNUMBER":
  5298. $this->info->tempmod->idnumber = $this->getContents();
  5299. break;
  5300. default:
  5301. break;
  5302. }
  5303. }
  5304. if (isset($this->tree[7]) && $this->tree[7] == "ROLES_ASSIGNMENTS") {
  5305. if ($this->level == 9) {
  5306. switch ($tagName) {
  5307. case "NAME":
  5308. $this->info->tempname = $this->getContents();
  5309. break;
  5310. case "SHORTNAME":
  5311. $this->info->tempshortname = $this->getContents();
  5312. break;
  5313. case "ID":
  5314. $this->info->tempid = $this->getContents(); // temp roleid
  5315. break;
  5316. }
  5317. }
  5318. if ($this->level == 11) {
  5319. switch ($tagName) {
  5320. case "USERID":
  5321. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->name = $this->info->tempname;
  5322. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->shortname = $this->info->tempshortname;
  5323. $this->info->tempuser = $this->getContents();
  5324. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->userid = $this->getContents();
  5325. break;
  5326. case "HIDDEN":
  5327. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->hidden = $this->getContents();
  5328. break;
  5329. case "TIMESTART":
  5330. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timestart = $this->getContents();
  5331. break;
  5332. case "TIMEEND":
  5333. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timeend = $this->getContents();
  5334. break;
  5335. case "TIMEMODIFIED":
  5336. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->timemodified = $this->getContents();
  5337. break;
  5338. case "MODIFIERID":
  5339. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->modifierid = $this->getContents();
  5340. break;
  5341. case "ENROL":
  5342. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->enrol = $this->getContents();
  5343. break;
  5344. case "SORTORDER":
  5345. $this->info->tempsection->mods[$this->info->tempmod->id]->roleassignments[$this->info->tempid]->assignments[$this->info->tempuser]->sortorder = $this->getContents();
  5346. break;
  5347. }
  5348. }
  5349. } /// ends role_assignments
  5350. if (isset($this->tree[7]) && $this->tree[7] == "ROLES_OVERRIDES") {
  5351. if ($this->level == 9) {
  5352. switch ($tagName) {
  5353. case "NAME":
  5354. $this->info->tempname = $this->getContents();
  5355. break;
  5356. case "SHORTNAME":
  5357. $this->info->tempshortname = $this->getContents();
  5358. break;
  5359. case "ID":
  5360. $this->info->tempid = $this->getContents(); // temp roleid
  5361. break;
  5362. }
  5363. }
  5364. if ($this->level == 11) {
  5365. switch ($tagName) {
  5366. case "NAME":
  5367. $this->info->tempsection->mods[$this->info->tempmod->id]->roleoverrides[$this->info->tempid]->name = $this->info->tempname;
  5368. $this->info->tempsection->mods[$this->info->tempmod->id]->roleoverrides[$this->info->tempid]->shortname = $this->info->tempshortname;
  5369. $this->info->tempname = $this->getContents(); // change to name of capability
  5370. $this->info->tempsection->mods[$this->info->tempmod->id]->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->name = $this->getContents();
  5371. break;
  5372. case "PERMISSION":
  5373. $this->info->tempsection->mods[$this->info->tempmod->id]->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->permission = $this->getContents();
  5374. break;
  5375. case "TIMEMODIFIED":
  5376. $this->info->tempsection->mods[$this->info->tempmod->id]->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->timemodified = $this->getContents();
  5377. break;
  5378. case "MODIFIERID":
  5379. $this->info->tempsection->mods[$this->info->tempmod->id]->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->modifierid = $this->getContents();
  5380. break;
  5381. }
  5382. }
  5383. } /// ends role_overrides
  5384. }
  5385. //Stop parsing if todo = SECTIONS and tagName = SECTIONS (en of the tag, of course)
  5386. //Speed up a lot (avoid parse all)
  5387. if ($tagName == "SECTIONS") {
  5388. $this->finished = true;
  5389. }
  5390. //Clear things
  5391. $this->tree[$this->level] = "";
  5392. $this->level--;
  5393. $this->content = "";
  5394. }
  5395. //This is the endTag handler we use where we are reading the optional format data zone (todo="FORMATDATA")
  5396. function endElementFormatData($parser, $tagName) {
  5397. //Check if we are into FORMATDATA zone
  5398. if ($this->tree[3] == 'FORMATDATA') {
  5399. if (!isset($this->temp)) {
  5400. $this->temp = '';
  5401. }
  5402. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  5403. }
  5404. if($tagName=='FORMATDATA') {
  5405. //Did we have any data? If not don't bother
  5406. if($this->temp!='<FORMATDATA></FORMATDATA>') {
  5407. //Prepend XML standard header to info gathered
  5408. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5409. $this->temp='';
  5410. //Call to xmlize for this portion of xml data (the FORMATDATA block)
  5411. $this->info->format_data = xmlize($xml_data,0);
  5412. }
  5413. //Stop parsing at end of FORMATDATA
  5414. $this->finished=true;
  5415. }
  5416. //Clear things
  5417. $this->tree[$this->level] = "";
  5418. $this->level--;
  5419. $this->content = "";
  5420. }
  5421. //This is the endTag handler we use where we are reading the metacourse zone (todo="METACOURSE")
  5422. function endElementMetacourse($parser, $tagName) {
  5423. //Check if we are into METACOURSE zone
  5424. if ($this->tree[3] == 'METACOURSE') {
  5425. //if (trim($this->content)) //Debug
  5426. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  5427. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  5428. //Dependig of different combinations, do different things
  5429. if ($this->level == 5) {
  5430. switch ($tagName) {
  5431. case 'CHILD':
  5432. //We've finalized a child, get it
  5433. $this->info->childs[] = $this->info->tempmeta;
  5434. unset($this->info->tempmeta);
  5435. break;
  5436. case 'PARENT':
  5437. //We've finalized a parent, get it
  5438. $this->info->parents[] = $this->info->tempmeta;
  5439. unset($this->info->tempmeta);
  5440. break;
  5441. default:
  5442. die($tagName);
  5443. }
  5444. }
  5445. if ($this->level == 6) {
  5446. switch ($tagName) {
  5447. case 'ID':
  5448. $this->info->tempmeta->id = $this->getContents();
  5449. break;
  5450. case 'IDNUMBER':
  5451. $this->info->tempmeta->idnumber = $this->getContents();
  5452. break;
  5453. case 'SHORTNAME':
  5454. $this->info->tempmeta->shortname = $this->getContents();
  5455. break;
  5456. }
  5457. }
  5458. }
  5459. //Stop parsing if todo = METACOURSE and tagName = METACOURSE (en of the tag, of course)
  5460. //Speed up a lot (avoid parse all)
  5461. if ($this->tree[3] == 'METACOURSE' && $tagName == 'METACOURSE') {
  5462. $this->finished = true;
  5463. }
  5464. //Clear things
  5465. $this->tree[$this->level] = '';
  5466. $this->level--;
  5467. $this->content = "";
  5468. }
  5469. //This is the endTag handler we use where we are reading the gradebook zone (todo="GRADEBOOK")
  5470. function endElementGradebook($parser, $tagName) {
  5471. //Check if we are into GRADEBOOK zone
  5472. if ($this->tree[3] == "GRADEBOOK") {
  5473. //if (trim($this->content)) //Debug
  5474. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  5475. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n";//Debug
  5476. //Acumulate data to info (content + close tag)
  5477. //Reconvert: strip htmlchars again and trim to generate xml data
  5478. if (!isset($this->temp)) {
  5479. $this->temp = "";
  5480. }
  5481. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  5482. // We have finished outcome, grade_category or grade_item, reset accumulated
  5483. // data because they are close tags
  5484. if ($this->level == 4) {
  5485. $this->temp = "";
  5486. }
  5487. //If we've finished a grade item, xmlize it an save to db
  5488. if (($this->level == 5) and ($tagName == "GRADE_ITEM")) {
  5489. //Prepend XML standard header to info gathered
  5490. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5491. //Call to xmlize for this portion of xml data (one PREFERENCE)
  5492. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5493. $data = xmlize($xml_data,0);
  5494. $item_id = $data["GRADE_ITEM"]["#"]["ID"]["0"]["#"];
  5495. $this->counter++;
  5496. //Save to db
  5497. $status = backup_putid($this->preferences->backup_unique_code, 'grade_items', $item_id,
  5498. null,$data);
  5499. //Create returning info
  5500. $this->info = $this->counter;
  5501. //Reset temp
  5502. unset($this->temp);
  5503. }
  5504. //If we've finished a grade_category, xmlize it an save to db
  5505. if (($this->level == 5) and ($tagName == "GRADE_CATEGORY")) {
  5506. //Prepend XML standard header to info gathered
  5507. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5508. //Call to xmlize for this portion of xml data (one CATECORY)
  5509. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5510. $data = xmlize($xml_data,0);
  5511. $category_id = $data["GRADE_CATEGORY"]["#"]["ID"]["0"]["#"];
  5512. $this->counter++;
  5513. //Save to db
  5514. $status = backup_putid($this->preferences->backup_unique_code, 'grade_categories' ,$category_id,
  5515. null,$data);
  5516. //Create returning info
  5517. $this->info = $this->counter;
  5518. //Reset temp
  5519. unset($this->temp);
  5520. }
  5521. if (($this->level == 5) and ($tagName == "GRADE_LETTER")) {
  5522. //Prepend XML standard header to info gathered
  5523. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5524. //Call to xmlize for this portion of xml data (one CATECORY)
  5525. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5526. $data = xmlize($xml_data,0);
  5527. $letter_id = $data["GRADE_LETTER"]["#"]["ID"]["0"]["#"];
  5528. $this->counter++;
  5529. //Save to db
  5530. $status = backup_putid($this->preferences->backup_unique_code, 'grade_letters' ,$letter_id,
  5531. null,$data);
  5532. //Create returning info
  5533. $this->info = $this->counter;
  5534. //Reset temp
  5535. unset($this->temp);
  5536. }
  5537. //If we've finished a grade_outcome, xmlize it an save to db
  5538. if (($this->level == 5) and ($tagName == "GRADE_OUTCOME")) {
  5539. //Prepend XML standard header to info gathered
  5540. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5541. //Call to xmlize for this portion of xml data (one CATECORY)
  5542. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5543. $data = xmlize($xml_data,0);
  5544. $outcome_id = $data["GRADE_OUTCOME"]["#"]["ID"]["0"]["#"];
  5545. $this->counter++;
  5546. //Save to db
  5547. $status = backup_putid($this->preferences->backup_unique_code, 'grade_outcomes' ,$outcome_id,
  5548. null,$data);
  5549. //Create returning info
  5550. $this->info = $this->counter;
  5551. //Reset temp
  5552. unset($this->temp);
  5553. }
  5554. //If we've finished a grade_outcomes_course, xmlize it an save to db
  5555. if (($this->level == 5) and ($tagName == "GRADE_OUTCOMES_COURSE")) {
  5556. //Prepend XML standard header to info gathered
  5557. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5558. //Call to xmlize for this portion of xml data (one CATECORY)
  5559. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5560. $data = xmlize($xml_data,0);
  5561. $outcomes_course_id = $data["GRADE_OUTCOMES_COURSE"]["#"]["ID"]["0"]["#"];
  5562. $this->counter++;
  5563. //Save to db
  5564. $status = backup_putid($this->preferences->backup_unique_code, 'grade_outcomes_courses' ,$outcomes_course_id,
  5565. null,$data);
  5566. //Create returning info
  5567. $this->info = $this->counter;
  5568. //Reset temp
  5569. unset($this->temp);
  5570. }
  5571. if (($this->level == 5) and ($tagName == "GRADE_CATEGORIES_HISTORY")) {
  5572. //Prepend XML standard header to info gathered
  5573. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5574. //Call to xmlize for this portion of xml data (one PREFERENCE)
  5575. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5576. $data = xmlize($xml_data,0);
  5577. $id = $data["GRADE_CATEGORIES_HISTORY"]["#"]["ID"]["0"]["#"];
  5578. $this->counter++;
  5579. //Save to db
  5580. $status = backup_putid($this->preferences->backup_unique_code, 'grade_categories_history', $id,
  5581. null,$data);
  5582. //Create returning info
  5583. $this->info = $this->counter;
  5584. //Reset temp
  5585. unset($this->temp);
  5586. }
  5587. if (($this->level == 5) and ($tagName == "GRADE_GRADES_HISTORY")) {
  5588. //Prepend XML standard header to info gathered
  5589. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5590. //Call to xmlize for this portion of xml data (one PREFERENCE)
  5591. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5592. $data = xmlize($xml_data,0);
  5593. $id = $data["GRADE_GRADES_HISTORY"]["#"]["ID"]["0"]["#"];
  5594. $this->counter++;
  5595. //Save to db
  5596. $status = backup_putid($this->preferences->backup_unique_code, 'grade_grades_history', $id,
  5597. null,$data);
  5598. //Create returning info
  5599. $this->info = $this->counter;
  5600. //Reset temp
  5601. unset($this->temp);
  5602. }
  5603. if (($this->level == 5) and ($tagName == "GRADE_ITEM_HISTORY")) {
  5604. //Prepend XML standard header to info gathered
  5605. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5606. //Call to xmlize for this portion of xml data (one PREFERENCE)
  5607. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5608. $data = xmlize($xml_data,0);
  5609. $id = $data["GRADE_ITEM_HISTORY"]["#"]["ID"]["0"]["#"];
  5610. $this->counter++;
  5611. //Save to db
  5612. $status = backup_putid($this->preferences->backup_unique_code, 'grade_items_history', $id,
  5613. null,$data);
  5614. //Create returning info
  5615. $this->info = $this->counter;
  5616. //Reset temp
  5617. unset($this->temp);
  5618. }
  5619. if (($this->level == 5) and ($tagName == "GRADE_OUTCOME_HISTORY")) {
  5620. //Prepend XML standard header to info gathered
  5621. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5622. //Call to xmlize for this portion of xml data (one PREFERENCE)
  5623. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5624. $data = xmlize($xml_data,0);
  5625. $id = $data["GRADE_OUTCOME_HISTORY"]["#"]["ID"]["0"]["#"];
  5626. $this->counter++;
  5627. //Save to db
  5628. $status = backup_putid($this->preferences->backup_unique_code, 'grade_outcomes_history', $id,
  5629. null,$data);
  5630. //Create returning info
  5631. $this->info = $this->counter;
  5632. //Reset temp
  5633. unset($this->temp);
  5634. }
  5635. }
  5636. //Stop parsing if todo = GRADEBOOK and tagName = GRADEBOOK (en of the tag, of course)
  5637. //Speed up a lot (avoid parse all)
  5638. if ($tagName == "GRADEBOOK" and $this->level == 3) {
  5639. $this->finished = true;
  5640. $this->counter = 0;
  5641. }
  5642. //Clear things
  5643. $this->tree[$this->level] = "";
  5644. $this->level--;
  5645. $this->content = "";
  5646. }
  5647. //This is the endTag handler we use where we are reading the gradebook zone (todo="GRADEBOOK")
  5648. function endElementOldGradebook($parser, $tagName) {
  5649. //Check if we are into GRADEBOOK zone
  5650. if ($this->tree[3] == "GRADEBOOK") {
  5651. //if (trim($this->content)) //Debug
  5652. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  5653. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n";//Debug
  5654. //Acumulate data to info (content + close tag)
  5655. //Reconvert: strip htmlchars again and trim to generate xml data
  5656. if (!isset($this->temp)) {
  5657. $this->temp = "";
  5658. }
  5659. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  5660. //We have finished preferences, letters or categories, reset accumulated
  5661. //data because they are close tags
  5662. if ($this->level == 4) {
  5663. $this->temp = "";
  5664. }
  5665. //If we've finished a message, xmlize it an save to db
  5666. if (($this->level == 5) and ($tagName == "GRADE_PREFERENCE")) {
  5667. //Prepend XML standard header to info gathered
  5668. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5669. //Call to xmlize for this portion of xml data (one PREFERENCE)
  5670. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5671. $data = xmlize($xml_data,0);
  5672. //echo strftime ("%X",time())."<p>"; //Debug
  5673. //traverse_xmlize($data); //Debug
  5674. //print_object ($GLOBALS['traverse_array']); //Debug
  5675. //$GLOBALS['traverse_array']=""; //Debug
  5676. //Now, save data to db. We'll use it later
  5677. //Get id and status from data
  5678. $preference_id = $data["GRADE_PREFERENCE"]["#"]["ID"]["0"]["#"];
  5679. $this->counter++;
  5680. //Save to db
  5681. $status = backup_putid($this->preferences->backup_unique_code, 'grade_preferences', $preference_id,
  5682. null,$data);
  5683. //Create returning info
  5684. $this->info = $this->counter;
  5685. //Reset temp
  5686. unset($this->temp);
  5687. }
  5688. //If we've finished a grade_letter, xmlize it an save to db
  5689. if (($this->level == 5) and ($tagName == "GRADE_LETTER")) {
  5690. //Prepend XML standard header to info gathered
  5691. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5692. //Call to xmlize for this portion of xml data (one LETTER)
  5693. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5694. $data = xmlize($xml_data,0);
  5695. //echo strftime ("%X",time())."<p>"; //Debug
  5696. //traverse_xmlize($data); //Debug
  5697. //print_object ($GLOBALS['traverse_array']); //Debug
  5698. //$GLOBALS['traverse_array']=""; //Debug
  5699. //Now, save data to db. We'll use it later
  5700. //Get id and status from data
  5701. $letter_id = $data["GRADE_LETTER"]["#"]["ID"]["0"]["#"];
  5702. $this->counter++;
  5703. //Save to db
  5704. $status = backup_putid($this->preferences->backup_unique_code, 'grade_letter' ,$letter_id,
  5705. null,$data);
  5706. //Create returning info
  5707. $this->info = $this->counter;
  5708. //Reset temp
  5709. unset($this->temp);
  5710. }
  5711. //If we've finished a grade_category, xmlize it an save to db
  5712. if (($this->level == 5) and ($tagName == "GRADE_CATEGORY")) {
  5713. //Prepend XML standard header to info gathered
  5714. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  5715. //Call to xmlize for this portion of xml data (one CATECORY)
  5716. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  5717. $data = xmlize($xml_data,0);
  5718. //echo strftime ("%X",time())."<p>"; //Debug
  5719. //traverse_xmlize($data); //Debug
  5720. //print_object ($GLOBALS['traverse_array']); //Debug
  5721. //$GLOBALS['traverse_array']=""; //Debug
  5722. //Now, save data to db. We'll use it later
  5723. //Get id and status from data
  5724. $category_id = $data["GRADE_CATEGORY"]["#"]["ID"]["0"]["#"];
  5725. $this->counter++;
  5726. //Save to db
  5727. $status = backup_putid($this->preferences->backup_unique_code, 'grade_category' ,$category_id,
  5728. null,$data);
  5729. //Create returning info
  5730. $this->info = $this->counter;
  5731. //Reset temp
  5732. unset($this->temp);
  5733. }
  5734. }
  5735. //Stop parsing if todo = GRADEBOOK and tagName = GRADEBOOK (en of the tag, of course)
  5736. //Speed up a lot (avoid parse all)
  5737. if ($tagName == "GRADEBOOK" and $this->level == 3) {
  5738. $this->finished = true;
  5739. $this->counter = 0;
  5740. }
  5741. //Clear things
  5742. $this->tree[$this->level] = "";
  5743. $this->level--;
  5744. $this->content = "";
  5745. }
  5746. //This is the endTag handler we use where we are reading the users zone (todo="USERS")
  5747. function endElementUsers($parser, $tagName) {
  5748. global $CFG;
  5749. //Check if we are into USERS zone
  5750. if ($this->tree[3] == "USERS") {
  5751. //if (trim($this->content)) //Debug
  5752. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  5753. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  5754. //Dependig of different combinations, do different things
  5755. if ($this->level == 4) {
  5756. switch ($tagName) {
  5757. case "USER":
  5758. //Increment counter
  5759. $this->counter++;
  5760. //Save to db, only save if record not already exist
  5761. // if there already is an new_id for this entry, just use that new_id?
  5762. $newuser = backup_getid($this->preferences->backup_unique_code,"user",$this->info->tempuser->id);
  5763. if (isset($newuser->new_id)) {
  5764. $newid = $newuser->new_id;
  5765. } else {
  5766. $newid = null;
  5767. }
  5768. backup_putid($this->preferences->backup_unique_code,"user",$this->info->tempuser->id,
  5769. $newid,$this->info->tempuser);
  5770. //Do some output
  5771. if ($this->counter % 10 == 0) {
  5772. if (!defined('RESTORE_SILENTLY')) {
  5773. echo ".";
  5774. if ($this->counter % 200 == 0) {
  5775. echo "<br />";
  5776. }
  5777. }
  5778. backup_flush(300);
  5779. }
  5780. //Delete temp obejct
  5781. unset($this->info->tempuser);
  5782. break;
  5783. }
  5784. }
  5785. if ($this->level == 5) {
  5786. switch ($tagName) {
  5787. case "ID":
  5788. $this->info->users[$this->getContents()] = $this->getContents();
  5789. $this->info->tempuser->id = $this->getContents();
  5790. break;
  5791. case "AUTH":
  5792. $this->info->tempuser->auth = $this->getContents();
  5793. break;
  5794. case "CONFIRMED":
  5795. $this->info->tempuser->confirmed = $this->getContents();
  5796. break;
  5797. case "POLICYAGREED":
  5798. $this->info->tempuser->policyagreed = $this->getContents();
  5799. break;
  5800. case "DELETED":
  5801. $this->info->tempuser->deleted = $this->getContents();
  5802. break;
  5803. case "USERNAME":
  5804. $this->info->tempuser->username = $this->getContents();
  5805. break;
  5806. case "PASSWORD":
  5807. $this->info->tempuser->password = $this->getContents();
  5808. break;
  5809. case "IDNUMBER":
  5810. $this->info->tempuser->idnumber = $this->getContents();
  5811. break;
  5812. case "FIRSTNAME":
  5813. $this->info->tempuser->firstname = $this->getContents();
  5814. break;
  5815. case "LASTNAME":
  5816. $this->info->tempuser->lastname = $this->getContents();
  5817. break;
  5818. case "EMAIL":
  5819. $this->info->tempuser->email = $this->getContents();
  5820. break;
  5821. case "EMAILSTOP":
  5822. $this->info->tempuser->emailstop = $this->getContents();
  5823. break;
  5824. case "ICQ":
  5825. $this->info->tempuser->icq = $this->getContents();
  5826. break;
  5827. case "SKYPE":
  5828. $this->info->tempuser->skype = $this->getContents();
  5829. break;
  5830. case "AIM":
  5831. $this->info->tempuser->aim = $this->getContents();
  5832. break;
  5833. case "YAHOO":
  5834. $this->info->tempuser->yahoo = $this->getContents();
  5835. break;
  5836. case "MSN":
  5837. $this->info->tempuser->msn = $this->getContents();
  5838. break;
  5839. case "PHONE1":
  5840. $this->info->tempuser->phone1 = $this->getContents();
  5841. break;
  5842. case "PHONE2":
  5843. $this->info->tempuser->phone2 = $this->getContents();
  5844. break;
  5845. case "INSTITUTION":
  5846. $this->info->tempuser->institution = $this->getContents();
  5847. break;
  5848. case "DEPARTMENT":
  5849. $this->info->tempuser->department = $this->getContents();
  5850. break;
  5851. case "ADDRESS":
  5852. $this->info->tempuser->address = $this->getContents();
  5853. break;
  5854. case "CITY":
  5855. $this->info->tempuser->city = $this->getContents();
  5856. break;
  5857. case "COUNTRY":
  5858. $this->info->tempuser->country = $this->getContents();
  5859. break;
  5860. case "LANG":
  5861. $this->info->tempuser->lang = $this->getContents();
  5862. break;
  5863. case "THEME":
  5864. $this->info->tempuser->theme = $this->getContents();
  5865. break;
  5866. case "TIMEZONE":
  5867. $this->info->tempuser->timezone = $this->getContents();
  5868. break;
  5869. case "FIRSTACCESS":
  5870. $this->info->tempuser->firstaccess = $this->getContents();
  5871. break;
  5872. case "LASTACCESS":
  5873. $this->info->tempuser->lastaccess = $this->getContents();
  5874. break;
  5875. case "LASTLOGIN":
  5876. $this->info->tempuser->lastlogin = $this->getContents();
  5877. break;
  5878. case "CURRENTLOGIN":
  5879. $this->info->tempuser->currentlogin = $this->getContents();
  5880. break;
  5881. case "LASTIP":
  5882. $this->info->tempuser->lastip = $this->getContents();
  5883. break;
  5884. case "SECRET":
  5885. $this->info->tempuser->secret = $this->getContents();
  5886. break;
  5887. case "PICTURE":
  5888. $this->info->tempuser->picture = $this->getContents();
  5889. break;
  5890. case "URL":
  5891. $this->info->tempuser->url = $this->getContents();
  5892. break;
  5893. case "DESCRIPTION":
  5894. $this->info->tempuser->description = $this->getContents();
  5895. break;
  5896. case "MAILFORMAT":
  5897. $this->info->tempuser->mailformat = $this->getContents();
  5898. break;
  5899. case "MAILDIGEST":
  5900. $this->info->tempuser->maildigest = $this->getContents();
  5901. break;
  5902. case "MAILDISPLAY":
  5903. $this->info->tempuser->maildisplay = $this->getContents();
  5904. break;
  5905. case "HTMLEDITOR":
  5906. $this->info->tempuser->htmleditor = $this->getContents();
  5907. break;
  5908. case "AJAX":
  5909. $this->info->tempuser->ajax = $this->getContents();
  5910. break;
  5911. case "AUTOSUBSCRIBE":
  5912. $this->info->tempuser->autosubscribe = $this->getContents();
  5913. break;
  5914. case "TRACKFORUMS":
  5915. $this->info->tempuser->trackforums = $this->getContents();
  5916. break;
  5917. case "MNETHOSTURL":
  5918. $this->info->tempuser->mnethosturl = $this->getContents();
  5919. break;
  5920. case "TIMEMODIFIED":
  5921. $this->info->tempuser->timemodified = $this->getContents();
  5922. break;
  5923. default:
  5924. break;
  5925. }
  5926. }
  5927. if ($this->level == 6 && $this->tree[5]!="ROLES_ASSIGNMENTS" && $this->tree[5]!="ROLES_OVERRIDES") {
  5928. switch ($tagName) {
  5929. case "ROLE":
  5930. //We've finalized a role, get it
  5931. $this->info->tempuser->roles[$this->info->temprole->type] = $this->info->temprole;
  5932. unset($this->info->temprole);
  5933. break;
  5934. case "USER_PREFERENCE":
  5935. //We've finalized a user_preference, get it
  5936. $this->info->tempuser->user_preferences[$this->info->tempuserpreference->name] = $this->info->tempuserpreference;
  5937. unset($this->info->tempuserpreference);
  5938. break;
  5939. case "USER_CUSTOM_PROFILE_FIELD":
  5940. //We've finalized a user_custom_profile_field, get it
  5941. $this->info->tempuser->user_custom_profile_fields[] = $this->info->tempusercustomprofilefield;
  5942. unset($this->info->tempusercustomprofilefield);
  5943. break;
  5944. case "USER_TAG":
  5945. //We've finalized a user_tag, get it
  5946. $this->info->tempuser->user_tags[] = $this->info->tempusertag;
  5947. unset($this->info->tempusertag);
  5948. break;
  5949. default:
  5950. break;
  5951. }
  5952. }
  5953. if ($this->level == 7 && $this->tree[5]!="ROLES_ASSIGNMENTS" && $this->tree[5]!="ROLES_OVERRIDES") {
  5954. /// If we are reading roles
  5955. if($this->tree[6] == 'ROLE') {
  5956. switch ($tagName) {
  5957. case "TYPE":
  5958. $this->info->temprole->type = $this->getContents();
  5959. break;
  5960. case "AUTHORITY":
  5961. $this->info->temprole->authority = $this->getContents();
  5962. break;
  5963. case "TEA_ROLE":
  5964. $this->info->temprole->tea_role = $this->getContents();
  5965. break;
  5966. case "EDITALL":
  5967. $this->info->temprole->editall = $this->getContents();
  5968. break;
  5969. case "TIMESTART":
  5970. $this->info->temprole->timestart = $this->getContents();
  5971. break;
  5972. case "TIMEEND":
  5973. $this->info->temprole->timeend = $this->getContents();
  5974. break;
  5975. case "TIMEMODIFIED":
  5976. $this->info->temprole->timemodified = $this->getContents();
  5977. break;
  5978. case "TIMESTART":
  5979. $this->info->temprole->timestart = $this->getContents();
  5980. break;
  5981. case "TIMEEND":
  5982. $this->info->temprole->timeend = $this->getContents();
  5983. break;
  5984. case "TIME":
  5985. $this->info->temprole->time = $this->getContents();
  5986. break;
  5987. case "TIMEACCESS":
  5988. $this->info->temprole->timeaccess = $this->getContents();
  5989. break;
  5990. case "ENROL":
  5991. $this->info->temprole->enrol = $this->getContents();
  5992. break;
  5993. default:
  5994. break;
  5995. }
  5996. /// If we are reading user_preferences
  5997. } else if ($this->tree[6] == 'USER_PREFERENCE') {
  5998. switch ($tagName) {
  5999. case "NAME":
  6000. $this->info->tempuserpreference->name = $this->getContents();
  6001. break;
  6002. case "VALUE":
  6003. $this->info->tempuserpreference->value = $this->getContents();
  6004. break;
  6005. default:
  6006. break;
  6007. }
  6008. /// If we are reading user_custom_profile_fields
  6009. } else if ($this->tree[6] == 'USER_CUSTOM_PROFILE_FIELD') {
  6010. switch ($tagName) {
  6011. case "FIELD_NAME":
  6012. $this->info->tempusercustomprofilefield->field_name = $this->getContents();
  6013. break;
  6014. case "FIELD_TYPE":
  6015. $this->info->tempusercustomprofilefield->field_type = $this->getContents();
  6016. break;
  6017. case "FIELD_DATA":
  6018. $this->info->tempusercustomprofilefield->field_data = $this->getContents();
  6019. break;
  6020. default:
  6021. break;
  6022. }
  6023. /// If we are reading user_tags
  6024. } else if ($this->tree[6] == 'USER_TAG') {
  6025. switch ($tagName) {
  6026. case "NAME":
  6027. $this->info->tempusertag->name = $this->getContents();
  6028. break;
  6029. case "RAWNAME":
  6030. $this->info->tempusertag->rawname = $this->getContents();
  6031. break;
  6032. default:
  6033. break;
  6034. }
  6035. }
  6036. }
  6037. if ($this->tree[5] == "ROLES_ASSIGNMENTS") {
  6038. if ($this->level == 7) {
  6039. switch ($tagName) {
  6040. case "NAME":
  6041. $this->info->tempname = $this->getContents();
  6042. break;
  6043. case "SHORTNAME":
  6044. $this->info->tempshortname = $this->getContents();
  6045. break;
  6046. case "ID":
  6047. $this->info->tempid = $this->getContents(); // temp roleid
  6048. break;
  6049. }
  6050. }
  6051. if ($this->level == 9) {
  6052. switch ($tagName) {
  6053. case "USERID":
  6054. $this->info->tempuser->roleassignments[$this->info->tempid]->name = $this->info->tempname;
  6055. $this->info->tempuser->roleassignments[$this->info->tempid]->shortname = $this->info->tempshortname;
  6056. $this->info->tempuserid = $this->getContents();
  6057. $this->info->tempuser->roleassignments[$this->info->tempid]->assignments[$this->info->tempuserid]->userid = $this->getContents();
  6058. break;
  6059. case "HIDDEN":
  6060. $this->info->tempuser->roleassignments[$this->info->tempid]->assignments[$this->info->tempuserid]->hidden = $this->getContents();
  6061. break;
  6062. case "TIMESTART":
  6063. $this->info->tempuser->roleassignments[$this->info->tempid]->assignments[$this->info->tempuserid]->timestart = $this->getContents();
  6064. break;
  6065. case "TIMEEND":
  6066. $this->info->tempuser->roleassignments[$this->info->tempid]->assignments[$this->info->tempuserid]->timeend = $this->getContents();
  6067. break;
  6068. case "TIMEMODIFIED":
  6069. $this->info->tempuser->roleassignments[$this->info->tempid]->assignments[$this->info->tempuserid]->timemodified = $this->getContents();
  6070. break;
  6071. case "MODIFIERID":
  6072. $this->info->tempuser->roleassignments[$this->info->tempid]->assignments[$this->info->tempuserid]->modifierid = $this->getContents();
  6073. break;
  6074. case "ENROL":
  6075. $this->info->tempuser->roleassignments[$this->info->tempid]->assignments[$this->info->tempuserid]->enrol = $this->getContents();
  6076. break;
  6077. case "SORTORDER":
  6078. $this->info->tempuser->roleassignments[$this->info->tempid]->assignments[$this->info->tempuserid]->sortorder = $this->getContents();
  6079. break;
  6080. }
  6081. }
  6082. } /// ends role_assignments
  6083. if ($this->tree[5] == "ROLES_OVERRIDES") {
  6084. if ($this->level == 7) {
  6085. switch ($tagName) {
  6086. case "NAME":
  6087. $this->info->tempname = $this->getContents();
  6088. break;
  6089. case "SHORTNAME":
  6090. $this->info->tempshortname = $this->getContents();
  6091. break;
  6092. case "ID":
  6093. $this->info->tempid = $this->getContents(); // temp roleid
  6094. break;
  6095. }
  6096. }
  6097. if ($this->level == 9) {
  6098. switch ($tagName) {
  6099. case "NAME":
  6100. $this->info->tempuser->roleoverrides[$this->info->tempid]->name = $this->info->tempname;
  6101. $this->info->tempuser->roleoverrides[$this->info->tempid]->shortname = $this->info->tempshortname;
  6102. $this->info->tempname = $this->getContents(); // change to name of capability
  6103. $this->info->tempuser->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->name = $this->getContents();
  6104. break;
  6105. case "PERMISSION":
  6106. $this->info->tempuser->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->permission = $this->getContents();
  6107. break;
  6108. case "TIMEMODIFIED":
  6109. $this->info->tempuser->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->timemodified = $this->getContents();
  6110. break;
  6111. case "MODIFIERID":
  6112. $this->info->tempuser->roleoverrides[$this->info->tempid]->overrides[$this->info->tempname]->modifierid = $this->getContents();
  6113. break;
  6114. }
  6115. }
  6116. } /// ends role_overrides
  6117. } // closes if this->tree[3]=="users"
  6118. //Stop parsing if todo = USERS and tagName = USERS (en of the tag, of course)
  6119. //Speed up a lot (avoid parse all)
  6120. if ($tagName == "USERS" and $this->level == 3) {
  6121. $this->finished = true;
  6122. $this->counter = 0;
  6123. }
  6124. //Clear things
  6125. $this->tree[$this->level] = "";
  6126. $this->level--;
  6127. $this->content = "";
  6128. }
  6129. //This is the endTag handler we use where we are reading the messages zone (todo="MESSAGES")
  6130. function endElementMessages($parser, $tagName) {
  6131. //Check if we are into MESSAGES zone
  6132. if ($this->tree[3] == "MESSAGES") {
  6133. //if (trim($this->content)) //Debug
  6134. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6135. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n";//Debug
  6136. //Acumulate data to info (content + close tag)
  6137. //Reconvert: strip htmlchars again and trim to generate xml data
  6138. if (!isset($this->temp)) {
  6139. $this->temp = "";
  6140. }
  6141. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6142. //If we've finished a message, xmlize it an save to db
  6143. if (($this->level == 4) and ($tagName == "MESSAGE")) {
  6144. //Prepend XML standard header to info gathered
  6145. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6146. //Call to xmlize for this portion of xml data (one MESSAGE)
  6147. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6148. $data = xmlize($xml_data,0);
  6149. //echo strftime ("%X",time())."<p>"; //Debug
  6150. //traverse_xmlize($data); //Debug
  6151. //print_object ($GLOBALS['traverse_array']); //Debug
  6152. //$GLOBALS['traverse_array']=""; //Debug
  6153. //Now, save data to db. We'll use it later
  6154. //Get id and status from data
  6155. $message_id = $data["MESSAGE"]["#"]["ID"]["0"]["#"];
  6156. $message_status = $data["MESSAGE"]["#"]["STATUS"]["0"]["#"];
  6157. if ($message_status == "READ") {
  6158. $table = "message_read";
  6159. } else {
  6160. $table = "message";
  6161. }
  6162. $this->counter++;
  6163. //Save to db
  6164. $status = backup_putid($this->preferences->backup_unique_code, $table,$message_id,
  6165. null,$data);
  6166. //Create returning info
  6167. $this->info = $this->counter;
  6168. //Reset temp
  6169. unset($this->temp);
  6170. }
  6171. //If we've finished a contact, xmlize it an save to db
  6172. if (($this->level == 5) and ($tagName == "CONTACT")) {
  6173. //Prepend XML standard header to info gathered
  6174. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6175. //Call to xmlize for this portion of xml data (one MESSAGE)
  6176. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6177. $data = xmlize($xml_data,0);
  6178. //echo strftime ("%X",time())."<p>"; //Debug
  6179. //traverse_xmlize($data); //Debug
  6180. //print_object ($GLOBALS['traverse_array']); //Debug
  6181. //$GLOBALS['traverse_array']=""; //Debug
  6182. //Now, save data to db. We'll use it later
  6183. //Get id and status from data
  6184. $contact_id = $data["CONTACT"]["#"]["ID"]["0"]["#"];
  6185. $this->counter++;
  6186. //Save to db
  6187. $status = backup_putid($this->preferences->backup_unique_code, 'message_contacts' ,$contact_id,
  6188. null,$data);
  6189. //Create returning info
  6190. $this->info = $this->counter;
  6191. //Reset temp
  6192. unset($this->temp);
  6193. }
  6194. }
  6195. //Stop parsing if todo = MESSAGES and tagName = MESSAGES (en of the tag, of course)
  6196. //Speed up a lot (avoid parse all)
  6197. if ($tagName == "MESSAGES" and $this->level == 3) {
  6198. $this->finished = true;
  6199. $this->counter = 0;
  6200. }
  6201. //Clear things
  6202. $this->tree[$this->level] = "";
  6203. $this->level--;
  6204. $this->content = "";
  6205. }
  6206. //This is the endTag handler we use where we are reading the blogs zone (todo="BLOGS")
  6207. function endElementBlogs($parser, $tagName) {
  6208. //Check if we are into BLOGS zone
  6209. if ($this->tree[3] == "BLOGS") {
  6210. //if (trim($this->content)) //Debug
  6211. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6212. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n";//Debug
  6213. //Acumulate data to info (content + close tag)
  6214. //Reconvert: strip htmlchars again and trim to generate xml data
  6215. if (!isset($this->temp)) {
  6216. $this->temp = "";
  6217. }
  6218. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6219. //If we've finished a blog, xmlize it an save to db
  6220. if (($this->level == 4) and ($tagName == "BLOG")) {
  6221. //Prepend XML standard header to info gathered
  6222. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6223. //Call to xmlize for this portion of xml data (one BLOG)
  6224. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6225. $data = xmlize($xml_data,0);
  6226. //echo strftime ("%X",time())."<p>"; //Debug
  6227. //traverse_xmlize($data); //Debug
  6228. //print_object ($GLOBALS['traverse_array']); //Debug
  6229. //$GLOBALS['traverse_array']=""; //Debug
  6230. //Now, save data to db. We'll use it later
  6231. //Get id from data
  6232. $blog_id = $data["BLOG"]["#"]["ID"]["0"]["#"];
  6233. $this->counter++;
  6234. //Save to db
  6235. $status = backup_putid($this->preferences->backup_unique_code, 'blog', $blog_id,
  6236. null,$data);
  6237. //Create returning info
  6238. $this->info = $this->counter;
  6239. //Reset temp
  6240. unset($this->temp);
  6241. }
  6242. }
  6243. //Stop parsing if todo = BLOGS and tagName = BLOGS (end of the tag, of course)
  6244. //Speed up a lot (avoid parse all)
  6245. if ($tagName == "BLOGS" and $this->level == 3) {
  6246. $this->finished = true;
  6247. $this->counter = 0;
  6248. }
  6249. //Clear things
  6250. $this->tree[$this->level] = "";
  6251. $this->level--;
  6252. $this->content = "";
  6253. }
  6254. //This is the endTag handler we use where we are reading the questions zone (todo="QUESTIONS")
  6255. function endElementQuestions($parser, $tagName) {
  6256. //Check if we are into QUESTION_CATEGORIES zone
  6257. if ($this->tree[3] == "QUESTION_CATEGORIES") {
  6258. //if (trim($this->content)) //Debug
  6259. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6260. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  6261. //Acumulate data to info (content + close tag)
  6262. //Reconvert: strip htmlchars again and trim to generate xml data
  6263. if (!isset($this->temp)) {
  6264. $this->temp = "";
  6265. }
  6266. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6267. //If we've finished a mod, xmlize it an save to db
  6268. if (($this->level == 4) and ($tagName == "QUESTION_CATEGORY")) {
  6269. //Prepend XML standard header to info gathered
  6270. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6271. //Call to xmlize for this portion of xml data (one QUESTION_CATEGORY)
  6272. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6273. $data = xmlize($xml_data,0);
  6274. //echo strftime ("%X",time())."<p>"; //Debug
  6275. //traverse_xmlize($data); //Debug
  6276. //print_object ($GLOBALS['traverse_array']); //Debug
  6277. //$GLOBALS['traverse_array']=""; //Debug
  6278. //Now, save data to db. We'll use it later
  6279. //Get id from data
  6280. $category_id = $data["QUESTION_CATEGORY"]["#"]["ID"]["0"]["#"];
  6281. //Save to db
  6282. $status = backup_putid($this->preferences->backup_unique_code,"question_categories",$category_id,
  6283. null,$data);
  6284. //Create returning info
  6285. $ret_info = new object();
  6286. $ret_info->id = $category_id;
  6287. $this->info[] = $ret_info;
  6288. //Reset temp
  6289. unset($this->temp);
  6290. }
  6291. }
  6292. //Stop parsing if todo = QUESTION_CATEGORIES and tagName = QUESTION_CATEGORY (en of the tag, of course)
  6293. //Speed up a lot (avoid parse all)
  6294. if ($tagName == "QUESTION_CATEGORIES" and $this->level == 3) {
  6295. $this->finished = true;
  6296. }
  6297. //Clear things
  6298. $this->tree[$this->level] = "";
  6299. $this->level--;
  6300. $this->content = "";
  6301. }
  6302. //This is the endTag handler we use where we are reading the scales zone (todo="SCALES")
  6303. function endElementScales($parser, $tagName) {
  6304. //Check if we are into SCALES zone
  6305. if ($this->tree[3] == "SCALES") {
  6306. //if (trim($this->content)) //Debug
  6307. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6308. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  6309. //Acumulate data to info (content + close tag)
  6310. //Reconvert: strip htmlchars again and trim to generate xml data
  6311. if (!isset($this->temp)) {
  6312. $this->temp = "";
  6313. }
  6314. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6315. //If we've finished a scale, xmlize it an save to db
  6316. if (($this->level == 4) and ($tagName == "SCALE")) {
  6317. //Prepend XML standard header to info gathered
  6318. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6319. //Call to xmlize for this portion of xml data (one SCALE)
  6320. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6321. $data = xmlize($xml_data,0);
  6322. //echo strftime ("%X",time())."<p>"; //Debug
  6323. //traverse_xmlize($data); //Debug
  6324. //print_object ($GLOBALS['traverse_array']); //Debug
  6325. //$GLOBALS['traverse_array']=""; //Debug
  6326. //Now, save data to db. We'll use it later
  6327. //Get id and from data
  6328. $scale_id = $data["SCALE"]["#"]["ID"]["0"]["#"];
  6329. //Save to db
  6330. $status = backup_putid($this->preferences->backup_unique_code,"scale",$scale_id,
  6331. null,$data);
  6332. //Create returning info
  6333. $ret_info = new object();
  6334. $ret_info->id = $scale_id;
  6335. $this->info[] = $ret_info;
  6336. //Reset temp
  6337. unset($this->temp);
  6338. }
  6339. }
  6340. //Stop parsing if todo = SCALES and tagName = SCALE (en of the tag, of course)
  6341. //Speed up a lot (avoid parse all)
  6342. if ($tagName == "SCALES" and $this->level == 3) {
  6343. $this->finished = true;
  6344. }
  6345. //Clear things
  6346. $this->tree[$this->level] = "";
  6347. $this->level--;
  6348. $this->content = "";
  6349. }
  6350. //This is the endTag handler we use where we are reading the groups zone (todo="GROUPS")
  6351. function endElementGroups($parser, $tagName) {
  6352. //Check if we are into GROUPS zone
  6353. if ($this->tree[3] == "GROUPS") {
  6354. //if (trim($this->content)) //Debug
  6355. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6356. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  6357. //Acumulate data to info (content + close tag)
  6358. //Reconvert: strip htmlchars again and trim to generate xml data
  6359. if (!isset($this->temp)) {
  6360. $this->temp = "";
  6361. }
  6362. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6363. //If we've finished a group, xmlize it an save to db
  6364. if (($this->level == 4) and ($tagName == "GROUP")) {
  6365. //Prepend XML standard header to info gathered
  6366. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6367. //Call to xmlize for this portion of xml data (one GROUP)
  6368. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6369. $data = xmlize($xml_data,0);
  6370. //echo strftime ("%X",time())."<p>"; //Debug
  6371. //traverse_xmlize($data); //Debug
  6372. //print_object ($GLOBALS['traverse_array']); //Debug
  6373. //$GLOBALS['traverse_array']=""; //Debug
  6374. //Now, save data to db. We'll use it later
  6375. //Get id and from data
  6376. $group_id = $data["GROUP"]["#"]["ID"]["0"]["#"];
  6377. //Save to db
  6378. $status = backup_putid($this->preferences->backup_unique_code,"groups",$group_id,
  6379. null,$data);
  6380. //Create returning info
  6381. $ret_info = new Object();
  6382. $ret_info->id = $group_id;
  6383. $this->info[] = $ret_info;
  6384. //Reset temp
  6385. unset($this->temp);
  6386. }
  6387. }
  6388. //Stop parsing if todo = GROUPS and tagName = GROUP (en of the tag, of course)
  6389. //Speed up a lot (avoid parse all)
  6390. if ($tagName == "GROUPS" and $this->level == 3) {
  6391. $this->finished = true;
  6392. }
  6393. //Clear things
  6394. $this->tree[$this->level] = "";
  6395. $this->level--;
  6396. $this->content = "";
  6397. }
  6398. //This is the endTag handler we use where we are reading the groupings zone (todo="GROUPINGS")
  6399. function endElementGroupings($parser, $tagName) {
  6400. //Check if we are into GROUPINGS zone
  6401. if ($this->tree[3] == "GROUPINGS") {
  6402. //Acumulate data to info (content + close tag)
  6403. //Reconvert: strip htmlchars again and trim to generate xml data
  6404. if (!isset($this->temp)) {
  6405. $this->temp = "";
  6406. }
  6407. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6408. //If we've finished a group, xmlize it an save to db
  6409. if (($this->level == 4) and ($tagName == "GROUPING")) {
  6410. //Prepend XML standard header to info gathered
  6411. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6412. //Call to xmlize for this portion of xml data (one GROUPING)
  6413. $data = xmlize($xml_data,0);
  6414. //Now, save data to db. We'll use it later
  6415. //Get id and from data
  6416. $grouping_id = $data["GROUPING"]["#"]["ID"]["0"]["#"];
  6417. //Save to db
  6418. $status = backup_putid($this->preferences->backup_unique_code,"groupings",$grouping_id,
  6419. null,$data);
  6420. //Create returning info
  6421. $ret_info = new Object();
  6422. $ret_info->id = $grouping_id;
  6423. $this->info[] = $ret_info;
  6424. //Reset temp
  6425. unset($this->temp);
  6426. }
  6427. }
  6428. //Stop parsing if todo = GROUPINGS and tagName = GROUPING (en of the tag, of course)
  6429. //Speed up a lot (avoid parse all)
  6430. if ($tagName == "GROUPINGS" and $this->level == 3) {
  6431. $this->finished = true;
  6432. }
  6433. //Clear things
  6434. $this->tree[$this->level] = "";
  6435. $this->level--;
  6436. $this->content = "";
  6437. }
  6438. //This is the endTag handler we use where we are reading the groupingsgroups zone (todo="GROUPINGGROUPS")
  6439. function endElementGroupingsGroups($parser, $tagName) {
  6440. //Check if we are into GROUPINGSGROUPS zone
  6441. if ($this->tree[3] == "GROUPINGSGROUPS") {
  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 group, xmlize it an save to db
  6449. if (($this->level == 4) and ($tagName == "GROUPINGGROUP")) {
  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 GROUPING)
  6453. $data = xmlize($xml_data,0);
  6454. //Now, save data to db. We'll use it later
  6455. //Get id and from data
  6456. $groupinggroup_id = $data["GROUPINGGROUP"]["#"]["ID"]["0"]["#"];
  6457. //Save to db
  6458. $status = backup_putid($this->preferences->backup_unique_code,"groupingsgroups",$groupinggroup_id,
  6459. null,$data);
  6460. //Create returning info
  6461. $ret_info = new Object();
  6462. $ret_info->id = $groupinggroup_id;
  6463. $this->info[] = $ret_info;
  6464. //Reset temp
  6465. unset($this->temp);
  6466. }
  6467. }
  6468. //Stop parsing if todo = GROUPINGS and tagName = GROUPING (en of the tag, of course)
  6469. //Speed up a lot (avoid parse all)
  6470. if ($tagName == "GROUPINGSGROUPS" and $this->level == 3) {
  6471. $this->finished = true;
  6472. }
  6473. //Clear things
  6474. $this->tree[$this->level] = "";
  6475. $this->level--;
  6476. $this->content = "";
  6477. }
  6478. //This is the endTag handler we use where we are reading the events zone (todo="EVENTS")
  6479. function endElementEvents($parser, $tagName) {
  6480. //Check if we are into EVENTS zone
  6481. if ($this->tree[3] == "EVENTS") {
  6482. //if (trim($this->content)) //Debug
  6483. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6484. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  6485. //Acumulate data to info (content + close tag)
  6486. //Reconvert: strip htmlchars again and trim to generate xml data
  6487. if (!isset($this->temp)) {
  6488. $this->temp = "";
  6489. }
  6490. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6491. //If we've finished a event, xmlize it an save to db
  6492. if (($this->level == 4) and ($tagName == "EVENT")) {
  6493. //Prepend XML standard header to info gathered
  6494. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6495. //Call to xmlize for this portion of xml data (one EVENT)
  6496. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6497. $data = xmlize($xml_data,0);
  6498. //echo strftime ("%X",time())."<p>"; //Debug
  6499. //traverse_xmlize($data); //Debug
  6500. //print_object ($GLOBALS['traverse_array']); //Debug
  6501. //$GLOBALS['traverse_array']=""; //Debug
  6502. //Now, save data to db. We'll use it later
  6503. //Get id and from data
  6504. $event_id = $data["EVENT"]["#"]["ID"]["0"]["#"];
  6505. //Save to db
  6506. $status = backup_putid($this->preferences->backup_unique_code,"event",$event_id,
  6507. null,$data);
  6508. //Create returning info
  6509. $ret_info = new object();
  6510. $ret_info->id = $event_id;
  6511. $this->info[] = $ret_info;
  6512. //Reset temp
  6513. unset($this->temp);
  6514. }
  6515. }
  6516. //Stop parsing if todo = EVENTS and tagName = EVENT (en of the tag, of course)
  6517. //Speed up a lot (avoid parse all)
  6518. if ($tagName == "EVENTS" and $this->level == 3) {
  6519. $this->finished = true;
  6520. }
  6521. //Clear things
  6522. $this->tree[$this->level] = "";
  6523. $this->level--;
  6524. $this->content = "";
  6525. }
  6526. //This is the endTag handler we use where we are reading the modules zone (todo="MODULES")
  6527. function endElementModules($parser, $tagName) {
  6528. //Check if we are into MODULES zone
  6529. if ($this->tree[3] == "MODULES") {
  6530. //if (trim($this->content)) //Debug
  6531. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6532. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  6533. //Acumulate data to info (content + close tag)
  6534. //Reconvert: strip htmlchars again and trim to generate xml data
  6535. if (!isset($this->temp)) {
  6536. $this->temp = "";
  6537. }
  6538. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6539. //If we've finished a mod, xmlize it an save to db
  6540. if (($this->level == 4) and ($tagName == "MOD")) {
  6541. //Only process the module if efectively it has been selected for restore. MDL-18482
  6542. if (empty($this->preferences->mods[$this->temp_mod_type]->granular) // We don't care about per instance, i.e. restore all instances.
  6543. or (array_key_exists($this->temp_mod_id, $this->preferences->mods[$this->temp_mod_type]->instances)
  6544. and
  6545. !empty($this->preferences->mods[$this->temp_mod_type]->instances[$this->temp_mod_id]->restore))) {
  6546. //Prepend XML standard header to info gathered
  6547. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6548. //Call to xmlize for this portion of xml data (one MOD)
  6549. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6550. $data = xmlize($xml_data,0);
  6551. //echo strftime ("%X",time())."<p>"; //Debug
  6552. //traverse_xmlize($data); //Debug
  6553. //print_object ($GLOBALS['traverse_array']); //Debug
  6554. //$GLOBALS['traverse_array']=""; //Debug
  6555. //Now, save data to db. We'll use it later
  6556. //Get id and modtype from data
  6557. $mod_id = $data["MOD"]["#"]["ID"]["0"]["#"];
  6558. $mod_type = $data["MOD"]["#"]["MODTYPE"]["0"]["#"];
  6559. //Only if we've selected to restore it
  6560. if (!empty($this->preferences->mods[$mod_type]->restore)) {
  6561. //Save to db
  6562. $status = backup_putid($this->preferences->backup_unique_code,$mod_type,$mod_id,
  6563. null,$data);
  6564. //echo "<p>id: ".$mod_id."-".$mod_type." len.: ".strlen($sla_mod_temp)." to_db: ".$status."<p>"; //Debug
  6565. //Create returning info
  6566. $ret_info = new object();
  6567. $ret_info->id = $mod_id;
  6568. $ret_info->modtype = $mod_type;
  6569. $this->info[] = $ret_info;
  6570. }
  6571. } else {
  6572. debugging("Info: skipping $this->temp_mod_type activity with mod id: $this->temp_mod_id. Not selected for restore", DEBUG_DEVELOPER);
  6573. }
  6574. //Reset current mod_type and mod_id
  6575. unset($this->temp_mod_type);
  6576. unset($this->temp_mod_id);
  6577. //Reset temp
  6578. unset($this->temp);
  6579. }
  6580. /// Grab current mod id and type when available
  6581. if ($this->level == 5) {
  6582. if ($tagName == 'ID') {
  6583. $this->temp_mod_id = trim($this->content);
  6584. } else if ($tagName == 'MODTYPE') {
  6585. $this->temp_mod_type = trim($this->content);
  6586. }
  6587. }
  6588. }
  6589. //Stop parsing if todo = MODULES and tagName = MODULES (en of the tag, of course)
  6590. //Speed up a lot (avoid parse all)
  6591. if ($tagName == "MODULES" and $this->level == 3) {
  6592. $this->finished = true;
  6593. }
  6594. //Clear things
  6595. $this->tree[$this->level] = "";
  6596. $this->level--;
  6597. $this->content = "";
  6598. }
  6599. //This is the endTag handler we use where we are reading the logs zone (todo="LOGS")
  6600. function endElementLogs($parser, $tagName) {
  6601. //Check if we are into LOGS zone
  6602. if ($this->tree[3] == "LOGS") {
  6603. //if (trim($this->content)) //Debug
  6604. // echo "C".str_repeat("&nbsp;",($this->level+2)*2).$this->getContents()."<br />\n"; //Debug
  6605. //echo $this->level.str_repeat("&nbsp;",$this->level*2)."&lt;/".$tagName."&gt;<br />\n"; //Debug
  6606. //Acumulate data to info (content + close tag)
  6607. //Reconvert: strip htmlchars again and trim to generate xml data
  6608. if (!isset($this->temp)) {
  6609. $this->temp = "";
  6610. }
  6611. $this->temp .= htmlspecialchars(trim($this->content))."</".$tagName.">";
  6612. //If we've finished a log, xmlize it an save to db
  6613. if (($this->level == 4) and ($tagName == "LOG")) {
  6614. //Prepend XML standard header to info gathered
  6615. $xml_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".$this->temp;
  6616. //Call to xmlize for this portion of xml data (one LOG)
  6617. //echo "-XMLIZE: ".strftime ("%X",time()),"-"; //Debug
  6618. $data = xmlize($xml_data,0);
  6619. //echo strftime ("%X",time())."<p>"; //Debug
  6620. //traverse_xmlize($data); //Debug
  6621. //print_object ($GLOBALS['traverse_array']); //Debug
  6622. //$GLOBALS['traverse_array']=""; //Debug
  6623. //Now, save data to db. We'll use it later
  6624. //Get id and modtype from data
  6625. $log_id = $data["LOG"]["#"]["ID"]["0"]["#"];
  6626. $log_module = $data["LOG"]["#"]["MODULE"]["0"]["#"];
  6627. //We only save log entries from backup file if they are:
  6628. // - Course logs
  6629. // - User logs
  6630. // - Module logs about one restored module
  6631. if ($log_module == "course" or
  6632. $log_module == "user" or
  6633. $this->preferences->mods[$log_module]->restore) {
  6634. //Increment counter
  6635. $this->counter++;
  6636. //Save to db
  6637. $status = backup_putid($this->preferences->backup_unique_code,"log",$log_id,
  6638. null,$data);
  6639. //echo "<p>id: ".$mod_id."-".$mod_type." len.: ".strlen($sla_mod_temp)." to_db: ".$status."<p>"; //Debug
  6640. //Create returning info
  6641. $this->info = $this->counter;
  6642. }
  6643. //Reset temp
  6644. unset($this->temp);
  6645. }
  6646. }
  6647. //Stop parsing if todo = LOGS and tagName = LOGS (en of the tag, of course)
  6648. //Speed up a lot (avoid parse all)
  6649. if ($tagName == "LOGS" and $this->level == 3) {
  6650. $this->finished = true;
  6651. $this->counter = 0;
  6652. }
  6653. //Clear things
  6654. $this->tree[$this->level] = "";
  6655. $this->level--;
  6656. $this->content = "";
  6657. }
  6658. //This is the endTag default handler we use when todo is undefined
  6659. function endElement($parser, $tagName) {
  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. //Clear things
  6664. $this->tree[$this->level] = "";
  6665. $this->level--;
  6666. $this->content = "";
  6667. }
  6668. //This is the handler to read data contents (simple accumule it)
  6669. function characterData($parser, $data) {
  6670. $this->content .= $data;
  6671. }
  6672. }
  6673. //This function executes the MoodleParser
  6674. function restore_read_xml ($xml_file,$todo,$preferences) {
  6675. global $CFG;
  6676. $status = true;
  6677. /// If enabled in the site, use split files instead of original moodle.xml file
  6678. /// This will speed parsing speed upto 20x.
  6679. if (!empty($CFG->experimentalsplitrestore)) {
  6680. /// Use splite file, else nothing to process (saves one full parsing for each non-existing todo)
  6681. $splitfile= dirname($xml_file) . '/' . strtolower('split_' . $todo . '.xml');
  6682. if (file_exists($splitfile)) {
  6683. $xml_file = $splitfile;
  6684. debugging("Info: todo=$todo, using split file", DEBUG_DEVELOPER);
  6685. } else {
  6686. /// For some todos, that are used in earlier restore steps (restore_precheck(), restore_form...
  6687. /// allow fallback to monolithic moodle.xml. Those todos are at the beggining of the xml, so
  6688. /// it doesn't hurts too much.
  6689. if ($todo == 'INFO' || $todo == 'COURSE_HEADER' || $todo == 'ROLES') {
  6690. debugging("Info: todo=$todo, no split file. Fallback to moodle.xml", DEBUG_DEVELOPER);
  6691. } else {
  6692. debugging("Info: todo=$todo, no split file. Parse skipped", DEBUG_DEVELOPER);
  6693. return true;
  6694. }
  6695. }
  6696. }
  6697. $xml_parser = xml_parser_create('UTF-8');
  6698. $moodle_parser = new MoodleParser();
  6699. $moodle_parser->todo = $todo;
  6700. $moodle_parser->preferences = $preferences;
  6701. xml_set_object($xml_parser,$moodle_parser);
  6702. //Depending of the todo we use some element_handler or another
  6703. if ($todo == "INFO") {
  6704. xml_set_element_handler($xml_parser, "startElementInfo", "endElementInfo");
  6705. } else if ($todo == "ROLES") {
  6706. xml_set_element_handler($xml_parser, "startElementRoles", "endElementRoles");
  6707. } else if ($todo == "COURSE_HEADER") {
  6708. xml_set_element_handler($xml_parser, "startElementCourseHeader", "endElementCourseHeader");
  6709. } else if ($todo == 'BLOCKS') {
  6710. xml_set_element_handler($xml_parser, "startElementBlocks", "endElementBlocks");
  6711. } else if ($todo == "SECTIONS") {
  6712. xml_set_element_handler($xml_parser, "startElementSections", "endElementSections");
  6713. } else if ($todo == 'FORMATDATA') {
  6714. xml_set_element_handler($xml_parser, "startElementFormatData", "endElementFormatData");
  6715. } else if ($todo == "METACOURSE") {
  6716. xml_set_element_handler($xml_parser, "startElementMetacourse", "endElementMetacourse");
  6717. } else if ($todo == "GRADEBOOK") {
  6718. if ($preferences->backup_version > 2007090500) {
  6719. xml_set_element_handler($xml_parser, "startElementGradebook", "endElementGradebook");
  6720. } else {
  6721. xml_set_element_handler($xml_parser, "startElementOldGradebook", "endElementOldGradebook");
  6722. }
  6723. } else if ($todo == "USERS") {
  6724. xml_set_element_handler($xml_parser, "startElementUsers", "endElementUsers");
  6725. } else if ($todo == "MESSAGES") {
  6726. xml_set_element_handler($xml_parser, "startElementMessages", "endElementMessages");
  6727. } else if ($todo == "BLOGS") {
  6728. xml_set_element_handler($xml_parser, "startElementBlogs", "endElementBlogs");
  6729. } else if ($todo == "QUESTIONS") {
  6730. xml_set_element_handler($xml_parser, "startElementQuestions", "endElementQuestions");
  6731. } else if ($todo == "SCALES") {
  6732. xml_set_element_handler($xml_parser, "startElementScales", "endElementScales");
  6733. } else if ($todo == "GROUPS") {
  6734. xml_set_element_handler($xml_parser, "startElementGroups", "endElementGroups");
  6735. } else if ($todo == "GROUPINGS") {
  6736. xml_set_element_handler($xml_parser, "startElementGroupings", "endElementGroupings");
  6737. } else if ($todo == "GROUPINGSGROUPS") {
  6738. xml_set_element_handler($xml_parser, "startElementGroupingsGroups", "endElementGroupingsGroups");
  6739. } else if ($todo == "EVENTS") {
  6740. xml_set_element_handler($xml_parser, "startElementEvents", "endElementEvents");
  6741. } else if ($todo == "MODULES") {
  6742. xml_set_element_handler($xml_parser, "startElementModules", "endElementModules");
  6743. } else if ($todo == "LOGS") {
  6744. xml_set_element_handler($xml_parser, "startElementLogs", "endElementLogs");
  6745. } else {
  6746. //Define default handlers (must no be invoked when everything become finished)
  6747. xml_set_element_handler($xml_parser, "startElementInfo", "endElementInfo");
  6748. }
  6749. xml_set_character_data_handler($xml_parser, "characterData");
  6750. $fp = fopen($xml_file,"r")
  6751. or $status = false;
  6752. if ($status) {
  6753. // MDL-9290 performance improvement on reading large xml
  6754. $lasttime = time(); // crmas
  6755. while ($data = fread($fp, 8192) and !$moodle_parser->finished) {
  6756. if ((time() - $lasttime) > 5) {
  6757. $lasttime = time();
  6758. backup_flush(1);
  6759. }
  6760. xml_parse($xml_parser, $data, feof($fp))
  6761. or die(sprintf("XML error: %s at line %d",
  6762. xml_error_string(xml_get_error_code($xml_parser)),
  6763. xml_get_current_line_number($xml_parser)));
  6764. }
  6765. fclose($fp);
  6766. }
  6767. //Get info from parser
  6768. $info = $moodle_parser->info;
  6769. //Clear parser mem
  6770. xml_parser_free($xml_parser);
  6771. if ($status && !empty($info)) {
  6772. return $info;
  6773. } else {
  6774. return $status;
  6775. }
  6776. }
  6777. /**
  6778. * @param string $errorstr passed by reference, if silent is true,
  6779. * errorstr will be populated and this function will return false rather than calling error() or notify()
  6780. * @param boolean $noredirect (optional) if this is passed, this function will not print continue, or
  6781. * redirect to the next step in the restore process, instead will return $backup_unique_code
  6782. */
  6783. function restore_precheck($id,$file,&$errorstr,$noredirect=false) {
  6784. global $CFG, $SESSION;
  6785. //Prepend dataroot to variable to have the absolute path
  6786. $file = $CFG->dataroot."/".$file;
  6787. if (!defined('RESTORE_SILENTLY')) {
  6788. //Start the main table
  6789. echo "<table cellpadding=\"5\">";
  6790. echo "<tr><td>";
  6791. //Start the mail ul
  6792. echo "<ul>";
  6793. }
  6794. //Check the file exists
  6795. if (!is_file($file)) {
  6796. if (!defined('RESTORE_SILENTLY')) {
  6797. error ("File not exists ($file)");
  6798. } else {
  6799. $errorstr = "File not exists ($file)";
  6800. return false;
  6801. }
  6802. }
  6803. //Check the file name ends with .zip
  6804. if (!substr($file,-4) == ".zip") {
  6805. if (!defined('RESTORE_SILENTLY')) {
  6806. error ("File has an incorrect extension");
  6807. } else {
  6808. $errorstr = 'File has an incorrect extension';
  6809. return false;
  6810. }
  6811. }
  6812. //Now calculate the unique_code for this restore
  6813. $backup_unique_code = time();
  6814. //Now check and create the backup dir (if it doesn't exist)
  6815. if (!defined('RESTORE_SILENTLY')) {
  6816. echo "<li>".get_string("creatingtemporarystructures").'</li>';
  6817. }
  6818. $status = check_and_create_backup_dir($backup_unique_code);
  6819. //Empty dir
  6820. if ($status) {
  6821. $status = clear_backup_dir($backup_unique_code);
  6822. }
  6823. //Now delete old data and directories under dataroot/temp/backup
  6824. if ($status) {
  6825. if (!defined('RESTORE_SILENTLY')) {
  6826. echo "<li>".get_string("deletingolddata").'</li>';
  6827. }
  6828. $status = backup_delete_old_data();
  6829. }
  6830. //Now copy he zip file to dataroot/temp/backup/backup_unique_code
  6831. if ($status) {
  6832. if (!defined('RESTORE_SILENTLY')) {
  6833. echo "<li>".get_string("copyingzipfile").'</li>';
  6834. }
  6835. if (! $status = backup_copy_file($file,$CFG->dataroot."/temp/backup/".$backup_unique_code."/".basename($file))) {
  6836. if (!defined('RESTORE_SILENTLY')) {
  6837. notify("Error copying backup file. Invalid name or bad perms.");
  6838. } else {
  6839. $errorstr = "Error copying backup file. Invalid name or bad perms";
  6840. return false;
  6841. }
  6842. }
  6843. }
  6844. //Now unzip the file
  6845. if ($status) {
  6846. if (!defined('RESTORE_SILENTLY')) {
  6847. echo "<li>".get_string("unzippingbackup").'</li>';
  6848. }
  6849. if (! $status = restore_unzip ($CFG->dataroot."/temp/backup/".$backup_unique_code."/".basename($file))) {
  6850. if (!defined('RESTORE_SILENTLY')) {
  6851. notify("Error unzipping backup file. Invalid zip file.");
  6852. } else {
  6853. $errorstr = "Error unzipping backup file. Invalid zip file.";
  6854. return false;
  6855. }
  6856. }
  6857. }
  6858. //Check for Blackboard backups and convert
  6859. if ($status){
  6860. require_once("$CFG->dirroot/backup/bb/restore_bb.php");
  6861. if (!defined('RESTORE_SILENTLY')) {
  6862. echo "<li>".get_string("checkingforbbexport").'</li>';
  6863. }
  6864. $status = blackboard_convert($CFG->dataroot."/temp/backup/".$backup_unique_code);
  6865. }
  6866. //Now check for the moodle.xml file
  6867. if ($status) {
  6868. $xml_file = $CFG->dataroot."/temp/backup/".$backup_unique_code."/moodle.xml";
  6869. if (!defined('RESTORE_SILENTLY')) {
  6870. echo "<li>".get_string("checkingbackup").'</li>';
  6871. }
  6872. if (! $status = restore_check_moodle_file ($xml_file)) {
  6873. if (!is_file($xml_file)) {
  6874. $errorstr = 'Error checking backup file. moodle.xml not found at root level of zip file.';
  6875. } else {
  6876. $errorstr = 'Error checking backup file. moodle.xml is incorrect or corrupted.';
  6877. }
  6878. if (!defined('RESTORE_SILENTLY')) {
  6879. notify($errorstr);
  6880. } else {
  6881. return false;
  6882. }
  6883. }
  6884. }
  6885. $info = "";
  6886. $course_header = "";
  6887. //Now read the info tag (all)
  6888. if ($status) {
  6889. if (!defined('RESTORE_SILENTLY')) {
  6890. echo "<li>".get_string("readinginfofrombackup").'</li>';
  6891. }
  6892. //Reading info from file
  6893. $info = restore_read_xml_info ($xml_file);
  6894. //Reading course_header from file
  6895. $course_header = restore_read_xml_course_header ($xml_file);
  6896. if(!is_object($course_header)){
  6897. // ensure we fail if there is no course header
  6898. $course_header = false;
  6899. }
  6900. }
  6901. if (!defined('RESTORE_SILENTLY')) {
  6902. //End the main ul
  6903. echo "</ul>\n";
  6904. //End the main table
  6905. echo "</td></tr>";
  6906. echo "</table>";
  6907. }
  6908. //We compare Moodle's versions
  6909. if ($status && $CFG->version < $info->backup_moodle_version) {
  6910. $message = new object();
  6911. $message->serverversion = $CFG->version;
  6912. $message->serverrelease = $CFG->release;
  6913. $message->backupversion = $info->backup_moodle_version;
  6914. $message->backuprelease = $info->backup_moodle_release;
  6915. print_simple_box(get_string('noticenewerbackup','',$message), "center", "70%", '', "20", "noticebox");
  6916. }
  6917. //Now we print in other table, the backup and the course it contains info
  6918. if ($info and $course_header and $status) {
  6919. //First, the course info
  6920. if (!defined('RESTORE_SILENTLY')) {
  6921. $status = restore_print_course_header($course_header);
  6922. }
  6923. //Now, the backup info
  6924. if ($status) {
  6925. if (!defined('RESTORE_SILENTLY')) {
  6926. $status = restore_print_info($info);
  6927. }
  6928. }
  6929. }
  6930. //Save course header and info into php session
  6931. if ($status) {
  6932. $SESSION->info = $info;
  6933. $SESSION->course_header = $course_header;
  6934. }
  6935. //Finally, a little form to continue
  6936. //with some hidden fields
  6937. if ($status) {
  6938. if (!defined('RESTORE_SILENTLY')) {
  6939. echo "<br /><div style='text-align:center'>";
  6940. $hidden["backup_unique_code"] = $backup_unique_code;
  6941. $hidden["launch"] = "form";
  6942. $hidden["file"] = $file;
  6943. $hidden["id"] = $id;
  6944. print_single_button("restore.php", $hidden, get_string("continue"),"post");
  6945. echo "</div>";
  6946. }
  6947. else {
  6948. if (empty($noredirect)) {
  6949. // in 2.0 we must not print "Continue" redirect link here, because ppl click on it and the execution gets interrupted on next page!!!
  6950. // imo RESTORE_SILENTLY is an ugly hack :-P
  6951. $sillystr = get_string('donotclickcontinue');
  6952. redirect($CFG->wwwroot.'/backup/restore.php?backup_unique_code='.$backup_unique_code.'&launch=form&file='.$file.'&id='.$id, $sillystr, 0);
  6953. } else {
  6954. return $backup_unique_code;
  6955. }
  6956. }
  6957. }
  6958. if (!$status) {
  6959. if (!defined('RESTORE_SILENTLY')) {
  6960. error ("An error has ocurred");
  6961. } else {
  6962. $errorstr = "An error has occured"; // helpful! :P
  6963. return false;
  6964. }
  6965. }
  6966. return true;
  6967. }
  6968. function restore_setup_for_check(&$restore,$backup_unique_code) {
  6969. global $SESSION;
  6970. $restore->backup_unique_code=$backup_unique_code;
  6971. $restore->users = 2; // yuk
  6972. // we set these from restore object on silent restore and from info (backup) object on import
  6973. $restore->course_files = isset($SESSION->restore->restore_course_files) ? $SESSION->restore->restore_course_files : $SESSION->info->backup_course_files;
  6974. $restore->site_files = isset($SESSION->restore->restore_site_files) ? $SESSION->restore->restore_site_files : $SESSION->info->backup_site_files;
  6975. if ($allmods = get_records("modules")) {
  6976. foreach ($allmods as $mod) {
  6977. $modname = $mod->name;
  6978. $var = "restore_".$modname;
  6979. //Now check that we have that module info in the backup file
  6980. if (isset($SESSION->info->mods[$modname]) && $SESSION->info->mods[$modname]->backup == "true") {
  6981. $restore->$var = 1;
  6982. }
  6983. }
  6984. }
  6985. // Calculate all session objects checksum and store them in session too
  6986. // so restore_execute.html (used by manual restore and import) will be
  6987. // able to detect any problem in session info.
  6988. restore_save_session_object_checksums($restore, $SESSION->info, $SESSION->course_header);
  6989. return true;
  6990. }
  6991. /**
  6992. * Save the checksum of the 3 main in-session restore objects (restore, info, course_header)
  6993. * so restore_execute.html will be able to check that all them have arrived correctly, without
  6994. * losing data for any type of session size limit/error. MDL-18469. Used both by manual restore
  6995. * and import
  6996. */
  6997. function restore_save_session_object_checksums($restore, $info, $course_header) {
  6998. global $SESSION;
  6999. $restore_checksums = array();
  7000. $restore_checksums['info'] = md5(serialize($info));
  7001. $restore_checksums['course_header'] = md5(serialize($course_header));
  7002. $restore_checksums['restore'] = md5(serialize($restore));
  7003. $SESSION->restore_checksums = $restore_checksums;
  7004. }
  7005. function backup_to_restore_array($backup,$k=0) {
  7006. if (is_array($backup) ) {
  7007. $restore = array();
  7008. foreach ($backup as $key => $value) {
  7009. $newkey = str_replace('backup','restore',$key);
  7010. $restore[$newkey] = backup_to_restore_array($value,$key);
  7011. }
  7012. }
  7013. else if (is_object($backup)) {
  7014. $restore = new stdClass();
  7015. $tmp = get_object_vars($backup);
  7016. foreach ($tmp as $key => $value) {
  7017. $newkey = str_replace('backup','restore',$key);
  7018. $restore->$newkey = backup_to_restore_array($value,$key);
  7019. }
  7020. }
  7021. else {
  7022. $newkey = str_replace('backup','restore',$k);
  7023. $restore = $backup;
  7024. }
  7025. return $restore;
  7026. }
  7027. /**
  7028. * compatibility function
  7029. * checks for per-instance backups AND
  7030. * older per-module backups
  7031. * and returns whether userdata has been selected.
  7032. */
  7033. function restore_userdata_selected($restore,$modname,$modid) {
  7034. // check first for per instance array
  7035. if (!empty($restore->mods[$modname]->granular)) { // supports per instance
  7036. return array_key_exists($modid,$restore->mods[$modname]->instances)
  7037. && !empty($restore->mods[$modname]->instances[$modid]->userinfo);
  7038. }
  7039. //print_object($restore->mods[$modname]);
  7040. return !empty($restore->mods[$modname]->userinfo);
  7041. }
  7042. function restore_execute(&$restore,$info,$course_header,&$errorstr) {
  7043. global $CFG, $USER;
  7044. $status = true;
  7045. //Checks for the required files/functions to restore every module
  7046. //and include them
  7047. if ($allmods = get_records("modules") ) {
  7048. foreach ($allmods as $mod) {
  7049. $modname = $mod->name;
  7050. $modfile = "$CFG->dirroot/mod/$modname/restorelib.php";
  7051. //If file exists and we have selected to restore that type of module
  7052. if ((file_exists($modfile)) and !empty($restore->mods[$modname]) and ($restore->mods[$modname]->restore)) {
  7053. include_once($modfile);
  7054. }
  7055. }
  7056. }
  7057. if (!defined('RESTORE_SILENTLY')) {
  7058. //Start the main table
  7059. echo "<table cellpadding=\"5\">";
  7060. echo "<tr><td>";
  7061. //Start the main ul
  7062. echo "<ul>";
  7063. }
  7064. //Location of the xml file
  7065. $xml_file = $CFG->dataroot."/temp/backup/".$restore->backup_unique_code."/moodle.xml";
  7066. // Re-assure xml file is in place before any further process
  7067. if (! $status = restore_check_moodle_file($xml_file)) {
  7068. if (!is_file($xml_file)) {
  7069. $errorstr = 'Error checking backup file. moodle.xml not found. Session problem?';
  7070. } else {
  7071. $errorstr = 'Error checking backup file. moodle.xml is incorrect or corrupted. Session problem?';
  7072. }
  7073. if (!defined('RESTORE_SILENTLY')) {
  7074. notify($errorstr);
  7075. }
  7076. return false;
  7077. }
  7078. //Preprocess the moodle.xml file spliting into smaller chucks (modules, users, logs...)
  7079. //for optimal parsing later in the restore process.
  7080. if (!empty($CFG->experimentalsplitrestore)) {
  7081. if (!defined('RESTORE_SILENTLY')) {
  7082. echo '<li>'.get_string('preprocessingbackupfile') . '</li>';
  7083. }
  7084. //First of all, split moodle.xml into handy files
  7085. if (!restore_split_xml ($xml_file, $restore)) {
  7086. $errorstr = "Error proccessing moodle.xml file. Process ended.";
  7087. if (!defined('RESTORE_SILENTLY')) {
  7088. notify($errorstr);
  7089. }
  7090. return false;
  7091. }
  7092. }
  7093. //If we've selected to restore into new course
  7094. //create it (course)
  7095. //Saving conversion id variables into backup_tables
  7096. if ($restore->restoreto == RESTORETO_NEW_COURSE) {
  7097. if (!defined('RESTORE_SILENTLY')) {
  7098. echo '<li>'.get_string('creatingnewcourse') . '</li>';
  7099. }
  7100. $oldidnumber = $course_header->course_idnumber;
  7101. if (!$status = restore_create_new_course($restore,$course_header)) {
  7102. if (!defined('RESTORE_SILENTLY')) {
  7103. notify("Error while creating the new empty course.");
  7104. } else {
  7105. $errorstr = "Error while creating the new empty course.";
  7106. return false;
  7107. }
  7108. }
  7109. //Print course fullname and shortname and category
  7110. if ($status) {
  7111. if (!defined('RESTORE_SILENTLY')) {
  7112. echo "<ul>";
  7113. echo "<li>".$course_header->course_fullname." (".$course_header->course_shortname.")".'</li>';
  7114. echo "<li>".get_string("category").": ".$course_header->category->name.'</li>';
  7115. if (!empty($oldidnumber)) {
  7116. echo "<li>".get_string("nomoreidnumber","moodle",$oldidnumber)."</li>";
  7117. }
  7118. echo "</ul>";
  7119. //Put the destination course_id
  7120. }
  7121. $restore->course_id = $course_header->course_id;
  7122. }
  7123. if ($status = restore_open_html($restore,$course_header)){
  7124. if (!defined('RESTORE_SILENTLY')) {
  7125. echo "<li>Creating the Restorelog.html in the course backup folder</li>";
  7126. }
  7127. }
  7128. } else {
  7129. $course = get_record("course","id",$restore->course_id);
  7130. if ($course) {
  7131. if (!defined('RESTORE_SILENTLY')) {
  7132. echo "<li>".get_string("usingexistingcourse");
  7133. echo "<ul>";
  7134. echo "<li>".get_string("from").": ".$course_header->course_fullname." (".$course_header->course_shortname.")".'</li>';
  7135. echo "<li>".get_string("to").": ". format_string($course->fullname) ." (".format_string($course->shortname).")".'</li>';
  7136. if (($restore->deleting)) {
  7137. echo "<li>".get_string("deletingexistingcoursedata").'</li>';
  7138. } else {
  7139. echo "<li>".get_string("addingdatatoexisting").'</li>';
  7140. }
  7141. echo "</ul></li>";
  7142. }
  7143. //If we have selected to restore deleting, we do it now.
  7144. if ($restore->deleting) {
  7145. if (!defined('RESTORE_SILENTLY')) {
  7146. echo "<li>".get_string("deletingolddata").'</li>';
  7147. }
  7148. $status = remove_course_contents($restore->course_id,false) and
  7149. delete_dir_contents($CFG->dataroot."/".$restore->course_id,"backupdata");
  7150. if ($status) {
  7151. //Now , this situation is equivalent to the "restore to new course" one (we
  7152. //have a course record and nothing more), so define it as "to new course"
  7153. $restore->restoreto = RESTORETO_NEW_COURSE;
  7154. } else {
  7155. if (!defined('RESTORE_SILENTLY')) {
  7156. notify("An error occurred while deleting some of the course contents.");
  7157. } else {
  7158. $errrostr = "An error occurred while deleting some of the course contents.";
  7159. return false;
  7160. }
  7161. }
  7162. }
  7163. } else {
  7164. if (!defined('RESTORE_SILENTLY')) {
  7165. notify("Error opening existing course.");
  7166. $status = false;
  7167. } else {
  7168. $errorstr = "Error opening existing course.";
  7169. return false;
  7170. }
  7171. }
  7172. }
  7173. //Now create users as needed
  7174. if ($status and ($restore->users == 0 or $restore->users == 1)) {
  7175. if (!defined('RESTORE_SILENTLY')) {
  7176. echo "<li>".get_string("creatingusers")."<br />";
  7177. }
  7178. if (!$status = restore_create_users($restore,$xml_file)) {
  7179. if (!defined('RESTORE_SILENTLY')) {
  7180. notify("Could not restore users.");
  7181. } else {
  7182. $errorstr = "Could not restore users.";
  7183. return false;
  7184. }
  7185. }
  7186. //Now print info about the work done
  7187. if ($status) {
  7188. $recs = get_records_sql("select old_id, new_id from {$CFG->prefix}backup_ids
  7189. where backup_code = '$restore->backup_unique_code' and
  7190. table_name = 'user'");
  7191. //We've records
  7192. if ($recs) {
  7193. $new_count = 0;
  7194. $exists_count = 0;
  7195. $student_count = 0;
  7196. $teacher_count = 0;
  7197. $counter = 0;
  7198. //Iterate, filling counters
  7199. foreach ($recs as $rec) {
  7200. //Get full record, using backup_getids
  7201. $record = backup_getid($restore->backup_unique_code,"user",$rec->old_id);
  7202. if (strpos($record->info,"new") !== false) {
  7203. $new_count++;
  7204. }
  7205. if (strpos($record->info,"exists") !== false) {
  7206. $exists_count++;
  7207. }
  7208. if (strpos($record->info,"student") !== false) {
  7209. $student_count++;
  7210. } else if (strpos($record->info,"teacher") !== false) {
  7211. $teacher_count++;
  7212. }
  7213. //Do some output
  7214. $counter++;
  7215. if ($counter % 10 == 0) {
  7216. if (!defined('RESTORE_SILENTLY')) {
  7217. echo ".";
  7218. if ($counter % 200 == 0) {
  7219. echo "<br />";
  7220. }
  7221. }
  7222. backup_flush(300);
  7223. }
  7224. }
  7225. if (!defined('RESTORE_SILENTLY')) {
  7226. //Now print information gathered
  7227. echo " (".get_string("new").": ".$new_count.", ".get_string("existing").": ".$exists_count.")";
  7228. echo "<ul>";
  7229. echo "<li>".get_string("students").": ".$student_count.'</li>';
  7230. echo "<li>".get_string("teachers").": ".$teacher_count.'</li>';
  7231. echo "</ul>";
  7232. }
  7233. } else {
  7234. if (!defined('RESTORE_SILENTLY')) {
  7235. notify("No users were found!");
  7236. } // no need to return false here, it's recoverable.
  7237. }
  7238. }
  7239. if (!defined('RESTORE_SILENTLY')) {
  7240. echo "</li>";
  7241. }
  7242. }
  7243. //Now create groups as needed
  7244. if ($status and ($restore->groups == RESTORE_GROUPS_ONLY or $restore->groups == RESTORE_GROUPS_GROUPINGS)) {
  7245. if (!defined('RESTORE_SILENTLY')) {
  7246. echo "<li>".get_string("creatinggroups");
  7247. }
  7248. if (!$status = restore_create_groups($restore,$xml_file)) {
  7249. if (!defined('RESTORE_SILENTLY')) {
  7250. notify("Could not restore groups!");
  7251. } else {
  7252. $errorstr = "Could not restore groups!";
  7253. return false;
  7254. }
  7255. }
  7256. if (!defined('RESTORE_SILENTLY')) {
  7257. echo '</li>';
  7258. }
  7259. }
  7260. //Now create groupings as needed
  7261. if ($status and ($restore->groups == RESTORE_GROUPINGS_ONLY or $restore->groups == RESTORE_GROUPS_GROUPINGS)) {
  7262. if (!defined('RESTORE_SILENTLY')) {
  7263. echo "<li>".get_string("creatinggroupings");
  7264. }
  7265. if (!$status = restore_create_groupings($restore,$xml_file)) {
  7266. if (!defined('RESTORE_SILENTLY')) {
  7267. notify("Could not restore groupings!");
  7268. } else {
  7269. $errorstr = "Could not restore groupings!";
  7270. return false;
  7271. }
  7272. }
  7273. if (!defined('RESTORE_SILENTLY')) {
  7274. echo '</li>';
  7275. }
  7276. }
  7277. //Now create groupingsgroups as needed
  7278. if ($status and $restore->groups == RESTORE_GROUPS_GROUPINGS) {
  7279. if (!defined('RESTORE_SILENTLY')) {
  7280. echo "<li>".get_string("creatinggroupingsgroups");
  7281. }
  7282. if (!$status = restore_create_groupings_groups($restore,$xml_file)) {
  7283. if (!defined('RESTORE_SILENTLY')) {
  7284. notify("Could not restore groups in groupings!");
  7285. } else {
  7286. $errorstr = "Could not restore groups in groupings!";
  7287. return false;
  7288. }
  7289. }
  7290. if (!defined('RESTORE_SILENTLY')) {
  7291. echo '</li>';
  7292. }
  7293. }
  7294. //Now create the course_sections and their associated course_modules
  7295. //we have to do this after groups and groupings are restored, because we need the new groupings id
  7296. if ($status) {
  7297. //Into new course
  7298. if ($restore->restoreto == RESTORETO_NEW_COURSE) {
  7299. if (!defined('RESTORE_SILENTLY')) {
  7300. echo "<li>".get_string("creatingsections");
  7301. }
  7302. if (!$status = restore_create_sections($restore,$xml_file)) {
  7303. if (!defined('RESTORE_SILENTLY')) {
  7304. notify("Error creating sections in the existing course.");
  7305. } else {
  7306. $errorstr = "Error creating sections in the existing course.";
  7307. return false;
  7308. }
  7309. }
  7310. if (!defined('RESTORE_SILENTLY')) {
  7311. echo '</li>';
  7312. }
  7313. //Into existing course
  7314. } else if ($restore->restoreto != RESTORETO_NEW_COURSE) {
  7315. if (!defined('RESTORE_SILENTLY')) {
  7316. echo "<li>".get_string("checkingsections");
  7317. }
  7318. if (!$status = restore_create_sections($restore,$xml_file)) {
  7319. if (!defined('RESTORE_SILENTLY')) {
  7320. notify("Error creating sections in the existing course.");
  7321. } else {
  7322. $errorstr = "Error creating sections in the existing course.";
  7323. return false;
  7324. }
  7325. }
  7326. if (!defined('RESTORE_SILENTLY')) {
  7327. echo '</li>';
  7328. }
  7329. //Error
  7330. } else {
  7331. if (!defined('RESTORE_SILENTLY')) {
  7332. notify("Neither a new course or an existing one was specified.");
  7333. $status = false;
  7334. } else {
  7335. $errorstr = "Neither a new course or an existing one was specified.";
  7336. return false;
  7337. }
  7338. }
  7339. }
  7340. //Now create metacourse info
  7341. if ($status and $restore->metacourse) {
  7342. //Only to new courses!
  7343. if ($restore->restoreto == RESTORETO_NEW_COURSE) {
  7344. if (!defined('RESTORE_SILENTLY')) {
  7345. echo "<li>".get_string("creatingmetacoursedata");
  7346. }
  7347. if (!$status = restore_create_metacourse($restore,$xml_file)) {
  7348. if (!defined('RESTORE_SILENTLY')) {
  7349. notify("Error creating metacourse in the course.");
  7350. } else {
  7351. $errorstr = "Error creating metacourse in the course.";
  7352. return false;
  7353. }
  7354. }
  7355. if (!defined('RESTORE_SILENTLY')) {
  7356. echo '</li>';
  7357. }
  7358. }
  7359. }
  7360. //Now create categories and questions as needed
  7361. if ($status) {
  7362. include_once("$CFG->dirroot/question/restorelib.php");
  7363. if (!defined('RESTORE_SILENTLY')) {
  7364. echo "<li>".get_string("creatingcategoriesandquestions");
  7365. echo "<ul>";
  7366. }
  7367. if (!$status = restore_create_questions($restore,$xml_file)) {
  7368. if (!defined('RESTORE_SILENTLY')) {
  7369. notify("Could not restore categories and questions!");
  7370. } else {
  7371. $errorstr = "Could not restore categories and questions!";
  7372. return false;
  7373. }
  7374. }
  7375. if (!defined('RESTORE_SILENTLY')) {
  7376. echo "</ul></li>";
  7377. }
  7378. }
  7379. //Now create user_files as needed
  7380. if ($status and ($restore->user_files)) {
  7381. if (!defined('RESTORE_SILENTLY')) {
  7382. echo "<li>".get_string("copyinguserfiles");
  7383. }
  7384. if (!$status = restore_user_files($restore)) {
  7385. if (!defined('RESTORE_SILENTLY')) {
  7386. notify("Could not restore user files!");
  7387. } else {
  7388. $errorstr = "Could not restore user files!";
  7389. return false;
  7390. }
  7391. }
  7392. //If all is ok (and we have a counter)
  7393. if ($status and ($status !== true)) {
  7394. //Inform about user dirs created from backup
  7395. if (!defined('RESTORE_SILENTLY')) {
  7396. echo "<ul>";
  7397. echo "<li>".get_string("userzones").": ".$status;
  7398. echo "</li></ul>";
  7399. }
  7400. }
  7401. if (!defined('RESTORE_SILENTLY')) {
  7402. echo '</li>';
  7403. }
  7404. }
  7405. //Now create course files as needed
  7406. if ($status and ($restore->course_files)) {
  7407. if (!defined('RESTORE_SILENTLY')) {
  7408. echo "<li>".get_string("copyingcoursefiles");
  7409. }
  7410. if (!$status = restore_course_files($restore)) {
  7411. if (empty($status)) {
  7412. notify("Could not restore course files!");
  7413. } else {
  7414. $errorstr = "Could not restore course files!";
  7415. return false;
  7416. }
  7417. }
  7418. //If all is ok (and we have a counter)
  7419. if ($status and ($status !== true)) {
  7420. //Inform about user dirs created from backup
  7421. if (!defined('RESTORE_SILENTLY')) {
  7422. echo "<ul>";
  7423. echo "<li>".get_string("filesfolders").": ".$status.'</li>';
  7424. echo "</ul>";
  7425. }
  7426. }
  7427. if (!defined('RESTORE_SILENTLY')) {
  7428. echo "</li>";
  7429. }
  7430. }
  7431. //Now create site files as needed
  7432. if ($status and ($restore->site_files)) {
  7433. if (!defined('RESTORE_SILENTLY')) {
  7434. echo "<li>".get_string('copyingsitefiles');
  7435. }
  7436. if (!$status = restore_site_files($restore)) {
  7437. if (empty($status)) {
  7438. notify("Could not restore site files!");
  7439. } else {
  7440. $errorstr = "Could not restore site files!";
  7441. return false;
  7442. }
  7443. }
  7444. //If all is ok (and we have a counter)
  7445. if ($status and ($status !== true)) {
  7446. //Inform about user dirs created from backup
  7447. if (!defined('RESTORE_SILENTLY')) {
  7448. echo "<ul>";
  7449. echo "<li>".get_string("filesfolders").": ".$status.'</li>';
  7450. echo "</ul>";
  7451. }
  7452. }
  7453. if (!defined('RESTORE_SILENTLY')) {
  7454. echo "</li>";
  7455. }
  7456. }
  7457. //Now create messages as needed
  7458. if ($status and ($restore->messages)) {
  7459. if (!defined('RESTORE_SILENTLY')) {
  7460. echo "<li>".get_string("creatingmessagesinfo");
  7461. }
  7462. if (!$status = restore_create_messages($restore,$xml_file)) {
  7463. if (!defined('RESTORE_SILENTLY')) {
  7464. notify("Could not restore messages!");
  7465. } else {
  7466. $errorstr = "Could not restore messages!";
  7467. return false;
  7468. }
  7469. }
  7470. if (!defined('RESTORE_SILENTLY')) {
  7471. echo "</li>";
  7472. }
  7473. }
  7474. //Now create blogs as needed
  7475. if ($status and ($restore->blogs)) {
  7476. if (!defined('RESTORE_SILENTLY')) {
  7477. echo "<li>".get_string("creatingblogsinfo");
  7478. }
  7479. if (!$status = restore_create_blogs($restore,$xml_file)) {
  7480. if (!defined('RESTORE_SILENTLY')) {
  7481. notify("Could not restore blogs!");
  7482. } else {
  7483. $errorstr = "Could not restore blogs!";
  7484. return false;
  7485. }
  7486. }
  7487. if (!defined('RESTORE_SILENTLY')) {
  7488. echo "</li>";
  7489. }
  7490. }
  7491. //Now create scales as needed
  7492. if ($status) {
  7493. if (!defined('RESTORE_SILENTLY')) {
  7494. echo "<li>".get_string("creatingscales");
  7495. }
  7496. if (!$status = restore_create_scales($restore,$xml_file)) {
  7497. if (!defined('RESTORE_SILENTLY')) {
  7498. notify("Could not restore custom scales!");
  7499. } else {
  7500. $errorstr = "Could not restore custom scales!";
  7501. return false;
  7502. }
  7503. }
  7504. if (!defined('RESTORE_SILENTLY')) {
  7505. echo '</li>';
  7506. }
  7507. }
  7508. //Now create events as needed
  7509. if ($status) {
  7510. if (!defined('RESTORE_SILENTLY')) {
  7511. echo "<li>".get_string("creatingevents");
  7512. }
  7513. if (!$status = restore_create_events($restore,$xml_file)) {
  7514. if (!defined('RESTORE_SILENTLY')) {
  7515. notify("Could not restore course events!");
  7516. } else {
  7517. $errorstr = "Could not restore course events!";
  7518. return false;
  7519. }
  7520. }
  7521. if (!defined('RESTORE_SILENTLY')) {
  7522. echo '</li>';
  7523. }
  7524. }
  7525. //Now create course modules as needed
  7526. if ($status) {
  7527. if (!defined('RESTORE_SILENTLY')) {
  7528. echo "<li>".get_string("creatingcoursemodules");
  7529. }
  7530. if (!$status = restore_create_modules($restore,$xml_file)) {
  7531. if (!defined('RESTORE_SILENTLY')) {
  7532. notify("Could not restore modules!");
  7533. } else {
  7534. $errorstr = "Could not restore modules!";
  7535. return false;
  7536. }
  7537. }
  7538. if (!defined('RESTORE_SILENTLY')) {
  7539. echo '</li>';
  7540. }
  7541. }
  7542. //Bring back the course blocks -- do it AFTER the modules!!!
  7543. if ($status) {
  7544. //If we are deleting and bringing into a course or making a new course, same situation
  7545. if ($restore->restoreto == RESTORETO_CURRENT_DELETING ||
  7546. $restore->restoreto == RESTORETO_EXISTING_DELETING ||
  7547. $restore->restoreto == RESTORETO_NEW_COURSE) {
  7548. if (!defined('RESTORE_SILENTLY')) {
  7549. echo '<li>'.get_string('creatingblocks');
  7550. }
  7551. $course_header->blockinfo = !empty($course_header->blockinfo) ? $course_header->blockinfo : NULL;
  7552. if (!$status = restore_create_blocks($restore, $info->backup_block_format, $course_header->blockinfo, $xml_file)) {
  7553. if (!defined('RESTORE_SILENTLY')) {
  7554. notify('Error while creating the course blocks');
  7555. } else {
  7556. $errorstr = "Error while creating the course blocks";
  7557. return false;
  7558. }
  7559. }
  7560. if (!defined('RESTORE_SILENTLY')) {
  7561. echo '</li>';
  7562. }
  7563. }
  7564. }
  7565. if ($status) {
  7566. //If we are deleting and bringing into a course or making a new course, same situation
  7567. if ($restore->restoreto == RESTORETO_CURRENT_DELETING ||
  7568. $restore->restoreto == RESTORETO_EXISTING_DELETING ||
  7569. $restore->restoreto == RESTORETO_NEW_COURSE) {
  7570. if (!defined('RESTORE_SILENTLY')) {
  7571. echo '<li>'.get_string('courseformatdata');
  7572. }
  7573. if (!$status = restore_set_format_data($restore, $xml_file)) {
  7574. $error = "Error while setting the course format data";
  7575. if (!defined('RESTORE_SILENTLY')) {
  7576. notify($error);
  7577. } else {
  7578. $errorstr=$error;
  7579. return false;
  7580. }
  7581. }
  7582. if (!defined('RESTORE_SILENTLY')) {
  7583. echo '</li>';
  7584. }
  7585. }
  7586. }
  7587. //Now create log entries as needed
  7588. if ($status and ($restore->logs)) {
  7589. if (!defined('RESTORE_SILENTLY')) {
  7590. echo "<li>".get_string("creatinglogentries");
  7591. }
  7592. if (!$status = restore_create_logs($restore,$xml_file)) {
  7593. if (!defined('RESTORE_SILENTLY')) {
  7594. notify("Could not restore logs!");
  7595. } else {
  7596. $errorstr = "Could not restore logs!";
  7597. return false;
  7598. }
  7599. }
  7600. if (!defined('RESTORE_SILENTLY')) {
  7601. echo '</li>';
  7602. }
  7603. }
  7604. //Now, if all is OK, adjust the instance field in course_modules !!
  7605. //this also calculates the final modinfo information so, after this,
  7606. //code needing it can be used (like role_assignments. MDL-13740)
  7607. if ($status) {
  7608. if (!defined('RESTORE_SILENTLY')) {
  7609. echo "<li>".get_string("checkinginstances");
  7610. }
  7611. if (!$status = restore_check_instances($restore)) {
  7612. if (!defined('RESTORE_SILENTLY')) {
  7613. notify("Could not adjust instances in course_modules!");
  7614. } else {
  7615. $errorstr = "Could not adjust instances in course_modules!";
  7616. return false;
  7617. }
  7618. }
  7619. if (!defined('RESTORE_SILENTLY')) {
  7620. echo '</li>';
  7621. }
  7622. }
  7623. //Now, if all is OK, adjust activity events
  7624. if ($status) {
  7625. if (!defined('RESTORE_SILENTLY')) {
  7626. echo "<li>".get_string("refreshingevents");
  7627. }
  7628. if (!$status = restore_refresh_events($restore)) {
  7629. if (!defined('RESTORE_SILENTLY')) {
  7630. notify("Could not refresh events for activities!");
  7631. } else {
  7632. $errorstr = "Could not refresh events for activities!";
  7633. return false;
  7634. }
  7635. }
  7636. if (!defined('RESTORE_SILENTLY')) {
  7637. echo '</li>';
  7638. }
  7639. }
  7640. //Now, if all is OK, adjust inter-activity links
  7641. if ($status) {
  7642. if (!defined('RESTORE_SILENTLY')) {
  7643. echo "<li>".get_string("decodinginternallinks");
  7644. }
  7645. if (!$status = restore_decode_content_links($restore)) {
  7646. if (!defined('RESTORE_SILENTLY')) {
  7647. notify("Could not decode content links!");
  7648. } else {
  7649. $errorstr = "Could not decode content links!";
  7650. return false;
  7651. }
  7652. }
  7653. if (!defined('RESTORE_SILENTLY')) {
  7654. echo '</li>';
  7655. }
  7656. }
  7657. //Now, with backup files prior to version 2005041100,
  7658. //convert all the wiki texts in the course to markdown
  7659. if ($status && $restore->backup_version < 2005041100) {
  7660. if (!defined('RESTORE_SILENTLY')) {
  7661. echo "<li>".get_string("convertingwikitomarkdown");
  7662. }
  7663. if (!$status = restore_convert_wiki2markdown($restore)) {
  7664. if (!defined('RESTORE_SILENTLY')) {
  7665. notify("Could not convert wiki texts to markdown!");
  7666. } else {
  7667. $errorstr = "Could not convert wiki texts to markdown!";
  7668. return false;
  7669. }
  7670. }
  7671. if (!defined('RESTORE_SILENTLY')) {
  7672. echo '</li>';
  7673. }
  7674. }
  7675. //Now create gradebook as needed -- AFTER modules and blocks!!!
  7676. if ($status) {
  7677. if ($restore->backup_version > 2007090500) {
  7678. if (!defined('RESTORE_SILENTLY')) {
  7679. echo "<li>".get_string("creatinggradebook");
  7680. }
  7681. if (!$status = restore_create_gradebook($restore,$xml_file)) {
  7682. if (!defined('RESTORE_SILENTLY')) {
  7683. notify("Could not restore gradebook!");
  7684. } else {
  7685. $errorstr = "Could not restore gradebook!";
  7686. return false;
  7687. }
  7688. }
  7689. if (!defined('RESTORE_SILENTLY')) {
  7690. echo '</li>';
  7691. }
  7692. } else {
  7693. // for moodle versions before 1.9, those grades need to be converted to use the new gradebook
  7694. // this code needs to execute *after* the course_modules are sorted out
  7695. if (!defined('RESTORE_SILENTLY')) {
  7696. echo "<li>".get_string("migratinggrades");
  7697. }
  7698. /// force full refresh of grading data before migration == crete all items first
  7699. if (!$status = restore_migrate_old_gradebook($restore,$xml_file)) {
  7700. if (!defined('RESTORE_SILENTLY')) {
  7701. notify("Could not migrate gradebook!");
  7702. } else {
  7703. $errorstr = "Could not migrade gradebook!";
  7704. return false;
  7705. }
  7706. }
  7707. if (!defined('RESTORE_SILENTLY')) {
  7708. echo '</li>';
  7709. }
  7710. }
  7711. /// force full refresh of grading data after all items are created
  7712. grade_force_full_regrading($restore->course_id);
  7713. grade_grab_course_grades($restore->course_id);
  7714. }
  7715. /*******************************************************************************
  7716. ************* Restore of Roles and Capabilities happens here ******************
  7717. *******************************************************************************/
  7718. // try to restore roles even when restore is going to fail - teachers might have
  7719. // at least some role assigned - this is not correct though
  7720. $status = restore_create_roles($restore, $xml_file) && $status;
  7721. $status = restore_roles_settings($restore, $xml_file) && $status;
  7722. //Now if all is OK, update:
  7723. // - course modinfo field
  7724. // - categories table
  7725. // - add user as teacher
  7726. if ($status) {
  7727. if (!defined('RESTORE_SILENTLY')) {
  7728. echo "<li>".get_string("checkingcourse");
  7729. }
  7730. //categories table
  7731. $course = get_record("course","id",$restore->course_id);
  7732. fix_course_sortorder();
  7733. // Check if the user has course update capability in the newly restored course
  7734. // there is no need to load his capabilities again, because restore_roles_settings
  7735. // would have loaded it anyway, if there is any assignments.
  7736. // fix for MDL-6831
  7737. $newcontext = get_context_instance(CONTEXT_COURSE, $restore->course_id);
  7738. if (!has_capability('moodle/course:manageactivities', $newcontext)) {
  7739. // fix for MDL-9065, use the new config setting if exists
  7740. if ($CFG->creatornewroleid) {
  7741. role_assign($CFG->creatornewroleid, $USER->id, 0, $newcontext->id);
  7742. } else {
  7743. if ($legacyteachers = get_roles_with_capability('moodle/legacy:editingteacher', CAP_ALLOW, get_context_instance(CONTEXT_SYSTEM))) {
  7744. if ($legacyteacher = array_shift($legacyteachers)) {
  7745. role_assign($legacyteacher->id, $USER->id, 0, $newcontext->id);
  7746. }
  7747. } else {
  7748. notify('Could not find a legacy teacher role. You might need your moodle admin to assign a role with editing privilages to this course.');
  7749. }
  7750. }
  7751. }
  7752. if (!defined('RESTORE_SILENTLY')) {
  7753. echo '</li>';
  7754. }
  7755. }
  7756. //Cleanup temps (files and db)
  7757. if ($status) {
  7758. if (!defined('RESTORE_SILENTLY')) {
  7759. echo "<li>".get_string("cleaningtempdata");
  7760. }
  7761. if (!$status = clean_temp_data ($restore)) {
  7762. if (!defined('RESTORE_SILENTLY')) {
  7763. notify("Could not clean up temporary data from files and database");
  7764. } else {
  7765. $errorstr = "Could not clean up temporary data from files and database";
  7766. return false;
  7767. }
  7768. }
  7769. if (!defined('RESTORE_SILENTLY')) {
  7770. echo '</li>';
  7771. }
  7772. }
  7773. // this is not a critical check - the result can be ignored
  7774. if (restore_close_html($restore)){
  7775. if (!defined('RESTORE_SILENTLY')) {
  7776. echo '<li>Closing the Restorelog.html file.</li>';
  7777. }
  7778. }
  7779. else {
  7780. if (!defined('RESTORE_SILENTLY')) {
  7781. notify("Could not close the restorelog.html file");
  7782. }
  7783. }
  7784. if (!defined('RESTORE_SILENTLY')) {
  7785. //End the main ul
  7786. echo "</ul>";
  7787. //End the main table
  7788. echo "</td></tr>";
  7789. echo "</table>";
  7790. }
  7791. return $status;
  7792. }
  7793. //Create, open and write header of the html log file
  7794. function restore_open_html($restore,$course_header) {
  7795. global $CFG;
  7796. $status = true;
  7797. //Open file for writing
  7798. //First, we check the course_id backup data folder exists and create it as necessary in CFG->dataroot
  7799. if (!$dest_dir = make_upload_directory("$restore->course_id/backupdata")) { // Backup folder
  7800. error("Could not create backupdata folder. The site administrator needs to fix the file permissions");
  7801. }
  7802. $status = check_dir_exists($dest_dir,true);
  7803. $restorelog_file = fopen("$dest_dir/restorelog.html","a");
  7804. //Add the stylesheet
  7805. $stylesheetshtml = '';
  7806. foreach ($CFG->stylesheets as $stylesheet) {
  7807. $stylesheetshtml .= '<link rel="stylesheet" type="text/css" href="'.$stylesheet.'" />'."\n";
  7808. }
  7809. ///Accessibility: added the 'lang' attribute to $direction, used in theme <html> tag.
  7810. $languagehtml = get_html_lang($dir=true);
  7811. //Write the header in the new logging file
  7812. fwrite ($restorelog_file,"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"");
  7813. fwrite ($restorelog_file," \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"> ");
  7814. fwrite ($restorelog_file,"<html dir=\"ltr\".$languagehtml.");
  7815. fwrite ($restorelog_file,"<head>");
  7816. fwrite ($restorelog_file,$stylesheetshtml);
  7817. fwrite ($restorelog_file,"<title>".$course_header->course_shortname." Restored </title>");
  7818. fwrite ($restorelog_file,"</head><body><br/><h1>The following changes were made during the Restoration of this Course.</h1><br/><br/>");
  7819. fwrite ($restorelog_file,"The Course ShortName is now - ".$course_header->course_shortname." The FullName is now - ".$course_header->course_fullname."<br/><br/>");
  7820. $startdate = addslashes($course_header->course_startdate);
  7821. $date = usergetdate($startdate);
  7822. fwrite ($restorelog_file,"The Originating Courses Start Date was " .$date['weekday'].", ".$date['mday']." ".$date['month']." ".$date['year']."");
  7823. $startdate += $restore->course_startdateoffset;
  7824. $date = usergetdate($startdate);
  7825. fwrite ($restorelog_file,"&nbsp;&nbsp;&nbsp;This Courses Start Date is now " .$date['weekday'].", ".$date['mday']." ".$date['month']." ".$date['year']."<br/><br/>");
  7826. if ($status) {
  7827. return $restorelog_file;
  7828. } else {
  7829. return false;
  7830. }
  7831. }
  7832. //Create & close footer of the html log file
  7833. function restore_close_html($restore) {
  7834. global $CFG;
  7835. $status = true;
  7836. //Open file for writing
  7837. //First, check that course_id/backupdata folder exists in CFG->dataroot
  7838. $dest_dir = $CFG->dataroot."/".$restore->course_id."/backupdata";
  7839. $status = check_dir_exists($dest_dir, true, true);
  7840. $restorelog_file = fopen("$dest_dir/restorelog.html","a");
  7841. //Write the footer to close the logging file
  7842. fwrite ($restorelog_file,"<br/>This file was written to directly by each modules restore process.");
  7843. fwrite ($restorelog_file,"<br/><br/>Log complete.</body></html>");
  7844. if ($status) {
  7845. return $restorelog_file;
  7846. } else {
  7847. return false;
  7848. }
  7849. }
  7850. /********************** Roles and Capabilities Related Functions *******************************/
  7851. /* Yu: Note recovering of role assignments/overrides need to take place after
  7852. users have been recovered, i.e. after we get their new_id, and after all
  7853. roles have been recreated or mapped. Contexts can be created on the fly.
  7854. The current order of restore is Restore (old) -> restore roles -> restore assignment/overrides
  7855. the order of restore among different contexts, i.e. course, mod, blocks, users should not matter
  7856. once roles and users have been restored.
  7857. */
  7858. /**
  7859. * This function restores all the needed roles for this course
  7860. * i.e. roles with an assignment in any of the mods or blocks,
  7861. * roles assigned on any user (e.g. parent role) and roles
  7862. * assigned at course levle
  7863. * This function should check for duplicate roles first
  7864. * It isn't now, just overwriting
  7865. */
  7866. function restore_create_roles($restore, $xmlfile) {
  7867. if (!defined('RESTORE_SILENTLY')) {
  7868. echo "<li>".get_string("creatingrolesdefinitions").'</li>';
  7869. }
  7870. $info = restore_read_xml_roles($xmlfile);
  7871. $sitecontext = get_context_instance(CONTEXT_SYSTEM);
  7872. // the following code creates new roles
  7873. // but we could use more intelligent detection, and role mapping
  7874. // get role mapping info from $restore
  7875. $rolemappings = array();
  7876. if (!empty($restore->rolesmapping)) {
  7877. $rolemappings = $restore->rolesmapping;
  7878. }
  7879. // $info->roles will be empty for backups pre 1.7
  7880. if (isset($info->roles) && $info->roles) {
  7881. foreach ($info->roles as $oldroleid=>$roledata) {
  7882. if (empty($restore->rolesmapping)) {
  7883. // if this is empty altogether, we came from import or there's no roles used in course at all
  7884. // in this case, write the same oldid as this is the same site
  7885. // no need to do mapping
  7886. $status = backup_putid($restore->backup_unique_code,"role",$oldroleid,
  7887. $oldroleid); // adding a new id
  7888. continue; // do not create additonal roles;
  7889. }
  7890. // first we check if the roles are in the mappings
  7891. // if so, we just do a mapping i.e. update oldids table
  7892. if (isset($rolemappings[$oldroleid]) && $rolemappings[$oldroleid]) {
  7893. $status = backup_putid($restore->backup_unique_code,"role",$oldroleid,
  7894. $rolemappings[$oldroleid]); // adding a new id
  7895. } else {
  7896. // code to make new role name/short name if same role name or shortname exists
  7897. $fullname = $roledata->name;
  7898. $shortname = $roledata->shortname;
  7899. $currentfullname = "";
  7900. $currentshortname = "";
  7901. $counter = 0;
  7902. do {
  7903. if ($counter) {
  7904. $suffixfull = " ".get_string("copyasnoun")." ".$counter;
  7905. $suffixshort = "_".$counter;
  7906. } else {
  7907. $suffixfull = "";
  7908. $suffixshort = "";
  7909. }
  7910. $currentfullname = $fullname.$suffixfull;
  7911. // Limit the size of shortname - database column accepts <= 100 chars
  7912. $currentshortname = substr($shortname, 0, 100 - strlen($suffixshort)).$suffixshort;
  7913. $coursefull = get_record("role","name",addslashes($currentfullname));
  7914. $courseshort = get_record("role","shortname",addslashes($currentshortname));
  7915. $counter++;
  7916. } while ($coursefull || $courseshort);
  7917. $roledata->name = $currentfullname;
  7918. $roledata->shortname= $currentshortname;
  7919. // done finding a unique name
  7920. $newroleid = create_role(addslashes($roledata->name),addslashes($roledata->shortname),'');
  7921. $status = backup_putid($restore->backup_unique_code,"role",$oldroleid,
  7922. $newroleid); // adding a new id
  7923. foreach ($roledata->capabilities as $capability) {
  7924. $roleinfo = new object();
  7925. $roleinfo = (object)$capability;
  7926. $roleinfo->contextid = $sitecontext->id;
  7927. $roleinfo->capability = $capability->name;
  7928. $roleinfo->roleid = $newroleid;
  7929. insert_record('role_capabilities', $roleinfo);
  7930. }
  7931. }
  7932. /// Now, restore role nameincourse (only if the role had nameincourse in backup)
  7933. if (!empty($roledata->nameincourse)) {
  7934. $newrole = backup_getid($restore->backup_unique_code, 'role', $oldroleid); /// Look for target role
  7935. $coursecontext = get_context_instance(CONTEXT_COURSE, $restore->course_id); /// Look for target context
  7936. if (!empty($newrole->new_id) && !empty($coursecontext)) {
  7937. /// Check the role hasn't any custom name in context
  7938. if (!record_exists('role_names', 'roleid', $newrole->new_id, 'contextid', $coursecontext->id)) {
  7939. $rolename = new object();
  7940. $rolename->roleid = $newrole->new_id;
  7941. $rolename->contextid = $coursecontext->id;
  7942. $rolename->name = addslashes($roledata->nameincourse);
  7943. insert_record('role_names', $rolename);
  7944. }
  7945. }
  7946. }
  7947. }
  7948. }
  7949. return true;
  7950. }
  7951. /**
  7952. * this function restores role assignments and role overrides
  7953. * in course/user/block/mod level, it passed through
  7954. * the xml file again
  7955. */
  7956. function restore_roles_settings($restore, $xmlfile) {
  7957. // data pulls from course, mod, user, and blocks
  7958. /*******************************************************
  7959. * Restoring from course level assignments *
  7960. *******************************************************/
  7961. if (!defined('RESTORE_SILENTLY')) {
  7962. echo "<li>".get_string("creatingcourseroles").'</li>';
  7963. }
  7964. $course = restore_read_xml_course_header($xmlfile);
  7965. if (!isset($restore->rolesmapping)) {
  7966. $isimport = true; // course import from another course, or course with no role assignments
  7967. } else {
  7968. $isimport = false; // course restore with role assignments
  7969. }
  7970. if (!empty($course->roleassignments) && !$isimport) {
  7971. $courseassignments = $course->roleassignments;
  7972. foreach ($courseassignments as $oldroleid => $courseassignment) {
  7973. restore_write_roleassignments($restore, $courseassignment->assignments, "course", CONTEXT_COURSE, $course->course_id, $oldroleid);
  7974. }
  7975. }
  7976. /*****************************************************
  7977. * Restoring from course level overrides *
  7978. *****************************************************/
  7979. if (!empty($course->roleoverrides) && !$isimport) {
  7980. $courseoverrides = $course->roleoverrides;
  7981. foreach ($courseoverrides as $oldroleid => $courseoverride) {
  7982. // if not importing into exiting course, or creating new role, we are ok
  7983. // local course overrides to be respected (i.e. restored course overrides ignored)
  7984. if (($restore->restoreto != RESTORETO_CURRENT_ADDING && $restore->restoreto != RESTORETO_EXISTING_ADDING) || empty($restore->rolesmapping[$oldroleid])) {
  7985. restore_write_roleoverrides($restore, $courseoverride->overrides, "course", CONTEXT_COURSE, $course->course_id, $oldroleid);
  7986. }
  7987. }
  7988. }
  7989. /*******************************************************
  7990. * Restoring role assignments/overrdies *
  7991. * from module level assignments *
  7992. *******************************************************/
  7993. if (!defined('RESTORE_SILENTLY')) {
  7994. echo "<li>".get_string("creatingmodroles").'</li>';
  7995. }
  7996. $sections = restore_read_xml_sections($xmlfile);
  7997. $secs = $sections->sections;
  7998. foreach ($secs as $section) {
  7999. if (isset($section->mods)) {
  8000. foreach ($section->mods as $modid=>$mod) {
  8001. if (isset($mod->roleassignments) && !$isimport) {
  8002. foreach ($mod->roleassignments as $oldroleid=>$modassignment) {
  8003. restore_write_roleassignments($restore, $modassignment->assignments, "course_modules", CONTEXT_MODULE, $modid, $oldroleid);
  8004. }
  8005. }
  8006. // role overrides always applies, in import or backup/restore
  8007. if (isset($mod->roleoverrides)) {
  8008. foreach ($mod->roleoverrides as $oldroleid=>$modoverride) {
  8009. restore_write_roleoverrides($restore, $modoverride->overrides, "course_modules", CONTEXT_MODULE, $modid, $oldroleid);
  8010. }
  8011. }
  8012. }
  8013. }
  8014. }
  8015. /*************************************************
  8016. * Restoring assignments from blocks level *
  8017. * role assignments/overrides *
  8018. *************************************************/
  8019. if ($restore->restoreto != RESTORETO_CURRENT_ADDING && $restore->restoreto != RESTORETO_EXISTING_ADDING) { // skip altogether if restoring to exisitng course by adding
  8020. if (!defined('RESTORE_SILENTLY')) {
  8021. echo "<li>".get_string("creatingblocksroles").'</li>';
  8022. }
  8023. $blocks = restore_read_xml_blocks($restore, $xmlfile);
  8024. if (isset($blocks->instances)) {
  8025. foreach ($blocks->instances as $instance) {
  8026. if (isset($instance->roleassignments) && !$isimport) {
  8027. foreach ($instance->roleassignments as $oldroleid=>$blockassignment) {
  8028. restore_write_roleassignments($restore, $blockassignment->assignments, "block_instance", CONTEXT_BLOCK, $instance->id, $oldroleid);
  8029. }
  8030. }
  8031. // likewise block overrides should always be restored like mods
  8032. if (isset($instance->roleoverrides)) {
  8033. foreach ($instance->roleoverrides as $oldroleid=>$blockoverride) {
  8034. restore_write_roleoverrides($restore, $blockoverride->overrides, "block_instance", CONTEXT_BLOCK, $instance->id, $oldroleid);
  8035. }
  8036. }
  8037. }
  8038. }
  8039. }
  8040. /************************************************
  8041. * Restoring assignments from userid level *
  8042. * role assignments/overrides *
  8043. ************************************************/
  8044. if (!defined('RESTORE_SILENTLY')) {
  8045. echo "<li>".get_string("creatinguserroles").'</li>';
  8046. }
  8047. $info = restore_read_xml_users($restore, $xmlfile);
  8048. if (!empty($info->users) && !$isimport) { // no need to restore user assignments for imports (same course)
  8049. //For each user, take its info from backup_ids
  8050. foreach ($info->users as $userid) {
  8051. $rec = backup_getid($restore->backup_unique_code,"user",$userid);
  8052. if (isset($rec->info->roleassignments)) {
  8053. foreach ($rec->info->roleassignments as $oldroleid=>$userassignment) {
  8054. restore_write_roleassignments($restore, $userassignment->assignments, "user", CONTEXT_USER, $userid, $oldroleid);
  8055. }
  8056. }
  8057. if (isset($rec->info->roleoverrides)) {
  8058. foreach ($rec->info->roleoverrides as $oldroleid=>$useroverride) {
  8059. restore_write_roleoverrides($restore, $useroverride->overrides, "user", CONTEXT_USER, $userid, $oldroleid);
  8060. }
  8061. }
  8062. }
  8063. }
  8064. return true;
  8065. }
  8066. // auxillary function to write role assignments read from xml to db
  8067. function restore_write_roleassignments($restore, $assignments, $table, $contextlevel, $oldid, $oldroleid) {
  8068. $role = backup_getid($restore->backup_unique_code, "role", $oldroleid);
  8069. foreach ($assignments as $assignment) {
  8070. $olduser = backup_getid($restore->backup_unique_code,"user",$assignment->userid);
  8071. //Oh dear, $olduser... can be an object, $obj->string or bool!
  8072. if (!$olduser || (is_string($olduser->info) && $olduser->info == "notincourse")) { // it's possible that user is not in the course
  8073. continue;
  8074. }
  8075. $assignment->userid = $olduser->new_id; // new userid here
  8076. $oldmodifier = backup_getid($restore->backup_unique_code,"user",$assignment->modifierid);
  8077. $assignment->modifierid = !empty($oldmodifier->new_id) ? $oldmodifier->new_id : 0; // new modifier id here
  8078. $assignment->roleid = $role->new_id; // restored new role id
  8079. // hack to make the correct contextid for course level imports
  8080. if ($contextlevel == CONTEXT_COURSE) {
  8081. $oldinstance->new_id = $restore->course_id;
  8082. } else {
  8083. $oldinstance = backup_getid($restore->backup_unique_code,$table,$oldid);
  8084. }
  8085. // new instance id not found (not restored module/block/user)... skip any assignment
  8086. if (!$oldinstance || empty($oldinstance->new_id)) {
  8087. continue;
  8088. }
  8089. $newcontext = get_context_instance($contextlevel, $oldinstance->new_id);
  8090. $assignment->contextid = $newcontext->id; // new context id
  8091. // might already have same assignment
  8092. role_assign($assignment->roleid, $assignment->userid, 0, $assignment->contextid, $assignment->timestart, $assignment->timeend, $assignment->hidden, $assignment->enrol, $assignment->timemodified);
  8093. }
  8094. }
  8095. // auxillary function to write role assignments read from xml to db
  8096. function restore_write_roleoverrides($restore, $overrides, $table, $contextlevel, $oldid, $oldroleid) {
  8097. // it is possible to have an override not relevant to this course context.
  8098. // should be ignored(?)
  8099. if (!$role = backup_getid($restore->backup_unique_code, "role", $oldroleid)) {
  8100. return null;
  8101. }
  8102. foreach ($overrides as $override) {
  8103. $override->capability = $override->name;
  8104. $oldmodifier = backup_getid($restore->backup_unique_code,"user",$override->modifierid);
  8105. $override->modifierid = !empty($oldmodifier->new_id)?$oldmodifier->new_id:0; // new modifier id here
  8106. $override->roleid = $role->new_id; // restored new role id
  8107. // hack to make the correct contextid for course level imports
  8108. if ($contextlevel == CONTEXT_COURSE) {
  8109. $oldinstance->new_id = $restore->course_id;
  8110. } else {
  8111. $oldinstance = backup_getid($restore->backup_unique_code,$table,$oldid);
  8112. }
  8113. // new instance id not found (not restored module/block/user)... skip any override
  8114. if (!$oldinstance || empty($oldinstance->new_id)) {
  8115. continue;
  8116. }
  8117. $newcontext = get_context_instance($contextlevel, $oldinstance->new_id);
  8118. $override->contextid = $newcontext->id; // new context id
  8119. // use assign capability instead so we can add context to context_rel
  8120. assign_capability($override->capability, $override->permission, $override->roleid, $override->contextid);
  8121. }
  8122. }
  8123. /**
  8124. * true or false function to see if user can roll dates on restore (any course is enough)
  8125. * @return bool
  8126. */
  8127. function restore_user_can_roll_dates() {
  8128. global $USER;
  8129. // if user has moodle/restore:rolldates capability at system or any course cat return true
  8130. if (has_capability('moodle/restore:rolldates', get_context_instance(CONTEXT_SYSTEM))) {
  8131. return true;
  8132. }
  8133. // Non-cached - get accessinfo
  8134. if (isset($USER->access)) {
  8135. $accessinfo = $USER->access;
  8136. } else {
  8137. $accessinfo = get_user_access_sitewide($USER->id);
  8138. }
  8139. $courses = get_user_courses_bycap($USER->id, 'moodle/restore:rolldates', $accessinfo, true);
  8140. return !empty($courses);
  8141. }
  8142. //write activity date changes to the html log file, and update date values in the the xml array
  8143. function restore_log_date_changes($recordtype, &$restore, &$xml, $TAGS, $NAMETAG='NAME') {
  8144. global $CFG;
  8145. $openlog = false;
  8146. // loop through time fields in $TAGS
  8147. foreach ($TAGS as $TAG) {
  8148. // check $TAG has a sensible value
  8149. if (!empty($xml[$TAG][0]['#']) && is_string($xml[$TAG][0]['#']) && is_numeric($xml[$TAG][0]['#'])) {
  8150. if ($openlog==false) {
  8151. $openlog = true; // only come through here once
  8152. // open file for writing
  8153. $course_dir = "$CFG->dataroot/$restore->course_id/backupdata";
  8154. check_dir_exists($course_dir, true);
  8155. $restorelog = fopen("$course_dir/restorelog.html", "a");
  8156. // start output for this record
  8157. $msg = new stdClass();
  8158. $msg->recordtype = $recordtype;
  8159. $msg->recordname = $xml[$NAMETAG][0]['#'];
  8160. fwrite ($restorelog, get_string("backupdaterecordtype", "moodle", $msg));
  8161. }
  8162. // write old date to $restorelog
  8163. $value = $xml[$TAG][0]['#'];
  8164. $date = usergetdate($value);
  8165. $msg = new stdClass();
  8166. $msg->TAG = $TAG;
  8167. $msg->weekday = $date['weekday'];
  8168. $msg->mday = $date['mday'];
  8169. $msg->month = $date['month'];
  8170. $msg->year = $date['year'];
  8171. fwrite ($restorelog, get_string("backupdateold", "moodle", $msg));
  8172. // write new date to $restorelog
  8173. $value += $restore->course_startdateoffset;
  8174. $date = usergetdate($value);
  8175. $msg = new stdClass();
  8176. $msg->TAG = $TAG;
  8177. $msg->weekday = $date['weekday'];
  8178. $msg->mday = $date['mday'];
  8179. $msg->month = $date['month'];
  8180. $msg->year = $date['year'];
  8181. fwrite ($restorelog, get_string("backupdatenew", "moodle", $msg));
  8182. // update $value in $xml tree for calling module
  8183. $xml[$TAG][0]['#'] = "$value";
  8184. }
  8185. }
  8186. // close the restore log, if it was opened
  8187. if ($openlog) {
  8188. fclose($restorelog);
  8189. }
  8190. }
  8191. ?>