2ae31fab7542969901d2ba154fc4ed4b633e792e
[moodle.git] / lib / db / upgrade.php
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
17 /**
18  * This file keeps track of upgrades to Moodle.
19  *
20  * Sometimes, changes between versions involve
21  * alterations to database structures and other
22  * major things that may break installations.
23  *
24  * The upgrade function in this file will attempt
25  * to perform all the necessary actions to upgrade
26  * your older installation to the current version.
27  *
28  * If there's something it cannot do itself, it
29  * will tell you what you need to do.
30  *
31  * The commands in here will all be database-neutral,
32  * using the methods of database_manager class
33  *
34  * Please do not forget to use upgrade_set_timeout()
35  * before any action that may take longer time to finish.
36  *
37  * @package   core_install
38  * @category  upgrade
39  * @copyright 2006 onwards Martin Dougiamas  http://dougiamas.com
40  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
41  */
43 defined('MOODLE_INTERNAL') || die();
45 /**
46  * Main upgrade tasks to be executed on Moodle version bump
47  *
48  * This function is automatically executed after one bump in the Moodle core
49  * version is detected. It's in charge of performing the required tasks
50  * to raise core from the previous version to the next one.
51  *
52  * It's a collection of ordered blocks of code, named "upgrade steps",
53  * each one performing one isolated (from the rest of steps) task. Usually
54  * tasks involve creating new DB objects or performing manipulation of the
55  * information for cleanup/fixup purposes.
56  *
57  * Each upgrade step has a fixed structure, that can be summarised as follows:
58  *
59  * if ($oldversion < XXXXXXXXXX.XX) {
60  *     // Explanation of the update step, linking to issue in the Tracker if necessary
61  *     upgrade_set_timeout(XX); // Optional for big tasks
62  *     // Code to execute goes here, usually the XMLDB Editor will
63  *     // help you here. See {@link http://docs.moodle.org/dev/XMLDB_editor}.
64  *     upgrade_main_savepoint(true, XXXXXXXXXX.XX);
65  * }
66  *
67  * All plugins within Moodle (modules, blocks, reports...) support the existence of
68  * their own upgrade.php file, using the "Frankenstyle" component name as
69  * defined at {@link http://docs.moodle.org/dev/Frankenstyle}, for example:
70  *     - {@link xmldb_page_upgrade($oldversion)}. (modules don't require the plugintype ("mod_") to be used.
71  *     - {@link xmldb_auth_manual_upgrade($oldversion)}.
72  *     - {@link xmldb_workshopform_accumulative_upgrade($oldversion)}.
73  *     - ....
74  *
75  * In order to keep the contents of this file reduced, it's allowed to create some helper
76  * functions to be used here in the {@link upgradelib.php} file at the same directory. Note
77  * that such a file must be manually included from upgrade.php, and there are some restrictions
78  * about what can be used within it.
79  *
80  * For more information, take a look to the documentation available:
81  *     - Data definition API: {@link http://docs.moodle.org/dev/Data_definition_API}
82  *     - Upgrade API: {@link http://docs.moodle.org/dev/Upgrade_API}
83  *
84  * @param int $oldversion
85  * @return bool always true
86  */
87 function xmldb_main_upgrade($oldversion) {
88     global $CFG, $USER, $DB, $OUTPUT, $SITE, $COURSE;
90     require_once($CFG->libdir.'/db/upgradelib.php'); // Core Upgrade-related functions
92     $dbman = $DB->get_manager(); // loads ddl manager and xmldb classes
94     if ($oldversion < 2011120500) {
95         // just in case somebody hacks upgrade scripts or env, we really can not continue
96         echo("You need to upgrade to 2.2.x first!\n");
97         exit(1);
98         // Note this savepoint is 100% unreachable, but needed to pass the upgrade checks
99         upgrade_main_savepoint(true, 2011120500);
100     }
102     // Moodle v2.2.0 release upgrade line
103     // Put any upgrade step following this
105     if ($oldversion < 2011120500.02) {
107         upgrade_set_timeout(60*20); // This may take a while
108         // MDL-28180. Some missing restrictions in certain backup & restore operations
109         // were causing incorrect duplicates in the course_completion_aggr_methd table.
110         // This upgrade step takes rid of them.
111         $sql = 'SELECT course, criteriatype, MIN(id) AS minid
112                   FROM {course_completion_aggr_methd}
113               GROUP BY course, criteriatype
114                 HAVING COUNT(*) > 1';
115         $duprs = $DB->get_recordset_sql($sql);
116         foreach ($duprs as $duprec) {
117             // We need to handle NULLs in criteriatype diferently
118             if (is_null($duprec->criteriatype)) {
119                 $where = 'course = ? AND criteriatype IS NULL AND id > ?';
120                 $params = array($duprec->course, $duprec->minid);
121             } else {
122                 $where = 'course = ? AND criteriatype = ? AND id > ?';
123                 $params = array($duprec->course, $duprec->criteriatype, $duprec->minid);
124             }
125             $DB->delete_records_select('course_completion_aggr_methd', $where, $params);
126         }
127         $duprs->close();
129         // Main savepoint reached
130         upgrade_main_savepoint(true, 2011120500.02);
131     }
133     if ($oldversion < 2011120500.03) {
135         // Changing precision of field value on table user_preferences to (1333)
136         $table = new xmldb_table('user_preferences');
137         $field = new xmldb_field('value', XMLDB_TYPE_CHAR, '1333', null, XMLDB_NOTNULL, null, null, 'name');
139         // Launch change of precision for field value
140         $dbman->change_field_precision($table, $field);
142         // Main savepoint reached
143         upgrade_main_savepoint(true, 2011120500.03);
144     }
146     if ($oldversion < 2012020200.03) {
148         // Define index rolecontext (not unique) to be added to role_assignments
149         $table = new xmldb_table('role_assignments');
150         $index = new xmldb_index('rolecontext', XMLDB_INDEX_NOTUNIQUE, array('roleid', 'contextid'));
152         // Conditionally launch add index rolecontext
153         if (!$dbman->index_exists($table, $index)) {
154             $dbman->add_index($table, $index);
155         }
157         // Define index usercontextrole (not unique) to be added to role_assignments
158         $index = new xmldb_index('usercontextrole', XMLDB_INDEX_NOTUNIQUE, array('userid', 'contextid', 'roleid'));
160         // Conditionally launch add index usercontextrole
161         if (!$dbman->index_exists($table, $index)) {
162             $dbman->add_index($table, $index);
163         }
165         // Main savepoint reached
166         upgrade_main_savepoint(true, 2012020200.03);
167     }
169     if ($oldversion < 2012020200.06) {
170         // Previously we always allowed users to override their email address via the messaging system
171         // We have now added a setting to allow admins to turn this this ability on and off
172         // While this setting defaults to 0 (off) we're setting it to 1 (on) to maintain the behaviour for upgrading sites
173         set_config('messagingallowemailoverride', 1);
175         // Main savepoint reached
176         upgrade_main_savepoint(true, 2012020200.06);
177     }
179     if ($oldversion < 2012021700.01) {
180         // Changing precision of field uniquehash on table post to 255
181         $table = new xmldb_table('post');
182         $field = new xmldb_field('uniquehash', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'content');
184         // Launch change of precision for field uniquehash
185         $dbman->change_field_precision($table, $field);
187         // Main savepoint reached
188         upgrade_main_savepoint(true, 2012021700.01);
189     }
191     if ($oldversion < 2012021700.02) {
192         // Somewhere before 1.9 summary and content column in post table were not null. In 1.9+
193         // not null became false.
194         $columns = $DB->get_columns('post');
196         // Fix discrepancies in summary field after upgrade from 1.9
197         if (array_key_exists('summary', $columns) && $columns['summary']->not_null != false) {
198             $table = new xmldb_table('post');
199             $summaryfield = new xmldb_field('summary', XMLDB_TYPE_TEXT, 'big', null, null, null, null, 'subject');
201             if ($dbman->field_exists($table, $summaryfield)) {
202                 $dbman->change_field_notnull($table, $summaryfield);
203             }
205         }
207         // Fix discrepancies in content field after upgrade from 1.9
208         if (array_key_exists('content', $columns) && $columns['content']->not_null != false) {
209             $table = new xmldb_table('post');
210             $contentfield = new xmldb_field('content', XMLDB_TYPE_TEXT, 'big', null, null, null, null, 'summary');
212             if ($dbman->field_exists($table, $contentfield)) {
213                 $dbman->change_field_notnull($table, $contentfield);
214             }
216         }
218         upgrade_main_savepoint(true, 2012021700.02);
219     }
221     // The ability to backup user (private) files is out completely - MDL-29248
222     if ($oldversion < 2012030100.01) {
223         unset_config('backup_general_user_files', 'backup');
224         unset_config('backup_general_user_files_locked', 'backup');
225         unset_config('backup_auto_user_files', 'backup');
227         upgrade_main_savepoint(true, 2012030100.01);
228     }
230     if ($oldversion < 2012030900.01) {
231         // Migrate all numbers to signed & all texts and binaries to big size.
232         // It should be safe to interrupt this and continue later.
233         upgrade_mysql_fix_unsigned_and_lob_columns();
235         // Main savepoint reached
236         upgrade_main_savepoint(true, 2012030900.01);
237     }
239     if ($oldversion < 2012031500.01) {
240         // Upgrade old course_allowed_modules data to be permission overrides.
241         if ($CFG->restrictmodulesfor === 'all') {
242             $courses = $DB->get_records_menu('course', array(), 'id', 'id, 1');
243         } else if ($CFG->restrictmodulesfor === 'requested') {
244             $courses = $DB->get_records_menu('course', array('restrictmodules' => 1), 'id', 'id, 1');
245         } else {
246             $courses = array();
247         }
249         if (!$dbman->table_exists('course_allowed_modules')) {
250             // Upgrade must already have been run on this server. This might happen,
251             // for example, during development of these changes.
252             $courses = array();
253         }
255         $modidtoname = $DB->get_records_menu('modules', array(), 'id', 'id, name');
257         $coursecount = count($courses);
258         if ($coursecount) {
259             $pbar = new progress_bar('allowedmods', 500, true);
260             $transaction = $DB->start_delegated_transaction();
261         }
263         $i = 0;
264         foreach ($courses as $courseid => $notused) {
265             $i += 1;
266             upgrade_set_timeout(60); // 1 minute per course should be fine.
268             $allowedmoduleids = $DB->get_records_menu('course_allowed_modules',
269             array('course' => $courseid), 'module', 'module, 1');
270             if (empty($allowedmoduleids)) {
271                 // This seems to be the best match for backwards compatibility,
272                 // not necessarily with the old code in course_allowed_module function,
273                 // but with the code that used to be in the coures settings form.
274                 $allowedmoduleids = explode(',', $CFG->defaultallowedmodules);
275                 $allowedmoduleids = array_combine($allowedmoduleids, $allowedmoduleids);
276             }
278             $context = context_course::instance($courseid);
280             list($roleids) = get_roles_with_cap_in_context($context, 'moodle/course:manageactivities');
281             list($managerroleids) = get_roles_with_cap_in_context($context, 'moodle/site:config');
282             foreach ($managerroleids as $roleid) {
283                 unset($roleids[$roleid]);
284             }
286             foreach ($modidtoname as $modid => $modname) {
287                 if (isset($allowedmoduleids[$modid])) {
288                     // Module is allowed, no worries.
289                     continue;
290                 }
292                 $capability = 'mod/' . $modname . ':addinstance';
293                 foreach ($roleids as $roleid) {
294                     assign_capability($capability, CAP_PREVENT, $roleid, $context);
295                 }
296             }
298             $pbar->update($i, $coursecount, "Upgrading legacy course_allowed_modules data - $i/$coursecount.");
299         }
301         if ($coursecount) {
302             $transaction->allow_commit();
303         }
305         upgrade_main_savepoint(true, 2012031500.01);
306     }
308     if ($oldversion < 2012031500.02) {
310         // Define field restrictmodules to be dropped from course
311         $table = new xmldb_table('course');
312         $field = new xmldb_field('restrictmodules');
314         // Conditionally launch drop field requested
315         if ($dbman->field_exists($table, $field)) {
316             $dbman->drop_field($table, $field);
317         }
319         // Since structure of 'course' table has changed we need to re-read $SITE from DB.
320         $SITE = $DB->get_record('course', array('id' => $SITE->id));
321         $COURSE = clone($SITE);
323         upgrade_main_savepoint(true, 2012031500.02);
324     }
326     if ($oldversion < 2012031500.03) {
328         // Define table course_allowed_modules to be dropped
329         $table = new xmldb_table('course_allowed_modules');
331         // Conditionally launch drop table for course_allowed_modules
332         if ($dbman->table_exists($table)) {
333             $dbman->drop_table($table);
334         }
336         upgrade_main_savepoint(true, 2012031500.03);
337     }
339     if ($oldversion < 2012031500.04) {
340         // Clean up the old admin settings.
341         unset_config('restrictmodulesfor');
342         unset_config('restrictbydefault');
343         unset_config('defaultallowedmodules');
345         upgrade_main_savepoint(true, 2012031500.04);
346     }
348     if ($oldversion < 2012032300.02) {
349         // Migrate the old admin debug setting.
350         if ($CFG->debug == 38911) {
351             set_config('debug', DEBUG_DEVELOPER);
352         } else if ($CFG->debug == 6143) {
353             set_config('debug', DEBUG_ALL);
354         }
355         upgrade_main_savepoint(true, 2012032300.02);
356     }
358     if ($oldversion < 2012042300.00) {
359         // This change makes the course_section index unique.
361         // xmldb does not allow changing index uniqueness - instead we must drop
362         // index then add it again
363         $table = new xmldb_table('course_sections');
364         $index = new xmldb_index('course_section', XMLDB_INDEX_NOTUNIQUE, array('course', 'section'));
366         // Conditionally launch drop index course_section
367         if ($dbman->index_exists($table, $index)) {
368             $dbman->drop_index($table, $index);
369         }
371         // Look for any duplicate course_sections entries. There should not be
372         // any but on some busy systems we found a few, maybe due to previous
373         // bugs.
374         $transaction = $DB->start_delegated_transaction();
375         $rs = $DB->get_recordset_sql('
376                 SELECT DISTINCT
377                     cs.id, cs.course
378                 FROM
379                     {course_sections} cs
380                     INNER JOIN {course_sections} older
381                         ON cs.course = older.course AND cs.section = older.section
382                         AND older.id < cs.id');
383         foreach ($rs as $rec) {
384             $DB->delete_records('course_sections', array('id' => $rec->id));
385             // We can't use rebuild_course_cache() here because introducing sectioncache later
386             // so reset modinfo manually.
387             $DB->set_field('course', 'modinfo', null, array('id' => $rec->course));
388         }
389         $rs->close();
390         $transaction->allow_commit();
392         // Define index course_section (unique) to be added to course_sections
393         $index = new xmldb_index('course_section', XMLDB_INDEX_UNIQUE, array('course', 'section'));
395         // Conditionally launch add index course_section
396         if (!$dbman->index_exists($table, $index)) {
397             $dbman->add_index($table, $index);
398         }
400         // Main savepoint reached
401         upgrade_main_savepoint(true, 2012042300.00);
402     }
404     if ($oldversion < 2012042300.02) {
405         require_once($CFG->dirroot.'/completion/criteria/completion_criteria.php');
406         // Delete orphaned criteria which were left when modules were removed
407         if ($DB->get_dbfamily() === 'mysql') {
408             $sql = "DELETE cc FROM {course_completion_criteria} cc
409                     LEFT JOIN {course_modules} cm ON cm.id = cc.moduleinstance
410                     WHERE cm.id IS NULL AND cc.criteriatype = ".COMPLETION_CRITERIA_TYPE_ACTIVITY;
411         } else {
412             $sql = "DELETE FROM {course_completion_criteria}
413                     WHERE NOT EXISTS (
414                         SELECT 'x' FROM {course_modules}
415                         WHERE {course_modules}.id = {course_completion_criteria}.moduleinstance)
416                     AND {course_completion_criteria}.criteriatype = ".COMPLETION_CRITERIA_TYPE_ACTIVITY;
417         }
418         $DB->execute($sql);
420         // Main savepoint reached
421         upgrade_main_savepoint(true, 2012042300.02);
422     }
424     if ($oldversion < 2012050300.01) {
425         // Make sure deleted users do not have picture flag.
426         $DB->set_field('user', 'picture', 0, array('deleted'=>1, 'picture'=>1));
427         upgrade_main_savepoint(true, 2012050300.01);
428     }
430     if ($oldversion < 2012050300.02) {
432         // Changing precision of field picture on table user to (10)
433         $table = new xmldb_table('user');
434         $field = new xmldb_field('picture', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'secret');
436         // Launch change of precision for field picture
437         $dbman->change_field_precision($table, $field);
439         // Main savepoint reached
440         upgrade_main_savepoint(true, 2012050300.02);
441     }
443     if ($oldversion < 2012050300.03) {
445         // Define field coursedisplay to be added to course
446         $table = new xmldb_table('course');
447         $field = new xmldb_field('coursedisplay', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0', 'completionnotify');
449         // Conditionally launch add field coursedisplay
450         if (!$dbman->field_exists($table, $field)) {
451             $dbman->add_field($table, $field);
452         }
454         // Since structure of 'course' table has changed we need to re-read $SITE from DB.
455         $SITE = $DB->get_record('course', array('id' => $SITE->id));
456         $COURSE = clone($SITE);
458         // Main savepoint reached
459         upgrade_main_savepoint(true, 2012050300.03);
460     }
462     if ($oldversion < 2012050300.04) {
464         // Define table course_display to be dropped
465         $table = new xmldb_table('course_display');
467         // Conditionally launch drop table for course_display
468         if ($dbman->table_exists($table)) {
469             $dbman->drop_table($table);
470         }
472         // Main savepoint reached
473         upgrade_main_savepoint(true, 2012050300.04);
474     }
476     if ($oldversion < 2012050300.05) {
478         // Clean up removed admin setting.
479         unset_config('navlinkcoursesections');
481         upgrade_main_savepoint(true, 2012050300.05);
482     }
484     if ($oldversion < 2012050400.01) {
486         // Define index sortorder (not unique) to be added to course
487         $table = new xmldb_table('course');
488         $index = new xmldb_index('sortorder', XMLDB_INDEX_NOTUNIQUE, array('sortorder'));
490         // Conditionally launch add index sortorder
491         if (!$dbman->index_exists($table, $index)) {
492             $dbman->add_index($table, $index);
493         }
495         // Main savepoint reached
496         upgrade_main_savepoint(true, 2012050400.01);
497     }
499     if ($oldversion < 2012050400.02) {
501         // Clean up removed admin setting.
502         unset_config('enablecourseajax');
504         upgrade_main_savepoint(true, 2012050400.02);
505     }
507     if ($oldversion < 2012051100.01) {
509         // Define field idnumber to be added to groups
510         $table = new xmldb_table('groups');
511         $field = new xmldb_field('idnumber', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null, 'courseid');
512         $index = new xmldb_index('idnumber', XMLDB_INDEX_NOTUNIQUE, array('idnumber'));
514         // Conditionally launch add field idnumber
515         if (!$dbman->field_exists($table, $field)) {
516             $dbman->add_field($table, $field);
517         }
519         // Conditionally launch add index idnumber
520         if (!$dbman->index_exists($table, $index)) {
521             $dbman->add_index($table, $index);
522         }
524         // Define field idnumber to be added to groupings
525         $table = new xmldb_table('groupings');
526         $field = new xmldb_field('idnumber', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null, 'name');
527         $index = new xmldb_index('idnumber', XMLDB_INDEX_NOTUNIQUE, array('idnumber'));
529         // Conditionally launch add field idnumber
530         if (!$dbman->field_exists($table, $field)) {
531             $dbman->add_field($table, $field);
532         }
534         // Conditionally launch add index idnumber
535         if (!$dbman->index_exists($table, $index)) {
536             $dbman->add_index($table, $index);
537         }
539         // Main savepoint reached
540         upgrade_main_savepoint(true, 2012051100.01);
541     }
543     if ($oldversion < 2012051100.03) {
545         // Amend course table to add sectioncache cache
546         $table = new xmldb_table('course');
547         $field = new xmldb_field('sectioncache', XMLDB_TYPE_TEXT, null, null, null, null, null, 'showgrades');
548         if (!$dbman->field_exists($table, $field)) {
549             $dbman->add_field($table, $field);
550         }
552         // Amend course_sections to add date, time and groupingid availability
553         // conditions and a setting about whether to show them
554         $table = new xmldb_table('course_sections');
555         $field = new xmldb_field('availablefrom', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'visible');
556         if (!$dbman->field_exists($table, $field)) {
557             $dbman->add_field($table, $field);
558         }
559         $field = new xmldb_field('availableuntil', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'availablefrom');
560         if (!$dbman->field_exists($table, $field)) {
561             $dbman->add_field($table, $field);
562         }
563         $field = new xmldb_field('showavailability', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'availableuntil');
564         // Conditionally launch add field showavailability
565         if (!$dbman->field_exists($table, $field)) {
566             $dbman->add_field($table, $field);
567         }
568         $field = new xmldb_field('groupingid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'showavailability');
569         // Conditionally launch add field groupingid
570         if (!$dbman->field_exists($table, $field)) {
571             $dbman->add_field($table, $field);
572         }
574         // Since structure of 'course' table has changed we need to re-read $SITE from DB.
575         $SITE = $DB->get_record('course', array('id' => $SITE->id));
576         $COURSE = clone($SITE);
578         // Add course_sections_availability to add completion & grade availability conditions
579         $table = new xmldb_table('course_sections_availability');
581         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
582         $table->add_field('coursesectionid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
583         $table->add_field('sourcecmid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
584         $table->add_field('requiredcompletion', XMLDB_TYPE_INTEGER, '1', null, null, null, null);
585         $table->add_field('gradeitemid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
586         $table->add_field('grademin', XMLDB_TYPE_NUMBER, '10, 5', null, null, null, null);
587         $table->add_field('grademax', XMLDB_TYPE_NUMBER, '10, 5', null, null, null, null);
589         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
590         $table->add_key('coursesectionid', XMLDB_KEY_FOREIGN, array('coursesectionid'), 'course_sections', array('id'));
591         $table->add_key('sourcecmid', XMLDB_KEY_FOREIGN, array('sourcecmid'), 'course_modules', array('id'));
592         $table->add_key('gradeitemid', XMLDB_KEY_FOREIGN, array('gradeitemid'), 'grade_items', array('id'));
594         if (!$dbman->table_exists($table)) {
595             $dbman->create_table($table);
596         }
598         // Main savepoint reached
599         upgrade_main_savepoint(true, 2012051100.03);
600     }
602     if ($oldversion < 2012052100.00) {
604         // Define field referencefileid to be added to files.
605         $table = new xmldb_table('files');
607         // Define field referencefileid to be added to files.
608         $field = new xmldb_field('referencefileid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'sortorder');
610         // Conditionally launch add field referencefileid.
611         if (!$dbman->field_exists($table, $field)) {
612             $dbman->add_field($table, $field);
613         }
615         // Define field referencelastsync to be added to files.
616         $field = new xmldb_field('referencelastsync', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'referencefileid');
618         // Conditionally launch add field referencelastsync.
619         if (!$dbman->field_exists($table, $field)) {
620             $dbman->add_field($table, $field);
621         }
623         // Define field referencelifetime to be added to files.
624         $field = new xmldb_field('referencelifetime', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'referencelastsync');
626         // Conditionally launch add field referencelifetime.
627         if (!$dbman->field_exists($table, $field)) {
628             $dbman->add_field($table, $field);
629         }
631         $key = new xmldb_key('referencefileid', XMLDB_KEY_FOREIGN, array('referencefileid'), 'files_reference', array('id'));
632         // Launch add key referencefileid
633         $dbman->add_key($table, $key);
635         // Define table files_reference to be created.
636         $table = new xmldb_table('files_reference');
638         // Adding fields to table files_reference.
639         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
640         $table->add_field('repositoryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
641         $table->add_field('lastsync', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
642         $table->add_field('lifetime', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
643         $table->add_field('reference', XMLDB_TYPE_TEXT, null, null, null, null, null);
645         // Adding keys to table files_reference.
646         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
647         $table->add_key('repositoryid', XMLDB_KEY_FOREIGN, array('repositoryid'), 'repository_instances', array('id'));
649         // Conditionally launch create table for files_reference
650         if (!$dbman->table_exists($table)) {
651             $dbman->create_table($table);
652         }
654         // Main savepoint reached
655         upgrade_main_savepoint(true, 2012052100.00);
656     }
658     if ($oldversion < 2012052500.03) { // fix invalid course_completion_records MDL-27368
659         //first get all instances of duplicate records
660         $sql = 'SELECT userid, course FROM {course_completions} WHERE (deleted IS NULL OR deleted <> 1) GROUP BY userid, course HAVING (count(id) > 1)';
661         $duplicates = $DB->get_recordset_sql($sql, array());
663         foreach ($duplicates as $duplicate) {
664             $pointer = 0;
665             //now get all the records for this user/course
666             $sql = 'userid = ? AND course = ? AND (deleted IS NULL OR deleted <> 1)';
667             $completions = $DB->get_records_select('course_completions', $sql,
668                 array($duplicate->userid, $duplicate->course), 'timecompleted DESC, timestarted DESC');
669             $needsupdate = false;
670             $origcompletion = null;
671             foreach ($completions as $completion) {
672                 $pointer++;
673                 if ($pointer === 1) { //keep 1st record but delete all others.
674                     $origcompletion = $completion;
675                 } else {
676                     //we need to keep the "oldest" of all these fields as the valid completion record.
677                     $fieldstocheck = array('timecompleted', 'timestarted', 'timeenrolled');
678                     foreach ($fieldstocheck as $f) {
679                         if ($origcompletion->$f > $completion->$f) {
680                             $origcompletion->$f = $completion->$f;
681                             $needsupdate = true;
682                         }
683                     }
684                     $DB->delete_records('course_completions', array('id'=>$completion->id));
685                 }
686             }
687             if ($needsupdate) {
688                 $DB->update_record('course_completions', $origcompletion);
689             }
690         }
692         // Main savepoint reached
693         upgrade_main_savepoint(true, 2012052500.03);
694     }
696     if ($oldversion < 2012052900.00) {
697         // Clean up all duplicate records in the course_completions table in preparation
698         // for adding a new index there.
699         upgrade_course_completion_remove_duplicates(
700             'course_completions',
701             array('userid', 'course'),
702             array('timecompleted', 'timestarted', 'timeenrolled')
703         );
705         // Main savepoint reached
706         upgrade_main_savepoint(true, 2012052900.00);
707     }
709     if ($oldversion < 2012052900.01) {
710         // Add indexes to prevent new duplicates in the course_completions table.
711         // Define index useridcourse (unique) to be added to course_completions
712         $table = new xmldb_table('course_completions');
713         $index = new xmldb_index('useridcourse', XMLDB_INDEX_UNIQUE, array('userid', 'course'));
715         // Conditionally launch add index useridcourse
716         if (!$dbman->index_exists($table, $index)) {
717             $dbman->add_index($table, $index);
718         }
720         // Main savepoint reached
721         upgrade_main_savepoint(true, 2012052900.01);
722     }
724     if ($oldversion < 2012052900.02) {
725         // Clean up all duplicate records in the course_completion_crit_compl table in preparation
726         // for adding a new index there.
727         upgrade_course_completion_remove_duplicates(
728             'course_completion_crit_compl',
729             array('userid', 'course', 'criteriaid'),
730             array('timecompleted')
731         );
733         // Main savepoint reached
734         upgrade_main_savepoint(true, 2012052900.02);
735     }
737     if ($oldversion < 2012052900.03) {
738         // Add indexes to prevent new duplicates in the course_completion_crit_compl table.
739         // Define index useridcoursecriteraid (unique) to be added to course_completion_crit_compl
740         $table = new xmldb_table('course_completion_crit_compl');
741         $index = new xmldb_index('useridcoursecriteraid', XMLDB_INDEX_UNIQUE, array('userid', 'course', 'criteriaid'));
743         // Conditionally launch add index useridcoursecriteraid
744         if (!$dbman->index_exists($table, $index)) {
745             $dbman->add_index($table, $index);
746         }
748         // Main savepoint reached
749         upgrade_main_savepoint(true, 2012052900.03);
750     }
752     if ($oldversion < 2012052900.04) {
753         // Clean up all duplicate records in the course_completion_aggr_methd table in preparation
754         // for adding a new index there.
755         upgrade_course_completion_remove_duplicates(
756             'course_completion_aggr_methd',
757             array('course', 'criteriatype')
758         );
760         // Main savepoint reached
761         upgrade_main_savepoint(true, 2012052900.04);
762     }
764     if ($oldversion < 2012052900.05) {
765         // Add indexes to prevent new duplicates in the course_completion_aggr_methd table.
766         // Define index coursecriteratype (unique) to be added to course_completion_aggr_methd
767         $table = new xmldb_table('course_completion_aggr_methd');
768         $index = new xmldb_index('coursecriteriatype', XMLDB_INDEX_UNIQUE, array('course', 'criteriatype'));
770         // Conditionally launch add index coursecriteratype
771         if (!$dbman->index_exists($table, $index)) {
772             $dbman->add_index($table, $index);
773         }
775         // Main savepoint reached
776         upgrade_main_savepoint(true, 2012052900.05);
777     }
779     if ($oldversion < 2012060600.01) {
780         // Add field referencehash to files_reference
781         $table = new xmldb_table('files_reference');
782         $field = new xmldb_field('referencehash', XMLDB_TYPE_CHAR, '40', null, XMLDB_NOTNULL, null, null, 'reference');
783         if (!$dbman->field_exists($table, $field)) {
784             $dbman->add_field($table, $field);
785         }
786         upgrade_main_savepoint(true, 2012060600.01);
787     }
789     if ($oldversion < 2012060600.02) {
790         // Populate referencehash field with SHA1 hash of the reference - this shoudl affect only 2.3dev sites
791         // that were using the feature for testing. Production sites have the table empty.
792         $rs = $DB->get_recordset('files_reference', null, '', 'id, reference');
793         foreach ($rs as $record) {
794             $hash = sha1($record->reference);
795             $DB->set_field('files_reference', 'referencehash', $hash, array('id' => $record->id));
796         }
797         $rs->close();
799         upgrade_main_savepoint(true, 2012060600.02);
800     }
802     if ($oldversion < 2012060600.03) {
803         // Merge duplicate records in files_reference that were created during the development
804         // phase at 2.3dev sites. This is needed so we can create the unique index over
805         // (repositoryid, referencehash) fields.
806         $sql = "SELECT repositoryid, referencehash, MIN(id) AS minid
807                   FROM {files_reference}
808               GROUP BY repositoryid, referencehash
809                 HAVING COUNT(*) > 1";
810         $duprs = $DB->get_recordset_sql($sql);
811         foreach ($duprs as $duprec) {
812             // get the list of all ids in {files_reference} that need to be remapped
813             $dupids = $DB->get_records_select('files_reference', "repositoryid = ? AND referencehash = ? AND id > ?",
814                 array($duprec->repositoryid, $duprec->referencehash, $duprec->minid), '', 'id');
815             $dupids = array_keys($dupids);
816             // relink records in {files} that are now referring to a duplicate record
817             // in {files_reference} to refer to the first one
818             list($subsql, $subparams) = $DB->get_in_or_equal($dupids);
819             $DB->set_field_select('files', 'referencefileid', $duprec->minid, "referencefileid $subsql", $subparams);
820             // and finally remove all orphaned records from {files_reference}
821             $DB->delete_records_list('files_reference', 'id', $dupids);
822         }
823         $duprs->close();
825         upgrade_main_savepoint(true, 2012060600.03);
826     }
828     if ($oldversion < 2012060600.04) {
829         // Add a unique index over repositoryid and referencehash fields in files_reference table
830         $table = new xmldb_table('files_reference');
831         $index = new xmldb_index('uq_external_file', XMLDB_INDEX_UNIQUE, array('repositoryid', 'referencehash'));
833         if (!$dbman->index_exists($table, $index)) {
834             $dbman->add_index($table, $index);
835         }
837         upgrade_main_savepoint(true, 2012060600.04);
838     }
840     if ($oldversion < 2012061800.01) {
842         // Define field screenreader to be dropped from user
843         $table = new xmldb_table('user');
844         $field = new xmldb_field('ajax');
846         // Conditionally launch drop field screenreader
847         if ($dbman->field_exists($table, $field)) {
848             $dbman->drop_field($table, $field);
849         }
851         // Main savepoint reached
852         upgrade_main_savepoint(true, 2012061800.01);
853     }
855     if ($oldversion < 2012062000.00) {
856         // Add field newcontextid to backup_files_template
857         $table = new xmldb_table('backup_files_template');
858         $field = new xmldb_field('newcontextid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'info');
860         if (!$dbman->field_exists($table, $field)) {
861             $dbman->add_field($table, $field);
862         }
864         upgrade_main_savepoint(true, 2012062000.00);
865     }
867     if ($oldversion < 2012062000.01) {
868         // Add field newitemid to backup_files_template
869         $table = new xmldb_table('backup_files_template');
870         $field = new xmldb_field('newitemid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'newcontextid');
872         if (!$dbman->field_exists($table, $field)) {
873             $dbman->add_field($table, $field);
874         }
876         upgrade_main_savepoint(true, 2012062000.01);
877     }
879     // Moodle v2.3.0 release upgrade line
880     // Put any upgrade step following this
882     if ($oldversion < 2012062500.02) {
883         // Drop some old backup tables, not used anymore
885         // Define table backup_files to be dropped
886         $table = new xmldb_table('backup_files');
888         // Conditionally launch drop table for backup_files
889         if ($dbman->table_exists($table)) {
890             $dbman->drop_table($table);
891         }
893         // Define table backup_ids to be dropped
894         $table = new xmldb_table('backup_ids');
896         // Conditionally launch drop table for backup_ids
897         if ($dbman->table_exists($table)) {
898             $dbman->drop_table($table);
899         }
901         // Main savepoint reached
902         upgrade_main_savepoint(true, 2012062500.02);
903     }
905     if ($oldversion < 2012070600.04) {
906         // Define table course_modules_avail_fields to be created
907         $table = new xmldb_table('course_modules_avail_fields');
909         // Adding fields to table course_modules_avail_fields
910         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
911         $table->add_field('coursemoduleid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
912         $table->add_field('userfield', XMLDB_TYPE_CHAR, '50', null, null, null, null);
913         $table->add_field('customfieldid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
914         $table->add_field('operator', XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, null);
915         $table->add_field('value', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
917         // Adding keys to table course_modules_avail_fields
918         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
919         $table->add_key('coursemoduleid', XMLDB_KEY_FOREIGN, array('coursemoduleid'), 'course_modules', array('id'));
921         // Conditionally launch create table for course_modules_avail_fields
922         if (!$dbman->table_exists($table)) {
923             $dbman->create_table($table);
924         }
926         // Main savepoint reached
927         upgrade_main_savepoint(true, 2012070600.04);
928     }
930     if ($oldversion < 2012070600.05) {
931         // Define table course_sections_avail_fields to be created
932         $table = new xmldb_table('course_sections_avail_fields');
934         // Adding fields to table course_sections_avail_fields
935         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
936         $table->add_field('coursesectionid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
937         $table->add_field('userfield', XMLDB_TYPE_CHAR, '50', null, null, null, null);
938         $table->add_field('customfieldid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
939         $table->add_field('operator', XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, null);
940         $table->add_field('value', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
942         // Adding keys to table course_sections_avail_fields
943         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
944         $table->add_key('coursesectionid', XMLDB_KEY_FOREIGN, array('coursesectionid'), 'course_sections', array('id'));
946         // Conditionally launch create table for course_sections_avail_fields
947         if (!$dbman->table_exists($table)) {
948             $dbman->create_table($table);
949         }
951         // Main savepoint reached
952         upgrade_main_savepoint(true, 2012070600.05);
953     }
955     if ($oldversion < 2012070600.06) {
957         // Drop "deleted" fields
958         $table = new xmldb_table('course_completions');
959         $field = new xmldb_field('timenotified');
960         $field = new xmldb_field('deleted');
962         // Conditionally launch drop field deleted from course_completions
963         if ($dbman->field_exists($table, $field)) {
964             $dbman->drop_field($table, $field);
965         }
967         $field = new xmldb_field('timenotified');
968         // Conditionally launch drop field timenotified from course_completions
969         if ($dbman->field_exists($table, $field)) {
970             $dbman->drop_field($table, $field);
971         }
973         // Main savepoint reached
974         upgrade_main_savepoint(true, 2012070600.06);
975     }
977     if ($oldversion < 2012070600.07) {
978         $table = new xmldb_table('course_completion_crit_compl');
979         $field = new xmldb_field('deleted');
981         // Conditionally launch drop field deleted from course_completion_crit_compl
982         if ($dbman->field_exists($table, $field)) {
983             $dbman->drop_field($table, $field);
984         }
985         // Main savepoint reached
986         upgrade_main_savepoint(true, 2012070600.07);
987     }
989     if ($oldversion < 2012070600.08) {
991         // Drop unused table "course_completion_notify"
992         $table = new xmldb_table('course_completion_notify');
994         // Conditionally launch drop table course_completion_notify
995         if ($dbman->table_exists($table)) {
996             $dbman->drop_table($table);
997         }
999         // Main savepoint reached
1000         upgrade_main_savepoint(true, 2012070600.08);
1001      }
1003     if ($oldversion < 2012070600.09) {
1005         // Define index path (not unique) to be added to context
1006         $table = new xmldb_table('context');
1007         $index = new xmldb_index('path', XMLDB_INDEX_NOTUNIQUE, array('path'), array('varchar_pattern_ops'));
1009         // Recreate index with new pattern hint
1010         if ($DB->get_dbfamily() === 'postgres') {
1011             if ($dbman->index_exists($table, $index)) {
1012                 $dbman->drop_index($table, $index);
1013             }
1014             $dbman->add_index($table, $index);
1015         }
1017         // Main savepoint reached
1018         upgrade_main_savepoint(true, 2012070600.09);
1019     }
1021     if ($oldversion < 2012070600.10) {
1023         // Define index name (unique) to be dropped form role
1024         $table = new xmldb_table('role');
1025         $index = new xmldb_index('name', XMLDB_INDEX_UNIQUE, array('name'));
1027         // Conditionally launch drop index name
1028         if ($dbman->index_exists($table, $index)) {
1029             $dbman->drop_index($table, $index);
1030         }
1032         // Main savepoint reached
1033         upgrade_main_savepoint(true, 2012070600.10);
1034     }
1036     if ($oldversion < 2012070600.11) {
1038         // Define index component-itemid-userid (not unique) to be added to role_assignments
1039         $table = new xmldb_table('role_assignments');
1040         $index = new xmldb_index('component-itemid-userid', XMLDB_INDEX_NOTUNIQUE, array('component', 'itemid', 'userid'));
1042         // Conditionally launch add index component-itemid-userid
1043         if (!$dbman->index_exists($table, $index)) {
1044             $dbman->add_index($table, $index);
1045         }
1047         // Main savepoint reached
1048         upgrade_main_savepoint(true, 2012070600.11);
1049     }
1051     if ($oldversion < 2012071900.01) {
1052         // Cleanup after simpeltests tool
1053         capabilities_cleanup('tool_unittest');
1054         unset_all_config_for_plugin('tool_unittest');
1056         upgrade_main_savepoint(true, 2012071900.01);
1057     }
1059     if ($oldversion < 2012072400.00) {
1060         // Remove obsolete xhtml strict setting - use THEME->doctype in theme config if necessary,
1061         // see theme_config->doctype in lib/outputlib.php for more details.
1062         unset_config('xmlstrictheaders');
1063         upgrade_main_savepoint(true, 2012072400.00);
1064     }
1066     if ($oldversion < 2012072401.00) {
1068         // Saves orphaned questions from the Dark Side
1069         upgrade_save_orphaned_questions();
1071         // Main savepoint reached
1072         upgrade_main_savepoint(true, 2012072401.00);
1073     }
1075     if ($oldversion < 2012072600.01) {
1076         // Handle events with empty eventtype //MDL-32827
1078         $DB->set_field('event', 'eventtype', 'site', array('eventtype' => '', 'courseid' => $SITE->id));
1079         $DB->set_field_select('event', 'eventtype', 'due', "eventtype = '' AND courseid != 0 AND groupid = 0 AND (modulename = 'assignment' OR modulename = 'assign')");
1080         $DB->set_field_select('event', 'eventtype', 'course', "eventtype = '' AND courseid != 0 AND groupid = 0");
1081         $DB->set_field_select('event', 'eventtype', 'group', "eventtype = '' AND groupid != 0");
1082         $DB->set_field_select('event', 'eventtype', 'user', "eventtype = '' AND userid != 0");
1084         // Main savepoint reached
1085         upgrade_main_savepoint(true, 2012072600.01);
1086     }
1088     if ($oldversion < 2012080200.02) {
1089         // Drop obsolete question upgrade field that should have been added to the install.xml.
1090         $table = new xmldb_table('question');
1091         $field = new xmldb_field('oldquestiontextformat', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0');
1093         if ($dbman->field_exists($table, $field)) {
1094             $dbman->drop_field($table, $field);
1095         }
1097         upgrade_main_savepoint(true, 2012080200.02);
1098     }
1100     if ($oldversion < 2012081400.01) {
1101         // Move the ability to disable blogs to its own setting MDL-25012.
1103         if (isset($CFG->bloglevel)) {
1104             // Only change settings if existing setting was set.
1105             if (empty($CFG->bloglevel)) {
1106                 set_config('enableblogs', 0);
1107                 // Now set the bloglevel to a valid setting as the disabled setting has been removed.
1108                 // This prevents confusing results when users enable the blog system in future.
1109                 set_config('bloglevel', BLOG_USER_LEVEL);
1110             } else {
1111                 set_config('enableblogs', 1);
1112             }
1113         }
1115         // Main savepoint reached
1116         upgrade_main_savepoint(true, 2012081400.01);
1117     }
1119     if ($oldversion < 2012081600.01) {
1120         // Delete removed setting - Google Maps API V2 will not work in 2013.
1121         unset_config('googlemapkey');
1122         upgrade_main_savepoint(true, 2012081600.01);
1123     }
1125     if ($oldversion < 2012082300.01) {
1126         // Add more custom enrol fields.
1127         $table = new xmldb_table('enrol');
1128         $field = new xmldb_field('customint5', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'customint4');
1130         if (!$dbman->field_exists($table, $field)) {
1131             $dbman->add_field($table, $field);
1132         }
1134         $field = new xmldb_field('customint6', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'customint5');
1135         if (!$dbman->field_exists($table, $field)) {
1136             $dbman->add_field($table, $field);
1137         }
1139         $field = new xmldb_field('customint7', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'customint6');
1140         if (!$dbman->field_exists($table, $field)) {
1141             $dbman->add_field($table, $field);
1142         }
1144         $field = new xmldb_field('customint8', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'customint7');
1145         if (!$dbman->field_exists($table, $field)) {
1146             $dbman->add_field($table, $field);
1147         }
1149         $field = new xmldb_field('customchar3', XMLDB_TYPE_CHAR, '1333', null, null, null, null, 'customchar2');
1150         if (!$dbman->field_exists($table, $field)) {
1151             $dbman->add_field($table, $field);
1152         }
1154         $field = new xmldb_field('customtext3', XMLDB_TYPE_TEXT, null, null, null, null, null, 'customtext2');
1155         if (!$dbman->field_exists($table, $field)) {
1156             $dbman->add_field($table, $field);
1157         }
1159         $field = new xmldb_field('customtext4', XMLDB_TYPE_TEXT, null, null, null, null, null, 'customtext3');
1160         if (!$dbman->field_exists($table, $field)) {
1161             $dbman->add_field($table, $field);
1162         }
1164         // Main savepoint reached.
1165         upgrade_main_savepoint(true, 2012082300.01);
1166     }
1168     if ($oldversion < 2012082300.02) {
1169         // Define field component to be added to groups_members
1170         $table = new xmldb_table('groups_members');
1171         $field = new xmldb_field('component', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null, 'timeadded');
1173         // Conditionally launch add field component
1174         if (!$dbman->field_exists($table, $field)) {
1175             $dbman->add_field($table, $field);
1176         }
1178         // Define field itemid to be added to groups_members
1179         $field = new xmldb_field('itemid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'component');
1181         // Conditionally launch add field itemid
1182         if (!$dbman->field_exists($table, $field)) {
1183             $dbman->add_field($table, $field);
1184         }
1186         // Main savepoint reached
1187         upgrade_main_savepoint(true, 2012082300.02);
1188     }
1190     if ($oldversion < 2012090500.00) {
1191         $subquery = 'SELECT b.id FROM {blog_external} b where b.id = ' . $DB->sql_cast_char2int('{post}.content', true);
1192         $sql = 'DELETE FROM {post}
1193                       WHERE {post}.module = \'blog_external\'
1194                             AND NOT EXISTS (' . $subquery . ')
1195                             AND ' . $DB->sql_isnotempty('post', 'uniquehash', false, false);
1196         $DB->execute($sql);
1197         upgrade_main_savepoint(true, 2012090500.00);
1198     }
1200     if ($oldversion < 2012090700.01) {
1201         // Add a category field in the course_request table
1202         $table = new xmldb_table('course_request');
1203         $field = new xmldb_field('category', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 0, 'summaryformat');
1204         if (!$dbman->field_exists($table, $field)) {
1205             $dbman->add_field($table, $field);
1206         }
1208         // Main savepoint reached.
1209         upgrade_main_savepoint(true, 2012090700.01);
1210     }
1212     if ($oldversion < 2012091700.00) {
1214         // Dropping screenreader field from user.
1215         $table = new xmldb_table('user');
1216         $field = new xmldb_field('screenreader');
1218         if ($dbman->field_exists($table, $field)) {
1219             $dbman->drop_field($table, $field);
1220         }
1222         // Main savepoint reached.
1223         upgrade_main_savepoint(true, 2012091700.00);
1224     }
1226     if ($oldversion < 2012092100.01) {
1227         // Some folders still have a sortorder set, which is used for main files but is not
1228         // supported by the folder resource. We reset the value here.
1229         $sql = 'UPDATE {files} SET sortorder = ? WHERE component = ? AND filearea = ? AND sortorder <> ?';
1230         $DB->execute($sql, array(0, 'mod_folder', 'content', 0));
1232         // Main savepoint reached.
1233         upgrade_main_savepoint(true, 2012092100.01);
1234     }
1236     if ($oldversion < 2012092600.00) {
1237         // Define index idname (unique) to be added to tag
1238         $table = new xmldb_table('tag');
1239         $index = new xmldb_index('idname', XMLDB_INDEX_UNIQUE, array('id', 'name'));
1241         // Conditionally launch add index idname
1242         if (!$dbman->index_exists($table, $index)) {
1243             $dbman->add_index($table, $index);
1244         }
1246         // Main savepoint reached
1247         upgrade_main_savepoint(true, 2012092600.00);
1248     }
1250     if ($oldversion < 2012101500.01) {
1251         // Find all orphaned blog associations that might exist.
1252         $sql = "SELECT ba.id
1253                   FROM {blog_association} ba
1254              LEFT JOIN {post} p
1255                     ON p.id = ba.blogid
1256                  WHERE p.id IS NULL";
1257         $orphanedrecordids = $DB->get_records_sql($sql);
1258         // Now delete these associations.
1259         foreach ($orphanedrecordids as $orphanedrecord) {
1260             $DB->delete_records('blog_association', array('id' => $orphanedrecord->id));
1261         }
1263         upgrade_main_savepoint(true, 2012101500.01);
1264     }
1266     if ($oldversion < 2012101800.02) {
1267         // Renaming backups using previous file naming convention.
1268         upgrade_rename_old_backup_files_using_shortname();
1270         // Main savepoint reached.
1271         upgrade_main_savepoint(true, 2012101800.02);
1272     }
1274     if ($oldversion < 2012103001.00) {
1275         // create new event_subscriptions table
1276         $table = new xmldb_table('event_subscriptions');
1277         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1278         $table->add_field('url', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
1279         $table->add_field('courseid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1280         $table->add_field('groupid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1281         $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1282         $table->add_field('pollinterval', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1283         $table->add_field('lastupdated', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1284         $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
1285         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1286         if (!$dbman->table_exists($table)) {
1287             $dbman->create_table($table);
1288         }
1289         // Main savepoint reached
1290         upgrade_main_savepoint(true, 2012103001.00);
1291     }
1293     if ($oldversion < 2012103002.00) {
1294         // Add subscription field to the event table
1295         $table = new xmldb_table('event');
1296         $field = new xmldb_field('subscriptionid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'timemodified');
1298         // Conditionally launch add field subscriptionid
1299         if (!$dbman->field_exists($table, $field)) {
1300             $dbman->add_field($table, $field);
1301         }
1302         upgrade_main_savepoint(true, 2012103002.00);
1303     }
1305     if ($oldversion < 2012103003.00) {
1306         // Fix uuid field in event table to match RFC-2445 UID property.
1307         $table = new xmldb_table('event');
1308         $field = new xmldb_field('uuid', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'visible');
1309         // The column already exists, so make sure there are no nulls (crazy mysql).
1310         $DB->set_field_select('event', 'uuid', '', "uuid IS NULL");
1311         // Changing precision of field uuid on table event to (255).
1312         $dbman->change_field_precision($table, $field);
1313         // Main savepoint reached
1314         upgrade_main_savepoint(true, 2012103003.00);
1315     }
1317     if ($oldversion < 2012110200.00) {
1319         // Define table course_format_options to be created
1320         $table = new xmldb_table('course_format_options');
1322         // Adding fields to table course_format_options
1323         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1324         $table->add_field('courseid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1325         $table->add_field('format', XMLDB_TYPE_CHAR, '21', null, XMLDB_NOTNULL, null, null);
1326         $table->add_field('sectionid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'format');
1327         $table->add_field('name', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
1328         $table->add_field('value', XMLDB_TYPE_TEXT, null, null, null, null, null);
1330         // Adding keys to table course_format_options
1331         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1332         $table->add_key('courseid', XMLDB_KEY_FOREIGN, array('courseid'), 'course', array('id'));
1334         // Adding indexes to table course_format_options
1335         $table->add_index('formatoption', XMLDB_INDEX_UNIQUE, array('courseid', 'format', 'sectionid', 'name'));
1337         // Conditionally launch create table for course_format_options
1338         if (!$dbman->table_exists($table)) {
1339             $dbman->create_table($table);
1340         }
1342         // Changing type of field format on table course to char with length 21
1343         $table = new xmldb_table('course');
1344         $field = new xmldb_field('format', XMLDB_TYPE_CHAR, '21', null, XMLDB_NOTNULL, null, 'topics', 'summaryformat');
1346         // Launch change of type for field format
1347         $dbman->change_field_type($table, $field);
1349         // Since structure of 'course' table has changed we need to re-read $SITE from DB.
1350         $SITE = $DB->get_record('course', array('id' => $SITE->id));
1351         $COURSE = clone($SITE);
1353         // Main savepoint reached
1354         upgrade_main_savepoint(true, 2012110200.00);
1355     }
1357     if ($oldversion < 2012110201.00) {
1359         // Copy fields 'coursedisplay', 'numsections', 'hiddensections' from table {course}
1360         // to table {course_format_options} as the additional format options
1361         $fields = array();
1362         $table = new xmldb_table('course');
1363         foreach (array('coursedisplay', 'numsections', 'hiddensections') as $fieldname) {
1364             // first check that fields still exist
1365             $field = new xmldb_field($fieldname);
1366             if ($dbman->field_exists($table, $field)) {
1367                 $fields[] = $fieldname;
1368             }
1369         }
1371         if (!empty($fields)) {
1372             $transaction = $DB->start_delegated_transaction();
1373             $rs = $DB->get_recordset_sql('SELECT id, format, '. join(',', $fields).'
1374                 FROM {course}
1375                 WHERE format <> ? AND format <> ?',
1376                 array('scorm', 'social'));
1377             // (do not copy fields from scrom and social formats, we already know that they are not used)
1378             foreach ($rs as $rec) {
1379                 foreach ($fields as $field) {
1380                     try {
1381                         $DB->insert_record('course_format_options',
1382                                 array(
1383                                     'courseid'  => $rec->id,
1384                                     'format'    => $rec->format,
1385                                     'sectionid' => 0,
1386                                     'name'      => $field,
1387                                     'value'     => $rec->$field
1388                                 ));
1389                     } catch (dml_exception $e) {
1390                         // index 'courseid,format,sectionid,name' violation
1391                         // continue; the entry in course_format_options already exists, use it
1392                     }
1393                 }
1394             }
1395             $rs->close();
1396             $transaction->allow_commit();
1398             // Drop fields from table course
1399             foreach ($fields as $fieldname) {
1400                 $field = new xmldb_field($fieldname);
1401                 $dbman->drop_field($table, $field);
1402             }
1403         }
1405         // Since structure of 'course' table has changed we need to re-read $SITE from DB.
1406         $SITE = $DB->get_record('course', array('id' => $SITE->id));
1407         $COURSE = clone($SITE);
1409         // Main savepoint reached
1410         upgrade_main_savepoint(true, 2012110201.00);
1411     }
1413     if ($oldversion < 2012110700.01) {
1415         // Define field caller_component to be added to portfolio_log.
1416         $table = new xmldb_table('portfolio_log');
1417         $field = new xmldb_field('caller_component', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'caller_file');
1419         // Conditionally launch add field caller_component.
1420         if (!$dbman->field_exists($table, $field)) {
1421             $dbman->add_field($table, $field);
1422         }
1424         // Main savepoint reached.
1425         upgrade_main_savepoint(true, 2012110700.01);
1426     }
1428     if ($oldversion < 2012111200.00) {
1430         // Define table temp_enroled_template to be created
1431         $table = new xmldb_table('temp_enroled_template');
1433         // Adding fields to table temp_enroled_template
1434         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1435         $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1436         $table->add_field('courseid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1437         $table->add_field('roleid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1439         // Adding keys to table temp_enroled_template
1440         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1442         // Adding indexes to table temp_enroled_template
1443         $table->add_index('userid', XMLDB_INDEX_NOTUNIQUE, array('userid'));
1444         $table->add_index('courseid', XMLDB_INDEX_NOTUNIQUE, array('courseid'));
1445         $table->add_index('roleid', XMLDB_INDEX_NOTUNIQUE, array('roleid'));
1447         // Conditionally launch create table for temp_enroled_template
1448         if (!$dbman->table_exists($table)) {
1449             $dbman->create_table($table);
1450         }
1452         // Define table temp_log_template to be created
1453         $table = new xmldb_table('temp_log_template');
1455         // Adding fields to table temp_log_template
1456         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1457         $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1458         $table->add_field('course', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1459         $table->add_field('action', XMLDB_TYPE_CHAR, '40', null, XMLDB_NOTNULL, null, null);
1461         // Adding keys to table temp_log_template
1462         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1464         // Adding indexes to table temp_log_template
1465         $table->add_index('action', XMLDB_INDEX_NOTUNIQUE, array('action'));
1466         $table->add_index('course', XMLDB_INDEX_NOTUNIQUE, array('course'));
1467         $table->add_index('user', XMLDB_INDEX_NOTUNIQUE, array('userid'));
1468         $table->add_index('usercourseaction', XMLDB_INDEX_NOTUNIQUE, array('userid', 'course', 'action'));
1470         // Conditionally launch create table for temp_log_template
1471         if (!$dbman->table_exists($table)) {
1472             $dbman->create_table($table);
1473         }
1475         // Main savepoint reached
1476         upgrade_main_savepoint(true, 2012111200.00);
1477     }
1479     if ($oldversion < 2012111200.01) {
1480         // Force the rebuild of the cache of every courses, some cached information could contain wrong icon references.
1481         $DB->execute('UPDATE {course} set modinfo = ?, sectioncache = ?', array(null, null));
1483         // Main savepoint reached.
1484         upgrade_main_savepoint(true, 2012111200.01);
1485     }
1487     if ($oldversion < 2012111601.01) {
1488         // Clea up after old shared memory caching support.
1489         unset_config('cachetype');
1490         unset_config('rcache');
1491         unset_config('rcachettl');
1492         unset_config('intcachemax');
1493         unset_config('memcachedhosts');
1494         unset_config('memcachedpconn');
1496         // Main savepoint reached.
1497         upgrade_main_savepoint(true, 2012111601.01);
1498     }
1500     if ($oldversion < 2012112100.00) {
1502         // Define field eventtype to be added to event_subscriptions.
1503         $table = new xmldb_table('event_subscriptions');
1504         $field = new xmldb_field('eventtype', XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, null, 'userid');
1506         // Conditionally launch add field eventtype.
1507         if (!$dbman->field_exists($table, $field)) {
1508             $dbman->add_field($table, $field);
1509         }
1511         // Main savepoint reached.
1512         upgrade_main_savepoint(true, 2012112100.00);
1513     }
1515     // Moodle v2.4.0 release upgrade line
1516     // Put any upgrade step following this
1518     if ($oldversion < 2012120300.01) {
1519         // Make sure site-course has format='site' //MDL-36840
1521         if ($SITE->format !== 'site') {
1522             $DB->set_field('course', 'format', 'site', array('id' => $SITE->id));
1523             $SITE->format = 'site';
1524             $COURSE->format = 'site';
1525         }
1527         // Main savepoint reached
1528         upgrade_main_savepoint(true, 2012120300.01);
1529     }
1531     if ($oldversion < 2012120300.04) {
1532         // Remove "_utf8" suffix from all langs in course table.
1533         $langs = $DB->get_records_sql("SELECT DISTINCT lang FROM {course} WHERE lang LIKE ?", array('%_utf8'));
1535         foreach ($langs as $lang=>$unused) {
1536             $newlang = str_replace('_utf8', '', $lang);
1537             $sql = "UPDATE {course} SET lang = :newlang WHERE lang = :lang";
1538             $DB->execute($sql, array('newlang'=>$newlang, 'lang'=>$lang));
1539         }
1541         // Main savepoint reached.
1542         upgrade_main_savepoint(true, 2012120300.04);
1543     }
1545     if ($oldversion < 2012123000.00) {
1546         // Purge removed module filters and all their settings.
1548         $tables = array('filter_active', 'filter_config');
1549         foreach ($tables as $table) {
1550             $DB->delete_records_select($table, "filter LIKE 'mod/%'");
1551             $filters = $DB->get_records_sql("SELECT DISTINCT filter FROM {{$table}} WHERE filter LIKE 'filter/%'");
1552             foreach ($filters as $filter) {
1553                 $DB->set_field($table, 'filter', substr($filter->filter, 7), array('filter'=>$filter->filter));
1554             }
1555         }
1557         $configs = array('stringfilters', 'filterall');
1558         foreach ($configs as $config) {
1559             if ($filters = get_config(null, $config)) {
1560                 $filters = explode(',', $filters);
1561                 $newfilters = array();
1562                 foreach($filters as $filter) {
1563                     if (strpos($filter, '/') === false) {
1564                         $newfilters[] = $filter;
1565                     } else if (strpos($filter, 'filter/') === 0) {
1566                         $newfilters[] = substr($filter, 7);
1567                     }
1568                 }
1569                 $filters = implode(',', $newfilters);
1570                 set_config($config, $filters);
1571             }
1572         }
1574         unset($tables);
1575         unset($table);
1576         unset($configs);
1577         unset($newfilters);
1578         unset($filters);
1579         unset($filter);
1581         // Main savepoint reached.
1582         upgrade_main_savepoint(true, 2012123000.00);
1583     }
1585     if ($oldversion < 2013021100.01) {
1586         // Make sure there are no bogus nulls in old MySQL tables.
1587         $DB->set_field_select('user', 'password', '', "password IS NULL");
1589         // Changing precision of field password on table user to (255).
1590         $table = new xmldb_table('user');
1591         $field = new xmldb_field('password', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'username');
1593         // Launch change of precision for field password.
1594         $dbman->change_field_precision($table, $field);
1596         // Main savepoint reached.
1597         upgrade_main_savepoint(true, 2013021100.01);
1598     }
1600     if ($oldversion < 2013021800.00) {
1601         // Add the site identifier to the cache config's file.
1602         $siteidentifier = $DB->get_field('config', 'value', array('name' => 'siteidentifier'));
1603         cache_helper::update_site_identifier($siteidentifier);
1605         // Main savepoint reached.
1606         upgrade_main_savepoint(true, 2013021800.00);
1607     }
1609     if ($oldversion < 2013021801.00) {
1610         // Fixing possible wrong MIME types for SMART Notebook files.
1611         $extensions = array('%.gallery', '%.galleryitem', '%.gallerycollection', '%.nbk', '%.notebook', '%.xbk');
1612         $select = $DB->sql_like('filename', '?', false);
1613         foreach ($extensions as $extension) {
1614             $DB->set_field_select(
1615                 'files',
1616                 'mimetype',
1617                 'application/x-smarttech-notebook',
1618                 $select,
1619                 array($extension)
1620             );
1621         }
1622         upgrade_main_savepoint(true, 2013021801.00);
1623     }
1625     if ($oldversion < 2013021801.01) {
1626         // This upgrade step is re-written under MDL-38228 (see below).
1627         /*
1628         // Retrieve the list of course_sections as a recordset to save memory
1629         $coursesections = $DB->get_recordset('course_sections', null, 'course, id', 'id, course, sequence');
1630         foreach ($coursesections as $coursesection) {
1631             // Retrieve all of the actual modules in this course and section combination to reduce DB calls
1632             $actualsectionmodules = $DB->get_records('course_modules',
1633                     array('course' => $coursesection->course, 'section' => $coursesection->id), '', 'id, section');
1635             // Break out the current sequence so that we can compare it
1636             $currentsequence = explode(',', $coursesection->sequence);
1637             $newsequence = array();
1639             // Check each of the modules in the current sequence
1640             foreach ($currentsequence as $module) {
1641                 if (isset($actualsectionmodules[$module])) {
1642                     $newsequence[] = $module;
1643                     // We unset the actualsectionmodules so that we don't get duplicates and that we can add orphaned
1644                     // modules later
1645                     unset($actualsectionmodules[$module]);
1646                 }
1647             }
1649             // Append any modules which have somehow been orphaned
1650             foreach ($actualsectionmodules as $module) {
1651                 $newsequence[] = $module->id;
1652             }
1654             // Piece it all back together
1655             $sequence = implode(',', $newsequence);
1657             // Only update if there have been changes
1658             if ($sequence !== $coursesection->sequence) {
1659                 $coursesection->sequence = $sequence;
1660                 $DB->update_record('course_sections', $coursesection);
1662                 // And clear the sectioncache and modinfo cache - they'll be regenerated on next use
1663                 $course = new stdClass();
1664                 $course->id = $coursesection->course;
1665                 $course->sectioncache = null;
1666                 $course->modinfo = null;
1667                 $DB->update_record('course', $course);
1668             }
1669         }
1670         $coursesections->close();
1671         */
1672         // Main savepoint reached.
1673         upgrade_main_savepoint(true, 2013021801.01);
1674     }
1676     if ($oldversion < 2013021902.00) {
1677         // ISO country change: Netherlands Antilles is split into BQ, CW & SX
1678         // http://www.iso.org/iso/iso_3166-1_newsletter_vi-8_split_of_the_dutch_antilles_final-en.pdf
1679         $sql = "UPDATE {user} SET country = '' WHERE country = ?";
1680         $DB->execute($sql, array('AN'));
1682         upgrade_main_savepoint(true, 2013021902.00);
1683     }
1685     if ($oldversion < 2013022600.00) {
1686         // Delete entries regarding invalid 'interests' option which breaks course.
1687         $DB->delete_records('course_sections_avail_fields', array('userfield' => 'interests'));
1688         $DB->delete_records('course_modules_avail_fields', array('userfield' => 'interests'));
1689         // Clear course cache (will be rebuilt on first visit) in case of changes to these.
1690         $DB->execute('UPDATE {course} set modinfo = ?, sectioncache = ?', array(null, null));
1692         upgrade_main_savepoint(true, 2013022600.00);
1693     }
1695     // Add index to field "timemodified" for grade_grades_history table.
1696     if ($oldversion < 2013030400.00) {
1697         $table = new xmldb_table('grade_grades_history');
1698         $field = new xmldb_field('timemodified');
1700         if ($dbman->field_exists($table, $field)) {
1701             $index = new xmldb_index('timemodified', XMLDB_INDEX_NOTUNIQUE, array('timemodified'));
1702             if (!$dbman->index_exists($table, $index)) {
1703                 $dbman->add_index($table, $index);
1704             }
1705         }
1707         // Main savepoint reached.
1708         upgrade_main_savepoint(true, 2013030400.00);
1709     }
1711     if ($oldversion < 2013030400.02) {
1712         // Cleanup qformat blackboard settings.
1713         unset_all_config_for_plugin('qformat_blackboard');
1715         upgrade_main_savepoint(true, 2013030400.02);
1716     }
1718     // This is checking to see if the site has been running a specific version with a bug in it
1719     // because this upgrade step is slow and is only needed if the site has been running with the affected versions.
1720     if ($oldversion >= 2012062504.08 && $oldversion < 2012062504.13) {
1721         // This upgrade step is re-written under MDL-38228 (see below).
1723         /*
1724         // Retrieve the list of course_sections as a recordset to save memory.
1725         // This is to fix a regression caused by MDL-37939.
1726         // In this case the upgrade step is fixing records where:
1727         // The data in course_sections.sequence contains the correct module id
1728         // The section field for on the course modules table may have been updated to point to the incorrect id.
1730         // This query is looking for sections where the sequence is not in sync with the course_modules table.
1731         // The syntax for the like query is looking for a value in a comma separated list.
1732         // It adds a comma to either site of the list and then searches for LIKE '%,id,%'.
1733         $sequenceconcat = $DB->sql_concat("','", 's.sequence', "','");
1734         $moduleconcat = $DB->sql_concat("'%,'", 'cm.id', "',%'");
1735         $sql = 'SELECT s2.id, s2.course, s2.sequence
1736                 FROM {course_sections} s2
1737                 JOIN(
1738                     SELECT DISTINCT s.id
1739                     FROM
1740                     {course_modules} cm
1741                     JOIN {course_sections} s
1742                     ON
1743                         cm.course = s.course
1744                     WHERE cm.section != s.id AND ' . $sequenceconcat . ' LIKE ' . $moduleconcat . '
1745                 ) d
1746                 ON s2.id = d.id';
1747         $coursesections = $DB->get_recordset_sql($sql);
1749         foreach ($coursesections as $coursesection) {
1750             // Retrieve all of the actual modules in this course and section combination to reduce DB calls.
1751             $actualsectionmodules = $DB->get_records('course_modules',
1752                     array('course' => $coursesection->course, 'section' => $coursesection->id), '', 'id, section');
1754             // Break out the current sequence so that we can compare it.
1755             $currentsequence = explode(',', $coursesection->sequence);
1756             $orphanlist = array();
1758             // Check each of the modules in the current sequence.
1759             foreach ($currentsequence as $cmid) {
1760                 if (!empty($cmid) && !isset($actualsectionmodules[$cmid])) {
1761                     $orphanlist[] = $cmid;
1762                 }
1763             }
1765             if (!empty($orphanlist)) {
1766                 list($sql, $params) = $DB->get_in_or_equal($orphanlist, SQL_PARAMS_NAMED);
1767                 $sql = "id $sql";
1769                 $DB->set_field_select('course_modules', 'section', $coursesection->id, $sql, $params);
1771                 // And clear the sectioncache and modinfo cache - they'll be regenerated on next use.
1772                 $course = new stdClass();
1773                 $course->id = $coursesection->course;
1774                 $course->sectioncache = null;
1775                 $course->modinfo = null;
1776                 $DB->update_record('course', $course);
1777             }
1778         }
1779         $coursesections->close();
1781         // No savepoint needed for this change.
1782          */
1783     }
1785     if ($oldversion < 2013032200.01) {
1786         // GD is now always available
1787         set_config('gdversion', 2);
1789         upgrade_main_savepoint(true, 2013032200.01);
1790     }
1792     if ($oldversion < 2013032600.03) {
1793         // Fixing possible wrong MIME type for MIME HTML (MHTML) files.
1794         $extensions = array('%.mht', '%.mhtml');
1795         $select = $DB->sql_like('filename', '?', false);
1796         foreach ($extensions as $extension) {
1797             $DB->set_field_select(
1798                 'files',
1799                 'mimetype',
1800                 'message/rfc822',
1801                 $select,
1802                 array($extension)
1803             );
1804         }
1805         upgrade_main_savepoint(true, 2013032600.03);
1806     }
1808     if ($oldversion < 2013032600.04) {
1809         // MDL-31983 broke the quiz version number. Fix it.
1810         $DB->set_field('modules', 'version', '2013021500',
1811                 array('name' => 'quiz', 'version' => '2013310100'));
1812         upgrade_main_savepoint(true, 2013032600.04);
1813     }
1815     if ($oldversion < 2013040200.00) {
1816         // Add openbadges tables.
1818         // Define table 'badge' to be created.
1819         $table = new xmldb_table('badge');
1821         // Adding fields to table 'badge'.
1822         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null);
1823         $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'id');
1824         $table->add_field('description', XMLDB_TYPE_TEXT, null, null, null, null, null, 'name');
1825         $table->add_field('image', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'description');
1826         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'image');
1827         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'timecreated');
1828         $table->add_field('usercreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'timemodified');
1829         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'usercreated');
1830         $table->add_field('issuername', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'usermodified');
1831         $table->add_field('issuerurl', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'issuername');
1832         $table->add_field('issuercontact', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'issuerurl');
1833         $table->add_field('expiredate', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'issuercontact');
1834         $table->add_field('expireperiod', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'expiredate');
1835         $table->add_field('type', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'expireperiod');
1836         $table->add_field('courseid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'type');
1837         $table->add_field('message', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null, 'courseid');
1838         $table->add_field('messagesubject', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null, 'message');
1839         $table->add_field('attachment', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'messagesubject');
1840         $table->add_field('notification', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'attachment');
1841         $table->add_field('status', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'notification');
1842         $table->add_field('nextcron', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'status');
1844         // Adding keys to table 'badge'.
1845         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1846         $table->add_key('fk_courseid', XMLDB_KEY_FOREIGN, array('courseid'), 'course', array('id'));
1847         $table->add_key('fk_usermodified', XMLDB_KEY_FOREIGN, array('usermodified'), 'user', array('id'));
1848         $table->add_key('fk_usercreated', XMLDB_KEY_FOREIGN, array('usercreated'), 'user', array('id'));
1850         // Adding indexes to table 'badge'.
1851         $table->add_index('type', XMLDB_INDEX_NOTUNIQUE, array('type'));
1853         // Conditionally launch create table for 'badge'.
1854         if (!$dbman->table_exists($table)) {
1855             $dbman->create_table($table);
1856         }
1858         // Define table 'badge_criteria' to be created.
1859         $table = new xmldb_table('badge_criteria');
1861         // Adding fields to table 'badge_criteria'.
1862         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null);
1863         $table->add_field('badgeid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'id');
1864         $table->add_field('criteriatype', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'badgeid');
1865         $table->add_field('method', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'criteriatype');
1867         // Adding keys to table 'badge_criteria'.
1868         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1869         $table->add_key('fk_badgeid', XMLDB_KEY_FOREIGN, array('badgeid'), 'badge', array('id'));
1871         // Adding indexes to table 'badge_criteria'.
1872         $table->add_index('criteriatype', XMLDB_INDEX_NOTUNIQUE, array('criteriatype'));
1873         $table->add_index('badgecriteriatype', XMLDB_INDEX_UNIQUE, array('badgeid', 'criteriatype'));
1875         // Conditionally launch create table for 'badge_criteria'.
1876         if (!$dbman->table_exists($table)) {
1877             $dbman->create_table($table);
1878         }
1880         // Define table 'badge_criteria_param' to be created.
1881         $table = new xmldb_table('badge_criteria_param');
1883         // Adding fields to table 'badge_criteria_param'.
1884         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null);
1885         $table->add_field('critid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'id');
1886         $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'critid');
1887         $table->add_field('value', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'name');
1889         // Adding keys to table 'badge_criteria_param'.
1890         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1891         $table->add_key('fk_critid', XMLDB_KEY_FOREIGN, array('critid'), 'badge_criteria', array('id'));
1893         // Conditionally launch create table for 'badge_criteria_param'.
1894         if (!$dbman->table_exists($table)) {
1895             $dbman->create_table($table);
1896         }
1898         // Define table 'badge_issued' to be created.
1899         $table = new xmldb_table('badge_issued');
1901         // Adding fields to table 'badge_issued'.
1902         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null);
1903         $table->add_field('badgeid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'id');
1904         $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'badgeid');
1905         $table->add_field('uniquehash', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null, 'userid');
1906         $table->add_field('dateissued', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'uniquehash');
1907         $table->add_field('dateexpire', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'dateissued');
1908         $table->add_field('visible', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'dateexpire');
1909         $table->add_field('issuernotified', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'visible');
1911         // Adding keys to table 'badge_issued'.
1912         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1913         $table->add_key('fk_badgeid', XMLDB_KEY_FOREIGN, array('badgeid'), 'badge', array('id'));
1914         $table->add_key('fk_userid', XMLDB_KEY_FOREIGN, array('userid'), 'user', array('id'));
1916         $table->add_index('badgeuser', XMLDB_INDEX_UNIQUE, array('badgeid', 'userid'));
1918         // Conditionally launch create table for 'badge_issued'.
1919         if (!$dbman->table_exists($table)) {
1920             $dbman->create_table($table);
1921         }
1923         // Define table 'badge_criteria_met' to be created.
1924         $table = new xmldb_table('badge_criteria_met');
1926         // Adding fields to table 'badge_criteria_met'.
1927         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null);
1928         $table->add_field('issuedid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'id');
1929         $table->add_field('critid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'issuedid');
1930         $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'critid');
1931         $table->add_field('datemet', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'userid');
1933         // Adding keys to table 'badge_criteria_met'
1934         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1935         $table->add_key('fk_critid', XMLDB_KEY_FOREIGN, array('critid'), 'badge_criteria', array('id'));
1936         $table->add_key('fk_userid', XMLDB_KEY_FOREIGN, array('userid'), 'user', array('id'));
1937         $table->add_key('fk_issuedid', XMLDB_KEY_FOREIGN, array('issuedid'), 'badge_issued', array('id'));
1939         // Conditionally launch create table for 'badge_criteria_met'.
1940         if (!$dbman->table_exists($table)) {
1941             $dbman->create_table($table);
1942         }
1944         // Define table 'badge_manual_award' to be created.
1945         $table = new xmldb_table('badge_manual_award');
1947         // Adding fields to table 'badge_manual_award'.
1948         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null);
1949         $table->add_field('badgeid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'id');
1950         $table->add_field('recipientid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'badgeid');
1951         $table->add_field('issuerid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'recipientid');
1952         $table->add_field('issuerrole', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'issuerid');
1953         $table->add_field('datemet', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'issuerrole');
1955         // Adding keys to table 'badge_manual_award'.
1956         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1957         $table->add_key('fk_badgeid', XMLDB_KEY_FOREIGN, array('badgeid'), 'badge', array('id'));
1958         $table->add_key('fk_recipientid', XMLDB_KEY_FOREIGN, array('recipientid'), 'user', array('id'));
1959         $table->add_key('fk_issuerid', XMLDB_KEY_FOREIGN, array('issuerid'), 'user', array('id'));
1960         $table->add_key('fk_issuerrole', XMLDB_KEY_FOREIGN, array('issuerrole'), 'role', array('id'));
1962         // Conditionally launch create table for 'badge_manual_award'.
1963         if (!$dbman->table_exists($table)) {
1964             $dbman->create_table($table);
1965         }
1967         // Define table 'badge_backpack' to be created.
1968         $table = new xmldb_table('badge_backpack');
1970         // Adding fields to table 'badge_backpack'.
1971         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null);
1972         $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'id');
1973         $table->add_field('email', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null, 'userid');
1974         $table->add_field('backpackurl', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'email');
1975         $table->add_field('backpackuid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'backpackurl');
1976         $table->add_field('backpackgid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'backpackuid');
1977         $table->add_field('autosync', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'backpackgid');
1978         $table->add_field('password', XMLDB_TYPE_CHAR, '50', null, null, null, null, 'autosync');
1980         // Adding keys to table 'badge_backpack'.
1981         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1982         $table->add_key('fk_userid', XMLDB_KEY_FOREIGN, array('userid'), 'user', array('id'));
1984         // Conditionally launch create table for 'badge_backpack'.
1985         if (!$dbman->table_exists($table)) {
1986             $dbman->create_table($table);
1987         }
1989         // Main savepoint reached.
1990         upgrade_main_savepoint(true, 2013040200.00);
1991     }
1993     if ($oldversion < 2013040201.00) {
1994         // Convert name field in event table to text type as RFC-2445 doesn't have any limitation on it.
1995         $table = new xmldb_table('event');
1996         $field = new xmldb_field('name', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
1997         if ($dbman->field_exists($table, $field)) {
1998             $dbman->change_field_type($table, $field);
1999         }
2000         // Main savepoint reached.
2001         upgrade_main_savepoint(true, 2013040201.00);
2002     }
2004     if ($oldversion < 2013040300.01) {
2006         // Define field completionstartonenrol to be dropped from course.
2007         $table = new xmldb_table('course');
2008         $field = new xmldb_field('completionstartonenrol');
2010         // Conditionally launch drop field completionstartonenrol.
2011         if ($dbman->field_exists($table, $field)) {
2012             $dbman->drop_field($table, $field);
2013         }
2015         // Since structure of 'course' table has changed we need to re-read $SITE from DB.
2016         $SITE = $DB->get_record('course', array('id' => $SITE->id));
2017         $COURSE = clone($SITE);
2019         // Main savepoint reached.
2020         upgrade_main_savepoint(true, 2013040300.01);
2021     }
2023     if ($oldversion < 2013041200.00) {
2024         // MDL-29877 Some bad restores created grade items with no category information.
2025         $sql = "UPDATE {grade_items}
2026                    SET categoryid = courseid
2027                  WHERE itemtype <> 'course' and itemtype <> 'category'
2028                        AND categoryid IS NULL";
2029         $DB->execute($sql);
2030         upgrade_main_savepoint(true, 2013041200.00);
2031     }
2033     if ($oldversion < 2013041600.00) {
2034         // Copy constants from /course/lib.php instead of including the whole library:
2035         $c = array( 'FRONTPAGENEWS'                 => 0,
2036                     'FRONTPAGECOURSELIST'           => 1,
2037                     'FRONTPAGECATEGORYNAMES'        => 2,
2038                     'FRONTPAGETOPICONLY'            => 3,
2039                     'FRONTPAGECATEGORYCOMBO'        => 4,
2040                     'FRONTPAGEENROLLEDCOURSELIST'   => 5,
2041                     'FRONTPAGEALLCOURSELIST'        => 6,
2042                     'FRONTPAGECOURSESEARCH'         => 7);
2043         // Update frontpage settings $CFG->frontpage and $CFG->frontpageloggedin. In 2.4 there was too much of hidden logic about them.
2044         // This script tries to make sure that with the new (more user-friendly) frontpage settings the frontpage looks as similar as possible to what it was before upgrade.
2045         $ncourses = $DB->count_records('course');
2046         foreach (array('frontpage', 'frontpageloggedin') as $configkey) {
2047             if ($frontpage = explode(',', $CFG->{$configkey})) {
2048                 $newfrontpage = array();
2049                 foreach ($frontpage as $v) {
2050                     switch ($v) {
2051                         case $c['FRONTPAGENEWS']:
2052                             // Not related to course listings, leave as it is.
2053                             $newfrontpage[] = $c['FRONTPAGENEWS'];
2054                             break;
2055                         case $c['FRONTPAGECOURSELIST']:
2056                             if ($configkey === 'frontpageloggedin' && empty($CFG->disablemycourses)) {
2057                                 // In 2.4 unless prohibited in config, the "list of courses" was considered "list of enrolled courses" plus course search box.
2058                                 $newfrontpage[] = $c['FRONTPAGEENROLLEDCOURSELIST'];
2059                             } else if ($ncourses <= 200) {
2060                                 // Still list of courses was only displayed in there were less than 200 courses in system. Otherwise - search box only.
2061                                 $newfrontpage[] = $c['FRONTPAGEALLCOURSELIST'];
2062                                 break; // skip adding search box
2063                             }
2064                             if (!in_array($c['FRONTPAGECOURSESEARCH'], $newfrontpage)) {
2065                                 $newfrontpage[] = $c['FRONTPAGECOURSESEARCH'];
2066                             }
2067                             break;
2068                         case $c['FRONTPAGECATEGORYNAMES']:
2069                             // In 2.4 search box was displayed automatically after categories list. In 2.5 it is displayed as a separate setting.
2070                             $newfrontpage[] = $c['FRONTPAGECATEGORYNAMES'];
2071                             if (!in_array($c['FRONTPAGECOURSESEARCH'], $newfrontpage)) {
2072                                 $newfrontpage[] = $c['FRONTPAGECOURSESEARCH'];
2073                             }
2074                             break;
2075                         case $c['FRONTPAGECATEGORYCOMBO']:
2076                             $maxcourses = empty($CFG->numcoursesincombo) ? 500 : $CFG->numcoursesincombo;
2077                             // In 2.4 combo list was not displayed if there are more than $CFG->numcoursesincombo courses in the system.
2078                             if ($ncourses < $maxcourses) {
2079                                 $newfrontpage[] = $c['FRONTPAGECATEGORYCOMBO'];
2080                             }
2081                             if (!in_array($c['FRONTPAGECOURSESEARCH'], $newfrontpage)) {
2082                                 $newfrontpage[] = $c['FRONTPAGECOURSESEARCH'];
2083                             }
2084                             break;
2085                     }
2086                 }
2087                 set_config($configkey, join(',', $newfrontpage));
2088             }
2089         }
2090         // $CFG->numcoursesincombo no longer affects whether the combo list is displayed. Setting is deprecated.
2091         unset_config('numcoursesincombo');
2093         upgrade_main_savepoint(true, 2013041600.00);
2094     }
2096     if ($oldversion < 2013041601.00) {
2097         // Create a new 'badge_external' table first.
2098         // Define table 'badge_external' to be created.
2099         $table = new xmldb_table('badge_external');
2101         // Adding fields to table 'badge_external'.
2102         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null);
2103         $table->add_field('backpackid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'id');
2104         $table->add_field('collectionid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'backpackid');
2106         // Adding keys to table 'badge_external'.
2107         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2108         $table->add_key('fk_backpackid', XMLDB_KEY_FOREIGN, array('backpackid'), 'badge_backpack', array('id'));
2110         // Conditionally launch create table for 'badge_external'.
2111         if (!$dbman->table_exists($table)) {
2112             $dbman->create_table($table);
2113         }
2115         // Perform user data migration.
2116         $usercollections = $DB->get_records('badge_backpack');
2117         foreach ($usercollections as $usercollection) {
2118             $collection = new stdClass();
2119             $collection->backpackid = $usercollection->id;
2120             $collection->collectionid = $usercollection->backpackgid;
2121             $DB->insert_record('badge_external', $collection);
2122         }
2124         // Finally, drop the column.
2125         // Define field backpackgid to be dropped from 'badge_backpack'.
2126         $table = new xmldb_table('badge_backpack');
2127         $field = new xmldb_field('backpackgid');
2129         // Conditionally launch drop field backpackgid.
2130         if ($dbman->field_exists($table, $field)) {
2131             $dbman->drop_field($table, $field);
2132         }
2134         // Main savepoint reached.
2135         upgrade_main_savepoint(true, 2013041601.00);
2136     }
2138     if ($oldversion < 2013041601.01) {
2139         // Changing the default of field descriptionformat on table user to 1.
2140         $table = new xmldb_table('user');
2141         $field = new xmldb_field('descriptionformat', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '1', 'description');
2143         // Launch change of default for field descriptionformat.
2144         $dbman->change_field_default($table, $field);
2146         // Main savepoint reached.
2147         upgrade_main_savepoint(true, 2013041601.01);
2148     }
2150     if ($oldversion < 2013041900.00) {
2151         require_once($CFG->dirroot . '/cache/locallib.php');
2152         // The features bin needs updating.
2153         cache_config_writer::update_default_config_stores();
2154         // Main savepoint reached.
2155         upgrade_main_savepoint(true, 2013041900.00);
2156     }
2158     if ($oldversion < 2013042300.00) {
2159         // Adding index to unreadmessageid field of message_working table (MDL-34933)
2160         $table = new xmldb_table('message_working');
2161         $index = new xmldb_index('unreadmessageid_idx', XMLDB_INDEX_NOTUNIQUE, array('unreadmessageid'));
2163         // Conditionally launch add index unreadmessageid
2164         if (!$dbman->index_exists($table, $index)) {
2165             $dbman->add_index($table, $index);
2166         }
2168         // Main savepoint reached.
2169         upgrade_main_savepoint(true, 2013042300.00);
2170     }
2172     // Moodle v2.5.0 release upgrade line.
2173     // Put any upgrade step following this.
2175     if ($oldversion < 2013051400.01) {
2176         // Fix incorrect cc-nc url. Unfortunately the license 'plugins' do
2177         // not give a mechanism to do this.
2179         $sql = "UPDATE {license}
2180                    SET source = :url, version = :newversion
2181                  WHERE shortname = :shortname AND version = :oldversion";
2183         $params = array(
2184             'url' => 'http://creativecommons.org/licenses/by-nc/3.0/',
2185             'shortname' => 'cc-nc',
2186             'newversion' => '2013051500',
2187             'oldversion' => '2010033100'
2188         );
2190         $DB->execute($sql, $params);
2192         // Main savepoint reached.
2193         upgrade_main_savepoint(true, 2013051400.01);
2194     }
2196     if ($oldversion < 2013061400.01) {
2197         // Clean up old tokens which haven't been deleted.
2198         $DB->execute("DELETE FROM {user_private_key} WHERE NOT EXISTS
2199                          (SELECT 'x' FROM {user} WHERE deleted = 0 AND id = userid)");
2201         // Main savepoint reached.
2202         upgrade_main_savepoint(true, 2013061400.01);
2203     }
2205     if ($oldversion < 2013061700.00) {
2206         // MDL-40103: Remove unused template tables from the database.
2207         // These are now created inline with xmldb_table.
2209         $tablestocleanup = array('temp_enroled_template','temp_log_template','backup_files_template','backup_ids_template');
2210         $dbman = $DB->get_manager();
2212         foreach ($tablestocleanup as $table) {
2213             $xmltable = new xmldb_table($table);
2214             if ($dbman->table_exists($xmltable)) {
2215                 $dbman->drop_table($xmltable);
2216             }
2217         }
2219         // Main savepoint reached.
2220         upgrade_main_savepoint(true, 2013061700.00);
2221     }
2223     if ($oldversion < 2013070800.00) {
2225         // Remove orphan repository instances.
2226         if ($DB->get_dbfamily() === 'mysql') {
2227             $sql = "DELETE {repository_instances} FROM {repository_instances}
2228                     LEFT JOIN {context} ON {context}.id = {repository_instances}.contextid
2229                     WHERE {context}.id IS NULL";
2230         } else {
2231             $sql = "DELETE FROM {repository_instances}
2232                     WHERE NOT EXISTS (
2233                         SELECT 'x' FROM {context}
2234                         WHERE {context}.id = {repository_instances}.contextid)";
2235         }
2236         $DB->execute($sql);
2238         // Main savepoint reached.
2239         upgrade_main_savepoint(true, 2013070800.00);
2240     }
2242     if ($oldversion < 2013070800.01) {
2244         // Define field lastnamephonetic to be added to user.
2245         $table = new xmldb_table('user');
2246         $field = new xmldb_field('lastnamephonetic', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'imagealt');
2247         $index = new xmldb_index('lastnamephonetic', XMLDB_INDEX_NOTUNIQUE, array('lastnamephonetic'));
2249         // Conditionally launch add field lastnamephonetic.
2250         if (!$dbman->field_exists($table, $field)) {
2251             $dbman->add_field($table, $field);
2252             $dbman->add_index($table, $index);
2253         }
2255         // Define field firstnamephonetic to be added to user.
2256         $table = new xmldb_table('user');
2257         $field = new xmldb_field('firstnamephonetic', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'lastnamephonetic');
2258         $index = new xmldb_index('firstnamephonetic', XMLDB_INDEX_NOTUNIQUE, array('firstnamephonetic'));
2260         // Conditionally launch add field firstnamephonetic.
2261         if (!$dbman->field_exists($table, $field)) {
2262             $dbman->add_field($table, $field);
2263             $dbman->add_index($table, $index);
2264         }
2266         // Define field alternatename to be added to user.
2267         $table = new xmldb_table('user');
2268         $field = new xmldb_field('middlename', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'firstnamephonetic');
2269         $index = new xmldb_index('middlename', XMLDB_INDEX_NOTUNIQUE, array('middlename'));
2271         // Conditionally launch add field firstnamephonetic.
2272         if (!$dbman->field_exists($table, $field)) {
2273             $dbman->add_field($table, $field);
2274             $dbman->add_index($table, $index);
2275         }
2277         // Define field alternatename to be added to user.
2278         $table = new xmldb_table('user');
2279         $field = new xmldb_field('alternatename', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'middlename');
2280         $index = new xmldb_index('alternatename', XMLDB_INDEX_NOTUNIQUE, array('alternatename'));
2282         // Conditionally launch add field alternatename.
2283         if (!$dbman->field_exists($table, $field)) {
2284             $dbman->add_field($table, $field);
2285             $dbman->add_index($table, $index);
2286         }
2288         // Main savepoint reached.
2289         upgrade_main_savepoint(true, 2013070800.01);
2290     }
2291     if ($oldversion < 2013071500.01) {
2292         // The enrol_authorize plugin has been removed, if there are no records
2293         // and no plugin files then remove the plugin data.
2294         $enrolauthorize = new xmldb_table('enrol_authorize');
2295         $enrolauthorizerefunds = new xmldb_table('enrol_authorize_refunds');
2297         if (!file_exists($CFG->dirroot.'/enrol/authorize/version.php') &&
2298             $dbman->table_exists($enrolauthorize) &&
2299             $dbman->table_exists($enrolauthorizerefunds)) {
2301             $enrolauthorizecount = $DB->count_records('enrol_authorize');
2302             $enrolauthorizerefundcount = $DB->count_records('enrol_authorize_refunds');
2304             if (empty($enrolauthorizecount) && empty($enrolauthorizerefundcount)) {
2306                 // Drop the database tables.
2307                 $dbman->drop_table($enrolauthorize);
2308                 $dbman->drop_table($enrolauthorizerefunds);
2310                 // Drop the message provider and associated data manually.
2311                 $DB->delete_records('message_providers', array('component' => 'enrol_authorize'));
2312                 $DB->delete_records_select('config_plugins', "plugin = 'message' AND ".$DB->sql_like('name', '?', false), array("%_provider_enrol_authorize_%"));
2313                 $DB->delete_records_select('user_preferences', $DB->sql_like('name', '?', false), array("message_provider_enrol_authorize_%"));
2315                 // Remove capabilities.
2316                 capabilities_cleanup('enrol_authorize');
2318                 // Remove all other associated config.
2319                 unset_all_config_for_plugin('enrol_authorize');
2320             }
2321         }
2322         upgrade_main_savepoint(true, 2013071500.01);
2323     }
2325     if ($oldversion < 2013071500.02) {
2326         // Define field attachment to be dropped from badge.
2327         $table = new xmldb_table('badge');
2328         $field = new xmldb_field('image');
2330         // Conditionally launch drop field eventtype.
2331         if ($dbman->field_exists($table, $field)) {
2332             $dbman->drop_field($table, $field);
2333         }
2335         upgrade_main_savepoint(true, 2013071500.02);
2336     }
2338     if ($oldversion < 2013072600.01) {
2339         upgrade_mssql_nvarcharmax();
2340         upgrade_mssql_varbinarymax();
2342         upgrade_main_savepoint(true, 2013072600.01);
2343     }
2345     if ($oldversion < 2013081200.00) {
2346         // Define field uploadfiles to be added to external_services.
2347         $table = new xmldb_table('external_services');
2348         $field = new xmldb_field('uploadfiles', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'downloadfiles');
2350         // Conditionally launch add field uploadfiles.
2351         if (!$dbman->field_exists($table, $field)) {
2352             $dbman->add_field($table, $field);
2353         }
2355         // Main savepoint reached.
2356         upgrade_main_savepoint(true, 2013081200.00);
2357     }
2359     if ($oldversion < 2013082300.01) {
2360         // Define the table 'backup_logs' and the field 'message' which we will be changing from a char to a text field.
2361         $table = new xmldb_table('backup_logs');
2362         $field = new xmldb_field('message', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null, 'loglevel');
2364         // Perform the change.
2365         $dbman->change_field_type($table, $field);
2367         // Main savepoint reached.
2368         upgrade_main_savepoint(true, 2013082300.01);
2369     }
2371     // Convert SCORM course format courses to singleactivity.
2372     if ($oldversion < 2013082700.00) {
2373         // First set relevant singleactivity settings.
2374         $formatoptions = new stdClass();
2375         $formatoptions->format = 'singleactivity';
2376         $formatoptions->sectionid = 0;
2377         $formatoptions->name = 'activitytype';
2378         $formatoptions->value = 'scorm';
2380         $courses = $DB->get_recordset('course', array('format' => 'scorm'), 'id');
2381         foreach ($courses as $course) {
2382             $formatoptions->courseid = $course->id;
2383             $DB->insert_record('course_format_options', $formatoptions);
2384         }
2385         $courses->close();
2387         // Now update course format for these courses.
2388         $sql = "UPDATE {course}
2389                    SET format = 'singleactivity', modinfo = '', sectioncache = ''
2390                  WHERE format = 'scorm'";
2391         $DB->execute($sql);
2392         upgrade_main_savepoint(true, 2013082700.00);
2393     }
2395     if ($oldversion < 2013090500.01) {
2396         // Define field calendartype to be added to course.
2397         $table = new xmldb_table('course');
2398         $field = new xmldb_field('calendartype', XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, null);
2400         // Conditionally launch add field calendartype.
2401         if (!$dbman->field_exists($table, $field)) {
2402             $dbman->add_field($table, $field);
2403         }
2405         // Since structure of 'course' table has changed we need to re-read $SITE from DB.
2406         $SITE = $DB->get_record('course', array('id' => $SITE->id));
2407         $COURSE = clone($SITE);
2409         // Define field calendartype to be added to user.
2410         $table = new xmldb_table('user');
2411         $field = new xmldb_field('calendartype', XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, 'gregorian');
2413         // Conditionally launch add field calendartype.
2414         if (!$dbman->field_exists($table, $field)) {
2415             $dbman->add_field($table, $field);
2416         }
2418         // Main savepoint reached.
2419         upgrade_main_savepoint(true, 2013090500.01);
2420     }
2422     if ($oldversion < 2013091000.02) {
2424         // Define field cacherev to be added to course.
2425         $table = new xmldb_table('course');
2426         $field = new xmldb_field('cacherev', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'completionnotify');
2428         // Conditionally launch add field cacherev.
2429         if (!$dbman->field_exists($table, $field)) {
2430             $dbman->add_field($table, $field);
2431         }
2433         // Since structure of 'course' table has changed we need to re-read $SITE from DB.
2434         $SITE = $DB->get_record('course', array('id' => $SITE->id));
2435         $COURSE = clone($SITE);
2437         // Main savepoint reached.
2438         upgrade_main_savepoint(true, 2013091000.02);
2439     }
2441     if ($oldversion < 2013091000.03) {
2443         // Define field modinfo to be dropped from course.
2444         $table = new xmldb_table('course');
2445         $field = new xmldb_field('modinfo');
2447         // Conditionally launch drop field modinfo.
2448         if ($dbman->field_exists($table, $field)) {
2449             $dbman->drop_field($table, $field);
2450         }
2452         // Define field sectioncache to be dropped from course.
2453         $field = new xmldb_field('sectioncache');
2455         // Conditionally launch drop field sectioncache.
2456         if ($dbman->field_exists($table, $field)) {
2457             $dbman->drop_field($table, $field);
2458         }
2460         // Since structure of 'course' table has changed we need to re-read $SITE from DB.
2461         $SITE = $DB->get_record('course', array('id' => $SITE->id));
2462         $COURSE = clone($SITE);
2464         // Main savepoint reached.
2465         upgrade_main_savepoint(true, 2013091000.03);
2466     }
2468     if ($oldversion < 2013091300.01) {
2470         $table = new xmldb_table('user');
2472         // Changing precision of field institution on table user to (255).
2473         $field = new xmldb_field('institution', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'phone2');
2475         // Launch change of precision for field institution.
2476         $dbman->change_field_precision($table, $field);
2478         // Changing precision of field department on table user to (255).
2479         $field = new xmldb_field('department', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'institution');
2481         // Launch change of precision for field department.
2482         $dbman->change_field_precision($table, $field);
2484         // Changing precision of field address on table user to (255).
2485         $field = new xmldb_field('address', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'department');
2487         // Launch change of precision for field address.
2488         $dbman->change_field_precision($table, $field);
2490         // Main savepoint reached.
2491         upgrade_main_savepoint(true, 2013091300.01);
2492     }
2494     if ($oldversion < 2013092000.01) {
2496         // Define table question_statistics to be created.
2497         $table = new xmldb_table('question_statistics');
2499         // Adding fields to table question_statistics.
2500         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2501         $table->add_field('hashcode', XMLDB_TYPE_CHAR, '40', null, XMLDB_NOTNULL, null, null);
2502         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2503         $table->add_field('questionid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2504         $table->add_field('slot', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
2505         $table->add_field('subquestion', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, null);
2506         $table->add_field('s', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
2507         $table->add_field('effectiveweight', XMLDB_TYPE_NUMBER, '15, 5', null, null, null, null);
2508         $table->add_field('negcovar', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0');
2509         $table->add_field('discriminationindex', XMLDB_TYPE_NUMBER, '15, 5', null, null, null, null);
2510         $table->add_field('discriminativeefficiency', XMLDB_TYPE_NUMBER, '15, 5', null, null, null, null);
2511         $table->add_field('sd', XMLDB_TYPE_NUMBER, '15, 10', null, null, null, null);
2512         $table->add_field('facility', XMLDB_TYPE_NUMBER, '15, 10', null, null, null, null);
2513         $table->add_field('subquestions', XMLDB_TYPE_TEXT, null, null, null, null, null);
2514         $table->add_field('maxmark', XMLDB_TYPE_NUMBER, '12, 7', null, null, null, null);
2515         $table->add_field('positions', XMLDB_TYPE_TEXT, null, null, null, null, null);
2516         $table->add_field('randomguessscore', XMLDB_TYPE_NUMBER, '12, 7', null, null, null, null);
2518         // Adding keys to table question_statistics.
2519         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2521         // Conditionally launch create table for question_statistics.
2522         if (!$dbman->table_exists($table)) {
2523             $dbman->create_table($table);
2524         }
2526         // Define table question_response_analysis to be created.
2527         $table = new xmldb_table('question_response_analysis');
2529         // Adding fields to table question_response_analysis.
2530         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2531         $table->add_field('hashcode', XMLDB_TYPE_CHAR, '40', null, XMLDB_NOTNULL, null, null);
2532         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2533         $table->add_field('questionid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2534         $table->add_field('subqid', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
2535         $table->add_field('aid', XMLDB_TYPE_CHAR, '100', null, null, null, null);
2536         $table->add_field('response', XMLDB_TYPE_TEXT, null, null, null, null, null);
2537         $table->add_field('rcount', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
2538         $table->add_field('credit', XMLDB_TYPE_NUMBER, '15, 5', null, XMLDB_NOTNULL, null, null);
2540         // Adding keys to table question_response_analysis.
2541         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2543         // Conditionally launch create table for question_response_analysis.
2544         if (!$dbman->table_exists($table)) {
2545             $dbman->create_table($table);
2546         }
2548         // Main savepoint reached.
2549         upgrade_main_savepoint(true, 2013092000.01);
2550     }
2552     if ($oldversion < 2013092001.01) {
2553         // Force uninstall of deleted tool.
2554         if (!file_exists("$CFG->dirroot/$CFG->admin/tool/bloglevelupgrade")) {
2555             // Remove capabilities.
2556             capabilities_cleanup('tool_bloglevelupgrade');
2557             // Remove all other associated config.
2558             unset_all_config_for_plugin('tool_bloglevelupgrade');
2559         }
2560         upgrade_main_savepoint(true, 2013092001.01);
2561     }
2563     if ($oldversion < 2013092001.02) {
2564         // Define field version to be dropped from modules.
2565         $table = new xmldb_table('modules');
2566         $field = new xmldb_field('version');
2568         // Conditionally launch drop field version.
2569         if ($dbman->field_exists($table, $field)) {
2570             // Migrate all plugin version info to config_plugins table.
2571             $modules = $DB->get_records('modules');
2572             foreach ($modules as $module) {
2573                 set_config('version', $module->version, 'mod_'.$module->name);
2574             }
2575             unset($modules);
2577             $dbman->drop_field($table, $field);
2578         }
2580         // Define field version to be dropped from block.
2581         $table = new xmldb_table('block');
2582         $field = new xmldb_field('version');
2584         // Conditionally launch drop field version.
2585         if ($dbman->field_exists($table, $field)) {
2586             $blocks = $DB->get_records('block');
2587             foreach ($blocks as $block) {
2588                 set_config('version', $block->version, 'block_'.$block->name);
2589             }
2590             unset($blocks);
2592             $dbman->drop_field($table, $field);
2593         }
2595         // Main savepoint reached.
2596         upgrade_main_savepoint(true, 2013092001.02);
2597     }
2599     if ($oldversion < 2013092700.01) {
2601         $table = new xmldb_table('files');
2603         // Define field referencelastsync to be dropped from files.
2604         $field = new xmldb_field('referencelastsync');
2606         // Conditionally launch drop field referencelastsync.
2607         if ($dbman->field_exists($table, $field)) {
2608             $dbman->drop_field($table, $field);
2609         }
2611         // Define field referencelifetime to be dropped from files.
2612         $field = new xmldb_field('referencelifetime');
2614         // Conditionally launch drop field referencelifetime.
2615         if ($dbman->field_exists($table, $field)) {
2616             $dbman->drop_field($table, $field);
2617         }
2619         // Main savepoint reached.
2620         upgrade_main_savepoint(true, 2013092700.01);
2621     }
2623     if ($oldversion < 2013100400.01) {
2624         // Add user_devices core table.
2626         // Define field id to be added to user_devices.
2627         $table = new xmldb_table('user_devices');
2629         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null);
2630         $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'id');
2631         $table->add_field('appid', XMLDB_TYPE_CHAR, '128', null, XMLDB_NOTNULL, null, null, 'userid');
2632         $table->add_field('name', XMLDB_TYPE_CHAR, '32', null, XMLDB_NOTNULL, null, null, 'appid');
2633         $table->add_field('model', XMLDB_TYPE_CHAR, '32', null, XMLDB_NOTNULL, null, null, 'name');
2634         $table->add_field('platform', XMLDB_TYPE_CHAR, '32', null, XMLDB_NOTNULL, null, null, 'model');
2635         $table->add_field('version', XMLDB_TYPE_CHAR, '32', null, XMLDB_NOTNULL, null, null, 'platform');
2636         $table->add_field('pushid', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'version');
2637         $table->add_field('uuid', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'pushid');
2638         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'uuid');
2639         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'timecreated');
2641         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2642         $table->add_key('pushid-userid', XMLDB_KEY_UNIQUE, array('pushid', 'userid'));
2643         $table->add_key('pushid-platform', XMLDB_KEY_UNIQUE, array('pushid', 'platform'));
2644         $table->add_key('userid', XMLDB_KEY_FOREIGN, array('userid'), 'user', array('id'));
2646         if (!$dbman->table_exists($table)) {
2647             $dbman->create_table($table);
2648         }
2650         // Main savepoint reached.
2651         upgrade_main_savepoint(true, 2013100400.01);
2652     }
2654     if ($oldversion < 2013100800.00) {
2656         // Define field maxfraction to be added to question_attempts.
2657         $table = new xmldb_table('question_attempts');
2658         $field = new xmldb_field('maxfraction', XMLDB_TYPE_NUMBER, '12, 7', null, XMLDB_NOTNULL, null, '1', 'minfraction');
2660         // Conditionally launch add field maxfraction.
2661         if (!$dbman->field_exists($table, $field)) {
2662             $dbman->add_field($table, $field);
2663         }
2665         // Main savepoint reached.
2666         upgrade_main_savepoint(true, 2013100800.00);
2667     }
2669     if ($oldversion < 2013100800.01) {
2670         // Create a new 'user_password_resets' table.
2671         $table = new xmldb_table('user_password_resets');
2672         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null);
2673         $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, null);
2674         $table->add_field('timerequested', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, null);
2675         $table->add_field('timererequested', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 0, null);
2676         $table->add_field('token', XMLDB_TYPE_CHAR, '32', null, XMLDB_NOTNULL, null, null, null);
2678         // Adding keys to table.
2679         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2680         $table->add_key('fk_userid', XMLDB_KEY_FOREIGN, array('userid'), 'user', array('id'));
2682         // Conditionally launch create table.
2683         if (!$dbman->table_exists($table)) {
2684             $dbman->create_table($table);
2685         }
2686         upgrade_main_savepoint(true, 2013100800.01);
2687     }
2689     if ($oldversion < 2013100800.02) {
2690         $sql = "INSERT INTO {user_preferences}(userid, name, value)
2691                 SELECT id, 'htmleditor', 'textarea' FROM {user} u where u.htmleditor = 0";
2692         $DB->execute($sql);
2694         // Define field htmleditor to be dropped from user
2695         $table = new xmldb_table('user');
2696         $field = new xmldb_field('htmleditor');
2698         // Conditionally launch drop field requested
2699         if ($dbman->field_exists($table, $field)) {
2700             $dbman->drop_field($table, $field);
2701         }
2702         // Main savepoint reached.
2703         upgrade_main_savepoint(true, 2013100800.02);
2704     }
2706     if ($oldversion < 2013100900.00) {
2708         // Define field lifetime to be dropped from files_reference.
2709         $table = new xmldb_table('files_reference');
2710         $field = new xmldb_field('lifetime');
2712         // Conditionally launch drop field lifetime.
2713         if ($dbman->field_exists($table, $field)) {
2714             $dbman->drop_field($table, $field);
2715         }
2717         // Main savepoint reached.
2718         upgrade_main_savepoint(true, 2013100900.00);
2719     }
2721     if ($oldversion < 2013100901.00) {
2722         // Fixing possible wrong MIME type for Java Network Launch Protocol (JNLP) files.
2723         $select = $DB->sql_like('filename', '?', false);
2724         $DB->set_field_select(
2725             'files',
2726             'mimetype',
2727             'application/x-java-jnlp-file',
2728             $select,
2729             array('%.jnlp')
2730         );
2732         // Main savepoint reached.
2733         upgrade_main_savepoint(true, 2013100901.00);
2734     }
2736     if ($oldversion < 2013102100.00) {
2737         // Changing default value for the status of a course backup.
2738         $table = new xmldb_table('backup_courses');
2739         $field = new xmldb_field('laststatus', XMLDB_TYPE_CHAR, '1', null, XMLDB_NOTNULL, null, '5', 'lastendtime');
2741         // Launch change of precision for field value
2742         $dbman->change_field_precision($table, $field);
2744         // Main savepoint reached.
2745         upgrade_main_savepoint(true, 2013102100.00);
2746     }
2748     if ($oldversion < 2013102201.00) {
2749         $params = array('plugin' => 'editor_atto', 'name' => 'version');
2750         $attoversion = $DB->get_record('config_plugins',
2751                                        $params,
2752                                        'value',
2753                                        IGNORE_MISSING);
2755         if ($attoversion) {
2756             $attoversion = floatval($attoversion->value);
2757         }
2758         // Only these versions that were part of 2.6 beta should be removed.
2759         // Manually installed versions of 2.5 - or later releases for 2.6 installed
2760         // via the plugins DB should not be uninstalled.
2761         if ($attoversion && $attoversion > 2013051500.00 && $attoversion < 2013102201.00) {
2762             // Remove all other associated config.
2763             unset_all_config_for_plugin('editor_atto');
2764             unset_all_config_for_plugin('atto_bold');
2765             unset_all_config_for_plugin('atto_clear');
2766             unset_all_config_for_plugin('atto_html');
2767             unset_all_config_for_plugin('atto_image');
2768             unset_all_config_for_plugin('atto_indent');
2769             unset_all_config_for_plugin('atto_italic');
2770             unset_all_config_for_plugin('atto_link');
2771             unset_all_config_for_plugin('atto_media');
2772             unset_all_config_for_plugin('atto_orderedlist');
2773             unset_all_config_for_plugin('atto_outdent');
2774             unset_all_config_for_plugin('atto_strike');
2775             unset_all_config_for_plugin('atto_title');
2776             unset_all_config_for_plugin('atto_underline');
2777             unset_all_config_for_plugin('atto_unlink');
2778             unset_all_config_for_plugin('atto_unorderedlist');
2780         }
2782         // Main savepoint reached.
2783         upgrade_main_savepoint(true, 2013102201.00);
2784     }
2786     if ($oldversion < 2013102500.01) {
2787         // Find all fileareas that have missing root folder entry and add the root folder entry.
2788         if (empty($CFG->filesrootrecordsfixed)) {
2789             upgrade_fix_missing_root_folders();
2790             // To skip running the same script on the upgrade to the next major release.
2791             set_config('filesrootrecordsfixed', 1);
2792         }
2794         // Main savepoint reached.
2795         upgrade_main_savepoint(true, 2013102500.01);
2796     }
2798     if ($oldversion < 2013110500.01) {
2799         // MDL-38228. Corrected course_modules upgrade script instead of 2013021801.01.
2801         // This upgrade script fixes the mismatches between DB fields course_modules.section
2802         // and course_sections.sequence. It makes sure that each module is included
2803         // in the sequence of at least one section.
2804         // There is also a separate script for admins: admin/cli/fix_course_sortorder.php
2806         // This script in included in each major version upgrade process so make sure we don't run it twice.
2807         if (empty($CFG->movingmoduleupgradescriptwasrun)) {
2808             upgrade_course_modules_sequences();
2810             // To skip running the same script on the upgrade to the next major release.
2811             set_config('movingmoduleupgradescriptwasrun', 1);
2812         }
2814         // Main savepoint reached.
2815         upgrade_main_savepoint(true, 2013110500.01);
2816     }
2818     if ($oldversion < 2013110600.01) {
2820         if (!file_exists($CFG->dirroot . '/theme/mymobile')) {
2821             // Replace the mymobile settings.
2822             $DB->set_field('course', 'theme', 'clean', array('theme' => 'mymobile'));
2823             $DB->set_field('course_categories', 'theme', 'clean', array('theme' => 'mymobile'));
2824             $DB->set_field('user', 'theme', 'clean', array('theme' => 'mymobile'));
2825             $DB->set_field('mnet_host', 'theme', 'clean', array('theme' => 'mymobile'));
2827             // Replace the theme configs.
2828             if (get_config('core', 'theme') === 'mymobile') {
2829                 set_config('theme', 'clean');
2830             }
2831             if (get_config('core', 'thememobile') === 'mymobile') {
2832                 set_config('thememobile', 'clean');
2833             }
2834             if (get_config('core', 'themelegacy') === 'mymobile') {
2835                 set_config('themelegacy', 'clean');
2836             }
2837             if (get_config('core', 'themetablet') === 'mymobile') {
2838                 set_config('themetablet', 'clean');
2839             }
2841             // Hacky emulation of plugin uninstallation.
2842             unset_all_config_for_plugin('theme_mymobile');
2843         }
2845         // Main savepoint reached.
2846         upgrade_main_savepoint(true, 2013110600.01);
2847     }
2849     if ($oldversion < 2013110600.02) {
2851         // If the user is logged in, we ensure that the alternate name fields are present
2852         // in the session. It will not be the case when upgrading from 2.5 downwards.
2853         if (!empty($USER->id)) {
2854             $refreshuser = $DB->get_record('user', array('id' => $USER->id));
2855             $fields = array('firstnamephonetic', 'lastnamephonetic', 'middlename', 'alternatename', 'firstname', 'lastname');
2856             foreach ($fields as $field) {
2857                 $USER->{$field} = $refreshuser->{$field};
2858             }
2859         }
2861         // Main savepoint reached.
2862         upgrade_main_savepoint(true, 2013110600.02);
2863     }
2865     // Moodle v2.6.0 release upgrade line.
2866     // Put any upgrade step following this.
2867     if ($oldversion < 2013111800.01) {
2869         // Delete notes of deleted courses.
2870         $sql = "DELETE FROM {post}
2871                  WHERE NOT EXISTS (SELECT {course}.id FROM {course}
2872                                     WHERE {course}.id = {post}.courseid)
2873                        AND {post}.module = ?";
2874         $DB->execute($sql, array('notes'));
2876         // Main savepoint reached.
2877         upgrade_main_savepoint(true, 2013111800.01);
2878     }
2880     if ($oldversion < 2013122400.01) {
2881         // Purge stored passwords from config_log table, ideally this should be in each plugin
2882         // but that would complicate backporting...
2883         $items = array(
2884             'core/cronremotepassword', 'core/proxypassword', 'core/smtppass', 'core/jabberpassword',
2885             'enrol_database/dbpass', 'enrol_ldap/bind_pw', 'url/secretphrase');
2886         foreach ($items as $item) {
2887             list($plugin, $name) = explode('/', $item);
2888             $sqlcomparevalue =  $DB->sql_compare_text('value');
2889             $sqlcompareoldvalue = $DB->sql_compare_text('oldvalue');
2890             if ($plugin === 'core') {
2891                 $sql = "UPDATE {config_log}
2892                            SET value = :value
2893                          WHERE name = :name AND plugin IS NULL AND $sqlcomparevalue <> :empty";
2894                 $params = array('value' => '********', 'name' => $name, 'empty' => '');
2895                 $DB->execute($sql, $params);
2897                 $sql = "UPDATE {config_log}
2898                            SET oldvalue = :value
2899                          WHERE name = :name AND plugin IS NULL AND $sqlcompareoldvalue <> :empty";
2900                 $params = array('value' => '********', 'name' => $name, 'empty' => '');
2901                 $DB->execute($sql, $params);
2903             } else {
2904                 $sql = "UPDATE {config_log}
2905                            SET value = :value
2906                          WHERE name = :name AND plugin = :plugin AND $sqlcomparevalue <> :empty";
2907                 $params = array('value' => '********', 'name' => $name, 'plugin' => $plugin, 'empty' => '');
2908                 $DB->execute($sql, $params);
2910                 $sql = "UPDATE {config_log}
2911                            SET oldvalue = :value
2912                          WHERE name = :name AND plugin = :plugin AND  $sqlcompareoldvalue <> :empty";
2913                 $params = array('value' => '********', 'name' => $name, 'plugin' => $plugin, 'empty' => '');
2914                 $DB->execute($sql, $params);
2915             }
2916         }
2917         // Main savepoint reached.
2918         upgrade_main_savepoint(true, 2013122400.01);
2919     }
2921     if ($oldversion < 2014011000.01) {
2923         // Define table cache_text to be dropped.
2924         $table = new xmldb_table('cache_text');
2926         // Conditionally launch drop table for cache_text.
2927         if ($dbman->table_exists($table)) {
2928             $dbman->drop_table($table);
2929         }
2931         unset_config('cachetext');
2933         // Main savepoint reached.
2934         upgrade_main_savepoint(true, 2014011000.01);
2935     }
2937     if ($oldversion < 2014011701.00) {
2938         // Fix gradebook sortorder duplicates.
2939         upgrade_grade_item_fix_sortorder();
2941         // Main savepoint reached.
2942         upgrade_main_savepoint(true, 2014011701.00);
2943     }
2945     if ($oldversion < 2014012300.01) {
2946         // Remove deleted users home pages.
2947         $sql = "DELETE FROM {my_pages}
2948                 WHERE EXISTS (SELECT {user}.id
2949                                   FROM {user}
2950                                   WHERE {user}.id = {my_pages}.userid
2951                                   AND {user}.deleted = 1)
2952                 AND {my_pages}.private = 1";
2953         $DB->execute($sql);
2955         // Reached main savepoint.
2956         upgrade_main_savepoint(true, 2014012300.01);
2957     }
2959     if ($oldversion < 2014012400.00) {
2960         // Define table lock_db to be created.
2961         $table = new xmldb_table('lock_db');
2963         // Adding fields to table lock_db.
2964         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2965         $table->add_field('resourcekey', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
2966         $table->add_field('expires', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
2967         $table->add_field('owner', XMLDB_TYPE_CHAR, '36', null, null, null, null);
2969         // Adding keys to table lock_db.
2970         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2972         // Adding indexes to table lock_db.
2973         $table->add_index('resourcekey_uniq', XMLDB_INDEX_UNIQUE, array('resourcekey'));
2974         $table->add_index('expires_idx', XMLDB_INDEX_NOTUNIQUE, array('expires'));
2975         $table->add_index('owner_idx', XMLDB_INDEX_NOTUNIQUE, array('owner'));
2977         // Conditionally launch create table for lock_db.
2978         if (!$dbman->table_exists($table)) {
2979             $dbman->create_table($table);
2980         }
2982         // Main savepoint reached.
2983         upgrade_main_savepoint(true, 2014012400.00);
2984     }
2986     if ($oldversion < 2014021300.01) {
2987         // Delete any cached stats to force recalculation later, then we can be sure that cached records will have the correct
2988         // field.
2989         $DB->delete_records('question_response_analysis');
2990         $DB->delete_records('question_statistics');
2991         $DB->delete_records('quiz_statistics');
2993         // Define field variant to be added to question_statistics.
2994         $table = new xmldb_table('question_statistics');
2995         $field = new xmldb_field('variant', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'subquestion');
2997         // Conditionally launch add field variant.
2998         if (!$dbman->field_exists($table, $field)) {
2999             $dbman->add_field($table, $field);
3000         }
3002         // Main savepoint reached.
3003         upgrade_main_savepoint(true, 2014021300.01);
3004     }
3006     if ($oldversion < 2014021300.02) {
3008         // Define field variant to be added to question_response_analysis.
3009         $table = new xmldb_table('question_response_analysis');
3010         $field = new xmldb_field('variant', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'questionid');
3012         // Conditionally launch add field variant.
3013         if (!$dbman->field_exists($table, $field)) {
3014             $dbman->add_field($table, $field);
3015         }
3017         // Main savepoint reached.
3018         upgrade_main_savepoint(true, 2014021300.02);
3019     }
3021     if ($oldversion < 2014021800.00) {
3023         // Define field queued to be added to portfolio_tempdata.
3024         $table = new xmldb_table('portfolio_tempdata');
3025         $field = new xmldb_field('queued', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'instance');
3027         // Conditionally launch add field queued.
3028         if (!$dbman->field_exists($table, $field)) {
3029             $dbman->add_field($table, $field);
3030         }
3032         // Main savepoint reached.
3033         upgrade_main_savepoint(true, 2014021800.00);
3034     }
3036     if ($oldversion < 2014021900.01) {
3037         // Force uninstall of deleted tool.
3039         // Normally, in this sort of situation, we would do a file_exists check,
3040         // in case the plugin had been added back as an add-on. However, this
3041         // plugin is completely useless after Moodle 2.6, so we check that the
3042         // files have been removed in upgrade_stale_php_files_present, and we
3043         // uninstall it unconditionally here.
3045         // Remove all associated config.
3046         unset_all_config_for_plugin('tool_qeupgradehelper');
3048         upgrade_main_savepoint(true, 2014021900.01);
3049     }
3051     if ($oldversion < 2014021900.02) {
3053         // Define table question_states to be dropped.
3054         $table = new xmldb_table('question_states');
3056         // Conditionally launch drop table for question_states.
3057         if ($dbman->table_exists($table)) {
3058             $dbman->drop_table($table);
3059         }
3061         // Main savepoint reached.
3062         upgrade_main_savepoint(true, 2014021900.02);
3063     }
3065     if ($oldversion < 2014021900.03) {
3067         // Define table question_sessions to be dropped.
3068         $table = new xmldb_table('question_sessions');
3070         // Conditionally launch drop table for question_sessions.
3071         if ($dbman->table_exists($table)) {
3072             $dbman->drop_table($table);
3073         }
3075         // Main savepoint reached.
3076         upgrade_main_savepoint(true, 2014021900.03);
3077     }
3079     if ($oldversion < 2014022600.00) {
3080         $table = new xmldb_table('task_scheduled');
3082         // Adding fields to table task_scheduled.
3083         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3084         $table->add_field('component', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
3085         $table->add_field('classname', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
3086         $table->add_field('lastruntime', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
3087         $table->add_field('nextruntime', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
3088         $table->add_field('blocking', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0');
3089         $table->add_field('minute', XMLDB_TYPE_CHAR, '25', null, XMLDB_NOTNULL, null, null);
3090         $table->add_field('hour', XMLDB_TYPE_CHAR, '25', null, XMLDB_NOTNULL, null, null);
3091         $table->add_field('day', XMLDB_TYPE_CHAR, '25', null, XMLDB_NOTNULL, null, null);
3092         $table->add_field('month', XMLDB_TYPE_CHAR, '25', null, XMLDB_NOTNULL, null, null);
3093         $table->add_field('dayofweek', XMLDB_TYPE_CHAR, '25', null, XMLDB_NOTNULL, null, null);
3094         $table->add_field('faildelay', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
3095         $table->add_field('customised', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0');
3096         $table->add_field('disabled', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0');
3098         // Adding keys to table task_scheduled.
3099         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3101         // Adding indexes to table task_scheduled.
3102         $table->add_index('classname_uniq', XMLDB_INDEX_UNIQUE, array('classname'));
3104         // Conditionally launch create table for task_scheduled.
3105         if (!$dbman->table_exists($table)) {
3106             $dbman->create_table($table);
3107         }
3109         // Define table task_adhoc to be created.
3110         $table = new xmldb_table('task_adhoc');
3112         // Adding fields to table task_adhoc.
3113         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3114         $table->add_field('component', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
3115         $table->add_field('classname', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
3116         $table->add_field('nextruntime', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
3117         $table->add_field('faildelay', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
3118         $table->add_field('customdata', XMLDB_TYPE_TEXT, null, null, null, null, null);
3119         $table->add_field('blocking', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0');
3121         // Adding keys to table task_adhoc.
3122         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3124         // Adding indexes to table task_adhoc.
3125         $table->add_index('nextruntime_idx', XMLDB_INDEX_NOTUNIQUE, array('nextruntime'));
3127         // Conditionally launch create table for task_adhoc.
3128         if (!$dbman->table_exists($table)) {
3129             $dbman->create_table($table);
3130         }
3132         // Main savepoint reached.
3133         upgrade_main_savepoint(true, 2014022600.00);
3134     }
3136     if ($oldversion < 2014031400.02) {
3137         // Delete any cached stats to force recalculation later, then we can be sure that cached records will have the correct
3138         // field.
3139         $DB->delete_records('question_response_analysis');
3140         $DB->delete_records('question_statistics');
3141         $DB->delete_records('quiz_statistics');
3143         // Define field response to be dropped from question_response_analysis.
3144         $table = new xmldb_table('question_response_analysis');
3145         $field = new xmldb_field('rcount');
3147         // Conditionally launch drop field response.
3148         if ($dbman->field_exists($table, $field)) {
3149             $dbman->drop_field($table, $field);
3150         }
3152         // Main savepoint reached.
3153         upgrade_main_savepoint(true, 2014031400.02);
3154     }
3156     if ($oldversion < 2014031400.03) {
3158         // Define table question_response_count to be created.
3159         $table = new xmldb_table('question_response_count');
3161         // Adding fields to table question_response_count.
3162         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3163         $table->add_field('analysisid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
3164         $table->add_field('try', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
3165         $table->add_field('rcount', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
3167         // Adding keys to table question_response_count.
3168         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3169         $table->add_key('analysisid', XMLDB_KEY_FOREIGN, array('analysisid'), 'question_response_analysis', array('id'));
3171         // Conditionally launch create table for question_response_count.
3172         if (!$dbman->table_exists($table)) {
3173             $dbman->create_table($table);
3174         }
3176         // Main savepoint reached.
3177         upgrade_main_savepoint(true, 2014031400.03);
3178     }
3180     if ($oldversion < 2014031400.04) {
3182         // Define field whichtries to be added to question_response_analysis.
3183         $table = new xmldb_table('question_response_analysis');
3184         $field = new xmldb_field('whichtries', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'hashcode');
3186         // Conditionally launch add field whichtries.
3187         if (!$dbman->field_exists($table, $field)) {
3188             $dbman->add_field($table, $field);
3189         }
3191         // Main savepoint reached.
3192         upgrade_main_savepoint(true, 2014031400.04);
3193     }
3195     if ($oldversion < 2014032600.00) {
3196         // Removing the themes from core.
3197         $themes = array('afterburner', 'anomaly', 'arialist', 'binarius', 'boxxie', 'brick', 'formal_white', 'formfactor',
3198             'fusion', 'leatherbound', 'magazine', 'nimble', 'nonzero', 'overlay', 'serenity', 'sky_high', 'splash',
3199             'standard', 'standardold');
3201         foreach ($themes as $key => $theme) {
3202             if (check_dir_exists($CFG->dirroot . '/theme/' . $theme, false)) {
3203                 // Ignore the themes that have been re-downloaded.
3204                 unset($themes[$key]);
3205             }
3206         }
3208         // Check we actually have themes to remove.
3209         if (count($themes) > 0) {
3211             // Replace the theme configs.
3212             if (in_array(get_config('core', 'theme'), $themes)) {
3213                 set_config('theme', 'clean');
3214             }
3215             if (in_array(get_config('core', 'thememobile'), $themes)) {
3216                 set_config('thememobile', 'clean');
3217             }
3218             if (in_array(get_config('core', 'themelegacy'), $themes)) {
3219                 set_config('themelegacy', 'clean');
3220             }
3221             if (in_array(get_config('core', 'themetablet'), $themes)) {
3222                 set_config('themetablet', 'clean');
3223             }
3224         }
3226         // Main savepoint reached.
3227         upgrade_main_savepoint(true, 2014032600.00);
3228     }
3230     if ($oldversion < 2014032600.02) {
3231         // Add new fields to the 'tag_instance' table.
3232         $table = new xmldb_table('tag_instance');
3233         $field = new xmldb_field('component', XMLDB_TYPE_CHAR, '100', null, false, null, null, 'tagid');
3234         if (!$dbman->field_exists($table, $field)) {
3235             $dbman->add_field($table, $field);
3236         }
3238         $field = new xmldb_field('contextid', XMLDB_TYPE_INTEGER, '10', null, false, null, null, 'itemid');
3239         // Define the 'contextid' foreign key to be added to the tag_instance table.
3240         $key = new xmldb_key('contextid', XMLDB_KEY_FOREIGN, array('contextid'), 'context', array('id'));
3241         if ($dbman->field_exists($table, $field)) {
3242             $dbman->drop_key($table, $key);
3243             $DB->set_field('tag_instance', 'contextid', null, array('contextid' => 0));
3244             $dbman->change_field_default($table, $field);
3245         } else {
3246             $dbman->add_field($table, $field);
3247         }
3248         $dbman->add_key($table, $key);
3250         $field = new xmldb_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'ordering');
3251         if (!$dbman->field_exists($table, $field)) {
3252             $dbman->add_field($table, $field);
3253         }
3255         $sql = "UPDATE {tag_instance}
3256                    SET timecreated = timemodified";
3257         $DB->execute($sql);
3259         // Update all the course tags.
3260         $sql = "UPDATE {tag_instance}
3261                    SET component = 'core',
3262                        contextid = (SELECT ctx.id
3263                                       FROM {context} ctx
3264                                      WHERE ctx.contextlevel = :contextlevel
3265                                        AND ctx.instanceid = {tag_instance}.itemid)
3266                  WHERE itemtype = 'course' AND contextid IS NULL";
3267         $DB->execute($sql, array('contextlevel' => CONTEXT_COURSE));
3269         // Update all the user tags.
3270         $sql = "UPDATE {tag_instance}
3271                    SET component = 'core',
3272                        contextid = (SELECT ctx.id
3273                                       FROM {context} ctx
3274                                      WHERE ctx.contextlevel = :contextlevel
3275                                        AND ctx.instanceid = {tag_instance}.itemid)
3276                  WHERE itemtype = 'user' AND contextid IS NULL";
3277         $DB->execute($sql, array('contextlevel' => CONTEXT_USER));
3279         // Update all the blog post tags.
3280         $sql = "UPDATE {tag_instance}
3281                    SET component = 'core',
3282                        contextid = (SELECT ctx.id
3283                                       FROM {context} ctx
3284                                       JOIN {post} p
3285                                         ON p.userid = ctx.instanceid
3286                                      WHERE ctx.contextlevel = :contextlevel
3287                                        AND p.id = {tag_instance}.itemid)
3288                  WHERE itemtype = 'post' AND contextid IS NULL";
3289         $DB->execute($sql, array('contextlevel' => CONTEXT_USER));
3291         // Update all the wiki page tags.
3292         $sql = "UPDATE {tag_instance}
3293                    SET component = 'mod_wiki',
3294                        contextid = (SELECT ctx.id
3295                                       FROM {context} ctx
3296                                       JOIN {course_modules} cm
3297                                         ON cm.id = ctx.instanceid
3298                                       JOIN {modules} m
3299                                         ON m.id = cm.module
3300                                       JOIN {wiki} w
3301                                         ON w.id = cm.instance
3302                                       JOIN {wiki_subwikis} sw
3303                                         ON sw.wikiid = w.id
3304                                       JOIN {wiki_pages} wp
3305                                         ON wp.subwikiid = sw.id
3306                                      WHERE m.name = 'wiki'
3307                                        AND ctx.contextlevel = :contextlevel
3308                                        AND wp.id = {tag_instance}.itemid)
3309                  WHERE itemtype = 'wiki_pages' AND contextid IS NULL";
3310         $DB->execute($sql, array('contextlevel' => CONTEXT_MODULE));
3312         // Update all the question tags.
3313         $sql = "UPDATE {tag_instance}
3314                    SET component = 'core_question',
3315                        contextid = (SELECT qc.contextid
3316                                       FROM {question} q
3317                                       JOIN {question_categories} qc
3318                                         ON q.category = qc.id
3319                                      WHERE q.id = {tag_instance}.itemid)
3320                  WHERE itemtype = 'question' AND contextid IS NULL";
3321         $DB->execute($sql);
3323         // Update all the tag tags.
3324         $sql = "UPDATE {tag_instance}
3325                    SET component = 'core',
3326                        contextid = :systemcontext
3327                  WHERE itemtype = 'tag' AND contextid IS NULL";
3328         $DB->execute($sql, array('systemcontext' => context_system::instance()->id));
3330         // Main savepoint reached.
3331         upgrade_main_savepoint(true, 2014032600.02);
3332     }
3334     if ($oldversion < 2014032700.01) {
3336         // Define field disabled to be added to task_scheduled.
3337         $table = new xmldb_table('task_scheduled');
3338         $field = new xmldb_field('disabled', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'customised');
3340         // Conditionally launch add field disabled.
3341         if (!$dbman->field_exists($table, $field)) {
3342             $dbman->add_field($table, $field);
3343         }
3345         // Main savepoint reached.
3346         upgrade_main_savepoint(true, 2014032700.01);
3347     }
3349     if ($oldversion < 2014032700.02) {
3351         // Update displayloginfailures setting.
3352         if (empty($CFG->displayloginfailures)) {
3353             set_config('displayloginfailures', 0);
3354         } else {
3355             set_config('displayloginfailures', 1);
3356         }
3358         // Main savepoint reached.
3359         upgrade_main_savepoint(true, 2014032700.02);
3360     }
3362     if ($oldversion < 2014040800.00) {
3364         // Define field availability to be added to course_modules.
3365         $table = new xmldb_table('course_modules');
3366         $field = new xmldb_field('availability', XMLDB_TYPE_TEXT, null, null, null, null, null, 'showdescription');
3368         // Conditionally launch add field availability.
3369         if (!$dbman->field_exists($table, $field)) {
3370             $dbman->add_field($table, $field);
3371         }
3373         // Define field availability to be added to course_sections.
3374         $table = new xmldb_table('course_sections');
3375         $field = new xmldb_field('availability', XMLDB_TYPE_TEXT, null, null, null, null, null, 'groupingid');
3377         // Conditionally launch add field availability.
3378         if (!$dbman->field_exists($table, $field)) {
3379             $dbman->add_field($table, $field);
3380         }
3382         // Update existing conditions to new format. This could be a slow
3383         // process, so begin by counting the number of affected modules/sections.
3384         // (Performance: On the OU system, these took ~0.3 seconds, with about
3385         // 20,000 results out of about 400,000 total rows in those tables.)
3386         $cmcount = $DB->count_records_sql("
3387                 SELECT COUNT(1)
3388                   FROM {course_modules} cm
3389                  WHERE cm.availablefrom != 0 OR
3390                        cm.availableuntil != 0 OR
3391                        EXISTS (SELECT 1 FROM {course_modules_availability} WHERE coursemoduleid = cm.id) OR
3392                        EXISTS (SELECT 1 FROM {course_modules_avail_fields} WHERE coursemoduleid = cm.id)");
3393         $sectcount = $DB->count_records_sql("
3394                 SELECT COUNT(1)
3395                   FROM {course_sections} cs
3396                  WHERE cs.groupingid != 0 OR
3397                        cs.availablefrom != 0 OR
3398                        cs.availableuntil != 0 OR
3399                        EXISTS (SELECT 1 FROM {course_sections_availability} WHERE coursesectionid = cs.id) OR
3400                        EXISTS (SELECT 1 FROM {course_sections_avail_fields} WHERE coursesectionid = cs.id)");
3402         if ($cmcount + $sectcount > 0) {
3403             // Show progress bar and start db transaction.
3404             $transaction = $DB->start_delegated_transaction();
3405             $pbar = new progress_bar('availupdate', 500, true);
3407             // Loop through all course-modules.
3408             // (Performance: On the OU system, the query took <1 second for ~20k
3409             // results; updating all those entries took ~3 minutes.)
3410             $done = 0;
3411             $lastupdate = 0;
3412             $rs = $DB->get_recordset_sql("
3413                     SELECT cm.id, cm.availablefrom, cm.availableuntil, cm.showavailability,
3414                            COUNT(DISTINCT cma.id) AS availcount,
3415                            COUNT(DISTINCT cmf.id) AS fieldcount
3416                       FROM {course_modules} cm
3417                            LEFT JOIN {course_modules_availability} cma ON cma.coursemoduleid = cm.id
3418                            LEFT JOIN {course_modules_avail_fields} cmf ON cmf.coursemoduleid = cm.id
3419                      WHERE cm.availablefrom != 0 OR
3420                            cm.availableuntil != 0 OR
3421                            cma.id IS NOT NULL OR
3422                            cmf.id IS NOT NULL
3423                   GROUP BY cm.id, cm.availablefrom, cm.availableuntil, cm.showavailability");
3424             foreach ($rs as $rec) {
3425                 // Update progress initially and then once per second.
3426                 if (time() != $lastupdate) {
3427                     $lastupdate = time();
3428                     $pbar->update($done, $cmcount + $sectcount,
3429                             "Updating activity availability settings ($done/$cmcount)");
3430                 }
3432                 // Get supporting records - only if there are any (to reduce the
3433                 // number of queries where just date/group is used).
3434                 if ($rec->availcount) {
3435                     $availrecs = $DB->get_records('course_modules_availability',
3436                             array('coursemoduleid' => $rec->id));
3437                 } else {
3438                     $availrecs = array();
3439                 }
3440                 if ($rec->fieldcount) {
3441                     $fieldrecs = $DB->get_records_sql("
3442                             SELECT cmaf.userfield, cmaf.operator, cmaf.value, uif.shortname
3443                               FROM {course_modules_avail_fields} cmaf
3444                          LEFT JOIN {user_info_field} uif ON uif.id = cmaf.customfieldid
3445                              WHERE cmaf.coursemoduleid = ?", array($rec->id));
3446                 } else {
3447                     $fieldrecs = array();
3448                 }
3450                 // Update item.
3451                 $availability = upgrade_availability_item(0, 0,
3452                         $rec->availablefrom, $rec->availableuntil,
3453                         $rec->showavailability, $availrecs, $fieldrecs);
3454                 if ($availability) {
3455                     $DB->set_field('course_modules', 'availability', $availability, array('id' => $rec->id));
3456                 }
3458                 // Update progress.
3459                 $done++;
3460             }
3461             $rs->close();
3463             // Loop through all course-sections.
3464             // (Performance: On the OU system, this took <1 second for, er, 150 results.)
3465             $done = 0;
3466             $rs = $DB->get_recordset_sql("
3467                     SELECT cs.id, cs.groupingid, cs.availablefrom,
3468                            cs.availableuntil, cs.showavailability,
3469                            COUNT(DISTINCT csa.id) AS availcount,
3470                            COUNT(DISTINCT csf.id) AS fieldcount
3471                       FROM {course_sections} cs
3472                            LEFT JOIN {course_sections_availability} csa ON csa.coursesectionid = cs.id
3473                            LEFT JOIN {course_sections_avail_fields} csf ON csf.coursesectionid = cs.id
3474                      WHERE cs.groupingid != 0 OR
3475                            cs.availablefrom != 0 OR
3476                            cs.availableuntil != 0 OR
3477                            csa.id IS NOT NULL OR
3478                            csf.id IS NOT NULL
3479                   GROUP BY cs.id, cs.groupingid, cs.availablefrom,
3480                            cs.availableuntil, cs.showavailability");
3481             foreach ($rs as $rec) {
3482                 // Update progress once per second.
3483                 if (time() != $lastupdate) {
3484                     $lastupdate = time();
3485                     $pbar->update($done + $cmcount, $cmcount + $sectcount,
3486                             "Updating section availability settings ($done/$sectcount)");
3487                 }
3489                 // Get supporting records - only if there are any (to reduce the
3490                 // number of queries where just date/group is used).
3491                 if ($rec->availcount) {
3492                     $availrecs = $DB->get_records('course_sections_availability',
3493                             array('coursesectionid' => $rec->id));
3494                 } else {
3495                     $availrecs = array();
3496                 }
3497                 if ($rec->fieldcount) {
3498                     $fieldrecs = $DB->get_records_sql("
3499                             SELECT csaf.userfield, csaf.operator, csaf.value, uif.shortname
3500                               FROM {course_sections_avail_fields} csaf
3501                          LEFT JOIN {user_info_field} uif ON uif.id = csaf.customfieldid
3502                              WHERE csaf.coursesectionid = ?", array($rec->id));
3503                 } else {
3504                     $fieldrecs = array();
3505                 }
3507                 // Update item.
3508                 $availability = upgrade_availability_item($rec->groupingid ? 1 : 0,
3509                         $rec->groupingid, $rec->availablefrom, $rec->availableuntil,
3510                         $rec->showavailability, $availrecs, $fieldrecs);
3511                 if ($availability) {
3512                     $DB->set_field('course_sections', 'availability', $availability, array('id' => $rec->id));
3513                 }
3515                 // Update progress.
3516                 $done++;
3517             }
3518             $rs->close();
3520             // Final progress update for 100%.
3521             $pbar->update($done + $cmcount, $cmcount + $sectcount,
3522                     'Availability settings updated for ' . ($cmcount + $sectcount) .
3523                     ' activities and sections');
3525             $transaction->allow_commit();
3526         }
3528         // Drop tables which are not necessary because they are covered by the
3529         // new availability fields.
3530         $table = new xmldb_table('course_modules_availability');
3531         if ($dbman->table_exists($table)) {
3532             $dbman->drop_table($table);
3533         }
3534         $table = new xmldb_table('course_modules_avail_fields');
3535         if ($dbman->table_exists($table)) {
3536             $dbman->drop_table($table);
3537         }
3538         $table = new xmldb_table('course_sections_availability');
3539         if ($dbman->table_exists($table)) {
3540             $dbman->drop_table($table);
3541         }
3542         $table = new xmldb_table('course_sections_avail_fields');
3543         if ($dbman->table_exists($table)) {
3544             $dbman->drop_table($table);
3545         }
3547         // Drop unnnecessary fields from course_modules.
3548         $table = new xmldb_table('course_modules');
3549         $field = new xmldb_field('availablefrom');
3550         if ($dbman->field_exists($table, $field)) {
3551             $dbman->drop_field($table, $field);
3552         }
3553         $field = new xmldb_field('availableuntil');
3554         if ($dbman->field_exists($table, $field)) {
3555             $dbman->drop_field($table, $field);
3556         }
3557         $field = new xmldb_field('showavailability');
3558         if ($dbman->field_exists($table, $field)) {
3559             $dbman->drop_field($table, $field);
3560         }
3562         // Drop unnnecessary fields from course_sections.
3563         $table = new xmldb_table('course_sections');
3564         $field = new xmldb_field('availablefrom');
3565         if ($dbman->field_exists($table, $field)) {
3566             $dbman->drop_field($table, $field);
3567         }
3568         $field = new xmldb_field('availableuntil');
3569         if ($dbman->field_exists($table, $field)) {
3570             $dbman->drop_field($table, $field);
3571         }
3572         $field = new xmldb_field('showavailability');
3573         if ($dbman->field_exists($table, $field)) {
3574             $dbman->drop_field($table, $field);
3575         }
3576         $field = new xmldb_field('groupingid');
3577         if ($dbman->field_exists($table, $field)) {
3578             $dbman->drop_field($table, $field);
3579         }
3581         // Main savepoint reached.
3582         upgrade_main_savepoint(true, 2014040800.00);
3583     }
3585     if ($oldversion < 2014041500.01) {
3587         $table = new xmldb_table('user_info_data');
3589         $sql = 'SELECT DISTINCT info.id
3590                   FROM {user_info_data} info
3591             INNER JOIN {user_info_data} older
3592                     ON info.fieldid = older.fieldid
3593                    AND info.userid = older.userid
3594                    AND older.id < info.id';
3595         $transaction = $DB->start_delegated_transaction();
3596         $rs = $DB->get_recordset_sql($sql);
3597         foreach ($rs as $rec) {
3598             $DB->delete_records('user_info_data', array('id' => $rec->id));
3599         }
3600         $transaction->allow_commit();
3602         $oldindex = new xmldb_index('userid_fieldid', XMLDB_INDEX_NOTUNIQUE, array('userid', 'fieldid'));
3603         if ($dbman->index_exists($table, $oldindex)) {
3604             $dbman->drop_index($table, $oldindex);
3605         }
3607         $newindex = new xmldb_index('userid_fieldid', XMLDB_INDEX_UNIQUE, array('userid', 'fieldid'));
3609         if (!$dbman->index_exists($table, $newindex)) {
3610             $dbman->add_index($table, $newindex);
3611         }
3613         // Main savepoint reached.
3614         upgrade_main_savepoint(true, 2014041500.01);
3615     }
3617     if ($oldversion < 2014050100.00) {
3618         // Fixing possible wrong MIME type for DigiDoc files.
3619         $extensions = array('%.bdoc', '%.cdoc', '%.ddoc');
3620         $select = $DB->sql_like('filename', '?', false);
3621         foreach ($extensions as $extension) {
3622             $DB->set_field_select(
3623                 'files',
3624                 'mimetype',
3625                 'application/x-digidoc',
3626                 $select,
3627                 array($extension)
3628             );
3629         }
3630         upgrade_main_savepoint(true, 2014050100.00);
3631     }
3633     // Moodle v2.7.0 release upgrade line.
3634     // Put any upgrade step following this.
3636     // MDL-32543 Make sure that the log table has correct length for action and url fields.
3637     if ($oldversion < 2014051200.02) {
3639         $table = new xmldb_table('log');
3641         $columns = $DB->get_columns('log');
3642         if ($columns['action']->max_length < 40) {
3643             $index1 = new xmldb_index('course-module-action', XMLDB_INDEX_NOTUNIQUE, array('course', 'module', 'action'));
3644             if ($dbman->index_exists($table, $index1)) {
3645                 $dbman->drop_index($table, $index1);
3646             }
3647             $index2 = new xmldb_index('action', XMLDB_INDEX_NOTUNIQUE, array('action'));
3648             if ($dbman->index_exists($table, $index2)) {
3649                 $dbman->drop_index($table, $index2);
3650             }
3651             $field = new xmldb_field('action', XMLDB_TYPE_CHAR, '40', null, XMLDB_NOTNULL, null, null, 'cmid');
3652             $dbman->change_field_precision($table, $field);
3653             $dbman->add_index($table, $index1);
3654             $dbman->add_index($table, $index2);
3655         }
3657         if ($columns['url']->max_length < 100) {
3658             $field = new xmldb_field('url', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null, 'action');
3659             $dbman->change_field_precision($table, $field);
3660         }
3662         upgrade_main_savepoint(true, 2014051200.02);
3663     }
3665     if ($oldversion < 2014060300.00) {
3666         $gspath = get_config('assignfeedback_editpdf', 'gspath');
3667         if ($gspath !== false) {
3668             set_config('pathtogs', $gspath);
3669             unset_config('gspath', 'assignfeedback_editpdf');
3670         }
3671         upgrade_main_savepoint(true, 2014060300.00);
3672     }
3674     if ($oldversion < 2014061000.00) {
3675         // Fixing possible wrong MIME type for Publisher files.
3676         $filetypes = array('%.pub'=>'application/x-mspublisher');
3677         upgrade_mimetypes($filetypes);
3678         upgrade_main_savepoint(true, 2014061000.00);
3679     }
3681     if ($oldversion < 2014062600.01) {
3682         // We only want to delete DragMath if the directory no longer exists. If the directory
3683         // is present then it means it has been restored, so do not perform the uninstall.
3684         if (!check_dir_exists($CFG->libdir . '/editor/tinymce/plugins/dragmath', false)) {
3685             // Purge DragMath plugin which is incompatible with GNU GPL license.
3686             unset_all_config_for_plugin('tinymce_dragmath');
3687         }
3689         // Main savepoint reached.
3690         upgrade_main_savepoint(true, 2014062600.01);
3691     }
3693     // Switch the order of the fields in the files_reference index, to improve the performance of search_references.
3694     if ($oldversion < 2014070100.00) {
3695         $table = new xmldb_table('files_reference');
3696         $index = new xmldb_index('uq_external_file', XMLDB_INDEX_UNIQUE, array('repositoryid', 'referencehash'));
3697         if ($dbman->index_exists($table, $index)) {
3698             $dbman->drop_index($table, $index);
3699         }
3700         upgrade_main_savepoint(true, 2014070100.00);
3701     }
3703     if ($oldversion < 2014070101.00) {
3704         $table = new xmldb_table('files_reference');
3705         $index = new xmldb_index('uq_external_file', XMLDB_INDEX_UNIQUE, array('referencehash', 'repositoryid'));
3706         if (!$dbman->index_exists($table, $index)) {
3707             $dbman->add_index($table, $index);
3708         }
3709         upgrade_main_savepoint(true, 2014070101.00);
3710     }
3712     if ($oldversion < 2014072400.01) {
3713         $table = new xmldb_table('user_devices');
3714         $oldindex = new xmldb_index('pushid-platform', XMLDB_KEY_UNIQUE, array('pushid', 'platform'));
3715         if ($dbman->index_exists($table, $oldindex)) {
3716             $key = new xmldb_key('pushid-platform', XMLDB_KEY_UNIQUE, array('pushid', 'platform'));
3717             $dbman->drop_key($table, $key);
3718         }
3719         upgrade_main_savepoint(true, 2014072400.01);
3720     }
3722     if ($oldversion < 2014080801.00) {
3724         // Define index behaviour (not unique) to be added to question_attempts.
3725         $table = new xmldb_table('question_attempts');
3726         $index = new xmldb_index('behaviour', XMLDB_INDEX_NOTUNIQUE, array('behaviour'));
3728         // Conditionally launch add index behaviour.
3729         if (!$dbman->index_exists($table, $index)) {
3730             $dbman->add_index($table, $index);
3731         }
3733         // Main savepoint reached.
3734         upgrade_main_savepoint(true, 2014080801.00);
3735     }
3737     if ($oldversion < 2014082900.01) {
3738         // Fixing possible wrong MIME type for 7-zip and Rar files.
3739         $filetypes = array(
3740                 '%.7z' => 'application/x-7z-compressed',
3741                 '%.rar' => 'application/x-rar-compressed');
3742         upgrade_mimetypes($filetypes);
3743         upgrade_main_savepoint(true, 2014082900.01);
3744     }
3746     if ($oldversion < 2014082900.02) {
3747         // Replace groupmembersonly usage with new availability system.
3748         $transaction = $DB->start_delegated_transaction();
3749         if ($CFG->enablegroupmembersonly) {
3750             // If it isn't already enabled, we need to enable availability.
3751             if (!$CFG->enableavailability) {
3752                 set_config('enableavailability', 1);
3753             }
3755             // Count all course-modules with groupmembersonly set (for progress
3756             // bar).
3757             $total = $DB->count_records('course_modules', array('groupmembersonly' => 1));
3758             $pbar = new progress_bar('upgradegroupmembersonly', 500, true);
3760             // Get all these course-modules, one at a time.
3761             $rs = $DB->get_recordset('course_modules', array('groupmembersonly' => 1),
3762                     'course, id');
3763             $i = 0;
3764             foreach ($rs as $cm) {
3765                 // Calculate and set new availability value.
3766                 $availability = upgrade_group_members_only($cm->groupingid, $cm->availability);
3767                 $DB->set_field('course_modules', 'availability', $availability,
3768                         array('id' => $cm->id));
3770                 // Update progress.
3771                 $i++;
3772                 $pbar->update($i, $total, "Upgrading groupmembersonly settings - $i/$total.");
3773             }
3774             $rs->close();
3775         }
3777         // Define field groupmembersonly to be dropped from course_modules.
3778         $table = new xmldb_table('course_modules');
3779         $field = new xmldb_field('groupmembersonly');
3781         // Conditionally launch drop field groupmembersonly.
3782         if ($dbman->field_exists($table, $field)) {
3783             $dbman->drop_field($table, $field);
3784         }
3786         // Unset old config variable.
3787         unset_config('enablegroupmembersonly');
3788         $transaction->allow_commit();
3790         upgrade_main_savepoint(true, 2014082900.02);
3791     }
3793     if ($oldversion < 2014100100.00) {
3795         // Define table messageinbound_handlers to be created.
3796         $table = new xmldb_table('messageinbound_handlers');
3798         // Adding fields to table messageinbound_handlers.
3799         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3800         $table->add_field('component', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
3801         $table->add_field('classname', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
3802         $table->add_field('defaultexpiration', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '86400');
3803         $table->add_field('validateaddress', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1');
3804         $table->add_field('enabled', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0');
3806         // Adding keys to table messageinbound_handlers.
3807         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3808         $table->add_key('classname', XMLDB_KEY_UNIQUE, array('classname'));
3810         // Conditionally launch create table for messageinbound_handlers.
3811         if (!$dbman->table_exists($table)) {
3812             $dbman->create_table($table);
3813         }
3815         // Define table messageinbound_datakeys to be created.
3816         $table = new xmldb_table('messageinbound_datakeys');
3818         // Adding fields to table messageinbound_datakeys.
3819         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3820         $table->add_field('handler', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
3821         $table->add_field('datavalue', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
3822         $table->add_field('datakey', XMLDB_TYPE_CHAR, '64', null, null, null, null);
3823         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
3824         $table->add_field('expires', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
3826         // Adding keys to table messageinbound_datakeys.
3827         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3828         $table->add_key('handler_datavalue', XMLDB_KEY_UNIQUE, array('handler', 'datavalue'));
3829         $table->add_key('handler', XMLDB_KEY_FOREIGN, array('handler'), 'messageinbound_handlers', array('id'));
3831         // Conditionally launch create table for messageinbound_datakeys.
3832         if (!$dbman->table_exists($table)) {
3833             $dbman->create_table($table);
3834         }
3836         // Main savepoint reached.
3837         upgrade_main_savepoint(true, 2014100100.00);
3838     }
3840     return true;