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