PageRenderTime 51ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/backup/util/helper/backup_general_helper.class.php

https://bitbucket.org/ngmares/moodle
PHP | 271 lines | 172 code | 26 blank | 73 comment | 38 complexity | 949ca328bbe11ff59e2d0c7675f0b0c3 MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-3.0, MPL-2.0-no-copyleft-exception, GPL-3.0, Apache-2.0, BSD-3-Clause
  1. <?php
  2. // This file is part of Moodle - http://moodle.org/
  3. //
  4. // Moodle is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // Moodle is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  16. /**
  17. * @package moodlecore
  18. * @subpackage backup-helper
  19. * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
  20. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  21. */
  22. /**
  23. * Non instantiable helper class providing general helper methods for backup/restore
  24. *
  25. * This class contains various general helper static methods available for backup/restore
  26. *
  27. * TODO: Finish phpdocs
  28. */
  29. abstract class backup_general_helper extends backup_helper {
  30. /**
  31. * Calculate one checksum for any array/object. Works recursively
  32. */
  33. public static function array_checksum_recursive($arr) {
  34. $checksum = ''; // Init checksum
  35. // Check we are going to process one array always, objects must be cast before
  36. if (!is_array($arr)) {
  37. throw new backup_helper_exception('array_expected');
  38. }
  39. foreach ($arr as $key => $value) {
  40. if ($value instanceof checksumable) {
  41. $checksum = md5($checksum . '-' . $key . '-' . $value->calculate_checksum());
  42. } else if (is_object($value)) {
  43. $checksum = md5($checksum . '-' . $key . '-' . self::array_checksum_recursive((array)$value));
  44. } else if (is_array($value)) {
  45. $checksum = md5($checksum . '-' . $key . '-' . self::array_checksum_recursive($value));
  46. } else {
  47. $checksum = md5($checksum . '-' . $key . '-' . $value);
  48. }
  49. }
  50. return $checksum;
  51. }
  52. /**
  53. * Load all the blocks information needed for a given path within moodle2 backup
  54. *
  55. * This function, given one full path (course, activities/xxxx) will look for all the
  56. * blocks existing in the backup file, returning one array used to build the
  57. * proper restore plan by the @restore_plan_builder
  58. */
  59. public static function get_blocks_from_path($path) {
  60. global $DB;
  61. $blocks = array(); // To return results
  62. static $availableblocks = array(); // Get and cache available blocks
  63. if (empty($availableblocks)) {
  64. $availableblocks = array_keys(get_plugin_list('block'));
  65. }
  66. $path = $path . '/blocks'; // Always look under blocks subdir
  67. if (!is_dir($path)) {
  68. return array();
  69. }
  70. if (!$dir = opendir($path)) {
  71. return array();
  72. }
  73. while (false !== ($file = readdir($dir))) {
  74. if ($file == '.' || $file == '..') { // Skip dots
  75. continue;
  76. }
  77. if (is_dir($path .'/' . $file)) { // Dir found, check it's a valid block
  78. if (!file_exists($path .'/' . $file . '/block.xml')) { // Skip if xml file not found
  79. continue;
  80. }
  81. // Extract block name
  82. $blockname = preg_replace('/(.*)_\d+/', '\\1', $file);
  83. // Check block exists and is installed
  84. if (in_array($blockname, $availableblocks) && $DB->record_exists('block', array('name' => $blockname))) {
  85. $blocks[$path .'/' . $file] = $blockname;
  86. }
  87. }
  88. }
  89. closedir($dir);
  90. return $blocks;
  91. }
  92. /**
  93. * Load and format all the needed information from moodle_backup.xml
  94. *
  95. * This function loads and process all the moodle_backup.xml
  96. * information, composing a big information structure that will
  97. * be the used by the plan builder in order to generate the
  98. * appropiate tasks / steps / settings
  99. */
  100. public static function get_backup_information($tempdir) {
  101. global $CFG;
  102. $info = new stdclass(); // Final information goes here
  103. $moodlefile = $CFG->tempdir . '/backup/' . $tempdir . '/moodle_backup.xml';
  104. if (!file_exists($moodlefile)) { // Shouldn't happen ever, but...
  105. throw new backup_helper_exception('missing_moodle_backup_xml_file', $moodlefile);
  106. }
  107. // Load the entire file to in-memory array
  108. $xmlparser = new progressive_parser();
  109. $xmlparser->set_file($moodlefile);
  110. $xmlprocessor = new restore_moodlexml_parser_processor();
  111. $xmlparser->set_processor($xmlprocessor);
  112. $xmlparser->process();
  113. $infoarr = $xmlprocessor->get_all_chunks();
  114. if (count($infoarr) !== 1) { // Shouldn't happen ever, but...
  115. throw new backup_helper_exception('problem_parsing_moodle_backup_xml_file');
  116. }
  117. $infoarr = $infoarr[0]['tags']; // for commodity
  118. // Let's build info
  119. $info->moodle_version = $infoarr['moodle_version'];
  120. $info->moodle_release = $infoarr['moodle_release'];
  121. $info->backup_version = $infoarr['backup_version'];
  122. $info->backup_release = $infoarr['backup_release'];
  123. $info->backup_date = $infoarr['backup_date'];
  124. $info->mnet_remoteusers = $infoarr['mnet_remoteusers'];
  125. $info->original_wwwroot = $infoarr['original_wwwroot'];
  126. $info->original_site_identifier_hash = $infoarr['original_site_identifier_hash'];
  127. $info->original_course_id = $infoarr['original_course_id'];
  128. $info->original_course_fullname = $infoarr['original_course_fullname'];
  129. $info->original_course_shortname= $infoarr['original_course_shortname'];
  130. $info->original_course_startdate= $infoarr['original_course_startdate'];
  131. $info->original_course_contextid= $infoarr['original_course_contextid'];
  132. $info->original_system_contextid= $infoarr['original_system_contextid'];
  133. // Moodle backup file don't have this option before 2.3
  134. if (!empty($infoarr['include_file_references_to_external_content'])) {
  135. $info->include_file_references_to_external_content = 1;
  136. } else {
  137. $info->include_file_references_to_external_content = 0;
  138. }
  139. $info->type = $infoarr['details']['detail'][0]['type'];
  140. $info->format = $infoarr['details']['detail'][0]['format'];
  141. $info->mode = $infoarr['details']['detail'][0]['mode'];
  142. // Build the role mappings custom object
  143. $rolemappings = new stdclass();
  144. $rolemappings->modified = false;
  145. $rolemappings->mappings = array();
  146. $info->role_mappings = $rolemappings;
  147. // Some initially empty containers
  148. $info->sections = array();
  149. $info->activities = array();
  150. // Now the contents
  151. $contentsarr = $infoarr['contents'];
  152. if (isset($contentsarr['course']) && isset($contentsarr['course'][0])) {
  153. $info->course = new stdclass();
  154. $info->course = (object)$contentsarr['course'][0];
  155. $info->course->settings = array();
  156. }
  157. if (isset($contentsarr['sections']) && isset($contentsarr['sections']['section'])) {
  158. $sectionarr = $contentsarr['sections']['section'];
  159. foreach ($sectionarr as $section) {
  160. $section = (object)$section;
  161. $section->settings = array();
  162. $sections[basename($section->directory)] = $section;
  163. }
  164. $info->sections = $sections;
  165. }
  166. if (isset($contentsarr['activities']) && isset($contentsarr['activities']['activity'])) {
  167. $activityarr = $contentsarr['activities']['activity'];
  168. foreach ($activityarr as $activity) {
  169. $activity = (object)$activity;
  170. $activity->settings = array();
  171. $activities[basename($activity->directory)] = $activity;
  172. }
  173. $info->activities = $activities;
  174. }
  175. $info->root_settings = array(); // For root settings
  176. // Now the settings, putting each one under its owner
  177. $settingsarr = $infoarr['settings']['setting'];
  178. foreach($settingsarr as $setting) {
  179. switch ($setting['level']) {
  180. case 'root':
  181. $info->root_settings[$setting['name']] = $setting['value'];
  182. break;
  183. case 'course':
  184. $info->course->settings[$setting['name']] = $setting['value'];
  185. break;
  186. case 'section':
  187. $info->sections[$setting['section']]->settings[$setting['name']] = $setting['value'];
  188. break;
  189. case 'activity':
  190. $info->activities[$setting['activity']]->settings[$setting['name']] = $setting['value'];
  191. break;
  192. default: // Shouldn't happen
  193. throw new backup_helper_exception('wrong_setting_level_moodle_backup_xml_file', $setting['level']);
  194. }
  195. }
  196. return $info;
  197. }
  198. /**
  199. * Given the information fetched from moodle_backup.xml file
  200. * decide if we are restoring in the same site the backup was
  201. * generated or no. Behavior of various parts of restore are
  202. * dependent of this.
  203. *
  204. * Backups created natively in 2.0 and later declare the hashed
  205. * site identifier. Backups created by conversion from a 1.9
  206. * backup do not declare such identifier, so there is a fallback
  207. * to wwwroot comparison. See MDL-16614.
  208. */
  209. public static function backup_is_samesite($info) {
  210. global $CFG;
  211. $hashedsiteid = md5(get_site_identifier());
  212. if (isset($info->original_site_identifier_hash) && !empty($info->original_site_identifier_hash)) {
  213. return $info->original_site_identifier_hash == $hashedsiteid;
  214. } else {
  215. return $info->original_wwwroot == $CFG->wwwroot;
  216. }
  217. }
  218. /**
  219. * Detects the format of the given unpacked backup directory
  220. *
  221. * @param string $tempdir the name of the backup directory
  222. * @return string one of backup::FORMAT_xxx constants
  223. */
  224. public static function detect_backup_format($tempdir) {
  225. global $CFG;
  226. require_once($CFG->dirroot . '/backup/util/helper/convert_helper.class.php');
  227. if (convert_helper::detect_moodle2_format($tempdir)) {
  228. return backup::FORMAT_MOODLE;
  229. }
  230. // see if a converter can identify the format
  231. $converters = convert_helper::available_converters();
  232. foreach ($converters as $name) {
  233. $classname = "{$name}_converter";
  234. if (!class_exists($classname)) {
  235. throw new coding_exception("available_converters() is supposed to load
  236. converter classes but class $classname not found");
  237. }
  238. $detected = call_user_func($classname .'::detect_format', $tempdir);
  239. if (!empty($detected)) {
  240. return $detected;
  241. }
  242. }
  243. return backup::FORMAT_UNKNOWN;
  244. }
  245. }