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