3 // This file keeps track of upgrades to
6 // Sometimes, changes between versions involve
7 // alterations to database structures and other
8 // major things that may break installations.
10 // The upgrade function in this file will attempt
11 // to perform all the necessary actions to upgrade
12 // your older installation to the current version.
14 // If there's something it cannot do itself, it
15 // will tell you what you need to do.
17 // The commands in here will all be database-neutral,
18 // using the methods of database_manager class
20 // Please do not forget to use upgrade_set_timeout()
21 // before any action that may take longer time to finish.
24 * @global moodle_database $DB
25 * @param int $oldversion
28 function xmldb_scorm_upgrade($oldversion) {
31 $dbman = $DB->get_manager();
33 //===== 1.9.0 upgrade line ======//
35 // Adding missing 'whatgrade' field to table scorm
36 if ($oldversion < 2008073000) {
37 $table = new xmldb_table('scorm');
38 $field = new xmldb_field('whatgrade');
39 $field->set_attributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'grademethod');
41 /// Launch add field whatgrade
42 if (!$dbman->field_exists($table,$field)) {
43 $dbman->add_field($table, $field);
44 $whatgradefixed = get_config('scorm', 'whatgradefixed');
45 if (empty($whatgradefixed)) {
46 /// fix bad usage of whatgrade/grading method.
47 $scorms = $DB->get_records('scorm');
48 foreach ($scorms as $scorm) {
49 $scorm->whatgrade = $scorm->grademethod/10;
50 $DB->update_record('scorm', $scorm);
54 //dump this config var as it isn't needed anymore.
55 unset_config('whatgradefixed', 'scorm');
58 upgrade_mod_savepoint(true, 2008073000, 'scorm');
61 if ($oldversion < 2008082500) {
63 /// Define field scormtype to be added to scorm
64 $table = new xmldb_table('scorm');
65 $field = new xmldb_field('scormtype', XMLDB_TYPE_CHAR, '50', null, XMLDB_NOTNULL, null, 'local', 'name');
67 /// Launch add field scormtype
68 $dbman->add_field($table, $field);
70 /// scorm savepoint reached
71 upgrade_mod_savepoint(true, 2008082500, 'scorm');
74 if ($oldversion < 2008090300) {
76 /// Define field sha1hash to be added to scorm
77 $table = new xmldb_table('scorm');
78 $field = new xmldb_field('sha1hash', XMLDB_TYPE_CHAR, '40', null, null, null, null, 'updatefreq');
80 /// Launch add field sha1hash
81 $dbman->add_field($table, $field);
83 /// scorm savepoint reached
84 upgrade_mod_savepoint(true, 2008090300, 'scorm');
87 if ($oldversion < 2008090301) {
89 /// Define field revision to be added to scorm
90 $table = new xmldb_table('scorm');
91 $field = new xmldb_field('revision', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'md5hash');
93 /// Launch add field revision
94 $dbman->add_field($table, $field);
96 /// scorm savepoint reached
97 upgrade_mod_savepoint(true, 2008090301, 'scorm');
100 if ($oldversion < 2008090302) {
101 $sql = "UPDATE {scorm}
102 SET scormtype = 'external'
103 WHERE reference LIKE ? OR reference LIKE ? OR reference LIKE ?";
104 $DB->execute($sql, array('http://%imsmanifest.xml', 'https://%imsmanifest.xml', 'www.%imsmanifest.xml'));
106 $sql = "UPDATE {scorm}
107 SET scormtype = 'localsync'
108 WHERE reference LIKE ? OR reference LIKE ? OR reference LIKE ?
109 OR reference LIKE ? OR reference LIKE ? OR reference LIKE ?";
110 $DB->execute($sql, array('http://%.zip', 'https://%.zip', 'www.%.zip', 'http://%.pif', 'https://%.pif', 'www.%.pif'));
112 $sql = "UPDATE {scorm} SET scormtype = 'imsrepository' WHERE reference LIKE ?";
113 $DB->execute($sql, array('#%'));
115 /// scorm savepoint reached
116 upgrade_mod_savepoint(true, 2008090302, 'scorm');
119 if ($oldversion < 2008090303) {
120 //remove obsoleted config settings
121 unset_config('scorm_advancedsettings');
122 unset_config('scorm_windowsettings');
124 /// scorm savepoint reached
125 upgrade_mod_savepoint(true, 2008090303, 'scorm');
128 if ($oldversion < 2008090304) {
129 /////////////////////////////////////
130 /// new file storage upgrade code ///
131 /////////////////////////////////////
133 require_once("$CFG->dirroot/mod/scorm/db/upgradelib.php");
135 $fs = get_file_storage();
137 $sqlfrom = "FROM {scorm} s
138 JOIN {modules} m ON m.name = 'scorm'
139 JOIN {course_modules} cm ON (cm.module = m.id AND cm.instance = s.id)";
141 $count = $DB->count_records_sql("SELECT COUNT('x') $sqlfrom");
143 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")) {
145 $pbar = new progress_bar('migratescormfiles', 500, true);
148 foreach ($rs as $scorm) {
150 upgrade_set_timeout(180); // set up timeout, may also abort execution
151 $pbar->update($i, $count, "Migrating scorm files - $i/$count.");
153 $context = get_context_instance(CONTEXT_MODULE, $scorm->cmid);
154 $coursecontext = get_context_instance(CONTEXT_COURSE, $scorm->course);
156 if ($scorm->scormtype === 'local' and preg_match('/.*(\.zip|\.pif)$/i', $scorm->reference)) {
157 // first copy local packages if found - do not delete in case they are shared ;-)
158 $packagefile = clean_param($scorm->reference, PARAM_PATH);
159 $pathnamehash = sha1("/$coursecontext->id/course/legacy/0/$packagefile");
160 if ($file = $fs->get_file_by_hash($pathnamehash)) {
161 $file_record = array('contextid'=>$context->id, 'component'=>'mod_scorm', 'filearea'=>'package',
162 'itemid'=>0, 'filepath'=>'/');
164 $fs->create_file_from_storedfile($file_record, $file);
165 } catch (Exception $x) {
166 // ignore any errors, we can not do much anyway
168 $scorm->reference = $file->get_filepath().$file->get_filename();
171 $scorm->reference = '';
173 $DB->update_record('scorm', $scorm);
174 // the package should be already extracted, we need to move the files there
175 // just in case somebody modified it directly there
176 scorm_migrate_moddata_files($scorm, $context);
178 } else if ($scorm->scormtype === 'local' and preg_match('/.*\/imsmanifest\.xml$/i', $scorm->reference)) {
179 // ignore imsmanifest in course root because we would be duplicating all course files which is not acceptable
180 // moddata dir is not used at all, ignore any rubbish there
181 $manifest = clean_param($scorm->reference, PARAM_PATH);
183 $pathnamehash = sha1("/$coursecontext->id/course/legacy/0/$manifest");
184 if ($file = $fs->get_file_by_hash($pathnamehash)) {
185 $scorm->reference = $file->get_filepath().$file->get_filename();
187 $manifestdir = '/'.str_ireplace('/imsmanifest.xml', '', $manifest).'/';
188 $pregmanifestdir = preg_quote($manifestdir, '/');
189 $file_record = array('contextid'=>$context->id, 'component'=>'mod_scorm', 'filearea'=>'content', 'itemid'=>0);
190 if ($files = $fs->get_directory_files($coursecontext->id, 'course', 'legacy', 0, $manifestdir, true)) {
191 foreach ($files as $file) {
192 $file_record['filepath'] = preg_replace("/^$pregmanifestdir/", '/', $file->get_filepath());
194 $fs->create_file_from_storedfile($file_record, $file);
195 } catch (Exception $x) {
196 // ignore any errors, we can not do much anyway
202 $scorm->reference = '';
204 $DB->update_record('scorm', $scorm);
207 // just try to migrate anything from moddata
208 scorm_migrate_moddata_files($scorm, $context);
211 // remove dirs if empty
212 @rmdir("$CFG->dataroot/$scorm->course/$CFG->moddata/scorm/$scorm->id/");
213 @rmdir("$CFG->dataroot/$scorm->course/$CFG->moddata/scorm/");
214 @rmdir("$CFG->dataroot/$scorm->course/$CFG->moddata/");
219 /// scorm savepoint reached
220 upgrade_mod_savepoint(true, 2008090304, 'scorm');
224 if ($oldversion < 2008090305) {
226 /// Define new fields forcecompleted, forcenewattempt, displayattemptstatus, and displaycoursestructure to be added to scorm
227 $table = new xmldb_table('scorm');
228 $field = new xmldb_field('forcecompleted', XMLDB_TYPE_INTEGER, 1, null, XMLDB_NOTNULL, null, 1, 'maxattempt');
229 if (!$dbman->field_exists($table,$field)) {
230 $dbman->add_field($table, $field);
232 $field = new xmldb_field('forcenewattempt', XMLDB_TYPE_INTEGER, 1, null, XMLDB_NOTNULL, null, 0, 'forcecompleted');
233 if (!$dbman->field_exists($table,$field)) {
234 $dbman->add_field($table, $field);
236 $field = new xmldb_field('lastattemptlock', XMLDB_TYPE_INTEGER, 1, null, XMLDB_NOTNULL, null, 0, 'forcenewattempt');
237 if (!$dbman->field_exists($table,$field)) {
238 $dbman->add_field($table, $field);
240 $field = new xmldb_field('displayattemptstatus', XMLDB_TYPE_INTEGER, 1, null, XMLDB_NOTNULL, null, 1, 'lastattemptlock');
241 if (!$dbman->field_exists($table,$field)) {
242 $dbman->add_field($table, $field);
244 $field = new xmldb_field('displaycoursestructure', XMLDB_TYPE_INTEGER, 1, null, XMLDB_NOTNULL, null, 1, 'displayattemptstatus');
245 if (!$dbman->field_exists($table,$field)) {
246 $dbman->add_field($table, $field);
249 /// scorm savepoint reached
250 upgrade_mod_savepoint(true, 2008090305, 'scorm');
254 // remove redundant config values
255 if ($oldversion < 2008090306) {
257 * comment this out as it is handled by the update mark 2008090310 below
258 * left for historical documentation as some early adopters may have done
260 $redundant_config = array(
261 'scorm_allowapidebug',
262 'scorm_allowtypeexternal',
263 'scorm_allowtypeimsrepository',
264 'scorm_allowtypelocalsync',
265 'scorm_apidebugmask',
270 foreach ($redundant_config as $rcfg) {
271 if (isset($CFG->$rcfg)) {
276 /// scorm savepoint reached
277 upgrade_mod_savepoint(true, 2008090306, 'scorm');
282 // remove redundant config values
283 if ($oldversion < 2008090307) {
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
288 $redundant_config = array(
289 'scorm_allowapidebug',
290 'scorm_allowtypeexternal',
291 'scorm_allowtypeimsrepository',
292 'scorm_allowtypelocalsync',
293 'scorm_apidebugmask',
316 foreach ($redundant_config as $rcfg) {
317 if (isset($CFG->$rcfg)) {
323 /// scorm savepoint reached
324 upgrade_mod_savepoint(true, 2008090307, 'scorm');
327 if ($oldversion < 2008090308) {
328 $table = new xmldb_table('scorm');
329 $field = new xmldb_field('timeopen', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'height');
330 if (!$dbman->field_exists($table,$field)) {
331 $dbman->add_field($table, $field);
333 $field = new xmldb_field('timeclose', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'timeopen');
334 if (!$dbman->field_exists($table,$field)) {
335 $dbman->add_field($table, $field);
338 /// scorm savepoint reached
339 upgrade_mod_savepoint(true, 2008090308, 'scorm');
343 if ($oldversion < 2008090310) {
344 // take above blocks that delete config and move the values in to config_plugins
346 $redundant_config = array(
347 'scorm_allowapidebug',
348 'scorm_allowtypeexternal',
349 'scorm_allowtypeimsrepository',
350 'scorm_allowtypelocalsync',
351 'scorm_apidebugmask',
373 'scorm_displayattemptstatus',
374 'scorm_displaycoursestructure',
375 'scorm_forcecompleted',
376 'scorm_forcenewattempt',
377 'scorm_lastattemptlock'
380 foreach ($redundant_config as $rcfg) {
381 if (isset($CFG->$rcfg)) {
382 $shortname = substr($rcfg, 6);
383 set_config($shortname, $CFG->$rcfg, 'scorm');
388 /// scorm savepoint reached
389 upgrade_mod_savepoint(true, 2008090310, 'scorm');
392 if ($oldversion < 2009042000) {
394 /// Rename field summary on table scorm to intro
395 $table = new xmldb_table('scorm');
396 $field = new xmldb_field('summary', XMLDB_TYPE_TEXT, 'small', null, XMLDB_NOTNULL, null, null, 'reference');
398 /// Launch rename field summary
399 $dbman->rename_field($table, $field, 'intro');
401 /// scorm savepoint reached
402 upgrade_mod_savepoint(true, 2009042000, 'scorm');
405 if ($oldversion < 2009042001) {
407 /// Define field introformat to be added to scorm
408 $table = new xmldb_table('scorm');
409 $field = new xmldb_field('introformat', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'intro');
411 /// Launch add field introformat
412 if (!$dbman->field_exists($table, $field)) {
413 $dbman->add_field($table, $field);
416 // conditionally migrate to html format in intro
417 if ($CFG->texteditors !== 'textarea') {
418 $rs = $DB->get_recordset('scorm', array('introformat'=>FORMAT_MOODLE), '', 'id,intro,introformat');
419 foreach ($rs as $s) {
420 $s->intro = text_to_html($s->intro, false, false, true);
421 $s->introformat = FORMAT_HTML;
422 $DB->update_record('scorm', $s);
423 upgrade_set_timeout();
428 /// scorm savepoint reached
429 upgrade_mod_savepoint(true, 2009042001, 'scorm');
432 if ($oldversion < 2009042002) {
434 /// Define field introformat to be added to scorm
435 $table = new xmldb_table('scorm_scoes');
436 $field = new xmldb_field('launch', XMLDB_TYPE_TEXT, 'small', null, XMLDB_NOTNULL, null, null);
438 /// Launch add field introformat
439 $dbman->change_field_type($table, $field);
441 /// scorm savepoint reached
442 upgrade_mod_savepoint(true, 2009042002, 'scorm');
444 if ($oldversion < 2010070800) {
445 //check to see if this has already been tidied up by a 1.9 upgrade.
446 $grademethodfixed = get_config('scorm', 'grademethodfixed');
447 if (empty($grademethodfixed)) {
448 /// fix bad usage of whatgrade/grading method.
449 $scorms = $DB->get_records('scorm');
450 if (!empty($scorm)) {
451 foreach ($scorms as $scorm) {
452 $scorm->grademethod = $scorm->grademethod%10;
453 $DB->update_record('scorm', $scorm);
457 //dump this config var as it isn't needed anymore.
458 unset_config('grademethodfixed', 'scorm');
461 /// scorm savepoint reached
462 upgrade_mod_savepoint(true, 2010070800, 'scorm');
464 if ($oldversion < 2010092400) {
465 $count = $DB->count_records('scorm', array('scormtype'=>'external'));
466 if (!empty($count)) {
467 set_config('allowtypeexternal', '1', 'scorm');
469 $count = $DB->count_records('scorm', array('scormtype'=>'localsync'));
470 if (!empty($count)) {
471 set_config('allowtypelocalsync', '1', 'scorm');
473 $count = $DB->count_records('scorm', array('scormtype'=>'imsrepository'));
474 if (!empty($count)) {
475 set_config('allowtypeimsrepository', '1', 'scorm');
477 /// scorm savepoint reached
478 upgrade_mod_savepoint(true, 2010092400, 'scorm');
481 if ($oldversion < 2011011400) {
482 // Fix scorm in the post table after upgrade from 1.9
483 $table = new xmldb_table('scorm');
484 $columns = $DB->get_columns('scorm');
486 // forcecompleted should be bigint(1) NOT NULL DEFAULT '1'
487 // Fixed in earlier upgrade code
488 $field = new xmldb_field('forcecompleted', XMLDB_TYPE_INTEGER, 1, null, XMLDB_NOTNULL, null, 1, 'maxattempt');
489 if ($dbman->field_exists($table, $field)) {
490 $dbman->change_field_precision($table, $field);
493 if (array_key_exists('forcenewattempt', $columns) && empty($columns['forcenewattempt']->not_null)) {
494 // forcenewattempt should be NOT NULL
495 // Fixed in earlier upgrade code
496 $field = new xmldb_field('forcenewattempt', XMLDB_TYPE_INTEGER, 1, null, XMLDB_NOTNULL, null, 0, 'forcecompleted');
497 if ($dbman->field_exists($table, $field)) {
498 $dbman->change_field_notnull($table, $field);
502 if (array_key_exists('lastattemptlock', $columns) && empty($columns['lastattemptlock']->not_null)) {
503 // lastattemptlock should be NOT NULL
504 // Fixed in earlier upgrade code
505 $field = new xmldb_field('lastattemptlock', XMLDB_TYPE_INTEGER, 1, null, XMLDB_NOTNULL, null, 0, 'forcenewattempt');
506 if ($dbman->field_exists($table, $field)) {
507 $dbman->change_field_notnull($table, $field);
511 if (array_key_exists('displayattemptstatus', $columns) && empty($columns['displayattemptstatus']->not_null)) {
512 // displayattemptstatus should be NOT NULL
513 // Fixed in earlier upgrade code
514 $field = new xmldb_field('displayattemptstatus', XMLDB_TYPE_INTEGER, 1, null, XMLDB_NOTNULL, null, 1, 'lastattemptlock');
515 if ($dbman->field_exists($table, $field)) {
516 $dbman->change_field_notnull($table, $field);
520 if (array_key_exists('displaycoursestructure', $columns) && empty($columns['displaycoursestructure']->not_null)) {
521 // displaycoursestructure should be NOT NULL
522 // Fixed in earlier upgrade code
523 $field = new xmldb_field('displaycoursestructure', XMLDB_TYPE_INTEGER, 1, null, XMLDB_NOTNULL, null, 1, 'displayattemptstatus');
524 if ($dbman->field_exists($table, $field)) {
525 $dbman->change_field_notnull($table, $field);
529 upgrade_mod_savepoint(true, 2011011400, 'scorm');