MDL-54864 core_question: Enforce context,stamp uniqueness for category
[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, $DB;
90     require_once($CFG->libdir.'/db/upgradelib.php'); // Core Upgrade-related functions.
92     $dbman = $DB->get_manager(); // Loads ddl manager and xmldb classes.
94     // Always keep this upgrade step with version being the minimum
95     // allowed version to upgrade from (v2.7.0 right now).
96     if ($oldversion < 2014051200) {
97         // Just in case somebody hacks upgrade scripts or env, we really can not continue.
98         echo("You need to upgrade to 2.7.x or higher first!\n");
99         exit(1);
100         // Note this savepoint is 100% unreachable, but needed to pass the upgrade checks.
101         upgrade_main_savepoint(true, 2014051200);
102     }
104     // MDL-32543 Make sure that the log table has correct length for action and url fields.
105     if ($oldversion < 2014051200.02) {
107         $table = new xmldb_table('log');
109         $columns = $DB->get_columns('log');
110         if ($columns['action']->max_length < 40) {
111             $index1 = new xmldb_index('course-module-action', XMLDB_INDEX_NOTUNIQUE, array('course', 'module', 'action'));
112             if ($dbman->index_exists($table, $index1)) {
113                 $dbman->drop_index($table, $index1);
114             }
115             $index2 = new xmldb_index('action', XMLDB_INDEX_NOTUNIQUE, array('action'));
116             if ($dbman->index_exists($table, $index2)) {
117                 $dbman->drop_index($table, $index2);
118             }
119             $field = new xmldb_field('action', XMLDB_TYPE_CHAR, '40', null, XMLDB_NOTNULL, null, null, 'cmid');
120             $dbman->change_field_precision($table, $field);
121             $dbman->add_index($table, $index1);
122             $dbman->add_index($table, $index2);
123         }
125         if ($columns['url']->max_length < 100) {
126             $field = new xmldb_field('url', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null, 'action');
127             $dbman->change_field_precision($table, $field);
128         }
130         upgrade_main_savepoint(true, 2014051200.02);
131     }
133     if ($oldversion < 2014060300.00) {
134         $gspath = get_config('assignfeedback_editpdf', 'gspath');
135         if ($gspath !== false) {
136             set_config('pathtogs', $gspath);
137             unset_config('gspath', 'assignfeedback_editpdf');
138         }
139         upgrade_main_savepoint(true, 2014060300.00);
140     }
142     if ($oldversion < 2014061000.00) {
143         // Fixing possible wrong MIME type for Publisher files.
144         $filetypes = array('%.pub'=>'application/x-mspublisher');
145         upgrade_mimetypes($filetypes);
146         upgrade_main_savepoint(true, 2014061000.00);
147     }
149     if ($oldversion < 2014062600.01) {
150         // We only want to delete DragMath if the directory no longer exists. If the directory
151         // is present then it means it has been restored, so do not perform the uninstall.
152         if (!check_dir_exists($CFG->libdir . '/editor/tinymce/plugins/dragmath', false)) {
153             // Purge DragMath plugin which is incompatible with GNU GPL license.
154             unset_all_config_for_plugin('tinymce_dragmath');
155         }
157         // Main savepoint reached.
158         upgrade_main_savepoint(true, 2014062600.01);
159     }
161     // Switch the order of the fields in the files_reference index, to improve the performance of search_references.
162     if ($oldversion < 2014070100.00) {
163         $table = new xmldb_table('files_reference');
164         $index = new xmldb_index('uq_external_file', XMLDB_INDEX_UNIQUE, array('repositoryid', 'referencehash'));
165         if ($dbman->index_exists($table, $index)) {
166             $dbman->drop_index($table, $index);
167         }
168         upgrade_main_savepoint(true, 2014070100.00);
169     }
171     if ($oldversion < 2014070101.00) {
172         $table = new xmldb_table('files_reference');
173         $index = new xmldb_index('uq_external_file', XMLDB_INDEX_UNIQUE, array('referencehash', 'repositoryid'));
174         if (!$dbman->index_exists($table, $index)) {
175             $dbman->add_index($table, $index);
176         }
177         upgrade_main_savepoint(true, 2014070101.00);
178     }
180     if ($oldversion < 2014072400.01) {
181         $table = new xmldb_table('user_devices');
182         $oldindex = new xmldb_index('pushid-platform', XMLDB_KEY_UNIQUE, array('pushid', 'platform'));
183         if ($dbman->index_exists($table, $oldindex)) {
184             $key = new xmldb_key('pushid-platform', XMLDB_KEY_UNIQUE, array('pushid', 'platform'));
185             $dbman->drop_key($table, $key);
186         }
187         upgrade_main_savepoint(true, 2014072400.01);
188     }
190     if ($oldversion < 2014080801.00) {
192         // Define index behaviour (not unique) to be added to question_attempts.
193         $table = new xmldb_table('question_attempts');
194         $index = new xmldb_index('behaviour', XMLDB_INDEX_NOTUNIQUE, array('behaviour'));
196         // Conditionally launch add index behaviour.
197         if (!$dbman->index_exists($table, $index)) {
198             $dbman->add_index($table, $index);
199         }
201         // Main savepoint reached.
202         upgrade_main_savepoint(true, 2014080801.00);
203     }
205     if ($oldversion < 2014082900.01) {
206         // Fixing possible wrong MIME type for 7-zip and Rar files.
207         $filetypes = array(
208                 '%.7z' => 'application/x-7z-compressed',
209                 '%.rar' => 'application/x-rar-compressed');
210         upgrade_mimetypes($filetypes);
211         upgrade_main_savepoint(true, 2014082900.01);
212     }
214     if ($oldversion < 2014082900.02) {
215         // Replace groupmembersonly usage with new availability system.
216         $transaction = $DB->start_delegated_transaction();
217         if ($CFG->enablegroupmembersonly) {
218             // If it isn't already enabled, we need to enable availability.
219             if (!$CFG->enableavailability) {
220                 set_config('enableavailability', 1);
221             }
223             // Count all course-modules with groupmembersonly set (for progress
224             // bar).
225             $total = $DB->count_records('course_modules', array('groupmembersonly' => 1));
226             $pbar = new progress_bar('upgradegroupmembersonly', 500, true);
228             // Get all these course-modules, one at a time.
229             $rs = $DB->get_recordset('course_modules', array('groupmembersonly' => 1),
230                     'course, id');
231             $i = 0;
232             foreach ($rs as $cm) {
233                 // Calculate and set new availability value.
234                 $availability = upgrade_group_members_only($cm->groupingid, $cm->availability);
235                 $DB->set_field('course_modules', 'availability', $availability,
236                         array('id' => $cm->id));
238                 // Update progress.
239                 $i++;
240                 $pbar->update($i, $total, "Upgrading groupmembersonly settings - $i/$total.");
241             }
242             $rs->close();
243         }
245         // Define field groupmembersonly to be dropped from course_modules.
246         $table = new xmldb_table('course_modules');
247         $field = new xmldb_field('groupmembersonly');
249         // Conditionally launch drop field groupmembersonly.
250         if ($dbman->field_exists($table, $field)) {
251             $dbman->drop_field($table, $field);
252         }
254         // Unset old config variable.
255         unset_config('enablegroupmembersonly');
256         $transaction->allow_commit();
258         upgrade_main_savepoint(true, 2014082900.02);
259     }
261     if ($oldversion < 2014100100.00) {
263         // Define table messageinbound_handlers to be created.
264         $table = new xmldb_table('messageinbound_handlers');
266         // Adding fields to table messageinbound_handlers.
267         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
268         $table->add_field('component', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
269         $table->add_field('classname', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
270         $table->add_field('defaultexpiration', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '86400');
271         $table->add_field('validateaddress', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1');
272         $table->add_field('enabled', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0');
274         // Adding keys to table messageinbound_handlers.
275         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
276         $table->add_key('classname', XMLDB_KEY_UNIQUE, array('classname'));
278         // Conditionally launch create table for messageinbound_handlers.
279         if (!$dbman->table_exists($table)) {
280             $dbman->create_table($table);
281         }
283         // Define table messageinbound_datakeys to be created.
284         $table = new xmldb_table('messageinbound_datakeys');
286         // Adding fields to table messageinbound_datakeys.
287         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
288         $table->add_field('handler', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
289         $table->add_field('datavalue', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
290         $table->add_field('datakey', XMLDB_TYPE_CHAR, '64', null, null, null, null);
291         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
292         $table->add_field('expires', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
294         // Adding keys to table messageinbound_datakeys.
295         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
296         $table->add_key('handler_datavalue', XMLDB_KEY_UNIQUE, array('handler', 'datavalue'));
297         $table->add_key('handler', XMLDB_KEY_FOREIGN, array('handler'), 'messageinbound_handlers', array('id'));
299         // Conditionally launch create table for messageinbound_datakeys.
300         if (!$dbman->table_exists($table)) {
301             $dbman->create_table($table);
302         }
304         // Main savepoint reached.
305         upgrade_main_savepoint(true, 2014100100.00);
306     }
308     if ($oldversion < 2014100600.01) {
309         // Define field aggregationstatus to be added to grade_grades.
310         $table = new xmldb_table('grade_grades');
311         $field = new xmldb_field('aggregationstatus', XMLDB_TYPE_CHAR, '10', null, XMLDB_NOTNULL, null, 'unknown', 'timemodified');
313         // Conditionally launch add field aggregationstatus.
314         if (!$dbman->field_exists($table, $field)) {
315             $dbman->add_field($table, $field);
316         }
318         $field = new xmldb_field('aggregationweight', XMLDB_TYPE_NUMBER, '10, 5', null, null, null, null, 'aggregationstatus');
320         // Conditionally launch add field aggregationweight.
321         if (!$dbman->field_exists($table, $field)) {
322             $dbman->add_field($table, $field);
323         }
325         // Define field aggregationcoef2 to be added to grade_items.
326         $table = new xmldb_table('grade_items');
327         $field = new xmldb_field('aggregationcoef2', XMLDB_TYPE_NUMBER, '10, 5', null, XMLDB_NOTNULL, null, '0', 'aggregationcoef');
329         // Conditionally launch add field aggregationcoef2.
330         if (!$dbman->field_exists($table, $field)) {
331             $dbman->add_field($table, $field);
332         }
334         $field = new xmldb_field('weightoverride', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'needsupdate');
336         // Conditionally launch add field weightoverride.
337         if (!$dbman->field_exists($table, $field)) {
338             $dbman->add_field($table, $field);
339         }
341         // Main savepoint reached.
342         upgrade_main_savepoint(true, 2014100600.01);
343     }
345     if ($oldversion < 2014100600.02) {
347         // Define field aggregationcoef2 to be added to grade_items_history.
348         $table = new xmldb_table('grade_items_history');
349         $field = new xmldb_field('aggregationcoef2', XMLDB_TYPE_NUMBER, '10, 5', null, XMLDB_NOTNULL, null, '0', 'aggregationcoef');
351         // Conditionally launch add field aggregationcoef2.
352         if (!$dbman->field_exists($table, $field)) {
353             $dbman->add_field($table, $field);
354         }
356         // Main savepoint reached.
357         upgrade_main_savepoint(true, 2014100600.02);
358     }
360     if ($oldversion < 2014100600.03) {
362         // Define field weightoverride to be added to grade_items_history.
363         $table = new xmldb_table('grade_items_history');
364         $field = new xmldb_field('weightoverride', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'decimals');
366         // Conditionally launch add field weightoverride.
367         if (!$dbman->field_exists($table, $field)) {
368             $dbman->add_field($table, $field);
369         }
371         // Main savepoint reached.
372         upgrade_main_savepoint(true, 2014100600.03);
373     }
374     if ($oldversion < 2014100600.04) {
375         // Set flags so we can display a notice on all courses that might
376         // be affected by the uprade to natural aggregation.
377         if (!get_config('grades_sumofgrades_upgrade_flagged', 'core')) {
378             // 13 == SUM_OF_GRADES.
379             $sql = 'SELECT DISTINCT courseid
380                       FROM {grade_categories}
381                      WHERE aggregation = ?';
382             $courses = $DB->get_records_sql($sql, array(13));
384             foreach ($courses as $course) {
385                 set_config('show_sumofgrades_upgrade_' . $course->courseid, 1);
386                 // Set each of the grade items to needing an update so that when the user visits the grade reports the
387                 // figures will be updated.
388                 $DB->set_field('grade_items', 'needsupdate', 1, array('courseid' => $course->courseid));
389             }
391             set_config('grades_sumofgrades_upgrade_flagged', 1);
392         }
394         // Main savepoint reached.
395         upgrade_main_savepoint(true, 2014100600.04);
396     }
398     if ($oldversion < 2014100700.00) {
400         // Define table messageinbound_messagelist to be created.
401         $table = new xmldb_table('messageinbound_messagelist');
403         // Adding fields to table messageinbound_messagelist.
404         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
405         $table->add_field('messageid', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
406         $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
407         $table->add_field('address', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
408         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
410         // Adding keys to table messageinbound_messagelist.
411         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
412         $table->add_key('userid', XMLDB_KEY_FOREIGN, array('userid'), 'user', array('id'));
414         // Conditionally launch create table for messageinbound_messagelist.
415         if (!$dbman->table_exists($table)) {
416             $dbman->create_table($table);
417         }
419         // Main savepoint reached.
420         upgrade_main_savepoint(true, 2014100700.00);
421     }
423     if ($oldversion < 2014100700.01) {
425         // Define field visible to be added to cohort.
426         $table = new xmldb_table('cohort');
427         $field = new xmldb_field('visible', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'descriptionformat');
429         // Conditionally launch add field visible.
430         if (!$dbman->field_exists($table, $field)) {
431             $dbman->add_field($table, $field);
432         }
434         // Main savepoint reached.
435         upgrade_main_savepoint(true, 2014100700.01);
436     }
438     if ($oldversion < 2014100800.00) {
439         // Remove qformat_learnwise (unless it has manually been added back).
440         if (!file_exists($CFG->dirroot . '/question/format/learnwise/format.php')) {
441             unset_all_config_for_plugin('qformat_learnwise');
442         }
444         // Main savepoint reached.
445         upgrade_main_savepoint(true, 2014100800.00);
446     }
448     if ($oldversion < 2014101001.00) {
449         // Some blocks added themselves to the my/ home page, but they did not declare the
450         // subpage of the default my home page. While the upgrade script has been fixed, this
451         // upgrade script will fix the data that was wrongly added.
453         // We only proceed if we can find the right entry from my_pages. Private => 1 refers to
454         // the constant value MY_PAGE_PRIVATE.
455         if ($systempage = $DB->get_record('my_pages', array('userid' => null, 'private' => 1))) {
457             // Select the blocks there could have been automatically added. showinsubcontexts is hardcoded to 0
458             // because it is possible for administrators to have forced it on the my/ page by adding it to the
459             // system directly rather than updating the default my/ page.
460             $blocks = array('course_overview', 'private_files', 'online_users', 'badges', 'calendar_month', 'calendar_upcoming');
461             list($blocksql, $blockparams) = $DB->get_in_or_equal($blocks, SQL_PARAMS_NAMED);
462             $select = "parentcontextid = :contextid
463                     AND pagetypepattern = :page
464                     AND showinsubcontexts = 0
465                     AND subpagepattern IS NULL
466                     AND blockname $blocksql";
467             $params = array(
468                 'contextid' => context_system::instance()->id,
469                 'page' => 'my-index'
470             );
471             $params = array_merge($params, $blockparams);
473             $DB->set_field_select(
474                 'block_instances',
475                 'subpagepattern',
476                 $systempage->id,
477                 $select,
478                 $params
479             );
480         }
482         // Main savepoint reached.
483         upgrade_main_savepoint(true, 2014101001.00);
484     }
486     if ($oldversion < 2014102000.00) {
488         // Define field aggregatesubcats to be dropped from grade_categories.
489         $table = new xmldb_table('grade_categories');
490         $field = new xmldb_field('aggregatesubcats');
492         // Conditionally launch drop field aggregatesubcats.
493         if ($dbman->field_exists($table, $field)) {
495             $sql = 'SELECT DISTINCT courseid
496                       FROM {grade_categories}
497                      WHERE aggregatesubcats = ?';
498             $courses = $DB->get_records_sql($sql, array(1));
500             foreach ($courses as $course) {
501                 set_config('show_aggregatesubcats_upgrade_' . $course->courseid, 1);
502                 // Set each of the grade items to needing an update so that when the user visits the grade reports the
503                 // figures will be updated.
504                 $DB->set_field('grade_items', 'needsupdate', 1, array('courseid' => $course->courseid));
505             }
508             $dbman->drop_field($table, $field);
509         }
511         // Main savepoint reached.
512         upgrade_main_savepoint(true, 2014102000.00);
513     }
515     if ($oldversion < 2014110300.00) {
516         // Run script restoring missing folder records for draft file areas.
517         upgrade_fix_missing_root_folders_draft();
519         // Main savepoint reached.
520         upgrade_main_savepoint(true, 2014110300.00);
521     }
523     // Moodle v2.8.0 release upgrade line.
524     // Put any upgrade step following this.
526     if ($oldversion < 2014111000.00) {
527         // Coming from 2.7 or older, we need to flag the step minmaxgrade to be ignored.
528         set_config('upgrade_minmaxgradestepignored', 1);
529         // Coming from 2.7 or older, we need to flag the step for changing calculated grades to be regraded.
530         set_config('upgrade_calculatedgradeitemsonlyregrade', 1);
532         // Main savepoint reached.
533         upgrade_main_savepoint(true, 2014111000.00);
534     }
536     if ($oldversion < 2014120100.00) {
538         // Define field sslverification to be added to mnet_host.
539         $table = new xmldb_table('mnet_host');
540         $field = new xmldb_field('sslverification', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'applicationid');
542         // Conditionally launch add field sslverification.
543         if (!$dbman->field_exists($table, $field)) {
544             $dbman->add_field($table, $field);
545         }
547         // Main savepoint reached.
548         upgrade_main_savepoint(true, 2014120100.00);
549     }
551     if ($oldversion < 2014120101.00) {
553         // Define field component to be added to comments.
554         $table = new xmldb_table('comments');
555         $field = new xmldb_field('component', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'contextid');
557         // Conditionally launch add field component.
558         if (!$dbman->field_exists($table, $field)) {
559             $dbman->add_field($table, $field);
560         }
562         // Main savepoint reached.
563         upgrade_main_savepoint(true, 2014120101.00);
564     }
566     if ($oldversion < 2014120102.00) {
568         // Define table user_password_history to be created.
569         $table = new xmldb_table('user_password_history');
571         // Adding fields to table user_password_history.
572         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
573         $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
574         $table->add_field('hash', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
575         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
577         // Adding keys to table user_password_history.
578         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
579         $table->add_key('userid', XMLDB_KEY_FOREIGN, array('userid'), 'user', array('id'));
581         // Conditionally launch create table for user_password_history.
582         if (!$dbman->table_exists($table)) {
583             $dbman->create_table($table);
584         }
586         // Main savepoint reached.
587         upgrade_main_savepoint(true, 2014120102.00);
588     }
590     if ($oldversion < 2015010800.01) {
592         // Make sure the private files handler is not set to expire.
593         $DB->set_field('messageinbound_handlers', 'defaultexpiration', 0,
594                 array('classname' => '\core\message\inbound\private_files_handler'));
596         // Main savepoint reached.
597         upgrade_main_savepoint(true, 2015010800.01);
599     }
601     if ($oldversion < 2015012600.00) {
603         // If the site is using internal and external storage, or just external
604         // storage, and the external path specified is empty we change the setting
605         // to internal only. That is how the backup code is handling this
606         // misconfiguration.
607         $storage = (int) get_config('backup', 'backup_auto_storage');
608         $folder = get_config('backup', 'backup_auto_destination');
609         if ($storage !== 0 && empty($folder)) {
610             set_config('backup_auto_storage', 0, 'backup');
611         }
613         // Main savepoint reached.
614         upgrade_main_savepoint(true, 2015012600.00);
615     }
617     if ($oldversion < 2015012600.01) {
619         // Convert calendar_lookahead to nearest new value.
620         $value = $DB->get_field('config', 'value', array('name' => 'calendar_lookahead'));
621         if ($value > 90) {
622             set_config('calendar_lookahead', '120');
623         } else if ($value > 60 and $value < 90) {
624             set_config('calendar_lookahead', '90');
625         } else if ($value > 30 and $value < 60) {
626             set_config('calendar_lookahead', '60');
627         } else if ($value > 21 and $value < 30) {
628             set_config('calendar_lookahead', '30');
629         } else if ($value > 14 and $value < 21) {
630             set_config('calendar_lookahead', '21');
631         } else if ($value > 7 and $value < 14) {
632             set_config('calendar_lookahead', '14');
633         }
635         // Main savepoint reached.
636         upgrade_main_savepoint(true, 2015012600.01);
637     }
639     if ($oldversion < 2015021100.00) {
641         // Define field timemodified to be added to registration_hubs.
642         $table = new xmldb_table('registration_hubs');
643         $field = new xmldb_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'secret');
645         // Conditionally launch add field timemodified.
646         if (!$dbman->field_exists($table, $field)) {
647             $dbman->add_field($table, $field);
648         }
650         // Main savepoint reached.
651         upgrade_main_savepoint(true, 2015021100.00);
652     }
654     if ($oldversion < 2015022401.00) {
656         // Define index useridfromto (not unique) to be added to message.
657         $table = new xmldb_table('message');
658         $index = new xmldb_index('useridfromto', XMLDB_INDEX_NOTUNIQUE, array('useridfrom', 'useridto'));
660         // Conditionally launch add index useridfromto.
661         if (!$dbman->index_exists($table, $index)) {
662             $dbman->add_index($table, $index);
663         }
665         // Define index useridfromto (not unique) to be added to message_read.
666         $table = new xmldb_table('message_read');
667         $index = new xmldb_index('useridfromto', XMLDB_INDEX_NOTUNIQUE, array('useridfrom', 'useridto'));
669         // Conditionally launch add index useridfromto.
670         if (!$dbman->index_exists($table, $index)) {
671             $dbman->add_index($table, $index);
672         }
674         // Main savepoint reached.
675         upgrade_main_savepoint(true, 2015022401.00);
676     }
678     if ($oldversion < 2015022500.00) {
679         $table = new xmldb_table('user_devices');
680         $index = new xmldb_index('uuid-userid', XMLDB_INDEX_NOTUNIQUE, array('uuid', 'userid'));
681         if (!$dbman->index_exists($table, $index)) {
682             $dbman->add_index($table, $index);
683         }
684         upgrade_main_savepoint(true, 2015022500.00);
685     }
687     if ($oldversion < 2015030400.00) {
688         // We have long since switched to storing timemodified per hub rather than a single 'registered' timestamp.
689         unset_config('registered');
690         upgrade_main_savepoint(true, 2015030400.00);
691     }
693     if ($oldversion < 2015031100.00) {
694         // Unset old config variable.
695         unset_config('enabletgzbackups');
697         upgrade_main_savepoint(true, 2015031100.00);
698     }
700     if ($oldversion < 2015031400.00) {
702         // Define index useridfrom (not unique) to be dropped form message.
703         $table = new xmldb_table('message');
704         $index = new xmldb_index('useridfrom', XMLDB_INDEX_NOTUNIQUE, array('useridfrom'));
706         // Conditionally launch drop index useridfrom.
707         if ($dbman->index_exists($table, $index)) {
708             $dbman->drop_index($table, $index);
709         }
711         // Define index useridfrom (not unique) to be dropped form message_read.
712         $table = new xmldb_table('message_read');
713         $index = new xmldb_index('useridfrom', XMLDB_INDEX_NOTUNIQUE, array('useridfrom'));
715         // Conditionally launch drop index useridfrom.
716         if ($dbman->index_exists($table, $index)) {
717             $dbman->drop_index($table, $index);
718         }
720         // Main savepoint reached.
721         upgrade_main_savepoint(true, 2015031400.00);
722     }
724     if ($oldversion < 2015031900.01) {
725         unset_config('crontime', 'registration');
726         upgrade_main_savepoint(true, 2015031900.01);
727     }
729     if ($oldversion < 2015032000.00) {
730         $table = new xmldb_table('badge_criteria');
732         $field = new xmldb_field('description', XMLDB_TYPE_TEXT, null, null, null, null, null);
733         // Conditionally add description field to the badge_criteria table.
734         if (!$dbman->field_exists($table, $field)) {
735             $dbman->add_field($table, $field);
736         }
738         $field = new xmldb_field('descriptionformat', XMLDB_TYPE_INTEGER, 2, null, XMLDB_NOTNULL, null, 0);
739         // Conditionally add description format field to the badge_criteria table.
740         if (!$dbman->field_exists($table, $field)) {
741             $dbman->add_field($table, $field);
742         }
744         upgrade_main_savepoint(true, 2015032000.00);
745     }
747     if ($oldversion < 2015040200.01) {
748         // Force uninstall of deleted tool.
749         if (!file_exists("$CFG->dirroot/$CFG->admin/tool/timezoneimport")) {
750             // Remove capabilities.
751             capabilities_cleanup('tool_timezoneimport');
752             // Remove all other associated config.
753             unset_all_config_for_plugin('tool_timezoneimport');
754         }
755         upgrade_main_savepoint(true, 2015040200.01);
756     }
758     if ($oldversion < 2015040200.02) {
759         // Define table timezone to be dropped.
760         $table = new xmldb_table('timezone');
761         // Conditionally launch drop table for timezone.
762         if ($dbman->table_exists($table)) {
763             $dbman->drop_table($table);
764         }
765         upgrade_main_savepoint(true, 2015040200.02);
766     }
768     if ($oldversion < 2015040200.03) {
769         if (isset($CFG->timezone) and $CFG->timezone == 99) {
770             // Migrate to real server timezone.
771             unset_config('timezone');
772         }
773         upgrade_main_savepoint(true, 2015040200.03);
774     }
776     if ($oldversion < 2015040700.01) {
777         $DB->delete_records('config_plugins', array('name' => 'requiremodintro'));
778         upgrade_main_savepoint(true, 2015040700.01);
779     }
781     if ($oldversion < 2015040900.01) {
782         // Add "My grades" to the user menu.
783         $oldconfig = get_config('core', 'customusermenuitems');
784         if (strpos("mygrades,grades|/grade/report/mygrades.php|grades", $oldconfig) === false) {
785             $newconfig = "mygrades,grades|/grade/report/mygrades.php|grades\n" . $oldconfig;
786             set_config('customusermenuitems', $newconfig);
787         }
789         upgrade_main_savepoint(true, 2015040900.01);
790     }
792     if ($oldversion < 2015040900.02) {
793         // Update the default user menu (add preferences, remove my files and my badges).
794         $oldconfig = get_config('core', 'customusermenuitems');
796         // Add "My preferences" at the end.
797         if (strpos($oldconfig, "mypreferences,moodle|/user/preference.php|preferences") === false) {
798             $newconfig = $oldconfig . "\nmypreferences,moodle|/user/preferences.php|preferences";
799         } else {
800             $newconfig = $oldconfig;
801         }
802         // Remove my files.
803         $newconfig = str_replace("myfiles,moodle|/user/files.php|download", "", $newconfig);
804         // Remove my badges.
805         $newconfig = str_replace("mybadges,badges|/badges/mybadges.php|award", "", $newconfig);
806         // Remove holes.
807         $newconfig = preg_replace('/\n+/', "\n", $newconfig);
808         $newconfig = preg_replace('/(\r\n)+/', "\n", $newconfig);
809         set_config('customusermenuitems', $newconfig);
811         upgrade_main_savepoint(true, 2015040900.02);
812     }
814     if ($oldversion < 2015050400.00) {
815         $config = get_config('core', 'customusermenuitems');
817         // Change "My preferences" in the user menu to "Preferences".
818         $config = str_replace("mypreferences,moodle|/user/preferences.php|preferences",
819             "preferences,moodle|/user/preferences.php|preferences", $config);
821         // Change "My grades" in the user menu to "Grades".
822         $config = str_replace("mygrades,grades|/grade/report/mygrades.php|grades",
823             "grades,grades|/grade/report/mygrades.php|grades", $config);
825         set_config('customusermenuitems', $config);
827         upgrade_main_savepoint(true, 2015050400.00);
828     }
830     if ($oldversion < 2015050401.00) {
831         // Make sure we have messages in the user menu because it's no longer in the nav tree.
832         $oldconfig = get_config('core', 'customusermenuitems');
833         $messagesconfig = "messages,message|/message/index.php|message";
834         $preferencesconfig = "preferences,moodle|/user/preferences.php|preferences";
836         // See if it exists.
837         if (strpos($oldconfig, $messagesconfig) === false) {
838             // See if preferences exists.
839             if (strpos($oldconfig, "preferences,moodle|/user/preferences.php|preferences") !== false) {
840                 // Insert it before preferences.
841                 $newconfig = str_replace($preferencesconfig, $messagesconfig . "\n" . $preferencesconfig, $oldconfig);
842             } else {
843                 // Custom config - we can only insert it at the end.
844                 $newconfig = $oldconfig . "\n" . $messagesconfig;
845             }
846             set_config('customusermenuitems', $newconfig);
847         }
849         upgrade_main_savepoint(true, 2015050401.00);
850     }
852     // Moodle v2.9.0 release upgrade line.
853     // Put any upgrade step following this.
855     if ($oldversion < 2015060400.02) {
857         // Sites that were upgrading from 2.7 and older will ignore this step.
858         if (empty($CFG->upgrade_minmaxgradestepignored)) {
860             upgrade_minmaxgrade();
862             // Flags this upgrade step as already run to prevent it from running multiple times.
863             set_config('upgrade_minmaxgradestepignored', 1);
864         }
866         upgrade_main_savepoint(true, 2015060400.02);
867     }
869     if ($oldversion < 2015061900.00) {
870         // MDL-49257. Changed the algorithm of calculating automatic weights of extra credit items.
872         // Before the change, in case when grade category (in "Natural" agg. method) had items with
873         // overridden weights, the automatic weight of extra credit items was illogical.
874         // In order to prevent grades changes after the upgrade we need to freeze gradebook calculation
875         // for the affected courses.
877         // This script in included in each major version upgrade process so make sure we don't run it twice.
878         if (empty($CFG->upgrade_extracreditweightsstepignored)) {
879             upgrade_extra_credit_weightoverride();
881             // To skip running the same script on the upgrade to the next major release.
882             set_config('upgrade_extracreditweightsstepignored', 1);
883         }
885         // Main savepoint reached.
886         upgrade_main_savepoint(true, 2015061900.00);
887     }
889     if ($oldversion < 2015062500.01) {
890         // MDL-48239. Changed calculated grade items so that the maximum and minimum grade can be set.
892         // If the changes are accepted and a regrade is done on the gradebook then some grades may change significantly.
893         // This is here to freeze the gradebook in affected courses.
895         // This script is included in each major version upgrade process so make sure we don't run it twice.
896         if (empty($CFG->upgrade_calculatedgradeitemsignored)) {
897             upgrade_calculated_grade_items();
899             // To skip running the same script on the upgrade to the next major release.
900             set_config('upgrade_calculatedgradeitemsignored', 1);
901             // This config value is never used again.
902             unset_config('upgrade_calculatedgradeitemsonlyregrade');
903         }
905         // Main savepoint reached.
906         upgrade_main_savepoint(true, 2015062500.01);
907     }
909     if ($oldversion < 2015081300.01) {
911         // Define field importtype to be added to grade_import_values.
912         $table = new xmldb_table('grade_import_values');
913         $field = new xmldb_field('importonlyfeedback', XMLDB_TYPE_INTEGER, '1', null, null, null, '0', 'importer');
915         // Conditionally launch add field importtype.
916         if (!$dbman->field_exists($table, $field)) {
917             $dbman->add_field($table, $field);
918         }
920         // Main savepoint reached.
921         upgrade_main_savepoint(true, 2015081300.01);
922     }
924     if ($oldversion < 2015082400.00) {
926         // Define table webdav_locks to be dropped.
927         $table = new xmldb_table('webdav_locks');
929         // Conditionally launch drop table for webdav_locks.
930         if ($dbman->table_exists($table)) {
931             $dbman->drop_table($table);
932         }
934         // Main savepoint reached.
935         upgrade_main_savepoint(true, 2015082400.00);
936     }
938     if ($oldversion < 2015090200.00) {
939         $table = new xmldb_table('message');
941         // Define the deleted fields to be added to the message tables.
942         $field1 = new xmldb_field('timeuserfromdeleted', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0',
943             'timecreated');
944         $field2 = new xmldb_field('timeusertodeleted', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0',
945             'timecreated');
946         $oldindex = new xmldb_index('useridfromto', XMLDB_INDEX_NOTUNIQUE,
947             array('useridfrom', 'useridto'));
948         $newindex = new xmldb_index('useridfromtodeleted', XMLDB_INDEX_NOTUNIQUE,
949             array('useridfrom', 'useridto', 'timeuserfromdeleted', 'timeusertodeleted'));
951         // Conditionally launch add field timeuserfromdeleted.
952         if (!$dbman->field_exists($table, $field1)) {
953             $dbman->add_field($table, $field1);
954         }
956         // Conditionally launch add field timeusertodeleted.
957         if (!$dbman->field_exists($table, $field2)) {
958             $dbman->add_field($table, $field2);
959         }
961         // Conditionally launch drop index useridfromto.
962         if ($dbman->index_exists($table, $oldindex)) {
963             $dbman->drop_index($table, $oldindex);
964         }
966         // Conditionally launch add index useridfromtodeleted.
967         if (!$dbman->index_exists($table, $newindex)) {
968             $dbman->add_index($table, $newindex);
969         }
971         // Now add them to the message_read table.
972         $table = new xmldb_table('message_read');
974         // Conditionally launch add field timeuserfromdeleted.
975         if (!$dbman->field_exists($table, $field1)) {
976             $dbman->add_field($table, $field1);
977         }
979         // Conditionally launch add field timeusertodeleted.
980         if (!$dbman->field_exists($table, $field2)) {
981             $dbman->add_field($table, $field2);
982         }
984         // Conditionally launch drop index useridfromto.
985         if ($dbman->index_exists($table, $oldindex)) {
986             $dbman->drop_index($table, $oldindex);
987         }
989         // Conditionally launch add index useridfromtodeleted.
990         if (!$dbman->index_exists($table, $newindex)) {
991             $dbman->add_index($table, $newindex);
992         }
994         // Main savepoint reached.
995         upgrade_main_savepoint(true, 2015090200.00);
996     }
998     if ($oldversion < 2015090801.00) {
999         // This upgrade script merges all tag instances pointing to the same course tag.
1000         // User id is no longer used for those tag instances.
1001         upgrade_course_tags();
1003         // If configuration variable "Show course tags" is set, disable the block
1004         // 'tags' because it can not be used for tagging courses any more.
1005         if (!empty($CFG->block_tags_showcoursetags)) {
1006             if ($record = $DB->get_record('block', array('name' => 'tags'), 'id, visible')) {
1007                 if ($record->visible) {
1008                     $DB->update_record('block', array('id' => $record->id, 'visible' => 0));
1009                 }
1010             }
1011         }
1013         // Define index idname (unique) to be dropped form tag (it's really weird).
1014         $table = new xmldb_table('tag');
1015         $index = new xmldb_index('idname', XMLDB_INDEX_UNIQUE, array('id', 'name'));
1017         // Conditionally launch drop index idname.
1018         if ($dbman->index_exists($table, $index)) {
1019             $dbman->drop_index($table, $index);
1020         }
1022         // Main savepoint reached.
1023         upgrade_main_savepoint(true, 2015090801.00);
1024     }
1026     if ($oldversion < 2015092200.00) {
1027         // Define index qtype (not unique) to be added to question.
1028         $table = new xmldb_table('question');
1029         $index = new xmldb_index('qtype', XMLDB_INDEX_NOTUNIQUE, array('qtype'));
1031         // Conditionally launch add index qtype.
1032         if (!$dbman->index_exists($table, $index)) {
1033             $dbman->add_index($table, $index);
1034         }
1036         // Main savepoint reached.
1037         upgrade_main_savepoint(true, 2015092200.00);
1038     }
1040     if ($oldversion < 2015092900.00) {
1041         // Rename backup_auto_keep setting to backup_auto_max_kept.
1042         $keep = get_config('backup', 'backup_auto_keep');
1043         if ($keep !== false) {
1044             set_config('backup_auto_max_kept', $keep, 'backup');
1045             unset_config('backup_auto_keep', 'backup');
1046         }
1048         // Main savepoint reached.
1049         upgrade_main_savepoint(true, 2015092900.00);
1050     }
1052     if ($oldversion < 2015100600.00) {
1054         // Define index notification (not unique) to be added to message_read.
1055         $table = new xmldb_table('message_read');
1056         $index = new xmldb_index('notificationtimeread', XMLDB_INDEX_NOTUNIQUE, array('notification', 'timeread'));
1058         // Conditionally launch add index notification.
1059         if (!$dbman->index_exists($table, $index)) {
1060             $dbman->add_index($table, $index);
1061         }
1063         // Main savepoint reached.
1064         upgrade_main_savepoint(true, 2015100600.00);
1065     }
1067     if ($oldversion < 2015100800.01) {
1068         // The only flag for preventing all plugins installation features is
1069         // now $CFG->disableupdateautodeploy in config.php.
1070         unset_config('updateautodeploy');
1071         upgrade_main_savepoint(true, 2015100800.01);
1072     }
1074     // Moodle v3.0.0 release upgrade line.
1075     // Put any upgrade step following this.
1077     if ($oldversion < 2016011300.01) {
1079         // This is a big upgrade script. We create new table tag_coll and the field
1080         // tag.tagcollid pointing to it.
1082         // Define table tag_coll to be created.
1083         $table = new xmldb_table('tag_coll');
1085         // Adding fields to table tagcloud.
1086         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1087         $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null);
1088         $table->add_field('isdefault', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0');
1089         $table->add_field('component', XMLDB_TYPE_CHAR, '100', null, null, null, null);
1090         $table->add_field('sortorder', XMLDB_TYPE_INTEGER, '5', null, XMLDB_NOTNULL, null, '0');
1091         $table->add_field('searchable', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '1');
1092         $table->add_field('customurl', XMLDB_TYPE_CHAR, '255', null, null, null, null);
1094         // Adding keys to table tagcloud.
1095         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1097         // Conditionally launch create table for tagcloud.
1098         if (!$dbman->table_exists($table)) {
1099             $dbman->create_table($table);
1100         }
1102         // Table {tag}.
1103         // Define index name (unique) to be dropped form tag - we will replace it with index on (tagcollid,name) later.
1104         $table = new xmldb_table('tag');
1105         $index = new xmldb_index('name', XMLDB_INDEX_UNIQUE, array('name'));
1107         // Conditionally launch drop index name.
1108         if ($dbman->index_exists($table, $index)) {
1109             $dbman->drop_index($table, $index);
1110         }
1112         // Define field tagcollid to be added to tag, we create it as null first and will change to notnull later.
1113         $table = new xmldb_table('tag');
1114         $field = new xmldb_field('tagcollid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'userid');
1116         // Conditionally launch add field tagcloudid.
1117         if (!$dbman->field_exists($table, $field)) {
1118             $dbman->add_field($table, $field);
1119         }
1121         // Main savepoint reached.
1122         upgrade_main_savepoint(true, 2016011300.01);
1123     }
1125     if ($oldversion < 2016011300.02) {
1126         // Create a default tag collection if not exists and update the field tag.tagcollid to point to it.
1127         if (!$tcid = $DB->get_field_sql('SELECT id FROM {tag_coll} ORDER BY isdefault DESC, sortorder, id', null,
1128                 IGNORE_MULTIPLE)) {
1129             $tcid = $DB->insert_record('tag_coll', array('isdefault' => 1, 'sortorder' => 0));
1130         }
1131         $DB->execute('UPDATE {tag} SET tagcollid = ? WHERE tagcollid IS NULL', array($tcid));
1133         // Define index tagcollname (unique) to be added to tag.
1134         $table = new xmldb_table('tag');
1135         $index = new xmldb_index('tagcollname', XMLDB_INDEX_UNIQUE, array('tagcollid', 'name'));
1136         $field = new xmldb_field('tagcollid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'userid');
1138         // Conditionally launch add index tagcollname.
1139         if (!$dbman->index_exists($table, $index)) {
1140             // Launch change of nullability for field tagcollid.
1141             $dbman->change_field_notnull($table, $field);
1142             $dbman->add_index($table, $index);
1143         }
1145         // Define key tagcollid (foreign) to be added to tag.
1146         $table = new xmldb_table('tag');
1147         $key = new xmldb_key('tagcollid', XMLDB_KEY_FOREIGN, array('tagcollid'), 'tag_coll', array('id'));
1149         // Launch add key tagcloudid.
1150         $dbman->add_key($table, $key);
1152         // Define index tagcolltype (not unique) to be added to tag.
1153         $table = new xmldb_table('tag');
1154         $index = new xmldb_index('tagcolltype', XMLDB_INDEX_NOTUNIQUE, array('tagcollid', 'tagtype'));
1156         // Conditionally launch add index tagcolltype.
1157         if (!$dbman->index_exists($table, $index)) {
1158             $dbman->add_index($table, $index);
1159         }
1161         // Main savepoint reached.
1162         upgrade_main_savepoint(true, 2016011300.02);
1163     }
1165     if ($oldversion < 2016011300.03) {
1167         // Define table tag_area to be created.
1168         $table = new xmldb_table('tag_area');
1170         // Adding fields to table tag_area.
1171         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1172         $table->add_field('component', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
1173         $table->add_field('itemtype', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
1174         $table->add_field('enabled', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '1');
1175         $table->add_field('tagcollid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1176         $table->add_field('callback', XMLDB_TYPE_CHAR, '100', null, null, null, null);
1177         $table->add_field('callbackfile', XMLDB_TYPE_CHAR, '100', null, null, null, null);
1179         // Adding keys to table tag_area.
1180         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1181         $table->add_key('tagcollid', XMLDB_KEY_FOREIGN, array('tagcollid'), 'tag_coll', array('id'));
1183         // Adding indexes to table tag_area.
1184         $table->add_index('compitemtype', XMLDB_INDEX_UNIQUE, array('component', 'itemtype'));
1186         // Conditionally launch create table for tag_area.
1187         if (!$dbman->table_exists($table)) {
1188             $dbman->create_table($table);
1189         }
1191         // Main savepoint reached.
1192         upgrade_main_savepoint(true, 2016011300.03);
1193     }
1195     if ($oldversion < 2016011300.04) {
1197         // Define index itemtype-itemid-tagid-tiuserid (unique) to be dropped form tag_instance.
1198         $table = new xmldb_table('tag_instance');
1199         $index = new xmldb_index('itemtype-itemid-tagid-tiuserid', XMLDB_INDEX_UNIQUE,
1200                 array('itemtype', 'itemid', 'tagid', 'tiuserid'));
1202         // Conditionally launch drop index itemtype-itemid-tagid-tiuserid.
1203         if ($dbman->index_exists($table, $index)) {
1204             $dbman->drop_index($table, $index);
1205         }
1207         // Main savepoint reached.
1208         upgrade_main_savepoint(true, 2016011300.04);
1209     }
1211     if ($oldversion < 2016011300.05) {
1213         $DB->execute("UPDATE {tag_instance} SET component = ? WHERE component IS NULL", array(''));
1215         // Changing nullability of field component on table tag_instance to not null.
1216         $table = new xmldb_table('tag_instance');
1217         $field = new xmldb_field('component', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null, 'tagid');
1219         // Launch change of nullability for field component.
1220         $dbman->change_field_notnull($table, $field);
1222         // Changing type of field itemtype on table tag_instance to char.
1223         $table = new xmldb_table('tag_instance');
1224         $field = new xmldb_field('itemtype', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null, 'component');
1226         // Launch change of type for field itemtype.
1227         $dbman->change_field_type($table, $field);
1229         // Main savepoint reached.
1230         upgrade_main_savepoint(true, 2016011300.05);
1231     }
1233     if ($oldversion < 2016011300.06) {
1235         // Define index taggeditem (unique) to be added to tag_instance.
1236         $table = new xmldb_table('tag_instance');
1237         $index = new xmldb_index('taggeditem', XMLDB_INDEX_UNIQUE, array('component', 'itemtype', 'itemid', 'tiuserid', 'tagid'));
1239         // Conditionally launch add index taggeditem.
1240         if (!$dbman->index_exists($table, $index)) {
1241             $dbman->add_index($table, $index);
1242         }
1244         // Main savepoint reached.
1245         upgrade_main_savepoint(true, 2016011300.06);
1246     }
1248     if ($oldversion < 2016011300.07) {
1250         // Define index taglookup (not unique) to be added to tag_instance.
1251         $table = new xmldb_table('tag_instance');
1252         $index = new xmldb_index('taglookup', XMLDB_INDEX_NOTUNIQUE, array('itemtype', 'component', 'tagid', 'contextid'));
1254         // Conditionally launch add index taglookup.
1255         if (!$dbman->index_exists($table, $index)) {
1256             $dbman->add_index($table, $index);
1257         }
1259         // Main savepoint reached.
1260         upgrade_main_savepoint(true, 2016011300.07);
1261     }
1263     if ($oldversion < 2016011301.00) {
1265         // Force uninstall of deleted tool.
1266         if (!file_exists("$CFG->dirroot/webservice/amf")) {
1267             // Remove capabilities.
1268             capabilities_cleanup('webservice_amf');
1269             // Remove all other associated config.
1270             unset_all_config_for_plugin('webservice_amf');
1271         }
1272         upgrade_main_savepoint(true, 2016011301.00);
1273     }
1275     if ($oldversion < 2016011901.00) {
1277         // Convert calendar_lookahead to nearest new value.
1278         $transaction = $DB->start_delegated_transaction();
1280         // Count all users who curretly have that preference set (for progress bar).
1281         $total = $DB->count_records_select('user_preferences', "name = 'calendar_lookahead' AND value != '0'");
1282         $pbar = new progress_bar('upgradecalendarlookahead', 500, true);
1284         // Get all these users, one at a time.
1285         $rs = $DB->get_recordset_select('user_preferences', "name = 'calendar_lookahead' AND value != '0'");
1286         $i = 0;
1287         foreach ($rs as $userpref) {
1289             // Calculate and set new lookahead value.
1290             if ($userpref->value > 90) {
1291                 $newvalue = 120;
1292             } else if ($userpref->value > 60 and $userpref->value < 90) {
1293                 $newvalue = 90;
1294             } else if ($userpref->value > 30 and $userpref->value < 60) {
1295                 $newvalue = 60;
1296             } else if ($userpref->value > 21 and $userpref->value < 30) {
1297                 $newvalue = 30;
1298             } else if ($userpref->value > 14 and $userpref->value < 21) {
1299                 $newvalue = 21;
1300             } else if ($userpref->value > 7 and $userpref->value < 14) {
1301                 $newvalue = 14;
1302             } else {
1303                 $newvalue = $userpref->value;
1304             }
1306             $DB->set_field('user_preferences', 'value', $newvalue, array('id' => $userpref->id));
1308             // Update progress.
1309             $i++;
1310             $pbar->update($i, $total, "Upgrading user preference settings - $i/$total.");
1311         }
1312         $rs->close();
1313         $transaction->allow_commit();
1315         upgrade_main_savepoint(true, 2016011901.00);
1316     }
1318     if ($oldversion < 2016020200.00) {
1320         // Define field isstandard to be added to tag.
1321         $table = new xmldb_table('tag');
1322         $field = new xmldb_field('isstandard', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'rawname');
1324         // Conditionally launch add field isstandard.
1325         if (!$dbman->field_exists($table, $field)) {
1326             $dbman->add_field($table, $field);
1327         }
1329         // Define index tagcolltype (not unique) to be dropped form tag.
1330         $index = new xmldb_index('tagcolltype', XMLDB_INDEX_NOTUNIQUE, array('tagcollid', 'tagtype'));
1332         // Conditionally launch drop index tagcolltype.
1333         if ($dbman->index_exists($table, $index)) {
1334             $dbman->drop_index($table, $index);
1335         }
1337         // Define index tagcolltype (not unique) to be added to tag.
1338         $index = new xmldb_index('tagcolltype', XMLDB_INDEX_NOTUNIQUE, array('tagcollid', 'isstandard'));
1340         // Conditionally launch add index tagcolltype.
1341         if (!$dbman->index_exists($table, $index)) {
1342             $dbman->add_index($table, $index);
1343         }
1345         // Define field tagtype to be dropped from tag.
1346         $field = new xmldb_field('tagtype');
1348         // Conditionally launch drop field tagtype and update isstandard.
1349         if ($dbman->field_exists($table, $field)) {
1350             $DB->execute("UPDATE {tag} SET isstandard=(CASE WHEN (tagtype = ?) THEN 1 ELSE 0 END)", array('official'));
1351             $dbman->drop_field($table, $field);
1352         }
1354         // Main savepoint reached.
1355         upgrade_main_savepoint(true, 2016020200.00);
1356     }
1358     if ($oldversion < 2016020201.00) {
1360         // Define field showstandard to be added to tag_area.
1361         $table = new xmldb_table('tag_area');
1362         $field = new xmldb_field('showstandard', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'callbackfile');
1364         // Conditionally launch add field showstandard.
1365         if (!$dbman->field_exists($table, $field)) {
1366             $dbman->add_field($table, $field);
1367         }
1369         // By default set user area to hide standard tags. 2 = core_tag_tag::HIDE_STANDARD (can not use constant here).
1370         $DB->execute("UPDATE {tag_area} SET showstandard = ? WHERE itemtype = ? AND component = ?",
1371             array(2, 'user', 'core'));
1373         // Changing precision of field enabled on table tag_area to (1).
1374         $table = new xmldb_table('tag_area');
1375         $field = new xmldb_field('enabled', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'itemtype');
1377         // Launch change of precision for field enabled.
1378         $dbman->change_field_precision($table, $field);
1380         // Main savepoint reached.
1381         upgrade_main_savepoint(true, 2016020201.00);
1382     }
1384     if ($oldversion < 2016021500.00) {
1385         $root = $CFG->tempdir . '/download';
1386         if (is_dir($root)) {
1387             // Fetch each repository type - include all repos, not just enabled.
1388             $repositories = $DB->get_records('repository', array(), '', 'type');
1390             foreach ($repositories as $id => $repository) {
1391                 $directory = $root . '/repository_' . $repository->type;
1392                 if (is_dir($directory)) {
1393                     fulldelete($directory);
1394                 }
1395             }
1396         }
1398         // Main savepoint reached.
1399         upgrade_main_savepoint(true, 2016021500.00);
1400     }
1402     if ($oldversion < 2016021501.00) {
1403         // This could take a long time. Unfortunately, no way to know how long, and no way to do progress, so setting for 1 hour.
1404         upgrade_set_timeout(3600);
1406         // Define index userid-itemid (not unique) to be added to grade_grades_history.
1407         $table = new xmldb_table('grade_grades_history');
1408         $index = new xmldb_index('userid-itemid-timemodified', XMLDB_INDEX_NOTUNIQUE, array('userid', 'itemid', 'timemodified'));
1410         // Conditionally launch add index userid-itemid.
1411         if (!$dbman->index_exists($table, $index)) {
1412             $dbman->add_index($table, $index);
1413         }
1415         // Main savepoint reached.
1416         upgrade_main_savepoint(true, 2016021501.00);
1417     }
1419     if ($oldversion < 2016030103.00) {
1421         // MDL-50887. Implement plugins infrastructure for antivirus and create ClamAV plugin.
1422         // This routine moves core ClamAV configuration to plugin level.
1424         // If clamav was configured and enabled, enable the plugin.
1425         if (!empty($CFG->runclamonupload) && !empty($CFG->pathtoclam)) {
1426             set_config('antiviruses', 'clamav');
1427         } else {
1428             set_config('antiviruses', '');
1429         }
1431         if (isset($CFG->runclamonupload)) {
1432             // Just unset global configuration, we have already enabled the plugin
1433             // which implies that ClamAV will be used for scanning uploaded files.
1434             unset_config('runclamonupload');
1435         }
1436         // Move core ClamAV configuration settings to plugin.
1437         if (isset($CFG->pathtoclam)) {
1438             set_config('pathtoclam', $CFG->pathtoclam, 'antivirus_clamav');
1439             unset_config('pathtoclam');
1440         }
1441         if (isset($CFG->quarantinedir)) {
1442             set_config('quarantinedir', $CFG->quarantinedir, 'antivirus_clamav');
1443             unset_config('quarantinedir');
1444         }
1445         if (isset($CFG->clamfailureonupload)) {
1446             set_config('clamfailureonupload', $CFG->clamfailureonupload, 'antivirus_clamav');
1447             unset_config('clamfailureonupload');
1448         }
1450         // Main savepoint reached.
1451         upgrade_main_savepoint(true, 2016030103.00);
1452     }
1454     if ($oldversion < 2016030400.01) {
1455         // Add the new services field.
1456         $table = new xmldb_table('external_functions');
1457         $field = new xmldb_field('services', XMLDB_TYPE_CHAR, '1333', null, null, null, null, 'capabilities');
1459         // Conditionally launch add field services.
1460         if (!$dbman->field_exists($table, $field)) {
1461             $dbman->add_field($table, $field);
1462         }
1463         // Main savepoint reached.
1464         upgrade_main_savepoint(true, 2016030400.01);
1465     }
1467     if ($oldversion < 2016041500.50) {
1469         // Define table competency to be created.
1470         $table = new xmldb_table('competency');
1472         // Adding fields to table competency.
1473         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1474         $table->add_field('shortname', XMLDB_TYPE_CHAR, '100', null, null, null, null);
1475         $table->add_field('description', XMLDB_TYPE_TEXT, null, null, null, null, null);
1476         $table->add_field('descriptionformat', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0');
1477         $table->add_field('idnumber', XMLDB_TYPE_CHAR, '100', null, null, null, null);
1478         $table->add_field('competencyframeworkid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1479         $table->add_field('parentid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1480         $table->add_field('path', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
1481         $table->add_field('sortorder', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1482         $table->add_field('ruletype', XMLDB_TYPE_CHAR, '100', null, null, null, null);
1483         $table->add_field('ruleoutcome', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0');
1484         $table->add_field('ruleconfig', XMLDB_TYPE_TEXT, null, null, null, null, null);
1485         $table->add_field('scaleid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1486         $table->add_field('scaleconfiguration', XMLDB_TYPE_TEXT, null, null, null, null, null);
1487         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1488         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1489         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1491         // Adding keys to table competency.
1492         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1494         // Adding indexes to table competency.
1495         $table->add_index('idnumberframework', XMLDB_INDEX_UNIQUE, array('competencyframeworkid', 'idnumber'));
1496         $table->add_index('ruleoutcome', XMLDB_INDEX_NOTUNIQUE, array('ruleoutcome'));
1498         // Conditionally launch create table for competency.
1499         if (!$dbman->table_exists($table)) {
1500             $dbman->create_table($table);
1501         }
1503         // Main savepoint reached.
1504         upgrade_main_savepoint(true, 2016041500.50);
1505     }
1507     if ($oldversion < 2016041500.51) {
1509         // Define table competency_coursecompsetting to be created.
1510         $table = new xmldb_table('competency_coursecompsetting');
1512         // Adding fields to table competency_coursecompsetting.
1513         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1514         $table->add_field('courseid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1515         $table->add_field('pushratingstouserplans', XMLDB_TYPE_INTEGER, '2', null, null, null, null);
1516         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1517         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1518         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1520         // Adding keys to table competency_coursecompsetting.
1521         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1522         $table->add_key('courseidlink', XMLDB_KEY_FOREIGN_UNIQUE, array('courseid'), 'course', array('id'));
1524         // Conditionally launch create table for competency_coursecompsetting.
1525         if (!$dbman->table_exists($table)) {
1526             $dbman->create_table($table);
1527         }
1529         // Main savepoint reached.
1530         upgrade_main_savepoint(true, 2016041500.51);
1531     }
1533     if ($oldversion < 2016041500.52) {
1535         // Define table competency_framework to be created.
1536         $table = new xmldb_table('competency_framework');
1538         // Adding fields to table competency_framework.
1539         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1540         $table->add_field('shortname', XMLDB_TYPE_CHAR, '100', null, null, null, null);
1541         $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1542         $table->add_field('idnumber', XMLDB_TYPE_CHAR, '100', null, null, null, null);
1543         $table->add_field('description', XMLDB_TYPE_TEXT, null, null, null, null, null);
1544         $table->add_field('descriptionformat', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0');
1545         $table->add_field('scaleid', XMLDB_TYPE_INTEGER, '11', null, null, null, null);
1546         $table->add_field('scaleconfiguration', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
1547         $table->add_field('visible', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '1');
1548         $table->add_field('taxonomies', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
1549         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1550         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1551         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1553         // Adding keys to table competency_framework.
1554         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1556         // Adding indexes to table competency_framework.
1557         $table->add_index('idnumber', XMLDB_INDEX_UNIQUE, array('idnumber'));
1559         // Conditionally launch create table for competency_framework.
1560         if (!$dbman->table_exists($table)) {
1561             $dbman->create_table($table);
1562         }
1564         // Main savepoint reached.
1565         upgrade_main_savepoint(true, 2016041500.52);
1566     }
1568     if ($oldversion < 2016041500.53) {
1570         // Define table competency_coursecomp to be created.
1571         $table = new xmldb_table('competency_coursecomp');
1573         // Adding fields to table competency_coursecomp.
1574         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1575         $table->add_field('courseid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1576         $table->add_field('competencyid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1577         $table->add_field('ruleoutcome', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, null);
1578         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1579         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1580         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1581         $table->add_field('sortorder', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1583         // Adding keys to table competency_coursecomp.
1584         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1585         $table->add_key('courseidlink', XMLDB_KEY_FOREIGN, array('courseid'), 'course', array('id'));
1586         $table->add_key('competencyid', XMLDB_KEY_FOREIGN, array('competencyid'), 'competency_competency', array('id'));
1588         // Adding indexes to table competency_coursecomp.
1589         $table->add_index('courseidruleoutcome', XMLDB_INDEX_NOTUNIQUE, array('courseid', 'ruleoutcome'));
1590         $table->add_index('courseidcompetencyid', XMLDB_INDEX_UNIQUE, array('courseid', 'competencyid'));
1592         // Conditionally launch create table for competency_coursecomp.
1593         if (!$dbman->table_exists($table)) {
1594             $dbman->create_table($table);
1595         }
1597         // Main savepoint reached.
1598         upgrade_main_savepoint(true, 2016041500.53);
1599     }
1601     if ($oldversion < 2016041500.54) {
1603         // Define table competency_plan to be created.
1604         $table = new xmldb_table('competency_plan');
1606         // Adding fields to table competency_plan.
1607         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1608         $table->add_field('name', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
1609         $table->add_field('description', XMLDB_TYPE_TEXT, null, null, null, null, null);
1610         $table->add_field('descriptionformat', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0');
1611         $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1612         $table->add_field('templateid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1613         $table->add_field('origtemplateid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1614         $table->add_field('status', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, null);
1615         $table->add_field('duedate', XMLDB_TYPE_INTEGER, '10', null, null, null, '0');
1616         $table->add_field('reviewerid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1617         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1618         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1619         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1621         // Adding keys to table competency_plan.
1622         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1624         // Adding indexes to table competency_plan.
1625         $table->add_index('useridstatus', XMLDB_INDEX_NOTUNIQUE, array('userid', 'status'));
1626         $table->add_index('templateid', XMLDB_INDEX_NOTUNIQUE, array('templateid'));
1627         $table->add_index('statusduedate', XMLDB_INDEX_NOTUNIQUE, array('status', 'duedate'));
1629         // Conditionally launch create table for competency_plan.
1630         if (!$dbman->table_exists($table)) {
1631             $dbman->create_table($table);
1632         }
1634         // Main savepoint reached.
1635         upgrade_main_savepoint(true, 2016041500.54);
1636     }
1638     if ($oldversion < 2016041500.55) {
1640         // Define table competency_template to be created.
1641         $table = new xmldb_table('competency_template');
1643         // Adding fields to table competency_template.
1644         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1645         $table->add_field('shortname', XMLDB_TYPE_CHAR, '100', null, null, null, null);
1646         $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1647         $table->add_field('description', XMLDB_TYPE_TEXT, null, null, null, null, null);
1648         $table->add_field('descriptionformat', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0');
1649         $table->add_field('visible', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '1');
1650         $table->add_field('duedate', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1651         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1652         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1653         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1655         // Adding keys to table competency_template.
1656         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1658         // Conditionally launch create table for competency_template.
1659         if (!$dbman->table_exists($table)) {
1660             $dbman->create_table($table);
1661         }
1663         // Main savepoint reached.
1664         upgrade_main_savepoint(true, 2016041500.55);
1665     }
1667     if ($oldversion < 2016041500.56) {
1669         // Define table competency_templatecomp to be created.
1670         $table = new xmldb_table('competency_templatecomp');
1672         // Adding fields to table competency_templatecomp.
1673         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1674         $table->add_field('templateid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1675         $table->add_field('competencyid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1676         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1677         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1678         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1679         $table->add_field('sortorder', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1681         // Adding keys to table competency_templatecomp.
1682         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1683         $table->add_key('templateidlink', XMLDB_KEY_FOREIGN, array('templateid'), 'competency_template', array('id'));
1684         $table->add_key('competencyid', XMLDB_KEY_FOREIGN, array('competencyid'), 'competency_competency', array('id'));
1686         // Conditionally launch create table for competency_templatecomp.
1687         if (!$dbman->table_exists($table)) {
1688             $dbman->create_table($table);
1689         }
1691         // Main savepoint reached.
1692         upgrade_main_savepoint(true, 2016041500.56);
1693     }
1695     if ($oldversion < 2016041500.57) {
1697         // Define table competency_templatecohort to be created.
1698         $table = new xmldb_table('competency_templatecohort');
1700         // Adding fields to table competency_templatecohort.
1701         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1702         $table->add_field('templateid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1703         $table->add_field('cohortid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1704         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1705         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1706         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1708         // Adding keys to table competency_templatecohort.
1709         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1711         // Adding indexes to table competency_templatecohort.
1712         $table->add_index('templateid', XMLDB_INDEX_NOTUNIQUE, array('templateid'));
1713         $table->add_index('templatecohortids', XMLDB_INDEX_UNIQUE, array('templateid', 'cohortid'));
1715         // Conditionally launch create table for competency_templatecohort.
1716         if (!$dbman->table_exists($table)) {
1717             $dbman->create_table($table);
1718         }
1720         // Main savepoint reached.
1721         upgrade_main_savepoint(true, 2016041500.57);
1722     }
1724     if ($oldversion < 2016041500.58) {
1726         // Define table competency_relatedcomp to be created.
1727         $table = new xmldb_table('competency_relatedcomp');
1729         // Adding fields to table competency_relatedcomp.
1730         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1731         $table->add_field('competencyid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1732         $table->add_field('relatedcompetencyid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1733         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1734         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1735         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1737         // Adding keys to table competency_relatedcomp.
1738         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1740         // Conditionally launch create table for competency_relatedcomp.
1741         if (!$dbman->table_exists($table)) {
1742             $dbman->create_table($table);
1743         }
1745         // Main savepoint reached.
1746         upgrade_main_savepoint(true, 2016041500.58);
1747     }
1749     if ($oldversion < 2016041500.59) {
1751         // Define table competency_usercomp to be created.
1752         $table = new xmldb_table('competency_usercomp');
1754         // Adding fields to table competency_usercomp.
1755         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1756         $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1757         $table->add_field('competencyid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1758         $table->add_field('status', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0');
1759         $table->add_field('reviewerid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1760         $table->add_field('proficiency', XMLDB_TYPE_INTEGER, '2', null, null, null, null);
1761         $table->add_field('grade', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1762         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1763         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1764         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1766         // Adding keys to table competency_usercomp.
1767         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1769         // Adding indexes to table competency_usercomp.
1770         $table->add_index('useridcompetency', XMLDB_INDEX_UNIQUE, array('userid', 'competencyid'));
1772         // Conditionally launch create table for competency_usercomp.
1773         if (!$dbman->table_exists($table)) {
1774             $dbman->create_table($table);
1775         }
1777         // Main savepoint reached.
1778         upgrade_main_savepoint(true, 2016041500.59);
1779     }
1781     if ($oldversion < 2016041500.60) {
1783         // Define table competency_usercompcourse to be created.
1784         $table = new xmldb_table('competency_usercompcourse');
1786         // Adding fields to table competency_usercompcourse.
1787         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1788         $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1789         $table->add_field('courseid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1790         $table->add_field('competencyid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1791         $table->add_field('proficiency', XMLDB_TYPE_INTEGER, '2', null, null, null, null);
1792         $table->add_field('grade', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1793         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1794         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1795         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1797         // Adding keys to table competency_usercompcourse.
1798         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1800         // Adding indexes to table competency_usercompcourse.
1801         $table->add_index('useridcoursecomp', XMLDB_INDEX_UNIQUE, array('userid', 'courseid', 'competencyid'));
1803         // Conditionally launch create table for competency_usercompcourse.
1804         if (!$dbman->table_exists($table)) {
1805             $dbman->create_table($table);
1806         }
1808         // Main savepoint reached.
1809         upgrade_main_savepoint(true, 2016041500.60);
1810     }
1812     if ($oldversion < 2016041500.61) {
1814         // Define table competency_usercompplan to be created.
1815         $table = new xmldb_table('competency_usercompplan');
1817         // Adding fields to table competency_usercompplan.
1818         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1819         $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1820         $table->add_field('competencyid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1821         $table->add_field('planid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1822         $table->add_field('proficiency', XMLDB_TYPE_INTEGER, '2', null, null, null, null);
1823         $table->add_field('grade', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1824         $table->add_field('sortorder', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1825         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1826         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1827         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1829         // Adding keys to table competency_usercompplan.
1830         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1832         // Adding indexes to table competency_usercompplan.
1833         $table->add_index('usercompetencyplan', XMLDB_INDEX_UNIQUE, array('userid', 'competencyid', 'planid'));
1835         // Conditionally launch create table for competency_usercompplan.
1836         if (!$dbman->table_exists($table)) {
1837             $dbman->create_table($table);
1838         }
1840         // Main savepoint reached.
1841         upgrade_main_savepoint(true, 2016041500.61);
1842     }
1844     if ($oldversion < 2016041500.62) {
1846         // Define table competency_plancomp to be created.
1847         $table = new xmldb_table('competency_plancomp');
1849         // Adding fields to table competency_plancomp.
1850         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1851         $table->add_field('planid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1852         $table->add_field('competencyid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1853         $table->add_field('sortorder', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1854         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1855         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1856         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1858         // Adding keys to table competency_plancomp.
1859         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1861         // Adding indexes to table competency_plancomp.
1862         $table->add_index('planidcompetencyid', XMLDB_INDEX_UNIQUE, array('planid', 'competencyid'));
1864         // Conditionally launch create table for competency_plancomp.
1865         if (!$dbman->table_exists($table)) {
1866             $dbman->create_table($table);
1867         }
1869         // Main savepoint reached.
1870         upgrade_main_savepoint(true, 2016041500.62);
1871     }
1873     if ($oldversion < 2016041500.63) {
1875         // Define table competency_evidence to be created.
1876         $table = new xmldb_table('competency_evidence');
1878         // Adding fields to table competency_evidence.
1879         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1880         $table->add_field('usercompetencyid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1881         $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1882         $table->add_field('action', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, null);
1883         $table->add_field('actionuserid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1884         $table->add_field('descidentifier', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
1885         $table->add_field('desccomponent', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
1886         $table->add_field('desca', XMLDB_TYPE_TEXT, null, null, null, null, null);
1887         $table->add_field('url', XMLDB_TYPE_CHAR, '255', null, null, null, null);
1888         $table->add_field('grade', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1889         $table->add_field('note', XMLDB_TYPE_TEXT, null, null, null, null, null);
1890         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1891         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1892         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1894         // Adding keys to table competency_evidence.
1895         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1897         // Adding indexes to table competency_evidence.
1898         $table->add_index('usercompetencyid', XMLDB_INDEX_NOTUNIQUE, array('usercompetencyid'));
1900         // Conditionally launch create table for competency_evidence.
1901         if (!$dbman->table_exists($table)) {
1902             $dbman->create_table($table);
1903         }
1905         // Main savepoint reached.
1906         upgrade_main_savepoint(true, 2016041500.63);
1907     }
1909     if ($oldversion < 2016041500.64) {
1911         // Define table competency_userevidence to be created.
1912         $table = new xmldb_table('competency_userevidence');
1914         // Adding fields to table competency_userevidence.
1915         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1916         $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1917         $table->add_field('name', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
1918         $table->add_field('description', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
1919         $table->add_field('descriptionformat', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, null);
1920         $table->add_field('url', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
1921         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1922         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1923         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1925         // Adding keys to table competency_userevidence.
1926         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1928         // Adding indexes to table competency_userevidence.
1929         $table->add_index('userid', XMLDB_INDEX_NOTUNIQUE, array('userid'));
1931         // Conditionally launch create table for competency_userevidence.
1932         if (!$dbman->table_exists($table)) {
1933             $dbman->create_table($table);
1934         }
1936         // Main savepoint reached.
1937         upgrade_main_savepoint(true, 2016041500.64);
1938     }
1940     if ($oldversion < 2016041500.65) {
1942         // Define table competency_userevidencecomp to be created.
1943         $table = new xmldb_table('competency_userevidencecomp');
1945         // Adding fields to table competency_userevidencecomp.
1946         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1947         $table->add_field('userevidenceid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1948         $table->add_field('competencyid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1949         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1950         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1951         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1953         // Adding keys to table competency_userevidencecomp.
1954         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1956         // Adding indexes to table competency_userevidencecomp.
1957         $table->add_index('userevidenceid', XMLDB_INDEX_NOTUNIQUE, array('userevidenceid'));
1958         $table->add_index('userevidencecompids', XMLDB_INDEX_UNIQUE, array('userevidenceid', 'competencyid'));
1960         // Conditionally launch create table for competency_userevidencecomp.
1961         if (!$dbman->table_exists($table)) {
1962             $dbman->create_table($table);
1963         }
1965         // Main savepoint reached.
1966         upgrade_main_savepoint(true, 2016041500.65);
1967     }
1969     if ($oldversion < 2016041500.66) {
1971         // Define table competency_modulecomp to be created.
1972         $table = new xmldb_table('competency_modulecomp');
1974         // Adding fields to table competency_modulecomp.
1975         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1976         $table->add_field('cmid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1977         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1978         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1979         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1980         $table->add_field('sortorder', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1981         $table->add_field('competencyid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1982         $table->add_field('ruleoutcome', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, null);
1984         // Adding keys to table competency_modulecomp.
1985         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1986         $table->add_key('cmidkey', XMLDB_KEY_FOREIGN, array('cmid'), 'course_modules', array('id'));
1987         $table->add_key('competencyidkey', XMLDB_KEY_FOREIGN, array('competencyid'), 'competency_competency', array('id'));
1989         // Adding indexes to table competency_modulecomp.
1990         $table->add_index('cmidruleoutcome', XMLDB_INDEX_NOTUNIQUE, array('cmid', 'ruleoutcome'));
1991         $table->add_index('cmidcompetencyid', XMLDB_INDEX_UNIQUE, array('cmid', 'competencyid'));
1993         // Conditionally launch create table for competency_modulecomp.
1994         if (!$dbman->table_exists($table)) {
1995             $dbman->create_table($table);
1996         }
1998         // Main savepoint reached.
1999         upgrade_main_savepoint(true, 2016041500.66);
2000     }
2002     if ($oldversion < 2016042100.00) {
2003         // Update all countries to upper case.
2004         $DB->execute("UPDATE {user} SET country = UPPER(country)");
2005         // Main savepoint reached.
2006         upgrade_main_savepoint(true, 2016042100.00);
2007     }
2009     if ($oldversion < 2016042600.01) {
2010         $deprecatedwebservices = [
2011             'moodle_course_create_courses',
2012             'moodle_course_get_courses',
2013             'moodle_enrol_get_enrolled_users',
2014             'moodle_enrol_get_users_courses',
2015             'moodle_enrol_manual_enrol_users',
2016             'moodle_file_get_files',
2017             'moodle_file_upload',
2018             'moodle_group_add_groupmembers',
2019             'moodle_group_create_groups',
2020             'moodle_group_delete_groupmembers',
2021             'moodle_group_delete_groups',
2022             'moodle_group_get_course_groups',
2023             'moodle_group_get_groupmembers',
2024             'moodle_group_get_groups',
2025             'moodle_message_send_instantmessages',
2026             'moodle_notes_create_notes',
2027             'moodle_role_assign',
2028             'moodle_role_unassign',
2029             'moodle_user_create_users',
2030             'moodle_user_delete_users',
2031             'moodle_user_get_course_participants_by_id',
2032             'moodle_user_get_users_by_courseid',
2033             'moodle_user_get_users_by_id',
2034             'moodle_user_update_users',
2035             'core_grade_get_definitions',
2036             'core_user_get_users_by_id',
2037             'moodle_webservice_get_siteinfo',
2038             'mod_forum_get_forum_discussions'
2039         ];
2041         list($insql, $params) = $DB->get_in_or_equal($deprecatedwebservices);
2042         $DB->delete_records_select('external_functions', "name $insql", $params);
2043         $DB->delete_records_select('external_services_functions', "functionname $insql", $params);
2044         // Main savepoint reached.
2045         upgrade_main_savepoint(true, 2016042600.01);
2046     }
2048     if ($oldversion < 2016051300.00) {
2049         // Add a default competency rating scale.
2050         make_competence_scale();
2052         // Savepoint reached.
2053         upgrade_main_savepoint(true, 2016051300.00);
2054     }
2056     if ($oldversion < 2016051700.01) {
2057         // This script is included in each major version upgrade process (3.0, 3.1) so make sure we don't run it twice.
2058         if (empty($CFG->upgrade_letterboundarycourses)) {
2059             // MDL-45390. If a grade is being displayed with letters and the grade boundaries are not being adhered to properly
2060             // then this course will also be frozen.
2061             // If the changes are accepted then the display of some grades may change.
2062             // This is here to freeze the gradebook in affected courses.
2063             upgrade_course_letter_boundary();
2065             // To skip running the same script on the upgrade to the next major version release.
2066             set_config('upgrade_letterboundarycourses', 1);
2067         }
2068         // Main savepoint reached.
2069         upgrade_main_savepoint(true, 2016051700.01);
2070     }
2072     // Moodle v3.1.0 release upgrade line.
2073     // Put any upgrade step following this.
2075     if ($oldversion < 2016081700.00) {
2077         // If someone is emotionally attached to it let's leave the config (basically the version) there.
2078         if (!file_exists($CFG->dirroot . '/report/search/classes/output/form.php')) {
2079             unset_all_config_for_plugin('report_search');
2080         }
2082         // Savepoint reached.
2083         upgrade_main_savepoint(true, 2016081700.00);
2084     }
2086     if ($oldversion < 2016081700.02) {
2087         // An upgrade step to remove any duplicate stamps, within the same context, in the question_categories table, and to
2088         // add a unique index to (contextid, stamp) to avoid future stamp duplication. See MDL-54864.
2090         // Extend the execution time limit of the script to 2 hours.
2091         upgrade_set_timeout(7200);
2093         // This SQL fetches the id of those records which have duplicate stamps within the same context.
2094         // This doesn't return the original record within the context, from which the duplicate stamps were likely created.
2095         $fromclause = "FROM (
2096                         SELECT min(id) AS minid, contextid, stamp
2097                             FROM {question_categories}
2098                             GROUP BY contextid, stamp
2099                         ) minid
2100                         JOIN {question_categories} qc
2101                             ON qc.contextid = minid.contextid AND qc.stamp = minid.stamp AND qc.id > minid.minid";
2103         // Get the total record count - used for the progress bar.
2104         $countduplicatessql = "SELECT count(qc.id) $fromclause";
2105         $total = $DB->count_records_sql($countduplicatessql);
2107         // Get the records themselves.
2108         $getduplicatessql = "SELECT qc.id $fromclause ORDER BY minid";
2109         $rs = $DB->get_recordset_sql($getduplicatessql);
2111         // For each duplicate, update the stamp to a new random value.
2112         $i = 0;
2113         $pbar = new progress_bar('updatequestioncategorystamp', 500, true);
2114         foreach ($rs as $record) {
2115             // Generate a new, unique stamp and update the record.
2116             do {
2117                 $newstamp = make_unique_id_code();
2118             } while (isset($usedstamps[$newstamp]));
2119             $usedstamps[$newstamp] = 1;
2120             $DB->set_field('question_categories', 'stamp', $newstamp, array('id' => $record->id));
2122             // Update progress.
2123             $i++;
2124             $pbar->update($i, $total, "Updating duplicate question category stamp - $i/$total.");
2125         }
2126         unset($usedstamps);
2128         // The uniqueness of each (contextid, stamp) pair is now guaranteed, so add the unique index to stop future duplicates.
2129         $table = new xmldb_table('question_categories');
2130         $index = new xmldb_index('contextidstamp', XMLDB_INDEX_UNIQUE, array('contextid', 'stamp'));
2131         if (!$dbman->index_exists($table, $index)) {
2132             $dbman->add_index($table, $index);
2133         }
2135         // Savepoint reached.
2136         upgrade_main_savepoint(true, 2016081700.02);
2137     }
2139     return true;