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 * Provides support for the conversion of moodle1 backup to the moodle2 format 20 * 21 * @package mod_resource 22 * @copyright 2011 Andrew Davis <andrew@moodle.com> 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 /** 29 * Resource conversion handler 30 */ 31 class moodle1_mod_resource_handler extends moodle1_mod_handler { 32 33 /** @var moodle1_file_manager instance */ 34 protected $fileman = null; 35 36 /** @var array of resource successors handlers */ 37 private $successors = array(); 38 39 /** 40 * Declare the paths in moodle.xml we are able to convert 41 * 42 * The method returns list of {@link convert_path} instances. 43 * For each path returned, the corresponding conversion method must be 44 * defined. 45 * 46 * Note that the paths /MOODLE_BACKUP/COURSE/MODULES/MOD/RESOURCE do not 47 * actually exist in the file. The last element with the module name was 48 * appended by the moodle1_converter class. 49 * 50 * @return array of {@link convert_path} instances 51 */ 52 public function get_paths() { 53 return array( 54 new convert_path( 55 'resource', '/MOODLE_BACKUP/COURSE/MODULES/MOD/RESOURCE', 56 array( 57 'renamefields' => array( 58 'summary' => 'intro', 59 ), 60 'newfields' => array( 61 'introformat' => 0, 62 ), 63 'dropfields' => array( 64 'modtype', 65 ), 66 ) 67 ) 68 ); 69 } 70 71 /** 72 * Converts /MOODLE_BACKUP/COURSE/MODULES/MOD/RESOURCE data 73 * 74 * This methods detects the resource type and eventually re-dispatches it to the 75 * corresponding resource successor (url, forum, page, imscp). 76 */ 77 public function process_resource(array $data, array $raw) { 78 global $CFG; 79 require_once("$CFG->libdir/resourcelib.php"); 80 81 // replay the upgrade step 2009042001 82 if ($CFG->texteditors !== 'textarea') { 83 $data['intro'] = text_to_html($data['intro'], false, false, true); 84 $data['introformat'] = FORMAT_HTML; 85 } 86 87 // fix invalid null popup and options data 88 if (!array_key_exists('popup', $data) or is_null($data['popup'])) { 89 $data['popup'] = ''; 90 } 91 if (!array_key_exists ('options', $data) or is_null($data['options'])) { 92 $data['options'] = ''; 93 } 94 95 // decide if the legacy resource should be handled by a successor module 96 if ($successor = $this->get_successor($data['type'], $data['reference'])) { 97 // the instance id will be kept 98 $instanceid = $data['id']; 99 100 // move the instance from the resource's modinfo stash to the successor's 101 // modinfo stash 102 $resourcemodinfo = $this->converter->get_stash('modinfo_resource'); 103 $successormodinfo = $this->converter->get_stash('modinfo_'.$successor->get_modname()); 104 $successormodinfo['instances'][$instanceid] = $resourcemodinfo['instances'][$instanceid]; 105 unset($resourcemodinfo['instances'][$instanceid]); 106 $this->converter->set_stash('modinfo_resource', $resourcemodinfo); 107 $this->converter->set_stash('modinfo_'.$successor->get_modname(), $successormodinfo); 108 109 // get the course module information for the legacy resource module 110 $cminfo = $this->get_cminfo($instanceid); 111 112 // use the version of the successor instead of the current mod/resource 113 // beware - the version.php declares info via $module object, do not use 114 // a variable of such name here 115 $plugin = new stdClass(); 116 $plugin->version = null; 117 $module = $plugin; 118 include $CFG->dirroot.'/mod/'.$successor->get_modname().'/version.php'; 119 $cminfo['version'] = $plugin->version; 120 121 // stash the new course module information for this successor 122 $cminfo['modulename'] = $successor->get_modname(); 123 $this->converter->set_stash('cminfo_'.$cminfo['modulename'], $cminfo, $instanceid); 124 125 // rewrite the coursecontents stash 126 $coursecontents = $this->converter->get_stash('coursecontents'); 127 $coursecontents[$cminfo['id']]['modulename'] = $successor->get_modname(); 128 $this->converter->set_stash('coursecontents', $coursecontents); 129 130 // delegate the processing to the successor handler 131 return $successor->process_legacy_resource($data, $raw); 132 } 133 134 // no successor is interested in this record, convert it to the new mod_resource (aka File module) 135 136 $resource = array(); 137 $resource['id'] = $data['id']; 138 $resource['name'] = $data['name']; 139 $resource['intro'] = $data['intro']; 140 $resource['introformat'] = $data['introformat']; 141 $resource['tobemigrated'] = 0; 142 $resource['legacyfiles'] = RESOURCELIB_LEGACYFILES_ACTIVE; 143 $resource['legacyfileslast'] = null; 144 $resource['filterfiles'] = 0; 145 $resource['revision'] = 1; 146 $resource['timemodified'] = $data['timemodified']; 147 148 // populate display and displayoptions fields 149 $options = array('printintro' => 1); 150 if ($data['options'] == 'frame') { 151 $resource['display'] = RESOURCELIB_DISPLAY_FRAME; 152 153 } else if ($data['options'] == 'objectframe') { 154 $resource['display'] = RESOURCELIB_DISPLAY_EMBED; 155 156 } else if ($data['options'] == 'forcedownload') { 157 $resource['display'] = RESOURCELIB_DISPLAY_DOWNLOAD; 158 159 } else if ($data['popup']) { 160 $resource['display'] = RESOURCELIB_DISPLAY_POPUP; 161 $rawoptions = explode(',', $data['popup']); 162 foreach ($rawoptions as $rawoption) { 163 list($name, $value) = explode('=', trim($rawoption), 2); 164 if ($value > 0 and ($name == 'width' or $name == 'height')) { 165 $options['popup'.$name] = $value; 166 continue; 167 } 168 } 169 170 } else { 171 $resource['display'] = RESOURCELIB_DISPLAY_AUTO; 172 } 173 $resource['displayoptions'] = serialize($options); 174 175 // get the course module id and context id 176 $instanceid = $resource['id']; 177 $currentcminfo = $this->get_cminfo($instanceid); 178 $moduleid = $currentcminfo['id']; 179 $contextid = $this->converter->get_contextid(CONTEXT_MODULE, $moduleid); 180 181 // get a fresh new file manager for this instance 182 $this->fileman = $this->converter->get_file_manager($contextid, 'mod_resource'); 183 184 // convert course files embedded into the intro 185 $this->fileman->filearea = 'intro'; 186 $this->fileman->itemid = 0; 187 $resource['intro'] = moodle1_converter::migrate_referenced_files($resource['intro'], $this->fileman); 188 189 // convert the referenced file itself as a main file in the content area 190 $reference = $data['reference']; 191 if (strpos($reference, '$@FILEPHP@$') === 0) { 192 $reference = str_replace(array('$@FILEPHP@$', '$@SLASH@$', '$@FORCEDOWNLOAD@$'), array('', '/', ''), $reference); 193 } 194 $this->fileman->filearea = 'content'; 195 $this->fileman->itemid = 0; 196 197 // Rebuild the file path. 198 $curfilepath = '/'; 199 if ($reference) { 200 $curfilepath = pathinfo('/'.$reference, PATHINFO_DIRNAME); 201 if ($curfilepath != '/') { 202 $curfilepath .= '/'; 203 } 204 } 205 try { 206 $this->fileman->migrate_file('course_files/'.$reference, $curfilepath, null, 1); 207 } catch (moodle1_convert_exception $e) { 208 // the file probably does not exist 209 $this->log('error migrating the resource main file', backup::LOG_WARNING, 'course_files/'.$reference); 210 } 211 212 // write resource.xml 213 $this->open_xml_writer("activities/resource_{$moduleid}/resource.xml"); 214 $this->xmlwriter->begin_tag('activity', array('id' => $instanceid, 'moduleid' => $moduleid, 215 'modulename' => 'resource', 'contextid' => $contextid)); 216 $this->write_xml('resource', $resource, array('/resource/id')); 217 $this->xmlwriter->end_tag('activity'); 218 $this->close_xml_writer(); 219 220 // write inforef.xml 221 $this->open_xml_writer("activities/resource_{$currentcminfo['id']}/inforef.xml"); 222 $this->xmlwriter->begin_tag('inforef'); 223 $this->xmlwriter->begin_tag('fileref'); 224 foreach ($this->fileman->get_fileids() as $fileid) { 225 $this->write_xml('file', array('id' => $fileid)); 226 } 227 $this->xmlwriter->end_tag('fileref'); 228 $this->xmlwriter->end_tag('inforef'); 229 $this->close_xml_writer(); 230 } 231 232 /** 233 * Give succesors a chance to finish their job 234 */ 235 public function on_resource_end(array $data) { 236 if ($successor = $this->get_successor($data['type'], $data['reference'])) { 237 $successor->on_legacy_resource_end($data); 238 } 239 } 240 241 /// internal implementation details follow ///////////////////////////////// 242 243 /** 244 * Returns the handler of the new 2.0 mod type according the given type of the legacy 1.9 resource 245 * 246 * @param string $type the value of the 'type' field in 1.9 resource 247 * @param string $reference a file path. Necessary to differentiate files from web URLs 248 * @throws moodle1_convert_exception for the unknown types 249 * @return null|moodle1_mod_handler the instance of the handler, or null if the type does not have a successor 250 */ 251 protected function get_successor($type, $reference) { 252 253 switch ($type) { 254 case 'text': 255 case 'html': 256 $name = 'page'; 257 break; 258 case 'directory': 259 $name = 'folder'; 260 break; 261 case 'ims': 262 $name = 'imscp'; 263 break; 264 case 'file': 265 // if starts with $@FILEPHP@$ then it is URL link to a local course file 266 // to be migrated to the new resource module 267 if (strpos($reference, '$@FILEPHP@$') === 0) { 268 $name = null; 269 break; 270 } 271 // if http:// https:// ftp:// OR starts with slash need to be converted to URL 272 if (strpos($reference, '://') or strpos($reference, '/') === 0) { 273 $name = 'url'; 274 } else { 275 $name = null; 276 } 277 break; 278 default: 279 throw new moodle1_convert_exception('unknown_resource_successor', $type); 280 } 281 282 if (is_null($name)) { 283 return null; 284 } 285 286 if (!isset($this->successors[$name])) { 287 $this->log('preparing resource successor handler', backup::LOG_DEBUG, $name); 288 $class = 'moodle1_mod_'.$name.'_handler'; 289 $this->successors[$name] = new $class($this->converter, 'mod', $name); 290 291 // add the successor into the modlist stash 292 $modnames = $this->converter->get_stash('modnameslist'); 293 $modnames[] = $name; 294 $modnames = array_unique($modnames); // should not be needed but just in case 295 $this->converter->set_stash('modnameslist', $modnames); 296 297 // add the successor's modinfo stash 298 $modinfo = $this->converter->get_stash('modinfo_resource'); 299 $modinfo['name'] = $name; 300 $modinfo['instances'] = array(); 301 $this->converter->set_stash('modinfo_'.$name, $modinfo); 302 } 303 304 return $this->successors[$name]; 305 } 306 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body