SCORM MDL-21568 fix regression
[moodle.git] / mod / scorm / db / upgrade.php
CommitLineData
e5dd8e3b 1<?php
b8a342d7 2
9528568b 3// This file keeps track of upgrades to
b8a342d7 4// the scorm module
5//
6// Sometimes, changes between versions involve
7// alterations to database structures and other
8// major things that may break installations.
9//
10// The upgrade function in this file will attempt
11// to perform all the necessary actions to upgrade
2e0406a5 12// your older installation to the current version.
b8a342d7 13//
14// If there's something it cannot do itself, it
15// will tell you what you need to do.
16//
17// The commands in here will all be database-neutral,
b1f93b15 18// using the methods of database_manager class
775f811a 19//
20// Please do not forget to use upgrade_set_timeout()
21// before any action that may take longer time to finish.
b8a342d7 22
775f811a 23function xmldb_scorm_upgrade($oldversion) {
24 global $CFG, $DB;
b8a342d7 25
c57ce9f2 26 $dbman = $DB->get_manager();
b8a342d7 27
219f652b 28//===== 1.9.0 upgrade line ======//
9858605e 29
c57ce9f2 30 // Adding missing 'whatgrade' field to table scorm
a4cdd6d2 31 if ($oldversion < 2008073000) {
c57ce9f2 32 $table = new xmldb_table('scorm');
33 $field = new xmldb_field('whatgrade');
2a88f626 34 $field->set_attributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'grademethod');
9528568b 35
c57ce9f2 36 /// Launch add field whatgrade
775f811a 37 if (!$dbman->field_exists($table,$field)) {
c57ce9f2 38 $dbman->add_field($table, $field);
d682eadf 39 $whatgradefixed = get_config('scorm', 'whatgradefixed');
b326c85a
DM
40 if (empty($whatgradefixed)) {
41 /// fix bad usage of whatgrade/grading method.
42 $scorms = $DB->get_records('scorm');
9d49a142
DM
43 if (!empty($scorm)) {
44 foreach ($scorms as $scorm) {
45 $scorm->whatgrade = $scorm->grademethod/10;
46 $DB->update_record('scorm', $scorm);
47 }
b326c85a 48 }
07b21d04 49 }
b326c85a
DM
50 } else {
51 //dump this config var as it isn't needed anymore.
52 unset_config('whatgradefixed', 'scorm');
c57ce9f2 53 }
9528568b 54
a4cdd6d2 55 upgrade_mod_savepoint(true, 2008073000, 'scorm');
c57ce9f2 56 }
9528568b 57
a4cdd6d2 58 if ($oldversion < 2008082500) {
9528568b 59
60 /// Define field scormtype to be added to scorm
61 $table = new xmldb_table('scorm');
2a88f626 62 $field = new xmldb_field('scormtype', XMLDB_TYPE_CHAR, '50', null, XMLDB_NOTNULL, null, 'local', 'name');
9528568b 63
64 /// Launch add field scormtype
65 $dbman->add_field($table, $field);
66
67 /// scorm savepoint reached
a4cdd6d2 68 upgrade_mod_savepoint(true, 2008082500, 'scorm');
9528568b 69 }
70
a4cdd6d2 71 if ($oldversion < 2008090300) {
9528568b 72
73 /// Define field sha1hash to be added to scorm
74 $table = new xmldb_table('scorm');
2a88f626 75 $field = new xmldb_field('sha1hash', XMLDB_TYPE_CHAR, '40', null, null, null, null, 'updatefreq');
9528568b 76
77 /// Launch add field sha1hash
78 $dbman->add_field($table, $field);
79
80 /// scorm savepoint reached
a4cdd6d2 81 upgrade_mod_savepoint(true, 2008090300, 'scorm');
9528568b 82 }
83
a4cdd6d2 84 if ($oldversion < 2008090301) {
9528568b 85
86 /// Define field revision to be added to scorm
87 $table = new xmldb_table('scorm');
2a88f626 88 $field = new xmldb_field('revision', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'md5hash');
9528568b 89
90 /// Launch add field revision
91 $dbman->add_field($table, $field);
92
93 /// scorm savepoint reached
a4cdd6d2 94 upgrade_mod_savepoint(true, 2008090301, 'scorm');
9528568b 95 }
96
a4cdd6d2 97 if ($oldversion < 2008090302) {
9528568b 98 $sql = "UPDATE {scorm}
99 SET scormtype = 'external'
100 WHERE reference LIKE ? OR reference LIKE ? OR reference LIKE ?";
101 $DB->execute($sql, array('http://%imsmanifest.xml', 'https://%imsmanifest.xml', 'www.%imsmanifest.xml'));
102
103 $sql = "UPDATE {scorm}
104 SET scormtype = 'localsync'
105 WHERE reference LIKE ? OR reference LIKE ? OR reference LIKE ?
106 OR reference LIKE ? OR reference LIKE ? OR reference LIKE ?";
107 $DB->execute($sql, array('http://%.zip', 'https://%.zip', 'www.%.zip', 'http://%.pif', 'https://%.pif', 'www.%.pif'));
108
109 $sql = "UPDATE {scorm} SET scormtype = 'imsrepository' WHERE reference LIKE ?";
110 $DB->execute($sql, array('#%'));
111
112 /// scorm savepoint reached
a4cdd6d2 113 upgrade_mod_savepoint(true, 2008090302, 'scorm');
9528568b 114 }
115
a4cdd6d2 116 if ($oldversion < 2008090303) {
9528568b 117 //remove obsoleted config settings
118 unset_config('scorm_advancedsettings');
119 unset_config('scorm_windowsettings');
120
121 /// scorm savepoint reached
a4cdd6d2 122 upgrade_mod_savepoint(true, 2008090303, 'scorm');
9528568b 123 }
124
a4cdd6d2 125 if ($oldversion < 2008090304) {
9528568b 126
127 /////////////////////////////////////
128 /// new file storage upgrade code ///
129 /////////////////////////////////////
130
131 function scorm_migrate_content_files($context, $base, $path) {
6aff538a 132 global $CFG, $OUTPUT;
9528568b 133
134 $fullpathname = $base.$path;
135 $fs = get_file_storage();
64f93798 136 $filearea = 'content';
9528568b 137 $items = new DirectoryIterator($fullpathname);
138
139 foreach ($items as $item) {
140 if ($item->isDot()) {
141 unset($item); // release file handle
142 continue;
143 }
144
145 if ($item->isLink()) {
146 // do not follow symlinks - they were never supported in moddata, sorry
147 unset($item); // release file handle
148 continue;
149 }
150
151 if ($item->isFile()) {
152 if (!$item->isReadable()) {
6aff538a 153 echo $OUTPUT->notification(" File not readable, skipping: ".$fullpathname.$item->getFilename());
9528568b 154 unset($item); // release file handle
155 continue;
156 }
157
158 $filepath = clean_param($path, PARAM_PATH);
159 $filename = clean_param($item->getFilename(), PARAM_FILE);
160 $oldpathname = $fullpathname.$item->getFilename();
161
162 if ($filename === '') {
163 continue;
164 unset($item); // release file handle
165 }
166
64f93798
PS
167 if (!$fs->file_exists($context->id, 'mod_scorm', $filearea, '0', $filepath, $filename)) {
168 $file_record = array('contextid'=>$context->id, 'component'=>'mod_scorm', 'filearea'=>$filearea, 'itemid'=>0, 'filepath'=>$filepath, 'filename'=>$filename,
9528568b 169 'timecreated'=>$item->getCTime(), 'timemodified'=>$item->getMTime());
170 unset($item); // release file handle
171 if ($fs->create_file_from_pathname($file_record, $oldpathname)) {
172 @unlink($oldpathname);
173 }
174 } else {
175 unset($item); // release file handle
176 }
177
178 } else {
179 //migrate recursively all subdirectories
180 $oldpathname = $fullpathname.$item->getFilename().'/';
181 $subpath = $path.$item->getFilename().'/';
182 unset($item); // release file handle
183 scorm_migrate_content_files($context, $base, $subpath);
184 @rmdir($oldpathname); // deletes dir if empty
185 }
186 }
187 unset($items); //release file handles
188 }
189
190 $fs = get_file_storage();
191
192 $sqlfrom = "FROM {scorm} s
193 JOIN {modules} m ON m.name = 'scorm'
194 JOIN {course_modules} cm ON (cm.module = m.id AND cm.instance = s.id)";
195
196 $count = $DB->count_records_sql("SELECT COUNT('x') $sqlfrom");
197
198 if ($rs = $DB->get_recordset_sql("SELECT s.id, s.scormtype, s.reference, s.course, cm.id AS cmid $sqlfrom ORDER BY s.course, s.id")) {
199
200 $pbar = new progress_bar('migratescormfiles', 500, true);
201
9528568b 202 $i = 0;
203 foreach ($rs as $scorm) {
204 $i++;
205 upgrade_set_timeout(180); // set up timeout, may also abort execution
206 $pbar->update($i, $count, "Migrating scorm files - $i/$count.");
207
208 $context = get_context_instance(CONTEXT_MODULE, $scorm->cmid);
209 $coursecontext = get_context_instance(CONTEXT_COURSE, $scorm->course);
210
211 // first copy local packages if found - do not delete in case they are shared ;-)
212 if ($scorm->scormtype === 'local' and preg_match('/.*(\.zip|\.pif)$/i', $scorm->reference)) {
64f93798
PS
213 $packagefile = clean_param($scorm->reference, PARAM_PATH);
214 $pathnamehash = sha1("/$coursecontext->id/course/legacy/0/$packagefile");
9528568b 215 if ($file = $fs->get_file_by_hash($pathnamehash)) {
64f93798 216 $file_record = array('scontextid'=>$context->id, 'component'=>'mod_scorm', 'filearea'=>'package',
9528568b 217 'itemid'=>0, 'filepath'=>'/');
84683aba
DM
218 try {
219 $fs->create_file_from_storedfile($file_record, $file);
220 } catch (Exception $x) {
221 }
222 $scorm->reference = $file->get_filepath().$file->get_filename();
223
9528568b 224 } else {
225 $scorm->reference = '';
226 }
227 $DB->update_record('scorm', $scorm);
228 }
229
230 // now migrate the extracted package
231 $basepath = "$CFG->dataroot/$scorm->course/$CFG->moddata/scorm/$scorm->id";
232 if (!is_dir($basepath)) {
233 //no files?
234 continue;
235 }
236
237 scorm_migrate_content_files($context, $basepath, '/');
238
239 // remove dirs if empty
240 @rmdir("$CFG->dataroot/$scorm->course/$CFG->moddata/scorm/$scorm->id/");
241 @rmdir("$CFG->dataroot/$scorm->course/$CFG->moddata/scorm/");
242 @rmdir("$CFG->dataroot/$scorm->course/$CFG->moddata/");
243 }
9528568b 244 $rs->close();
245 }
246
247 /// scorm savepoint reached
a4cdd6d2 248 upgrade_mod_savepoint(true, 2008090304, 'scorm');
9528568b 249 }
250
6381fa56 251
a4cdd6d2 252 if ($oldversion < 2008090305) {
6381fa56 253
254 /// Define new fields forcecompleted, forcenewattempt, displayattemptstatus, and displaycoursestructure to be added to scorm
255 $table = new xmldb_table('scorm');
2a88f626 256 $field = new xmldb_field('forcecompleted', XMLDB_TYPE_INTEGER, '1', null, null, null, '0', 'maxattempt');
6381fa56 257 if (!$dbman->field_exists($table,$field)) {
258 $dbman->add_field($table, $field);
259 }
2a88f626 260 $field = new xmldb_field('forcenewattempt', XMLDB_TYPE_INTEGER, '1', null, null, null, '0', 'forcecompleted');
6381fa56 261 if (!$dbman->field_exists($table,$field)) {
262 $dbman->add_field($table, $field);
263 }
2a88f626 264 $field = new xmldb_field('lastattemptlock', XMLDB_TYPE_INTEGER, '1', null, null, null, '0', 'forcenewattempt');
6381fa56 265 if (!$dbman->field_exists($table,$field)) {
266 $dbman->add_field($table, $field);
267 }
2a88f626 268 $field = new xmldb_field('displayattemptstatus', XMLDB_TYPE_INTEGER, '1', null, null, null, '1', 'lastattemptlock');
6381fa56 269 if (!$dbman->field_exists($table,$field)) {
270 $dbman->add_field($table, $field);
271 }
2a88f626 272 $field = new xmldb_field('displaycoursestructure', XMLDB_TYPE_INTEGER, '1', null, null, null, '1', 'displayattemptstatus');
6381fa56 273 if (!$dbman->field_exists($table,$field)) {
274 $dbman->add_field($table, $field);
275 }
65478eea 276
6381fa56 277 /// scorm savepoint reached
a4cdd6d2 278 upgrade_mod_savepoint(true, 2008090305, 'scorm');
6381fa56 279 }
65478eea 280
30fc6e2d 281
282 // remove redundant config values
a4cdd6d2 283 if ($oldversion < 2008090306) {
65478eea 284 /*
285 * comment this out as it is handled by the update mark 2008090310 below
286 * left for historical documentation as some early adopters may have done
287 * this already.
30fc6e2d 288 $redundant_config = array(
289 'scorm_allowapidebug',
290 'scorm_allowtypeexternal',
291 'scorm_allowtypeimsrepository',
65478eea 292 'scorm_allowtypelocalsync',
293 'scorm_apidebugmask',
294 'scorm_frameheight',
30fc6e2d 295 'scorm_framewidth',
296 'scorm_maxattempts',
297 'scorm_updatetime');
298 foreach ($redundant_config as $rcfg) {
299 if (isset($CFG->$rcfg)) {
300 unset_config($rcfg);
301 }
302 }
65478eea 303 */
1adc77e6 304 /// scorm savepoint reached
a4cdd6d2 305 upgrade_mod_savepoint(true, 2008090306, 'scorm');
1adc77e6 306 }
65478eea 307
308
1adc77e6 309
310 // remove redundant config values
a4cdd6d2 311 if ($oldversion < 2008090307) {
65478eea 312 /*
313 * comment this out as it is handled by the update mark 2008090310 below
314 * left for historical documentation as some early adopters may have done
315 * this already.
1adc77e6 316 $redundant_config = array(
317 'scorm_allowapidebug',
318 'scorm_allowtypeexternal',
319 'scorm_allowtypeimsrepository',
65478eea 320 'scorm_allowtypelocalsync',
321 'scorm_apidebugmask',
322 'scorm_frameheight',
1adc77e6 323 'scorm_framewidth',
324 'scorm_maxattempts',
325 'scorm_updatetime',
65478eea 326 'scorm_resizable',
327 'scorm_scrollbars',
328 'scorm_directories',
1adc77e6 329 'scorm_location',
65478eea 330 'scorm_menubar',
331 'scorm_toolbar',
1adc77e6 332 'scorm_status',
333 'scorm_grademethod',
334 'scorm_maxgrade',
335 'scorm_whatgrade',
336 'scorm_popup',
337 'scorm_skipview',
338 'scorm_hidebrowse',
339 'scorm_hidetoc',
340 'scorm_hidenav',
341 'scorm_auto',
342 'scorm_updatefreq'
343 );
344 foreach ($redundant_config as $rcfg) {
345 if (isset($CFG->$rcfg)) {
346 unset_config($rcfg);
30fc6e2d 347 }
348 }
65478eea 349 */
350
30fc6e2d 351 /// scorm savepoint reached
a4cdd6d2 352 upgrade_mod_savepoint(true, 2008090307, 'scorm');
30fc6e2d 353 }
65478eea 354
a4cdd6d2 355 if ($oldversion < 2008090308) {
d54e2145 356 $table = new xmldb_table('scorm');
2a88f626 357 $field = new xmldb_field('timeopen', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'height');
d54e2145 358 if (!$dbman->field_exists($table,$field)) {
359 $dbman->add_field($table, $field);
360 }
2a88f626 361 $field = new xmldb_field('timeclose', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'timeopen');
d54e2145 362 if (!$dbman->field_exists($table,$field)) {
363 $dbman->add_field($table, $field);
364 }
65478eea 365
d54e2145 366 /// scorm savepoint reached
a4cdd6d2 367 upgrade_mod_savepoint(true, 2008090308, 'scorm');
d54e2145 368 }
65478eea 369
370
a4cdd6d2 371 if ($oldversion < 2008090310) {
65478eea 372 // take above blocks that delete config and move the values in to config_plugins
373
374 $redundant_config = array(
375 'scorm_allowapidebug',
376 'scorm_allowtypeexternal',
377 'scorm_allowtypeimsrepository',
378 'scorm_allowtypelocalsync',
379 'scorm_apidebugmask',
380 'scorm_frameheight',
381 'scorm_framewidth',
382 'scorm_maxattempts',
383 'scorm_updatetime',
384 'scorm_resizable',
385 'scorm_scrollbars',
386 'scorm_directories',
387 'scorm_location',
388 'scorm_menubar',
389 'scorm_toolbar',
390 'scorm_status',
391 'scorm_grademethod',
392 'scorm_maxgrade',
393 'scorm_whatgrade',
394 'scorm_popup',
395 'scorm_skipview',
396 'scorm_hidebrowse',
397 'scorm_hidetoc',
398 'scorm_hidenav',
399 'scorm_auto',
400 'scorm_updatefreq',
401 'scorm_displayattemptstatus',
402 'scorm_displaycoursestructure',
403 'scorm_forcecompleted',
404 'scorm_forcenewattempt',
405 'scorm_lastattemptlock'
406 );
407
408 foreach ($redundant_config as $rcfg) {
409 if (isset($CFG->$rcfg)) {
410 $shortname = substr($rcfg, 6);
a4cdd6d2
PS
411 set_config($shortname, $CFG->$rcfg, 'scorm');
412 unset_config($rcfg);
65478eea 413 }
414 }
415
416 /// scorm savepoint reached
a4cdd6d2 417 upgrade_mod_savepoint(true, 2008090310, 'scorm');
65478eea 418 }
419
a4cdd6d2 420 if ($oldversion < 2009042000) {
d0bcf735 421
422 /// Rename field summary on table scorm to intro
423 $table = new xmldb_table('scorm');
2a88f626 424 $field = new xmldb_field('summary', XMLDB_TYPE_TEXT, 'small', null, XMLDB_NOTNULL, null, null, 'reference');
d0bcf735 425
426 /// Launch rename field summary
427 $dbman->rename_field($table, $field, 'intro');
428
429 /// scorm savepoint reached
a4cdd6d2 430 upgrade_mod_savepoint(true, 2009042000, 'scorm');
d0bcf735 431 }
432
a4cdd6d2 433 if ($oldversion < 2009042001) {
d0bcf735 434
435 /// Define field introformat to be added to scorm
436 $table = new xmldb_table('scorm');
2a88f626 437 $field = new xmldb_field('introformat', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'intro');
d0bcf735 438
439 /// Launch add field introformat
d682eadf
PS
440 if (!$dbman->field_exists($table, $field)) {
441 $dbman->add_field($table, $field);
442 }
443
444 // conditionally migrate to html format in intro
445 if ($CFG->texteditors !== 'textarea') {
39ac3f6e 446 $rs = $DB->get_recordset('scorm', array('introformat'=>FORMAT_MOODLE), '', 'id,intro,introformat');
d682eadf
PS
447 foreach ($rs as $s) {
448 $s->intro = text_to_html($s->intro, false, false, true);
449 $s->introformat = FORMAT_HTML;
39ac3f6e 450 $DB->update_record('scorm', $s);
d682eadf
PS
451 upgrade_set_timeout();
452 }
453 $rs->close();
454 }
d0bcf735 455
456 /// scorm savepoint reached
a4cdd6d2 457 upgrade_mod_savepoint(true, 2009042001, 'scorm');
d0bcf735 458 }
459
a4cdd6d2 460 if ($oldversion < 2009042002) {
1bd51a6c
DM
461
462 /// Define field introformat to be added to scorm
463 $table = new xmldb_table('scorm_scoes');
464 $field = new xmldb_field('launch', XMLDB_TYPE_TEXT, 'small', null, XMLDB_NOTNULL, null, null);
465
466 /// Launch add field introformat
467 $dbman->change_field_type($table, $field);
468
469 /// scorm savepoint reached
a4cdd6d2 470 upgrade_mod_savepoint(true, 2009042002, 'scorm');
1bd51a6c 471 }
03751efe 472 if ($oldversion < 2010070800) {
b326c85a
DM
473 //check to see if this has already been tidied up by a 1.9 upgrade.
474 $grademethodfixed = get_config('scorm', 'grademethodfixed');
475 if (empty($grademethodfixed)) {
476 /// fix bad usage of whatgrade/grading method.
07b21d04 477 $scorms = $DB->get_records('scorm');
9d49a142
DM
478 if (!empty($scorm)) {
479 foreach ($scorms as $scorm) {
480 $scorm->grademethod = $scorm->grademethod%10;
481 $DB->update_record('scorm', $scorm);
482 }
07b21d04 483 }
b326c85a
DM
484 } else {
485 //dump this config var as it isn't needed anymore.
486 unset_config('grademethodfixed', 'scorm');
487 }
d682eadf 488
03751efe
DM
489 /// scorm savepoint reached
490 upgrade_mod_savepoint(true, 2010070800, 'scorm');
491 }
a4cdd6d2 492 return true;
b8a342d7 493}
494
e5dd8e3b 495